### Regular Updates | ### Regular Updates | ||||
#### New Features | #### New Features | ||||
- Roxbot will remove all redundant settings (removed roles from self assign, etc.). | |||||
- Cogs have a message if they fail to load. This is better than the entire program breaking. | |||||
- Roxbot Facts! | |||||
#### Minor Changes | #### Minor Changes | ||||
- Roxbot will remove all redundant settings (removed roles from self assign, etc.). | |||||
- Cogs have a message if they fail to load instead of breaking entire bot. | |||||
- NSFW commands should have even less chance of dupes. | - NSFW commands should have even less chance of dupes. | ||||
- All time formatting is now standardised. | - All time formatting is now standardised. | ||||
- Error messages dont time out anymore. | - Error messages dont time out anymore. | ||||
- Roxbot can now fully function in DMs. Before, she would break. DM's have less commands. | - Roxbot can now fully function in DMs. Before, she would break. DM's have less commands. | ||||
- `;subreddit`'s "subscriptable" error has been fixed. | - `;subreddit`'s "subscriptable" error has been fixed. | ||||
- is_anal value can be changed again and check now works. | - is_anal value can be changed again and check now works. | ||||
- Common commands that would go over 2000 characters have been paginated to avoid this error. | |||||
## v1.8.0 | ## v1.8.0 | ||||
#### New Features | #### New Features |
if user_id not in settings.warnings: | if user_id not in settings.warnings: | ||||
settings.warnings[user_id] = [] | settings.warnings[user_id] = [] | ||||
warn_limit = 10 | |||||
if len(settings.warnings[user_id]) > warn_limit: | |||||
raise commands.CommandError("You can only warn a user {} times!".format(warn_limit)) | |||||
settings.warnings[user_id].append(warning_dict) | settings.warnings[user_id].append(warning_dict) | ||||
settings.update(settings.warnings, "warnings") | settings.update(settings.warnings, "warnings") | ||||
settings = gs.get(ctx.guild) | settings = gs.get(ctx.guild) | ||||
if user is None: | if user is None: | ||||
output = "" | |||||
paginator = commands.Paginator() | |||||
for member in settings.warnings: | for member in settings.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]: | if not settings.warnings[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: | ||||
output += "{}: {} Warning(s)\n".format(str(member_obj), len( | |||||
settings.warnings[member])) | |||||
paginator.add_line("{}: {} Warning(s)".format(str(member_obj), len(settings.warnings[member]))) | |||||
else: | else: | ||||
output += "{}: {} Warning(s)\n".format(member, len( | |||||
settings.warnings[member])) | |||||
if not output: | |||||
paginator.add_line("{}: {} Warning(s)".format(member, len(settings.warnings[member]))) | |||||
if len(paginator.pages) <= 0: | |||||
return await ctx.send("No warnings on record.") | return await ctx.send("No warnings on record.") | ||||
return await ctx.send(output) | |||||
for page in paginator.pages: | |||||
await ctx.send(page) | |||||
else: | |||||
user_id = str(user.id) | |||||
user_id = str(user.id) | |||||
if not settings.warnings.get(user_id): | |||||
return await ctx.send("This user doesn't have any warning on record.") | |||||
if not settings.warnings.get(user_id): | |||||
return await ctx.send("This user doesn't have any warning on record.") | |||||
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.set_thumbnail(url=user.avatar_url) | |||||
x = 1 | |||||
userlist = settings.warnings[user_id] | |||||
for warning in userlist: | |||||
try: | |||||
warned_by = str(await self.bot.get_user_info(warning["warned-by"])) | |||||
except discord.ext.commands.CommandInvokeError: | |||||
warned_by = warning["warned-by"] | |||||
date = roxbot.datetime_formatting.format(datetime.datetime.fromtimestamp(warning["date"])) | |||||
warn_reason = warning["warning"] | |||||
em.add_field(name="Warning %s" % x, value="Warned by: {}\nTime: {}\nReason: {}".format(warned_by, date, warn_reason)) | |||||
x += 1 | |||||
return await ctx.send(embed=em) | |||||
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.set_thumbnail(url=user.avatar_url) | |||||
x = 1 | |||||
userlist = settings.warnings[user_id] | |||||
for warning in userlist: | |||||
try: | |||||
warned_by = str(await self.bot.get_user_info(warning["warned-by"])) | |||||
except discord.ext.commands.CommandInvokeError: | |||||
warned_by = warning["warned-by"] | |||||
date = roxbot.datetime_formatting.format(datetime.datetime.fromtimestamp(warning["date"])) | |||||
warn_reason = warning["warning"] | |||||
em.add_field(name="Warning %s" % x, value="Warned by: {}\nTime: {}\nReason: {}".format(warned_by, date, warn_reason)) | |||||
x += 1 | |||||
return await ctx.send(embed=em) | |||||
@warn.command() | @warn.command() | ||||
async def remove(self, ctx, user: roxbot.converters.User=None, index=None): | async def remove(self, ctx, user: roxbot.converters.User=None, index=None): |
debug = "0" | debug = "0" | ||||
settings = roxbot.guild_settings.get(ctx.guild) | settings = roxbot.guild_settings.get(ctx.guild) | ||||
cc = settings.custom_commands | cc = settings.custom_commands | ||||
list_no_prefix = "" | |||||
list_prefix = "" | |||||
no_prefix_commands = cc["0"] | no_prefix_commands = cc["0"] | ||||
prefix_commands = {**cc["1"], **cc["2"]} | prefix_commands = {**cc["1"], **cc["2"]} | ||||
for command in no_prefix_commands: | |||||
if debug == "1": | |||||
command += " - {}".format(cc["0"][command]) | |||||
list_no_prefix = list_no_prefix + "- " + command + "\n" | |||||
for command in prefix_commands: | |||||
if debug == "1": | |||||
command += " - {}".format(cc["1"][command]) | |||||
list_prefix = list_prefix + "- " + command + "\n" | |||||
if not list_prefix: | |||||
list_prefix = "There are no commands setup.\n" | |||||
if not list_no_prefix: | |||||
list_no_prefix = "There are no commands setup.\n" | |||||
# TODO: Sort out a way to shorten this if it goes over 2000 characters. Also clean up command to make sense | |||||
em = discord.Embed(title="Here is the list of Custom Commands", color=roxbot.EmbedColours.pink) | |||||
em.add_field(name="Commands that require Prefix:", value=list_prefix, inline=False) | |||||
em.add_field(name="Commands that don't:", value=list_no_prefix, inline=False) | |||||
return await ctx.send(embed=em) | |||||
paginator = commands.Paginator() | |||||
paginator.add_line("Here is the list of Custom Commands...") | |||||
paginator.add_line() | |||||
paginator.add_line("Commands that require Prefix:") | |||||
if not prefix_commands: | |||||
paginator.add_line("There are no commands setup.") | |||||
else: | |||||
for command in prefix_commands: | |||||
if debug == "1": | |||||
command += " = '{}'".format(prefix_commands[command]) | |||||
paginator.add_line("- " + command) | |||||
paginator.add_line() | |||||
paginator.add_line("Commands that don't require prefix:") | |||||
if not no_prefix_commands: | |||||
paginator.add_line("There are no commands setup.") | |||||
else: | |||||
for command in no_prefix_commands: | |||||
if debug == "1": | |||||
command += " = '{}'".format(no_prefix_commands[command]) | |||||
paginator.add_line("- " + command) | |||||
output = paginator.pages | |||||
for page in output: | |||||
await ctx.send(page) | |||||
def setup(bot_client): | def setup(bot_client): |
{command_prefix}listroles | {command_prefix}listroles | ||||
""" | """ | ||||
settings = gs.get(ctx.guild) | settings = gs.get(ctx.guild) | ||||
paginator = commands.Paginator(prefix="`", suffix="`") | |||||
if not settings.self_assign["enabled"]: | if not settings.self_assign["enabled"]: | ||||
embed = discord.Embed(colour=roxbot.EmbedColours.pink, description="SelfAssignable roles are not enabled on this server") | embed = discord.Embed(colour=roxbot.EmbedColours.pink, description="SelfAssignable roles are not enabled on this server") | ||||
return await ctx.send(embed=embed) | return await ctx.send(embed=embed) | ||||
roles = [] | |||||
paginator.add_line("The self-assignable roles for this server are: \n") | |||||
for role in settings.self_assign["roles"]: | for role in settings.self_assign["roles"]: | ||||
for serverrole in ctx.guild.roles: | for serverrole in ctx.guild.roles: | ||||
if role == serverrole.id: | if role == serverrole.id: | ||||
roles.append("**"+serverrole.name+"**") | |||||
roles = '\n'.join(roles) | |||||
embed = discord.Embed(colour=roxbot.EmbedColours.pink, description="The self-assignable roles for this server are: \n"+roles) | |||||
return await ctx.send(embed=embed) | |||||
paginator.add_line("- {}".format(serverrole.name)) | |||||
for page in paginator.pages: | |||||
await ctx.send(page) | |||||
@commands.guild_only() | @commands.guild_only() | ||||
@commands.command(pass_context=True) | @commands.command(pass_context=True) |
@commands.command() | @commands.command() | ||||
async def queue(self, ctx): | async def queue(self, ctx): | ||||
"""Displays what videos are queued up and waiting to be played.""" | """Displays what videos are queued up and waiting to be played.""" | ||||
output = "" | |||||
paginator = commands.Paginator(prefix="", suffix="") | |||||
index = 1 | index = 1 | ||||
for video in self.playlist[ctx.guild.id]: | |||||
output += "{}) '{}' queued by {}\n".format(index, video["title"], video["queued_by"]) | |||||
index += 1 | |||||
if output == "": | |||||
output = "Nothing is up next. Maybe you should add something!" | |||||
embed = discord.Embed(title="Queue", description=output, colour=roxbot.EmbedColours.pink) | |||||
return await ctx.send(embed=embed) | |||||
if len(self.playlist[ctx.guild.id]) == 0: | |||||
return await ctx.send("Nothing is up next. Maybe you should add something!") | |||||
else: | |||||
for video in self.playlist[ctx.guild.id]: | |||||
paginator.add_line("{}) '{}' queued by {}\n".format(index, video["title"], video["queued_by"])) | |||||
index += 1 | |||||
if len(paginator.pages) <= 1: | |||||
embed = discord.Embed(title="Queue", description=paginator.pages[0], colour=roxbot.EmbedColours.pink) | |||||
return await ctx.send(embed=embed) | |||||
else: | |||||
pages = [] | |||||
pages.append(discord.Embed(title="Queue", description=paginator.pages.pop(0), colour=roxbot.EmbedColours.pink)) | |||||
for page in paginator.pages: | |||||
pages.append(discord.Embed(description=page, colour=roxbot.EmbedColours.pink)) | |||||
for page in pages: | |||||
await ctx.send(embed=page) | |||||
@commands.guild_only() | @commands.guild_only() | ||||
@roxbot.checks.is_admin_or_mod() | @roxbot.checks.is_admin_or_mod() |
setting[x] = "True" | setting[x] = "True" | ||||
elif convert[x] == "channel": | elif convert[x] == "channel": | ||||
if isinstance(setting[x], list): | if isinstance(setting[x], list): | ||||
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 | |||||
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: | else: | ||||
try: | try: | ||||
setting[x] = self.bot.get_channel(setting[x]).mention | setting[x] = self.bot.get_channel(setting[x]).mention | ||||
pass | pass | ||||
elif convert[x] == "role": | elif convert[x] == "role": | ||||
if isinstance(setting[x], list): | if isinstance(setting[x], list): | ||||
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 | |||||
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: | else: | ||||
try: | try: | ||||
setting[x] = discord.utils.get(ctx.guild.roles, id=setting[x]).name | setting[x] = discord.utils.get(ctx.guild.roles, id=setting[x]).name | ||||
pass | pass | ||||
elif convert[x] == "user": | elif convert[x] == "user": | ||||
if isinstance(setting[x], list): | if isinstance(setting[x], list): | ||||
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 | |||||
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: | else: | ||||
user = self.bot.get_user(setting[x]) | user = self.bot.get_user(setting[x]) | ||||
if user is None: | if user is None: | ||||
setting[x] = str(setting[x]) | setting[x] = str(setting[x]) | ||||
else: | else: | ||||
setting[x] = str(user) | 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(): | for x in setting.items(): | ||||
if x[0] != "convert": | if x[0] != "convert": | ||||
settingcontent += str(x).strip("()") + "\n" | settingcontent += str(x).strip("()") + "\n" | ||||
# TODO: Use paginator to make the output here not break all the time. | # TODO: Use paginator to make the output here not break all the time. | ||||
config = guild_settings.get(ctx.guild) | config = guild_settings.get(ctx.guild) | ||||
settings = dict(config.settings.copy()) # Make a copy of settings so we don't change the actual settings. | settings = dict(config.settings.copy()) # Make a copy of settings so we don't change the actual settings. | ||||
em = discord.Embed(colour=EmbedColours.pink) | |||||
em.set_author(name="{} settings for {}.".format(self.bot.user.name, ctx.message.guild.name), icon_url=self.bot.user.avatar_url) | |||||
paginator = commands.Paginator(prefix="```md") | |||||
paginator.add_line("{} settings for {}.\n".format(self.bot.user.name, ctx.message.guild.name)) | |||||
if option in settings: | if option in settings: | ||||
raw = bool(ctx.invoked_with == "printsettingsraw") | raw = bool(ctx.invoked_with == "printsettingsraw") | ||||
settingcontent = self.parse_setting(ctx, settings[option], raw=raw) | settingcontent = self.parse_setting(ctx, settings[option], raw=raw) | ||||
em.add_field(name=option, value=settingcontent, inline=False) | |||||
return await ctx.send(embed=em) | |||||
paginator.add_line("**{}**".format(option)) | |||||
paginator.add_line(settingcontent) | |||||
for page in paginator.pages: | |||||
await ctx.send(page) | |||||
else: | else: | ||||
for setting in settings: | for setting in settings: | ||||
if setting != "custom_commands" and setting != "warnings": | if setting != "custom_commands" and setting != "warnings": | ||||
raw = bool(ctx.invoked_with == "printsettingsraw") | raw = bool(ctx.invoked_with == "printsettingsraw") | ||||
settingcontent = self.parse_setting(ctx, settings[setting], raw=raw) | settingcontent = self.parse_setting(ctx, settings[setting], raw=raw) | ||||
em.add_field(name=setting, value=settingcontent, inline=False) | |||||
elif setting == "custom_commands": | |||||
em.add_field(name="custom_commands", value="For Custom Commands, use the custom list command.", inline=False) | |||||
return await ctx.send(embed=em) | |||||
paginator.add_line("**{}**".format(setting)) | |||||
paginator.add_line(settingcontent) | |||||
for page in paginator.pages: | |||||
await ctx.send(page) | |||||
@commands.group(case_insensitive=True) | @commands.group(case_insensitive=True) | ||||
@checks.is_admin_or_mod() | @checks.is_admin_or_mod() |