diff --git a/bot.py b/bot.py index ea3c9de..b62cf3b 100644 --- a/bot.py +++ b/bot.py @@ -2,6 +2,8 @@ import discord import traceback +import logging +import datetime from discord.ext import commands from cogs.utils import config @@ -17,7 +19,13 @@ extensions = ['cogs.interaction', 'cogs.tags'] bot = commands.Bot(command_prefix=config.commandPrefix, description=config.botDescription, pm_help=None) +discord_logger = logging.getLogger('discord') +discord_logger.setLevel(logging.WARNING) +log = logging.getLogger() +log.setLevel(logging.INFO) +handler = logging.FileHandler(filename='bonfire.log', encoding='utf-8', mode='a') +log.addHandler(handler) # Bot event overrides @bot.event @@ -29,6 +37,8 @@ async def on_ready(): destination = discord.utils.find(lambda m: m.id == channel_id, bot.get_all_channels()) await bot.send_message(destination, "I have just finished restarting!") config.saveContent('restart_server', 0) + if not hasattr(bot, 'uptime'): + bot.uptime = datetime.datetime.utcnow() @bot.event diff --git a/cogs/core.py b/cogs/core.py index 9bc7236..4ab0cbc 100644 --- a/cogs/core.py +++ b/cogs/core.py @@ -16,12 +16,22 @@ class Core: def __init__(self, bot): self.bot = bot - @commands.command() - async def test(self): - await self.bot.say((await self.bot.application_info()).id) + + def get_bot_uptime(self): + now = datetime.datetime.utcnow() + delta = now - self.bot.uptime + hours, remainder = divmod(int(delta.total_seconds()), 3600) + minutes, seconds = divmod(remainder, 60) + days, hours = divmod(hours, 24) + if days: + fmt = '{d} days, {h} hours, {m} minutes, and {s} seconds' + else: + fmt = '{h} hours, {m} minutes, and {s} seconds' + + return fmt.format(d=days, h=hours, m=minutes, s=seconds) @commands.command() - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def calendar(self, month: str=None, year: int=None): """Provides a printout of the current month's calendar Provide month and year to print the calendar of that year and month""" @@ -50,9 +60,15 @@ class Core: year = datetime.datetime.today().year cal = calendar.TextCalendar().formatmonth(year, month) await self.bot.say("```{}```".format(cal)) + + @commands.command() + @checks.customPermsOrRole(send_messages=True) + async def uptime(self): + """Provides a printout of the current bot's uptime""" + await self.bot.say("Uptime: ```{}```".format(self.get_bot_uptime())) @commands.command() - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def addbot(self): """Provides a link that you can use to add me to a server""" perms = discord.Permissions.none() @@ -69,7 +85,7 @@ class Core: .format(discord.utils.oauth_url('183748889814237186', perms))) @commands.command(pass_context=True) - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def doggo(self, ctx): """Use this to print a random doggo image. Doggo is love, doggo is life.""" @@ -79,7 +95,7 @@ class Core: await self.bot.upload(f) @commands.command() - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def joke(self): """Prints a random riddle""" fortuneCommand = "/usr/bin/fortune riddles" @@ -88,7 +104,7 @@ class Core: @commands.command(pass_context=True) - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def roll(self, ctx, notation: str="d6"): """Rolls a die based on the notation given Format should be #d#""" diff --git a/cogs/interaction.py b/cogs/interaction.py index 685a32f..61420ee 100644 --- a/cogs/interaction.py +++ b/cogs/interaction.py @@ -18,10 +18,10 @@ def userBattling(ctx): battling = config.getContent('battling') if battling is None: return False - if ctx.message.author.id in battling or ctx.message.author.id in battling.values(): + if ctx.message.author.id in battling.values() or ctx.message.author.id in battling.keys(): return True if str(ctx.command) == 'battle': - return ctx.message.mentions[0].id in battling.values() + return ctx.message.mentions[0].id in battling.values() or ctx.message.mentions[0].id in battling.keys() return False @@ -75,7 +75,8 @@ class Interaction: self.bot = bot @commands.group(pass_context=True, no_pm=True,invoke_without_command=True) - @checks.customPermsOrRole("send_messages") + @commands.cooldown(1,180,BucketType.user) + @checks.customPermsOrRole(send_messages=True) async def battle(self, ctx, player2: discord.Member): """Challenges the mentioned user to a battle""" if len(ctx.message.mentions) == 0: @@ -105,7 +106,7 @@ class Interaction: @commands.command(pass_context=True, no_pm=True) - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def accept(self, ctx): """Accepts the battle challenge""" if not userBattling(ctx): @@ -134,7 +135,7 @@ class Interaction: battlingOff(ctx.message.author.id) @commands.command(pass_context=True, no_pm=True) - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def decline(self, ctx): """Declines the battle challenge""" if not userBattling(ctx): @@ -156,7 +157,7 @@ class Interaction: @commands.command(pass_context=True, no_pm=True) @commands.cooldown(1,180,BucketType.user) - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def boop(self, ctx, boopee: discord.Member): """Boops the mentioned person""" booper = ctx.message.author diff --git a/cogs/links.py b/cogs/links.py index 027e951..a0f8886 100644 --- a/cogs/links.py +++ b/cogs/links.py @@ -13,7 +13,7 @@ class Links: self.bot = bot @commands.command() - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def urban(self, *msg: str): """Pulls the top urbandictionary.com definition for a term""" url = "http://api.urbandictionary.com/v0/define?term={}".format('+'.join(msg)) @@ -31,7 +31,7 @@ class Links: await self.bot.say('```Error: Definition is too long for me to send```') @commands.command(pass_context=True) - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def derpi(self, ctx, *search: str): """Provides a random image from the first page of derpibooru.org for the following term""" if len(search) > 0: @@ -64,7 +64,7 @@ class Links: @commands.command(pass_context=True) - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def e621(self, ctx, *, tags: str): """Searches for a random image from e621.net Format for the search terms need to be 'search term 1, search term 2, etc.' diff --git a/cogs/mod.py b/cogs/mod.py index bfb1841..d1d9533 100644 --- a/cogs/mod.py +++ b/cogs/mod.py @@ -20,7 +20,7 @@ class Mod: await self.bot.say('Invalid subcommand passed: {0.subcommand_passed}'.format(ctx)) @nsfw.command(name="add", pass_context=True, no_pm=True) - @checks.customPermsOrRole("kick_members") + @checks.customPermsOrRole(kick_members=True) async def nsfw_add(self, ctx): """Registers this channel as a 'nsfw' channel""" nsfw_channels = config.getContent('nsfw_channels') @@ -32,7 +32,7 @@ class Mod: await self.bot.say("This channel has just been registered as 'nsfw'! Have fun you naughties ;)") @nsfw.command(name="remove", aliases=["delete"], pass_context=True, no_pm=True) - @checks.customPermsOrRole("kick_members") + @checks.customPermsOrRole(kick_members=True) async def nsfw_remove(self, ctx): """Removes this channel as a 'nsfw' channel""" nsfw_channels = config.getContent('nsfw_channels') @@ -44,28 +44,27 @@ class Mod: await self.bot.say("This channel has just been unregistered as a nsfw channel") @commands.command(pass_context=True, no_pm=True) - @checks.customPermsOrRole("manage_server") + @checks.customPermsOrRole(manage_server=True) async def leave(self, ctx): """Forces the bot to leave the server""" await self.bot.say('Why must I leave? Hopefully I can come back :c') await self.bot.leave_server(ctx.message.server) @commands.command(pass_context=True, no_pm=True) - @checks.customPermsOrRole("kick_members") + @checks.customPermsOrRole(kick_members=True) async def say(self, ctx, *, msg: str): """Tells the bot to repeat what you say""" await self.bot.say(msg) await self.bot.delete_message(ctx.message) @commands.group(pass_context=True, invoke_without_command=True, no_pm=True) - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def perms(self, ctx, *, command: str): """This command can be used to print the current allowed permissions on a specific command This supports groups as well as subcommands; pass no argument to print a list of available permissions""" if command is None or len(command) == 0: await self.bot.say("Valid permissions are: ```{}```".format("\n".join("{}".format(i) for i in valid_perms))) return - command = " ".join(command) custom_perms = config.getContent('custom_permissions') or {} server_perms = custom_perms.get(ctx.message.server.id) @@ -73,12 +72,14 @@ class Mod: await self.bot.say("There are no custom permissions setup on this server yet!") return - command_perms = server_perms.get(command) - if command_perms is None: + perms_value = server_perms.get(command) + if perms_value is None: await self.bot.say("That command has no custom permissions setup on it!") else: + permissions = discord.Permissions(perms_value) + needed_perm = [perm[0] for perm in permissions._perm_iterator() if perm[1]][0] await self.bot.say("You need to have the permission `{}` " - "to use the command `{}` in this server".format(command_perms, command)) + "to use the command `{}` in this server".format(needed_perm, command)) @perms.command(name="add", aliases=["setup,create"], pass_context=True, no_pm=True) @commands.has_permissions(manage_server=True) @@ -88,52 +89,55 @@ class Mod: If you want to open the command to everyone, provide 'none' as the permission""" command = " ".join(msg[0:len(msg) - 1]) permissions = msg[len(msg) - 1] + + #If a user can run the command, they have to have send_messages permissions; so use this as the base if permissions.lower() == "none": permissions = "send_messages" - msg = msg[0:len(msg) - 1] - count = 0 - cmd = self.bot.commands.get(msg[count]) - while isinstance(cmd, commands.Group): - count += 1 + + #Convert the string to an int value of the permissions obj, based on the required permission + perm_obj = discord.Permissions.none() + setattr(perm_obj,permissions,True) + perm_value = perm_obj.value + + cmd = None + for part in msg[0:len(msg) - 1]: try: - cmd = cmd.commands.get(msg[count]) - except: + if cmd is None: + cmd = self.bot.commands.get(part) + else: + cmd = cmd.commands.get(part) + except AttributeError: break + + if cmd is None: + await self.bot.say("That command does not exist! You can't have custom permissions on a non-existant command....") + return for check in cmd.checks: if "isOwner" == check.__name__ or re.search("has_permissions", str(check)) is not None: await self.bot.say("This command cannot have custom permissions setup!") return - if getattr(discord.Permissions, permissions, None) is None and not permissions.lower() == "none": + if getattr(discord.Permissions, permissions, None) is None: await self.bot.say("{} does not appear to be a valid permission! Valid permissions are: ```{}```" .format(permissions, "\n".join(valid_perms))) return - custom_perms = config.getContent('custom_permissions') - if custom_perms is None: - custom_perms = {} - server_perms = custom_perms.get(ctx.message.server.id) - if server_perms is None: - custom_perms[ctx.message.server.id] = {command: permissions} - else: - server_perms[command] = permissions - custom_perms[ctx.message.server.id] = server_perms - if config.saveContent('custom_permissions', custom_perms): - await self.bot.say("I have just added your custom permissions; " - "you now need to have `{}` permissions to use the command `{}`".format(permissions, command)) - else: - await self.bot.say("I was unable to save this data") + custom_perms = config.getContent('custom_permissions') or {} + server_perms = custom_perms.get(ctx.message.server.id) or {} + server_perms[command] = perm_value + custom_perms[ctx.message.server.id] = server_perms + + config.saveContent('custom_permissions', custom_perms) + await self.bot.say("I have just added your custom permissions; " + "you now need to have `{}` permissions to use the command `{}`".format(permissions, command)) @perms.command(name="remove", aliases=["delete"], pass_context=True, no_pm=True) @commands.has_permissions(manage_server=True) async def remove_perms(self, ctx, *command: str): """Removes the custom permissions setup on the command specified""" cmd = " ".join(command) - custom_perms = config.getContent('custom_permissions') - if custom_perms is None: - await self.bot.say("You do not have custom permissions setup on this server yet!") - return + custom_perms = config.getContent('custom_permissions') or {} server_perms = custom_perms.get(ctx.message.server.id) if server_perms is None: await self.bot.say("There are no custom permissions setup on this server yet!") @@ -143,11 +147,64 @@ class Mod: await self.bot.say("You do not have custom permissions setup on this command yet!") return del custom_perms[ctx.message.server.id][cmd] - if config.saveContent('custom_permissions', custom_perms): - await self.bot.say("I have just removed the custom permissions for {}!".format(cmd)) - else: - await self.bot.say("I was unable to save this data") - - + config.saveContent('custom_permissions', custom_perms) + await self.bot.say("I have just removed the custom permissions for {}!".format(cmd)) + + @commands.group(aliases=['rule'], pass_context=True, no_pm=True, invoke_without_command=True) + @checks.customPermsOrRole(send_messages=True) + async def rules(self, ctx): + """This command can be used to view the current rules on the server""" + rules = config.getContent('rules') or {} + server_rules = rules.get(ctx.message.server.id) + if server_rules is None or len(server_rules) == 0: + await self.bot.say("This server currently has no rules on it! I see you like to live dangerously...") + return + fmt = "\n".join("{}) {}".format(num+1,rule) for num,rule in enumerate(server_rules)) + await self.bot.say('```{}```'.format(fmt)) + + @rules.command(name='add', aliases=['create'], pass_context=True, no_pm=True) + @checks.customPermsOrRole(manage_server=True) + async def rules_add(self, ctx, *, rule: str): + """Adds a rule to this server's rules""" + rules = config.getContent('rules') or {} + server_rules = rules.get(ctx.message.server.id) or [] + server_rules.append(rule) + rules[ctx.message.server.id] = server_rules + config.saveContent('rules',rules) + await self.bot.say("I have just saved your new rule, use the rules command to view this server's current rules") + + @rules.command(name='remove', aliases=['delete'], pass_context=True, no_pm=True) + @checks.customPermsOrRole(manage_server=True) + async def rules_delete(self, ctx, rule: int=None): + """Removes one of the rules from the list of this server's rules + Provide a number to delete that rule; if no number is provided + I'll print your current rules and ask for a number""" + rules = config.getContent('rules') or {} + server_rules = rules.get(ctx.message.server.id) + if server_rules is None or len(server_rules) == 0: + await self.bot.say("This server currently has no rules on it! Can't remove something that doesn't exist bro") + return + list_rules = "\n".join("{}) {}".format(num+1,rule) for num,rule in enumerate(server_rules)) + + if rule is None: + await self.bot.say("Your rules are:\n```{}```Please provide the rule number you would like to remove (just the number)".format(list_rules)) + + msg = await self.bot.wait_for_message(timeout=60.0, author=ctx.message.author, channel = ctx.message.channel, check = lambda m: m.content.isdigit()) + if msg is None: + await self.bot.say("You took too long...it's just a number, seriously? Try typing a bit quicker") + return + del server_rules[int(msg.content)-1] + rules[ctx.message.server.id] = server_rules + config.saveContent('rules',rules) + + try: + del server_rules[rule-1] + rules[ctx.message.server.id] = server_rules + config.saveContent('rules',rules) + await self.bot.say("I have just removed that rule from your list of rules!") + except IndexError: + await self.bot.say("That is not a valid rule number, try running the command again. Your current rules are:\n```{}```".format(list_rules)) + + def setup(bot): bot.add_cog(Mod(bot)) diff --git a/cogs/overwatch.py b/cogs/overwatch.py index fd777ee..80aec4c 100644 --- a/cogs/overwatch.py +++ b/cogs/overwatch.py @@ -28,7 +28,7 @@ class Overwatch: pass @ow.command(name="stats", pass_context=True, no_pm=True) - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def ow_stats(self, ctx, user: discord.Member = None, hero: str = ""): """Prints out a basic overview of a member's stats Provide a hero after the member to get stats for that specific hero""" @@ -74,7 +74,7 @@ class Overwatch: .format(user.name, hero.title(), fmt.title().replace("_", " "))) @ow.command(pass_context=True, name="add", no_pm=True) - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def add(self, ctx, bt: str): """Saves your battletag for looking up information""" bt = bt.replace("#", "-") @@ -96,7 +96,7 @@ class Overwatch: await self.bot.say("I was unable to save this data") @ow.command(pass_context=True, name="delete", aliases=['remove'], no_pm=True) - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def delete(self, ctx): """Removes your battletag from the records""" result = config.getContent('overwatch') diff --git a/cogs/playlist.py b/cogs/playlist.py index 1143b36..564dc75 100644 --- a/cogs/playlist.py +++ b/cogs/playlist.py @@ -27,7 +27,7 @@ class VoiceState: self.voice = None self.bot = bot self.play_next_song = asyncio.Event() - self.songs = asyncio.Queue() + self.songs = asyncio.Queue(maxsize=10) self.skip_votes = set() # a set of user_ids that voted self.audio_player = self.bot.loop.create_task(self.audio_player_task()) self.opts = { @@ -72,7 +72,6 @@ class Music: def __init__(self, bot): self.bot = bot self.voice_states = {} - self.max_songs = 10 def get_voice_state(self, server): state = self.voice_states.get(server.id) @@ -97,7 +96,7 @@ class Music: pass @commands.command(no_pm=True) - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def join(self, *, channel: discord.Channel): """Joins a voice channel.""" try: @@ -113,7 +112,7 @@ class Music: await self.bot.say('Ready to play audio in ' + channel.name) @commands.command(pass_context=True, no_pm=True) - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def summon(self, ctx): """Summons the bot to join your voice channel.""" summoned_channel = ctx.message.author.voice_channel @@ -129,7 +128,7 @@ class Music: return True @commands.command(pass_context=True, no_pm=True) - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def play(self, ctx, *, song: str): """Plays a song. If there is a song currently in the queue, then it is @@ -145,7 +144,7 @@ class Music: if not success: return - if len(state.songs) >= self.max_songs: + if state.songs.full(): await self.bot.say("The queue is currently full! You'll need to wait to add a new song") return @@ -156,7 +155,7 @@ class Music: await state.songs.put(entry) @commands.command(pass_context=True, no_pm=True) - @checks.customPermsOrRole("kick_members") + @checks.customPermsOrRole(kick_members=True) async def volume(self, ctx, value: int): """Sets the volume of the currently playing song.""" @@ -167,7 +166,7 @@ class Music: await self.bot.say('Set the volume to {:.0%}'.format(player.volume)) @commands.command(pass_context=True, no_pm=True) - @checks.customPermsOrRole("kick_members") + @checks.customPermsOrRole(kick_members=True) async def pause(self, ctx): """Pauses the currently played song.""" state = self.get_voice_state(ctx.message.server) @@ -176,7 +175,7 @@ class Music: player.pause() @commands.command(pass_context=True, no_pm=True) - @checks.customPermsOrRole("kick_members") + @checks.customPermsOrRole(kick_members=True) async def resume(self, ctx): """Resumes the currently played song.""" state = self.get_voice_state(ctx.message.server) @@ -185,7 +184,7 @@ class Music: player.resume() @commands.command(pass_context=True, no_pm=True) - @checks.customPermsOrRole("kick_members") + @checks.customPermsOrRole(kick_members=True) async def stop(self, ctx): """Stops playing audio and leaves the voice channel. This also clears the queue. @@ -205,14 +204,14 @@ class Music: pass @commands.command(pass_context=True, no_pm=True) - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def queuelength(self, ctx): """Prints the length of the queue""" await self.bot.say("There are a total of {} songs in the queue" .format(str(self.get_voice_state(ctx.message.server).songs.qsize()))) @commands.command(pass_context=True, no_pm=True) - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def skip(self, ctx): """Vote to skip a song. The song requester can automatically skip. 3 skip votes are needed for the song to be skipped. @@ -239,7 +238,7 @@ class Music: await self.bot.say('You have already voted to skip this song.') @commands.command(pass_context=True, no_pm=True) - @checks.customPermsOrRole("kick_members") + @checks.customPermsOrRole(kick_members=True) async def modskip(self, ctx): """Forces a song skip, can only be used by a moderator""" state = self.get_voice_state(ctx.message.server) @@ -251,7 +250,7 @@ class Music: await self.bot.say('Song has just been skipped.') @commands.command(pass_context=True, no_pm=True) - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def playing(self, ctx): """Shows info about the currently played song.""" diff --git a/cogs/stats.py b/cogs/stats.py index 5f73687..1e057f0 100644 --- a/cogs/stats.py +++ b/cogs/stats.py @@ -13,7 +13,7 @@ class Stats: self.bot = bot @commands.command(pass_context=True, no_pm=True) - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def mostboops(self, ctx): """Shows the person you have 'booped' the most, as well as how many times""" boops = config.getContent('boops') @@ -33,7 +33,7 @@ class Stats: ctx.message.author.mention, member.mention, most_boops)) @commands.command(pass_context=True, no_pm=True) - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def listboops(self, ctx): """Lists all the users you have booped and the amount of times""" members = ctx.message.server.members @@ -50,7 +50,7 @@ class Stats: await self.bot.say("You have booped:```{}```".format(output)) @commands.command(pass_context=True, no_pm=True) - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def leaderboard(self, ctx): """Prints a leaderboard of everyone in the server's battling record""" battles = config.getContent('battle_records') @@ -71,7 +71,7 @@ class Stats: @commands.command(pass_context=True) - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def stats(self, ctx, member: discord.Member=None): """Prints the battling stats for you, or the user provided""" member = member or ctx.message.author diff --git a/cogs/tags.py b/cogs/tags.py index 77ae258..7100e06 100644 --- a/cogs/tags.py +++ b/cogs/tags.py @@ -9,7 +9,7 @@ class Tags: self.bot = bot @commands.command(pass_context=True) - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def tags(self, ctx): """Prints all the custom tags that this server currently has""" tags = config.getContent('tags') @@ -17,7 +17,7 @@ class Tags: await self.bot.say('```{}```'.format(fmt)) @commands.group(pass_context=True, invoke_without_command=True, no_pm=True) - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def tag(self, ctx, *, tag: str): """This can be used to call custom tags The format to call a custom tag is !tag """ @@ -29,7 +29,7 @@ class Tags: await self.bot.say("{}".format(result[0]['result'])) @tag.command(name='add', aliases=['create', 'start'], pass_context=True, no_pm=True) - @checks.customPermsOrRole("kick_members") + @checks.customPermsOrRole(kick_members=True) async def add_tag(self, ctx, *, result: str): """Use this to add a new tag that can be used in this server Format to add a tag is !tag add - """ @@ -54,7 +54,7 @@ class Tags: await self.bot.say("I was unable to save this data") @tag.command(name='delete', aliases=['remove', 'stop'], pass_context=True, no_pm=True) - @checks.customPermsOrRole("kick_members") + @checks.customPermsOrRole(kick_members=True) async def del_tag(self, ctx, *, tag: str): """Use this to remove a tag that from use for this server Format to delete a tag is !tag delete """ diff --git a/cogs/twitch.py b/cogs/twitch.py index cdbb662..648329c 100644 --- a/cogs/twitch.py +++ b/cogs/twitch.py @@ -52,7 +52,7 @@ class Twitch: await asyncio.sleep(30) @commands.group(no_pm=True, invoke_without_command=True, pass_context=True) - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def twitch(self, ctx, *, member: discord.Member=None): """Use this command to check the twitch info of a user""" if member is None: @@ -78,7 +78,7 @@ class Twitch: await self.bot.say("```{}```".format(fmt)) @twitch.command(name='add', pass_context=True, no_pm=True) - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def add_twitch_url(self, ctx, url: str): """Saves your user's twitch URL""" try: @@ -107,7 +107,7 @@ class Twitch: await self.bot.say("I have just saved your twitch url {}".format(ctx.message.author.mention)) @twitch.command(name='remove', aliases=['delete'], pass_context=True, no_pm=True) - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def remove_twitch_url(self, ctx): """Removes your twitch URL""" twitch = config.getContent('twitch') @@ -121,13 +121,13 @@ class Twitch: ctx.message.author.mention)) @twitch.group(pass_context=True, no_pm=True, invoke_without_command=True) - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def notify(self, ctx): """This can be used to turn notifications on or off""" pass @notify.command(name='on', aliases=['start,yes'], pass_context=True, no_pm=True) - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def notify_on(self, ctx): """Turns twitch notifications on""" twitch = config.getContent('twitch') @@ -146,7 +146,7 @@ class Twitch: ctx.message.author.mention)) @notify.command(name='off', aliases=['stop,no'], pass_context=True, no_pm=True) - @checks.customPermsOrRole("send_messages") + @checks.customPermsOrRole(send_messages=True) async def notify_off(self, ctx): """Turns twitch notifications off""" twitch = config.getContent('twitch') diff --git a/cogs/utils/checks.py b/cogs/utils/checks.py index 0e50508..445d5b1 100644 --- a/cogs/utils/checks.py +++ b/cogs/utils/checks.py @@ -1,4 +1,5 @@ from discord.ext import commands +import discord from . import config @@ -23,6 +24,25 @@ def customPermsOrRole(perm): return getattr(ctx.message.author.permissions_in(ctx.message.channel), _perm) return commands.check(predicate) + +def customPermsOrRole(**perms): + def predicate(ctx): + if ctx.message.channel.is_private: + return False + + member_perms = ctx.message.author.permissions_in(ctx.message.channel) + default_perms = discord.Permissions.none() + for perm,setting in perms.items(): + setattr(default_perms,perm,setting) + + try: + required_perm = config.getContent('custom_permissions')[ctx.message.server.id][ctx.command.qualified_name] + except KeyError: + required_perm = default_perms + return member_perms >= required_perm + + + return commands.check(predicate) def isPM():