Source code for bTagScript.adapter.discord_adapters

from random import choice
from typing import Union

from discord import Guild, Member, TextChannel, Thread

from ..interface import Adapter
from ..utils import escape_content
from ..verb import Verb

__all__ = (
    "AttributeAdapter",
    "MemberAdapter",
    "ChannelAdapter",
    "GuildAdapter",
)


[docs]class AttributeAdapter(Adapter): """ Base attribute adapter for discord.py objects """ __slots__ = ("object", "_attributes", "_methods") def __init__(self, base: Union[TextChannel, Member, Guild]) -> None: """ Init for the attribute adapter """ self.object = base self._attributes = { "id": base.id, "created_at": base.created_at, "timestamp": int(base.created_at.timestamp()), "name": getattr(base, "name", str(base)), } self._methods = {} self.update_attributes() self.update_methods() def __repr__(self) -> str: """ printable repr """ return f"<{type(self).__qualname__} object={self.object!r}>"
[docs] def update_attributes(self) -> None: """ Update attributes for the block """
[docs] def update_methods(self) -> None: """ Update methods for the block """
[docs] def get_value(self, ctx: Verb) -> str: """ Get the value for the adapter """ should_escape = False if ctx.parameter is None: return_value = str(self.object) else: try: value = self._attributes[ctx.parameter] except KeyError: if method := self._methods.get(ctx.parameter): value = method() else: return if isinstance(value, tuple): value, should_escape = value return_value = str(value) if value is not None else None return escape_content(return_value) if should_escape else return_value
[docs]class MemberAdapter(AttributeAdapter): """ The ``{author}`` block with no parameters returns the tag invoker's full username and discriminator, but passing the attributes listed below to the block payload will return that attribute instead. **Aliases:** ``user`` **Usage:** ``{author([attribute])`` **Payload:** None **Parameter:** attribute, None Attributes ---------- id The author's Discord ID. name The author's username. nick The author's nickname, if they have one, else their username. avatar A link to the author's avatar, which can be used in embeds. discriminator The author's discriminator. created_at The author's account creation date. timestamp The author's account creation date as a UTC timestamp. joined_at The date the author joined the server. mention A formatted text that pings the author. bot Whether or not the author is a bot. color The author's top role's color as a hex code. top_role The author's top role. boost If the user boosted, this will be the the UTC timestamp of when they did, if not, this will be empty. timed_out If the user is timed out, this will be the the UTC timestamp of when they'll be "untimed-out", if not timed out, this will be empty. banner The users banner url roleids A list of the author's role IDs, split by spaces. """
[docs] def update_attributes(self) -> None: """ Update the adapter with all it's needed attributes """ additional_attributes = { "color": self.object.color, "colour": self.object.color, "nick": self.object.display_name, "avatar": (self.object.display_avatar.url, False), "discriminator": self.object.discriminator, "joined_at": getattr(self.object, "joined_at", ""), "mention": self.object.mention, "bot": self.object.bot, "top_role": getattr(self.object, "top_role", ""), "boost": getattr(self.object, "premium_since", ""), "timed_out": getattr(self.object, "timed_out_until", ""), "banner": self.object.banner.url if self.object.banner else "", } if roleids := getattr(self.object, "_roles", None): additional_attributes["roleids"] = " ".join(str(r) for r in roleids) self._attributes.update(additional_attributes)
[docs]class ChannelAdapter(AttributeAdapter): """ The ``{channel}`` block with no parameters returns the channel's full name but passing the attributes listed below to the block payload will return that attribute instead. **Usage:** ``{channel([attribute])`` **Payload:** None **Parameter:** attribute, None Attributes ---------- id The channel's ID. name The channel's name. created_at The channel's creation date. timestamp The channel's creation date as a UTC timestamp. nsfw Whether the channel is nsfw. mention A formatted text that pings the channel. topic The channel's topic. slowmode The channel's slowmode in seconds, 0 if disabled """
[docs] def update_attributes(self) -> None: """ Update block attributes """ if isinstance(self.object, TextChannel): additional_attributes = { "channel_type": "textchannel", "nsfw": self.object.nsfw, "mention": self.object.mention, "topic": self.object.topic or None, "slowmode": self.object.slowmode_delay, } self._attributes.update(additional_attributes) elif isinstance(self.object, Thread): pass
[docs]class GuildAdapter(AttributeAdapter): """ The ``{server}`` block with no parameters returns the server's name but passing the attributes listed below to the block payload will return that attribute instead. **Aliases:** ``guild`` **Usage:** ``{server([attribute])`` **Payload:** None **Parameter:** attribute, None Attributes ---------- id The server's ID. name The server's name. icon A link to the server's icon, which can be used in embeds. created_at The server's creation date. timestamp The server's creation date as a UTC timestamp. member_count The server's member count. bots The number of bots in the server. humans The number of humans in the server. description The server's description if one is set, or "No description". random A random member from the server. """
[docs] def update_attributes(self) -> None: """ Update block attributes """ guild = self.object bots = 0 humans = 0 for m in guild.members: if m.bot: bots += 1 else: humans += 1 member_count = guild.member_count additional_attributes = { "icon": guild.icon.url if guild.icon else "", "member_count": member_count, "members": member_count, "bots": bots, "humans": humans, "description": guild.description or "No description", } self._attributes.update(additional_attributes)
[docs] def update_methods(self) -> None: """ Update methods for the block """ additional_methods = {"random": self.random_member} self._methods.update(additional_methods)
[docs] def random_member(self) -> None: """ Return a random member """ return choice(self.object.members)