Ejemplo n.º 1
0
    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
Ejemplo n.º 2
0
    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)
Ejemplo n.º 3
0
    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)
Ejemplo n.º 4
0
    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)))
Ejemplo n.º 5
0
    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)
Ejemplo n.º 6
0
    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
Ejemplo n.º 7
0
    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)))