async def _from(
        self,
        ctx: context.CustomContext,
        *,
        person: Fuzzy[
            CaseInsensitiveMember, CaseInsensitiveUser, FuzzySettings(weights=(5, 1))
        ] = None,
    ):
        """List the tags that someone made on this server"""

        member = person or ctx.author
        all_tags = await self.bot.db.fetch(
            "SELECT * FROM tag WHERE author = $1 AND guild_id = $2 ORDER BY uses desc",
            member.id,
            ctx.guild.id,
        )

        pretty_tags = []

        for record in all_tags:
            pretty_tags.append(
                f"`{config.BOT_PREFIX}{record['name']}`  {escape_markdown(record['title'])}"
            )

        pages = paginator.SimplePages(
            entries=pretty_tags,
            author=f"Tags from {member.display_name}",
            icon=member.display_avatar.url,
            empty_message=f"{member} hasn't made any tags on this server yet.",
            per_page=12,
        )
        await pages.start(ctx)
Beispiel #2
0
    async def list_npcs(
        self,
        ctx: CustomContext,
        *,
        person: Fuzzy[
            converter.CaseInsensitiveMember,
            converter.CaseInsensitiveUser,
            FuzzySettings(weights=(5, 1)),
        ] = None,
    ):
        """List every NPC you or someone else has access to

        **Example**
           `{PREFIX}{COMMAND}` list all of your NPCs
           `{PREFIX}{COMMAND} @DerJonas` to see what NPCs someone else has access to
           `{PREFIX}{COMMAND} DerJonas#8036`
           `{PREFIX}{COMMAND} Jonas`"""

        member = person or ctx.author
        npcs = [self._npc_cache[i] for i in self._npc_access_cache[member.id]]
        npcs.sort(key=lambda npc: npc["id"])

        pretty_npcs = []

        for record in npcs:
            avatar = (
                f"[Avatar]({record['avatar_url']})\n" if record["avatar_url"] else ""
            )

            owner = self.bot.get_user(record["owner_id"])
            owner_value = (
                "\n"
                if not owner
                else f"Owner: {owner.mention} {escape_markdown(str(owner))}\n"
            )

            pretty_npcs.append(
                f"**__NPC #{record['id']} - {escape_markdown(record['name'])}__**"
            )
            pretty_npcs.append(
                f"{avatar}Trigger Phrase: `{escape_markdown(record['trigger_phrase'])}`"
            )
            pretty_npcs.append(owner_value)

        if pretty_npcs:
            pretty_npcs.insert(
                0,
                f"You can create a new NPC with `{config.BOT_PREFIX}npc create`, "
                f"or edit the name, avatar and/or trigger phrase of an existing one with "
                f"`{config.BOT_PREFIX}npc edit <npc>`.\n",
            )

        pages = paginator.SimplePages(
            author=f"{member.display_name}'s NPCs",
            icon=member.display_avatar.url,
            entries=pretty_npcs,
            per_page=20,
            empty_message="This person hasn't made any NPCs yet.",
        )
        await pages.start(ctx)
    async def clear(
        self,
        ctx,
        amount: int,
        *,
        target: Fuzzy[CaseInsensitiveMember, CaseInsensitiveUser,
                      FuzzySettings(weights=(5, 1))] = None,
    ):
        """Purge an amount of messages in the current channel"""
        if amount > 500 or amount < 0:
            return await ctx.send(
                f"{config.NO} You can only clear up to 500 messages at most.")

        def check(message):
            if target:
                return message.author.id == target.id
            return True

        try:
            deleted = await ctx.channel.purge(limit=amount, check=check)
        except discord.Forbidden:
            raise exceptions.ForbiddenError(task=ForbiddenTask.MESSAGE_DELETE)

        await ctx.send(f"{config.YES} Deleted **{len(deleted)}** messages.",
                       delete_after=5)
Beispiel #4
0
 async def _from(
     self,
     ctx,
     *,
     person_or_party: Fuzzy[
         CaseInsensitiveMember,
         CaseInsensitiveUser,
         PoliticalParty,
         FuzzySettings(weights=(5, 1, 2)),
     ] = None,
 ):
     """List the laws a specific person or Political Party authored"""
     return await self._from_person_model(
         ctx, model=models.Law, member_or_party=person_or_party
     )
Beispiel #5
0
    async def set_channel_perms(self,
                                ctx,
                                *,
                                channel: Fuzzy[
                                    CaseInsensitiveTextChannel] = None):
        """Toggle Read and/or Send Messages permissions for a role or person in one of your nation's channels"""

        if not channel:
            channel = await ctx.converted_input(
                f"{config.USER_INTERACTION_REQUIRED} Which channel's permissions should be changed?",
                converter=Fuzzy[CaseInsensitiveTextChannel],
                return_input_on_fail=False,
            )

        if channel.category_id not in self.bot.mk.NATION_CATEGORIES:
            return await ctx.send(
                f"{config.NO} The `{channel.name}` channel does not belong to your nation."
            )

        user_input = await ctx.input(
            f"{config.USER_INTERACTION_REQUIRED} For which role *or* person should the "
            f"permissions in {channel.mention} be changed?")

        conv = Fuzzy[CaseInsensitiveRole, CaseInsensitiveMember,
                     FuzzySettings(weights=(6, 4))]
        role = await conv.convert(ctx, user_input)

        overwrites = channel.overwrites_for(role)

        result = await PermissionSelectorMenu(
            role=role, channel=channel, overwrites=overwrites).prompt(ctx)

        if not result.confirmed:
            return await ctx.send(
                f"{config.NO} You didn't decide on which permission(s) to change."
            )

        permission_to_change = result.result

        if permission_to_change["read"]:
            overwrites.read_messages = not overwrites.read_messages

        if permission_to_change["send"]:
            overwrites.send_messages = not overwrites.send_messages

        await channel.set_permissions(target=role, overwrite=overwrites)
        await ctx.send(f"{config.YES} Done.")
    async def vibecheck(
        self,
        ctx,
        *,
        person: Fuzzy[CaseInsensitiveMember, CaseInsensitiveUser,
                      FuzzySettings(weights=(5, 1))] = None,
    ):
        """vibecheck"""

        member = person or ctx.author

        not_vibing = [
            "https://i.kym-cdn.com/entries/icons/mobile/000/031/163/Screen_Shot_2019-09-16_at_10.22.26_AM.jpg",
            "https://s3.amazonaws.com/media.thecrimson.com/photos/2019/11/18/194724_1341037.png",
            "https://i.kym-cdn.com/photos/images/newsfeed/001/574/493/3ab.jpg",
            "https://i.imgflip.com/3ebtvt.jpg",
            "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT814jrNuqJsaVVHGqWw_0snlcysLN5fLpocEYrx6hzkgXYx7RV5w&s",
            "https://img.buzzfeed.com/buzzfeed-static/static/2019-10/7/15/asset/c5dd65974640/sub-buzz-521-1570462442-1.png?downsize=700:*&output-format=auto&output-quality=auto",
            "https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/12132fe4-1709-4287-9dcc-4ee9fc252a01/ddk55pz-bf72cab3-2b9e-474e-94a8-00e5f53d2baf.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7InBhdGgiOiJcL2ZcLzEyMTMyZmU0LTE3MDktNDI4Ny05ZGNjLTRlZTlmYzI1MmEwMVwvZGRrNTVwei1iZjcyY2FiMy0yYjllLTQ3NGUtOTRhOC0wMGU1ZjUzZDJiYWYuanBnIn1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmZpbGUuZG93bmxvYWQiXX0.Sb6Axu0O6iZ3YmZJHg5wRe-r41iLnWVqa_ddWrtbQlo",
            "https://pbs.twimg.com/media/EHgYHjOX4AAuv6s.jpg",
            "https://pbs.twimg.com/media/EGTsxzaUwAAuBLG?format=jpg&name=900x900",
            "https://66.media.tumblr.com/c2fc65d9f8614dbd9bb7378983e0598e/tumblr_pxw332rEmZ1yom1s3o1_1280.png",
        ]

        vibing = [
            "https://i.redd.it/ax6jb6lhdah31.jpg",
            "https://i.redd.it/3a6nr5b3u4x31.png",
            "https://i.kym-cdn.com/photos/images/original/001/599/028/bf3.jpg",
            "https://i.redd.it/p4e6a65i3bw31.jpg",
            "https://media.makeameme.org/created/congratulations-you-have-61e05e0d4b.jpg",
        ]

        passed = True if random.randrange(1, stop=100) >= 65 else False

        if passed:
            image = random.choice(vibing)
            pretty = "passed"
        else:
            image = random.choice(not_vibing)
            pretty = "not passed"

        embed = text.SafeEmbed(
            title=f"{member} has __{pretty}__ the vibe check", )

        embed.set_image(url=image)
        await ctx.send(embed=embed)
    async def whohas(
        self,
        ctx,
        *,
        role: Fuzzy[CaseInsensitiveRole, DemocracivCaseInsensitiveRole,
                    PoliticalParty,
                    FuzzySettings(
                        no_choice_exception=
                        f"{config.NO} There is no role on this or the "
                        f"Democraciv server that matches `{{argument}}`.",
                        weights=(5, 2, 2),
                    ), ],
    ):
        """Detailed information about a role"""

        if isinstance(role, PoliticalParty):
            role = role.role

        await self.role_info(ctx, role)
Beispiel #8
0
    async def npc(self, ctx: CustomContext, *, npc: str = ""):
        """What is an NPC?"""

        if ctx.invoked_with.lower() == "npcs":
            if npc:
                conv = Fuzzy[
                    converter.CaseInsensitiveMember,
                    converter.CaseInsensitiveUser,
                    FuzzySettings(weights=(5, 1)),
                ]
                person = await conv.convert(ctx, npc)

            else:
                person = ctx.author

            return await ctx.invoke(self.bot.get_command("npc list"), person=person)

        if npc:
            converted = await Fuzzy[AnyNPCConverter].convert(ctx, npc)
            return await ctx.invoke(self.bot.get_command("npc info"), npc=converted)

        p = config.BOT_PREFIX
        embed = text.SafeEmbed(
            description=f"NPCs allow you to make it look like you speak as a different character, "
            f"or on behalf of someone else, like an organization or group.\n\n"
            f"This can elevate the role-playing experience by making it clear "
            f"when someone talks in character, or out-of-character (OOC). "
            f"Political parties, newspapers, government departments or other groups can "
            f"use this to release official looking announcements.\n\n"
            f"To get started, you can create a new NPC with `{p}npc create`. NPCs are "
            f"not bound to any server, every NPC that you make on this server can "
            f"also be used in every other server I am in.\n\nServer administrators "
            f"can disable NPC usage on their server for any reason with "
            f"the `{p}server npc` command.\n\n\nSee `{p}help npcs` or "
            f"`{p}commands` to see every NPC-related command and learn more about them."
        )

        embed.set_author(name="What are NPCs?", icon_url=self.bot.dciv.icon.url)
        embed.set_image(
            url="https://cdn.discordapp.com/attachments/818226072805179392/818230819835215882/npc.gif"
        )
        await ctx.send(embed=embed)
    async def transfer(
        self,
        ctx: context.CustomContext,
        to_person: Fuzzy[
            CaseInsensitiveMember, CaseInsensitiveUser, FuzzySettings(weights=(5, 1))
        ],
        *,
        tag: OwnedTag,
    ):
        """Transfer a tag of yours to someone else"""

        if to_person == ctx.author:
            return await ctx.send(
                f"{config.NO} You cannot transfer your tag to yourself."
            )

        await self.bot.db.execute(
            "UPDATE tag SET author = $1 WHERE id = $2", to_person.id, tag.id
        )
        return await ctx.send(
            f"{config.YES} {to_person} is now the owner of `{config.BOT_PREFIX}{tag.name}`."
        )
    async def avatar(
        self,
        ctx,
        *,
        person: Fuzzy[CaseInsensitiveMember, CaseInsensitiveUser,
                      FuzzySettings(weights=(5, 1))] = None,
    ):
        """View someone's avatar in detail

        **Example**
             `{PREFIX}{COMMAND}`
             `{PREFIX}{COMMAND} @DerJonas`
             `{PREFIX}{COMMAND} DerJonas`
             `{PREFIX}{COMMAND} DerJonas#8109`
        """

        member: discord.Member = person or ctx.author
        avatar_png = member.display_avatar.with_size(4096).url
        embed = text.SafeEmbed()
        embed.set_image(url=avatar_png)
        embed.set_author(name=member, icon_url=avatar_png, url=avatar_png)
        await ctx.send(embed=embed)
    async def stats(
        self,
        ctx: context.CustomContext,
        *,
        person: Fuzzy[
            CaseInsensitiveMember, CaseInsensitiveUser, FuzzySettings(weights=(5, 1))
        ] = None,
    ):
        """View general statistics or statistics about a specific person

        **Example**
            `{PREFIX}{COMMAND}` to view general statistics
            `{PREFIX}{COMMAND} DerJonas` to view statistics specific to that person"""

        if person:
            return await self._person_stats(ctx, person)

        total = await self.bot.db.fetch(
            "SELECT COUNT(name) FROM tag "
            "UNION ALL "
            "SELECT COUNT(name) FROM tag WHERE guild_id = $1 "
            "UNION ALL "
            "SELECT COUNT(name) FROM tag WHERE global = true",
            ctx.guild.id,
        )

        total_total = total[0]["count"]
        total_local = total[1]["count"]
        total_global = total[2]["count"]

        top_global_tags = await self.bot.db.fetch(
            "SELECT name, uses FROM tag WHERE global = true "
            "ORDER BY uses DESC LIMIT 5"
        )

        top_server_tags = await self.bot.db.fetch(
            "SELECT name, uses FROM tag WHERE guild_id = $1 "
            "ORDER BY uses DESC LIMIT 5",
            ctx.guild.id,
        )

        top_local_tags = await self.bot.db.fetch(
            "SELECT name, uses FROM tag WHERE global = false AND guild_id = $1 "
            "ORDER BY uses DESC LIMIT 5",
            ctx.guild.id,
        )

        embed = text.SafeEmbed(
            description=f"There are {total_total} tags in total, of which "
            f"{total_global} are global. {total_local} are from this server."
        )
        embed.set_author(name=f"Tags on {ctx.guild.name}", icon_url=ctx.guild_icon)

        embed.add_field(
            name="Top Global Tags", value=self._fmt_stats(top_global_tags), inline=False
        )
        embed.add_field(
            name="Top Tags from this Server (Global and Local)",
            value=self._fmt_stats(top_server_tags),
            inline=False,
        )
        embed.add_field(
            name="Top Local Tags from this Server",
            value=self._fmt_stats(top_local_tags),
            inline=False,
        )

        cog = self.bot.get_cog(self.bot.mk.LEGISLATURE_NAME)

        if cog:
            top_tag_creators = await self.bot.db.fetch(
                "SELECT author FROM tag WHERE guild_id = $1", ctx.guild.id
            )
            value = cog.format_stats(
                record=top_tag_creators, record_key="author", stats_name="tags"
            )

            top_global_tag_creators = await self.bot.db.fetch(
                "SELECT author FROM tag WHERE global = true"
            )
            global_value = cog.format_stats(
                record=top_global_tag_creators,
                record_key="author",
                stats_name="global tags",
            )

            embed.add_field(
                name="People with the most Global Tags from any Server",
                value=global_value,
                inline=False,
            )
            embed.add_field(
                name="People with the most Tags from this Server",
                value=value,
                inline=False,
            )

        await ctx.send(embed=embed)
Beispiel #12
0
    async def send(
        self,
        ctx,
        to_person_or_iban_or_organization: Fuzzy[
            converter.CaseInsensitiveMember, converter.CaseInsensitiveUser,
            BankCorporationAbbreviation, BankUUIDConverter,
            FuzzySettings(weights=(5, 1)), ],
        amount: decimal.Decimal,
        *,
        purpose: str = None,
    ):
        """Send money to a specific bank account, organization, or person on this server

        **Examples**
            `-bank send @DerJonas 9.99`
            `-bank send DerJonas#8036 250`
            `-bank send c4a3ec17-cba4-462f-bdda-05620f574dce 32.10 Thanks ;)`
            `-bank send GOOGLE 1000.21` assuming 'GOOGLE' is the abbreviation of an existing, published organization
        """

        await self.is_connected_with_bank_user(ctx)
        currency = ""

        if not isinstance(to_person_or_iban_or_organization, uuid.UUID):
            # if IBAN, skip currency selection
            embed = text.SafeEmbed(
                title=f"{config.USER_INTERACTION_REQUIRED}  Currency Selection",
                description=
                "Since you did not specify an IBAN to send the money to, "
                "I cannot automatically determine the currency for this "
                "transaction. Once you've chosen a currency, I will send the money to the recipient's "
                "default account for the chosen currency.\n\n"
                "This only works provided that the recipient have previously selected a default account "
                "for the chosen currency on [democracivbank.com](https://democracivbank.com).",
            )

            view = CurrencySelector(ctx, self._currencies)
            msg = await ctx.send(embed=embed, view=view)
            currency = await view.prompt()

            if not currency:
                return

            await msg.delete()

        if isinstance(to_person_or_iban_or_organization,
                      (discord.Member, discord.User)):
            to_iban = await self.resolve_iban(
                to_person_or_iban_or_organization.id, currency)
        elif isinstance(to_person_or_iban_or_organization, str):
            to_iban = await self.resolve_iban(
                to_person_or_iban_or_organization, currency)
        else:
            # is UUID
            to_iban = str(to_person_or_iban_or_organization)
            currency = await self.get_currency_from_iban(to_iban)

        view = PickBankAccountView(ctx, currency, amount, to_iban)
        msg = await ctx.send(
            content=
            f"{config.USER_INTERACTION_REQUIRED} From what bank account would you like to send "
            f"the money?",
            view=view,
        )

        from_iban = await view.prompt()
        await msg.delete()

        if not from_iban:
            return

        pretty_amount = self.get_currency(currency).with_amount(amount)
        fmt = ""

        if isinstance(to_person_or_iban_or_organization, discord.abc.User):
            fmt = to_person_or_iban_or_organization.mention
        elif isinstance(to_person_or_iban_or_organization, str):
            r = await self.request(BankRoute("GET", f"account/{to_iban}/"))
            pretty_target = await r.json()
            fmt = f"**{pretty_target['corporate_holder']['name']}**"

        em = text.SafeEmbed(
            title=f"{config.USER_INTERACTION_REQUIRED}  Confirm Transaction",
            description=f"Do you really want to send **{pretty_amount}** "
            f"to {fmt}?",
        )
        v = ConfirmView(ctx)
        m = await ctx.send(embed=em, view=v)

        result = await v.prompt()
        await m.delete()

        if not result:
            return

        purpose = "Sent via the Democraciv Discord Bot" if not purpose else purpose
        transaction = await self.send_money(ctx.author.id, from_iban, to_iban,
                                            amount, purpose)

        embed = text.SafeEmbed(
            title=
            f"You sent {pretty_amount} to {transaction['safe_to_account']}",
            description=
            f"[See the transaction details here.](https://democracivbank.com/transaction/{transaction['id']})",
        )
        embed.set_author(name=self.BANK_NAME, icon_url=self.BANK_ICON_URL)
        await ctx.send(embed=embed)
    async def whois(
        self,
        ctx,
        *,
        person: Fuzzy[CaseInsensitiveMember, CaseInsensitiveUser,
                      CaseInsensitiveRole, DemocracivCaseInsensitiveRole,
                      PoliticalParty,
                      FuzzySettings(weights=(5, 2, 1, 1, 0)), ] = None,
    ):
        """See detailed information about someone

        **Example**
         `{PREFIX}{COMMAND}`
         `{PREFIX}{COMMAND} Jonas - u/Jovanos`
         `{PREFIX}{COMMAND} @DerJonas`
         `{PREFIX}{COMMAND} DerJonas`
         `{PREFIX}{COMMAND} deRjoNAS`
         `{PREFIX}{COMMAND} DerJonas#8109`
         `{PREFIX}{COMMAND} 212972352890339328`
        """
        def _get_roles(roles):
            fmt = []

            for role in roles[::-1]:
                if not role.is_default():
                    fmt.append(role.mention)

            if not fmt:
                return "-"
            else:
                return ", ".join(fmt)

        if isinstance(person, discord.Role):
            return await self.role_info(ctx, person)

        elif isinstance(person, PoliticalParty):
            return await self.role_info(ctx, person.role)

        member = person or ctx.author
        embed = text.SafeEmbed()

        if isinstance(member, discord.User):
            embed.description = ":warning: This person is not here in this server."

        embed.add_field(name="Person",
                        value=f"{member} {member.mention}",
                        inline=False)
        embed.add_field(name="ID", value=member.id, inline=False)
        embed.add_field(
            name="Discord Registration",
            value=f'{member.created_at.strftime("%B %d, %Y")}',
            inline=True,
        )

        if isinstance(member, discord.Member):
            join_pos, max_members = await self.get_member_join_position(
                member, ctx.guild.members)

            if not join_pos:
                join_pos = "Unknown"

            embed.add_field(
                name="Joined",
                value=
                f'{(await self.get_member_join_date(member)).strftime("%B %d, %Y")}',
                inline=True,
            )
            embed.add_field(name="Join Position",
                            value=f"{join_pos}/{max_members}",
                            inline=True)
            embed.add_field(
                name=f"Roles ({len(member.roles) - 1})",
                value=_get_roles(member.roles),
                inline=False,
            )

        embed.set_thumbnail(url=member.display_avatar.url)
        await ctx.send(embed=embed)