Beispiel #1
0
    async def topservers(self, ctx):
        """See your top servers by XP."""
        data = await self.bot.db.execute(
            """
            SELECT guild_id, SUM(h0+h1+h2+h3+h4+h5+h6+h7+h8+h9+h10+h11+h12+h13+h14+h15+h16+h17+h18+h19+h20+h21+h22+h23)
                as xp FROM user_activity
                WHERE user_id = %s
            GROUP BY guild_id
            ORDER BY xp DESC
            """,
            ctx.author.id,
        )
        rows = []
        total_xp = 0
        for i, (guild_id, xp) in enumerate(data, start=1):
            guild = self.bot.get_guild(guild_id)
            if guild is None:
                guild_name = guild_id
            else:
                guild_name = guild.name

            level = util.get_level(xp)
            total_xp += xp
            rows.append(f"`#{i}` **{guild_name}** — Level **{level}**")

        content = discord.Embed()
        content.set_author(
            name=
            f"Top servers by XP for {util.displayname(ctx.author, escape=False)}",
            icon_url=ctx.author.avatar_url,
        )
        content.set_footer(
            text=f"Combined global level {util.get_level(total_xp)}")
        content.colour = ctx.author.color
        await util.send_as_pages(ctx, content, rows)
Beispiel #2
0
    async def activity(self,
                       ctx,
                       user: typing.Optional[discord.Member] = None,
                       scope=""):
        """See your hourly activity chart (GMT)."""
        if user is None:
            user = ctx.author

        is_global = scope.lower() == "global"

        if is_global:
            global_activity = await self.bot.db.execute(
                """
                SELECT h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11,h12,h13,h14,h15,h16,h17,h18,h19,20,h21,h22,h23
                    FROM user_activity
                WHERE user_id = %s
                GROUP BY guild_id
                """,
                user.id,
            )
            if global_activity:
                activity_data = []
                for i in range(24):
                    activity_data.append(sum(r[i] for r in global_activity))
                xp = sum(activity_data)
            else:
                activity_data = [0] * 24
                xp = 0
        else:
            activity_data = await self.bot.db.execute(
                """
                SELECT h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11,h12,h13,h14,h15,h16,h17,h18,h19,20,h21,h22,h23
                    FROM user_activity
                WHERE user_id = %s AND guild_id = %s
                """,
                user.id,
                ctx.guild.id,
                one_row=True,
            )
            xp = sum(activity_data) if activity_data else 0

        if xp == 0:
            return ctx.send("No data!")

        level = util.get_level(xp)

        title = (
            f"LVL {level} | {xp - util.get_xp(level)}/"
            f"{util.xp_to_next_level(level)} XP to levelup | Total xp: {xp}")

        await self.bot.loop.run_in_executor(
            None, lambda: plotter.create_graph(
                activity_data, str(user.color), title=title))

        with open("downloads/graph.png", "rb") as img:
            await ctx.send(
                f"`Hourly cumulative {'global' if is_global else 'server'} activity for {user}`",
                file=discord.File(img),
            )
Beispiel #3
0
    async def on_message(self, message):
        """Listener that gets called on every message."""
        if not self.bot.is_ready():
            return
        self.stats_messages += 1
        self.bot.cache.event_triggers["message"] += 1

        # ignore DMs
        if message.guild is None:
            return

        if message.channel.id in self.bot.cache.votechannels:
            # votechannels
            votechannel_type = await self.bot.db.execute(
                "SELECT voting_type FROM voting_channel WHERE channel_id = %s",
                message.channel.id,
                one_value=True,
            )
            if votechannel_type == "rating":
                for e in ["0️⃣", "1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣"]:
                    await message.add_reaction(e)
            elif votechannel_type == "voting":
                await message.add_reaction(emojis.UPVOTE)
                await message.add_reaction(emojis.DOWNVOTE)

        # xp gain
        message_xp = util.xp_from_message(message)
        if self.xp_cache.get(str(message.guild.id)) is None:
            self.xp_cache[str(message.guild.id)] = {}
        try:
            self.xp_cache[str(message.guild.id)][str(
                message.author.id)]["xp"] += message_xp
            self.xp_cache[str(message.guild.id)][str(
                message.author.id)]["messages"] += 1
        except KeyError:
            self.xp_cache[str(message.guild.id)][str(message.author.id)] = {
                "xp": message_xp,
                "messages": 1,
                "bot": message.author.bot,
            }

        # if bot account, ignore everything after this
        if message.author.bot:
            return

        # announce_levelup = self.bot.cache.levelupmessage.get(str(message.guild.id), False)
        # disabled for now
        announce_levelup = False
        autoresponses = self.bot.cache.autoresponse.get(
            str(message.guild.id), True)

        # log emojis
        unicode_emojis = util.find_unicode_emojis(message.content)
        custom_emojis = util.find_custom_emojis(message.content)

        for emoji_name in unicode_emojis:
            if self.emoji_usage_cache["unicode"].get(str(
                    message.guild.id)) is None:
                self.emoji_usage_cache["unicode"][str(message.guild.id)] = {}
            if (self.emoji_usage_cache["unicode"][str(message.guild.id)].get(
                    str(message.author.id)) is None):
                self.emoji_usage_cache["unicode"][str(message.guild.id)][str(
                    message.author.id)] = {}
            try:
                self.emoji_usage_cache["unicode"][str(message.guild.id)][str(
                    message.author.id)][emoji_name] += 1
            except KeyError:
                self.emoji_usage_cache["unicode"][str(message.guild.id)][str(
                    message.author.id)][emoji_name] = 1

        for emoji_name, emoji_id in custom_emojis:
            if self.emoji_usage_cache["custom"].get(str(
                    message.guild.id)) is None:
                self.emoji_usage_cache["custom"][str(message.guild.id)] = {}
            if (self.emoji_usage_cache["custom"][str(message.guild.id)].get(
                    str(message.author.id)) is None):
                self.emoji_usage_cache["custom"][str(message.guild.id)][str(
                    message.author.id)] = {}
            try:
                self.emoji_usage_cache["custom"][str(message.guild.id)][str(
                    message.author.id)][str(emoji_id)]["uses"] += 1
            except KeyError:
                self.emoji_usage_cache["custom"][str(message.guild.id)][str(
                    message.author.id)][str(emoji_id)] = {
                        "uses": 1,
                        "name": emoji_name
                    }

        if autoresponses:
            await self.easter_eggs(message)

        # level up message
        if announce_levelup:
            activity_data = await self.bot.db.execute(
                "SELECT * FROM user_activity WHERE user_id = %s AND guild_id = %s",
                message.author.id,
                message.guild.id,
                one_row=True,
            )
            if activity_data:
                xp = sum(activity_data[3:])
                level_before = util.get_level(xp - message_xp)
                level_now = util.get_level(xp)

                if level_now > level_before:
                    try:
                        await message.channel.send(
                            f"{message.author.mention} just leveled up! (level **{level_now}**)",
                            delete_after=5,
                        )
                    except discord.errors.Forbidden:
                        pass
Beispiel #4
0
    async def profile(self, ctx, user: discord.Member = None):
        """Your personal customizable user profile."""
        if user is None:
            user = ctx.author

        badges = []
        badge_classes = {
            "dev": "fab fa-dev",
            "patreon": "fab fa-patreon",
            "lastfm": "fab fa-lastfm",
            "sunsign": "fas fa-sun",
            "location": "fas fa-compass",
            "bot": "fas fa-robot",
        }

        def get_font_size(username):
            length = len(username)
            if length < 15:
                return "24px"
            elif length < 20:
                return "18px"
            elif length < 25:
                return "15px"
            else:
                return "11px"

        def make_badge(classname):
            return f'<li class="badge-container"><i class="corner-logo {classname}"></i></li>'

        if user.id == self.bot.owner_id:
            badges.append(make_badge(badge_classes["dev"]))

        if user.bot:
            badges.append(make_badge(badge_classes["bot"]))

        if await queries.is_donator(ctx, user):
            badges.append(make_badge(badge_classes["patreon"]))

        user_settings = await self.bot.db.execute(
            "SELECT lastfm_username, sunsign, location_string FROM user_settings WHERE user_id = %s",
            user.id,
            one_row=True,
        )
        if user_settings:
            if user_settings[0] is not None:
                badges.append(make_badge(badge_classes["lastfm"]))
            if user_settings[1] is not None:
                badges.append(make_badge(badge_classes["sunsign"]))
            if user_settings[2] is not None:
                badges.append(make_badge(badge_classes["location"]))

        server_activity = await self.bot.db.execute(
            """
            SELECT h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11,h12,h13,h14,h15,h16,h17,h18,h19,h20,h21,h22,h23 as xp
                FROM user_activity
            WHERE user_id = %s AND guild_id = %s
            """,
            user.id,
            ctx.guild.id,
            one_row=True,
        )
        server_xp = sum(server_activity) if server_activity else 0

        global_activity = await self.bot.db.execute(
            """
            SELECT h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11,h12,h13,h14,h15,h16,h17,h18,h19,h20,h21,h22,h23 as xp
                FROM user_activity
            WHERE user_id = %s
            GROUP BY guild_id
            """,
            user.id,
        )
        if global_activity:
            new_global_activity = []
            for i in range(24):
                new_global_activity.append(sum(r[i] for r in global_activity))
            global_xp = sum(new_global_activity)
        else:
            new_global_activity = [0] * 24
            global_xp = 0

        if user.bot:
            description = "I am a bot<br>BEEP BOOP"
        else:
            description = "You should change this by using<br>>editprofile description"

        profile_data = await self.bot.db.execute(
            """
            SELECT description, background_url, background_color, show_graph
            FROM user_profile WHERE user_id = %s
            """,
            user.id,
            one_row=True,
        )

        fishy = await self.bot.db.execute(
            """
            SELECT fishy_count FROM fishy WHERE user_id = %s
            """,
            user.id,
            one_value=True,
        )

        if profile_data:
            description, background_url, background_color, show_graph = profile_data
            if description is not None:
                description = bleach.clean(
                    description.replace("\n", "<br>"),
                    tags=bleach.sanitizer.ALLOWED_TAGS + ["br"],
                )
            background_url = background_url or ""
            background_color = (("#" + background_color) if background_color
                                is not None else user.color)
        else:
            background_color = user.color
            background_url = ""
            show_graph = True

        command_uses = await self.bot.db.execute(
            """
            SELECT SUM(uses) FROM command_usage WHERE user_id = %s
            GROUP BY user_id
            """,
            user.id,
            one_value=True,
        )

        replacements = {
            "BACKGROUND_IMAGE": background_url,
            "WRAPPER_CLASS": "custom-bg" if background_url != "" else "",
            "SIDEBAR_CLASS": "blur" if background_url != "" else "",
            "OVERLAY_CLASS": "overlay" if background_url != "" else "",
            "USER_COLOR": background_color,
            "AVATAR_URL": user.avatar_url_as(size=128, format="png"),
            "USERNAME": user.name,
            "DISCRIMINATOR": f"#{user.discriminator}",
            "DESCRIPTION": description,
            "FISHY_AMOUNT": fishy or 0,
            "SERVER_LEVEL": util.get_level(server_xp),
            "GLOBAL_LEVEL": util.get_level(global_xp),
            "ACTIVITY_DATA": str(new_global_activity),
            "CHART_MAX": max(new_global_activity),
            "COMMANDS_USED": command_uses or 0,
            "BADGES": "\n".join(badges),
            "USERNAME_SIZE": get_font_size(user.name),
            "SHOW_GRAPH": "true" if show_graph else "false",
            "DESCRIPTION_HEIGHT": "250px" if show_graph else "350px",
        }

        payload = {
            "html": util.format_html(self.profile_html, replacements),
            "width": 600,
            "height": 400,
            "imageFormat": "png",
        }
        buffer = await util.render_html(self.bot, payload)
        await ctx.send(
            file=discord.File(fp=buffer, filename=f"profile_{user.name}.png"))