def create_image(self, text): # Shorten really long text text = add_dots(text, max(self._image_sizes), ending="") # Find the appropriate image size image = self.get_matching_image(len(text)) text = "\n".join(textwrap.wrap(text, width=min(self._image_sizes))) # Upscales the image img_width, img_height = image.size img_width_n = img_width * self.UPSCALE img_height_n = img_height * self.UPSCALE image = image.resize((img_width_n, img_height_n), Image.ANTIALIAS) draw = ImageDraw.Draw(image) # Puts text on top draw.text(self.DRAW_POS, text, self.COLOR_WHITE, font=self.font_mc) # Downscales the image again, effectively anti-aliasing the text image = image.resize((img_width, img_height), Image.ANTIALIAS) # Save data in memory mem_file = BytesIO() image.save(mem_file, "png") # Reset cursor to start mem_file.seek(0) return mem_file
async def log_say_command(self, message, content, prefix, lang): log_channel = await self.getter.handle_log_channel(message.guild) if not log_channel: return embed = Embed(title=self.trans.get("MSG_LOGPOST_SAY", lang).format(prefix), description=add_dots(content, 350)) embed.set_author(name="{} ({})".format(message.author.name, message.author.id), icon_url=message.author.avatar_url) embed.add_field(name=self.trans.get("INFO_CHANNEL", lang), value=message.channel.mention) await log_channel.send(embed=embed)
async def send_log(self, message: Message, lang, reason=""): if not self.getter: self.loop.call_later(5, self.send_log(message, lang, reason)) logger.warning("Getter is not set, calling in 5 seconds...") return log_channel = await self.getter.handle_log_channel(message.guild) if not log_channel: return author = message.author embed_title = self.trans.get("MSG_MOD_MSG_DELETED", lang).format(reason) embed = Embed(title=embed_title, description=add_dots(message.content)) embed.set_author(name="{} ({})".format(author.name, author.id), icon_url=author.avatar_url) embed.add_field(name=self.trans.get("INFO_CHANNEL", lang), value=message.channel.mention) logger.debug("Sending logs for {}".format(message.guild.name)) await log_channel.send(embed=embed)
async def on_message(self, message, **kwargs): assert isinstance(message, Message) prefix = kwargs.get("prefix") trans = self.trans lang = kwargs.get("lang") if not is_valid_command(message.content, commands, prefix=prefix): return else: self.stats.add(MESSAGE) def startswith(*msg): for a in msg: if message.content.startswith(a): return True return False if startswith(prefix + "wiki", prefix + "define"): if startswith(prefix + "wiki"): search = str(message.content)[len(prefix + "wiki "):].strip(" ") elif startswith(prefix + "define"): search = str(message.content)[len(prefix + "define "):].strip(" ") else: # Not possible, but k return if not search: await message.channel.send(trans.get("MSG_WIKI_NO_QUERY", lang)) return summary = await self.wiki.get_definition(search) if not summary: await message.channel.send(trans.get("MSG_WIKI_NO_DEF", lang)) return await message.channel.send( trans.get("MSG_WIKI_DEFINITION", lang).format( search, add_dots(summary, max_len=MAX_WIKI_LENGTH))) elif startswith(prefix + "urban"): search = str(message.content)[len(prefix + "urban "):].strip(" ") if not search: await message.channel.send( trans.get("MSG_URBAN_NO_QUERY", lang)) return description = await self.urban.urban_dictionary(search) if not description: await message.channel.send(trans.get("MSG_URBAN_NO_DEF", lang)) return await message.channel.send( trans.get("MSG_URBAN_DEFINITION", lang).format( search, add_dots(description, max_len=MAX_URBAN_LENGTH)))
async def on_message(self, message, **kwargs): trans = self.trans prefix = kwargs.get("prefix") lang = kwargs.get("lang") # Check if this is a valid command if not is_valid_command(message.content, commands, prefix): return else: self.stats.add(MESSAGE) def startswith(*matches): for match in matches: if message.content.startswith(match): return True return False # !poll start # Arguments: "[title]" [option1]|(option2)|... # OR : "[title]" [option1],(option2),... if startswith(prefix + "poll start"): if not self.handler.is_admin(message.author, message.guild): await message.channel.send(trans.get("PERM_ADMIN", lang)) self.stats.add(WRONG_PERMS) return if self.vote.in_progress(message.guild.id): await message.channel.send( trans.get("MSG_VOTING_IN_PROGRESS", lang)) return arguments = message.content[len(prefix + "poll start "):].strip(" ") if not arguments: await message.channel.send( trans.get("MSG_VOTING_I_USAGE", lang).format(prefix)) return # TITLE # Handle short_title, "longer title", 'also like this' if arguments[0] == "\"": _, title, arguments = arguments.split("\"", maxsplit=3) elif arguments[0] == "'": _, title, arguments = arguments.split("'", maxsplit=3) else: title, arguments = arguments.split(" ", maxsplit=1) arguments = arguments.lstrip(" ") # CHOICES # | as separator if "|" in arguments: items = [a.strip(" ") for a in arguments.split("|") if a] # , used as separator else: items = [a.strip(" ") for a in arguments.split(",") if a] # Send an error if there's only a title if len(items) < 2: await message.channel.send( trans.get("MSG_VOTING_NEED_OPTIONS", lang).format(prefix)) return # END OF ARGUMENT PARSING # Check item amount if len(items) > VOTE_ITEM_LIMIT: await message.channel.send( trans.get("MSG_VOTING_OPTIONS_TM", lang).format(VOTE_ITEM_LIMIT, len(items))) return # Check total length if (len(title) + sum([len(a) for a in items])) > VOTE_ITEM_MAX_LENGTH: await message.channel.send( trans.get("MSG_VOTING_OPTIONS_TL ", lang).format(VOTE_ITEM_MAX_LENGTH, sum([len(a) for a in items]))) return # Check if any option is empty if any(e == "" for e in items): await message.channel.send( trans.get("MSG_VOTING_EMPTY_ITEM", lang)) return self.vote.start_vote(message.author.id, message.guild.id, title, items) # Generates a list of options to show choices = "\n\n".join([ "[{}]\n{}".format(en + 1, ch) for en, ch in enumerate( self.vote.get_choices(message.guild.id)) ]) await message.channel.send( trans.get("MSG_VOTING_STARTED", lang).format(title, choices)) # !poll end elif startswith(prefix + "poll end"): if not self.handler.is_admin(message.author, message.guild): await message.channel.send(trans.get("PERM_ADMIN", lang)) self.stats.add(WRONG_PERMS) return if not self.vote.in_progress(message.guild.id): await message.channel.send( trans.get("MSG_VOTING_NO_PROGRESS", lang)) return # Wait for confirmation msg = await message.channel.send( trans.get("MSG_VOTING_END_CONFIRMATION", lang).format(OK_EMOJI)) await msg.add_reaction(OK_EMOJI) def check(reaction, user): return user == message.author and str( reaction.emoji) == OK_EMOJI try: await self.client.wait_for('reaction_add', timeout=45, check=check) except asyncio.TimeoutError: await message.channel.send( trans.get("MSG_VOTING_END_ABORT", lang)) return await msg.delete() votes = self.vote.get_votes(message.guild.id) title = self.vote.get_title(message.guild.id) total_votes = sum(votes.values()) embed = Embed(title="**{}**".format(title), colour=Colour(0x303F9F), description=trans.get("MSG_VOTING_AMOUNT", lang).format(total_votes)) for name, val in votes.items(): # Zero-width space dotted = add_dots(name, max_len=240) or "\u200B" embed.add_field(name=dotted, value=trans.get("MSG_VOTING_AMOUNT2", lang).format(val)) # Actually end the voting self.vote.end_voting(message.guild.id) try: await message.channel.send( trans.get("MSG_VOTING_ENDED", lang) + "\n", embed=embed) except errors.HTTPException as e: await message.channel.send(trans.get("MSG_VOTING_ERROR", lang)) log_to_file("VOTING ({}): {}".format(e, embed.to_dict()), "bug") # !poll status elif startswith(prefix + "poll status"): if not self.vote.in_progress(message.guild.id): await message.channel.send( trans.get("MSG_VOTING_NO_PROGRESS", lang)) return header = self.vote.get_title(message.guild.id) votes = sum(self.vote.get_votes(message.guild.id).values()) if votes == 0: vote_disp = trans.get("MSG_VOTING_S_NONE", lang) elif votes == 1: vote_disp = trans.get("MSG_VOTING_S_ONE", lang) else: vote_disp = trans.get("MSG_VOTING_S_MULTI", lang).format(votes) await message.channel.send( trans.get("MSG_VOTING_STATUS", lang).format(header, vote_disp)) # !vote elif startswith(prefix + "vote"): # Ignore if there is no vote going on instead of getting an exception if not self.vote.in_progress(message.guild.id): await message.add_reaction(X_EMOJI) msg = await message.channel.send( trans.get("MSG_VOTING_NO_PROGRESS", lang)) await asyncio.sleep(2) await msg.delete() return # Get the choice, but tell the author if he/she didn't supply a number try: choice = int(message.content[len(prefix + "vote "):]) - 1 # Cannot convert to int except ValueError: await message.add_reaction(BLOCK_EMOJI) m = await message.channel.send( trans.get("MSG_VOTING_NOT_NUMBER", lang)) await asyncio.sleep(2) await m.delete() return res = self.vote.plus_one(choice, message.author.id, message.guild.id) # User already voted if res == -1: await message.add_reaction(BLOCK_EMOJI) msg = await message.channel.send( trans.get("MSG_VOTING_CHEATER", lang)) await asyncio.sleep(2) await msg.delete() # No such option elif not res: await message.add_reaction(X_EMOJI) msg = await message.channel.send( trans.get("MSG_VOTING_INVALID_NUMBER", lang)) await asyncio.sleep(2) await msg.delete() # Everything ok, was added else: await message.add_reaction(OK_EMOJI) self.stats.add(VOTE)
async def on_message(self, message, **kwargs): trans = self.trans prefix = kwargs.get("prefix") lang = kwargs.get("lang") simple_commands = {"( ͡° ͜ʖ ͡°)": trans.get("MSG_WHOKNOWS", lang)} # Loop over simple commands for k, v in simple_commands.items(): if message.content.startswith(k): await message.channel.send(v) self.stats.add(MESSAGE) return # Check if this is a valid command if not is_valid_command(message.content, commands, prefix): return else: self.stats.add(MESSAGE) def startswith(*matches): for match in matches: if message.content.startswith(match): return True return False # Other commands if startswith(prefix + "kappa"): await message.channel.send(file=File(KAPPA_LOCATION, "kappa.png")) self.stats.add(IMAGE_SENT) # !randomgif (optional_tag) elif startswith(prefix + "randomgif"): tags = message.content[len(prefix + "randomgif "):] gif = await self.gif.get_random_gif(tags or None) nonexistent = False if gif == -1: await message.channel.send(trans.get("MSG_GIPHY_TOOFAST", lang)) return # Gif with such tag does not exist, fall back to random one if gif is None: gif = await self.gif.get_random_gif() nonexistent = True embed = Embed(colour=Colour(GIPHY_GREEN)) embed.set_image(url=gif) if not nonexistent: embed.set_footer(text=trans.get("MSG_GIPHY_POWEREDBY", lang)) else: that_text = trans.get( "MSG_GIPHY_POWEREDBY", lang) + " | " + trans.get( "MSG_GIPHY_NOSUCHTAG", lang).format(add_dots(tags, 20)) embed.set_footer(text=that_text) await message.channel.send(embed=embed) self.stats.add(IMAGE_SENT) # !meme [meme name]|[top text]|[bottom text] elif startswith(prefix + "meme"): query = message.content[len(prefix + "meme "):] if not query: await message.channel.send( trans.get("ERROR_INVALID_CMD_ARGUMENTS", lang)) return middle = [a.strip(" ") for a in query.split("|")] # If only two arguments are passed, assume no bottom text if len(middle) == 2: name = middle[0] top = middle[1] bottom = "" # 0, 1 or more than 3 arguments - error elif len(middle) < 2 or len(middle) > 3: await message.channel.send( trans.get("MSG_MEME_USAGE", lang).replace("_", prefix)) return # Normal else: name = middle[0] top = middle[1] bottom = middle[2] meme = await self.generator.caption_meme(name, top, bottom) if not meme: await message.channel.send( trans.get("MSG_MEME_NONEXISTENT", lang)) else: embed = Embed(colour=Colour(0x607D8B)) embed.set_image(url=meme) embed.set_footer(text=trans.get("MSG_MEME_FOOTER", lang)) await message.channel.send(embed=embed) elif startswith(prefix + "rip"): if len(message.mentions) == 1: ripperoni = " " + message.mentions[0].name elif len(message.mentions) == 0: ripperoni = " " + message.content[len(prefix + "rip "):] else: ripperoni = "" ripperoni = self.everyone_filter(ripperoni, message.author, force_remove=True) prays = self.stats.get_amount(PRAYER) await message.channel.send( trans.get("MSG_RIP", lang).format(ripperoni, prays)) self.stats.add(PRAYER) elif startswith(prefix + "achievement"): text = message.content[len(prefix + "achievement "):].strip(" ") if not text: await message.channel.send( trans.get("MSG_ACHIEVMENT_NOTEXT", lang)) return img = self.achievement.create_image(text) img_filename = "Achievement_{}.png".format(gen_id(4)) await message.channel.send(file=File(img, img_filename)) # Just in case GC fails del img
async def on_message(self, message, **kwargs): assert isinstance(message, Message) prefix = kwargs.get("prefix") trans = self.trans lang = kwargs.get("lang") if not is_valid_command(message.content, commands, prefix=prefix): return else: self.stats.add(MESSAGE) def startswith(*msg): for a in msg: if message.content.startswith(a): return True return False if startswith(prefix + "wiki", prefix + "define"): if startswith(prefix + "wiki"): search = str(message.content)[len(prefix + "wiki "):].strip(" ") elif startswith(prefix + "define"): search = str(message.content)[len(prefix + "define "):].strip(" ") else: # Shouldn't happen, RuntimeError means startswith() is not working properly raise RuntimeError # filter mentions search = filter_text(search) if not search: await message.channel.send(trans.get("MSG_WIKI_NO_QUERY", lang)) return summary = await self.wiki.get_definition(search) if not summary: await message.channel.send(trans.get("MSG_WIKI_NO_DEF", lang)) return await message.channel.send( trans.get("MSG_WIKI_DEFINITION", lang).format( search, add_dots(filter_text(summary), max_len=MAX_WIKI_LENGTH))) elif startswith(prefix + "urban"): search = str(message.content)[len(prefix + "urban "):].strip(" ") if not search: await message.channel.send( trans.get("MSG_URBAN_NO_QUERY", lang)) return # filter mentions search = filter_text(search) description = await self.urban.urban_dictionary(search) if not description: await message.channel.send(trans.get("MSG_URBAN_NO_DEF", lang)) return await message.channel.send( trans.get("MSG_URBAN_DEFINITION", lang).format( search, add_dots(filter_text(description), max_len=MAX_URBAN_LENGTH)))