コード例 #1
0
    async def profile(self, ctx: Context, *, member: Member = None):
        """User's profile"""

        if not member:
            member = ctx.author

        user, _ = await User.get_or_create(id=member.id)
        # Calculate current level progress:
        # (exp - curr lvl req) * 100 / (curr lvl req - next lvl req)
        current_level_exp = (user.level * 4)**2
        next_level_exp = ((user.level + 1) * 4)**2
        progress = round((user.exp - current_level_exp) * 100 /
                         (next_level_exp - current_level_exp))
        # Find position of profile in global user ranking
        rank = (await User.all().order_by("-exp")).index(user)

        embed = Embed(ctx,
                      title=f"{member.name}'s profile",
                      color=member.color)
        embed.set_thumbnail(url=member.avatar_url)

        embed.add_fields(
            ("Rank", str(rank + 1)),
            ("Level", f"{user.level}"),
            ("Experience", f"{user.exp}/{next_level_exp} ({progress}%)"),
            ("Balance", f"{user.balance} coins"),
        )

        if mutes := await Mute.filter(guild__id=ctx.guild.id,
                                      user__id=member.id).count():
            embed.add_field(name="Mutes", value=str(mutes))
コード例 #2
0
ファイル: moderation.py プロジェクト: GHOSTL0V3/nagatoro
    async def mute(self,
                   ctx: Context,
                   member: Member,
                   time: Timedelta,
                   *,
                   reason: str = None):
        """Mute someone

        Muting someone gives them the mute role specified by the muterole command and removes the role after the specified time has passed.
        Note: Mutes are checked every 10 seconds, so times are not perfect.
        """

        mute = await Mute.filter(user__id=member.id,
                                 guild__id=ctx.guild.id,
                                 active=True).first()
        if mute:
            mute.end += time
            await mute.save()
            return await ctx.send(
                t(ctx, "message_extended", member=member, time=time))
            # NOTE: Extensions don't add a mute entry, they just make the
            # active mute longer.
            # return await ctx.send(f"{member.name} is already muted.")

        user, _ = await User.get_or_create(id=member.id)
        guild, _ = await Guild.get_or_create(id=ctx.guild.id)
        if not guild.mute_role:
            return await ctx.send(t(ctx, "no_mute_role", guild=ctx.guild))
        mute = await Mute.create(
            moderator=ctx.author.id,
            user=user,
            guild=guild,
            reason=reason,
            end=datetime.utcnow() + time,
        )

        mute_role = ctx.guild.get_role(guild.mute_role)
        # TODO: Check if member has lower permissions required to mute them
        await member.add_roles(
            mute_role,
            reason=f"Muted by {ctx.author} for {time}, reason: {reason}")

        embed = Embed(ctx, title=f"Mute [{mute.id}]", color=member.color)
        embed.set_thumbnail(url=member.avatar_url)
        embed.description = t(ctx,
                              "message",
                              member=member.mention,
                              time=time,
                              reason=reason)

        await ctx.send(embed=embed)

        try:
            await member.send(
                t(ctx, "dm_message", guild=ctx.guild, time=time,
                  reason=reason))
        except (Forbidden, HTTPException, AttributeError):
            pass
コード例 #3
0
ファイル: anime.py プロジェクト: mlunax/nagatoro
    async def character(self, ctx: Context, *, name: str):
        """Character info from AniList"""

        query = """
        query ($name: String) {
            Character (search: $name) {
                name {full}
                image {large}
                description (asHtml: false)
                siteUrl
                favourites
                media (perPage: 10) {
                    edges {
                        node {
                            title {romaji}
                            siteUrl
                        }
                        characterRole
                    }
                }
            }
        }
        """

        character = (await anilist(query, {"name": name}))["data"]["Character"]

        embed = Embed(ctx,
                      title=character["name"]["full"],
                      description="",
                      url=character["siteUrl"],
                      footer="Via AniList",
                      color=Color.blue())

        embed.set_thumbnail(url=character["image"]["large"])

        if character["favourites"]:
            embed.description += f"❤️ {character['favourites']} favorites \n\n"

        if character["description"]:
            description = clean_description(character["description"])
            embed.description += f"Description: ||{description[:250]}...||" \
                if len(description) >= 250 \
                else f"Description: ||{description}||"

        appears_in = ["Main 🌕 Supporting 🌗 Background 🌑"]
        for i in character["media"]["edges"]:
            role = i["characterRole"] \
                .replace("MAIN", "🌕") \
                .replace("SUPPORTING", "🌗") \
                .replace("BACKGROUND", "🌑")

            appears_in.append(f"{role} [{i['node']['title']['romaji']}]"
                              f"({i['node']['siteUrl']})")

        embed.add_field(name="Appears in", value="\n".join(appears_in))

        await ctx.send(embed=embed)
コード例 #4
0
ファイル: anime.py プロジェクト: GHOSTL0V3/nagatoro
    async def manga(self, ctx: Context, *, title: str):
        """Manga info from AniList"""

        query = """
        query ($title: String) {
            Media (search: $title, type: MANGA) {
                title {romaji}
                coverImage {extraLarge color}
                description (asHtml: false)
                siteUrl
                rankings {rank allTime type context}
                status
                chapters
                volumes
                format
                averageScore
                genres
            }
        }
        """
        manga = (await anilist(query, {"title": title}))["data"]["Media"]

        embed = Embed(
            ctx,
            title=manga["title"]["romaji"],
            description="",
            url=manga["siteUrl"],
            footer="Via AniList",
        )

        embed.set_thumbnail(url=manga["coverImage"]["extraLarge"])

        for i in manga["rankings"]:
            if not i["allTime"]:
                continue

            if i["type"] == "RATED":
                embed.description += "⭐"
            elif i["type"] == "POPULAR":
                embed.description += "❤️"

            embed.description += f" #{i['rank']} {i['context'].title()}\n"
        embed.description += "\n"

        if manga["description"]:
            description = clean_description(manga["description"])
            embed.description += (
                t(ctx, "synopsis_ellipsis", synopsis=description[:250])
                if len(description) >= 250
                else t(ctx, "synopsis", synopsis=description)
            )

        if color_hex := manga["coverImage"]["color"]:
            embed.color = Color(int(color_hex.replace("#", ""), 16))
コード例 #5
0
ファイル: anime.py プロジェクト: GHOSTL0V3/nagatoro
    async def anime(self, ctx: Context, *, title: str):
        """Anime info from AniList"""

        query = """
        query ($title: String) {
            Media (search: $title, type: ANIME) {
                title {romaji}
                coverImage {extraLarge color}
                description (asHtml: false)
                siteUrl
                rankings {rank allTime type context}
                status
                episodes
                duration
                season
                seasonYear
                format
                averageScore
                genres
                studios (isMain: true) {nodes {name}}
            }
        }
        """
        anime = (await anilist(query, {"title": title}))["data"]["Media"]

        embed = Embed(
            ctx,
            title=anime["title"]["romaji"],
            description="",
            url=anime["siteUrl"],
            footer="Via AniList",
        )

        embed.set_thumbnail(url=anime["coverImage"]["extraLarge"])

        for i in anime["rankings"]:
            if not i["allTime"]:
                continue

            if i["type"] == "RATED":
                embed.description += "⭐"
            elif i["type"] == "POPULAR":
                embed.description += "❤️"

            embed.description += f" #{i['rank']} {i['context'].title()}\n"
        embed.description += "\n"

        if description := clean_description(anime["description"]):
            embed.description += (
                t(ctx, "synopsis_ellipsis", synopsis=description[:250])
                if len(description) >= 250
                else t(ctx, "synopsis", synopsis=description)
            )
コード例 #6
0
ファイル: utility.py プロジェクト: mlunax/nagatoro
    async def user(self, ctx: Context, *, user: Union[Member, User] = None):
        """Shows info about an user or a member"""

        if not user:
            user = ctx.author

        title = str(user) if not user.bot else f"{user} :robot:"
        embed = Embed(ctx, title=title, color=user.color)
        embed.set_thumbnail(url=user.avatar_url)
        embed.add_fields(("ID", user.id), ("Created at", user.created_at))

        await ctx.send(embed=embed)
コード例 #7
0
ファイル: anime.py プロジェクト: GHOSTL0V3/nagatoro
    async def studio(self, ctx: Context, *, name: str):
        """Studio info from AniList"""

        query = """
        query ($name: String) {
            Studio (search: $name, sort: SEARCH_MATCH) {
                name
                siteUrl
                isAnimationStudio
                media (sort: POPULARITY_DESC, perPage: 10) {
                    nodes {
                        title {romaji}
                        coverImage {extraLarge}
                        siteUrl
                        popularity
                        favourites
                    }
                }
            }
        }
        """
        studio = (await anilist(query, {"name": name}))["data"]["Studio"]

        embed = Embed(
            ctx, title=studio["name"], url=studio["siteUrl"], footer="Via AniList"
        )

        embed.set_thumbnail(url=studio["media"]["nodes"][0]["coverImage"]["extraLarge"])

        if studio["isAnimationStudio"]:
            embed.description = t(ctx, "animation_studio")

        # TODO: Observe, if this breaks when isAnimationStudio=False.
        most_popular = [t(ctx, "most_popular_header")]
        for i in studio["media"]["nodes"]:
            most_popular.append(
                t(
                    ctx,
                    "most_popular_item",
                    popularity=i["popularity"],
                    favorites=i["favourites"],
                    title=i["title"]["romaji"],
                    url=i["siteUrl"],
                )
            )

        embed.add_field(
            name=t(ctx, "most_popular_title"), value="\n".join(most_popular)
        )

        await ctx.send(embed=embed)
コード例 #8
0
    async def server(self, ctx: Context):
        """Shows info about this server"""

        embed = Embed(ctx, title=ctx.guild.name)
        embed.set_thumbnail(url=ctx.guild.icon_url_as(size=2048))

        embed.add_fields(
            (t(ctx, "id"), ctx.guild.id),
            (t(ctx, "owner"), ctx.guild.owner.mention),
            (t(ctx, "region"), ctx.guild.region),
            (t(ctx, "members"), str(ctx.guild.member_count)),
            (t(ctx, "text_channels"), str(len(ctx.guild.text_channels))),
            (t(ctx, "voice_channels"), str(len(ctx.guild.voice_channels))),
        )

        await ctx.send(embed=embed)
コード例 #9
0
ファイル: anime.py プロジェクト: mlunax/nagatoro
    async def studio(self, ctx: Context, *, name: str):
        """Studio info from AniList"""

        query = """
        query ($name: String) {
            Studio (search: $name, sort: SEARCH_MATCH) {
                name
                siteUrl
                isAnimationStudio
                media (sort: POPULARITY_DESC, perPage: 10) {
                    nodes {
                        title {romaji}
                        coverImage {extraLarge}
                        siteUrl
                        popularity
                        favourites
                    }
                }
            }
        }
        """
        studio = (await anilist(query, {"name": name}))["data"]["Studio"]

        embed = Embed(ctx,
                      title=studio["name"],
                      url=studio["siteUrl"],
                      footer="Via AniList")

        embed.set_thumbnail(
            url=studio["media"]["nodes"][0]["coverImage"]["extraLarge"])

        if studio["isAnimationStudio"]:
            embed.description = "Animation Studio"

        # TODO: Observe, if this breaks when isAnimationStudio=False.
        most_popular = ["Popularity ⭐ Favorites ❤"]
        for i in studio["media"]["nodes"]:
            most_popular.append(f"{i['popularity']} ⭐ {i['favourites']} ❤️ "
                                f"[{i['title']['romaji']}]({i['siteUrl']}) ")

        embed.add_field(name="Most popular productions",
                        value="\n".join(most_popular))

        await ctx.send(embed=embed)
コード例 #10
0
ファイル: anime.py プロジェクト: GHOSTL0V3/nagatoro
    async def anilist(self, ctx: Context, *, username: str):
        """AniList profile

        Shows anime/manga stats and favorites.
        """

        query = """
        query ($username: String) {
            User (name: $username) {
                name
                avatar {large}
                siteUrl
                favourites {
                    anime {
                        nodes {title {romaji} siteUrl}
                    }
                    manga {
                        nodes {title {romaji} siteUrl}
                    }
                    characters {
                        nodes {name {full} siteUrl}
                    }
                    staff {
                        nodes {name {full} siteUrl}
                    }
                    studios {
                        nodes {name siteUrl}
                    }
                }
            }
        }
        """
        list_query = """
        query ($username: String, $type: MediaType) {
            MediaListCollection (userName: $username, type: $type) {
                lists {status name entries {id}}
            }
        }
        """

        await ctx.trigger_typing()
        user = (await anilist(query, {"username": username}))["data"]["User"]
        anime_lists, manga_lists = [
            (await anilist(list_query, {"username": username, "type": i}))["data"][
                "MediaListCollection"
            ]["lists"]
            for i in ["ANIME", "MANGA"]
        ]

        embed = Embed(
            ctx,
            title=t(ctx, "title", user=user["name"]),
            url=user["siteUrl"],
            footer="Via AniList",
        )

        embed.set_thumbnail(url=user["avatar"]["large"])

        if anime_lists:
            anime_list_body = ""
            for i in anime_lists:
                if i["status"]:
                    status = (
                        i["status"]
                        .replace("COMPLETED", "✅")
                        .replace("PLANNING", "🗓️")
                        .replace("DROPPED", "🗑️")
                        .replace("CURRENT", "📺")
                        .replace("PAUSED", "⏸️")
                        .replace("REPEATING", "🔁")
                    )
                else:
                    status = "⚙️"

                anime_list_body += f"{status} **{len(i['entries'])}** " f"{i['name']}\n"

            embed.add_field(name=t(ctx, "anime"), value=anime_list_body)

        if manga_lists:
            manga_list_body = ""
            for i in manga_lists:
                if i["status"]:
                    status = (
                        i["status"]
                        .replace("COMPLETED", "✅")
                        .replace("PLANNING", "🗓️")
                        .replace("DROPPED", "🗑️️")
                        .replace("CURRENT", "📖")
                        .replace("PAUSED", "⏸️")
                        .replace("REPEATING", "🔁")
                    )
                else:
                    status = "⚙️"

                manga_list_body += f"{status} **{len(i['entries'])}** " f"{i['name']}\n"

            embed.add_field(name=t(ctx, "manga"), value=manga_list_body)

        if any(user["favourites"][i]["nodes"] for i in user["favourites"]):
            favorites_body = ""
            for i in user["favourites"]:
                if not user["favourites"][i]["nodes"]:
                    continue

                # Section header
                favorites_body += f"__{i.title()}__"

                # Show total amount of favs if they exceed a limit (3)
                if (favorites_count := len(user["favourites"][i]["nodes"])) > 3:
                    favorites_body += f" ({favorites_count})"
                favorites_body += "\n"

                for item in user["favourites"][i]["nodes"][:3]:
                    # There are three types of names, so unify them.
                    if i in ["anime", "manga"]:
                        name = item["title"]["romaji"]
                    elif i in ["characters", "staff"]:
                        name = item["name"]["full"]
                    else:
                        name = item["name"]

                    favorites_body += f"[{name}]({item['siteUrl']})\n"

            embed.add_field(
                name=t(ctx, "favorites"), value=favorites_body, inline=False
            )
コード例 #11
0
ファイル: anime.py プロジェクト: GHOSTL0V3/nagatoro
    async def character(self, ctx: Context, *, name: str):
        """Character info from AniList"""

        query = """
        query ($name: String) {
            Character (search: $name) {
                name {full}
                image {large}
                description (asHtml: false)
                siteUrl
                favourites
                media (perPage: 10) {
                    edges {
                        node {
                            title {romaji}
                            siteUrl
                        }
                        characterRole
                    }
                }
            }
        }
        """

        character = (await anilist(query, {"name": name}))["data"]["Character"]

        embed = Embed(
            ctx,
            title=character["name"]["full"],
            description="",
            url=character["siteUrl"],
            footer="Via AniList",
            color=Color.blue(),
        )

        embed.set_thumbnail(url=character["image"]["large"])

        if character["favourites"]:
            embed.description += (
                t(ctx, "favorites", favorites=character["favourites"]) + "\n\n"
            )

        if character["description"]:
            description = clean_description(character["description"])
            embed.description += (
                t(ctx, "character_description_ellipsis", description=description[:250])
                if len(description) >= 250
                else t(ctx, "character_description", description=description)
            )

        appears_in = [t(ctx, "appears_in_header")]
        for i in character["media"]["edges"]:
            role = (
                i["characterRole"]
                .replace("MAIN", "🌕")
                .replace("SUPPORTING", "🌗")
                .replace("BACKGROUND", "🌑")
            )

            appears_in.append(
                t(
                    ctx,
                    "appears_in_item",
                    role=role,
                    title=i["node"]["title"]["romaji"],
                    url=i["node"]["siteUrl"],
                )
            )

        embed.add_field(name=t(ctx, "appears_in_title"), value="\n".join(appears_in))

        await ctx.send(embed=embed)