import asyncio from typing import Any, List import random from time import sleep import config from discord.ext import commands async def await_n(it) -> List[Any]: lst = [asyncio.create_task(task) for task in it] if not lst: return [] done, _ = await asyncio.wait(lst) return [task.result() for task in done] async def answer(ctx: commands.Context, msg: str): await ctx.send(f'{ctx.author.mention} {msg}') @commands.command(help='display this help message', aliases=('hepl', 'h', '?')) async def help(ctx: commands.Context): command_doc = '\n'.join( f' * {config.COMMAND_PREFIX.strip()} {c.name:15} - {c.help}' for c in ctx.bot.commands) await answer(ctx, f'''``` {config.HELP_TEXT}\nThese are all available commands:\n{command_doc}```''') @commands.command(help='create a new lobby', aliases=('create', 'inti', 'craete', 'cretae', 'c', 'i', '+')) async def init(ctx: commands.Context): ctx.bot.meta_channel = ctx.bot.get_meta_channel(ctx) or await ctx.bot.create_category(ctx) ctx.bot.lobby_channel = ctx.bot.get_lobby_channel(ctx, ctx.bot.meta_channel) or await ctx.bot.create_lobby(ctx) @commands.command(help=f'destruct all {config.NAME} channels', aliases=('kill', 'desctruction', 'genocide', '-')) async def destroy(ctx: commands.Context): futures = [] meta_channel = ctx.bot.get_meta_channel(ctx) for channel in (ctx.bot.get_lobby_channel(ctx, meta_channel), meta_channel): if channel: futures.append(channel.delete()) await await_n(futures) ctx.bot.lobby_channel = None ctx.bot.meta_channel = None ctx.bot.pair_channels = [] @commands.command(help='start shuffling', aliases=('start', 'run', 'strat', 'rnu')) async def shuffle(ctx: commands.Context): channels = await ctx.bot.get_channels(ctx) if not channels: return meta_channel, lobby_channel = channels members = lobby_channel.members[:] slots = len(members) >> 1 ctx.bot.pair_channels = await ctx.bot.create_pair_channels(ctx, meta_channel, slots) slots = [] for i, _ in enumerate(ctx.bot.pair_channels): slots.append(i) slots.append(i) random.shuffle(slots) futures = [] for slot in slots: member = members.pop() if member is None: break futures.append(member.move_to(ctx.bot.pair_channels[slot])) if members: futures.append(members.pop().move_to(random.choice(ctx.bot.pair_channels))) await await_n(futures) @commands.command(help='move everyone back to lobby', aliases=('quit', 'exit', 'abort', 'back', 'return')) async def stop(ctx: commands.Context): channels = await ctx.bot.get_channels(ctx) if not channels: return meta_channel, lobby_channel = channels pair_channels = ctx.bot.get_pair_channels(ctx, meta_channel) futures = [] for channel in pair_channels: for member in channel.members: futures.append(member.move_to(lobby_channel)) await await_n(futures) await ctx.bot.destroy_pair_channels(ctx, meta_channel) @commands.command(help='repeat "shuffle" and "stop" (default: 3) times and (default: 120) seconds') async def loop(ctx: commands.Context, *args): if len(args) >= 1 and args[0].isdigit(): n = int(args[0]) else: n = 3 if len(args) >= 2 and args[1].isdigit(): t = int(ctx.args[1]) else: t = 120 await answer(ctx, f'repeat shuffling {n} times and each {t} seconds') for _ in range(n): await shuffle(ctx) sleep(t) await stop(ctx) bot_commands = [cmd for cmd in locals().values() if isinstance(cmd, commands.Command)]