async def on_message_edit(self, ctx_before, ctx_after): if not ctx_before.author.bot: logs_channel = self.get_channel(settings.LOG_ROOMS['messages']) embed = discord.Embed() embed.colour = discord.Color.from_rgb(245, 124, 110) embed.set_author(name=tr('Bot.Edited', ctx_before), icon_url=ctx_before.author.avatar_url) if not isinstance(ctx_before.channel, discord.channel.DMChannel): channel = ctx_before.channel.mention else: channel = ctx_before.author.mention embed.description = tr( 'Bot.EventOccurredIn', ctx=ctx_before, author=ctx_before.author.mention, guild=ctx_before.guild.name if ctx_before.guild else ctx_before.author.mention, channel=channel) embed.add_field(name=tr('Before', ctx_before), value=ctx_before.content, inline=False) embed.add_field(name=tr('After', ctx_after), value=ctx_after.content, inline=False) await logs_channel.send(embed=embed)
async def blend_images(self, ctx, template, bg_size, bg_coord): """ Old function. Will be replaced. Blend two images Args: ctx (common.Message): context template (str): template image key bg_size (int): background size bg_coord (int): background coordinates """ # Replace it by async request response = requests.get(await self.get_image(ctx)) foreground = os.path.join(self._images_folder, template) foreground = Image.open(foreground) background = Image.open(BytesIO(response.content)) if 3000 in background.size: await ctx.send( tr('Cogs.Fun.Fun.ImageSizeError', ctx, w=background.size[0], h=background.size[1])) else: filepath = f'{self._temp_images_folder}/{template}' background = background.resize(bg_size) blended = Image.new('RGBA', foreground.size) blended.paste(background, bg_coord) blended.paste(foreground, (0, 0), foreground) blended.save(filepath, 'PNG') await ctx.send(file=discord.File(filepath)) os.remove(filepath)
async def reload_module(self, ctx, *cogs): # "prefix *" - each module # "prefix Module.module" - specific one # TODO: add folder (group) reboot: "?rm tools (will reboot each module)" if not cogs: cogs = settings.COGS else: cogs = [f'cogs.{i}' for i in cogs] # First, we need to reload localization files Locales.load_aliases(cogs) Locales.load_translations(module_paths=cogs) await ctx.send( tr('Cogs.Tools.Bot.UpdatedLocalizationFiles', ctx, 'bookmark', 1)) message = '' for cog in cogs: if cog in self.bot.extensions: try: self.bot.reload_extension(cog) message += f"{tr('Cogs.Tools.Bot.ModuleWasRebooted', ctx, 'wrench', 1, module=cog)}\n" except ExtensionError: message += f"{tr('Cogs.Tools.Bot.FailedToRebootModule', ctx, 'fire', 1, module=cog)}\n" else: message += f"{tr('Cogs.Tools.Bot.ModuleNotFound', ctx, 'warning', 1, module=cog)}\n" await ctx.send(message)
async def set_guild_prefix(self, ctx, prefix): # if prefix is a word then add space if not re.match(r'[@_!#$%^&*()<>?/\|}{~:]', prefix): prefix += ' ' Guilds.update_guild(ctx.message.guild.id, prefix=prefix) await ctx.send( tr('Cogs.Tools.Admin.PrefixHasBeenSet', ctx, prefix=prefix))
async def guild_info(self, ctx): info = Guilds.get_guild_info(ctx.message.guild.id) embed = discord.Embed() embed.title = tr('Guild info', ctx) embed.description = ( f'\n• {tr("Locale", ctx)}: {info.get("locale")}' f'\n\n• {tr("Prefix", ctx)}: {info.get("prefix")}') await ctx.send(embed=embed)
async def restart(self, ctx): embed = discord.Embed( title=tr('Cogs.Tools.Bot.RebootNotification', ctx=ctx, emoji='gear'), color=discord.Color.from_rgb(255, 188, 64), ) subprocess.call([sys.executable, 'Bot/bot.py']) await ctx.send(embed=embed)
async def set_guild_locale(self, ctx, locale: str = None): """ Set guild locale Args: ctx (common.Message): context locale (str): locale key code in lower case """ locale = locale.lower() if re.match(r'[a-z\-A-Z]{5}', locale): if locale == Guilds.get_guild_info(ctx.message.guild.id, 'locale'): await ctx.send(tr('Cogs.Tools.Admin.SameLocale', ctx)) else: Guilds.update_guild(ctx.message.guild.id, locale=locale) Locales.load_translations(locale) await ctx.send( tr('Cogs.Tools.Admin.LocaleHasBeenSet', ctx, locale=locale)) else: await ctx.send(tr('Cogs.Tools.Admin.LocaleFormatIsIncorrect', ctx))
async def text_to_speech_list(self, ctx, section: str): lines = await AudioConverter.get_alphabet(section) lines = '"{}"'.format('", "'.join(lines.keys())) embed = discord.Embed() embed.set_author(name=tr('Cogs.Fun.TextToSpeechList', ctx)) await ctx.author.send(embed=embed) for line in textwrap.wrap(lines, 500): # await ctx.author.send(line) embed.add_field(name='================', value=line) await ctx.author.send(embed=embed)
async def on_command_error(self, ctx, error): logs_channel = self.get_channel(settings.LOG_ROOMS['errors']) message = tr('Error', ctx) if isinstance(error, commands.CommandOnCooldown): member = ctx.message.author.mention message = tr('Bot.PleaseWait', ctx, member=member) elif isinstance(error, commands.UserInputError): message = tr('Bot.InvalidInput', ctx, arg=ctx.command) elif isinstance(error, commands.BadArgument): message = tr('Bot.BadCommandArgument', arg=ctx.command.content) elif isinstance(error, commands.CommandNotFound): message = tr('Bot.CommandNotFound', ctx, arg=ctx.message.content) elif isinstance(error, commands.CommandInvokeError): message = f'{tr("Bot.CommandInvokeError", ctx)}: {error.original}' elif isinstance(error, UnboundLocalError): message = f'{tr("Bot.LocalError", ctx)}: {error}' title = tr('Error', ctx) embed_logs = discord.Embed() embed_logs.set_author(name=title, icon_url=ctx.message.author.avatar_url) embed_logs.colour = discord.Color.from_rgb(252, 197, 114) channel = ctx.guild.id if ctx.guild else 'DM' embed_logs.description = f'{ctx.message.author.mention} in {channel}\n{message}' embed_logs.set_footer(text=f'{datetime.fromtimestamp(time.time())}') await ctx.send(message) await logs_channel.send(embed=embed_logs)
async def on_message(self, ctx: discord.Message): """ (AVATAR) [Type of event] User sent message in <#channel.mention> [Content title] Content [If File title] File URL """ if not ctx.author.bot: logs_channel = self.get_channel(settings.LOG_ROOMS['messages']) embed = discord.Embed() embed.colour = discord.Color.from_rgb(110, 162, 245) embed.set_author(name=tr('Bot.Message', ctx), icon_url=ctx.author.avatar_url) embed.description = tr( 'Bot.EventOccurredIn', ctx=ctx, author=ctx.author.mention, guild=ctx.guild.name if ctx.guild else ctx.author.mention, channel=ctx.channel.mention if not isinstance(ctx.channel, discord.channel.DMChannel) else ctx.author.mention) if ctx.content: embed.add_field(name=tr('Bot.Message', ctx), value=ctx.content, inline=False) if ctx.attachments: embed.add_field(name=tr('Bot.File', ctx), value=ctx.attachments[0].proxy_url, inline=False) await logs_channel.send(embed=embed) await self.process_commands(ctx)
async def info(self, ctx): embed = discord.Embed() embed.colour = discord.Color.from_rgb(178, 66, 219) uname = platform.uname() embed.description = f''' • :snake: Python - {sys.version.split()[0]} • :space_invader: Discord API - {discord.__version__} • :pager: {uname.system} • :computer: {uname.machine} • :bulb: {uname.processor} ''' embed.set_author(name=tr('Cogs.Tools.Bot.BotInfoTitle', ctx), icon_url=self.bot.get_user( self.bot.user.id).avatar_url) await ctx.send(embed=embed)
async def set_presence(self, ctx, presence: int = None): presences = ( ('online', (157, 245, 110)), # online/green ('idle', (252, 219, 3)), # idle/orange ('dnd', (219, 66, 74)), # dnd/red ('offline', (158, 158, 158)), # offline/white ('invisible', (158, 158, 158)), # invisible/white ) embed = discord.Embed() embed.title = tr('Cogs.Tools.Bot.StatusHasBeenSet', ctx, status_name=presences[presence][0]) embed.colour = discord.Color.from_rgb(*presences[presence][1]) await ctx.send(embed=embed) await set_presence(self.bot, presence=presence)
async def text_to_speech(self, ctx, section: str, *text: str): """ Text to speech command. Example: pls <section; f.e: vox> <file1> <file2> Or if files contains more than one word: pls <section; f.e: kingpin> <file name 1>, <file name 2> """ text = str(' '.join(text)) text = text.split(',') if ',' in text else text.split(' ') result = await AudioConverter.text_to_speech(section, *text) if result: await ctx.send(ctx.message.author.mention, file=discord.File(result.get('output'))) os.remove(result.get('output')) else: await ctx.send(tr('Cogs.Fun.WrongCategory', ctx))
async def magic(self, ctx, scale=3): if scale > 10: scale = 3 await ctx.send(tr('The scale argument can\'t be more than 10', ctx)) image_path = self.save_image(await self.get_image(ctx)) image = WImage(filename=image_path) image.liquid_rescale(width=int(image.width * 0.5), height=int(image.height * 0.5), delta_x=int(0.5 * scale) if scale else 1, rigidity=0) image.liquid_rescale(width=int(image.width * 1.5), height=int(image.height * 1.5), delta_x=scale if scale else 2, rigidity=0) image.save(filename=image_path) await ctx.send(file=discord.File(image_path)) os.remove(image_path)
def add_aliases_formatting(self, aliases): self.paginator.add_line( '**{}**: {}'.format(tr('Bot.AliasHeading', self.context), ', '.join(aliases)), empty=True )
async def impact_meme(self, ctx, *string): # Forked from: https://github.com/Littlemansmg/Discord-Meme-Generator image_path = self.save_image(await self.get_image(ctx)) font_path = f'{self._resources}/Fonts/impact.ttf' if string: string_size = len(string) // 2 top_string = ' '.join(string[:string_size]) bottom_string = ' '.join(string[string_size:]) with Image.open(image_path) as image: size = image.size font_size = int(size[1] / 5) font = ImageFont.truetype(font_path, font_size) edit = ImageDraw.Draw(image) # find biggest font size that works top_text_size = font.getsize(top_string) bottom_text_size = font.getsize(bottom_string) while top_text_size[0] > size[0] - 20 or bottom_text_size[ 0] > size[0] - 20: font_size = font_size - 1 # fix it font = ImageFont.truetype(font_path, font_size) top_text_size = font.getsize(top_string) bottom_text_size = font.getsize(bottom_string) # find top centered position for top text top_text_posx = (size[0] / 2) - (top_text_size[0] / 2) top_text_posy = 0 top_text_pos = (top_text_posx, top_text_posy) # find bottom centered position for bottom text bottom_text_posx = (size[0] / 2) - (bottom_text_size[0] / 2) bottom_text_posy = size[1] - bottom_text_size[1] - 10 bottom_text_pos = (bottom_text_posx, bottom_text_posy) # draw outlines # there may be a better way outline_range = int(font_size / 15) for x in range(-outline_range, outline_range + 1): for y in range(-outline_range, outline_range + 1): edit.text((top_text_pos[0] + x, top_text_pos[1] + y), top_string, (0, 0, 0), font=font) edit.text( (bottom_text_pos[0] + x, bottom_text_pos[1] + y), bottom_string, (0, 0, 0), font=font) edit.text(top_text_pos, top_string, (255, 255, 255), font=font) edit.text(bottom_text_pos, bottom_string, (255, 255, 255), font=font) image.save(image_path, 'PNG') await ctx.send(file=discord.File(image_path)) os.remove(image_path) else: await ctx.send(tr('Cogs.Fun.Fun.ImpactMemeEmptyString', ctx))
async def reload_translations(self, ctx): Locales.load_aliases() Locales.load_translations() await ctx.send( tr('Cogs.Tools.Bot.UpdatedLocalizationFiles', ctx, 'bookmark', 1))
async def restart_error(self, ctx, error): if isinstance(error, commands.NotOwner): await ctx.send( tr('Cogs.Tools.Admin.AccessDenied', ctx=ctx, emoji='alien'))
async def reload_module_error(self, ctx, error): if isinstance(error, commands.NotOwner): await ctx.send(tr('Cogs.Tools.Admin.AccessDenied', ctx)) if isinstance(error, commands.BadArgument): await ctx.send('Invalid argument')