Reordering of commands to be grouped better
This commit is contained in:
parent
32f195b2f1
commit
5aa87ce653
485
cogs/admin.py
Normal file
485
cogs/admin.py
Normal file
|
@ -0,0 +1,485 @@
|
|||
from discord.ext import commands
|
||||
|
||||
from . import utils
|
||||
|
||||
import discord
|
||||
import re
|
||||
|
||||
class Administration:
|
||||
|
||||
|
||||
@commands.command(enabled=False)
|
||||
@commands.guild_only()
|
||||
@utils.custom_perms(manage_guild=True)
|
||||
async def restrict(self, ctx, *options):
|
||||
"""
|
||||
This is an intuitive command to restrict something to something
|
||||
The format is `!restrict what who/where`
|
||||
|
||||
For example, `!restrict command role` will require a user to have `role`
|
||||
to be able to run `command`
|
||||
`!restrict command channel` will only allow `command` to be ran in `channel`
|
||||
"""
|
||||
pass
|
||||
|
||||
@commands.command(aliases=['nick'])
|
||||
@commands.guild_only()
|
||||
@utils.custom_perms(kick_members=True)
|
||||
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
|
||||
RESULT: My nickname is now Music Bot"""
|
||||
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}")
|
||||
|
||||
@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)
|
||||
if settings is None:
|
||||
settings = {}
|
||||
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)
|
||||
|
||||
|
||||
@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)
|
||||
if settings is None:
|
||||
settings = {}
|
||||
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)
|
||||
|
||||
@commands.command(aliases=['alerts'])
|
||||
@commands.guild_only()
|
||||
@utils.custom_perms(kick_members=True)
|
||||
async def notifications(self, ctx, channel: discord.TextChannel):
|
||||
"""This command is used to set a channel as the server's 'notifications' channel
|
||||
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!"""
|
||||
key = str(ctx.message.guild.id)
|
||||
entry = {'server_id': key,
|
||||
'notification_channel': str(channel.id)}
|
||||
if not await utils.update_content('server_settings', entry, key):
|
||||
await utils.add_content('server_settings', entry)
|
||||
await ctx.send("I have just changed this server's 'notifications' channel"
|
||||
"\nAll notifications will now go to `{}`".format(channel))
|
||||
|
||||
@commands.command()
|
||||
@commands.guild_only()
|
||||
@utils.custom_perms(kick_members=True)
|
||||
async def usernotify(self, ctx, on_off: str):
|
||||
"""This command can be used to set whether or not you want user notificaitons to show
|
||||
Provide on, yes, or true to set it on; otherwise it will be turned off
|
||||
|
||||
EXAMPLE: !usernotify on
|
||||
RESULT: Annying join/leave notifications! Yay!"""
|
||||
# Join/Leave notifications can be kept separate from normal alerts
|
||||
# So we base this channel on it's own and not from alerts
|
||||
# When mod logging becomes available, that will be kept to it's own channel if wanted as well
|
||||
on_off = True if re.search("(on|yes|true)", on_off.lower()) else False
|
||||
key = str(ctx.message.guild.id)
|
||||
entry = {'server_id': key,
|
||||
'join_leave': on_off}
|
||||
if not await utils.update_content('server_settings', entry, key):
|
||||
await utils.add_content('server_settings', entry)
|
||||
|
||||
fmt = "notify" if on_off else "not notify"
|
||||
await ctx.send("This server will now {} if someone has joined or left".format(fmt))
|
||||
|
||||
@commands.group()
|
||||
async def nsfw(self, ctx):
|
||||
"""Handles adding or removing a channel as a nsfw channel"""
|
||||
# This command isn't meant to do anything, so just send an error if an invalid subcommand is passed
|
||||
pass
|
||||
|
||||
@nsfw.command(name="add")
|
||||
@utils.custom_perms(kick_members=True)
|
||||
async def nsfw_add(self, ctx):
|
||||
"""Registers this channel as a 'nsfw' channel
|
||||
|
||||
EXAMPLE: !nsfw add
|
||||
RESULT: ;)"""
|
||||
|
||||
if type(ctx.message.channel) is discord.DMChannel:
|
||||
key = 'DMs'
|
||||
else:
|
||||
key = str(ctx.message.guild.id)
|
||||
|
||||
entry = {'server_id': key,
|
||||
'nsfw_channels': [str(ctx.message.channel.id)]}
|
||||
update = {'nsfw_channels': r.row['nsfw_channels'].append(str(ctx.message.channel.id))}
|
||||
|
||||
server_settings = await utils.get_content('server_settings', key)
|
||||
if server_settings and 'nsfw_channels' in server_settings.keys():
|
||||
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)
|
||||
|
||||
await ctx.send("This channel has just been registered as 'nsfw'! Have fun you naughties ;)")
|
||||
|
||||
@nsfw.command(name="remove", aliases=["delete"])
|
||||
@utils.custom_perms(kick_members=True)
|
||||
async def nsfw_remove(self, ctx):
|
||||
"""Removes this channel as a 'nsfw' channel
|
||||
|
||||
EXAMPLE: !nsfw remove
|
||||
RESULT: ;("""
|
||||
|
||||
if type(ctx.message.channel) is discord.DMChannel:
|
||||
key = 'DMs'
|
||||
else:
|
||||
key = str(ctx.message.guild.id)
|
||||
|
||||
server_settings = await utils.get_content('server_settings', key)
|
||||
channel = str(ctx.message.channel.id)
|
||||
try:
|
||||
channels = server_settings['nsfw_channels']
|
||||
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!")
|
||||
|
||||
|
||||
@commands.group(invoke_without_command=True)
|
||||
@commands.guild_only()
|
||||
@utils.custom_perms(send_messages=True)
|
||||
async def perms(self, ctx, *, command: str = None):
|
||||
"""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
|
||||
|
||||
EXAMPLE: !perms help RESULT: Hopefully a result saying you just need send_messages permissions; otherwise lol
|
||||
this server's admin doesn't like me """
|
||||
if command is None:
|
||||
await ctx.send(
|
||||
"Valid permissions are: ```\n{}```".format("\n".join("{}".format(i) for i in valid_perms)))
|
||||
return
|
||||
|
||||
cmd = self.bot.get_command(command)
|
||||
|
||||
if cmd is None:
|
||||
await ctx.send("That is not a valid command!")
|
||||
return
|
||||
|
||||
server_settings = await utils.get_content('server_settings', str(ctx.message.guild.id))
|
||||
try:
|
||||
server_perms = server_settings['permissions']
|
||||
except (TypeError, IndexError, KeyError):
|
||||
server_perms = {}
|
||||
|
||||
perms_value = server_perms.get(cmd.qualified_name)
|
||||
if perms_value is None:
|
||||
# If we don't find custom permissions, get the required permission for a command
|
||||
# based on what we set in utils.custom_perms, if custom_perms isn't found, we'll get an IndexError
|
||||
try:
|
||||
custom_perms = [func for func in cmd.checks if "custom_perms" in func.__qualname__][0]
|
||||
except IndexError:
|
||||
# Loop through and check if there is a check called is_owner
|
||||
# If we loop through and don't find one, this means that the only other choice is to be
|
||||
# Able to manage the server (for the utils on perm commands)
|
||||
for func in cmd.checks:
|
||||
if "is_owner" in func.__qualname__:
|
||||
await ctx.send("You need to own the bot to run this command")
|
||||
return
|
||||
await ctx.send(
|
||||
"You are required to have `manage_guild` permissions to run `{}`".format(cmd.qualified_name))
|
||||
return
|
||||
|
||||
# Perms will be an attribute if custom_perms is found no matter what, so no need to check this
|
||||
perms = "\n".join(attribute for attribute, setting in custom_perms.perms.items() if setting)
|
||||
await ctx.send(
|
||||
"You are required to have `{}` permissions to run `{}`".format(perms, cmd.qualified_name))
|
||||
else:
|
||||
# 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
|
||||
permissions = discord.Permissions(perms_value)
|
||||
needed_perm = [perm[0] for perm in permissions if perm[1]][0]
|
||||
await ctx.send("You need to have the permission `{}` "
|
||||
"to use the command `{}` in this server".format(needed_perm, command))
|
||||
|
||||
@perms.command(name="add", aliases=["setup,create"])
|
||||
@commands.guild_only()
|
||||
@commands.has_permissions(manage_guild=True)
|
||||
async def add_perms(self, ctx, *msg: str):
|
||||
"""Sets up custom permissions on the provided command
|
||||
Format must be 'perms add <command> <permission>'
|
||||
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"""
|
||||
|
||||
# Since subcommands exist, base the last word in the list as the permission, and the rest of it as the command
|
||||
command = " ".join(msg[0:len(msg) - 1])
|
||||
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
|
||||
try:
|
||||
permissions = msg[len(msg) - 1]
|
||||
except IndexError:
|
||||
await ctx.send("Please provide the permissions you want to setup, the format for this must be in:\n"
|
||||
"`perms add <command> <permission>`")
|
||||
return
|
||||
|
||||
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
|
||||
|
||||
# If a user can run a command, they have to have send_messages permissions; so use this as the base
|
||||
if permissions.lower() == "none":
|
||||
permissions = "send_messages"
|
||||
|
||||
# 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:
|
||||
await ctx.send("{} does not appear to be a valid permission! Valid permissions are: ```\n{}```"
|
||||
.format(permissions, "\n".join(valid_perms)))
|
||||
return
|
||||
perm_value = perm_obj.value
|
||||
|
||||
# Two cases I use should never have custom permissions setup on them, is_owner for obvious reasons
|
||||
# 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
|
||||
# Currently the second case is only on adding and removing permissions, to avoid abuse on these
|
||||
for check in cmd.checks:
|
||||
if "is_owner" == check.__name__ or "has_permissions" in str(check):
|
||||
await ctx.send("This command cannot have custom permissions setup!")
|
||||
return
|
||||
|
||||
key = str(ctx.message.guild.id)
|
||||
entry = {'server_id': key,
|
||||
'permissions': {cmd.qualified_name: perm_value}}
|
||||
|
||||
if not await utils.update_content('server_settings', entry, key):
|
||||
await utils.add_content('server_settings', entry)
|
||||
|
||||
await ctx.send("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"])
|
||||
@commands.guild_only()
|
||||
@commands.has_permissions(manage_guild=True)
|
||||
async def remove_perms(self, ctx, *, command: str):
|
||||
"""Removes the custom permissions setup on the command specified
|
||||
|
||||
EXAMPLE: !perms remove play
|
||||
RESULT: Freedom!"""
|
||||
|
||||
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
|
||||
|
||||
update = {'permissions': {cmd.qualified_name: None}}
|
||||
await utils.update_content('server_settings', update, str(ctx.message.guild.id))
|
||||
await ctx.send("I have just removed the custom permissions for {}!".format(cmd))
|
||||
|
||||
@commands.command()
|
||||
@commands.guild_only()
|
||||
@utils.custom_perms(manage_guild=True)
|
||||
async def prefix(self, ctx, *, prefix: str):
|
||||
"""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"""
|
||||
key = str(ctx.message.guild.id)
|
||||
if len(prefix.strip()) > 20:
|
||||
await ctx.send("Please keep prefixes under 20 characters")
|
||||
return
|
||||
if prefix.lower().strip() == "none":
|
||||
prefix = None
|
||||
|
||||
entry = {'server_id': key,
|
||||
'prefix': prefix}
|
||||
|
||||
if not await utils.update_content('server_settings', entry, key):
|
||||
await utils.add_content('prefixes', entry)
|
||||
|
||||
if prefix is None:
|
||||
fmt = "I have just cleared your custom prefix, the default prefix will have to be used now"
|
||||
else:
|
||||
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)
|
||||
await ctx.send(fmt)
|
||||
|
||||
@commands.group(aliases=['rule'], invoke_without_command=True)
|
||||
@commands.guild_only()
|
||||
@utils.custom_perms(send_messages=True)
|
||||
async def rules(self, ctx, rule: int = None):
|
||||
"""This command can be used to view the current rules on the server
|
||||
|
||||
EXAMPLE: !rules 5
|
||||
RESULT: Rule 5 is printed"""
|
||||
server_settings = await utils.get_content('server_settings', str(ctx.message.guild.id))
|
||||
if server_settings is None:
|
||||
await ctx.send("This server currently has no rules on it! I see you like to live dangerously...")
|
||||
return
|
||||
|
||||
rules = server_settings.get('rules')
|
||||
|
||||
if not rules or len(rules) == 0:
|
||||
await ctx.send("This server currently has no rules on it! I see you like to live dangerously...")
|
||||
return
|
||||
|
||||
if rule is None:
|
||||
try:
|
||||
pages = utils.Pages(self.bot, message=ctx.message, entries=rules, per_page=5)
|
||||
pages.title = "Rules for {}".format(ctx.message.guild.name)
|
||||
await pages.paginate()
|
||||
except utils.CannotPaginate as e:
|
||||
await ctx.send(str(e))
|
||||
else:
|
||||
try:
|
||||
fmt = rules[rule - 1]
|
||||
except IndexError:
|
||||
await ctx.send("That rules does not exist.")
|
||||
return
|
||||
await ctx.send("Rule {}: \"{}\"".format(rule, fmt))
|
||||
|
||||
@rules.command(name='add', aliases=['create'])
|
||||
@commands.guild_only()
|
||||
@utils.custom_perms(manage_guild=True)
|
||||
async def rules_add(self, ctx, *, rule: str):
|
||||
"""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!"""
|
||||
key = str(ctx.message.guild.id)
|
||||
entry = {'server_id': key,
|
||||
'rules': [rule]}
|
||||
update = {'rules': r.row['rules'].append(rule)}
|
||||
|
||||
server_settings = await utils.get_content('server_settings', key)
|
||||
if server_settings and 'rules' in server_settings.keys():
|
||||
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)
|
||||
|
||||
await ctx.send("I have just saved your new rule, use the rules command to view this server's current rules")
|
||||
|
||||
@rules.command(name='remove', aliases=['delete'])
|
||||
@commands.guild_only()
|
||||
@utils.custom_perms(manage_guild=True)
|
||||
async def rules_delete(self, ctx, rule: int):
|
||||
"""Removes one of the rules from the list of this server's rules
|
||||
Provide a number to delete that rule
|
||||
|
||||
EXAMPLE: !rules delete 5
|
||||
RESULT: Freedom from opression!"""
|
||||
update = {'rules': r.row['rules'].delete_at(rule - 1)}
|
||||
if not await utils.update_content('server_settings', update, str(ctx.message.guild.id)):
|
||||
await ctx.send("That is not a valid rule number, try running the command again.")
|
||||
else:
|
||||
await ctx.send("I have just removed that rule from your list of rules!")
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(Administration(bot))
|
208
cogs/images.py
Normal file
208
cogs/images.py
Normal file
|
@ -0,0 +1,208 @@
|
|||
from discord.ext import commands
|
||||
import discord
|
||||
import random
|
||||
import re
|
||||
import math
|
||||
from bs4 import BeautifulSoup as bs
|
||||
|
||||
from . import utils
|
||||
|
||||
class Images:
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
@commands.command(aliases=['rc'])
|
||||
@utils.custom_perms(send_messages=True)
|
||||
async def cat(self, ctx):
|
||||
"""Use this to print a random cat image.
|
||||
|
||||
EXAMPLE: !cat
|
||||
RESULT: A beautiful picture of a cat o3o"""
|
||||
result = await utils.request('http://random.cat/meow')
|
||||
if result is None:
|
||||
await ctx.send("I couldn't connect! Sorry no cats right now ;w;")
|
||||
return
|
||||
filename = result.get('file', None)
|
||||
if filename is None:
|
||||
await ctx.send("I couldn't connect! Sorry no cats right now ;w;")
|
||||
return
|
||||
|
||||
image = await utils.download_image(filename)
|
||||
filename = re.search('.*\/i\/(.*)', filename).group(1)
|
||||
f = discord.File(image, filename=filename)
|
||||
await ctx.send(file=f)
|
||||
|
||||
|
||||
@commands.command(aliases=['dog', 'rd'])
|
||||
@utils.custom_perms(send_messages=True)
|
||||
async def doggo(self, ctx):
|
||||
"""Use this to print a random doggo image.
|
||||
|
||||
EXAMPLE: !doggo
|
||||
RESULT: A beautiful picture of a dog o3o"""
|
||||
result = await utils.request('http://random.dog', attr='text')
|
||||
try:
|
||||
soup = bs(result, 'html.parser')
|
||||
filename = soup.img.get('src')
|
||||
except (TypeError, AttributeError):
|
||||
await ctx.send("I couldn't connect! Sorry no dogs right now ;w;")
|
||||
return
|
||||
|
||||
image = await utils.download_image("http://random.dog/{}".format(filename))
|
||||
f = discord.File(image, filename=filename)
|
||||
await ctx.send(file=f)
|
||||
|
||||
@commands.command()
|
||||
@utils.custom_perms(send_messages=True)
|
||||
async def snek(self, ctx):
|
||||
"""Use this to print a random snek image.
|
||||
|
||||
EXAMPLE: !snek
|
||||
RESULT: A beautiful picture of a snek o3o"""
|
||||
# Find a random image based on how many we currently have
|
||||
f = random.SystemRandom().choice(glob.glob('images/snek*'))
|
||||
with open(f, 'rb') as f:
|
||||
await ctx.send(file=discord.File(f))
|
||||
|
||||
@commands.command()
|
||||
@commands.guild_only()
|
||||
@utils.custom_perms(send_messages=True)
|
||||
async def avatar(self, ctx, member: discord.Member = None):
|
||||
"""Provides an image for the provided person's avatar (yours if no other member is provided)
|
||||
|
||||
EXAMPLE: !avatar @person
|
||||
RESULT: A full image of that person's avatar"""
|
||||
|
||||
if member is None:
|
||||
member = ctx.message.author
|
||||
|
||||
url = member.avatar_url
|
||||
if '.gif' not in url:
|
||||
url = member.avatar_url_as(format='png')
|
||||
filename = 'avatar.png'
|
||||
else:
|
||||
filename = 'avatar.gif'
|
||||
if ctx.message.guild.me.permissions_in(ctx.message.channel).attach_files:
|
||||
filedata = await utils.download_image(url)
|
||||
if filedata is None:
|
||||
await ctx.send(url)
|
||||
else:
|
||||
f = discord.File(filedata, filename=filename)
|
||||
await ctx.send(file=f)
|
||||
else:
|
||||
await ctx.send(url)
|
||||
|
||||
@commands.command()
|
||||
@utils.custom_perms(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
|
||||
|
||||
EXAMPLE: !derpi Rainbow Dash
|
||||
RESULT: A picture of Rainbow Dash!"""
|
||||
await ctx.message.channel.trigger_typing()
|
||||
|
||||
if len(search) > 0:
|
||||
url = 'https://derpibooru.org/search.json'
|
||||
|
||||
# Ensure a filter was not provided, as we either want to use our own, or none (for safe pics)
|
||||
query = ' '.join(value for value in search if not re.search('&?filter_id=[0-9]+', value))
|
||||
params = {'q': query}
|
||||
|
||||
nsfw = await utils.channel_is_nsfw(ctx.message.channel)
|
||||
# If this is a nsfw channel, we just need to tack on 'explicit' to the terms
|
||||
# Also use the custom filter that I have setup, that blocks some certain tags
|
||||
# If the channel is not nsfw, we don't need to do anything, as the default filter blocks explicit
|
||||
if nsfw:
|
||||
params['q'] += ", (explicit OR suggestive)"
|
||||
params['filter_id'] = 95938
|
||||
else:
|
||||
params['q'] += ", safe"
|
||||
# Lets filter out some of the "crap" that's on derpibooru by requiring an image with a score higher than 15
|
||||
params['q'] += ', score.gt:15'
|
||||
|
||||
try:
|
||||
# Get the response from derpibooru and parse the 'search' result from it
|
||||
data = await utils.request(url, payload=params)
|
||||
|
||||
if data is None:
|
||||
await ctx.send("Sorry but I failed to connect to Derpibooru!")
|
||||
return
|
||||
results = data['search']
|
||||
except KeyError:
|
||||
await ctx.send("No results with that search term, {0}!".format(ctx.message.author.mention))
|
||||
return
|
||||
|
||||
# The first request we've made ensures there are results
|
||||
# Now we can get the total count from that, and make another request based on the number of pages as well
|
||||
if len(results) > 0:
|
||||
# Get the total number of pages
|
||||
pages = math.ceil(data['total'] / len(results))
|
||||
# Set a new paramater to set which page to use, randomly based on the number of pages
|
||||
params['page'] = random.SystemRandom().randint(1, pages)
|
||||
data = await utils.request(url, payload=params)
|
||||
if data is None:
|
||||
await ctx.send("Sorry but I failed to connect to Derpibooru!")
|
||||
return
|
||||
# Now get the results again
|
||||
results = data['search']
|
||||
|
||||
# Get the image link from the now random page'd and random result from that page
|
||||
index = random.SystemRandom().randint(0, len(results) - 1)
|
||||
#image_link = 'https://derpibooru.org/{}'.format(results[index]['id'])
|
||||
image_link = 'https:{}'.format(results[index]['image'])
|
||||
else:
|
||||
await ctx.send("No results with that search term, {0}!".format(ctx.message.author.mention))
|
||||
return
|
||||
else:
|
||||
# If no search term was provided, search for a random image
|
||||
# .url will be the URL we end up at, not the one requested.
|
||||
# https://derpibooru.org/images/random redirects to a random image, so this is exactly what we want
|
||||
image_link = await utils.request('https://derpibooru.org/images/random', attr='url')
|
||||
await ctx.send(image_link)
|
||||
|
||||
@commands.command()
|
||||
@utils.custom_perms(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.'
|
||||
If the channel the command is ran in, is registered as a nsfw channel, this image will be explicit
|
||||
|
||||
EXAMPLE: !e621 dragon
|
||||
RESULT: A picture of a dragon (hopefully, screw your tagging system e621)"""
|
||||
await ctx.message.channel.trigger_typing()
|
||||
|
||||
# This changes the formatting for queries, so we don't
|
||||
# Have to use e621's stupid formatting when using the command
|
||||
|
||||
tags = tags.replace(' ', '_')
|
||||
tags = tags.replace(',_', ' ')
|
||||
|
||||
url = 'https://e621.net/post/index.json'
|
||||
params = {'limit': 320,
|
||||
'tags': tags}
|
||||
|
||||
nsfw = await utils.channel_is_nsfw(ctx.message.channel)
|
||||
|
||||
# e621 by default does not filter explicit content, so tack on
|
||||
# safe/explicit based on if this channel is nsfw or not
|
||||
params['tags'] += " rating:explicit" if nsfw else " rating:safe"
|
||||
|
||||
data = await utils.request(url, payload=params)
|
||||
|
||||
if data is None:
|
||||
await ctx.send("Sorry, I had trouble connecting at the moment; please try again later")
|
||||
return
|
||||
|
||||
# Try to find an image from the list. If there were no results, we're going to attempt to find
|
||||
# A number between (0,-1) and receive an error.
|
||||
# The response should be in a list format, so we'll end up getting a key error if the response was in json
|
||||
# i.e. it responded with a 404/504/etc.
|
||||
try:
|
||||
rand_image = data[random.SystemRandom().randint(0, len(data) - 1)]['file_url']
|
||||
await ctx.send(rand_image)
|
||||
except (ValueError, KeyError):
|
||||
await ctx.send("No results with that tag {}".format(ctx.message.author.mention))
|
||||
return
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(Stats(bot))
|
|
@ -123,34 +123,6 @@ class Interaction:
|
|||
fmt = random.SystemRandom().choice(hugs)
|
||||
await ctx.send(fmt.format(user.display_name))
|
||||
|
||||
@commands.command()
|
||||
@commands.guild_only()
|
||||
@utils.custom_perms(send_messages=True)
|
||||
async def avatar(self, ctx, member: discord.Member = None):
|
||||
"""Provides an image for the provided person's avatar (yours if no other member is provided)
|
||||
|
||||
EXAMPLE: !avatar @person
|
||||
RESULT: A full image of that person's avatar"""
|
||||
|
||||
if member is None:
|
||||
member = ctx.message.author
|
||||
|
||||
url = member.avatar_url
|
||||
if '.gif' not in url:
|
||||
url = member.avatar_url_as(format='png')
|
||||
filename = 'avatar.png'
|
||||
else:
|
||||
filename = 'avatar.gif'
|
||||
if ctx.message.guild.me.permissions_in(ctx.message.channel).attach_files:
|
||||
filedata = await utils.download_image(url)
|
||||
if filedata is None:
|
||||
await ctx.send(url)
|
||||
else:
|
||||
f = discord.File(filedata, filename=filename)
|
||||
await ctx.send(file=f)
|
||||
else:
|
||||
await ctx.send(url)
|
||||
|
||||
@commands.group(invoke_without_command=True)
|
||||
@commands.guild_only()
|
||||
@commands.cooldown(1, 180, BucketType.user)
|
||||
|
|
111
cogs/links.py
111
cogs/links.py
|
@ -174,117 +174,6 @@ class Links:
|
|||
except KeyError:
|
||||
await ctx.send("Sorry but I failed to connect to urban dictionary!")
|
||||
|
||||
@commands.command()
|
||||
@utils.custom_perms(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
|
||||
|
||||
EXAMPLE: !derpi Rainbow Dash
|
||||
RESULT: A picture of Rainbow Dash!"""
|
||||
await ctx.message.channel.trigger_typing()
|
||||
|
||||
if len(search) > 0:
|
||||
url = 'https://derpibooru.org/search.json'
|
||||
|
||||
# Ensure a filter was not provided, as we either want to use our own, or none (for safe pics)
|
||||
query = ' '.join(value for value in search if not re.search('&?filter_id=[0-9]+', value))
|
||||
params = {'q': query}
|
||||
|
||||
nsfw = await utils.channel_is_nsfw(ctx.message.channel)
|
||||
# If this is a nsfw channel, we just need to tack on 'explicit' to the terms
|
||||
# Also use the custom filter that I have setup, that blocks some certain tags
|
||||
# If the channel is not nsfw, we don't need to do anything, as the default filter blocks explicit
|
||||
if nsfw:
|
||||
params['q'] += ", (explicit OR suggestive)"
|
||||
params['filter_id'] = 95938
|
||||
else:
|
||||
params['q'] += ", safe"
|
||||
# Lets filter out some of the "crap" that's on derpibooru by requiring an image with a score higher than 15
|
||||
params['q'] += ', score.gt:15'
|
||||
|
||||
try:
|
||||
# Get the response from derpibooru and parse the 'search' result from it
|
||||
data = await utils.request(url, payload=params)
|
||||
|
||||
if data is None:
|
||||
await ctx.send("Sorry but I failed to connect to Derpibooru!")
|
||||
return
|
||||
results = data['search']
|
||||
except KeyError:
|
||||
await ctx.send("No results with that search term, {0}!".format(ctx.message.author.mention))
|
||||
return
|
||||
|
||||
# The first request we've made ensures there are results
|
||||
# Now we can get the total count from that, and make another request based on the number of pages as well
|
||||
if len(results) > 0:
|
||||
# Get the total number of pages
|
||||
pages = math.ceil(data['total'] / len(results))
|
||||
# Set a new paramater to set which page to use, randomly based on the number of pages
|
||||
params['page'] = random.SystemRandom().randint(1, pages)
|
||||
data = await utils.request(url, payload=params)
|
||||
if data is None:
|
||||
await ctx.send("Sorry but I failed to connect to Derpibooru!")
|
||||
return
|
||||
# Now get the results again
|
||||
results = data['search']
|
||||
|
||||
# Get the image link from the now random page'd and random result from that page
|
||||
index = random.SystemRandom().randint(0, len(results) - 1)
|
||||
image_link = 'https://derpibooru.org/{}'.format(results[index]['id'])
|
||||
else:
|
||||
await ctx.send("No results with that search term, {0}!".format(ctx.message.author.mention))
|
||||
return
|
||||
else:
|
||||
# If no search term was provided, search for a random image
|
||||
# .url will be the URL we end up at, not the one requested.
|
||||
# https://derpibooru.org/images/random redirects to a random image, so this is exactly what we want
|
||||
image_link = await utils.request('https://derpibooru.org/images/random', attr='url')
|
||||
await ctx.send(image_link)
|
||||
|
||||
@commands.command()
|
||||
@utils.custom_perms(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.'
|
||||
If the channel the command is ran in, is registered as a nsfw channel, this image will be explicit
|
||||
|
||||
EXAMPLE: !e621 dragon
|
||||
RESULT: A picture of a dragon (hopefully, screw your tagging system e621)"""
|
||||
await ctx.message.channel.trigger_typing()
|
||||
|
||||
# This changes the formatting for queries, so we don't
|
||||
# Have to use e621's stupid formatting when using the command
|
||||
|
||||
tags = tags.replace(' ', '_')
|
||||
tags = tags.replace(',_', ' ')
|
||||
|
||||
url = 'https://e621.net/post/index.json'
|
||||
params = {'limit': 320,
|
||||
'tags': tags}
|
||||
|
||||
nsfw = await utils.channel_is_nsfw(ctx.message.channel)
|
||||
|
||||
# e621 by default does not filter explicit content, so tack on
|
||||
# safe/explicit based on if this channel is nsfw or not
|
||||
params['tags'] += " rating:explicit" if nsfw else " rating:safe"
|
||||
|
||||
data = await utils.request(url, payload=params)
|
||||
|
||||
if data is None:
|
||||
await ctx.send("Sorry, I had trouble connecting at the moment; please try again later")
|
||||
return
|
||||
|
||||
# Try to find an image from the list. If there were no results, we're going to attempt to find
|
||||
# A number between (0,-1) and receive an error.
|
||||
# The response should be in a list format, so we'll end up getting a key error if the response was in json
|
||||
# i.e. it responded with a 404/504/etc.
|
||||
try:
|
||||
rand_image = data[random.SystemRandom().randint(0, len(data) - 1)]['file_url']
|
||||
await ctx.send(rand_image)
|
||||
except (ValueError, KeyError):
|
||||
await ctx.send("No results with that tag {}".format(ctx.message.author.mention))
|
||||
return
|
||||
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(Links(bot))
|
||||
|
|
|
@ -14,13 +14,12 @@ import datetime
|
|||
import psutil
|
||||
|
||||
|
||||
class Core:
|
||||
class Miscallaneous:
|
||||
"""Core commands, these are the miscallaneous commands that don't fit into other categories'"""
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
# This is a dictionary used to hold information about which page a certain help message is on
|
||||
self.help_embeds = {}
|
||||
self.help_embeds = []
|
||||
self.results_per_page = 10
|
||||
self.commands = None
|
||||
self.process = psutil.Process()
|
||||
|
@ -35,55 +34,54 @@ class Core:
|
|||
|
||||
EXAMPLE: !help help
|
||||
RESULT: This information"""
|
||||
groups = {}
|
||||
entries = []
|
||||
|
||||
cmd = None
|
||||
page = 1
|
||||
|
||||
if message is not None:
|
||||
# If something is provided, it can either be the page number or a command
|
||||
# Try to convert to an int (the page number), if not, then a command should have been provided
|
||||
try:
|
||||
page = int(message)
|
||||
except:
|
||||
cmd = self.bot.get_command(message)
|
||||
|
||||
if cmd is None:
|
||||
entries = []
|
||||
for cmd in utils.get_all_commands(self.bot):
|
||||
if await cmd.can_run(ctx):
|
||||
entries.append(cmd.qualified_name)
|
||||
try:
|
||||
pages = utils.Pages(self.bot, message=ctx.message, entries=entries)
|
||||
await pages.paginate(start_page=page)
|
||||
except utils.CannotPaginate as e:
|
||||
await ctx.send(str(e))
|
||||
else:
|
||||
# Get the description for a command
|
||||
description = cmd.help
|
||||
if description is not None:
|
||||
# Split into examples, results, and the description itself based on the string
|
||||
example = [x.replace('EXAMPLE: ', '') for x in description.split('\n') if 'EXAMPLE:' in x]
|
||||
result = [x.replace('RESULT: ', '') for x in description.split('\n') if 'RESULT:' in x]
|
||||
description = [x for x in description.split('\n') if x and 'EXAMPLE:' not in x and 'RESULT:' not in x]
|
||||
for cmd in utils.get_all_commands(self.bot):
|
||||
cog = cmd.cog_name
|
||||
if cog in groups:
|
||||
groups[cog].append(cmd)
|
||||
else:
|
||||
example = None
|
||||
result = None
|
||||
# Also get the subcommands for this command, if they exist
|
||||
subcommands = [x.qualified_name for x in utils.get_all_subcommands(cmd) if x.qualified_name != cmd.qualified_name]
|
||||
groups[cog] = [cmd]
|
||||
|
||||
# The rest is simple, create the embed, set the thumbail to me, add all fields if they exist
|
||||
embed = discord.Embed(title=cmd.qualified_name)
|
||||
embed.set_thumbnail(url=self.bot.user.avatar_url)
|
||||
if description:
|
||||
embed.add_field(name="Description", value="\n".join(description), inline=False)
|
||||
if example:
|
||||
embed.add_field(name="Example", value="\n".join(example), inline=False)
|
||||
if result:
|
||||
embed.add_field(name="Result", value="\n".join(result), inline=False)
|
||||
if subcommands:
|
||||
embed.add_field(name='Subcommands', value="\n".join(subcommands), inline=False)
|
||||
for cog, cmds in groups.items():
|
||||
entry = {'title': "{} Commands".format(cog),
|
||||
'fields': []}
|
||||
|
||||
await ctx.send(embed=embed)
|
||||
for cmd in cmds:
|
||||
if not cmd.help:
|
||||
# Assume if there's no description for a command, it's not supposed to be used
|
||||
# I.e. the !command command. It's just a parent
|
||||
continue
|
||||
description = cmd.help.partition('\n')[0]
|
||||
entry['fields'].append({
|
||||
'name': "**{}**".format(cmd.qualified_name),
|
||||
'value': description,
|
||||
'inline': False
|
||||
})
|
||||
entries.append(entry)
|
||||
|
||||
try:
|
||||
pages = utils.DetailedPages(self.bot, message=ctx.message, entries=entries)
|
||||
pages.embed.set_thumbnail(url=ctx.message.guild.me.avatar_url)
|
||||
await pages.paginate()
|
||||
except utils.CannotPaginate as e:
|
||||
await ctx.send(str(e))
|
||||
|
||||
|
||||
@commands.command()
|
||||
@utils.custom_perms(send_messages=True)
|
||||
async def say(self, ctx, *, msg: str):
|
||||
"""Tells the bot to repeat what you say
|
||||
|
||||
EXAMPLE: !say I really like orange juice
|
||||
RESULT: I really like orange juice"""
|
||||
fmt = "\u200B{}".format(msg)
|
||||
await ctx.send(fmt)
|
||||
try:
|
||||
await ctx.message.delete()
|
||||
except:
|
||||
pass
|
||||
|
||||
@commands.command()
|
||||
@utils.custom_perms(send_messages=True)
|
||||
|
@ -167,7 +165,7 @@ class Core:
|
|||
cal = calendar.TextCalendar().formatmonth(year, month)
|
||||
await ctx.send("```\n{}```".format(cal))
|
||||
|
||||
@commands.command()
|
||||
@commands.command(aliases=['about'])
|
||||
@utils.custom_perms(send_messages=True)
|
||||
async def info(self, ctx):
|
||||
"""This command can be used to print out some of my information"""
|
||||
|
@ -253,59 +251,6 @@ class Core:
|
|||
await ctx.send("Use this URL to add me to a server that you'd like!\n{}"
|
||||
.format(discord.utils.oauth_url(app_info.id, perms)))
|
||||
|
||||
@commands.command(aliases=['rc'])
|
||||
@utils.custom_perms(send_messages=True)
|
||||
async def cat(self, ctx):
|
||||
"""Use this to print a random cat image.
|
||||
|
||||
EXAMPLE: !cat
|
||||
RESULT: A beautiful picture of a cat o3o"""
|
||||
result = await utils.request('http://random.cat/meow')
|
||||
if result is None:
|
||||
await ctx.send("I couldn't connect! Sorry no cats right now ;w;")
|
||||
return
|
||||
filename = result.get('file', None)
|
||||
if filename is None:
|
||||
await ctx.send("I couldn't connect! Sorry no cats right now ;w;")
|
||||
return
|
||||
|
||||
image = await utils.download_image(filename)
|
||||
filename = re.search('.*\/i\/(.*)', filename).group(1)
|
||||
f = discord.File(image, filename=filename)
|
||||
await ctx.send(file=f)
|
||||
|
||||
|
||||
@commands.command(aliases=['dog', 'rd'])
|
||||
@utils.custom_perms(send_messages=True)
|
||||
async def doggo(self, ctx):
|
||||
"""Use this to print a random doggo image.
|
||||
|
||||
EXAMPLE: !doggo
|
||||
RESULT: A beautiful picture of a dog o3o"""
|
||||
result = await utils.request('http://random.dog', attr='text')
|
||||
try:
|
||||
soup = bs(result, 'html.parser')
|
||||
filename = soup.img.get('src')
|
||||
except (TypeError, AttributeError):
|
||||
await ctx.send("I couldn't connect! Sorry no dogs right now ;w;")
|
||||
return
|
||||
|
||||
image = await utils.download_image("http://random.dog/{}".format(filename))
|
||||
f = discord.File(image, filename=filename)
|
||||
await ctx.send(file=f)
|
||||
|
||||
@commands.command()
|
||||
@utils.custom_perms(send_messages=True)
|
||||
async def snek(self, ctx):
|
||||
"""Use this to print a random snek image.
|
||||
|
||||
EXAMPLE: !snek
|
||||
RESULT: A beautiful picture of a snek o3o"""
|
||||
# Find a random image based on how many we currently have
|
||||
f = random.SystemRandom().choice(glob.glob('images/snek*'))
|
||||
with open(f, 'rb') as f:
|
||||
await ctx.send(file=discord.File(f))
|
||||
|
||||
@commands.command()
|
||||
@utils.custom_perms(send_messages=True)
|
||||
async def joke(self, ctx):
|
||||
|
@ -372,4 +317,4 @@ class Core:
|
|||
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(Core(bot))
|
||||
bot.add_cog(Miscallaneous(bot))
|
474
cogs/mod.py
474
cogs/mod.py
|
@ -10,26 +10,13 @@ import rethinkdb as r
|
|||
valid_perms = [p for p in dir(discord.Permissions) if isinstance(getattr(discord.Permissions, p), property)]
|
||||
|
||||
|
||||
class Mod:
|
||||
class Moderation:
|
||||
"""Commands that can be used by a or an admin, depending on the command"""
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
@commands.command(aliases=['nick'])
|
||||
@commands.guild_only()
|
||||
@utils.custom_perms(kick_members=True)
|
||||
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
|
||||
RESULT: My nickname is now Music Bot"""
|
||||
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}")
|
||||
|
||||
@commands.command()
|
||||
@commands.guild_only()
|
||||
|
@ -108,391 +95,6 @@ class Mod:
|
|||
except discord.HTTPException:
|
||||
await ctx.send("Sorry, I failed to ban that user!")
|
||||
|
||||
@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)
|
||||
if settings is None:
|
||||
settings = {}
|
||||
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)
|
||||
|
||||
|
||||
@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)
|
||||
if settings is None:
|
||||
settings = {}
|
||||
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)
|
||||
|
||||
@commands.command(aliases=['alerts'])
|
||||
@commands.guild_only()
|
||||
@utils.custom_perms(kick_members=True)
|
||||
async def notifications(self, ctx, channel: discord.TextChannel):
|
||||
"""This command is used to set a channel as the server's 'notifications' channel
|
||||
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!"""
|
||||
key = str(ctx.message.guild.id)
|
||||
entry = {'server_id': key,
|
||||
'notification_channel': str(channel.id)}
|
||||
if not await utils.update_content('server_settings', entry, key):
|
||||
await utils.add_content('server_settings', entry)
|
||||
await ctx.send("I have just changed this server's 'notifications' channel"
|
||||
"\nAll notifications will now go to `{}`".format(channel))
|
||||
|
||||
@commands.command()
|
||||
@commands.guild_only()
|
||||
@utils.custom_perms(kick_members=True)
|
||||
async def usernotify(self, ctx, on_off: str):
|
||||
"""This command can be used to set whether or not you want user notificaitons to show
|
||||
Provide on, yes, or true to set it on; otherwise it will be turned off
|
||||
|
||||
EXAMPLE: !usernotify on
|
||||
RESULT: Annying join/leave notifications! Yay!"""
|
||||
# Join/Leave notifications can be kept separate from normal alerts
|
||||
# So we base this channel on it's own and not from alerts
|
||||
# When mod logging becomes available, that will be kept to it's own channel if wanted as well
|
||||
on_off = True if re.search("(on|yes|true)", on_off.lower()) else False
|
||||
key = str(ctx.message.guild.id)
|
||||
entry = {'server_id': key,
|
||||
'join_leave': on_off}
|
||||
if not await utils.update_content('server_settings', entry, key):
|
||||
await utils.add_content('server_settings', entry)
|
||||
|
||||
fmt = "notify" if on_off else "not notify"
|
||||
await ctx.send("This server will now {} if someone has joined or left".format(fmt))
|
||||
|
||||
@commands.group()
|
||||
async def nsfw(self, ctx):
|
||||
"""Handles adding or removing a channel as a nsfw channel"""
|
||||
# This command isn't meant to do anything, so just send an error if an invalid subcommand is passed
|
||||
pass
|
||||
|
||||
@nsfw.command(name="add")
|
||||
@utils.custom_perms(kick_members=True)
|
||||
async def nsfw_add(self, ctx):
|
||||
"""Registers this channel as a 'nsfw' channel
|
||||
|
||||
EXAMPLE: !nsfw add
|
||||
RESULT: ;)"""
|
||||
|
||||
if type(ctx.message.channel) is discord.DMChannel:
|
||||
key = 'DMs'
|
||||
else:
|
||||
key = str(ctx.message.guild.id)
|
||||
|
||||
entry = {'server_id': key,
|
||||
'nsfw_channels': [str(ctx.message.channel.id)]}
|
||||
update = {'nsfw_channels': r.row['nsfw_channels'].append(str(ctx.message.channel.id))}
|
||||
|
||||
server_settings = await utils.get_content('server_settings', key)
|
||||
if server_settings and 'nsfw_channels' in server_settings.keys():
|
||||
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)
|
||||
|
||||
await ctx.send("This channel has just been registered as 'nsfw'! Have fun you naughties ;)")
|
||||
|
||||
@nsfw.command(name="remove", aliases=["delete"])
|
||||
@utils.custom_perms(kick_members=True)
|
||||
async def nsfw_remove(self, ctx):
|
||||
"""Removes this channel as a 'nsfw' channel
|
||||
|
||||
EXAMPLE: !nsfw remove
|
||||
RESULT: ;("""
|
||||
|
||||
if type(ctx.message.channel) is discord.DMChannel:
|
||||
key = 'DMs'
|
||||
else:
|
||||
key = str(ctx.message.guild.id)
|
||||
|
||||
server_settings = await utils.get_content('server_settings', key)
|
||||
channel = str(ctx.message.channel.id)
|
||||
try:
|
||||
channels = server_settings['nsfw_channels']
|
||||
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!")
|
||||
|
||||
@commands.command()
|
||||
@utils.custom_perms(kick_members=True)
|
||||
async def say(self, ctx, *, msg: str):
|
||||
"""Tells the bot to repeat what you say
|
||||
|
||||
EXAMPLE: !say I really like orange juice
|
||||
RESULT: I really like orange juice"""
|
||||
fmt = "\u200B{}".format(msg)
|
||||
await ctx.send(fmt)
|
||||
try:
|
||||
await ctx.message.delete()
|
||||
except:
|
||||
pass
|
||||
|
||||
@commands.group(invoke_without_command=True)
|
||||
@commands.guild_only()
|
||||
@utils.custom_perms(send_messages=True)
|
||||
async def perms(self, ctx, *, command: str = None):
|
||||
"""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
|
||||
|
||||
EXAMPLE: !perms help RESULT: Hopefully a result saying you just need send_messages permissions; otherwise lol
|
||||
this server's admin doesn't like me """
|
||||
if command is None:
|
||||
await ctx.send(
|
||||
"Valid permissions are: ```\n{}```".format("\n".join("{}".format(i) for i in valid_perms)))
|
||||
return
|
||||
|
||||
cmd = self.bot.get_command(command)
|
||||
|
||||
if cmd is None:
|
||||
await ctx.send("That is not a valid command!")
|
||||
return
|
||||
|
||||
server_settings = await utils.get_content('server_settings', str(ctx.message.guild.id))
|
||||
try:
|
||||
server_perms = server_settings['permissions']
|
||||
except (TypeError, IndexError, KeyError):
|
||||
server_perms = {}
|
||||
|
||||
perms_value = server_perms.get(cmd.qualified_name)
|
||||
if perms_value is None:
|
||||
# If we don't find custom permissions, get the required permission for a command
|
||||
# based on what we set in utils.custom_perms, if custom_perms isn't found, we'll get an IndexError
|
||||
try:
|
||||
custom_perms = [func for func in cmd.checks if "custom_perms" in func.__qualname__][0]
|
||||
except IndexError:
|
||||
# Loop through and check if there is a check called is_owner
|
||||
# If we loop through and don't find one, this means that the only other choice is to be
|
||||
# Able to manage the server (for the utils on perm commands)
|
||||
for func in cmd.checks:
|
||||
if "is_owner" in func.__qualname__:
|
||||
await ctx.send("You need to own the bot to run this command")
|
||||
return
|
||||
await ctx.send(
|
||||
"You are required to have `manage_guild` permissions to run `{}`".format(cmd.qualified_name))
|
||||
return
|
||||
|
||||
# Perms will be an attribute if custom_perms is found no matter what, so no need to check this
|
||||
perms = "\n".join(attribute for attribute, setting in custom_perms.perms.items() if setting)
|
||||
await ctx.send(
|
||||
"You are required to have `{}` permissions to run `{}`".format(perms, cmd.qualified_name))
|
||||
else:
|
||||
# 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
|
||||
permissions = discord.Permissions(perms_value)
|
||||
needed_perm = [perm[0] for perm in permissions if perm[1]][0]
|
||||
await ctx.send("You need to have the permission `{}` "
|
||||
"to use the command `{}` in this server".format(needed_perm, command))
|
||||
|
||||
@perms.command(name="add", aliases=["setup,create"])
|
||||
@commands.guild_only()
|
||||
@commands.has_permissions(manage_guild=True)
|
||||
async def add_perms(self, ctx, *msg: str):
|
||||
"""Sets up custom permissions on the provided command
|
||||
Format must be 'perms add <command> <permission>'
|
||||
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"""
|
||||
|
||||
# Since subcommands exist, base the last word in the list as the permission, and the rest of it as the command
|
||||
command = " ".join(msg[0:len(msg) - 1])
|
||||
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
|
||||
try:
|
||||
permissions = msg[len(msg) - 1]
|
||||
except IndexError:
|
||||
await ctx.send("Please provide the permissions you want to setup, the format for this must be in:\n"
|
||||
"`perms add <command> <permission>`")
|
||||
return
|
||||
|
||||
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
|
||||
|
||||
# If a user can run a command, they have to have send_messages permissions; so use this as the base
|
||||
if permissions.lower() == "none":
|
||||
permissions = "send_messages"
|
||||
|
||||
# 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:
|
||||
await ctx.send("{} does not appear to be a valid permission! Valid permissions are: ```\n{}```"
|
||||
.format(permissions, "\n".join(valid_perms)))
|
||||
return
|
||||
perm_value = perm_obj.value
|
||||
|
||||
# Two cases I use should never have custom permissions setup on them, is_owner for obvious reasons
|
||||
# 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
|
||||
# Currently the second case is only on adding and removing permissions, to avoid abuse on these
|
||||
for check in cmd.checks:
|
||||
if "is_owner" == check.__name__ or "has_permissions" in str(check):
|
||||
await ctx.send("This command cannot have custom permissions setup!")
|
||||
return
|
||||
|
||||
key = str(ctx.message.guild.id)
|
||||
entry = {'server_id': key,
|
||||
'permissions': {cmd.qualified_name: perm_value}}
|
||||
|
||||
if not await utils.update_content('server_settings', entry, key):
|
||||
await utils.add_content('server_settings', entry)
|
||||
|
||||
await ctx.send("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"])
|
||||
@commands.guild_only()
|
||||
@commands.has_permissions(manage_guild=True)
|
||||
async def remove_perms(self, ctx, *, command: str):
|
||||
"""Removes the custom permissions setup on the command specified
|
||||
|
||||
EXAMPLE: !perms remove play
|
||||
RESULT: Freedom!"""
|
||||
|
||||
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
|
||||
|
||||
update = {'permissions': {cmd.qualified_name: None}}
|
||||
await utils.update_content('server_settings', update, str(ctx.message.guild.id))
|
||||
await ctx.send("I have just removed the custom permissions for {}!".format(cmd))
|
||||
|
||||
@commands.command()
|
||||
@commands.guild_only()
|
||||
@utils.custom_perms(manage_guild=True)
|
||||
async def prefix(self, ctx, *, prefix: str):
|
||||
"""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"""
|
||||
key = str(ctx.message.guild.id)
|
||||
if len(prefix.strip()) > 20:
|
||||
await ctx.send("Please keep prefixes under 20 characters")
|
||||
return
|
||||
if prefix.lower().strip() == "none":
|
||||
prefix = None
|
||||
|
||||
entry = {'server_id': key,
|
||||
'prefix': prefix}
|
||||
|
||||
if not await utils.update_content('server_settings', entry, key):
|
||||
await utils.add_content('prefixes', entry)
|
||||
|
||||
if prefix is None:
|
||||
fmt = "I have just cleared your custom prefix, the default prefix will have to be used now"
|
||||
else:
|
||||
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)
|
||||
await ctx.send(fmt)
|
||||
|
||||
@commands.command()
|
||||
@commands.guild_only()
|
||||
@utils.custom_perms(manage_messages=True)
|
||||
|
@ -576,78 +178,6 @@ class Mod:
|
|||
except:
|
||||
pass
|
||||
|
||||
@commands.group(aliases=['rule'], invoke_without_command=True)
|
||||
@commands.guild_only()
|
||||
@utils.custom_perms(send_messages=True)
|
||||
async def rules(self, ctx, rule: int = None):
|
||||
"""This command can be used to view the current rules on the server
|
||||
|
||||
EXAMPLE: !rules 5
|
||||
RESULT: Rule 5 is printed"""
|
||||
server_settings = await utils.get_content('server_settings', str(ctx.message.guild.id))
|
||||
if server_settings is None:
|
||||
await ctx.send("This server currently has no rules on it! I see you like to live dangerously...")
|
||||
return
|
||||
|
||||
rules = server_settings.get('rules')
|
||||
|
||||
if not rules or len(rules) == 0:
|
||||
await ctx.send("This server currently has no rules on it! I see you like to live dangerously...")
|
||||
return
|
||||
|
||||
if rule is None:
|
||||
try:
|
||||
pages = utils.Pages(self.bot, message=ctx.message, entries=rules, per_page=5)
|
||||
pages.title = "Rules for {}".format(ctx.message.guild.name)
|
||||
await pages.paginate()
|
||||
except utils.CannotPaginate as e:
|
||||
await ctx.send(str(e))
|
||||
else:
|
||||
try:
|
||||
fmt = rules[rule - 1]
|
||||
except IndexError:
|
||||
await ctx.send("That rules does not exist.")
|
||||
return
|
||||
await ctx.send("Rule {}: \"{}\"".format(rule, fmt))
|
||||
|
||||
@rules.command(name='add', aliases=['create'])
|
||||
@commands.guild_only()
|
||||
@utils.custom_perms(manage_guild=True)
|
||||
async def rules_add(self, ctx, *, rule: str):
|
||||
"""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!"""
|
||||
key = str(ctx.message.guild.id)
|
||||
entry = {'server_id': key,
|
||||
'rules': [rule]}
|
||||
update = {'rules': r.row['rules'].append(rule)}
|
||||
|
||||
server_settings = await utils.get_content('server_settings', key)
|
||||
if server_settings and 'rules' in server_settings.keys():
|
||||
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)
|
||||
|
||||
await ctx.send("I have just saved your new rule, use the rules command to view this server's current rules")
|
||||
|
||||
@rules.command(name='remove', aliases=['delete'])
|
||||
@commands.guild_only()
|
||||
@utils.custom_perms(manage_guild=True)
|
||||
async def rules_delete(self, ctx, rule: int):
|
||||
"""Removes one of the rules from the list of this server's rules
|
||||
Provide a number to delete that rule
|
||||
|
||||
EXAMPLE: !rules delete 5
|
||||
RESULT: Freedom from opression!"""
|
||||
update = {'rules': r.row['rules'].delete_at(rule - 1)}
|
||||
if not await utils.update_content('server_settings', update, str(ctx.message.guild.id)):
|
||||
await ctx.send("That is not a valid rule number, try running the command again.")
|
||||
else:
|
||||
await ctx.send("I have just removed that rule from your list of rules!")
|
||||
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(Mod(bot))
|
||||
bot.add_cog(Moderation(bot))
|
||||
|
|
|
@ -303,6 +303,7 @@ class Music:
|
|||
state = self.voice_states.get(ctx.message.guild.id)
|
||||
if state and state.voice and state.voice.channel:
|
||||
await state.voice.move_to(channel)
|
||||
await ctx.send("Joined {} and ready to play".format(channel.name))
|
||||
return True
|
||||
else:
|
||||
self.voice_states[ctx.message.guild.id] = VoiceState(ctx.message.guild, self.bot)
|
||||
|
|
102
cogs/roles.py
102
cogs/roles.py
|
@ -303,5 +303,107 @@ class Roles:
|
|||
await ctx.send("I have just added the role {} to: ```\n{}```".format(name, fmt))
|
||||
|
||||
|
||||
@commands.group(invoke_without_command=True, aliases=['assign'])
|
||||
@commands.guild_only()
|
||||
@utils.custom_perms(manage_roles=True)
|
||||
async def assigns(self, ctx, *role: discord.Role):
|
||||
"""Adds the provided role(s) to the list of available self-assignable roles
|
||||
|
||||
EXAMPLE: !assigns Member NSFW
|
||||
RESULT: Allows users to self-assign the roles Member, and NSFW"""
|
||||
roles = [str(r.id) for r in role]
|
||||
key = str(ctx.message.guild.id)
|
||||
server_settings = await utils.get_content('server_settings', key)
|
||||
|
||||
if server_settings is None:
|
||||
entry = {'server_id': key, 'self_assignable_roles': roles}
|
||||
await utils.add_content('server_settings', entry)
|
||||
else:
|
||||
self_assignable_roles = server_settings.get('self_assignable_roles', [])
|
||||
self_assignable_roles.extend(roles)
|
||||
self_assignable_roles = list(set(self_assignable_roles))
|
||||
update = {'self_assignable_roles': self_assignable_roles}
|
||||
await utils.update_content('server_settings', update, key)
|
||||
|
||||
if len(roles) == 1:
|
||||
fmt = "Successfully added {} as a self-assignable role".format(role[0].name)
|
||||
else:
|
||||
fmt = "Succesfully added the following roles as self-assignable:\n{}".format(
|
||||
"\n".join(["**{}**".format(r.name) for r in role])
|
||||
)
|
||||
await ctx.send(fmt)
|
||||
|
||||
@assigns.command(name='remove')
|
||||
@commands.guild_only()
|
||||
@utils.custom_perms(manage_roles=True)
|
||||
async def _remove_assigns(self, ctx, *role: discord.Role):
|
||||
"""Removes the provided role(s) from the list of available self-assignable roles
|
||||
|
||||
EXAMPLE: !assigns remove Member NSFW
|
||||
RESULT: Removes the ability for users to self-assign the roles Member, and NSFW"""
|
||||
roles = [str(r.id) for r in role]
|
||||
key = str(ctx.message.guild.id)
|
||||
server_settings = await utils.get_content('server_settings', key)
|
||||
|
||||
if server_settings is None:
|
||||
await ctx.send("There are no self-assignable roles on this server")
|
||||
return
|
||||
self_assignable_roles = server_settings.get('self_assignable_roles', [])
|
||||
if len(self_assignable_roles) == 0:
|
||||
await ctx.send("There are no self-assignable roles on this server")
|
||||
return
|
||||
|
||||
fmt = ""
|
||||
for r in role:
|
||||
rid = str(r.id)
|
||||
try:
|
||||
self_assignable_roles.remove(rid)
|
||||
except ValueError:
|
||||
fmt += "\n{} is not a self-assignable role".format(r.name)
|
||||
else:
|
||||
fmt += "\n{} is no longer a self-assignable role".format(r.name)
|
||||
|
||||
update = {'self_assignable_roles': self_assignable_roles}
|
||||
await utils.update_content('server_settings', update, key)
|
||||
await ctx.send(fmt)
|
||||
|
||||
@assigns.command(name='me')
|
||||
@commands.guild_only()
|
||||
@commands.check(utils.is_owner)
|
||||
async def _me_assigns(self, ctx, *role: discord.Role):
|
||||
"""Assigns the provided role(s) to you, if they can be assigned
|
||||
|
||||
EXAMPLE: !assign me Member
|
||||
RESULT: You now have the Member role"""
|
||||
if not ctx.message.guild.me.guild_permissions.manage_roles:
|
||||
await ctx.send("I need to have manage roles permissions to assign roles")
|
||||
return
|
||||
|
||||
author = ctx.message.author
|
||||
key = str(ctx.message.guild.id)
|
||||
server_settings = await utils.get_content('server_settings', key)
|
||||
|
||||
if server_settings is None:
|
||||
await ctx.send("There are no self-assignable roles on this server")
|
||||
return
|
||||
self_assignable_roles = server_settings.get('self_assignable_roles', [])
|
||||
if len(self_assignable_roles) == 0:
|
||||
await ctx.send("There are no self-assignable roles on this server")
|
||||
return
|
||||
|
||||
fmt = ""
|
||||
roles = [r for r in role if str(r.id) in self_assignable_roles]
|
||||
fmt += "\n".join(["Successfully added {}".format(r.name)
|
||||
if str(r.id) in self_assignable_roles else
|
||||
"{} is not available to be self-assigned".format(r.name)
|
||||
for r in role])
|
||||
|
||||
try:
|
||||
await author.add_roles(*roles)
|
||||
await ctx.send(fmt)
|
||||
except discord.HTTPException:
|
||||
await ctx.send("I cannot assign roles to you {}".format(author.mention))
|
||||
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(Roles(bot))
|
||||
|
|
|
@ -245,7 +245,7 @@ class Stats:
|
|||
@commands.command()
|
||||
@commands.guild_only()
|
||||
@utils.custom_perms(send_messages=True)
|
||||
async def stats(self, ctx, member: discord.Member = None):
|
||||
async def battlestats(self, ctx, member: discord.Member = None):
|
||||
"""Prints the battling stats for you, or the user provided
|
||||
|
||||
EXAMPLE: !stats @OtherPerson
|
||||
|
|
Loading…
Reference in a new issue