Source code for curious.dataclasses.webhook

# This file is part of curious.
#
# curious is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# curious is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with curious.  If not, see <http://www.gnu.org/licenses/>.

"""
Wrappers for Webhook objects.

.. currentmodule:: curious.dataclasses.webhook
"""

import typing

from curious.dataclasses import channel as dt_channel, embed as dt_embed, guild as dt_guild, \
    user as dt_user
from curious.dataclasses.bases import Dataclass
from curious.util import base64ify


[docs]class Webhook(Dataclass): """ Represents a webhook on the guild. Messages in a guild can be sent by either a Member or a Webhook object - curious makes a key distinction between them. These classes are *mostly* compatible and don't require much effort to use them generically. .. code-block:: python3 @event("message_create") async def handle_messages(ctx, message: Message): author = message.author # can be Webhook or Member """ __slots__ = "user", "guild_id", "channel_id", "token", "owner", \ "default_name", "_default_avatar" def __init__(self, client, **kwargs) -> None: # Use the webhook ID is provided (i.e created from a message object). # If that doesn't exist, we use the ID of the data instead (it's probably right!). super().__init__(kwargs.get("webhook_id", kwargs.get("id")), cl=client) #: The user object associated with this webhook. self.user = None # type: dt_user.User #: The ID of the Guild associated with this object. self.guild_id = None # type: int #: The ID of the Channel associated with this object. self.channel_id = None # type: int #: The token associated with this webhook. #: This is None if the webhook was received from a Message object. self.token = kwargs.get("token", None) # type: str #: The owner of this webhook. self.owner = None # type: dt_user.User #: The default name of this webhook. self.default_name = None # type: str #: The default avatar of this webhook. self._default_avatar = None # type: str def __repr__(self) -> str: return "<Webhook id={} name={} channel={} owner={}>".format(self.id, self.name, repr(self.channel), repr(self.owner)) __str__ = __repr__ @property def default_avatar_url(self) -> str: """ :return: The default avatar URL for this webhook. """ return "https://cdn.discordapp.com/avatars/{}/{}.png".format(self.id, self._default_avatar) @property def avatar_url(self) -> str: """ :return: The computed avatar URL for this webhook. """ if self.user.avatar_hash is None: return self.default_avatar_url return str(self.user.avatar_url) @property def name(self) -> str: """ :return: The computed name for this webhook. """ # this is kept so you can easily do `message.author.name` all the time. return self.user.name or self.default_name @property def guild(self) -> 'dt_guild.Guild': """ :return: The :class:`.Guild` this webhook is in. """ return self._bot.guilds.get(self.guild_id) @property def channel(self) -> 'dt_channel.Channel': """ :return: The :class:`.Channel` this webhook is in. """ if self.guild is None: return None return self.guild.channels.get(self.channel_id)
[docs] @classmethod async def create(cls, channel: 'dt_channel.Channel', *, name: str, avatar: bytes) -> 'Webhook': """ Creates a new webhook. :param channel: The :class:`.Channel` to create the webhook in. :param name: The name of the webhook to create. :param avatar: The bytes data for the webhook's default avatar. :return: A new :class:`.Webhook`. """ return await channel.create_webhook(name=name, avatar=avatar)
[docs] async def get_token(self) -> str: """ Gets the token for this webhook, if no token was set earlier. :return: The token for the webhook. """ if self.token: return self.token us = await self._bot.http.get_webhook(self.id) self.token = us.get("token") return self.token
[docs] async def delete(self) -> None: """ Deletes the webhook. You must either be the owner of this webhook, or the webhook must have a token associated to delete it. """ if self.token is not None: return await self._bot.http.delete_webhook_with_token(self.id, self.token) else: return await self.guild.delete_webhook(self)
[docs] async def edit(self, *, name: str = None, avatar: bytes = None) -> 'Webhook': """ Edits this webhook. :param name: The new name for this webhook. :param avatar: The bytes-encoded content of the new avatar. :return: The webhook object. """ if avatar is not None: avatar = base64ify(avatar) if self.token is not None: # edit with token, don't pass to guild data = await self._bot.http.edit_webhook_with_token(self.id, name=name, avatar=avatar) self.default_name = data.get("name") self._default_avatar = data.get("avatar") # Update the user too self.user.username = data.get("name") self.user.avatar_hash = data.get("avatar") else: await self.channel.edit_webhook(self, name=name, avatar=avatar) return self
[docs] async def execute(self, *, content: str = None, username: str = None, avatar_url: str = None, embeds: 'typing.List[dt_embed.Embed]'=None, wait: bool = False) \ -> typing.Union[None, str]: """ Executes the webhook. :param content: Any raw content to send. :param username: A username to override the default username of the webhook with. :param avatar_url: The URL for the avatar to override the default avatar with. :param embeds: A list of embeds to add to the message. :param wait: Should we wait for the message to arrive before returning? """ if embeds: embeds = [embed.to_dict() for embed in embeds] if self.token is None: await self.get_token() data = await self._bot.http.execute_webhook(self.id, self.token, content=content, embeds=embeds, username=username, avatar_url=avatar_url, wait=wait) if wait: return self._bot.state.make_message(data, cache=False)