- easy setup and get that wiki going | - easy setup and get that wiki going | ||||
### Big Changes | ### Big Changes | ||||
- All settings have been decentralised between servers and cogs. All changes to the settings have been moved to independant commands. This doesn't effect custom commands or warnings. | |||||
- All settings have been decentralised between servers and cogs. All changes to the settings have been moved to independant commands. This doesn't effect custom commands or warnings. | |||||
- is_anal setting is now depreciated.`;suck` and `;spank` now only work in channels marked NSFW. | |||||
- perm_roles setting is now depreciated. All commands will work of Discord's permission system. | |||||
### Regular Updates | ### Regular Updates | ||||
#### New Features | #### New Features |
# REMEMBER TO UNCOMMENT THE GSS LINE, ROXIE | # REMEMBER TO UNCOMMENT THE GSS LINE, ROXIE | ||||
# DO NOT UNCOMMENT GSS IF YOU ARE NOT ROXIE | # DO NOT UNCOMMENT GSS IF YOU ARE NOT ROXIE | ||||
cogs = [ | |||||
"roxbot.cogs.admin", | |||||
"roxbot.cogs.customcommands", | |||||
"roxbot.cogs.fun", | |||||
"roxbot.cogs.image", | |||||
"roxbot.cogs.joinleave", | |||||
"roxbot.cogs.nsfw", | |||||
"roxbot.cogs.reddit", | |||||
"roxbot.cogs.selfassign", | |||||
"roxbot.cogs.trivia", | |||||
"roxbot.cogs.twitch", | |||||
"roxbot.cogs.util", | |||||
"roxbot.cogs.voice", | |||||
#"roxbot.cogs.gss" | |||||
] | |||||
# Sets up Logging that discord.py does on its own | # Sets up Logging that discord.py does on its own | ||||
logger = logging.getLogger('discord') | logger = logging.getLogger('discord') | ||||
bot.load_extension("roxbot.system") | bot.load_extension("roxbot.system") | ||||
print("system.py Loaded") | print("system.py Loaded") | ||||
bot.load_extension("roxbot.settings.settings") | |||||
print("settings.py Loaded") | |||||
bot.load_extension("roxbot.err_handle") | bot.load_extension("roxbot.err_handle") | ||||
print("err_handle.py Loaded") | print("err_handle.py Loaded") | ||||
# Load Extension Cogs | # Load Extension Cogs | ||||
print("Cogs Loaded:") | print("Cogs Loaded:") | ||||
for cog in cogs: | |||||
for cog in roxbot.cogs: | |||||
try: | try: | ||||
bot.load_extension(cog) | bot.load_extension(cog) | ||||
print(cog.split(".")[2]) | print(cog.split(".")[2]) |
__version__ = "2.0.0a" | __version__ = "2.0.0a" | ||||
datetime_formatting = "{:%a %Y/%m/%d %H:%M:%S} UTC" | datetime_formatting = "{:%a %Y/%m/%d %H:%M:%S} UTC" | ||||
cogs = [ | |||||
"roxbot.cogs.admin", | |||||
"roxbot.cogs.customcommands", | |||||
"roxbot.cogs.fun", | |||||
"roxbot.cogs.image", | |||||
"roxbot.cogs.joinleave", | |||||
"roxbot.cogs.nsfw", | |||||
"roxbot.cogs.reddit", | |||||
"roxbot.cogs.selfassign", | |||||
"roxbot.cogs.trivia", | |||||
"roxbot.cogs.twitch", | |||||
"roxbot.cogs.util", | |||||
"roxbot.cogs.voice", | |||||
#"roxbot.cogs.gss" | |||||
] |
# TODO: Clean up this file. | # TODO: Clean up this file. | ||||
def is_owner_or_admin(): | |||||
def has_permission_or_owner(**perms): | |||||
def predicate(ctx): | def predicate(ctx): | ||||
if ctx.author.id == roxbot.owner: | if ctx.author.id == roxbot.owner: | ||||
return True | return True | ||||
elif isinstance(ctx.channel, discord.DMChannel): | |||||
return False | |||||
else: | |||||
for role in ctx.author.roles: | |||||
if role.id in gs.get(ctx.guild)["admin"]["admin_roles"]: | |||||
return True | |||||
return False | |||||
return commands.has_permissions(**perms) | |||||
return commands.check(predicate) | return commands.check(predicate) | ||||
def _is_admin_or_mod(ctx): | |||||
if ctx.message.author.id == roxbot.owner: | |||||
return True | |||||
elif isinstance(ctx.channel, discord.DMChannel): | |||||
return False | |||||
else: | |||||
admin_roles = gs.get(ctx.guild)["admin"]["admin_roles"] | |||||
mod_roles = gs.get(ctx.guild)["admin"]["mod_roles"] | |||||
for role in ctx.author.roles: | |||||
if role.id in mod_roles or role.id in admin_roles: | |||||
return True | |||||
return False | |||||
def is_admin_or_mod(): | |||||
return commands.check(_is_admin_or_mod) | |||||
def nsfw_predicate(ctx): | def nsfw_predicate(ctx): | ||||
if isinstance(ctx.channel, discord.DMChannel): | if isinstance(ctx.channel, discord.DMChannel): | ||||
return False | return False | ||||
def is_nfsw_enabled(): | def is_nfsw_enabled(): | ||||
return commands.check(lambda ctx: nsfw_predicate(ctx)) | return commands.check(lambda ctx: nsfw_predicate(ctx)) | ||||
def isnt_anal(): | |||||
def predicate(ctx): | |||||
if isinstance(ctx.channel, discord.DMChannel): | |||||
return False | |||||
anal = gs.get(ctx.guild)["admin"]["is_anal"] | |||||
if not anal or (nsfw_predicate(ctx) and gs.get(ctx.guild).is_anal["y/n"]): | |||||
return True | |||||
else: | |||||
return False | |||||
return commands.check(predicate) |
self.bot = bot_client | self.bot = bot_client | ||||
self.settings = { | self.settings = { | ||||
"admin": { | "admin": { | ||||
"convert": {"admin_roles": "role", "mod_roles": "role"}, | |||||
"convert": {"warnings": "hide"}, | |||||
"admin_roles": [], | "admin_roles": [], | ||||
"mod_roles": [], | "mod_roles": [], | ||||
"is_anal": 0, | "is_anal": 0, | ||||
"warnings": {}, | "warnings": {}, | ||||
}, | |||||
"logging": { | |||||
"enabled": 0, | |||||
"convert": {"enabled": "bool", "channel": "channel"}, | |||||
"channel": 0 | |||||
} | } | ||||
} | } | ||||
self.slow_mode = False | self.slow_mode = False | ||||
pass | pass | ||||
@commands.guild_only() | @commands.guild_only() | ||||
@roxbot.checks.is_admin_or_mod() | |||||
@commands.has_permissions(manage_messages=True) | |||||
@commands.bot_has_permissions(manage_messages=True) | @commands.bot_has_permissions(manage_messages=True) | ||||
@commands.command() | @commands.command() | ||||
async def slowmode(self, ctx, seconds): | async def slowmode(self, ctx, seconds): | ||||
"""Puts the current channel in slowmode. | |||||
"""Puts the current channel in slowmode. Requires the Manage Messages permission. | |||||
Usage: | Usage: | ||||
;slowmode [time/"off"] | ;slowmode [time/"off"] | ||||
seconds = number of seconds for the cooldown between messages a user has. | seconds = number of seconds for the cooldown between messages a user has. | ||||
@commands.cooldown(1, 5) | @commands.cooldown(1, 5) | ||||
@commands.command() | @commands.command() | ||||
async def purge(self, ctx, limit=0, *, author: roxbot.converters.User=None): | async def purge(self, ctx, limit=0, *, author: roxbot.converters.User=None): | ||||
"""Purges messages from the text channel. | |||||
"""Purges messages from the text channel. Requires the Manage Messages permission. | |||||
Limit = Limit of messages to be deleted | Limit = Limit of messages to be deleted | ||||
Author (optional) = If given, roxbot will selectively only delete this user's messages.""" | Author (optional) = If given, roxbot will selectively only delete this user's messages.""" | ||||
# TODO: To sort out the limit == how many to delete for the author, and not just a limit. | # TODO: To sort out the limit == how many to delete for the author, and not just a limit. | ||||
return await ctx.send(self.OK_PURGE_CONFIRMATION.format(len(messages))) | return await ctx.send(self.OK_PURGE_CONFIRMATION.format(len(messages))) | ||||
@commands.guild_only() | @commands.guild_only() | ||||
@roxbot.checks.is_admin_or_mod() | |||||
@commands.has_permissions(kick_members=True) | |||||
@commands.group(case_insensitive=True) | @commands.group(case_insensitive=True) | ||||
async def warn(self, ctx): | async def warn(self, ctx): | ||||
"""Group of commands handling warnings""" | |||||
"""Group of commands handling . Requires the Kick Members permission.""" | |||||
if ctx.invoked_subcommand is None: | if ctx.invoked_subcommand is None: | ||||
return await ctx.send('Missing Argument') | return await ctx.send('Missing Argument') | ||||
"""Adds a warning to a user.""" | """Adds a warning to a user.""" | ||||
# Warning in the settings is a dictionary of user ids. The user ids are equal to a list of dictionaries. | # Warning in the settings is a dictionary of user ids. The user ids are equal to a list of dictionaries. | ||||
settings = gs.get(ctx.guild) | settings = gs.get(ctx.guild) | ||||
warnings = settings["admin"]["warnings"] | |||||
warning_limit = 2 | warning_limit = 2 | ||||
warning_dict = { | warning_dict = { | ||||
"warned-by": ctx.author.id, | "warned-by": ctx.author.id, | ||||
} | } | ||||
user_id = str(user.id) | user_id = str(user.id) | ||||
if user_id not in settings.warnings: | |||||
settings.warnings[user_id] = [] | |||||
if user_id not in warnings: | |||||
warnings[user_id] = [] | |||||
warn_limit = 10 | warn_limit = 10 | ||||
if len(settings.warnings[user_id]) > warn_limit: | |||||
if len(warnings[user_id]) > warn_limit: | |||||
return await ctx.send(self.WARN_WARN_ADD_LIMIT_REACHED.format(warn_limit)) | return await ctx.send(self.WARN_WARN_ADD_LIMIT_REACHED.format(warn_limit)) | ||||
settings.warnings[user_id].append(warning_dict) | |||||
settings.update(settings.warnings, "warnings") | |||||
warnings[user_id].append(warning_dict) | |||||
settings["admin"]["warnings"] = warnings | |||||
settings.update(settings["admin"], "admin") | |||||
amount_warnings = len(settings.warnings[user_id]) | |||||
amount_warnings = len(warnings[user_id]) | |||||
if amount_warnings > warning_limit: | if amount_warnings > warning_limit: | ||||
await ctx.author.send(self.OK_WARN_ADD_USER_LIMIT_DM.format(str(user), amount_warnings, warning_limit)) | await ctx.author.send(self.OK_WARN_ADD_USER_LIMIT_DM.format(str(user), amount_warnings, warning_limit)) | ||||
async def list(self, ctx, *, user: roxbot.converters.User=None): | async def list(self, ctx, *, user: roxbot.converters.User=None): | ||||
"""Lists all or just the warnings for one user.""" | """Lists all or just the warnings for one user.""" | ||||
settings = gs.get(ctx.guild) | settings = gs.get(ctx.guild) | ||||
warnings = settings["admin"]["warnings"] | |||||
if user is None: | if user is None: | ||||
paginator = commands.Paginator() | paginator = commands.Paginator() | ||||
for member in settings.warnings: | |||||
for member in warnings: | |||||
# Remove users with no warning here instead of remove cause im lazy | # Remove users with no warning here instead of remove cause im lazy | ||||
if not settings.warnings[member]: | |||||
settings.warnings.pop(member) | |||||
if not warnings[member]: | |||||
warnings.pop(member) | |||||
else: | else: | ||||
member_obj = discord.utils.get(ctx.guild.members, id=int(member)) | member_obj = discord.utils.get(ctx.guild.members, id=int(member)) | ||||
if member_obj: | if member_obj: | ||||
paginator.add_line("{}: {} Warning(s)".format(str(member_obj), len(settings.warnings[member]))) | |||||
paginator.add_line("{}: {} Warning(s)".format(str(member_obj), len(warnings[member]))) | |||||
else: | else: | ||||
paginator.add_line("{}: {} Warning(s)".format(member, len(settings.warnings[member]))) | |||||
paginator.add_line("{}: {} Warning(s)".format(member, len(warnings[member]))) | |||||
settings["admin"]["warnings"] = warnings | |||||
settings.update(settings["admin"], "admin") | |||||
if len(paginator.pages) <= 0: | if len(paginator.pages) <= 0: | ||||
return await ctx.send(self.OK_WARN_LIST_NO_WARNINGS) | return await ctx.send(self.OK_WARN_LIST_NO_WARNINGS) | ||||
for page in paginator.pages: | for page in paginator.pages: | ||||
else: | else: | ||||
user_id = str(user.id) | user_id = str(user.id) | ||||
if not settings.warnings.get(user_id): | |||||
if not warnings.get(user_id): | |||||
return await ctx.send(self.OK_WARN_LIST_USER_NO_WARNINGS) | return await ctx.send(self.OK_WARN_LIST_USER_NO_WARNINGS) | ||||
if not settings.warnings[user_id]: | |||||
settings.warnings.pop(user_id) | |||||
settings.update(settings.warnings, "warnings") | |||||
em = discord.Embed(title="Warnings for {}".format(str(user)), colour=roxbot.EmbedColours.pink) | em = discord.Embed(title="Warnings for {}".format(str(user)), colour=roxbot.EmbedColours.pink) | ||||
em.set_thumbnail(url=user.avatar_url) | em.set_thumbnail(url=user.avatar_url) | ||||
x = 1 | x = 1 | ||||
userlist = settings.warnings[user_id] | |||||
userlist = warnings[user_id] | |||||
for warning in userlist: | for warning in userlist: | ||||
try: | try: | ||||
warned_by = str(await self.bot.get_user_info(warning["warned-by"])) | warned_by = str(await self.bot.get_user_info(warning["warned-by"])) | ||||
"""Removes one or all of the warnings for a user.""" | """Removes one or all of the warnings for a user.""" | ||||
user_id = str(user.id) | user_id = str(user.id) | ||||
settings = gs.get(ctx.guild) | settings = gs.get(ctx.guild) | ||||
warnings = settings["admin"]["warnings"] | |||||
if index: | if index: | ||||
try: | try: | ||||
index = int(index) | index = int(index) | ||||
index -= 1 | index -= 1 | ||||
settings.warnings[user_id].pop(index) | |||||
if not settings.warnings[user_id]: | |||||
settings.warnings.pop(user_id) | |||||
warnings[user_id].pop(index) | |||||
if not warnings[user_id]: | |||||
warnings.pop(user_id) | |||||
settings.update(settings.warnings, "warnings") | |||||
settings["admin"]["warnings"] = warnings | |||||
settings.update(settings["admin"], "admin") | |||||
return await ctx.send(self.OK_WARN_REMOVE_REMOVED_WARNING.format(index+1, str(user))) | return await ctx.send(self.OK_WARN_REMOVE_REMOVED_WARNING.format(index+1, str(user))) | ||||
except Exception as e: | except Exception as e: | ||||
if isinstance(e, IndexError): | if isinstance(e, IndexError): | ||||
return await ctx.send(self.ERROR_WARN_REMOVE_INDEXERROR.format(len(settings.warnings[user_id]))) | |||||
return await ctx.send(self.ERROR_WARN_REMOVE_INDEXERROR.format(len(settings["warnings"][user_id]))) | |||||
elif isinstance(e, KeyError): | elif isinstance(e, KeyError): | ||||
return await ctx.send(self.WARN_WARN_REMOVE_USER_NOT_FOUND.format(str(user))) | return await ctx.send(self.WARN_WARN_REMOVE_USER_NOT_FOUND.format(str(user))) | ||||
elif isinstance(e, ValueError): | elif isinstance(e, ValueError): | ||||
raise e | raise e | ||||
else: | else: | ||||
try: | try: | ||||
settings.warnings.pop(user_id) | |||||
settings.update(settings.warnings, "warnings") | |||||
warnings.pop(user_id) | |||||
settings["admin"]["warnings"] = warnings | |||||
settings.update(settings["admin"], "admin") | |||||
return await ctx.send(self.OK_WARN_REMOVE_REMOVED_WARNINGS.format(str(user))) | return await ctx.send(self.OK_WARN_REMOVE_REMOVED_WARNINGS.format(str(user))) | ||||
except KeyError: | except KeyError: | ||||
return await ctx.send(self.WARN_WARN_REMOVE_USER_NOT_FOUND.format(str(user))) | return await ctx.send(self.WARN_WARN_REMOVE_USER_NOT_FOUND.format(str(user))) | ||||
async def prune(self, ctx, dry_run=0): | async def prune(self, ctx, dry_run=0): | ||||
"""Purges banned users from the warn list. Add a 1 at the end to do a dry run.""" | """Purges banned users from the warn list. Add a 1 at the end to do a dry run.""" | ||||
settings = gs.get(ctx.guild) | settings = gs.get(ctx.guild) | ||||
warnings = settings.warnings.copy() | |||||
warnings = settings["admin"]["warnings"].copy() | |||||
count = 0 | count = 0 | ||||
for ban in await ctx.guild.bans(): | for ban in await ctx.guild.bans(): | ||||
for user in warnings: | for user in warnings: | ||||
if int(user) == ban.user.id: | if int(user) == ban.user.id: | ||||
if dry_run == 0: | if dry_run == 0: | ||||
settings.warnings.pop(user) | |||||
settings["admin"]["warnings"].pop(user) | |||||
count += 1 | count += 1 | ||||
settings.update(settings.warnings, "warnings") | |||||
settings.update(settings["admin"], "admin") | |||||
return await ctx.send(self.OK_WARN_PRUNE_PRUNED.format(count)) | return await ctx.send(self.OK_WARN_PRUNE_PRUNED.format(count)) | ||||
@commands.guild_only() | @commands.guild_only() | ||||
@commands.bot_has_permissions(kick_members=True) | @commands.bot_has_permissions(kick_members=True) | ||||
@commands.command() | @commands.command() | ||||
async def kick(self, ctx, member: discord.Member, *, reason=""): | async def kick(self, ctx, member: discord.Member, *, reason=""): | ||||
"""Kicks mentioned user. Allows you to give a reason.""" | |||||
"""Kicks mentioned user. Allows you to give a reason. Requires the Kick Members permission.""" | |||||
try: | try: | ||||
await member.kick(reason=reason) | await member.kick(reason=reason) | ||||
return await ctx.send(self.OK_MOD_ACTION.format("Kicked", member, reason)) | return await ctx.send(self.OK_MOD_ACTION.format("Kicked", member, reason)) | ||||
@commands.bot_has_permissions(ban_members=True) | @commands.bot_has_permissions(ban_members=True) | ||||
@commands.command() | @commands.command() | ||||
async def ban(self, ctx, member: discord.Member, *, reason=""): | async def ban(self, ctx, member: discord.Member, *, reason=""): | ||||
"""Bans mentioned user. Allows you to give a reason.""" | |||||
"""Bans mentioned user. Allows you to give a reason. Requires the Ban Members permission.""" | |||||
try: | try: | ||||
await member.ban(reason=reason, delete_message_days=0) | await member.ban(reason=reason, delete_message_days=0) | ||||
return await ctx.send(self.OK_MOD_ACTION.format("Banned", member, reason)) | return await ctx.send(self.OK_MOD_ACTION.format("Banned", member, reason)) | ||||
@commands.bot_has_permissions(ban_members=True) | @commands.bot_has_permissions(ban_members=True) | ||||
@commands.command() | @commands.command() | ||||
async def unban(self, ctx, member: roxbot.converters.User, *, reason=""): | async def unban(self, ctx, member: roxbot.converters.User, *, reason=""): | ||||
"""Unbans user with given ID. Allows you to give a reason.""" | |||||
"""Unbans user with given ID. Allows you to give a reason. Requires the Ban Members permission.""" | |||||
ban = await ctx.guild.get_ban(member) | ban = await ctx.guild.get_ban(member) | ||||
mem = ban.user | mem = ban.user | ||||
if mem is None: | if mem is None: | ||||
# TODO: For issues like this, make BadArgument a negative response embed not an error | |||||
return await ctx.send(self.WARN_UNBAN_NOTFOUND) | return await ctx.send(self.WARN_UNBAN_NOTFOUND) | ||||
try: | try: | ||||
await ctx.guild.unban(mem, reason=reason) | await ctx.guild.unban(mem, reason=reason) |
"custom_commands": { | "custom_commands": { | ||||
"0": {}, | "0": {}, | ||||
"1": {}, | "1": {}, | ||||
"2": {} | |||||
"2": {}, | |||||
"convert": {"0": "hide", "1": "hide", "2": "hide"} | |||||
} | } | ||||
} | } | ||||
command_output = self._get_output(settings["custom_commands"]["0"][command]) | command_output = self._get_output(settings["custom_commands"]["0"][command]) | ||||
return await channel.send(command_output) | return await channel.send(command_output) | ||||
@commands.has_permissions(manage_messages=True) | |||||
@commands.guild_only() | @commands.guild_only() | ||||
@commands.group(aliases=["cc"]) | @commands.group(aliases=["cc"]) | ||||
@roxbot.checks.is_owner_or_admin() | |||||
async def custom(self, ctx): | async def custom(self, ctx): | ||||
""""A group of commands to manage custom commands for your server.""" | |||||
"""" | |||||
A group of commands to manage custom commands for your server. | |||||
Requires the Manage Messages permission. | |||||
""" | |||||
if ctx.invoked_subcommand is None: | if ctx.invoked_subcommand is None: | ||||
return await ctx.send('Missing Argument') | return await ctx.send('Missing Argument') | ||||
response += '\n' | response += '\n' | ||||
return await ctx.send(response) | return await ctx.send(response) | ||||
@roxbot.checks.isnt_anal() | |||||
@commands.is_nsfw() | |||||
@commands.command() | @commands.command() | ||||
async def spank(self, ctx, *, user: discord.User = None): | async def spank(self, ctx, *, user: discord.User = None): | ||||
""" | """ | ||||
return await ctx.send("You didn't mention someone for me to spank") | return await ctx.send("You didn't mention someone for me to spank") | ||||
return await ctx.send(":peach: :wave: *{} spanks {}*".format(self.bot.user.name, user.name)) | return await ctx.send(":peach: :wave: *{} spanks {}*".format(self.bot.user.name, user.name)) | ||||
@roxbot.checks.isnt_anal() | |||||
@commands.is_nsfw() | |||||
@commands.command(aliases=["succ"]) | @commands.command(aliases=["succ"]) | ||||
async def suck(self, ctx, *, user: discord.User = None): | async def suck(self, ctx, *, user: discord.User = None): | ||||
""" | """ |
return ctx.send("Error, message roxie thanks.") | return ctx.send("Error, message roxie thanks.") | ||||
return await ctx.invoke(self.perms, role=arg) | return await ctx.invoke(self.perms, role=arg) | ||||
@commands.command() | |||||
async def gss(self, ctx, selection=None, *, changes=None): | |||||
"""Custom Cog for the GaySoundsShitposts Discord Server.""" | |||||
selection = selection.lower() | |||||
settings = roxbot.guild_settings.get(ctx.guild) | |||||
gss = settings["gss"] | |||||
if selection == "loggingchannel": | |||||
if ctx.message.channel_mentions: | |||||
channel = ctx.channel_mentions[0] | |||||
else: | |||||
channel = self.bot.get_channel(changes) | |||||
gss["log_channel"] = channel.id | |||||
await ctx.send("Logging Channel set to '{}'".format(channel.name)) | |||||
elif selection == "requireddays": | |||||
gss["required_days"] = int(changes) | |||||
await ctx.send("Required days set to '{}'".format(str(changes))) | |||||
elif selection == "requiredscore": | |||||
gss["required_score"] = int(changes) | |||||
await ctx.send("Required score set to '{}'".format(str(changes))) | |||||
else: | |||||
return await ctx.send("No valid option given.") | |||||
return settings.update(gss, "gss") | |||||
def setup(bot_client): | def setup(bot_client): | ||||
bot_client.add_cog(GaySoundsShitposts(bot_client)) | bot_client.add_cog(GaySoundsShitposts(bot_client)) |
""" | """ | ||||
import typing | |||||
import discord | import discord | ||||
from discord.ext import commands | |||||
import roxbot | import roxbot | ||||
from roxbot import guild_settings | from roxbot import guild_settings | ||||
return await channel.send(embed=discord.Embed( | return await channel.send(embed=discord.Embed( | ||||
description="{}#{} has left or been beaned.".format(member.name, member.discriminator), colour=roxbot.EmbedColours.pink)) | description="{}#{} has left or been beaned.".format(member.name, member.discriminator), colour=roxbot.EmbedColours.pink)) | ||||
@commands.has_permissions(manage_messages=True) | |||||
@commands.command() | |||||
async def greets(self, ctx, setting, channel: typing.Optional[discord.TextChannel] = None, *, text: str): | |||||
"""Edits settings for the Welcome Messages | |||||
Options: | |||||
enable/disable: Enable/disables parts of the cog. Needs to specify which part. | |||||
channel: Sets the channels for either option. Must be a ID or mention. | |||||
message: specifies a custom message for the greet messages. | |||||
""" | |||||
setting = setting.lower() | |||||
settings = guild_settings.get(ctx.guild) | |||||
greets = settings["greets"] | |||||
if setting == "enable": | |||||
greets["enabled"] = 1 | |||||
await ctx.send("'greets' was enabled!") | |||||
elif setting == "disable": | |||||
greets["enabled"] = 0 | |||||
await ctx.send("'greets' was disabled :cry:") | |||||
elif setting == "channel": | |||||
if channel is None: | |||||
channel = ctx.channel | |||||
greets["welcome-channel"] = channel.id | |||||
elif setting == "custommessage": | |||||
greets["custom-message"] = text | |||||
await ctx.send("Custom message set to '{}'".format(text)) | |||||
else: | |||||
return await ctx.send("No valid option given.") | |||||
return settings.update(greets, "greets") | |||||
@commands.has_permissions(manage_messages=True) | |||||
@commands.command() | |||||
async def goodbyes(self, ctx, setting, *, channel: typing.Optional[discord.TextChannel] = None): | |||||
"""Edits settings for the Welcome Messages | |||||
Options: | |||||
enable/disable: Enable/disables parts of the cog. Needs to specify which part. | |||||
channel: Sets the channels for either option. Must be a ID or mention. | |||||
message: specifies a custom message for the greet messages. | |||||
""" | |||||
setting = setting.lower() | |||||
settings = guild_settings.get(ctx.guild) | |||||
goodbyes = settings["goodbyes"] | |||||
if setting == "enable": | |||||
goodbyes["enabled"] = 1 | |||||
await ctx.send("'goodbyes' was enabled!") | |||||
elif setting == "disable": | |||||
goodbyes["enabled"] = 0 | |||||
await ctx.send("'goodbyes' was disabled :cry:") | |||||
elif setting == "channel": | |||||
if channel is None: | |||||
channel = ctx.channel | |||||
goodbyes["goodbye-channel"] = channel.id | |||||
else: | |||||
return await ctx.send("No valid option given.") | |||||
return settings.update(goodbyes, "goodbyes") | |||||
def setup(Bot): | def setup(Bot): | ||||
Bot.add_cog(JoinLeave(Bot)) | Bot.add_cog(JoinLeave(Bot)) |
""" | """ | ||||
import typing | |||||
import random | import random | ||||
import discord | import discord | ||||
from discord.ext import commands | from discord.ext import commands | ||||
def __init__(self, bot_client): | def __init__(self, bot_client): | ||||
self.bot = bot_client | self.bot = bot_client | ||||
self.cache = {} | self.cache = {} | ||||
self.settings = { | |||||
"nsfw": { | |||||
"enabled": 0, | |||||
"channels": [], | |||||
"convert": {"enabled": "bool", "channels": "channel"}, | |||||
"blacklist": [] | |||||
} | |||||
} | |||||
@roxbot.checks.is_nfsw_enabled() | @roxbot.checks.is_nfsw_enabled() | ||||
@commands.command(hidden=True) | @commands.command(hidden=True) | ||||
post_url = "https://simg3.gelbooru.com/images/" | post_url = "https://simg3.gelbooru.com/images/" | ||||
return await ctx.invoke(self.gelbooru_clone, base_url=base_url, post_url=post_url, tags=tags) | return await ctx.invoke(self.gelbooru_clone, base_url=base_url, post_url=post_url, tags=tags) | ||||
@commands.command() | |||||
async def nsfw(self, ctx, setting, channel: typing.Optional[discord.TextChannel] = None, *, changes=None): | |||||
"""Edits settings for the nsfw cog and other nsfw commands. | |||||
If nsfw is enabled and nsfw channels are added, the bot will only allow nsfw commands in the specified channels. | |||||
Options: | |||||
enable/disable: Enable/disables nsfw commands. | |||||
addchannel/removechannel: Adds/Removes a nsfw channel. | |||||
addbadtag/removebadtag: Add/Removes blacklisted tags so that you can avoid em with the commands. | |||||
Example: | |||||
;settings nsfw addchannel #nsfw_stuff | |||||
""" | |||||
setting = setting.lower() | |||||
settings = roxbot.guild_settings.get(ctx.guild) | |||||
nsfw = settings["nsfw"] | |||||
if setting == "enable": | |||||
nsfw["enabled"] = 1 | |||||
await ctx.send("'nsfw' was enabled!") | |||||
elif setting == "disable": | |||||
nsfw["enabled"] = 0 | |||||
await ctx.send("'nsfw' was disabled :cry:") | |||||
elif setting == "addchannel": | |||||
if not channel and not changes: | |||||
channel = ctx.channel | |||||
if channel.id not in nsfw["channels"]: | |||||
nsfw["channels"].append(channel.id) | |||||
await ctx.send("'{}' has been added to the nsfw channel list.".format(channel.name)) | |||||
else: | |||||
return await ctx.send("'{}' is already in the list.".format(channel.name)) | |||||
elif setting == "removechannel": | |||||
if not channel and not changes: | |||||
channel = ctx.channel | |||||
try: | |||||
nsfw["channels"].remove(channel.id) | |||||
await ctx.send("'{}' has been removed from the nsfw channel list.".format(channel.name)) | |||||
except ValueError: | |||||
return await ctx.send("That role was not in the list.") | |||||
elif setting == "addbadtag": | |||||
if changes not in nsfw["blacklist"]: | |||||
nsfw["blacklist"].append(changes) | |||||
await ctx.send("'{}' has been added to the blacklisted tag list.".format(changes)) | |||||
else: | |||||
return await ctx.send("'{}' is already in the list.".format(changes)) | |||||
elif setting == "removebadtag": | |||||
try: | |||||
nsfw["blacklist"].remove(changes) | |||||
await ctx.send("'{}' has been removed from the blacklisted tag list.".format(changes)) | |||||
except ValueError: | |||||
return await ctx.send("That tag was not in the blacklisted tag list.") | |||||
else: | |||||
return await ctx.send("No valid option given.") | |||||
return settings.update(nsfw, "nsfw") | |||||
def setup(bot_client): | def setup(bot_client): | ||||
bot_client.add_cog(NFSW(bot_client)) | bot_client.add_cog(NFSW(bot_client)) |
SOFTWARE. | SOFTWARE. | ||||
""" | """ | ||||
import discord | import discord | ||||
from discord.ext import commands | from discord.ext import commands | ||||
sa["roles"].remove(role.id) | sa["roles"].remove(role.id) | ||||
return settings.update(sa, "self_assign") | return settings.update(sa, "self_assign") | ||||
@commands.has_permissions(manage_roles=True) | |||||
@commands.guild_only() | |||||
@commands.command(aliases=["sa"]) | |||||
async def selfassign(self, ctx, setting, *, role: discord.Role): | |||||
"""Edits settings for self assign cog. Requires Manage Roles permission. | |||||
Options: | |||||
enable/disable: Enable/disables the cog. | |||||
add/remove: adds or removes a role that can be self assigned in the server. | |||||
""" | |||||
settings = roxbot.guild_settings.get(ctx.guild) | |||||
self_assign = settings["self_assign"] | |||||
setting = setting.lower() | |||||
if setting == "enable": | |||||
self_assign["enabled"] = 1 | |||||
await ctx.send("'self_assign' was enabled!") | |||||
elif setting == "disable": | |||||
self_assign["enabled"] = 0 | |||||
await ctx.send("'self_assign' was disabled :cry:") | |||||
elif setting == "add": | |||||
try: | |||||
if role.id in self_assign["roles"]: | |||||
return await ctx.send("{} is already a self-assignable role.".format(role.name)) | |||||
self_assign["roles"].append(role.id) | |||||
await ctx.send('Role "{}" added'.format(str(role))) | |||||
except AttributeError: | |||||
raise commands.BadArgument("Could not find that role.") | |||||
elif setting == "remove": | |||||
try: | |||||
if role.id in self_assign["roles"]: | |||||
self_assign["roles"].remove(role.id) | |||||
await ctx.send('"{}" has been removed from the self-assignable roles.'.format(str(role))) | |||||
else: | |||||
return await ctx.send("That role was not in the list.") | |||||
except AttributeError: | |||||
raise commands.BadArgument("Could not find that role.") | |||||
else: | |||||
return await ctx.send("No valid option given.") | |||||
return settings.update(self_assign, "self_assign") | |||||
@commands.guild_only() | @commands.guild_only() | ||||
@commands.command(pass_context=True) | @commands.command(pass_context=True) | ||||
async def listroles(self, ctx): | async def listroles(self, ctx): |
else: | else: | ||||
await ctx.send(embed=discord.Embed(description="Game isn't being played here.", colour=self.error_colour)) | await ctx.send(embed=discord.Embed(description="Game isn't being played here.", colour=self.error_colour)) | ||||
@checks.is_admin_or_mod() | |||||
@commands.has_permissions(manage_channels=True) | |||||
@trivia.command() | @trivia.command() | ||||
async def kick(self, ctx, user: discord.Member): | async def kick(self, ctx, user: discord.Member): | ||||
"""Mod command to kick users out of the game. Useful if a user is AFK.""" | |||||
"""Mod command to kick users out of the game. Useful if a user is AFK. Requires Manage Channels permission.""" | |||||
channel = ctx.channel | channel = ctx.channel | ||||
player = user | player = user | ||||
if channel.id in self.games: | if channel.id in self.games: |
""" | """ | ||||
from discord import ActivityType | |||||
import typing | |||||
import discord | |||||
from discord.ext import commands | from discord.ext import commands | ||||
import roxbot | import roxbot | ||||
return | return | ||||
if member_a.activitiy: | if member_a.activitiy: | ||||
if member_a.activity.type == ActivityType.streaming and member_b.activity.type != ActivityType.streaming: | |||||
if member_a.activity.type == discord.ActivityType.streaming and member_b.activity.type != discord.ActivityType.streaming: | |||||
if not twitch["whitelist"]["enabled"] or member_a.id in twitch["whitelist"]["list"]: | if not twitch["whitelist"]["enabled"] or member_a.id in twitch["whitelist"]["list"]: | ||||
channel = self.bot.get_channel(twitch["channel"]) | channel = self.bot.get_channel(twitch["channel"]) | ||||
return await channel.send(":video_game:** {} is live!** :video_game:\n{}\n{}".format( | return await channel.send(":video_game:** {} is live!** :video_game:\n{}\n{}".format( | ||||
member_a.name, member_a.game.name, member_a.game.url)) | member_a.name, member_a.game.name, member_a.game.url)) | ||||
@commands.group() | |||||
@roxbot.checks.is_admin_or_mod() | |||||
@commands.group(aliases=["wl"]) | |||||
@commands.has_permissions(manage_channels=True) | |||||
async def whitelist(self, ctx): | async def whitelist(self, ctx): | ||||
"""Command group that handles the twitch cog's whitelist.""" | """Command group that handles the twitch cog's whitelist.""" | ||||
if ctx.invoked_subcommand is None: | if ctx.invoked_subcommand is None: | ||||
elif option == 'list': | elif option == 'list': | ||||
return await ctx.send(settings["twitch"]["whitelist"]["list"]) | return await ctx.send(settings["twitch"]["whitelist"]["list"]) | ||||
@commands.has_permissions(manage_channels=True) | |||||
@commands.command() | |||||
async def twitch(self, ctx, setting, *, channel: discord.TextChannel = None): | |||||
"""Edits settings for self assign cog. | |||||
Options: | |||||
enable/disable: Enable/disables the cog. | |||||
channel: Sets the channel to shill in. | |||||
""" | |||||
setting = setting.lower() | |||||
settings = roxbot.guild_settings.get(ctx.guild) | |||||
twitch = settings["twitch"] | |||||
if setting == "enable": | |||||
twitch["enabled"] = 1 | |||||
await ctx.send("'twitch' was enabled!") | |||||
elif setting == "disable": | |||||
twitch["enabled"] = 0 | |||||
await ctx.send("'twitch' was disabled :cry:") | |||||
elif setting == "channel": | |||||
twitch["channel"] = channel.id | |||||
await ctx.send("{} has been set as the twitch shilling channel!".format(channel.mention)) | |||||
else: | |||||
return await ctx.send("No valid option given.") | |||||
return settings.update(twitch, "twitch") | |||||
def setup(bot_client): | def setup(bot_client): | ||||
bot_client.add_cog(Twitch(bot_client)) | bot_client.add_cog(Twitch(bot_client)) |
from discord.ext import commands | from discord.ext import commands | ||||
import roxbot | import roxbot | ||||
from roxbot import guild_settings | |||||
def _clear_cache(): | def _clear_cache(): | ||||
def volume_perms(): | def volume_perms(): | ||||
def predicate(ctx): | def predicate(ctx): | ||||
gs = guild_settings.get(ctx.guild) | |||||
gs = roxbot.guild_settings.get(ctx.guild) | |||||
if gs["voice"]["need_perms"]: # Had to copy the admin or mod code cause it wouldn't work ;-; | if gs["voice"]["need_perms"]: # Had to copy the admin or mod code cause it wouldn't work ;-; | ||||
if ctx.message.author.id == roxbot.owner: | if ctx.message.author.id == roxbot.owner: | ||||
return True | return True | ||||
embed.set_footer(text="{}/{} | Volume: {}%".format(time_played, duration, int(self.now_playing[guild.id].volume*100))) | embed.set_footer(text="{}/{} | Volume: {}%".format(time_played, duration, int(self.now_playing[guild.id].volume*100))) | ||||
return embed | return embed | ||||
@roxbot.checks.is_admin_or_mod() | |||||
@roxbot.checks.has_permission_or_owner(manage_channels=True) | |||||
@commands.guild_only() | @commands.guild_only() | ||||
@commands.command() | @commands.command() | ||||
async def join(self, ctx, *, channel: discord.VoiceChannel = None): | async def join(self, ctx, *, channel: discord.VoiceChannel = None): | ||||
async def play(self, ctx, *, url, stream=False, from_queue=False, queued_by=None): | async def play(self, ctx, *, url, stream=False, from_queue=False, queued_by=None): | ||||
"""Plays from a url or search query (almost anything youtube_dl supports)""" | """Plays from a url or search query (almost anything youtube_dl supports)""" | ||||
guild = ctx.guild | guild = ctx.guild | ||||
voice = guild_settings.get(guild).get("voice") | |||||
voice = roxbot.guild_settings.get(guild).get("voice") | |||||
# Checks if invoker is in voice with the bot. Skips admins and mods and owner and if the song was queued previously. | # Checks if invoker is in voice with the bot. Skips admins and mods and owner and if the song was queued previously. | ||||
if not (roxbot.checks._is_admin_or_mod(ctx) or from_queue): | if not (roxbot.checks._is_admin_or_mod(ctx) or from_queue): | ||||
@commands.guild_only() | @commands.guild_only() | ||||
@commands.command() | @commands.command() | ||||
async def skip(self, ctx, option=""): | async def skip(self, ctx, option=""): | ||||
"""Skips or votes to skip the current video. Use option "--force" if your an admin and """ | |||||
voice = guild_settings.get(ctx.guild)["voice"] | |||||
"""Skips or votes to skip the current video. Can use option "--force" if you have manage_channels permission. """ | |||||
voice = roxbot.guild_settings.get(ctx.guild)["voice"] | |||||
if ctx.voice_client.is_playing(): | if ctx.voice_client.is_playing(): | ||||
if voice["skip_voting"] and not (option == "--force" and roxbot.checks._is_admin_or_mod(ctx)): # Admin force skipping | |||||
if voice["skip_voting"] and not (option == "--force" and ctx.author.guild_permissions.manage_channels): # Admin force skipping | |||||
if ctx.author in self.skip_votes[ctx.guild.id]: | if ctx.author in self.skip_votes[ctx.guild.id]: | ||||
return await ctx.send("You have already voted to skip the current track.") | return await ctx.send("You have already voted to skip the current track.") | ||||
else: | else: | ||||
await ctx.send(embed=page) | await ctx.send(embed=page) | ||||
@commands.guild_only() | @commands.guild_only() | ||||
@roxbot.checks.is_admin_or_mod() | |||||
@commands.has_permissions(manage_channels=True) | |||||
@commands.command() | @commands.command() | ||||
async def remove(self, ctx, index): | async def remove(self, ctx, index): | ||||
"""Removes a item from the queue with the given index. Can also input all to delete all queued items.""" | |||||
"""Removes a item from the queue with the given index. Can also input all to delete all queued items. Requires the Manage Channels permission""" | |||||
# Try and convert index into an into. If not possible, just move forward | # Try and convert index into an into. If not possible, just move forward | ||||
try: | try: | ||||
index = int(index) | index = int(index) | ||||
raise commands.CommandError("Valid Index not given.") | raise commands.CommandError("Valid Index not given.") | ||||
@commands.guild_only() | @commands.guild_only() | ||||
@roxbot.checks.is_admin_or_mod() | |||||
@commands.has_permissions(manage_channels=True) | |||||
@commands.command(alaises=["disconnect"]) | @commands.command(alaises=["disconnect"]) | ||||
async def stop(self, ctx): | async def stop(self, ctx): | ||||
"""Stops and disconnects the bot from voice.""" | |||||
"""Stops and disconnects the bot from voice. Requires the Manage Channels permission""" | |||||
if ctx.voice_client is None: | if ctx.voice_client is None: | ||||
raise commands.CommandError("Roxbot is not in a voice channel.") | raise commands.CommandError("Roxbot is not in a voice channel.") | ||||
else: | else: | ||||
await ctx.voice_client.disconnect() | await ctx.voice_client.disconnect() | ||||
return await ctx.send(":wave:") | return await ctx.send(":wave:") | ||||
@commands.has_permissions(manage_channels=True) | |||||
@commands.command() | |||||
async def voice(self, ctx, setting=None, change=None): | |||||
"""Edits settings for the voice cog. Requires the Manage Channels permission | |||||
Options: | |||||
enable/disable: Enable/disables specified change. | |||||
skipratio: Specify what the ratio should be for skip voting if enabled. Example: 0.6 for 60% | |||||
maxlength/duration: Specify (in seconds) the max duration of a video that can be played. Ignored if staff of the server/bot owner. | |||||
Possible settings to enable/disable: | |||||
needperms: specifies whether volume controls and other bot functions need mod/admin perms. | |||||
skipvoting: specifies whether skipping should need over half of voice users to vote to skip. Bypassed by mods. | |||||
Example: | |||||
;settings voice enable skipvoting | |||||
""" | |||||
setting = setting.lower() | |||||
change = change.lower() | |||||
settings = roxbot.guild_settings.get(ctx.guild) | |||||
voice = settings["voice"] | |||||
if setting == "enable": | |||||
if change == "needperms": | |||||
voice["need_perms"] = 1 | |||||
await ctx.send("'{}' has been enabled!".format(change)) | |||||
elif change == "skipvoting": | |||||
voice["skip_voting"] = 1 | |||||
await ctx.send("'{}' has been enabled!".format(change)) | |||||
else: | |||||
return await ctx.send("Not a valid change.") | |||||
elif setting == "disable": | |||||
if change == "needperms": | |||||
voice["need_perms"] = 1 | |||||
await ctx.send("'{}' was disabled :cry:".format(change)) | |||||
elif change == "skipvoting": | |||||
voice["skip_voting"] = 1 | |||||
await ctx.send("'{}' was disabled :cry:".format(change)) | |||||
else: | |||||
return await ctx.send("Not a valid change.") | |||||
elif setting == "skipratio": | |||||
change = float(change) | |||||
if 1 > change > 0: | |||||
voice["skip_ratio"] = change | |||||
elif 0 < change <= 100: | |||||
change = change/10 | |||||
voice["skip_ratio"] = change | |||||
else: | |||||
return await ctx.send("Valid ratio not given.") | |||||
await ctx.send("Skip Ratio was set to {}".format(change)) | |||||
elif setting == "maxlength" or setting == "maxduration": | |||||
change = int(change) | |||||
if change >= 1: | |||||
voice["skip_ratio"] = change | |||||
else: | |||||
return await ctx.send("Valid max duration not given.") | |||||
await ctx.send("Max Duration was set to {}".format(change)) | |||||
else: | |||||
return await ctx.send("Valid option not given.") | |||||
return settings.update(voice, "voice") | |||||
def setup(bot_client): | def setup(bot_client): | ||||
bot_client.add_cog(Voice(bot_client)) | bot_client.add_cog(Voice(bot_client)) |
for key, setting in settings.items(): | for key, setting in settings.items(): | ||||
if setting.get("convert"): | if setting.get("convert"): | ||||
for x in setting["convert"].keys(): | for x in setting["convert"].keys(): | ||||
if setting["convert"][x] != "bool": | |||||
if setting["convert"][x] not in ("bool", "hide"): | |||||
if isinstance(setting[x], list): | if isinstance(setting[x], list): | ||||
for y, value in enumerate(setting[x]): | for y, value in enumerate(setting[x]): | ||||
if option == "str": | if option == "str": | ||||
""" | """ | ||||
Get latest settings, and update them with a change. | Get latest settings, and update them with a change. | ||||
:param changed_dict: | :param changed_dict: | ||||
:param setting: Setting should be a str of the setting key. If nothing is passed, it is assumed changed_dict is the settings file for the whole server. | |||||
:param setting: Setting should be a str of the setting key. | |||||
If nothing is passed, it is assumed changed_dict is the settings file for the whole server. | |||||
THIS IS NOT RECOMMENED. Always try and just pass the cogs settings and not a whole settings file. | |||||
:return: | :return: | ||||
""" | """ | ||||
self.settings = self.refresh() | self.settings = self.refresh() | ||||
settings = self.settings.copy() | |||||
if setting is not None: | if setting is not None: | ||||
self.settings[setting] = changed_dict | |||||
settings[setting] = changed_dict | |||||
elif isinstance(changed_dict, dict): | |||||
settings = changed_dict | |||||
elif isinstance(changed_dict, GuildSettings): | |||||
settings = changed_dict.settings | |||||
else: | else: | ||||
self.settings = changed_dict | |||||
settings = self.settings.copy() | |||||
self._convert(settings, "str") | |||||
raise TypeError("changed_dict can only be a dict or GuildSettings object.") | |||||
settings = self._convert(settings, "str") | |||||
_write_changes(self.id, self.cogs, settings) | _write_changes(self.id, self.cogs, settings) |
SOFTWARE. | SOFTWARE. | ||||
""" | """ | ||||
import typing | |||||
import discord | import discord | ||||
from discord.ext import commands | |||||
import roxbot | import roxbot | ||||
from roxbot import guild_settings | from roxbot import guild_settings | ||||
class Logging: | class Logging: | ||||
def __init__(self, bot_client): | def __init__(self, bot_client): | ||||
self.bot = bot_client | self.bot = bot_client | ||||
self.settings = { | |||||
"logging": { | |||||
"enabled": 0, | |||||
"convert": {"enabled": "bool", "channel": "channel"}, | |||||
"channel": 0 | |||||
} | |||||
} | |||||
async def on_member_join(self, member): | async def on_member_join(self, member): | ||||
logging = guild_settings.get(member.guild)["logging"] | logging = guild_settings.get(member.guild)["logging"] | ||||
embed = discord.Embed(description="{} left the server".format(member), colour=roxbot.EmbedColours.pink) | embed = discord.Embed(description="{} left the server".format(member), colour=roxbot.EmbedColours.pink) | ||||
return await channel.send(embed=embed) | return await channel.send(embed=embed) | ||||
@commands.guild_only() | |||||
@commands.command(aliases=["log"]) | |||||
async def logging(self, ctx, setting, *, channel: typing.Optional[discord.TextChannel] = None): | |||||
"""Edits the logging settings. | |||||
Options: | |||||
enable/disable: Enable/disables logging. | |||||
channel: sets the channel. | |||||
""" | |||||
setting = setting.lower() | |||||
settings = guild_settings.get(ctx.guild) | |||||
if setting == "enable": | |||||
settings["logging"]["enabled"] = 1 | |||||
await ctx.send("'logging' was enabled!") | |||||
elif setting == "disable": | |||||
settings["logging"]["enabled"] = 0 | |||||
await ctx.send("'logging' was disabled :cry:") | |||||
elif setting == "channel": | |||||
if not channel: | |||||
channel = ctx.channel | |||||
settings["logging"]["channel"] = channel.id | |||||
await ctx.send("{} has been set as the logging channel!".format(channel.mention)) | |||||
else: | |||||
return await ctx.send("No valid option given.") | |||||
return settings.update(settings["logging"], "logging") | |||||
def setup(bot_client): | def setup(bot_client): | ||||
bot_client.add_cog(Logging(bot_client)) | bot_client.add_cog(Logging(bot_client)) |
# Ignore everything in this directory | |||||
* | |||||
# Except this file | |||||
!.gitignore |
# -*- coding: utf-8 -*- | |||||
""" | |||||
MIT License | |||||
Copyright (c) 2017-2018 Roxanne Gibson | |||||
Permission is hereby granted, free of charge, to any person obtaining a copy | |||||
of this software and associated documentation files (the "Software"), to deal | |||||
in the Software without restriction, including without limitation the rights | |||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||||
copies of the Software, and to permit persons to whom the Software is | |||||
furnished to do so, subject to the following conditions: | |||||
The above copyright notice and this permission notice shall be included in all | |||||
copies or substantial portions of the Software. | |||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||||
SOFTWARE. | |||||
""" | |||||
import discord | |||||
from discord.ext import commands | |||||
from roxbot import checks, guild_settings, EmbedColours | |||||
class Settings: | |||||
""" | |||||
Settings is a mix of settings and admin stuff for the bot. OWNER OR ADMIN ONLY. | |||||
""" | |||||
def __init__(self, bot_client): | |||||
self.bot = bot_client | |||||
def get_channel(self, ctx, channel): | |||||
if ctx.message.channel_mentions: | |||||
return ctx.message.channel_mentions[0] | |||||
else: | |||||
return self.bot.get_channel(channel) | |||||
def parse_setting(self, ctx, settings_to_copy, raw=False): | |||||
settingcontent = "" | |||||
setting = settings_to_copy.copy() | |||||
convert = setting.get("convert", None) | |||||
if convert is not None and not raw: | |||||
for x in convert.keys(): | |||||
if convert[x] == "bool": | |||||
if setting[x] == 0: | |||||
setting[x] = "False" | |||||
else: | |||||
setting[x] = "True" | |||||
elif convert[x] == "channel": | |||||
if isinstance(setting[x], list): | |||||
if len(setting[x]) >= 60: | |||||
setting[x] = "There is too many channels to display." | |||||
else: | |||||
new_channels = [] | |||||
for channel in setting[x]: | |||||
try: | |||||
new_channels.append(self.bot.get_channel(channel).mention) | |||||
except AttributeError: | |||||
new_channels.append(channel) | |||||
setting[x] = new_channels | |||||
else: | |||||
try: | |||||
setting[x] = self.bot.get_channel(setting[x]).mention | |||||
except AttributeError: | |||||
pass | |||||
elif convert[x] == "role": | |||||
if isinstance(setting[x], list): | |||||
if len(setting[x]) >= 60: | |||||
setting[x] = "There is too many roles to display." | |||||
else: | |||||
new_roles = [] | |||||
for role_id in setting[x]: | |||||
try: | |||||
new_roles.append(discord.utils.get(ctx.guild.roles, id=role_id).name) | |||||
except AttributeError: | |||||
new_roles.append(role_id) | |||||
setting[x] = new_roles | |||||
else: | |||||
try: | |||||
setting[x] = discord.utils.get(ctx.guild.roles, id=setting[x]).name | |||||
except AttributeError: | |||||
pass | |||||
elif convert[x] == "user": | |||||
if isinstance(setting[x], list): | |||||
if len(setting[x]) >= 60: | |||||
setting[x] = "There is too many users to display." | |||||
else: | |||||
new_users = [] | |||||
for user_id in setting[x]: | |||||
user = self.bot.get_user(user_id) | |||||
if user is None: | |||||
new_users.append(str(user_id)) | |||||
else: | |||||
new_users.append(str(user)) | |||||
setting[x] = new_users | |||||
else: | |||||
user = self.bot.get_user(setting[x]) | |||||
if user is None: | |||||
setting[x] = str(setting[x]) | |||||
else: | |||||
setting[x] = str(user) | |||||
elif convert[x] == "hide": | |||||
setting[x] = "This is hidden. Please use other commands to get this data." | |||||
for x in setting.items(): | |||||
if x[0] != "convert": | |||||
settingcontent += str(x).strip("()") + "\n" | |||||
return settingcontent | |||||
@commands.command(aliases=["printsettingsraw"]) | |||||
@checks.is_admin_or_mod() | |||||
async def printsettings(self, ctx, option=None): | |||||
"""OWNER OR ADMIN ONLY: Prints the servers settings file.""" | |||||
# TODO: Use paginator to make the output here not break all the time. | |||||
config = guild_settings.get(ctx.guild) | |||||
settings = dict(config.settings.copy()) # Make a copy of settings so we don't change the actual settings. | |||||
paginator = commands.Paginator(prefix="```md") | |||||
paginator.add_line("{} settings for {}.\n".format(self.bot.user.name, ctx.message.guild.name)) | |||||
if option in settings: | |||||
raw = bool(ctx.invoked_with == "printsettingsraw") | |||||
settingcontent = self.parse_setting(ctx, settings[option], raw=raw) | |||||
paginator.add_line("**{}**".format(option)) | |||||
paginator.add_line(settingcontent) | |||||
for page in paginator.pages: | |||||
await ctx.send(page) | |||||
else: | |||||
for setting in settings: | |||||
if setting != "custom_commands" and setting != "warnings": | |||||
raw = bool(ctx.invoked_with == "printsettingsraw") | |||||
settingcontent = self.parse_setting(ctx, settings[setting], raw=raw) | |||||
paginator.add_line("**{}**".format(setting)) | |||||
paginator.add_line(settingcontent) | |||||
for page in paginator.pages: | |||||
await ctx.send(page) | |||||
@commands.group(case_insensitive=True) | |||||
@checks.is_admin_or_mod() | |||||
async def settings(self, ctx): | |||||
self.guild_settings = guild_settings.get(ctx.guild) | |||||
@settings.command(aliases=["log"]) | |||||
async def logging(self, ctx, selection=None, *, changes=None): | |||||
"""Edits the logging settings. | |||||
Options: | |||||
enable/disable: Enable/disables logging. | |||||
channel: sets the channel. | |||||
""" | |||||
selection = selection.lower() | |||||
settings = guild_settings.get(ctx.guild) | |||||
if selection == "enable": | |||||
settings.logging["enabled"] = 1 | |||||
await ctx.send("'logging' was enabled!") | |||||
elif selection == "disable": | |||||
settings.logging["enabled"] = 0 | |||||
await ctx.send("'logging' was disabled :cry:") | |||||
elif selection == "channel": | |||||
channel = self.get_channel(ctx, changes) | |||||
settings.logging["channel"] = channel.id | |||||
await ctx.send("{} has been set as the logging channel!".format(channel.mention)) | |||||
else: | |||||
return await ctx.send("No valid option given.") | |||||
return self.guild_settings.update(settings.logging, "logging") | |||||
@settings.command(aliases=["sa"]) | |||||
async def selfassign(self, ctx, selection=None, *, changes=None): | |||||
"""Edits settings for self assign cog. | |||||
Options: | |||||
enable/disable: Enable/disables the cog. | |||||
addrole/removerole: adds or removes a role that can be self assigned in the server. | |||||
""" | |||||
selection = selection.lower() | |||||
role = discord.utils.find(lambda u: u.name == changes, ctx.message.guild.roles) | |||||
self_assign = self.guild_settings.self_assign | |||||
if selection == "enable": | |||||
self_assign["enabled"] = 1 | |||||
await ctx.send("'self_assign' was enabled!") | |||||
elif selection == "disable": | |||||
self_assign["enabled"] = 0 | |||||
await ctx.send("'self_assign' was disabled :cry:") | |||||
elif selection == "addrole": | |||||
try: | |||||
if role.id in self_assign["roles"]: | |||||
return await ctx.send("{} is already a self-assignable role.".format(role.name)) | |||||
self_assign["roles"].append(role.id) | |||||
await ctx.send('Role "{}" added'.format(str(role))) | |||||
except AttributeError: | |||||
return await ctx.send("Role param incorrect. Check you spelt it correctly") | |||||
elif selection == "removerole": | |||||
try: | |||||
if role.id in self_assign["roles"]: | |||||
self_assign["roles"].remove(role.id) | |||||
await ctx.send('"{}" has been removed from the self-assignable roles.'.format(str(role))) | |||||
else: | |||||
return await ctx.send("That role was not in the list.") | |||||
except AttributeError: | |||||
return await ctx.send("Role param incorrect. Check you spelt it correctly") | |||||
else: | |||||
return await ctx.send("No valid option given.") | |||||
return self.guild_settings.update(self_assign, "self_assign") | |||||
@settings.command(aliases=["jl"]) | |||||
async def joinleave(self, ctx, selection=None, *, changes=None): | |||||
"""Edits settings for joinleave cog. | |||||
Options: | |||||
enable/disable: Enable/disables parts of the cog. Needs to specify which part. | |||||
Example: | |||||
;settings joinleave enable greets|goodbyes | |||||
greetschannel/goodbyeschannel: Sets the channels for either option. Must be a ID or mention. | |||||
custommessage: specifies a custom message for the greet messages. | |||||
""" | |||||
selection = selection.lower() | |||||
channel = self.get_channel(ctx, changes) | |||||
greets = self.guild_settings.greets | |||||
goodbyes = self.guild_settings.goodbyes | |||||
if selection == "greets": | |||||
if changes == "enable": | |||||
greets["enabled"] = 1 | |||||
await ctx.send("'greets' was enabled!") | |||||
elif changes == "disable": | |||||
greets["enabled"] = 0 | |||||
await ctx.send("'greets' was disabled :cry:") | |||||
elif selection == "goodbyes": | |||||
if changes == "enable": | |||||
goodbyes["enabled"] = 1 | |||||
await ctx.send("'goodbyes' was enabled!") | |||||
elif changes == "disable": | |||||
goodbyes["enabled"] = 0 | |||||
await ctx.send("'goodbyes' was disabled :cry:") | |||||
else: | |||||
if selection == "greetschannel": | |||||
greets["welcome-channel"] = channel.id | |||||
changes = "greets" | |||||
await ctx.send("{} has been set as the welcome channel!".format(channel.mention)) | |||||
elif selection == "goodbyeschannel": | |||||
goodbyes["goodbye-channel"] = channel.id | |||||
changes = "goodbyes" | |||||
await ctx.send("{} has been set as the goodbye channel!".format(channel.mention)) | |||||
elif selection == "custommessage": | |||||
greets["custom-message"] = changes | |||||
await ctx.send("Custom message set to '{}'".format(changes)) | |||||
changes = "greets" | |||||
else: | |||||
return await ctx.send("No valid option given.") | |||||
if changes == "greets": | |||||
return self.guild_settings.update(greets, "greets") | |||||
elif changes == "goodbyes": | |||||
return self.guild_settings.update(goodbyes, "goodbyes") | |||||
@settings.command() | |||||
async def twitch(self, ctx, selection=None, *, changes=None): | |||||
"""Edits settings for self assign cog. | |||||
Options: | |||||
enable/disable: Enable/disables the cog. | |||||
channel: Sets the channel to shill in. | |||||
""" | |||||
# TODO: Menu also needs editing since I edited the twitch backend | |||||
selection = selection.lower() | |||||
twitch = self.guild_settings.twitch | |||||
if selection == "enable": | |||||
twitch["enabled"] = 1 | |||||
await ctx.send("'twitch' was enabled!") | |||||
elif selection == "disable": | |||||
twitch["enabled"] = 0 | |||||
await ctx.send("'twitch' was disabled :cry:") | |||||
elif selection == "channel": | |||||
channel = self.get_channel(ctx, changes) | |||||
twitch["channel"] = channel.id | |||||
await ctx.send("{} has been set as the twitch shilling channel!".format(channel.mention)) | |||||
# Is lacking whitelist options. Might be added or might be depreciated. | |||||
# Turns out this is handled in the cog and I don't think it needs changing but may be confusing. | |||||
else: | |||||
return await ctx.send("No valid option given.") | |||||
return self.guild_settings.update(twitch, "twitch") | |||||
@settings.command(aliases=["perms"]) | |||||
async def permrole(self, ctx, selection=None, *, changes=None): | |||||
"""Edits settings for permission roles. | |||||
Options: | |||||
addadmin/removeadmin: Adds/Removes admin role. | |||||
addmod/removemod: Adds/Removes mod role. | |||||
Example: | |||||
;settings permrole addadmin Admin | |||||
""" | |||||
selection = selection.lower() | |||||
role = discord.utils.find(lambda u: u.name == changes, ctx.message.guild.roles) | |||||
perm_roles = self.guild_settings.perm_roles | |||||
if selection == "addadmin": | |||||
if role.id not in perm_roles["admin"]: | |||||
perm_roles["admin"].append(role.id) | |||||
await ctx.send("'{}' has been added to the Admin role list.".format(role.name)) | |||||
else: | |||||
return await ctx.send("'{}' is already in the list.".format(role.name)) | |||||
elif selection == "addmod": | |||||
if role.id not in perm_roles["mod"]: | |||||
perm_roles["mod"].append(role.id) | |||||
await ctx.send("'{}' has been added to the Mod role list.".format(role.name)) | |||||
else: | |||||
return await ctx.send("'{}' is already in the list.".format(role.name)) | |||||
elif selection == "removeadmin": | |||||
try: | |||||
perm_roles["admin"].remove(role.id) | |||||
await ctx.send("'{}' has been removed from the Admin role list.".format(role.name)) | |||||
except ValueError: | |||||
return await ctx.send("That role was not in the list.") | |||||
elif selection == "removemod": | |||||
try: | |||||
perm_roles["mod"].remove(role.id) | |||||
await ctx.send("'{}' has been removed from the Mod role list.".format(role.name)) | |||||
except ValueError: | |||||
return await ctx.send("That role was not in the list.") | |||||
else: | |||||
return await ctx.send("No valid option given.") | |||||
return self.guild_settings.update(perm_roles, "perm_roles") | |||||
@settings.command() | |||||
async def gss(self, ctx, selection=None, *, changes=None): | |||||
"""Custom Cog for the GaySoundsShitposts Discord Server.""" | |||||
# TODO: Menu | |||||
selection = selection.lower() | |||||
gss = self.guild_settings.gss | |||||
if selection == "loggingchannel": | |||||
channel = self.get_channel(ctx, changes) | |||||
gss["log_channel"] = channel.id | |||||
await ctx.send("Logging Channel set to '{}'".format(channel.name)) | |||||
elif selection == "requireddays": | |||||
gss["required_days"] = int(changes) | |||||
await ctx.send("Required days set to '{}'".format(str(changes))) | |||||
elif selection == "requiredscore": | |||||
gss["required_score"] = int(changes) | |||||
await ctx.send("Required score set to '{}'".format(str(changes))) | |||||
else: | |||||
return await ctx.send("No valid option given.") | |||||
return self.guild_settings.update(gss, "gss") | |||||
@settings.command() | |||||
async def nsfw(self, ctx, selection=None, *, changes=None): | |||||
"""Edits settings for the nsfw cog and other nsfw commands. | |||||
If nsfw is enabled and nsfw channels are added, the bot will only allow nsfw commands in the specified channels. | |||||
Options: | |||||
enable/disable: Enable/disables nsfw commands. | |||||
addchannel/removechannel: Adds/Removes a nsfw channel. | |||||
addbadtag/removebadtag: Add/Removes blacklisted tags so that you can avoid em with the commands. | |||||
Example: | |||||
;settings nsfw addchannel #nsfw_stuff | |||||
""" | |||||
#menu = Menu.nsfw(ctx.guild) | |||||
#print(menu.content) | |||||
selection = selection.lower() | |||||
nsfw = self.guild_settings.nsfw | |||||
if selection == "enable": | |||||
nsfw["enabled"] = 1 | |||||
await ctx.send("'nsfw' was enabled!") | |||||
elif selection == "disable": | |||||
nsfw["enabled"] = 0 | |||||
await ctx.send("'nsfw' was disabled :cry:") | |||||
elif selection == "addchannel": | |||||
channel = self.get_channel(ctx, changes) | |||||
if channel.id not in nsfw["channels"]: | |||||
nsfw["channels"].append(channel.id) | |||||
await ctx.send("'{}' has been added to the nsfw channel list.".format(channel.name)) | |||||
else: | |||||
return await ctx.send("'{}' is already in the list.".format(channel.name)) | |||||
elif selection == "removechannel": | |||||
channel = self.get_channel(ctx, changes) | |||||
try: | |||||
nsfw["channels"].remove(channel.id) | |||||
await ctx.send("'{}' has been removed from the nsfw channel list.".format(channel.name)) | |||||
except ValueError: | |||||
return await ctx.send("That role was not in the list.") | |||||
elif selection == "addbadtag": | |||||
if changes not in nsfw["blacklist"]: | |||||
nsfw["blacklist"].append(changes) | |||||
await ctx.send("'{}' has been added to the blacklisted tag list.".format(changes)) | |||||
else: | |||||
return await ctx.send("'{}' is already in the list.".format(changes)) | |||||
elif selection == "removebadtag": | |||||
try: | |||||
nsfw["blacklist"].remove(changes) | |||||
await ctx.send("'{}' has been removed from the blacklisted tag list.".format(changes)) | |||||
except ValueError: | |||||
return await ctx.send("That tag was not in the blacklisted tag list.") | |||||
else: | |||||
return await ctx.send("No valid option given.") | |||||
return self.guild_settings.update(nsfw, "nsfw") | |||||
@settings.command() | |||||
async def voice(self, ctx, setting=None, change=None): | |||||
"""Edits settings for the voice cog. | |||||
Options: | |||||
enable/disable: Enable/disables specified change. | |||||
skipratio: Specify what the ratio should be for skip voting if enabled. Example: 0.6 for 60% | |||||
maxlength/duration: Specify (in seconds) the max duration of a video that can be played. Ignored if staff of the server/bot owner. | |||||
Possible settings to enable/disable: | |||||
needperms: specifies whether volume controls and other bot functions need mod/admin perms. | |||||
skipvoting: specifies whether skipping should need over half of voice users to vote to skip. Bypassed by mods. | |||||
Example: | |||||
;settings voice enable skipvoting | |||||
""" | |||||
setting = setting.lower() | |||||
change = change.lower() | |||||
voice = self.guild_settings.voice | |||||
if setting == "enable": | |||||
if change == "needperms": | |||||
voice["need_perms"] = 1 | |||||
await ctx.send("'{}' has been enabled!".format(change)) | |||||
elif change == "skipvoting": | |||||
voice["skip_voting"] = 1 | |||||
await ctx.send("'{}' has been enabled!".format(change)) | |||||
else: | |||||
return await ctx.send("Not a valid change.") | |||||
elif setting == "disable": | |||||
if change == "needperms": | |||||
voice["need_perms"] = 1 | |||||
await ctx.send("'{}' was disabled :cry:".format(change)) | |||||
elif change == "skipvoting": | |||||
voice["skip_voting"] = 1 | |||||
await ctx.send("'{}' was disabled :cry:".format(change)) | |||||
else: | |||||
return await ctx.send("Not a valid change.") | |||||
elif setting == "skipratio": | |||||
change = float(change) | |||||
if 1 > change > 0: | |||||
voice["skip_ratio"] = change | |||||
elif 0 < change <= 100: | |||||
change = change/10 | |||||
voice["skip_ratio"] = change | |||||
else: | |||||
return await ctx.send("Valid ratio not given.") | |||||
await ctx.send("Skip Ratio was set to {}".format(change)) | |||||
elif setting == "maxlength" or setting == "maxduration": | |||||
change = int(change) | |||||
if change >= 1: | |||||
voice["skip_ratio"] = change | |||||
else: | |||||
return await ctx.send("Valid max duration not given.") | |||||
await ctx.send("Max Duration was set to {}".format(change)) | |||||
else: | |||||
return await ctx.send("Valid option not given.") | |||||
return self.guild_settings.update(voice, "voice") | |||||
@commands.guild_only() | |||||
@checks.is_admin_or_mod() | |||||
@commands.command() | |||||
async def serverisanal(self, ctx): | |||||
"""Tells the bot where the server is anal or not. | |||||
This only changes if roxbot can do the suck and spank commands outside of the specified nsfw channels.""" | |||||
gs = guild_settings.get(ctx.guild) | |||||
is_anal = gs.is_anal | |||||
if is_anal["y/n"] == 0: | |||||
is_anal["y/n"] = 1 | |||||
gs.update(is_anal, "is_anal") | |||||
await ctx.send("I now know this server is anal") | |||||
else: | |||||
is_anal["y/n"] = 0 | |||||
gs.update(is_anal, "is_anal") | |||||
await ctx.send("I now know this server is NOT anal") | |||||
def setup(bot_client): | |||||
bot_client.add_cog(Settings(bot_client)) |
await self.bot.change_presence(status=discord_status) | await self.bot.change_presence(status=discord_status) | ||||
await ctx.send("**:ok:** Status set to {}".format(discord_status)) | await ctx.send("**:ok:** Status set to {}".format(discord_status)) | ||||
def parse_setting(self, ctx, settings_to_copy, raw=False): | |||||
settingcontent = "" | |||||
setting = settings_to_copy.copy() | |||||
convert = setting.get("convert", None) | |||||
if convert is not None and not raw: | |||||
for x in convert.keys(): | |||||
if convert[x] == "bool": | |||||
if setting[x] == 0: | |||||
setting[x] = "False" | |||||
else: | |||||
setting[x] = "True" | |||||
elif convert[x] == "channel": | |||||
if isinstance(setting[x], list): | |||||
if len(setting[x]) >= 60: | |||||
setting[x] = "There is too many channels to display." | |||||
else: | |||||
new_channels = [] | |||||
for channel in setting[x]: | |||||
try: | |||||
new_channels.append(self.bot.get_channel(channel).mention) | |||||
except AttributeError: | |||||
new_channels.append(channel) | |||||
setting[x] = new_channels | |||||
else: | |||||
try: | |||||
setting[x] = self.bot.get_channel(setting[x]).mention | |||||
except AttributeError: | |||||
pass | |||||
elif convert[x] == "role": | |||||
if isinstance(setting[x], list): | |||||
if len(setting[x]) >= 60: | |||||
setting[x] = "There is too many roles to display." | |||||
else: | |||||
new_roles = [] | |||||
for role_id in setting[x]: | |||||
try: | |||||
new_roles.append(discord.utils.get(ctx.guild.roles, id=role_id).name) | |||||
except AttributeError: | |||||
new_roles.append(role_id) | |||||
setting[x] = new_roles | |||||
else: | |||||
try: | |||||
setting[x] = discord.utils.get(ctx.guild.roles, id=setting[x]).name | |||||
except AttributeError: | |||||
pass | |||||
elif convert[x] == "user": | |||||
if isinstance(setting[x], list): | |||||
if len(setting[x]) >= 60: | |||||
setting[x] = "There is too many users to display." | |||||
else: | |||||
new_users = [] | |||||
for user_id in setting[x]: | |||||
user = self.bot.get_user(user_id) | |||||
if user is None: | |||||
new_users.append(str(user_id)) | |||||
else: | |||||
new_users.append(str(user)) | |||||
setting[x] = new_users | |||||
else: | |||||
user = self.bot.get_user(setting[x]) | |||||
if user is None: | |||||
setting[x] = str(setting[x]) | |||||
else: | |||||
setting[x] = str(user) | |||||
elif convert[x] == "hide": | |||||
setting[x] = "This is hidden. Please use other commands to get this data." | |||||
for x in setting.items(): | |||||
if x[0] != "convert": | |||||
settingcontent += str(x).strip("()") + "\n" | |||||
return settingcontent | |||||
@commands.command(aliases=["printsettingsraw"]) | |||||
@commands.has_permissions(manage_guild=True) | |||||
async def printsettings(self, ctx, option=None): | |||||
"""OWNER OR ADMIN ONLY: Prints the servers settings file.""" | |||||
config = roxbot.guild_settings.get(ctx.guild) | |||||
settings = dict(config.settings.copy()) # Make a copy of settings so we don't change the actual settings. | |||||
paginator = commands.Paginator(prefix="```md") | |||||
paginator.add_line("{} settings for {}.\n".format(self.bot.user.name, ctx.message.guild.name)) | |||||
if option in settings: | |||||
raw = bool(ctx.invoked_with == "printsettingsraw") | |||||
settingcontent = self.parse_setting(ctx, settings[option], raw=raw) | |||||
paginator.add_line("**{}**".format(option)) | |||||
paginator.add_line(settingcontent) | |||||
for page in paginator.pages: | |||||
await ctx.send(page) | |||||
else: | |||||
for setting in settings: | |||||
raw = bool(ctx.invoked_with == "printsettingsraw") | |||||
settingcontent = self.parse_setting(ctx, settings[setting], raw=raw) | |||||
paginator.add_line("**{}**".format(setting)) | |||||
paginator.add_line(settingcontent) | |||||
for page in paginator.pages: | |||||
await ctx.send(page) | |||||
@commands.command() | @commands.command() | ||||
@commands.is_owner() | @commands.is_owner() | ||||
async def shutdown(self, ctx): | async def shutdown(self, ctx): |