From 9fe3b500a2cf79f92929bcc3c2caee08af20c899 Mon Sep 17 00:00:00 2001 From: janine9vn Date: Tue, 24 Nov 2020 21:37:11 -0500 Subject: [PATCH 1/7] Move constants and restructure directory - constants moved to constants.py file - create an overall "bot" directory - renamed lovelace.py to bot.py --- lovelace.py => bot/bot.py | 306 ++++++++++++++++++-------------------- bot/constants.py | 19 +++ 2 files changed, 163 insertions(+), 162 deletions(-) rename lovelace.py => bot/bot.py (84%) create mode 100644 bot/constants.py diff --git a/lovelace.py b/bot/bot.py similarity index 84% rename from lovelace.py rename to bot/bot.py index aea7dc5..d8ff69e 100644 --- a/lovelace.py +++ b/bot/bot.py @@ -1,162 +1,144 @@ -import os -from dotenv import load_dotenv - -import discord -from discord.ext import commands - -load_dotenv() -TOKEN = os.getenv('TOKEN') -COMMAND_PREFIX = "!" - -AFFINITY_GROUPS = { - 'womxn': ['womxn', 'women', 'woman'], - 'acearo': ['ace', 'aro', 'ace/aro', 'acearo'], - 'aapi': ['aapi'], - 'disability': ['disability', '(dis)ability'], - 'middle-sexualities': ['middle sexualities', 'middle-sexualities'], - 'race-ethnicity': ['race and ethnicity', 'race', 'ethnicity', 'race-ethnicity'], - 'transnon-binary': ['trans and non-binary', 'trans and nonbinary', 'trans', 'non-binary', 'enby', 'transgender', 'transnon-binary'], - 'inqueery': ['inqueery'] -} - -WORKING_GROUPS = { - 'dis-ability': ['disability', '(dis)ability'], - 'beyondthebinary': ['binary', 'beyond the binary', 'beyond-the-binary', 'beyond_the_binary'], - 'black_queer': ['black and queer', 'black', 'queery', 'black n queer', 'black_and_queer', 'black-and-queer', 'black_queer'] -} - -ACTIVE_GUILD = "oSTEM Global" - - -class oSTEMBot(commands.Bot): - """ - This is the base bot instance. - """ - - def __init__(self, **kwargs): - super().__init__(**kwargs) - - -# Intents -intents = discord.Intents.default() -intents.members = True - - -bot = oSTEMBot( - command_prefix=COMMAND_PREFIX, - activity=discord.Game(name=f"Commands: {COMMAND_PREFIX}help"), - intents=intents -) - - -class WorkingGroups(commands.Cog): - """A cog that manages users adding themslves and leaving Working Groups""" - - def __init__(self, bot: commands.Bot): - self.bot = bot - - @commands.command() - async def join_wg(self, ctx: commands.Context, *, working_group: str) -> None: - """Direct Message the bot with the affinity group they want to join. The bot will add you to the correct group. - - The current working groups can be found on the oSTEM.org website. - """ - guild = discord.utils.get(bot.guilds, name=ACTIVE_GUILD) - if await _has_role_check(ctx, guild, "Member"): - category = discord.utils.get(guild.categories, name="Working Groups") - await _add_remove_from_group(ctx, working_group, category, True) - else: - msg_content = """Sorry, you have not accepted the server rules yet.\ - \nPlease read the #welcome channel and click on the existing reaction emoji to agree to the server rules.""" - await ctx.author.send(msg_content) - - @commands.command() - async def leave_wg(self, ctx: commands.Context, *, working_group: str) -> None: - """Direct Message the bot with the affinity group that you would like to leave. - The bot will remove you from the group.""" - guild = discord.utils.get(bot.guilds, name=ACTIVE_GUILD) - category = discord.utils.get(guild.categories, name="Working Groups") - await _add_remove_from_group(ctx, working_group, category, False) - - -class AffinityGroups(commands.Cog): - """A cog that manages users adding themselves and leaving Affinity Groups""" - - def __init__(self, bot: commands.Bot): - self.bot = bot - - @commands.command() - async def join_ag(self, ctx: commands.Context, *, affinity_group: str) -> None: - """Direct Message the bot with the affinity group they want to join. The bot will add you to the correct group. - - The current affinity groups can be found on the oSTEM.org website - """ - guild = discord.utils.get(bot.guilds, name=ACTIVE_GUILD) - if await _has_role_check(ctx, guild, "Member"): - category = discord.utils.get(guild.categories, name="affinity groups") - await _add_remove_from_group(ctx, affinity_group, category, True) - else: - msg_content = """Sorry, you have not accepted the server rules yet.\ - \nPlease read the #welcome channel and click on the existing reaction emoji to agree to the server rules.""" - await ctx.author.send(msg_content) - - @commands.command() - async def leave_ag(self, ctx: commands.Context, *, affinity_group: str) -> None: - """Direct Message the bot with the affinity group that you would like to leave. - The bot will remove you from the group.""" - - guild = discord.utils.get(bot.guilds, name=ACTIVE_GUILD) - category = discord.utils.get(guild.categories, name="affinity groups") - await _add_remove_from_group(ctx, affinity_group, category, False) - - -async def _has_role_check(ctx: commands.Context, guild, *role_name: int) -> bool: - """Checks if the user has a specific role within the server""" - member = guild.get_member(int(ctx.author.id)) - - for role in member.roles: - if role.name in role_name: - return True - return False - - -async def _add_remove_from_group(ctx: commands.Context, channel_name: str, category, add: bool = True) -> bool: - """Helper function to add or remove a user from a specific channel. - If add is false, it will remove the permissions.""" - - guild = discord.utils.get(bot.guilds, name=ACTIVE_GUILD) - - active_group = '' - if category.name == "affinity groups": - active_group = AFFINITY_GROUPS - elif category.name == "Working Groups": - active_group = WORKING_GROUPS - - msg_content = f":x: Sorry, there was an error. Please try again or contact an admin." - - for key, value in active_group.items(): - if channel_name.lower() in value: - channel = discord.utils.get(guild.channels, category_id=category.id, name=key) - await channel.set_permissions(ctx.author, read_messages=add, send_messages=add, add_reactions=add, - read_message_history=add, external_emojis=add, attach_files=add, - embed_links=add) - if add is True: - result = "added" - else: - result = "removed" - msg_content = f":white_check_mark: You have been successfully {result} from the {key} affinity group channel.\ - \nIf there was an error, please contact an admin." - await ctx.author.send(msg_content) - if ctx.channel.type is discord.ChannelType.text: - await ctx.message.delete() - - -@bot.command(hidden=True) -async def on_ready(self, *args, **kwargs): - print(f'{bot.user} has connected to Discord') - - -bot.add_cog(AffinityGroups(bot)) -bot.add_cog(WorkingGroups(bot)) - -bot.run(TOKEN) +import os +from dotenv import load_dotenv + +import discord +from discord.ext import commands + +from lovelace.constants import COMMAND_PREFIX, ACTIVE_GUILD, AFFINITY_GROUPS, WORKING_GROUPS + +load_dotenv() +TOKEN = os.getenv('TOKEN') + + +class oSTEMBot(commands.Bot): + """ + This is the base bot instance. + """ + + def __init__(self, **kwargs): + super().__init__(**kwargs) + + +# Intents +intents = discord.Intents.default() +intents.members = True + + +bot = oSTEMBot( + command_prefix=COMMAND_PREFIX, + activity=discord.Game(name=f"Commands: {COMMAND_PREFIX}help"), + intents=intents +) + + +class WorkingGroups(commands.Cog): + """A cog that manages users adding themslves and leaving Working Groups""" + + def __init__(self, bot: commands.Bot): + self.bot = bot + + @commands.command() + async def join_wg(self, ctx: commands.Context, *, working_group: str) -> None: + """Direct Message the bot with the affinity group they want to join. The bot will add you to the correct group. + + The current working groups can be found on the oSTEM.org website. + """ + guild = discord.utils.get(bot.guilds, name=ACTIVE_GUILD) + if await _has_role_check(ctx, guild, "Member"): + category = discord.utils.get(guild.categories, name="Working Groups") + await _add_remove_from_group(ctx, working_group, category, True) + else: + msg_content = """Sorry, you have not accepted the server rules yet.\ + \nPlease read the #welcome channel and click on the existing reaction emoji to agree to the server rules.""" + await ctx.author.send(msg_content) + + @commands.command() + async def leave_wg(self, ctx: commands.Context, *, working_group: str) -> None: + """Direct Message the bot with the affinity group that you would like to leave. + The bot will remove you from the group.""" + guild = discord.utils.get(bot.guilds, name=ACTIVE_GUILD) + category = discord.utils.get(guild.categories, name="Working Groups") + await _add_remove_from_group(ctx, working_group, category, False) + + +class AffinityGroups(commands.Cog): + """A cog that manages users adding themselves and leaving Affinity Groups""" + + def __init__(self, bot: commands.Bot): + self.bot = bot + + @commands.command() + async def join_ag(self, ctx: commands.Context, *, affinity_group: str) -> None: + """Direct Message the bot with the affinity group they want to join. The bot will add you to the correct group. + + The current affinity groups can be found on the oSTEM.org website + """ + guild = discord.utils.get(bot.guilds, name=ACTIVE_GUILD) + if await _has_role_check(ctx, guild, "Member"): + category = discord.utils.get(guild.categories, name="affinity groups") + await _add_remove_from_group(ctx, affinity_group, category, True) + else: + msg_content = """Sorry, you have not accepted the server rules yet.\ + \nPlease read the #welcome channel and click on the existing reaction emoji to agree to the server rules.""" + await ctx.author.send(msg_content) + + @commands.command() + async def leave_ag(self, ctx: commands.Context, *, affinity_group: str) -> None: + """Direct Message the bot with the affinity group that you would like to leave. + The bot will remove you from the group.""" + + guild = discord.utils.get(bot.guilds, name=ACTIVE_GUILD) + category = discord.utils.get(guild.categories, name="affinity groups") + await _add_remove_from_group(ctx, affinity_group, category, False) + + +async def _has_role_check(ctx: commands.Context, guild, *role_name: int) -> bool: + """Checks if the user has a specific role within the server""" + member = guild.get_member(int(ctx.author.id)) + + for role in member.roles: + if role.name in role_name: + return True + return False + + +async def _add_remove_from_group(ctx: commands.Context, channel_name: str, category, add: bool = True) -> bool: + """Helper function to add or remove a user from a specific channel. + If add is false, it will remove the permissions.""" + + guild = discord.utils.get(bot.guilds, name=ACTIVE_GUILD) + + active_group = '' + if category.name == "affinity groups": + active_group = AFFINITY_GROUPS + elif category.name == "Working Groups": + active_group = WORKING_GROUPS + + msg_content = f":x: Sorry, there was an error. Please try again or contact an admin." + + for key, value in active_group.items(): + if channel_name.lower() in value: + channel = discord.utils.get(guild.channels, category_id=category.id, name=key) + await channel.set_permissions(ctx.author, read_messages=add, send_messages=add, add_reactions=add, + read_message_history=add, external_emojis=add, attach_files=add, + embed_links=add) + if add is True: + result = "added" + else: + result = "removed" + msg_content = f":white_check_mark: You have been successfully {result} from the {key} affinity group channel.\ + \nIf there was an error, please contact an admin." + await ctx.author.send(msg_content) + if ctx.channel.type is discord.ChannelType.text: + await ctx.message.delete() + + +@bot.command(hidden=True) +async def on_ready(self, *args, **kwargs): + print(f'{bot.user} has connected to Discord') + + +bot.add_cog(AffinityGroups(bot)) +bot.add_cog(WorkingGroups(bot)) + +bot.run(TOKEN) diff --git a/bot/constants.py b/bot/constants.py new file mode 100644 index 0000000..52cae1b --- /dev/null +++ b/bot/constants.py @@ -0,0 +1,19 @@ +COMMAND_PREFIX = "!" +ACTIVE_GUILD = "oSTEM Global" + +AFFINITY_GROUPS = { + 'womxn': ['womxn', 'women', 'woman'], + 'acearo': ['ace', 'aro', 'ace/aro', 'acearo'], + 'aapi': ['aapi'], + 'disability': ['disability', '(dis)ability'], + 'middle-sexualities': ['middle sexualities', 'middle-sexualities'], + 'race-ethnicity': ['race and ethnicity', 'race', 'ethnicity', 'race-ethnicity'], + 'transnon-binary': ['trans and non-binary', 'trans and nonbinary', 'trans', 'non-binary', 'enby', 'transgender', 'transnon-binary'], + 'inqueery': ['inqueery'] +} + +WORKING_GROUPS = { + 'dis-ability': ['disability', '(dis)ability'], + 'beyondthebinary': ['binary', 'beyond the binary', 'beyond-the-binary', 'beyond_the_binary'], + 'black_queer': ['black and queer', 'black', 'queery', 'black n queer', 'black_and_queer', 'black-and-queer', 'black_queer'] +} From 7097f790d12dc823c92491a318d2d3db89320cae Mon Sep 17 00:00:00 2001 From: janine9vn Date: Tue, 24 Nov 2020 21:59:18 -0500 Subject: [PATCH 2/7] Refactor directory to accomodate extensions Lovelace is now a package! It requires a different command to run, the README is updated. There is now an overaching bot directory folder with appropriate __init__ and __main__ files. Additionally, there are two new folder strucutres: exts and utils. exts is for Extensions while util is for utility functions and classes. Functionality for autoloading extensions was also added. It checks if a setup function is in the file, if yes than it'll load in the extension. --- README.md | 9 ++- bot/__init__.py | 0 bot/__main__.py | 23 ++++++ bot/bot.py | 116 +--------------------------- bot/exts/__init__.py | 0 bot/exts/affinity_working_groups.py | 105 +++++++++++++++++++++++++ bot/utils/role_checks.py | 11 +++ 7 files changed, 147 insertions(+), 117 deletions(-) create mode 100644 bot/__init__.py create mode 100644 bot/__main__.py create mode 100644 bot/exts/__init__.py create mode 100644 bot/exts/affinity_working_groups.py create mode 100644 bot/utils/role_checks.py diff --git a/README.md b/README.md index d95c9dd..8a4c46b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # lovelace -oSTEM's custom Discord bot, Lovelace. Currently in an alpha state with major rewrites and reorganization to come. +oSTEM's custom Discord bot, Lovelace. Happily accepting contributions! ## Set-up Requirements This is a Python Discord bot that uses the discord.py framework. @@ -15,4 +15,9 @@ to install all of the dependencies of this project ## Running the bot on a test server This bot is tightly coupled with how we set-up our server. - The affinity and working groups require that the specific channel names tied to those dictionary constants are present. -- You will need to update the `ACTIVE_GUILD` constant to match the test server. +- You will need to update the `ACTIVE_GUILD` constant to match the test server. +- Ensure you have a `.env` file with the token for your test bot (`TOKEN=...`) +- To run locally, you will need to navigate to the `lovelace` folder and then run the command: +```bash +python -m bot +``` \ No newline at end of file diff --git a/bot/__init__.py b/bot/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/bot/__main__.py b/bot/__main__.py new file mode 100644 index 0000000..3967fef --- /dev/null +++ b/bot/__main__.py @@ -0,0 +1,23 @@ +import importlib +import inspect +import os +import pkgutil + +from dotenv import load_dotenv + +from bot import exts +from bot.bot import bot + +if __name__ == "__main__": + load_dotenv() + TOKEN = os.getenv('TOKEN') + + for module in pkgutil.walk_packages(exts.__path__, f"{exts.__name__}."): + if module.ispkg: + imported = importlib.import_module(module.name) + if not inspect.isfunction(getattr(imported, "setup", None)): + # If there's no setup function, we skip it as it's not an extension and will fail to load + continue + bot.load_extension(module.name) + + bot.run(TOKEN) diff --git a/bot/bot.py b/bot/bot.py index d8ff69e..ca44aeb 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -1,13 +1,7 @@ -import os -from dotenv import load_dotenv - import discord from discord.ext import commands -from lovelace.constants import COMMAND_PREFIX, ACTIVE_GUILD, AFFINITY_GROUPS, WORKING_GROUPS - -load_dotenv() -TOKEN = os.getenv('TOKEN') +from bot.constants import COMMAND_PREFIX class oSTEMBot(commands.Bot): @@ -31,114 +25,6 @@ def __init__(self, **kwargs): ) -class WorkingGroups(commands.Cog): - """A cog that manages users adding themslves and leaving Working Groups""" - - def __init__(self, bot: commands.Bot): - self.bot = bot - - @commands.command() - async def join_wg(self, ctx: commands.Context, *, working_group: str) -> None: - """Direct Message the bot with the affinity group they want to join. The bot will add you to the correct group. - - The current working groups can be found on the oSTEM.org website. - """ - guild = discord.utils.get(bot.guilds, name=ACTIVE_GUILD) - if await _has_role_check(ctx, guild, "Member"): - category = discord.utils.get(guild.categories, name="Working Groups") - await _add_remove_from_group(ctx, working_group, category, True) - else: - msg_content = """Sorry, you have not accepted the server rules yet.\ - \nPlease read the #welcome channel and click on the existing reaction emoji to agree to the server rules.""" - await ctx.author.send(msg_content) - - @commands.command() - async def leave_wg(self, ctx: commands.Context, *, working_group: str) -> None: - """Direct Message the bot with the affinity group that you would like to leave. - The bot will remove you from the group.""" - guild = discord.utils.get(bot.guilds, name=ACTIVE_GUILD) - category = discord.utils.get(guild.categories, name="Working Groups") - await _add_remove_from_group(ctx, working_group, category, False) - - -class AffinityGroups(commands.Cog): - """A cog that manages users adding themselves and leaving Affinity Groups""" - - def __init__(self, bot: commands.Bot): - self.bot = bot - - @commands.command() - async def join_ag(self, ctx: commands.Context, *, affinity_group: str) -> None: - """Direct Message the bot with the affinity group they want to join. The bot will add you to the correct group. - - The current affinity groups can be found on the oSTEM.org website - """ - guild = discord.utils.get(bot.guilds, name=ACTIVE_GUILD) - if await _has_role_check(ctx, guild, "Member"): - category = discord.utils.get(guild.categories, name="affinity groups") - await _add_remove_from_group(ctx, affinity_group, category, True) - else: - msg_content = """Sorry, you have not accepted the server rules yet.\ - \nPlease read the #welcome channel and click on the existing reaction emoji to agree to the server rules.""" - await ctx.author.send(msg_content) - - @commands.command() - async def leave_ag(self, ctx: commands.Context, *, affinity_group: str) -> None: - """Direct Message the bot with the affinity group that you would like to leave. - The bot will remove you from the group.""" - - guild = discord.utils.get(bot.guilds, name=ACTIVE_GUILD) - category = discord.utils.get(guild.categories, name="affinity groups") - await _add_remove_from_group(ctx, affinity_group, category, False) - - -async def _has_role_check(ctx: commands.Context, guild, *role_name: int) -> bool: - """Checks if the user has a specific role within the server""" - member = guild.get_member(int(ctx.author.id)) - - for role in member.roles: - if role.name in role_name: - return True - return False - - -async def _add_remove_from_group(ctx: commands.Context, channel_name: str, category, add: bool = True) -> bool: - """Helper function to add or remove a user from a specific channel. - If add is false, it will remove the permissions.""" - - guild = discord.utils.get(bot.guilds, name=ACTIVE_GUILD) - - active_group = '' - if category.name == "affinity groups": - active_group = AFFINITY_GROUPS - elif category.name == "Working Groups": - active_group = WORKING_GROUPS - - msg_content = f":x: Sorry, there was an error. Please try again or contact an admin." - - for key, value in active_group.items(): - if channel_name.lower() in value: - channel = discord.utils.get(guild.channels, category_id=category.id, name=key) - await channel.set_permissions(ctx.author, read_messages=add, send_messages=add, add_reactions=add, - read_message_history=add, external_emojis=add, attach_files=add, - embed_links=add) - if add is True: - result = "added" - else: - result = "removed" - msg_content = f":white_check_mark: You have been successfully {result} from the {key} affinity group channel.\ - \nIf there was an error, please contact an admin." - await ctx.author.send(msg_content) - if ctx.channel.type is discord.ChannelType.text: - await ctx.message.delete() - - @bot.command(hidden=True) async def on_ready(self, *args, **kwargs): print(f'{bot.user} has connected to Discord') - - -bot.add_cog(AffinityGroups(bot)) -bot.add_cog(WorkingGroups(bot)) - -bot.run(TOKEN) diff --git a/bot/exts/__init__.py b/bot/exts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/bot/exts/affinity_working_groups.py b/bot/exts/affinity_working_groups.py new file mode 100644 index 0000000..14b3eb6 --- /dev/null +++ b/bot/exts/affinity_working_groups.py @@ -0,0 +1,105 @@ +import discord +from discord.ext import commands + +from bot.bot import bot +from bot.constants import ACTIVE_GUILD, AFFINITY_GROUPS, WORKING_GROUPS +from bot.utils.role_checks import _has_role_check + + +class WorkingGroups(commands.Cog): + """A cog that manages users adding themslves and leaving Working Groups""" + + def __init__(self, bot: commands.Bot): + self.bot = bot + + @commands.command() + async def join_wg(self, ctx: commands.Context, *, working_group: str) -> None: + """Direct Message the bot with the affinity group they want to join. The bot will add you to the correct group. + + The current working groups can be found on the oSTEM.org website. + """ + guild = discord.utils.get(bot.guilds, name=ACTIVE_GUILD) + if await _has_role_check(ctx, guild, "Member"): + category = discord.utils.get(guild.categories, name="Working Groups") + await _add_remove_from_group(ctx, working_group, category, True) + else: + msg_content = """Sorry, you have not accepted the server rules yet.\ + \nPlease read the #welcome channel and click on the existing reaction emoji to agree to the server rules.""" + await ctx.author.send(msg_content) + + @commands.command() + async def leave_wg(self, ctx: commands.Context, *, working_group: str) -> None: + """Direct Message the bot with the affinity group that you would like to leave. + The bot will remove you from the group.""" + guild = discord.utils.get(bot.guilds, name=ACTIVE_GUILD) + category = discord.utils.get(guild.categories, name="Working Groups") + await _add_remove_from_group(ctx, working_group, category, False) + + +class AffinityGroups(commands.Cog): + """A cog that manages users adding themselves and leaving Affinity Groups""" + + def __init__(self, bot: commands.Bot): + self.bot = bot + + @commands.command() + async def join_ag(self, ctx: commands.Context, *, affinity_group: str) -> None: + """Direct Message the bot with the affinity group they want to join. The bot will add you to the correct group. + + The current affinity groups can be found on the oSTEM.org website + """ + guild = discord.utils.get(bot.guilds, name=ACTIVE_GUILD) + if await _has_role_check(ctx, guild, "Member"): + category = discord.utils.get(guild.categories, name="affinity groups") + await _add_remove_from_group(ctx, affinity_group, category, True) + else: + msg_content = """Sorry, you have not accepted the server rules yet.\ + \nPlease read the #welcome channel and click on the existing reaction emoji to agree to the server rules.""" + await ctx.author.send(msg_content) + + @commands.command() + async def leave_ag(self, ctx: commands.Context, *, affinity_group: str) -> None: + """Direct Message the bot with the affinity group that you would like to leave. + The bot will remove you from the group.""" + + guild = discord.utils.get(bot.guilds, name=ACTIVE_GUILD) + category = discord.utils.get(guild.categories, name="affinity groups") + await _add_remove_from_group(ctx, affinity_group, category, False) + + +async def _add_remove_from_group(ctx: commands.Context, channel_name: str, category, add: bool = True) -> bool: + """Helper function to add or remove a user from a specific channel. + If add is false, it will remove the permissions.""" + + guild = discord.utils.get(bot.guilds, name=ACTIVE_GUILD) + + active_group = '' + if category.name == "affinity groups": + active_group = AFFINITY_GROUPS + elif category.name == "Working Groups": + active_group = WORKING_GROUPS + + msg_content = ":x: Sorry, there was an error. Please try again or contact an admin." + + for key, value in active_group.items(): + if channel_name.lower() in value: + channel = discord.utils.get(guild.channels, category_id=category.id, name=key) + await channel.set_permissions(ctx.author, read_messages=add, send_messages=add, add_reactions=add, + read_message_history=add, external_emojis=add, attach_files=add, + embed_links=add) + if add is True: + result = "added" + else: + result = "removed" + msg_content = f":white_check_mark: You have been successfully {result} from the {key} affinity group channel.\ + \nIf there was an error, please contact an admin." + await ctx.author.send(msg_content) + if ctx.channel.type is discord.ChannelType.text: + # If the message was in a public channel, we will delete the message to maintain privacy + await ctx.message.delete() + + +def setup(bot: commands.Bot) -> None: + """Load Affinity and Working Groups cogs""" + bot.add_cog(AffinityGroups(bot)) + bot.add_cog(WorkingGroups(bot)) diff --git a/bot/utils/role_checks.py b/bot/utils/role_checks.py new file mode 100644 index 0000000..df26799 --- /dev/null +++ b/bot/utils/role_checks.py @@ -0,0 +1,11 @@ +from discord.ext import commands + + +async def _has_role_check(ctx: commands.Context, guild, *role_name: int) -> bool: + """Checks if the user has a specific role within the server""" + member = guild.get_member(int(ctx.author.id)) + + for role in member.roles: + if role.name in role_name: + return True + return False From f57f5b6091d5c88405e6443ef0b7d252b74b1595 Mon Sep 17 00:00:00 2001 From: Janine vN Date: Tue, 24 Nov 2020 22:39:38 -0500 Subject: [PATCH 3/7] Update bot/utils/role_checks.py Co-authored-by: Travis DePrato <773453+travigd@users.noreply.github.com> --- bot/utils/role_checks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/utils/role_checks.py b/bot/utils/role_checks.py index df26799..87520c7 100644 --- a/bot/utils/role_checks.py +++ b/bot/utils/role_checks.py @@ -1,7 +1,7 @@ from discord.ext import commands -async def _has_role_check(ctx: commands.Context, guild, *role_name: int) -> bool: +async def _has_role_check(ctx: commands.Context, guild, *role_names: str) -> bool: """Checks if the user has a specific role within the server""" member = guild.get_member(int(ctx.author.id)) From 64e551d21482ad82f67540539d3155c9c3421d05 Mon Sep 17 00:00:00 2001 From: Janine vN Date: Sun, 6 Jun 2021 13:46:38 -0400 Subject: [PATCH 4/7] SImplifying Bot I've simplified the bot set-up and made it not a module to make sure that setting it up locally for contributions is easier. The other big change is the less-smart, but more-readable/understandable method of loading extensions. If a new extenion is added it must be manually added to Lovelace's `__init__()`. These changes are also made in preperation for adding in slash commands. --- .gitignore | 3 +++ bot/__init__.py | 0 bot/__main__.py | 23 ------------------ bot/bot.py | 35 +++++++++++++++++----------- bot/exts/affinity_working_groups.py | 36 ++++++++++------------------- bot/utils/role_checks.py | 2 +- 6 files changed, 38 insertions(+), 61 deletions(-) delete mode 100644 bot/__init__.py delete mode 100644 bot/__main__.py diff --git a/.gitignore b/.gitignore index b6e4761..6738b9d 100644 --- a/.gitignore +++ b/.gitignore @@ -127,3 +127,6 @@ dmypy.json # Pyre type checker .pyre/ + +# Editors +.vscode/ \ No newline at end of file diff --git a/bot/__init__.py b/bot/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/bot/__main__.py b/bot/__main__.py deleted file mode 100644 index 3967fef..0000000 --- a/bot/__main__.py +++ /dev/null @@ -1,23 +0,0 @@ -import importlib -import inspect -import os -import pkgutil - -from dotenv import load_dotenv - -from bot import exts -from bot.bot import bot - -if __name__ == "__main__": - load_dotenv() - TOKEN = os.getenv('TOKEN') - - for module in pkgutil.walk_packages(exts.__path__, f"{exts.__name__}."): - if module.ispkg: - imported = importlib.import_module(module.name) - if not inspect.isfunction(getattr(imported, "setup", None)): - # If there's no setup function, we skip it as it's not an extension and will fail to load - continue - bot.load_extension(module.name) - - bot.run(TOKEN) diff --git a/bot/bot.py b/bot/bot.py index ca44aeb..99a1bb0 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -1,30 +1,39 @@ +import os + import discord from discord.ext import commands +from dotenv import load_dotenv -from bot.constants import COMMAND_PREFIX +from constants import COMMAND_PREFIX -class oSTEMBot(commands.Bot): +class Lovelace(commands.Bot): """ This is the base bot instance. """ def __init__(self, **kwargs): super().__init__(**kwargs) + self.load_extension("exts.affinity_working_groups") + + async def on_ready(self, *args, **kwargs): + print(f'{bot.user} has connected to Discord') -# Intents -intents = discord.Intents.default() -intents.members = True +if __name__ == "__main__": + load_dotenv() + TOKEN = os.getenv('TOKEN') + # Intents + intents = discord.Intents.default() + intents.members = True -bot = oSTEMBot( - command_prefix=COMMAND_PREFIX, - activity=discord.Game(name=f"Commands: {COMMAND_PREFIX}help"), - intents=intents -) + bot = Lovelace( + command_prefix=COMMAND_PREFIX, + activity=discord.Game(name=f"Commands: {COMMAND_PREFIX}help"), + intents=intents, + allowed_mentions=discord.AllowedMentions(everyone=False) + ) -@bot.command(hidden=True) -async def on_ready(self, *args, **kwargs): - print(f'{bot.user} has connected to Discord') + bot.run(TOKEN) \ No newline at end of file diff --git a/bot/exts/affinity_working_groups.py b/bot/exts/affinity_working_groups.py index 14b3eb6..a365bba 100644 --- a/bot/exts/affinity_working_groups.py +++ b/bot/exts/affinity_working_groups.py @@ -1,9 +1,7 @@ import discord from discord.ext import commands -from bot.bot import bot -from bot.constants import ACTIVE_GUILD, AFFINITY_GROUPS, WORKING_GROUPS -from bot.utils.role_checks import _has_role_check +from constants import ACTIVE_GUILD, AFFINITY_GROUPS, WORKING_GROUPS class WorkingGroups(commands.Cog): @@ -18,22 +16,17 @@ async def join_wg(self, ctx: commands.Context, *, working_group: str) -> None: The current working groups can be found on the oSTEM.org website. """ - guild = discord.utils.get(bot.guilds, name=ACTIVE_GUILD) - if await _has_role_check(ctx, guild, "Member"): - category = discord.utils.get(guild.categories, name="Working Groups") - await _add_remove_from_group(ctx, working_group, category, True) - else: - msg_content = """Sorry, you have not accepted the server rules yet.\ - \nPlease read the #welcome channel and click on the existing reaction emoji to agree to the server rules.""" - await ctx.author.send(msg_content) + guild = discord.utils.get(self.bot.guilds, name=ACTIVE_GUILD) + category = discord.utils.get(guild.categories, name="Working Groups") + await _add_remove_from_group(self, ctx, working_group, category, True) @commands.command() async def leave_wg(self, ctx: commands.Context, *, working_group: str) -> None: """Direct Message the bot with the affinity group that you would like to leave. The bot will remove you from the group.""" - guild = discord.utils.get(bot.guilds, name=ACTIVE_GUILD) + guild = discord.utils.get(self.bot.guilds, name=ACTIVE_GUILD) category = discord.utils.get(guild.categories, name="Working Groups") - await _add_remove_from_group(ctx, working_group, category, False) + await _add_remove_from_group(self, ctx, working_group, category, False) class AffinityGroups(commands.Cog): @@ -48,26 +41,21 @@ async def join_ag(self, ctx: commands.Context, *, affinity_group: str) -> None: The current affinity groups can be found on the oSTEM.org website """ - guild = discord.utils.get(bot.guilds, name=ACTIVE_GUILD) - if await _has_role_check(ctx, guild, "Member"): - category = discord.utils.get(guild.categories, name="affinity groups") - await _add_remove_from_group(ctx, affinity_group, category, True) - else: - msg_content = """Sorry, you have not accepted the server rules yet.\ - \nPlease read the #welcome channel and click on the existing reaction emoji to agree to the server rules.""" - await ctx.author.send(msg_content) + guild = discord.utils.get(self.bot.guilds, name=ACTIVE_GUILD) + category = discord.utils.get(guild.categories, name="affinity groups") + await _add_remove_from_group(self, ctx, affinity_group, category, True) @commands.command() async def leave_ag(self, ctx: commands.Context, *, affinity_group: str) -> None: """Direct Message the bot with the affinity group that you would like to leave. The bot will remove you from the group.""" - guild = discord.utils.get(bot.guilds, name=ACTIVE_GUILD) + guild = discord.utils.get(self.bot.guilds, name=ACTIVE_GUILD) category = discord.utils.get(guild.categories, name="affinity groups") - await _add_remove_from_group(ctx, affinity_group, category, False) + await _add_remove_from_group(self, ctx, affinity_group, category, False) -async def _add_remove_from_group(ctx: commands.Context, channel_name: str, category, add: bool = True) -> bool: +async def _add_remove_from_group(bot, ctx: commands.Context, channel_name: str, category, add: bool = True) -> bool: """Helper function to add or remove a user from a specific channel. If add is false, it will remove the permissions.""" diff --git a/bot/utils/role_checks.py b/bot/utils/role_checks.py index 87520c7..60309d5 100644 --- a/bot/utils/role_checks.py +++ b/bot/utils/role_checks.py @@ -6,6 +6,6 @@ async def _has_role_check(ctx: commands.Context, guild, *role_names: str) -> boo member = guild.get_member(int(ctx.author.id)) for role in member.roles: - if role.name in role_name: + if role.name in role_names: return True return False From 75d918eb7bdb5c534961d7cdd921241376c42ecb Mon Sep 17 00:00:00 2001 From: Janine vN Date: Wed, 16 Jun 2021 16:44:31 -0400 Subject: [PATCH 5/7] Add in Docker related files This adds in the Dockerfile to run a basic instance of this bot. It takes the bot Token as an ENV argument. Eventually this should be changed to use a proper secrets file / vault. --- .dockerignore | 3 +++ Dockerfile | 10 ++++++++++ 2 files changed, 13 insertions(+) create mode 100644 .dockerignore create mode 100644 Dockerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..5ebe6da --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +.env +.github/ +.vscode/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..11abd4b --- /dev/null +++ b/Dockerfile @@ -0,0 +1,10 @@ +FROM python:3.9-slim-buster +WORKDIR /app +COPY requirements.txt . +RUN python3 -m pip install -r requirements.txt + +COPY bot/ . + +ENV token=$TOKEN + +CMD ["python3", "./bot.py"] \ No newline at end of file From 79d47e53f4f7bdcfd08f163c4d6de23244597ab1 Mon Sep 17 00:00:00 2001 From: Janine vN Date: Wed, 16 Jun 2021 17:26:33 -0400 Subject: [PATCH 6/7] Switch functionality to Slash Commands This probably-too-large commit is a complete overhaul of the affinity and working group commands to use Slash Commands instead. Overall, the previous `!` commands were removed and instead replaced with the slash commands response. It makes some assumptions about the server setup and reduces some of the code complexity and constants required. With this includes a file to register and update the slash commands. --- README.md | 34 ++++---- bot/bot.py | 11 +-- bot/constants.py | 20 +---- bot/exts/affinity_working_groups.py | 119 +++++++++++++--------------- bot/register_command.py | 99 +++++++++++++++++++++++ requirements.txt | 4 +- 6 files changed, 184 insertions(+), 103 deletions(-) create mode 100644 bot/register_command.py diff --git a/README.md b/README.md index 8a4c46b..e34b941 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,25 @@ -# lovelace +# Lovelace oSTEM's custom Discord bot, Lovelace. Happily accepting contributions! -## Set-up Requirements -This is a Python Discord bot that uses the discord.py framework. -- Python 3.6+ +This bot uses the discord.py library for the basic bot functionality and uses dislash.py for Slash Commands support. + +The main purpose of the bot is to provide functionality for joining Affinity and Working groups securely + +# Set-up Requirements +This is a Python Discord bot that uses the discord.py and dislash.py frameworks. +It requires python 3.6+ but it currently using what is specified in the `Dockerfile`. + +Additional, this bot uses Docker to run the application. +The commands to build the docker image and to run the container are as follows: -Run the command ```bash -python -m pip install -r requirements.txt +docker build -t lovelace . ``` -to install all of the dependencies of this project - -## Running the bot on a test server -This bot is tightly coupled with how we set-up our server. -- The affinity and working groups require that the specific channel names tied to those dictionary constants are present. -- You will need to update the `ACTIVE_GUILD` constant to match the test server. -- Ensure you have a `.env` file with the token for your test bot (`TOKEN=...`) -- To run locally, you will need to navigate to the `lovelace` folder and then run the command: ```bash -python -m bot -``` \ No newline at end of file +docker run -e "TOKEN=token_goes_here" lovelace +``` + +The `register_command.py` file is required to run once and requires an adjustment to the `Dockerfile`, specifically the file for `CMD`. This registers the Slash Commands for the specified Guild. + +Once the commands are registered for the guild, the bot can be re-run normally with the Docker commands listed above. diff --git a/bot/bot.py b/bot/bot.py index 99a1bb0..8a84732 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -1,10 +1,10 @@ import os import discord +from dislash import SlashClient from discord.ext import commands -from dotenv import load_dotenv -from constants import COMMAND_PREFIX +from constants import COMMAND_PREFIX, LOG_CHANNEL class Lovelace(commands.Bot): @@ -17,11 +17,10 @@ def __init__(self, **kwargs): self.load_extension("exts.affinity_working_groups") async def on_ready(self, *args, **kwargs): - print(f'{bot.user} has connected to Discord') + await self.get_channel(LOG_CHANNEL).send("I have connected.") if __name__ == "__main__": - load_dotenv() TOKEN = os.getenv('TOKEN') # Intents @@ -31,9 +30,11 @@ async def on_ready(self, *args, **kwargs): bot = Lovelace( command_prefix=COMMAND_PREFIX, - activity=discord.Game(name=f"Commands: {COMMAND_PREFIX}help"), + acitivty=None, intents=intents, allowed_mentions=discord.AllowedMentions(everyone=False) ) + slash = SlashClient(bot) + bot.run(TOKEN) \ No newline at end of file diff --git a/bot/constants.py b/bot/constants.py index 52cae1b..c2ea530 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -1,19 +1,3 @@ COMMAND_PREFIX = "!" -ACTIVE_GUILD = "oSTEM Global" - -AFFINITY_GROUPS = { - 'womxn': ['womxn', 'women', 'woman'], - 'acearo': ['ace', 'aro', 'ace/aro', 'acearo'], - 'aapi': ['aapi'], - 'disability': ['disability', '(dis)ability'], - 'middle-sexualities': ['middle sexualities', 'middle-sexualities'], - 'race-ethnicity': ['race and ethnicity', 'race', 'ethnicity', 'race-ethnicity'], - 'transnon-binary': ['trans and non-binary', 'trans and nonbinary', 'trans', 'non-binary', 'enby', 'transgender', 'transnon-binary'], - 'inqueery': ['inqueery'] -} - -WORKING_GROUPS = { - 'dis-ability': ['disability', '(dis)ability'], - 'beyondthebinary': ['binary', 'beyond the binary', 'beyond-the-binary', 'beyond_the_binary'], - 'black_queer': ['black and queer', 'black', 'queery', 'black n queer', 'black_and_queer', 'black-and-queer', 'black_queer'] -} +GUILD_ID = 754379784460566569 +LOG_CHANNEL = 784878993160929310 diff --git a/bot/exts/affinity_working_groups.py b/bot/exts/affinity_working_groups.py index a365bba..8367a80 100644 --- a/bot/exts/affinity_working_groups.py +++ b/bot/exts/affinity_working_groups.py @@ -1,7 +1,6 @@ import discord from discord.ext import commands - -from constants import ACTIVE_GUILD, AFFINITY_GROUPS, WORKING_GROUPS +from dislash import slash_commands class WorkingGroups(commands.Cog): @@ -10,23 +9,30 @@ class WorkingGroups(commands.Cog): def __init__(self, bot: commands.Bot): self.bot = bot - @commands.command() - async def join_wg(self, ctx: commands.Context, *, working_group: str) -> None: - """Direct Message the bot with the affinity group they want to join. The bot will add you to the correct group. - - The current working groups can be found on the oSTEM.org website. - """ - guild = discord.utils.get(self.bot.guilds, name=ACTIVE_GUILD) - category = discord.utils.get(guild.categories, name="Working Groups") - await _add_remove_from_group(self, ctx, working_group, category, True) + @slash_commands.command(name="working-group") + async def affinity_group(self, interaction): + for k, v in interaction.data.options.items(): + if v.name == "join": + add = True + action = "joined" + else: + add = False + action = "left" + + result = await _add_remove_from_group(interaction.guild, interaction.author, v.value, "working groups", add) - @commands.command() - async def leave_wg(self, ctx: commands.Context, *, working_group: str) -> None: - """Direct Message the bot with the affinity group that you would like to leave. - The bot will remove you from the group.""" - guild = discord.utils.get(self.bot.guilds, name=ACTIVE_GUILD) - category = discord.utils.get(guild.categories, name="Working Groups") - await _add_remove_from_group(self, ctx, working_group, category, False) + if result is True: + msg_content = f":white_check_mark: You have successfully {action} the {v.value} working group channel.\ + \nIf there was an error, please contact an admin." + else: + msg_content = ":x: Sorry, there was an error. Please try again or contact an admin." + + await interaction.reply( + content=msg_content, + hide_user_input=True, + ephemeral=True, # Only visible to the invoker of the command + type=4, # Immediate response with acknowledge + ) class AffinityGroups(commands.Cog): @@ -35,56 +41,45 @@ class AffinityGroups(commands.Cog): def __init__(self, bot: commands.Bot): self.bot = bot - @commands.command() - async def join_ag(self, ctx: commands.Context, *, affinity_group: str) -> None: - """Direct Message the bot with the affinity group they want to join. The bot will add you to the correct group. - - The current affinity groups can be found on the oSTEM.org website - """ - guild = discord.utils.get(self.bot.guilds, name=ACTIVE_GUILD) - category = discord.utils.get(guild.categories, name="affinity groups") - await _add_remove_from_group(self, ctx, affinity_group, category, True) - - @commands.command() - async def leave_ag(self, ctx: commands.Context, *, affinity_group: str) -> None: - """Direct Message the bot with the affinity group that you would like to leave. - The bot will remove you from the group.""" + @slash_commands.command(name="affinity-group") + async def affinity_group(self, interaction): + for k, v in interaction.data.options.items(): + if v.name == "join": + add = True + action = "joined" + else: + add = False + action = "left" + + result = await _add_remove_from_group(interaction.guild, interaction.author, v.value, "affinity groups", add) - guild = discord.utils.get(self.bot.guilds, name=ACTIVE_GUILD) - category = discord.utils.get(guild.categories, name="affinity groups") - await _add_remove_from_group(self, ctx, affinity_group, category, False) + if result is True: + msg_content = f":white_check_mark: You have successfully {action} the {v.value} affinity group channel.\ + \nIf there was an error, please contact an admin." + else: + msg_content = ":x: Sorry, there was an error. Please try again or contact an admin." + + await interaction.reply( + content=msg_content, + hide_user_input=True, + ephemeral=True, # Only visible to the invoker of the command + type=4, # Immediate response with acknowledge + ) -async def _add_remove_from_group(bot, ctx: commands.Context, channel_name: str, category, add: bool = True) -> bool: +async def _add_remove_from_group(guild, user, channel_name: str, category_name: str, add: bool) -> bool: """Helper function to add or remove a user from a specific channel. If add is false, it will remove the permissions.""" - guild = discord.utils.get(bot.guilds, name=ACTIVE_GUILD) - - active_group = '' - if category.name == "affinity groups": - active_group = AFFINITY_GROUPS - elif category.name == "Working Groups": - active_group = WORKING_GROUPS - - msg_content = ":x: Sorry, there was an error. Please try again or contact an admin." - - for key, value in active_group.items(): - if channel_name.lower() in value: - channel = discord.utils.get(guild.channels, category_id=category.id, name=key) - await channel.set_permissions(ctx.author, read_messages=add, send_messages=add, add_reactions=add, - read_message_history=add, external_emojis=add, attach_files=add, - embed_links=add) - if add is True: - result = "added" - else: - result = "removed" - msg_content = f":white_check_mark: You have been successfully {result} from the {key} affinity group channel.\ - \nIf there was an error, please contact an admin." - await ctx.author.send(msg_content) - if ctx.channel.type is discord.ChannelType.text: - # If the message was in a public channel, we will delete the message to maintain privacy - await ctx.message.delete() + category = discord.utils.get(guild.categories, name=category_name) + channel = discord.utils.get(guild.channels, category_id=category.id, name=channel_name) + if add is True: + await channel.set_permissions(user, read_messages=add, send_messages=add, add_reactions=add, + read_message_history=add, external_emojis=add, attach_files=add, embed_links=add) + else: + # Resets the permissions for the user and removes the channel-specific override + await channel.set_permissions(user, overwrite=None) + return True def setup(bot: commands.Bot) -> None: diff --git a/bot/register_command.py b/bot/register_command.py new file mode 100644 index 0000000..38a2e30 --- /dev/null +++ b/bot/register_command.py @@ -0,0 +1,99 @@ +import os + +import discord +from dislash import SlashClient, Option, Type, SlashCommand, OptionChoice +from discord.ext import commands +from dislash.slash_commands import slash_client + +from constants import COMMAND_PREFIX, GUILD_ID + + +class Lovelace(commands.Bot): + """ + This is the base bot instance. + """ + + def __init__(self, **kwargs): + super().__init__(**kwargs) + self.load_extension("exts.affinity_working_groups") + + async def on_ready(self, *args, **kwargs): + print(f'{bot.user} has connected to Discord') + + +if __name__ == "__main__": + TOKEN = os.getenv('TOKEN') + + # Intents + intents = discord.Intents.default() + intents.members = True + + + bot = Lovelace( + command_prefix=COMMAND_PREFIX, + intents=intents, + allowed_mentions=discord.AllowedMentions(everyone=False) + ) + + slash = SlashClient(bot) + + + @slash.event + async def on_ready(): + sc = SlashCommand(name="working-group", + description="Join or leave a working group", + options=[ + Option(name="join", description="Join a working group", type=Type.STRING, + choices=[ + OptionChoice(name="Beyond the Binary", value="beyondthebinary"), + OptionChoice(name="Black & Queer", value="black_queer"), + OptionChoice(name="Queer Enabled", value="queer-enabled"), + ] + ), + Option(name="leave", description="Leave a working group", type=Type.STRING, + choices=[ + OptionChoice(name="Beyond the Binary", value="beyondthebinary"), + OptionChoice(name="Black & Queer", value="black_queer"), + OptionChoice(name="Queer Enabled", value="queer-enabled"), + ] + ) + ] + ) + + sc1 = SlashCommand(name="affinity-group", + description="Join or leave an affinity group", + options=[ + Option(name="join", description="Join an affinity group", type=Type.STRING, + choices=[ + OptionChoice(name="AAPI", value="aapi"), + OptionChoice(name="Ace/Aro", value="acearo"), + OptionChoice(name="(Dis)Ability", value="disability"), + OptionChoice(name="InQueery", value="inqueery"), + OptionChoice(name="Middle Sexualities", value="middle-sexualities"), + OptionChoice(name="Race and Ethnicity", value="race-ethnicity"), + OptionChoice(name="Trans and Non-binary", value="transnon-binary"), + OptionChoice(name="Women", value="women") + + ] + ), + Option(name="leave", description="Leave an affinity group", type=Type.STRING, + choices=[ + OptionChoice(name="AAPI", value="aapi"), + OptionChoice(name="Ace/Aro", value="acearo"), + OptionChoice(name="(Dis)Ability", value="disability"), + OptionChoice(name="InQueery", value="inqueery"), + OptionChoice(name="Middle Sexualities", value="middle-sexualities"), + OptionChoice(name="Race and Ethnicity", value="race-ethnicity"), + OptionChoice(name="Trans and Non-binary", value="transnon-binary"), + OptionChoice(name="Women", value="women") + + ] + ) + ] + ) + + await slash.register_guild_slash_command(GUILD_ID, sc) + await slash.register_guild_slash_command(GUILD_ID, sc1) + + + bot.run(TOKEN) diff --git a/requirements.txt b/requirements.txt index 062c9a8..b2b3d41 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ -discord -python-dotenv +discord.py +dislash.py \ No newline at end of file From aefb4f4e63d49f4ffe590e68efb292a0d9091641 Mon Sep 17 00:00:00 2001 From: Janine vN Date: Wed, 16 Jun 2021 17:27:26 -0400 Subject: [PATCH 7/7] Remove extraneous file and directory With the bot simplication, this removes files that are no longer used. --- bot/utils/role_checks.py | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 bot/utils/role_checks.py diff --git a/bot/utils/role_checks.py b/bot/utils/role_checks.py deleted file mode 100644 index 60309d5..0000000 --- a/bot/utils/role_checks.py +++ /dev/null @@ -1,11 +0,0 @@ -from discord.ext import commands - - -async def _has_role_check(ctx: commands.Context, guild, *role_names: str) -> bool: - """Checks if the user has a specific role within the server""" - member = guild.get_member(int(ctx.author.id)) - - for role in member.roles: - if role.name in role_names: - return True - return False