diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..01c523a --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ + +.idea/ +*.pyc diff --git a/README.md b/README.md index a88bd7c..44ef0f8 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,32 @@ # Fox-V3 +Cog Function +| Name | Status | Description +| --- | --- | --- | +| ccrole | **Beta** | Create custom commands that also assign roles | +| chatter | **Alpha** | Chat-bot trained to talk like your guild +| fight | **Incomplete** | Organize bracket tournaments within discord | +| flag | **Beta** | Create temporary marks on users that expire after specified time | +| hangman | **Incomplete** | Play a game of hangman | +| immortal | **Private** | Cog designed for a specific server, not recommended to install | +| leaver | **Incomplete** | Send a message in a channel when a user leaves the server | +| reactrestrict | **Alpha** | Removes reactions by role per channel | +| stealemoji | **Alpha** | Steals any custom emoji it sees | +| werewolf | **Incomplete** | Play the classic party game Werewolf within discord | -Cog Status +Cog Status Descriptions - - ccrole: **Incomplete** - Not yet ported to v3 - - challonge: **Incomplete** - Challonge integration with discord - - chatter: **Alpha** - Train your chat-bot to talk like your guild - - fight: **Incomplete** - Still in-progress, a massive project - - flag: **Incomplete** - Not yet ported to v3 - - hangman: **Incomplete** - Not yet ported to v3 - - immortal: **Private** - Designed for a specific server, not recommended to install - - leaver: **Incomplete** - Not yet ported to v3 - - reactrestrict: **Beta** - Removes reactions by role per channel - - stealemoji: **Alpha** - Steals any custom emoji it sees - - werewolf: **Incomplete** - Play the classic party game Werewolf within discord - -Many of these are functional in my V2 cogs at [Fox-Cogs v2](https://github.com/bobloy/Fox-Cogs) \ No newline at end of file + - ccrole: May have some bugs, please create an issue if you find any + - chatter: Missing some key features, but currently functional + - fight: Still in-progress, a massive project + - flag: Not yet ported to v3 + - hangman: Not yet ported to v3 + - immortal: Designed for a specific server, not recommended to install + - leaver: Not yet ported to v3 + - reactrestrict: A bit clunky, but functional + - stealemoji: Some planned upgrades for server generation + - werewolf: Another massive project, will be fully customizable + +Many of these are functional in my V2 cogs at [Fox-Cogs v2](https://github.com/bobloy/Fox-Cogs) + \ No newline at end of file diff --git a/ccrole/ccrole.py b/ccrole/ccrole.py index 2ca5b91..38cff39 100644 --- a/ccrole/ccrole.py +++ b/ccrole/ccrole.py @@ -3,10 +3,9 @@ import asyncio from discord.ext import commands -from redbot.core import Config +from redbot.core import Config, checks -from .utils import checks -from .utils.chat_formatting import pagify, box +from redbot.core.utils.chat_formatting import pagify, box import os import re @@ -19,224 +18,240 @@ class CCRole: def __init__(self, bot): self.bot = bot - self.file_path = "data/ccrole/commands.json" - self.c_commands = dataIO.load_json(self.file_path) + self.config = Config.get_conf(self, identifier=9999114111108101) + default_guild = { + "cmdlist" : {}, + "settings": {} + } + + self.config.register_guild(**default_guild) + - @commands.group(pass_context=True, no_pm=True) + @commands.group(no_pm=True) async def ccrole(self, ctx): """Custom commands management""" - if ctx.invoked_subcommand is None: - await self.bot.send_cmd_help(ctx) + if not ctx.invoked_subcommand: + await ctx.send_help() - @ccrole.command(name="add", pass_context=True) + @ccrole.command(name="add") @checks.mod_or_permissions(administrator=True) async def ccrole_add(self, ctx, command : str): """Adds a custom command with roles""" command = command.lower() - if command in self.bot.commands: - await self.bot.say("That command is already a standard command.") + if command in self.bot.all_commands: + await ctx.send("That command is already a standard command.") return - server = ctx.message.server - author = ctx.message.author + guild = ctx.guild + author = ctx.author + channel = ctx.channel + + cmdlist = self.config.guild(ctx.guild).cmdlist - if server.id not in self.c_commands: - self.c_commands[server.id] = {} - cmdlist = self.c_commands[server.id] - if command in cmdlist: - await self.bot.say("This command already exists. Delete" - "`it with {}ccrole delete` first." - "".format(ctx.prefix)) + if await cmdlist.get_raw(command, default=None): + await ctx.send("This command already exists. Delete it with `{}ccrole delete` first.".format(ctx.prefix)) return # Roles to add - await self.bot.say('What roles should it add? (Must be comma separated)\nSay `None` to skip adding roles') + await ctx.send('What roles should it add? (Must be **comma separated**)\nSay `None` to skip adding roles') - answer = await self.bot.wait_for_message(timeout=120, author=author) - if not answer: - await self.bot.say("Timed out, canceling") - return + def check(m): + return m.author == author and m.channel==channel + + try: + answer = await self.bot.wait_for('message', timeout=120, check=check) + except asyncio.TimeoutError: + await ctx.send("Timed out, canceling") + arole_list = [] if answer.content.upper()!="NONE": - arole_list = answer.content.split(",") - - try: - arole_list = [discord.utils.get(server.roles, name=role.strip(' ')).id for role in arole_list] - except: - await self.bot.say("Invalid answer, canceling") + arole_list = await self._get_roles_from_content(ctx, answer.content) + if arole_list is None: + await ctx.send("Invalid answer, canceling") return # Roles to remove - await self.bot.say('What roles should it remove? (Must be comma separated)\nSay `None` to skip removing roles') - - answer = await self.bot.wait_for_message(timeout=120, author=author) - if not answer: - await self.bot.say("Timed out, canceling") - return + await ctx.send('What roles should it remove? (Must be comma separated)\nSay `None` to skip removing roles') + try: + answer = await self.bot.wait_for('message', timeout=120, check=check) + except asyncio.TimeoutError: + await ctx.send("Timed out, canceling") rrole_list = [] if answer.content.upper()!="NONE": - rrole_list = answer.content.split(",") - - try: - rrole_list = [discord.utils.get(server.roles, name=role.strip(' ')).id for role in rrole_list] - except: - await self.bot.say("Invalid answer, canceling") + rrole_list = await self._get_roles_from_content(ctx, answer.content) + if rrole_list is None: + await ctx.send("Invalid answer, canceling") return # Roles to use - await self.bot.say('What roles are allowed to use this command? (Must be comma separated)\nSay `None` to allow all roles') + await ctx.send('What roles are allowed to use this command? (Must be comma separated)\nSay `None` to allow all roles') - answer = await self.bot.wait_for_message(timeout=120, author=author) - if not answer: - await self.bot.say("Timed out, canceling") - return + try: + answer = await self.bot.wait_for('message', timeout=120, check=check) + except asyncio.TimeoutError: + await ctx.send("Timed out, canceling") prole_list = [] if answer.content.upper()!="NONE": - prole_list = answer.content.split(",") - - try: - prole_list = [discord.utils.get(server.roles, name=role.strip(' ')).id for role in prole_list] - except: - await self.bot.say("Invalid answer, canceling") + prole_list = await self._get_roles_from_content(ctx, answer.content) + if prole_list is None: + await ctx.send("Invalid answer, canceling") return # Selfrole - await self.bot.say('Is this a targeted command?(yes/no)\nNo will make this a selfrole command') + await ctx.send('Is this a targeted command?(yes/no)\nNo will make this a selfrole command') - answer = await self.bot.wait_for_message(timeout=120, author=author) - if not answer: - await self.bot.say("Timed out, canceling") - return + try: + answer = await self.bot.wait_for('message', timeout=120, check=check) + except asyncio.TimeoutError: + await ctx.send("Timed out, canceling") if answer.content.upper() in ["Y", "YES"]: targeted = True - await self.bot.say("This command will be targeted") + await ctx.send("This command will be **`targeted`**") else: targeted = False - await self.bot.say("This command will be selfrole") + await ctx.send("This command will be **`selfrole`**") # Message to send - await self.bot.say('What message should the bot send?\nSay `None` to send the default `Success!` message') + await ctx.send('What message should the bot say when using this command?\nSay `None` to send the default `Success!` message') - answer = await self.bot.wait_for_message(timeout=120, author=author) - if not answer: - await self.bot.say("Timed out, canceling") - return + try: + answer = await self.bot.wait_for('message', timeout=120, check=check) + except asyncio.TimeoutError: + await ctx.send("Timed out, canceling") text = "Success!" if answer.content.upper()!="NONE": text = answer.content # Save the command - cmdlist[command] = {'text': text, 'aroles': arole_list, 'rroles': rrole_list, "proles": prole_list, "targeted": targeted} + out = {'text': text, 'aroles': arole_list, 'rroles': rrole_list, "proles": prole_list, "targeted": targeted} - self.c_commands[server.id] = cmdlist - dataIO.save_json(self.file_path, self.c_commands) - await self.bot.say("Custom command successfully added.") - - @ccrole.command(name="delete", pass_context=True) + await cmdlist.set_raw(command, value=out) + + ctx.send("Custom Command **`{}`** successfully added".format(command)) + + @ccrole.command(name="delete") @checks.mod_or_permissions(administrator=True) async def ccrole_delete(self, ctx, command : str): """Deletes a custom command Example: [p]ccrole delete yourcommand""" - server = ctx.message.server + guild = ctx.guild command = command.lower() - if server.id in self.c_commands: - cmdlist = self.c_commands[server.id] - if command in cmdlist: - cmdlist.pop(command, None) - self.c_commands[server.id] = cmdlist - dataIO.save_json(self.file_path, self.c_commands) - await self.bot.say("Custom command successfully deleted.") - else: - await self.bot.say("That command doesn't exist.") + if not await self.config.guild(ctx.guild).cmdlist.get_raw(command, default=None): + await ctx.send("That command doesn't exist") else: - await self.bot.say("There are no custom commands in this server." - " Use `{}ccrole add` to start adding some." - "".format(ctx.prefix)) + await self.config.guild(ctx.guild).cmdlist.set_raw(command, value=None) + await ctx.send("Custom command successfully deleted.") - @ccrole.command(name="list", pass_context=True) + @ccrole.command(name="list") async def ccrole_list(self, ctx): """Shows custom commands list""" - server = ctx.message.server - commands = self.c_commands.get(server.id, {}) + guild = ctx.guild + commands = await self.config.guild(ctx.guild).cmdlist() if not commands: - await self.bot.say("There are no custom commands in this server." - " Use `{}ccrole add` to start adding some." - "".format(ctx.prefix)) + await ctx.send("There are no custom commands in this server. Use `{}ccrole add` to start adding some.".format(ctx.prefix)) return commands = ", ".join([ctx.prefix + c for c in sorted(commands.keys())]) commands = "Custom commands:\n\n" + commands if len(commands) < 1500: - await self.bot.say(box(commands)) + await ctx.send(box(commands)) else: for page in pagify(commands, delims=[" ", "\n"]): - await self.bot.whisper(box(page)) + await ctx.author.send(box(page)) + await ctx.send("Command list DM'd") async def on_message(self, message): - if len(message.content) < 2 or message.channel.is_private: + if len(message.content) < 2 or message.guild is None: return - server = message.server - prefix = self.get_prefix(message) - - if not prefix: + guild = message.guild + try: + prefix = await self.get_prefix(message) + except ValueError: return - if server.id in self.c_commands and self.bot.user_allowed(message): - cmdlist = self.c_commands[server.id] - cmd = message.content[len(prefix):].split()[0] - if cmd in cmdlist: - cmd = cmdlist[cmd] - await self.eval_cc(cmd, message) - elif cmd.lower() in cmdlist: - cmd = cmdlist[cmd.lower()] - await self.eval_cc(cmd, message) - - def get_prefix(self, message): - for p in self.bot.settings.get_prefixes(message.server): - if message.content.startswith(p): + + cmdlist = self.config.guild(guild).cmdlist + cmd = message.content[len(prefix):].split()[0] + cmd = await cmdlist.get_raw(cmd.lower(), default=None) + + if cmd: + await self.eval_cc(cmd, message) + + async def _get_roles_from_content(self, ctx, content): + content_list = content.split(",") + role_list = [] + try: + role_list = [discord.utils.get(ctx.guild.roles, name=role.strip(' ')).id for role in content_list] + except: + return None + else: + return role_list + + async def get_prefix(self, message: discord.Message) -> str: + """ + Borrowed from alias cog + Tries to determine what prefix is used in a message object. + Looks to identify from longest prefix to smallest. + + Will raise ValueError if no prefix is found. + :param message: Message object + :return: + """ + content = message.content + prefix_list = await self.bot.command_prefix(self.bot, message) + prefixes = sorted(prefix_list, + key=lambda pfx: len(pfx), + reverse=True) + for p in prefixes: + if content.startswith(p): return p - return False + raise ValueError async def eval_cc(self, cmd, message): + """Does all the work""" if cmd['proles'] and not (set(role.id for role in message.author.roles) & set(cmd['proles'])): return # Not authorized, do nothing if cmd['targeted']: try: - target = discord.utils.get(message.server.members, mention=message.content.split()[1]) + target = discord.utils.get(message.guild.members, mention=message.content.split()[1]) except: target = None if not target: out_message = "This command is targeted! @mention a target\n`{} `".format(message.content.split()[0]) - await self.bot.send_message(message.channel, out_message) + await message.channel.send(out_message) return else: target = message.author if cmd['aroles']: - arole_list = [discord.utils.get(message.server.roles, id=roleid) for roleid in cmd['aroles']] + arole_list = [discord.utils.get(message.guild.roles, id=roleid) for roleid in cmd['aroles']] # await self.bot.send_message(message.channel, "Adding: "+str([str(arole) for arole in arole_list])) - await self.bot.add_roles(target, *arole_list) - + try: + await target.add_roles(*arole_list) + except discord.Forbidden: + await message.channel.send("Permission error: Unable to add roles") await asyncio.sleep(1) if cmd['rroles']: - rrole_list = [discord.utils.get(message.server.roles, id=roleid) for roleid in cmd['rroles']] + rrole_list = [discord.utils.get(message.guild.roles, id=roleid) for roleid in cmd['rroles']] # await self.bot.send_message(message.channel, "Removing: "+str([str(rrole) for rrole in rrole_list])) - await self.bot.remove_roles(target, *rrole_list) - - await self.bot.send_message(message.channel, cmd['text']) + try: + await target.remove_roles(*rrole_list) + except discord.Forbidden: + await message.channel.send("Permission error: Unable to remove roles") + await message.channel.send(cmd['text']) # {'text': text, 'aroles': arole_list, 'rroles': rrole_list, "proles", prole_list, "targeted": targeted} @@ -269,23 +284,4 @@ class CCRole: # first = objects[first] # else: # return raw_result - # return str(getattr(first, second, raw_result)) - - -def check_folders(): - if not os.path.exists("data/ccrole"): - print("Creating data/ccrole folder...") - os.makedirs("data/ccrole") - - -def check_files(): - f = "data/ccrole/commands.json" - if not dataIO.is_valid_json(f): - print("Creating empty commands.json...") - dataIO.save_json(f, {}) - - -def setup(bot): - check_folders() - check_files() - bot.add_cog(CCRole(bot)) \ No newline at end of file + # return str(getattr(first, second, raw_result)) \ No newline at end of file diff --git a/challonge/__init__.py b/challonge/__init__.py deleted file mode 100644 index a1e7e01..0000000 --- a/challonge/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from .challonge import Challonge - -def setup(bot): - n = Challonge(bot) - bot.add_cog(n) \ No newline at end of file diff --git a/challonge/challonge.py b/challonge/challonge.py deleted file mode 100644 index 3d468db..0000000 --- a/challonge/challonge.py +++ /dev/null @@ -1,134 +0,0 @@ -import os - -import challonge - -import discord -from discord.ext import commands - -from redbot.core.utils.chat_formatting import pagify -from redbot.core.utils.chat_formatting import box -from redbot.core import Config -from redbot.core import checks - - - - -class Challonge: - """Cog for organizing Challonge tourneys""" - - def __init__(self, bot): - self.bot = bot - self.config = Config.get_conf(self, identifier=6710497108108111110103101) - default_global = { - "username": None, - "apikey": None - } - default_guild = { - "reportchannel": None, - "announcechannel": None - } - - self.config.register_global(**default_global) - self.config.register_guild(**default_guild) - - await self._set_credentials() - -# ************************Challonge command group start************************ - - @commands.group() - @commands.guild_only() - async def challonge(self, ctx): - """Challonge command base""" - if ctx.invoked_subcommand is None: - await ctx.send_help() - # await ctx.send("I can do stuff!") - - - @challonge.command(name="apikey") - async def c_apikey(self, ctx, username, apikey): - """Sets challonge username and apikey""" - await self.config.username.set(username) - await self.config.apikey.set(apikey) - await self._set_credentials() - await ctx.send("Success!") - - @challonge.command(name="report") - async def c_report(self, ctx, channel: discord.TextChannel=None): - """Set the channel for self-reporting matches""" - if channel is None: - channel = ctx.channel - - await self.config.guild(ctx.guild).reportchnnl.set(channel.id) - - channel = (await self._get_reportchnnl(ctx.guild)) - await ctx.send("Self-Reporting Channel is now set to: " + channel.mention) - - @challonge.command(name="announce") - async def c_announce(self, ctx, channel: discord.TextChannel=None): - """Set the channel for tournament announcements""" - if channel is None: - channel = ctx.channel - - await self.config.guild(ctx.guild).announcechnnl.set(channel.id) - - channel = (await self._get_announcechnnl(ctx.guild)) - await ctx.send("Announcement Channel is now set to: " + channel.mention) - -# ************************Private command group start************************ - async def _print_tourney(self, guild: discord.Guild, tID: int): - channel = (await self._get_announcechnnl(ctx.guild)) - - await channel.send() - - async def _set_credentials(self): - username = await self.config.username - apikey = await self.config.apikey - if username and apikey: - challonge.set_credentials(username, apikey) - return True - return False - - async def _get_message_from_id(self, guild: discord.Guild, message_id: int): - """ - Tries to find a message by ID in the current guild context. - :param ctx: - :param message_id: - :return: - """ - for channel in guild.text_channels: - try: - return await channel.get_message(message_id) - except discord.NotFound: - pass - except AttributeError: # VoiceChannel object has no attribute 'get_message' - pass - - return None - - async def _get_announcechnnl(self, guild: discord.Guild): - channelid = await self.config.guild(guild).announcechnnl() - channel = self._get_channel_from_id(channelid) - return channel - - async def _get_reportchnnl(self, guild: discord.Guild): - channelid = await self.config.guild(guild).reportchnnl() - channel = self._get_channel_from_id(channelid) - return channel - - def _get_channel_from_id(self, channelid): - return self.bot.get_channel(channelid) - - def _get_user_from_id(self, userid): - # guild = self._get_guild_from_id(guildID) - # return discord.utils.get(guild.members, id=userid) - return self.bot.get_user(userid) - - def _get_guild_from_id(self, guildID): - return self.bot.get_guild(guildID) - - - - - - - \ No newline at end of file diff --git a/challonge/info.json b/challonge/info.json deleted file mode 100644 index a687545..0000000 --- a/challonge/info.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "author" : ["Bobloy"], - "bot_version" : [3,0,0], - "description" : "[Incomplete] Cog to organize tournaments within Discord using Challonge", - "hidden" : false, - "install_msg" : "Thank you for installing the Challonge Cog.", - "requirements" : ["iso8601", "challonge"], - "short" : "[Incomplete] Cog to organize Challonge tournaments", - "tags" : ["game", "fun", "fight", "tournament", "tourney", "challonge", "elimination", "bracket", "bobloy"] -} \ No newline at end of file diff --git a/werewolf/builder.py b/werewolf/builder.py index b80fcb6..b10b4a9 100644 --- a/werewolf/builder.py +++ b/werewolf/builder.py @@ -2,7 +2,6 @@ import asyncio import discord # Import all roles here -from werewolf.role import Role from werewolf.roles.vanillawerewolf import VanillaWerewolf from werewolf.roles.villager import Villager from werewolf.roles.seer import Seer @@ -10,39 +9,44 @@ from werewolf.roles.seer import Seer # All roles in this list for iterating role_list = [Villager, VanillaWerewolf] -#Example code: -# 0 = Villager -# 1 = VanillaWerewolf -# E1 = Random Town -# R1 = Random Werewolf -# J1 = Benign Neutral +""" +Example code: +0 = Villager +1 = VanillaWerewolf +E1 = Random Town +R1 = Random Werewolf +J1 = Benign Neutral -# 0001-1112E11R112P2 -# 0,0,0,1,11,12,E1,R1,R1,R1,R2,P2 +0001-1112E11R112P2 +0,0,0,1,11,12,E1,R1,R1,R1,R2,P2 + +pre-letter = exact role position +double digit position preempted by `-` +""" -# pre-letter = exact role position -# double digit position pre-empted by `-` async def parse_code(code): + """Do the magic described above""" out = [] - #Do the magic described above decode = code.copy() # for now, pass exact names for role_id in decode: print(role_id) if role_id == "Villager": role = Villager - if role_id == "VanillaWerewolf": + elif role_id == "VanillaWerewolf": role = VanillaWerewolf - if role_id == "Seer": + elif role_id == "Seer": role = Seer + else: # Fail to parse + return None out.append(role) return out - + + async def build_game(channel: discord.TextChannel): await channel.send("Not currently available") - - + code = 12345678 await channel.send("Your game code is **`{}`**".format(code)) diff --git a/werewolf/game.py b/werewolf/game.py index 0d9743c..12522c0 100644 --- a/werewolf/game.py +++ b/werewolf/game.py @@ -1,8 +1,6 @@ import asyncio import discord -from datetime import datetime, timedelta - import random from werewolf.player import Player @@ -14,7 +12,7 @@ class Game: """ Base class to run a single game of Werewolf """ - + default_secret_channel = { "channel": None, "players": [], @@ -59,10 +57,7 @@ class Game: self.vote_groups = {} # ID : VoteGroup() self.night_results = [] - - - - + self.loop = asyncio.get_event_loop() async def setup(self, ctx): @@ -91,7 +86,8 @@ class Game: self.guild.me: discord.PermissionOverwrite(read_messages=True, send_messages=True) } - self.channel_category = await self.guild.create_category("ww-game", overwrites=overwrite, reason="New game of werewolf") + self.channel_category = await self.guild.create_category("ww-game", overwrites=overwrite, reason="New game of " + "werewolf") for player in self.players: overwrite[player.member] = discord.PermissionOverwrite(read_messages=True) @@ -145,7 +141,7 @@ class Game: """ await self._at_day_start() # Once cycle ends, this will trigger end_game - await self._end_game() # Handle open channels + await self._end_game() # Handle open channels async def _at_game_start(self): # ID 0 if self.game_over: diff --git a/werewolf/player.py b/werewolf/player.py index 374c8c3..a90a8be 100644 --- a/werewolf/player.py +++ b/werewolf/player.py @@ -1,8 +1,6 @@ import asyncio - import discord -from datetime import datetime, timedelta class Player: """ diff --git a/werewolf/role.py b/werewolf/role.py index dd7e944..a0c692b 100644 --- a/werewolf/role.py +++ b/werewolf/role.py @@ -1,5 +1,6 @@ import asyncio + class Role: """ Base Role class for werewolf game diff --git a/werewolf/roles/seer.py b/werewolf/roles/seer.py index cca024f..56d135b 100644 --- a/werewolf/roles/seer.py +++ b/werewolf/roles/seer.py @@ -97,12 +97,12 @@ class Seer(Role): # async def _at_day_end(self): # pass - async def _at_night_start(self): + async def _at_night_start(self, data=None): await self.game.generate_targets(self.player.member) await self.player.send_dm("{}\n**Pick a target to see tonight**\n") - async def _at_night_end(self): + async def _at_night_end(self, data=None): target = await self.game.visit(self.see_target) alignment = None diff --git a/werewolf/werewolf.py b/werewolf/werewolf.py index 3d0630c..30791a0 100644 --- a/werewolf/werewolf.py +++ b/werewolf/werewolf.py @@ -5,8 +5,6 @@ from discord.ext import commands from redbot.core import Config -from datetime import datetime, timedelta - from werewolf.game import Game @@ -48,9 +46,8 @@ class Werewolf: await ctx.send("Failed to start a new game") else: await ctx.send("New game has started") - - - @commands.guild_only() + + @commands.guild_only() @ww.command() async def join(self, ctx): """ @@ -140,7 +137,7 @@ class Werewolf: await game.vote(ctx.author, id, channel) else: await ctx.send("Nothing to vote for in this channel") - + @ww.command() async def choose(self, ctx, data): """ @@ -157,7 +154,7 @@ class Werewolf: # If multiple games, panic for game in self.games.values(): if await game.get_player_by_member(ctx.author): - break #game = game + break # game = game else: await ctx.send("You're not part of any werewolf game") return