diff options
| -rw-r--r-- | bot/__main__.py | 14 | ||||
| -rw-r--r-- | bot/cogs/bot.py | 21 | ||||
| -rw-r--r-- | bot/cogs/eval.py | 12 | ||||
| -rw-r--r-- | bot/cogs/events.py | 11 | ||||
| -rw-r--r-- | bot/cogs/security.py | 2 | ||||
| -rw-r--r-- | bot/cogs/verification.py | 54 | ||||
| -rw-r--r-- | bot/constants.py | 11 | ||||
| -rw-r--r-- | bot/decorators.py | 27 | ||||
| -rw-r--r-- | requirements.txt | 2 |
9 files changed, 137 insertions, 17 deletions
diff --git a/bot/__main__.py b/bot/__main__.py index 2dc0ccc1f..9f9c82077 100644 --- a/bot/__main__.py +++ b/bot/__main__.py @@ -5,8 +5,14 @@ from discord import Game from discord.ext.commands import AutoShardedBot, when_mentioned_or bot = AutoShardedBot( - command_prefix=when_mentioned_or(">>> ", ">> ", ">>>", ">>"), # Order matters - game=Game(name=">>> help") + command_prefix=when_mentioned_or( + ">>> self.", ">> self.", "> self.", "self.", + ">>> bot.", ">> bot.", "> bot.", "bot.", + ">>> ", ">> ", "> ", + ">>>", ">>", ">" + ), # Order matters (and so do commas) + game=Game(name="Help: bot.help()"), + help_attrs={"aliases": ["help()"]} ) # Internal/debug @@ -14,10 +20,12 @@ bot.load_extension("bot.cogs.logging") bot.load_extension("bot.cogs.security") bot.load_extension("bot.cogs.events") + # Owner-only bot.load_extension("bot.cogs.eval") -# Commands +# Commands, etc bot.load_extension("bot.cogs.bot") +bot.load_extension("bot.cogs.verification") bot.run(os.environ.get("BOT_TOKEN")) diff --git a/bot/cogs/bot.py b/bot/cogs/bot.py index 6ab844725..e8530a8d0 100644 --- a/bot/cogs/bot.py +++ b/bot/cogs/bot.py @@ -1,9 +1,12 @@ # coding=utf-8 from discord import Embed -from discord.ext.commands import AutoShardedBot, Context, group +from discord.ext.commands import AutoShardedBot, Context, command, group from dulwich.repo import Repo +from bot.constants import VERIFIED_ROLE +from bot.decorators import with_role + __author__ = "Gareth Coles" @@ -16,6 +19,7 @@ class Bot: self.bot = bot @group(invoke_without_command=True, name="bot") + @with_role(VERIFIED_ROLE) async def bot_group(self, ctx: Context): """ Bot informational commands @@ -23,14 +27,15 @@ class Bot: await ctx.invoke(self.bot.get_command("help"), "bot") - @bot_group.command(aliases=["about"]) + @bot_group.command(aliases=["about"], hidden=True) + @with_role(VERIFIED_ROLE) async def info(self, ctx: Context): """ - Get information about the current bot + Get information about the bot """ embed = Embed( - description="A utility bot designed just for the Python server! Try `>>> help` for more info.", + description="A utility bot designed just for the Python server! Try `bot.help()` for more info.", url="https://github.com/discord-python/bot" ) @@ -48,6 +53,14 @@ class Bot: await ctx.send(embed=embed) + @command(name="bot.info()", aliases=["bot.info", "bot.about", "bot.about()"]) + def info_wrapper(self, ctx: Context): + """ + Get information about the bot + """ + + return self.info(ctx) + def setup(bot): bot.add_cog(Bot(bot)) diff --git a/bot/cogs/eval.py b/bot/cogs/eval.py index ceca8ab77..cf4b69eca 100644 --- a/bot/cogs/eval.py +++ b/bot/cogs/eval.py @@ -2,14 +2,16 @@ from io import StringIO -from discord.ext.commands import AutoShardedBot, Context, command, is_owner +from discord.ext.commands import AutoShardedBot, Context, command +from bot.constants import OWNER_ROLE +from bot.decorators import with_role from bot.interpreter import Interpreter -__author__ = "Gareth Coles" +__author__ = "Careth Goles" -class Eval: +class EvalCog: # Named this way because a flake8 plugin isn't case-sensitive """ Bot owner only: Evaluate Python code """ @@ -19,7 +21,7 @@ class Eval: self.interpreter = Interpreter(bot) @command() - @is_owner() + @with_role(OWNER_ROLE) async def eval(self, ctx: Context, *, string: str): """ Bot owner only: Evaluate Python code @@ -75,5 +77,5 @@ class Eval: def setup(bot): - bot.add_cog(Eval(bot)) + bot.add_cog(EvalCog(bot)) print("Cog loaded: Eval") diff --git a/bot/cogs/events.py b/bot/cogs/events.py index 1c4d52623..a64859d77 100644 --- a/bot/cogs/events.py +++ b/bot/cogs/events.py @@ -18,12 +18,17 @@ class Events: async def on_command_error(self, ctx: Context, e: CommandError): command = ctx.command - parent = command.parent + parent = None - if parent: + if command is not None: + parent = command.parent + + if parent and command: help_command = (self.bot.get_command("help"), parent.name, command.name) - else: + elif command: help_command = (self.bot.get_command("help"), command.name) + else: + help_command = (self.bot.get_command("help"),) if isinstance(e, BadArgument): await ctx.send(f"Bad argument: {e}\n") diff --git a/bot/cogs/security.py b/bot/cogs/security.py index 91029f2cd..6827af690 100644 --- a/bot/cogs/security.py +++ b/bot/cogs/security.py @@ -11,7 +11,7 @@ class Security: def __init__(self, bot: AutoShardedBot): self.bot = bot - self.bot.check(self.check_not_bot) + self.bot.check(self.check_not_bot) # Global commands check - no bots can run any commands at all def check_not_bot(self, ctx: Context): return not ctx.author.bot diff --git a/bot/cogs/verification.py b/bot/cogs/verification.py new file mode 100644 index 000000000..d4fbe5d78 --- /dev/null +++ b/bot/cogs/verification.py @@ -0,0 +1,54 @@ +# coding=utf-8 +from discord import Message, Object +from discord.ext.commands import AutoShardedBot, Context, command + +from bot.constants import VERIFICATION_CHANNEL, VERIFIED_ROLE +from bot.decorators import in_channel, without_role + +__author__ = "Careth Goles" + + +class Verification: + """ + User verification + """ + + def __init__(self, bot: AutoShardedBot): + self.bot = bot + + async def on_message(self, message: Message): + if message.author.bot: + return # They're a bot, ignore + + ctx = await self.bot.get_context(message) # type: Context + + if ctx.command is not None and ctx.command.name == "accept": + return # They didn't use a command, or they used a command that isn't the accept command + + if ctx.channel.id == VERIFICATION_CHANNEL: # We're in the verification channel + for role in ctx.author.roles: + if role.id == VERIFIED_ROLE: + return # They're already verified + + await ctx.send( + f"{ctx.author.mention} Please type `self.accept()` to verify that you accept our rules, " + f"and gain access to the rest of the server.", + delete_after=10 + ) + await ctx.message.delete() + + @command(name="accept", hidden=True, aliases=["verify", "verified", "accepted", "accept()"]) + @without_role(VERIFIED_ROLE) + @in_channel(VERIFICATION_CHANNEL) + async def accept(self, ctx: Context): + """ + Accept our rules and gain access to the rest of the server + """ + + await ctx.author.add_roles(Object(VERIFIED_ROLE), reason="Accepted the rules") + await ctx.message.delete() + + +def setup(bot): + bot.add_cog(Verification(bot)) + print("Cog loaded: Verification") diff --git a/bot/constants.py b/bot/constants.py new file mode 100644 index 000000000..af1830e07 --- /dev/null +++ b/bot/constants.py @@ -0,0 +1,11 @@ +# coding=utf-8 + +__author__ = "Gareth Coles" + + +VERIFICATION_CHANNEL = 352442727016693763 + +ADMIN_ROLE = 267628507062992896 +MODERATOR_ROLE = 267629731250176001 +VERIFIED_ROLE = 352427296948486144 +OWNER_ROLE = 267627879762755584 diff --git a/bot/decorators.py b/bot/decorators.py new file mode 100644 index 000000000..833094210 --- /dev/null +++ b/bot/decorators.py @@ -0,0 +1,27 @@ +# coding=utf-8 +from discord.ext import commands +from discord.ext.commands import Context + +__author__ = "Careth Goles" + + +def with_role(*role_ids: int): + async def predicate(ctx: Context): + for role in ctx.author.roles: + if role.id in role_ids: + return True + return False + return commands.check(predicate) + + +def without_role(*role_ids: int): + async def predicate(ctx: Context): + author_roles = [role.id for role in ctx.author.roles] + return all(role not in author_roles for role in role_ids) + return commands.check(predicate) + + +def in_channel(channel_id): + async def predicate(ctx: Context): + return ctx.channel.id == channel_id + return commands.check(predicate) diff --git a/requirements.txt b/requirements.txt index b1cabf9b0..58eeb7bd5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ -https://github.com/Rapptz/discord.py/archive/rewrite.zip +https://github.com/Rapptz/discord.py/archive/rewrite.zip#egg=discord.py[voice] dulwich
\ No newline at end of file |