2016-07-09 13:27:19 +12:00
|
|
|
from discord.ext import commands
|
2017-02-13 10:39:57 +13:00
|
|
|
|
|
|
|
from . import utils
|
2016-09-29 12:39:34 +13:00
|
|
|
|
2016-07-16 02:58:10 +12:00
|
|
|
import discord
|
2016-07-17 00:27:10 +12:00
|
|
|
import re
|
2016-08-26 17:12:54 +12:00
|
|
|
import asyncio
|
2016-09-29 12:39:34 +13:00
|
|
|
import rethinkdb as r
|
2016-07-16 02:58:10 +12:00
|
|
|
|
2016-08-13 05:37:29 +12:00
|
|
|
valid_perms = [p for p in dir(discord.Permissions) if isinstance(getattr(discord.Permissions, p), property)]
|
2016-07-16 09:39:26 +12:00
|
|
|
|
2016-07-09 13:27:19 +12:00
|
|
|
|
|
|
|
class Mod:
|
2016-07-09 13:59:10 +12:00
|
|
|
"""Commands that can be used by a or an admin, depending on the command"""
|
2016-07-16 09:39:26 +12:00
|
|
|
|
2016-07-09 13:27:19 +12:00
|
|
|
def __init__(self, bot):
|
|
|
|
self.bot = bot
|
2016-08-13 05:37:29 +12:00
|
|
|
|
2017-04-09 15:04:46 +12:00
|
|
|
@commands.command(aliases=['nick'])
|
|
|
|
@commands.guild_only()
|
2017-02-13 10:39:57 +13:00
|
|
|
@utils.custom_perms(kick_members=True)
|
2016-12-15 10:52:11 +13:00
|
|
|
async def nickname(self, ctx, *, name=None):
|
|
|
|
"""Used to set the nickname for Bonfire (provide no nickname and it will reset)
|
|
|
|
|
|
|
|
EXAMPLE: !nick Music Bot
|
2017-03-06 15:45:44 +13:00
|
|
|
RESULT: My nickname is now Music Bot"""
|
2017-03-25 09:37:03 +13:00
|
|
|
try:
|
|
|
|
await ctx.message.guild.me.edit(nick=name)
|
|
|
|
except discord.HTTPException:
|
|
|
|
await ctx.send("Sorry but I can't change my nickname to {}".format(name))
|
|
|
|
else:
|
|
|
|
await ctx.send("\N{OK HAND SIGN}")
|
2016-12-15 10:52:11 +13:00
|
|
|
|
2017-04-09 15:04:46 +12:00
|
|
|
@commands.command()
|
|
|
|
@commands.guild_only()
|
2017-02-13 10:39:57 +13:00
|
|
|
@utils.custom_perms(kick_members=True)
|
2017-03-06 15:45:44 +13:00
|
|
|
async def kick(self, ctx, member: discord.Member):
|
2016-11-29 17:55:55 +13:00
|
|
|
"""Used to kick a member from this server
|
|
|
|
|
|
|
|
EXAMPLE: !kick @Member
|
|
|
|
RESULT: They're kicked from the server?"""
|
2016-10-10 11:19:20 +13:00
|
|
|
try:
|
2017-03-06 15:45:44 +13:00
|
|
|
await member.kick()
|
|
|
|
await ctx.send("\N{OK HAND SIGN}")
|
2016-10-10 11:19:20 +13:00
|
|
|
except discord.Forbidden:
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send("But I can't, muh permissions >:c")
|
2016-10-10 11:19:20 +13:00
|
|
|
|
2017-04-09 15:04:46 +12:00
|
|
|
@commands.command()
|
|
|
|
@commands.guild_only()
|
2017-02-13 10:39:57 +13:00
|
|
|
@utils.custom_perms(ban_members=True)
|
2016-10-10 11:19:20 +13:00
|
|
|
async def unban(self, ctx, member_id: int):
|
|
|
|
"""Used to unban a member from this server
|
|
|
|
Due to the fact that I cannot find a user without being in a server with them
|
2016-11-29 17:55:55 +13:00
|
|
|
only the ID should be provided
|
|
|
|
|
|
|
|
EXAMPLE: !unban 353217589321750912
|
|
|
|
RESULT: That dude be unbanned"""
|
2016-10-10 11:19:20 +13:00
|
|
|
|
|
|
|
# Lets only accept an int for this method, in order to ensure only an ID is provided
|
|
|
|
# Due to that though, we need to ensure a string is passed as the member's ID
|
|
|
|
try:
|
2017-03-08 21:22:26 +13:00
|
|
|
await self.bot.http.unban(member_id, ctx.guild.id)
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send("\N{OK HAND SIGN}")
|
2016-10-10 11:19:20 +13:00
|
|
|
except discord.Forbidden:
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send("But I can't, muh permissions >:c")
|
2016-10-10 11:19:20 +13:00
|
|
|
except discord.HTTPException:
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send("Sorry, I failed to unban that user!")
|
2016-10-10 11:19:20 +13:00
|
|
|
|
2017-04-09 15:04:46 +12:00
|
|
|
@commands.command()
|
|
|
|
@commands.guild_only()
|
2017-02-13 10:39:57 +13:00
|
|
|
@utils.custom_perms(ban_members=True)
|
2016-10-10 10:56:47 +13:00
|
|
|
async def ban(self, ctx, *, member):
|
|
|
|
"""Used to ban a member
|
|
|
|
This can be used to ban someone preemptively as well.
|
2016-11-29 17:55:55 +13:00
|
|
|
Provide the ID of the user and this should ban them without them being in the server
|
|
|
|
|
|
|
|
EXAMPLE: !ban 531251325312
|
|
|
|
RESULT: That dude be banned"""
|
2016-10-10 10:56:47 +13:00
|
|
|
|
|
|
|
# Lets first check if a user ID was provided, as that will be the easiest case to ban
|
|
|
|
if member.isdigit():
|
2017-03-06 15:45:44 +13:00
|
|
|
try:
|
2017-03-08 21:22:26 +13:00
|
|
|
await self.bot.http.ban(member, ctx.guild.id)
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send("\N{OK HAND SIGN}")
|
|
|
|
except discord.Forbidden:
|
|
|
|
await ctx.send("But I can't, muh permissions >:c")
|
|
|
|
except discord.HTTPException:
|
|
|
|
await ctx.send("Sorry, I failed to ban that user!")
|
|
|
|
finally:
|
|
|
|
return
|
2016-10-10 10:56:47 +13:00
|
|
|
else:
|
|
|
|
# If no ID was provided, lets try to convert what was given using the internal coverter
|
2017-03-08 21:18:28 +13:00
|
|
|
converter = commands.converter.MemberConverter()
|
|
|
|
converter.prepare(ctx, member)
|
2016-10-10 10:56:47 +13:00
|
|
|
try:
|
|
|
|
member = converter.convert()
|
|
|
|
except commands.converter.BadArgument:
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send(
|
2016-11-29 21:05:22 +13:00
|
|
|
'{} does not appear to be a valid member. If this member is not in this server, please provide '
|
|
|
|
'their ID'.format(member))
|
2016-10-10 10:56:47 +13:00
|
|
|
return
|
|
|
|
# Now lets try actually banning the member we've been given
|
|
|
|
try:
|
2017-03-06 15:45:44 +13:00
|
|
|
await member.ban()
|
|
|
|
await ctx.send("\N{OK HAND SIGN}")
|
2016-10-10 11:19:20 +13:00
|
|
|
except discord.Forbidden:
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send("But I can't, muh permissions >:c")
|
2016-11-29 21:05:22 +13:00
|
|
|
except discord.HTTPException:
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send("Sorry, I failed to ban that user!")
|
2016-10-10 10:56:47 +13:00
|
|
|
|
2017-04-11 13:26:28 +12:00
|
|
|
@commands.command()
|
|
|
|
@commands.guild_only()
|
|
|
|
@utils.custom_perms(manage_guild=True)
|
|
|
|
async def ignore(self, ctx, member_or_channel):
|
|
|
|
"""This command can be used to have Bonfire ignore certain members/channels
|
|
|
|
|
|
|
|
EXAMPLE: !ignore #general
|
|
|
|
RESULT: Bonfire will ignore commands sent in the general channel"""
|
|
|
|
key = str(ctx.message.guild.id)
|
|
|
|
|
|
|
|
converter = commands.converter.MemberConverter()
|
|
|
|
converter.prepare(ctx, member_or_channel)
|
|
|
|
member = None
|
|
|
|
channel = None
|
|
|
|
try:
|
|
|
|
member = converter.convert()
|
|
|
|
except commands.converter.BadArgument:
|
|
|
|
converter = commands.converter.TextChannelConverter()
|
|
|
|
converter.prepare(ctx, member_or_channel)
|
|
|
|
try:
|
|
|
|
channel = converter.convert()
|
|
|
|
except commands.converter.BadArgument:
|
|
|
|
await ctx.send("{} does not appear to be a member or channel!".format(member_or_channel))
|
|
|
|
return
|
|
|
|
|
|
|
|
settings = await utils.get_content('server_settings', key)
|
|
|
|
ignored = settings.get('ignored', {'members': [], 'channels': []})
|
|
|
|
if member:
|
|
|
|
if str(member.id) in ignored['members']:
|
|
|
|
await ctx.send("I am already ignoring {}!".format(member.display_name))
|
|
|
|
return
|
|
|
|
elif member.guild_permissions >= ctx.message.author.guild_permissions:
|
|
|
|
await ctx.send("You cannot make me ignore someone at equal or higher rank than you!")
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
ignored['members'].append(str(member.id))
|
|
|
|
fmt = "Ignoring {}".format(member.display_name)
|
|
|
|
elif channel:
|
|
|
|
if str(channel.id) in ignored['channels']:
|
|
|
|
await ctx.send("I am already ignoring {}!".format(channel.mention))
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
ignored['channels'].append(str(channel.id))
|
|
|
|
fmt = "Ignoring {}".format(channel.mention)
|
|
|
|
|
|
|
|
update = {'ignored': ignored}
|
|
|
|
await utils.update_content('server_settings', update, key)
|
|
|
|
await ctx.send(fmt)
|
|
|
|
|
2017-04-14 11:30:14 +12:00
|
|
|
|
|
|
|
@commands.command()
|
|
|
|
@commands.guild_only()
|
|
|
|
@utils.custom_perms(manage_guild=True)
|
|
|
|
async def unignore(self, ctx, member_or_channel):
|
|
|
|
"""This command can be used to have Bonfire stop ignoring certain members/channels
|
|
|
|
|
|
|
|
EXAMPLE: !unignore #general
|
|
|
|
RESULT: Bonfire will no longer ignore commands sent in the general channel"""
|
|
|
|
key = str(ctx.message.guild.id)
|
|
|
|
|
|
|
|
converter = commands.converter.MemberConverter()
|
|
|
|
converter.prepare(ctx, member_or_channel)
|
|
|
|
member = None
|
|
|
|
channel = None
|
|
|
|
try:
|
|
|
|
member = converter.convert()
|
|
|
|
except commands.converter.BadArgument:
|
|
|
|
converter = commands.converter.TextChannelConverter()
|
|
|
|
converter.prepare(ctx, member_or_channel)
|
|
|
|
try:
|
|
|
|
channel = converter.convert()
|
|
|
|
except commands.converter.BadArgument:
|
|
|
|
await ctx.send("{} does not appear to be a member or channel!".format(member_or_channel))
|
|
|
|
return
|
|
|
|
|
|
|
|
settings = await utils.get_content('server_settings', key)
|
|
|
|
ignored = settings.get('ignored', {'members': [], 'channels': []})
|
|
|
|
if member:
|
|
|
|
if str(member.id) not in ignored['members']:
|
|
|
|
await ctx.send("I'm not even ignoring {}!".format(member.display_name))
|
|
|
|
return
|
|
|
|
|
|
|
|
ignored['members'].remove(str(member.id))
|
|
|
|
fmt = "I am no longer ignoring {}".format(member.display_name)
|
|
|
|
elif channel:
|
|
|
|
if str(channel.id) not in ignored['channels']:
|
|
|
|
await ctx.send("I'm not even ignoring {}!".format(channel.mention))
|
|
|
|
return
|
|
|
|
|
|
|
|
ignored['channels'].remove(str(channel.id))
|
|
|
|
fmt = "I am no longer ignoring {}".format(channel.mention)
|
|
|
|
|
|
|
|
update = {'ignored': ignored}
|
|
|
|
await utils.update_content('server_settings', update, key)
|
|
|
|
await ctx.send(fmt)
|
|
|
|
|
2017-04-09 15:04:46 +12:00
|
|
|
@commands.command(aliases=['alerts'])
|
|
|
|
@commands.guild_only()
|
2017-02-13 10:39:57 +13:00
|
|
|
@utils.custom_perms(kick_members=True)
|
2017-03-08 17:28:30 +13:00
|
|
|
async def notifications(self, ctx, channel: discord.TextChannel):
|
2016-08-12 07:00:24 +12:00
|
|
|
"""This command is used to set a channel as the server's 'notifications' channel
|
2016-11-29 17:55:55 +13:00
|
|
|
Any notifications (like someone going live on Twitch, or Picarto) will go to that channel
|
|
|
|
|
|
|
|
EXAMPLE: !alerts #alerts
|
|
|
|
RESULT: No more alerts spammed in #general!"""
|
2017-03-08 20:55:22 +13:00
|
|
|
key = str(ctx.message.guild.id)
|
|
|
|
entry = {'server_id': key,
|
|
|
|
'notification_channel': str(channel.id)}
|
2017-03-08 21:26:50 +13:00
|
|
|
if not await utils.update_content('server_settings', entry, key):
|
|
|
|
await utils.add_content('server_settings', entry)
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send("I have just changed this server's 'notifications' channel"
|
2017-03-08 11:35:30 +13:00
|
|
|
"\nAll notifications will now go to `{}`".format(channel))
|
2016-08-13 05:37:29 +12:00
|
|
|
|
2017-04-09 15:04:46 +12:00
|
|
|
@commands.command()
|
|
|
|
@commands.guild_only()
|
2017-02-13 10:39:57 +13:00
|
|
|
@utils.custom_perms(kick_members=True)
|
2016-08-13 05:37:29 +12:00
|
|
|
async def usernotify(self, ctx, on_off: str):
|
2016-08-02 04:10:20 +12:00
|
|
|
"""This command can be used to set whether or not you want user notificaitons to show
|
2016-11-29 17:55:55 +13:00
|
|
|
Provide on, yes, or true to set it on; otherwise it will be turned off
|
|
|
|
|
|
|
|
EXAMPLE: !usernotify on
|
|
|
|
RESULT: Annying join/leave notifications! Yay!"""
|
2016-08-18 08:46:20 +12:00
|
|
|
# Join/Leave notifications can be kept separate from normal alerts
|
|
|
|
# So we base this channel on it's own and not from alerts
|
2016-08-16 15:30:52 +12:00
|
|
|
# When mod logging becomes available, that will be kept to it's own channel if wanted as well
|
2017-03-08 17:28:30 +13:00
|
|
|
on_off = True if re.search("(on|yes|true)", on_off.lower()) else False
|
2017-03-08 20:55:22 +13:00
|
|
|
key = str(ctx.message.guild.id)
|
|
|
|
entry = {'server_id': key,
|
2017-03-08 17:28:30 +13:00
|
|
|
'join_leave': on_off}
|
2017-03-08 21:26:50 +13:00
|
|
|
if not await utils.update_content('server_settings', entry, key):
|
|
|
|
await utils.add_content('server_settings', entry)
|
2017-03-08 17:28:30 +13:00
|
|
|
|
2016-08-12 07:33:19 +12:00
|
|
|
fmt = "notify" if on_off else "not notify"
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send("This server will now {} if someone has joined or left".format(fmt))
|
2016-08-13 05:37:29 +12:00
|
|
|
|
2017-03-06 15:45:44 +13:00
|
|
|
@commands.group()
|
2016-07-10 07:39:32 +12:00
|
|
|
async def nsfw(self, ctx):
|
2016-07-10 07:40:51 +12:00
|
|
|
"""Handles adding or removing a channel as a nsfw channel"""
|
2016-08-16 15:30:52 +12:00
|
|
|
# This command isn't meant to do anything, so just send an error if an invalid subcommand is passed
|
2017-03-06 15:45:44 +13:00
|
|
|
pass
|
2016-07-16 09:39:26 +12:00
|
|
|
|
2017-03-06 15:45:44 +13:00
|
|
|
@nsfw.command(name="add")
|
2017-02-13 10:39:57 +13:00
|
|
|
@utils.custom_perms(kick_members=True)
|
2016-07-10 07:38:48 +12:00
|
|
|
async def nsfw_add(self, ctx):
|
2016-11-29 17:55:55 +13:00
|
|
|
"""Registers this channel as a 'nsfw' channel
|
|
|
|
|
|
|
|
EXAMPLE: !nsfw add
|
|
|
|
RESULT: ;)"""
|
2017-03-23 16:21:34 +13:00
|
|
|
|
2017-03-25 08:13:46 +13:00
|
|
|
if type(ctx.message.channel) is discord.DMChannel:
|
2017-03-23 16:21:34 +13:00
|
|
|
key = 'DMs'
|
|
|
|
else:
|
|
|
|
key = str(ctx.message.guild.id)
|
|
|
|
|
2017-03-08 17:28:30 +13:00
|
|
|
entry = {'server_id': key,
|
2017-03-08 20:55:22 +13:00
|
|
|
'nsfw_channels': [str(ctx.message.channel.id)]}
|
|
|
|
update = {'nsfw_channels': r.row['nsfw_channels'].append(str(ctx.message.channel.id))}
|
2017-03-08 17:28:30 +13:00
|
|
|
|
|
|
|
server_settings = await utils.get_content('server_settings', key)
|
2017-03-08 19:43:40 +13:00
|
|
|
if server_settings and 'nsfw_channels' in server_settings.keys():
|
2017-03-08 17:28:30 +13:00
|
|
|
await utils.update_content('server_settings', update, key)
|
|
|
|
elif server_settings:
|
|
|
|
await utils.update_content('server_settings', entry, key)
|
2016-09-29 12:39:34 +13:00
|
|
|
else:
|
2017-03-08 21:02:01 +13:00
|
|
|
await utils.add_content('server_settings', entry)
|
2017-03-08 17:28:30 +13:00
|
|
|
|
|
|
|
await ctx.send("This channel has just been registered as 'nsfw'! Have fun you naughties ;)")
|
2016-07-16 09:39:26 +12:00
|
|
|
|
2017-03-06 15:45:44 +13:00
|
|
|
@nsfw.command(name="remove", aliases=["delete"])
|
2017-02-13 10:39:57 +13:00
|
|
|
@utils.custom_perms(kick_members=True)
|
2016-07-18 09:10:12 +12:00
|
|
|
async def nsfw_remove(self, ctx):
|
2016-11-29 17:55:55 +13:00
|
|
|
"""Removes this channel as a 'nsfw' channel
|
|
|
|
|
|
|
|
EXAMPLE: !nsfw remove
|
|
|
|
RESULT: ;("""
|
2017-03-08 17:28:30 +13:00
|
|
|
|
2017-03-25 08:14:13 +13:00
|
|
|
if type(ctx.message.channel) is discord.DMChannel:
|
2017-03-23 16:21:34 +13:00
|
|
|
key = 'DMs'
|
|
|
|
else:
|
|
|
|
key = str(ctx.message.guild.id)
|
|
|
|
|
2017-03-08 17:28:30 +13:00
|
|
|
server_settings = await utils.get_content('server_settings', key)
|
2017-03-08 20:55:22 +13:00
|
|
|
channel = str(ctx.message.channel.id)
|
2017-03-08 17:28:30 +13:00
|
|
|
try:
|
2017-03-08 19:43:40 +13:00
|
|
|
channels = server_settings['nsfw_channels']
|
2017-03-08 17:28:30 +13:00
|
|
|
if channel in channels:
|
|
|
|
channels.remove(channel)
|
|
|
|
|
|
|
|
entry = {'nsfw_channels': channels}
|
|
|
|
await utils.update_content('server_settings', entry, key)
|
|
|
|
await ctx.send("This channel has just been unregistered as a nsfw channel")
|
|
|
|
return
|
|
|
|
except (TypeError, IndexError):
|
|
|
|
pass
|
|
|
|
|
|
|
|
await ctx.send("This channel is not registered as a 'nsfw' channel!")
|
2016-07-16 09:39:26 +12:00
|
|
|
|
2017-03-06 15:45:44 +13:00
|
|
|
@commands.command()
|
2017-02-13 10:39:57 +13:00
|
|
|
@utils.custom_perms(kick_members=True)
|
2016-12-22 19:58:53 +13:00
|
|
|
async def say(self, ctx, *, msg: str):
|
2016-11-29 17:55:55 +13:00
|
|
|
"""Tells the bot to repeat what you say
|
|
|
|
|
|
|
|
EXAMPLE: !say I really like orange juice
|
|
|
|
RESULT: I really like orange juice"""
|
2016-08-21 11:54:51 +12:00
|
|
|
fmt = "\u200B{}".format(msg)
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send(fmt)
|
2016-08-22 13:52:27 +12:00
|
|
|
try:
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.message.delete()
|
2016-08-22 13:52:27 +12:00
|
|
|
except:
|
|
|
|
pass
|
2016-07-16 09:39:26 +12:00
|
|
|
|
2017-04-09 15:04:46 +12:00
|
|
|
@commands.group(invoke_without_command=True)
|
|
|
|
@commands.guild_only()
|
2017-02-13 10:39:57 +13:00
|
|
|
@utils.custom_perms(send_messages=True)
|
2016-08-13 05:37:29 +12:00
|
|
|
async def perms(self, ctx, *, command: str = None):
|
2016-07-16 10:59:15 +12:00
|
|
|
"""This command can be used to print the current allowed permissions on a specific command
|
2016-11-29 17:55:55 +13:00
|
|
|
This supports groups as well as subcommands; pass no argument to print a list of available permissions
|
|
|
|
|
2016-11-29 21:05:22 +13:00
|
|
|
EXAMPLE: !perms help RESULT: Hopefully a result saying you just need send_messages permissions; otherwise lol
|
|
|
|
this server's admin doesn't like me """
|
2016-07-31 14:20:38 +12:00
|
|
|
if command is None:
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send(
|
2016-08-13 05:37:29 +12:00
|
|
|
"Valid permissions are: ```\n{}```".format("\n".join("{}".format(i) for i in valid_perms)))
|
2016-07-16 07:16:10 +12:00
|
|
|
return
|
2016-07-18 09:10:12 +12:00
|
|
|
|
2017-03-06 15:45:44 +13:00
|
|
|
cmd = self.bot.get_command(command)
|
2016-08-31 10:33:46 +12:00
|
|
|
|
2016-08-29 07:39:28 +12:00
|
|
|
if cmd is None:
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send("That is not a valid command!")
|
2016-07-16 01:56:13 +12:00
|
|
|
return
|
2016-07-31 12:20:55 +12:00
|
|
|
|
2017-03-08 20:55:22 +13:00
|
|
|
server_settings = await utils.get_content('server_settings', str(ctx.message.guild.id))
|
2017-03-08 17:28:30 +13:00
|
|
|
try:
|
2017-03-08 19:43:40 +13:00
|
|
|
server_perms = server_settings['permissions']
|
2017-03-08 21:26:50 +13:00
|
|
|
except (TypeError, IndexError, KeyError):
|
2017-03-08 17:28:30 +13:00
|
|
|
server_perms = {}
|
|
|
|
|
2016-08-29 07:39:28 +12:00
|
|
|
perms_value = server_perms.get(cmd.qualified_name)
|
2016-07-31 00:55:26 +12:00
|
|
|
if perms_value is None:
|
2016-08-29 07:39:28 +12:00
|
|
|
# If we don't find custom permissions, get the required permission for a command
|
2017-02-13 10:39:57 +13:00
|
|
|
# based on what we set in utils.custom_perms, if custom_perms isn't found, we'll get an IndexError
|
2016-08-29 07:39:28 +12:00
|
|
|
try:
|
2017-02-20 10:12:13 +13:00
|
|
|
custom_perms = [func for func in cmd.checks if "custom_perms" in func.__qualname__][0]
|
2016-08-29 07:40:34 +12:00
|
|
|
except IndexError:
|
2016-08-31 10:33:46 +12:00
|
|
|
# Loop through and check if there is a check called is_owner
|
2016-09-29 12:39:34 +13:00
|
|
|
# If we loop through and don't find one, this means that the only other choice is to be
|
2017-02-13 10:39:57 +13:00
|
|
|
# Able to manage the server (for the utils on perm commands)
|
2017-03-08 19:23:16 +13:00
|
|
|
for func in cmd.checks:
|
2016-08-29 07:39:28 +12:00
|
|
|
if "is_owner" in func.__qualname__:
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send("You need to own the bot to run this command")
|
2016-08-29 07:39:28 +12:00
|
|
|
return
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send(
|
2017-03-08 21:28:57 +13:00
|
|
|
"You are required to have `manage_guild` permissions to run `{}`".format(cmd.qualified_name))
|
2016-08-29 07:39:28 +12:00
|
|
|
return
|
2016-08-31 10:33:46 +12:00
|
|
|
|
2016-09-29 12:39:34 +13:00
|
|
|
# Perms will be an attribute if custom_perms is found no matter what, so no need to check this
|
2016-08-29 07:39:28 +12:00
|
|
|
perms = "\n".join(attribute for attribute, setting in custom_perms.perms.items() if setting)
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send(
|
2016-08-31 10:33:46 +12:00
|
|
|
"You are required to have `{}` permissions to run `{}`".format(perms, cmd.qualified_name))
|
2016-07-18 03:17:47 +12:00
|
|
|
else:
|
2016-08-16 15:30:52 +12:00
|
|
|
# Permissions are saved as bit values, so create an object based on that value
|
|
|
|
# Then check which permission is true, that is our required permission
|
|
|
|
# There's no need to check for errors here, as we ensure a permission is valid when adding it
|
2016-07-31 00:55:26 +12:00
|
|
|
permissions = discord.Permissions(perms_value)
|
2016-07-31 12:20:55 +12:00
|
|
|
needed_perm = [perm[0] for perm in permissions if perm[1]][0]
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send("You need to have the permission `{}` "
|
2017-03-08 11:35:30 +13:00
|
|
|
"to use the command `{}` in this server".format(needed_perm, command))
|
2016-07-16 09:39:26 +12:00
|
|
|
|
2017-04-09 15:04:46 +12:00
|
|
|
@perms.command(name="add", aliases=["setup,create"])
|
|
|
|
@commands.guild_only()
|
2017-03-08 21:28:57 +13:00
|
|
|
@commands.has_permissions(manage_guild=True)
|
2016-07-16 10:18:04 +12:00
|
|
|
async def add_perms(self, ctx, *msg: str):
|
2016-07-16 11:30:46 +12:00
|
|
|
"""Sets up custom permissions on the provided command
|
2016-07-17 00:04:24 +12:00
|
|
|
Format must be 'perms add <command> <permission>'
|
2016-11-29 17:55:55 +13:00
|
|
|
If you want to open the command to everyone, provide 'none' as the permission
|
|
|
|
|
|
|
|
EXAMPLE: !perms add skip ban_members
|
|
|
|
RESULT: No more random people voting to skip a song"""
|
2016-08-18 08:46:20 +12:00
|
|
|
|
2016-08-16 15:30:52 +12:00
|
|
|
# Since subcommands exist, base the last word in the list as the permission, and the rest of it as the command
|
2016-07-18 09:10:12 +12:00
|
|
|
command = " ".join(msg[0:len(msg) - 1])
|
2017-03-21 10:18:29 +13:00
|
|
|
if command == "":
|
|
|
|
await ctx.send("Please provide the permissions you want to setup, the format for this must be in:\n"
|
|
|
|
"`perms add <command> <permission>`")
|
|
|
|
return
|
2016-10-02 09:29:37 +13:00
|
|
|
try:
|
|
|
|
permissions = msg[len(msg) - 1]
|
|
|
|
except IndexError:
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send("Please provide the permissions you want to setup, the format for this must be in:\n"
|
2017-03-08 11:35:30 +13:00
|
|
|
"`perms add <command> <permission>`")
|
2016-10-03 07:08:20 +13:00
|
|
|
return
|
2016-07-31 12:20:55 +12:00
|
|
|
|
2017-03-08 17:28:30 +13:00
|
|
|
cmd = self.bot.get_command(command)
|
|
|
|
|
|
|
|
if cmd is None:
|
|
|
|
await ctx.send(
|
|
|
|
"That command does not exist! You can't have custom permissions on a non-existant command....")
|
|
|
|
return
|
|
|
|
|
2016-08-16 15:30:52 +12:00
|
|
|
# If a user can run a command, they have to have send_messages permissions; so use this as the base
|
2016-07-18 08:24:13 +12:00
|
|
|
if permissions.lower() == "none":
|
2016-07-18 08:56:29 +12:00
|
|
|
permissions = "send_messages"
|
2016-07-31 12:20:55 +12:00
|
|
|
|
2016-09-29 12:39:34 +13:00
|
|
|
# Convert the string to an int value of the permissions object, based on the required permission
|
|
|
|
# If we hit an attribute error, that means the permission given was not correct
|
|
|
|
perm_obj = discord.Permissions.none()
|
|
|
|
try:
|
|
|
|
setattr(perm_obj, permissions, True)
|
|
|
|
except AttributeError:
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send("{} does not appear to be a valid permission! Valid permissions are: ```\n{}```"
|
2017-03-08 11:35:30 +13:00
|
|
|
.format(permissions, "\n".join(valid_perms)))
|
2016-09-18 13:30:20 +12:00
|
|
|
return
|
2016-07-30 23:58:01 +12:00
|
|
|
perm_value = perm_obj.value
|
2016-08-18 08:46:20 +12:00
|
|
|
|
2016-08-16 15:30:52 +12:00
|
|
|
# Two cases I use should never have custom permissions setup on them, is_owner for obvious reasons
|
2016-08-18 08:46:20 +12:00
|
|
|
# The other case is if I'm using the default has_permissions case
|
|
|
|
# Which means I do not want to check custom permissions at all
|
2016-08-16 15:30:52 +12:00
|
|
|
# Currently the second case is only on adding and removing permissions, to avoid abuse on these
|
2017-02-13 21:06:56 +13:00
|
|
|
for check in cmd.checks:
|
2017-03-08 21:33:18 +13:00
|
|
|
if "is_owner" == check.__name__ or "has_permissions" in str(check):
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send("This command cannot have custom permissions setup!")
|
2016-07-16 07:16:10 +12:00
|
|
|
return
|
2016-07-16 09:39:26 +12:00
|
|
|
|
2017-03-08 20:55:22 +13:00
|
|
|
key = str(ctx.message.guild.id)
|
|
|
|
entry = {'server_id': key,
|
2017-03-08 17:28:30 +13:00
|
|
|
'permissions': {cmd.qualified_name: perm_value}}
|
2016-09-29 12:39:34 +13:00
|
|
|
|
2017-03-08 17:28:30 +13:00
|
|
|
if not await utils.update_content('server_settings', entry, key):
|
|
|
|
await utils.add_content('server_settings', entry)
|
2016-07-31 12:20:55 +12:00
|
|
|
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send("I have just added your custom permissions; "
|
2017-03-08 11:35:30 +13:00
|
|
|
"you now need to have `{}` permissions to use the command `{}`".format(permissions, command))
|
2016-07-18 09:10:12 +12:00
|
|
|
|
2017-04-09 15:04:46 +12:00
|
|
|
@perms.command(name="remove", aliases=["delete"])
|
|
|
|
@commands.guild_only()
|
2017-03-08 21:28:57 +13:00
|
|
|
@commands.has_permissions(manage_guild=True)
|
2016-09-29 15:31:53 +13:00
|
|
|
async def remove_perms(self, ctx, *, command: str):
|
2016-11-29 17:55:55 +13:00
|
|
|
"""Removes the custom permissions setup on the command specified
|
|
|
|
|
|
|
|
EXAMPLE: !perms remove play
|
|
|
|
RESULT: Freedom!"""
|
2016-08-18 08:46:20 +12:00
|
|
|
|
2017-03-06 15:45:44 +13:00
|
|
|
cmd = self.bot.get_command(command)
|
2016-08-16 15:30:52 +12:00
|
|
|
|
|
|
|
if cmd is None:
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send(
|
2016-08-16 15:30:52 +12:00
|
|
|
"That command does not exist! You can't have custom permissions on a non-existant command....")
|
|
|
|
return
|
2016-08-18 08:46:20 +12:00
|
|
|
|
2017-03-08 17:28:30 +13:00
|
|
|
update = {'permissions': {cmd.qualified_name: None}}
|
2017-03-08 21:44:27 +13:00
|
|
|
await utils.update_content('server_settings', update, str(ctx.message.guild.id))
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send("I have just removed the custom permissions for {}!".format(cmd))
|
2016-08-13 05:37:29 +12:00
|
|
|
|
2017-04-09 15:04:46 +12:00
|
|
|
@commands.command()
|
|
|
|
@commands.guild_only()
|
2017-03-06 15:45:44 +13:00
|
|
|
@utils.custom_perms(manage_guild=True)
|
2016-09-01 07:10:33 +12:00
|
|
|
async def prefix(self, ctx, *, prefix: str):
|
2016-11-29 17:55:55 +13:00
|
|
|
"""This command can be used to set a custom prefix per server
|
|
|
|
|
|
|
|
EXAMPLE: !prefix new_prefix
|
|
|
|
RESULT: You probably screwing it up and not realizing you now need to do new_prefixprefix"""
|
2017-03-08 20:55:22 +13:00
|
|
|
key = str(ctx.message.guild.id)
|
2017-04-07 09:41:31 +12:00
|
|
|
if len(prefix.strip()) > 20:
|
|
|
|
await ctx.send("Please keep prefixes under 20 characters")
|
|
|
|
return
|
2016-10-13 10:49:52 +13:00
|
|
|
if prefix.lower().strip() == "none":
|
2016-09-29 12:39:34 +13:00
|
|
|
prefix = None
|
|
|
|
|
2017-03-08 20:55:22 +13:00
|
|
|
entry = {'server_id': key,
|
2016-09-29 12:39:34 +13:00
|
|
|
'prefix': prefix}
|
|
|
|
|
2017-03-08 17:28:30 +13:00
|
|
|
if not await utils.update_content('server_settings', entry, key):
|
|
|
|
await utils.add_content('prefixes', entry)
|
2016-10-13 10:52:36 +13:00
|
|
|
|
|
|
|
if prefix is None:
|
|
|
|
fmt = "I have just cleared your custom prefix, the default prefix will have to be used now"
|
|
|
|
else:
|
2016-10-13 10:54:30 +13:00
|
|
|
fmt = "I have just updated the prefix for this server; you now need to call commands with `{0}`. " \
|
|
|
|
"For example, you can call this command again with {0}prefix".format(prefix)
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send(fmt)
|
2016-09-01 07:10:33 +12:00
|
|
|
|
2017-04-09 15:04:46 +12:00
|
|
|
@commands.command()
|
|
|
|
@commands.guild_only()
|
2017-02-13 10:39:57 +13:00
|
|
|
@utils.custom_perms(manage_messages=True)
|
2016-08-13 05:37:29 +12:00
|
|
|
async def purge(self, ctx, limit: int = 100):
|
2016-11-29 17:55:55 +13:00
|
|
|
"""This command is used to a purge a number of messages from the channel
|
|
|
|
|
|
|
|
EXAMPLE: !purge 50
|
|
|
|
RESULT: -50 messages in this channel"""
|
2017-03-08 12:56:24 +13:00
|
|
|
if not ctx.message.channel.permissions_for(ctx.message.guild.me).manage_messages:
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send("I do not have permission to delete messages...")
|
2016-08-28 07:36:07 +12:00
|
|
|
return
|
2017-01-22 11:58:23 +13:00
|
|
|
try:
|
2017-03-08 21:44:27 +13:00
|
|
|
await ctx.message.channel.purge(limit=limit, before=ctx.message)
|
|
|
|
await ctx.message.delete()
|
2017-01-22 11:58:23 +13:00
|
|
|
except discord.HTTPException:
|
2017-03-08 12:56:24 +13:00
|
|
|
await ctx.message.channel.send("Detected messages that are too far "
|
|
|
|
"back for me to delete; I can only bulk delete messages"
|
|
|
|
" that are under 14 days old.")
|
2016-07-31 12:20:55 +12:00
|
|
|
|
2017-04-09 15:04:46 +12:00
|
|
|
@commands.command()
|
|
|
|
@commands.guild_only()
|
2017-02-13 10:39:57 +13:00
|
|
|
@utils.custom_perms(manage_messages=True)
|
2017-04-17 10:58:05 +12:00
|
|
|
async def prune(self, ctx, *specifications):
|
2016-08-26 16:50:09 +12:00
|
|
|
"""This command can be used to prune messages from certain members
|
|
|
|
Mention any user you want to prune messages from; if no members are mentioned, the messages removed will be mine
|
2016-11-29 17:55:55 +13:00
|
|
|
If no limit is provided, then 100 will be used. This is also the max limit we can use
|
|
|
|
|
|
|
|
EXAMPLE: !prune 50
|
|
|
|
RESULT: 50 of my messages are removed from this channel"""
|
2016-08-26 16:50:09 +12:00
|
|
|
# We can only get logs from 100 messages at a time, so make sure we are not above that threshold
|
2017-04-17 10:52:38 +12:00
|
|
|
limit = 100
|
|
|
|
for x in specifications:
|
|
|
|
try:
|
2017-04-17 11:03:32 +12:00
|
|
|
limit = int(x)
|
2017-04-17 10:52:38 +12:00
|
|
|
if limit <= 100:
|
|
|
|
break
|
|
|
|
else:
|
|
|
|
limit = 100
|
|
|
|
except (TypeError, ValueError):
|
|
|
|
continue
|
2016-08-26 16:50:09 +12:00
|
|
|
|
|
|
|
# If no members are provided, assume we're trying to prune our own messages
|
|
|
|
members = ctx.message.mentions
|
2017-03-07 11:09:41 +13:00
|
|
|
roles = ctx.message.role_mentions
|
2017-03-08 11:35:30 +13:00
|
|
|
|
2016-08-26 16:50:09 +12:00
|
|
|
if len(members) == 0:
|
2017-03-06 15:45:44 +13:00
|
|
|
members = [ctx.message.guild.me]
|
2017-03-07 11:09:41 +13:00
|
|
|
|
|
|
|
# Our check for if a message should be deleted
|
|
|
|
def check(m):
|
|
|
|
if m.author in members:
|
|
|
|
return True
|
|
|
|
if any(x in m.author.roles for x in roles):
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
|
2016-08-28 07:36:07 +12:00
|
|
|
# If we're not setting the user to the bot, then we're deleting someone elses messages
|
|
|
|
# To do so, we need manage_messages permission, so check if we have that
|
2017-03-08 12:56:24 +13:00
|
|
|
if not ctx.message.channel.permissions_for(ctx.message.guild.me).manage_messages:
|
|
|
|
await ctx.send("I do not have permission to delete messages...")
|
2016-08-28 07:36:07 +12:00
|
|
|
return
|
2016-08-26 16:50:09 +12:00
|
|
|
|
|
|
|
# Since logs_from will give us any message, not just the user's we need
|
|
|
|
# We'll increment count, and stop deleting messages if we hit the limit.
|
|
|
|
count = 0
|
2017-03-08 21:44:27 +13:00
|
|
|
async for msg in ctx.message.channel.history(before=ctx.message):
|
2017-03-07 11:09:41 +13:00
|
|
|
if check(msg):
|
2016-09-18 13:30:20 +12:00
|
|
|
try:
|
2017-03-06 15:45:44 +13:00
|
|
|
await msg.delete()
|
2016-09-18 13:30:20 +12:00
|
|
|
count += 1
|
2017-03-07 11:09:41 +13:00
|
|
|
except:
|
2016-09-18 13:30:20 +12:00
|
|
|
pass
|
2016-08-26 16:50:09 +12:00
|
|
|
if count >= limit:
|
|
|
|
break
|
2017-03-08 11:35:30 +13:00
|
|
|
|
2017-03-06 15:45:44 +13:00
|
|
|
msg = await ctx.send("{} messages succesfully deleted".format(count))
|
2017-03-07 11:08:55 +13:00
|
|
|
await asyncio.sleep(5)
|
2016-09-19 09:13:41 +12:00
|
|
|
try:
|
2017-03-06 15:45:44 +13:00
|
|
|
await msg.delete()
|
2017-03-08 11:35:30 +13:00
|
|
|
await ctx.message.delete()
|
|
|
|
except:
|
2016-09-19 09:13:41 +12:00
|
|
|
pass
|
2016-08-26 16:50:09 +12:00
|
|
|
|
2017-04-09 15:04:46 +12:00
|
|
|
@commands.group(aliases=['rule'], invoke_without_command=True)
|
|
|
|
@commands.guild_only()
|
2017-02-13 10:39:57 +13:00
|
|
|
@utils.custom_perms(send_messages=True)
|
2016-09-29 12:39:34 +13:00
|
|
|
async def rules(self, ctx, rule: int = None):
|
2016-11-29 17:55:55 +13:00
|
|
|
"""This command can be used to view the current rules on the server
|
|
|
|
|
|
|
|
EXAMPLE: !rules 5
|
|
|
|
RESULT: Rule 5 is printed"""
|
2017-03-08 20:55:22 +13:00
|
|
|
server_settings = await utils.get_content('server_settings', str(ctx.message.guild.id))
|
2017-03-20 16:13:14 +13:00
|
|
|
if server_settings is None:
|
|
|
|
await ctx.send("This server currently has no rules on it! I see you like to live dangerously...")
|
|
|
|
return
|
|
|
|
|
2017-03-08 20:55:22 +13:00
|
|
|
rules = server_settings.get('rules')
|
2017-03-08 17:28:30 +13:00
|
|
|
|
|
|
|
if not rules or len(rules) == 0:
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send("This server currently has no rules on it! I see you like to live dangerously...")
|
2016-09-29 15:31:53 +13:00
|
|
|
return
|
|
|
|
|
2016-09-29 12:39:34 +13:00
|
|
|
if rule is None:
|
2017-02-13 12:36:11 +13:00
|
|
|
try:
|
2017-02-13 12:58:27 +13:00
|
|
|
pages = utils.Pages(self.bot, message=ctx.message, entries=rules, per_page=5)
|
2017-03-08 12:56:24 +13:00
|
|
|
pages.title = "Rules for {}".format(ctx.message.guild.name)
|
2017-02-13 12:36:11 +13:00
|
|
|
await pages.paginate()
|
|
|
|
except utils.CannotPaginate as e:
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send(str(e))
|
2016-09-29 12:39:34 +13:00
|
|
|
else:
|
2016-09-29 15:31:53 +13:00
|
|
|
try:
|
|
|
|
fmt = rules[rule - 1]
|
|
|
|
except IndexError:
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send("That rules does not exist.")
|
2016-09-29 15:31:53 +13:00
|
|
|
return
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send("Rule {}: \"{}\"".format(rule, fmt))
|
2016-07-31 12:20:55 +12:00
|
|
|
|
2017-04-09 15:04:46 +12:00
|
|
|
@rules.command(name='add', aliases=['create'])
|
|
|
|
@commands.guild_only()
|
2017-03-08 21:28:57 +13:00
|
|
|
@utils.custom_perms(manage_guild=True)
|
2016-07-31 07:12:35 +12:00
|
|
|
async def rules_add(self, ctx, *, rule: str):
|
2016-11-29 17:55:55 +13:00
|
|
|
"""Adds a rule to this server's rules
|
|
|
|
|
|
|
|
EXAMPLE: !rules add No fun allowed in this server >:c
|
|
|
|
RESULT: No more fun...unless they break the rules!"""
|
2017-03-08 20:55:22 +13:00
|
|
|
key = str(ctx.message.guild.id)
|
|
|
|
entry = {'server_id': key,
|
2016-09-29 12:39:34 +13:00
|
|
|
'rules': [rule]}
|
2016-11-29 21:35:27 +13:00
|
|
|
update = {'rules': r.row['rules'].append(rule)}
|
2017-03-08 17:28:30 +13:00
|
|
|
|
|
|
|
server_settings = await utils.get_content('server_settings', key)
|
2017-03-08 21:44:27 +13:00
|
|
|
if server_settings and 'rules' in server_settings.keys():
|
2017-03-08 17:28:30 +13:00
|
|
|
await utils.update_content('server_settings', update, key)
|
|
|
|
elif server_settings:
|
|
|
|
await utils.update_content('server_settings', entry, key)
|
|
|
|
else:
|
|
|
|
await utils.add_content('server_settings', entry)
|
2016-09-29 12:39:34 +13:00
|
|
|
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send("I have just saved your new rule, use the rules command to view this server's current rules")
|
2016-07-31 12:20:55 +12:00
|
|
|
|
2017-04-09 15:04:46 +12:00
|
|
|
@rules.command(name='remove', aliases=['delete'])
|
|
|
|
@commands.guild_only()
|
2017-03-08 21:28:57 +13:00
|
|
|
@utils.custom_perms(manage_guild=True)
|
2016-09-29 12:39:34 +13:00
|
|
|
async def rules_delete(self, ctx, rule: int):
|
2016-07-31 07:20:31 +12:00
|
|
|
"""Removes one of the rules from the list of this server's rules
|
2016-11-29 17:55:55 +13:00
|
|
|
Provide a number to delete that rule
|
|
|
|
|
|
|
|
EXAMPLE: !rules delete 5
|
|
|
|
RESULT: Freedom from opression!"""
|
2016-09-29 12:39:34 +13:00
|
|
|
update = {'rules': r.row['rules'].delete_at(rule - 1)}
|
2017-03-08 20:55:22 +13:00
|
|
|
if not await utils.update_content('server_settings', update, str(ctx.message.guild.id)):
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send("That is not a valid rule number, try running the command again.")
|
2016-09-29 12:39:34 +13:00
|
|
|
else:
|
2017-03-06 15:45:44 +13:00
|
|
|
await ctx.send("I have just removed that rule from your list of rules!")
|
2016-07-31 12:20:55 +12:00
|
|
|
|
|
|
|
|
2016-07-09 13:31:18 +12:00
|
|
|
def setup(bot):
|
|
|
|
bot.add_cog(Mod(bot))
|