mirror of
https://github.com/brandons209/Red-bot-Cogs.git
synced 2024-05-10 07:23:12 +12:00
132 lines
5.3 KiB
Python
132 lines
5.3 KiB
Python
import asyncio
|
|
import discord
|
|
import random
|
|
from datetime import datetime, timedelta
|
|
from typing import Optional, Literal
|
|
|
|
from redbot.core import Config, checks, commands
|
|
from redbot.core.utils.chat_formatting import *
|
|
from redbot.core.utils.predicates import MessagePredicate
|
|
|
|
from .discord_thread_feature import *
|
|
from .time_utils import *
|
|
|
|
|
|
class ThreadRotate(commands.Cog):
|
|
"""
|
|
Rotate threads for events, roleplay, etc
|
|
"""
|
|
|
|
def __init__(self, bot):
|
|
self.bot = bot
|
|
self.config = Config.get_conf(self, identifier=45612361654894681623, force_registration=True)
|
|
|
|
default_channel = {
|
|
"topics": {},
|
|
"ping_roles": [],
|
|
"rotation_interval": 10080,
|
|
"rotate_on": None,
|
|
"last_topic": None,
|
|
}
|
|
self.config.register_channel(**default_channel)
|
|
|
|
@commands.group(name="rotate")
|
|
@commands.guild_only()
|
|
@checks.admin()
|
|
async def thread_rotate(self, ctx):
|
|
"""
|
|
Manage thread rotations per channel
|
|
"""
|
|
pass
|
|
|
|
@thread_rotate.command(name="setup")
|
|
async def thread_rotate_setup(self, ctx, channel: discord.TextChannel):
|
|
"""
|
|
Interactively setup a thread rotation for a channel
|
|
"""
|
|
guild = ctx.guild
|
|
await ctx.send(
|
|
info(
|
|
"Welcome to the thread rotation setup wizard!\n\nFirst, please specifiy the rotation interval. Rotation intervals can be formatted as follows:\n\t5 minutes\n\t1 minute 30 seconds\n\t1 hour\n\t2 days\n\t30 days\n\t5h30m\n\t(etc)"
|
|
)
|
|
)
|
|
|
|
pred = MessagePredicate.same_context(ctx)
|
|
try:
|
|
msg = await self.bot.wait_for("message", check=pred, timeout=121)
|
|
except asyncio.TimeoutError:
|
|
await ctx.send(error("Took too long, cancelling setup!"), delete_after=30)
|
|
return
|
|
|
|
interval = parse_timedelta(msg.content.strip())
|
|
if interval is None:
|
|
await ctx.send(error("Invalid time interval, please run setup again!"), delete_after=60)
|
|
return
|
|
|
|
await ctx.send(
|
|
info(
|
|
"Thank you.\n\nNow, please specify the date and time to start rotation. You can say `now` to start rotation as soon as setup is complete.\n\nValid date formats are:\n\tFebruary 14 at 6pm EDT\n\t2019-04-13 06:43:00 PST\n\t01/20/18 at 21:00:43\n\t(etc)"
|
|
)
|
|
)
|
|
|
|
pred = MessagePredicate.same_context(ctx)
|
|
try:
|
|
msg = await self.bot.wait_for("message", check=pred, timeout=121)
|
|
except asyncio.TimeoutError:
|
|
await ctx.send(error("Took too long, cancelling setup!"), delete_after=30)
|
|
return
|
|
|
|
date = parse_time(msg.content.strip())
|
|
if date is None:
|
|
await ctx.send(error("Invalid date, please run setup again!"), delete_after=60)
|
|
return
|
|
|
|
await ctx.send(
|
|
info(
|
|
"Great, next step is to list all roles that should be pinged and added to each thread when it rotates.\n\nList each role **seperated by a comma `,`**.\nYou can use role IDs, role mentions, or role names."
|
|
)
|
|
)
|
|
|
|
pred = MessagePredicate.same_context(ctx)
|
|
try:
|
|
msg = await self.bot.wait_for("message", check=pred, timeout=241)
|
|
except asyncio.TimeoutError:
|
|
await ctx.send(error("Took too long, cancelling setup!"), delete_after=30)
|
|
return
|
|
|
|
roles = [m.strip().strip("<").strip(">").strip("@").strip("&") for m in msg.content.split(",")]
|
|
role_objs = []
|
|
for r in roles:
|
|
try:
|
|
role = guild.get_role(int(r))
|
|
except:
|
|
role = discord.utils.find(lambda c: c.name == r, guild.roles)
|
|
if role is None:
|
|
await ctx.send(error(f"Unknown channel: `{r}`, please run the command again."))
|
|
return
|
|
|
|
role_objs.append(channel)
|
|
|
|
await ctx.send(
|
|
info(
|
|
"Final step is to list the thread topics and their selection weights.\nThe weight is how likely the topic will be choosen.\nA weight of `1` means it will not be choosen more or less than other topics.\nA weight between 0 and 1 means it is that weight times less likely to be choosen, with a weight of 0 meaning it will never be choosen.\nA weight greater than 1 means it will be that times more likely to be choosen.\n\nFor example, a weight of 1.5 means that topic is 1.5 more likely to be choose over the others. A weight of 0.5 means that topic is half as likely to be choosen by others.\n\nPlease use this format for listing the weights:\n"
|
|
)
|
|
)
|
|
await ctx.send(box("topic name: weight_value\ntopic 2 name: weight_value\ntopic 3 name: weight_value"))
|
|
|
|
pred = MessagePredicate.same_context(ctx)
|
|
try:
|
|
msg = await self.bot.wait_for("message", check=pred, timeout=301)
|
|
except asyncio.TimeoutError:
|
|
await ctx.send(error("Took too long, cancelling setup!"), delete_after=30)
|
|
return
|
|
|
|
topics = msg.content.split("\n")
|
|
parsed_topics = {}
|
|
# TODO error checking
|
|
for topic in topics:
|
|
topic = topic.split(":")
|
|
parsed_topics[topic[0]] = float(topic[1])
|
|
|
|
await ctx.send(info(f"Please review the settings for thread rotation on channel {channel.mention}"))
|