示例#1
0
class MessageEmbed(SlottedModel):
    """
    Message embed object.

    Attributes
    ----------
    title : str
        Title of the embed.
    type : str
        Type of the embed.
    description : str
        Description of the embed.
    url : str
        URL of the embed.
    """
    title = Field(text)
    type = Field(str, default='rich')
    description = Field(text)
    url = Field(text)
    timestamp = Field(lazy_datetime)
    color = Field(int)
    footer = Field(MessageEmbedFooter)
    image = Field(MessageEmbedImage)
    thumbnail = Field(MessageEmbedThumbnail)
    video = Field(MessageEmbedVideo)
    author = Field(MessageEmbedAuthor)
    fields = ListField(MessageEmbedField)
示例#2
0
class GuildEmoji(Emoji):
    """
    An emoji object.

    Attributes
    ----------
    id : snowflake
        The ID of this emoji.
    name : str
        The name of this emoji.
    require_colons : bool
        Whether this emoji requires colons to use.
    managed : bool
        Whether this emoji is managed by an integration.
    roles : list(snowflake)
        Roles this emoji is attached to.
    """
    id = Field(snowflake)
    guild_id = Field(snowflake)
    name = Field(text)
    require_colons = Field(bool)
    managed = Field(bool)
    roles = ListField(snowflake)

    @property
    def url(self):
        return 'https://discordapp.com/api/emojis/{}.png'.format(self.id)

    @cached_property
    def guild(self):
        return self.client.state.guilds.get(self.guild_id)
示例#3
0
class WatcherChangeParserResult(GatewayEvent):
    app_id = Field(str)
    branch_name = Field(str)
    branch_version = Field(str)
    parser = Field(str)  # name of parser
    result = ListField(str)  # absolute path to some files

    def __str__(self):
        return "[{}][{}][{}]".format(self.app_id, self.parser, self.result)
示例#4
0
class GuildPreview(SlottedModel):
    id = Field(int)
    name = Field(str)
    icon = Field(str)
    splash = Field(str)
    discovery_splash = Field(str)
    emojis = AutoDictField(GuildEmoji, 'id')
    features = ListField(str)
    approximate_member_count = Field(int)
    approximate_presence_count = Field(int)
    description = Field(str)
示例#5
0
class GuildEmojisUpdate(GatewayEvent):
    """
    Sent when a guild's emojis are updated.

    Attributes
    -----
    guild_id : snowflake
        The ID of the guild the emojis are being updated in.
    emojis : list[:class:`disco.types.guild.Emoji`]
        The new set of emojis for the guild
    """
    guild_id = Field(snowflake)
    emojis = ListField(Emoji)
示例#6
0
class MessageDeleteBulk(GatewayEvent):
    """
    Sent when multiple messages are deleted from a channel.

    Attributes
    -----
    channel_id : snowflake
        The channel the messages are being deleted in.
    ids : list[snowflake]
        List of messages being deleted in the channel.
    """
    channel_id = Field(snowflake)
    ids = ListField(snowflake)
示例#7
0
class GuildMembersChunk(GatewayEvent):
    """
    Sent in response to a member's chunk request.

    Attributes
    -----
    guild_id : snowflake
        The ID of the guild this member chunk is for.
    members : list[:class:`disco.types.guild.GuildMember`]
        The chunk of members.
    not_found : list[snowflake]
        An array of invalid requested guild members.
    presences : list[:class:`disco.types.user.Presence`]
        An array of requested member presence states.
    """
    guild_id = Field(snowflake)
    members = ListField(GuildMember)
    not_found = ListField(snowflake)
    presences = ListField(Presence)

    @property
    def guild(self):
        return self.client.state.guilds.get(self.guild_id)
示例#8
0
class Ready(GatewayEvent):
    """
    Sent after the initial gateway handshake is complete. Contains data required
    for bootstrapping the client's states.

    Attributes
    -----
    version : int
        The gateway version.
    session_id : str
        The session ID.
    user : :class:`disco.types.user.User`
        The user object for the authed account.
    guilds : list[:class:`disco.types.guild.Guild`
        All guilds this account is a member of. These are shallow guild objects.
    private_channels list[:class:`disco.types.channel.Channel`]
        All private channels (DMs) open for this account.
    """
    version = Field(int, alias='v')
    session_id = Field(str)
    user = Field(User)
    guilds = ListField(Guild)
    private_channels = ListField(Guild)
示例#9
0
文件: guild.py 项目: elderlabs/disco2
class GuildEmoji(Emoji):
    """
    An emoji object.

    Attributes
    ----------
    id : snowflake
        The ID of this emoji.
    name : str
        The name of this emoji.
    require_colons : bool
        Whether this emoji requires colons to use.
    managed : bool
        Whether this emoji is managed by an integration.
    roles : list(snowflake)
        Roles this emoji is attached to.
    animated : bool
        Whether this emoji is animated.
    """
    id = Field(snowflake)
    guild_id = Field(snowflake)
    name = Field(text)
    require_colons = Field(bool)
    managed = Field(bool)
    roles = ListField(snowflake)
    animated = Field(bool)

    def __str__(self):
        return u'<{}:{}:{}>'.format('a' if self.animated else '', self.name,
                                    self.id)

    def update(self, **kwargs):
        return self.client.api.guilds_emojis_modify(self.guild_id, self.id,
                                                    **kwargs)

    def delete(self, **kwargs):
        return self.client.api.guilds_emojis_delete(self.guild_id, self.id,
                                                    **kwargs)

    @property
    def url(self):
        return 'https://media.discordapp.net/emojis/{}.{}'.format(
            self.id, 'gif' if self.animated else 'png')

    @cached_property
    def guild(self):
        return self.client.state.guilds.get(self.guild_id)
示例#10
0
class GuildMembersChunk(GatewayEvent):
    """
    Sent in response to a member's chunk request.

    Attributes
    -----
    guild_id : snowflake
        The ID of the guild this member chunk is for.
    members : list[:class:`disco.types.guild.GuildMember`]
        The chunk of members.
    """
    guild_id = Field(snowflake)
    members = ListField(GuildMember)

    @property
    def guild(self):
        return self.client.state.guilds.get(self.guild_id)
示例#11
0
文件: guild.py 项目: elderlabs/disco2
class AuditLogEntry(SlottedModel):
    id = Field(snowflake)
    guild_id = Field(snowflake)
    user_id = Field(snowflake)
    target_id = Field(snowflake)
    action_type = Field(enum(AuditLogActionTypes))
    changes = ListField(AuditLogObjectChange)
    options = DictField(text, text)
    reason = Field(text)

    _cached_target = Field(None)

    @classmethod
    def create(cls, client, users, webhooks, data, **kwargs):
        self = super(SlottedModel, cls).create(client, data, **kwargs)

        if self.action_type in MEMBER_ACTIONS:
            self._cached_target = users[self.target_id]
        elif self.action_type in WEBHOOK_ACTIONS:
            self._cached_target = webhooks[self.target_id]

        return self

    @cached_property
    def guild(self):
        return self.client.state.guilds.get(self.guild_id)

    @cached_property
    def user(self):
        return self.client.state.users.get(self.user_id)

    @cached_property
    def target(self):
        if self.action_type in GUILD_ACTIONS:
            return self.guild
        elif self.action_type in CHANNEL_ACTIONS:
            return self.guild.channels.get(self.target_id)
        elif self.action_type in MEMBER_ACTIONS:
            return self._cached_target or self.state.users.get(self.target_id)
        elif self.action_type in ROLE_ACTIONS:
            return self.guild.roles.get(self.target_id)
        elif self.action_type in WEBHOOK_ACTIONS:
            return self._cached_target
        elif self.action_type in EMOJI_ACTIONS:
            return self.guild.emojis.get(self.target_id)
示例#12
0
class MessageEmbed(SlottedModel):
    """
    Message embed object.

    Attributes
    ----------
    title : str
        Title of the embed.
    type : str
        Type of the embed.
    description : str
        Description of the embed.
    url : str
        URL of the embed.
    """
    title = Field(text)
    type = Field(str, default='rich')
    description = Field(text)
    url = Field(text)
    timestamp = Field(datetime)
    color = Field(int)
    footer = Field(MessageEmbedFooter)
    image = Field(MessageEmbedImage)
    thumbnail = Field(MessageEmbedThumbnail)
    video = Field(MessageEmbedVideo)
    author = Field(MessageEmbedAuthor)
    fields = ListField(MessageEmbedField)

    def set_footer(self, *args, **kwargs):
        self.footer = MessageEmbedFooter(*args, **kwargs)

    def set_image(self, *args, **kwargs):
        self.image = MessageEmbedImage(*args, **kwargs)

    def set_thumbnail(self, *args, **kwargs):
        self.thumbnail = MessageEmbedThumbnail(*args, **kwargs)

    def set_video(self, *args, **kwargs):
        self.video = MessageEmbedVideo(*args, **kwargs)

    def set_author(self, *args, **kwargs):
        self.author = MessageEmbedAuthor(*args, **kwargs)

    def add_field(self, *args, **kwargs):
        self.fields.append(MessageEmbedField(*args, **kwargs))
示例#13
0
class PresenceUpdate(GatewayEvent):
    """
    Sent when a user's presence is updated.

    Attributes
    -----
    presence : :class:`disco.types.user.Presence`
        The updated presence object.
    guild_id : snowflake
        The guild this presence update is for.
    roles : list[snowflake]
        List of roles the user from the presence is part of.
    """
    guild_id = Field(snowflake)
    roles = ListField(snowflake)

    @property
    def guild(self):
        return self.client.state.guilds.get(self.guild_id)
示例#14
0
class GuildCreate(GatewayEvent):
    """
    Sent when a guild is joined, or becomes available.

    Attributes
    -----
    guild : :class:`disco.types.guild.Guild`
        The guild being created (e.g. joined)
    unavailable : bool
        If false, this guild is coming online from a previously unavailable state,
        and if None, this is a normal guild join event.
    """
    unavailable = Field(bool)
    presences = ListField(Presence)

    @property
    def created(self):
        """
        Shortcut property which is true when we actually joined the guild.
        """
        return self.unavailable is None
示例#15
0
class MessageDeleteBulk(GatewayEvent):
    """
    Sent when multiple messages are deleted from a channel.

    Attributes
    -----
    channel_id : snowflake
        The channel the messages are being deleted in.
    ids : list[snowflake]
        List of messages being deleted in the channel.
    """
    channel_id = Field(snowflake)
    ids = ListField(snowflake)

    @property
    def channel(self):
        return self.client.state.channels.get(self.channel_id)

    @property
    def guild(self):
        return self.channel.guild
示例#16
0
class WebConfig(Model):
    viewers = ListField(snowflake)
    editors = ListField(snowflake)
    admins = ListField(snowflake)
示例#17
0
class Party(SlottedModel):
    id = Field(text)
    size = ListField(int)
示例#18
0
class Presence(SlottedModel):
    user = Field(User, alias='user', ignore_dump=['presence'])
    game = Field(Game)
    status = Field(Status)
    activities = ListField(Game)
    client_status = Field(ClientStatus)
示例#19
0
class Message(SlottedModel):
    """
    Represents a Message created within a Channel on Discord.

    Attributes
    ----------
    id : snowflake
        The ID of this message.
    channel_id : snowflake
        The channel ID this message was sent in.
    type : `MessageType`
        Type of the message.
    author : :class:`disco.types.user.User`
        The author of this message.
    content : str
        The unicode contents of this message.
    nonce : str
        The nonce of this message.
    timestamp : datetime
        When this message was created.
    edited_timestamp : datetime?
        When this message was last edited.
    tts : bool
        Whether this is a TTS (text-to-speech) message.
    mention_everyone : bool
        Whether this message has an @everyone which mentions everyone.
    pinned : bool
        Whether this message is pinned in the channel.
    mentions : dict[snowflake, `User`]
        Users mentioned within this message.
    mention_roles : list[snowflake]
        IDs for roles mentioned within this message.
    embeds : list[`MessageEmbed`]
        Embeds for this message.
    attachments : list[`MessageAttachment`]
        Attachments for this message.
    reactions : list[`MessageReaction`]
        Reactions for this message.
    """
    id = Field(snowflake)
    channel_id = Field(snowflake)
    webhook_id = Field(snowflake)
    type = Field(enum(MessageType))
    author = Field(User)
    content = Field(text)
    nonce = Field(snowflake)
    timestamp = Field(datetime)
    edited_timestamp = Field(datetime)
    tts = Field(bool)
    mention_everyone = Field(bool)
    pinned = Field(bool)
    mentions = AutoDictField(User, 'id')
    mention_roles = ListField(snowflake)
    embeds = ListField(MessageEmbed)
    attachments = AutoDictField(MessageAttachment, 'id')
    reactions = ListField(MessageReaction)

    def __str__(self):
        return '<Message {} ({})>'.format(self.id, self.channel_id)

    @cached_property
    def guild(self):
        """
        Returns
        -------
        `Guild`
            The guild (if applicable) this message was created in.
        """
        return self.channel.guild

    @cached_property
    def member(self):
        """
        Returns
        -------
        `GuildMember`
            The guild member (if applicable) that sent this message.
        """
        return self.channel.guild.get_member(self.author)

    @cached_property
    def channel(self):
        """
        Returns
        -------
        `Channel`
            The channel this message was created in.
        """
        return self.client.state.channels.get(self.channel_id)

    def pin(self):
        """
        Pins the message to the channel it was created in.
        """
        self.channel.create_pin(self)

    def unpin(self):
        """
        Unpins the message from the channel it was created in.
        """
        self.channel.delete_pin(self)

    def reply(self, *args, **kwargs):
        """
        Reply to this message (see `Channel.send_message`).

        Returns
        -------
        `Message`
            The created message object.
        """
        return self.channel.send_message(*args, **kwargs)

    def edit(self, *args, **kwargs):
        """
        Edit this message.

        Args
        ----
        content : str
            The new edited contents of the message.

        Returns
        -------
        `Message`
            The edited message object.
        """
        return self.client.api.channels_messages_modify(
            self.channel_id, self.id, *args, **kwargs)

    def delete(self):
        """
        Delete this message.

        Returns
        -------
        `Message`
            The deleted message object.
        """
        return self.client.api.channels_messages_delete(
            self.channel_id, self.id)

    def get_reactors(self, emoji, *args, **kwargs):
        """
        Returns an iterator which paginates the reactors for the given emoji.

        Returns
        -------
        `Paginator`(`User`)
            An iterator which handles pagination of reactors.
        """
        if isinstance(emoji, Emoji):
            emoji = emoji.to_string()

        return Paginator(self.client.api.channels_messages_reactions_get,
                         'after', self.channel_id, self.id, emoji, *args,
                         **kwargs)

    def create_reaction(self, emoji):
        warnings.warn(
            'Message.create_reaction will be deprecated soon, use Message.add_reaction',
            DeprecationWarning)
        return self.add_reaction(emoji)

    def add_reaction(self, emoji):
        """
        Adds a reaction to the message.

        Parameters
        ----------
        emoji : `Emoji`|str
            An emoji or string representing an emoji
        """
        if isinstance(emoji, Emoji):
            emoji = emoji.to_string()

        self.client.api.channels_messages_reactions_create(
            self.channel_id, self.id, emoji)

    def delete_reaction(self, emoji, user=None):
        """
        Deletes a reaction from the message.
        """
        if isinstance(emoji, Emoji):
            emoji = emoji.to_string()

        if user:
            user = to_snowflake(user)

        self.client.api.channels_messages_reactions_delete(
            self.channel_id, self.id, emoji, user)

    def is_mentioned(self, entity):
        """
        Returns
        -------
        bool
            Whether the give entity was mentioned.
        """
        entity = to_snowflake(entity)
        return entity in self.mentions or entity in self.mention_roles

    @cached_property
    def without_mentions(self, valid_only=False):
        """
        Returns
        -------
        str
            the message contents with all mentions removed.
        """
        return self.replace_mentions(lambda u: '',
                                     lambda r: '',
                                     lambda c: '',
                                     nonexistant=not valid_only)

    @cached_property
    def with_proper_mentions(self):
        """
        Returns
        -------
        str
            The message with mentions replaced w/ their proper form.
        """
        def replace_user(u):
            return u'@' + six.text_type(u)

        def replace_role(r):
            return u'@' + six.text_type(r)

        def replace_channel(c):
            return six.text_type(c)

        return self.replace_mentions(replace_user, replace_role,
                                     replace_channel)

    def replace_mentions(self,
                         user_replace=None,
                         role_replace=None,
                         channel_replace=None,
                         nonexistant=False):
        """
        Replaces user and role mentions with the result of a given lambda/function.

        Args
        ----
        user_replace : function
            A function taking a single argument, the user object mentioned, and
            returning a valid string.
        role_replace : function
            A function taking a single argument, the role ID mentioned, and
            returning a valid string.

        Returns
        -------
        str
            The message contents with all valid mentions replaced.
        """
        def replace(getter, func, match):
            oid = int(match.group(2))
            obj = getter(oid)

            if obj or nonexistant:
                return func(obj or oid) or match.group(0)

            return match.group(0)

        content = self.content

        if user_replace:
            replace_user = functools.partial(replace, self.mentions.get,
                                             user_replace)
            content = re.sub('(<@!?([0-9]+)>)', replace_user, content)

        if role_replace:
            replace_role = functools.partial(
                replace, lambda v: (self.guild and self.guild.roles.get(v)),
                role_replace)
            content = re.sub('(<@&([0-9]+)>)', replace_role, content)

        if channel_replace:
            replace_channel = functools.partial(replace,
                                                self.client.state.channels.get,
                                                channel_replace)
            content = re.sub('(<#([0-9]+)>)', replace_channel, content)

        return content
示例#20
0
class MessageEmbed(SlottedModel):
    """
    Message embed object.

    Attributes
    ----------
    title : str
        Title of the embed.
    type : str
        Type of the embed.
    description : str
        Description of the embed.
    url : str
        URL of the embed.
    timestamp : datetime
        The timestamp for the embed.
    color : int
        The color of the embed.
    footer : `MessageEmbedFooter`
        The footer of the embed.
    thumbnail : `MessageEmbedThumbnail`
        The thumbnail of the embed.
    video : `MessageEmbedVideo`
        The video of the embed.
    author : `MessageEmbedAuthor`
        The author of the embed.
    fields : list[`MessageEmbedField]`
        The fields of the embed.
    """
    title = Field(text)
    type = Field(str, default='rich')
    description = Field(text)
    url = Field(text)
    timestamp = Field(datetime)
    color = Field(int)
    footer = Field(MessageEmbedFooter)
    image = Field(MessageEmbedImage)
    thumbnail = Field(MessageEmbedThumbnail)
    video = Field(MessageEmbedVideo)
    author = Field(MessageEmbedAuthor)
    fields = ListField(MessageEmbedField)

    def set_footer(self, *args, **kwargs):
        """
        Sets the footer of the embed, see `MessageEmbedFooter`.
        """
        self.footer = MessageEmbedFooter(*args, **kwargs)

    def set_image(self, *args, **kwargs):
        """
        Sets the image of the embed, see `MessageEmbedImage`.
        """
        self.image = MessageEmbedImage(*args, **kwargs)

    def set_thumbnail(self, *args, **kwargs):
        """
        Sets the thumbnail of the embed, see `MessageEmbedThumbnail`.
        """
        self.thumbnail = MessageEmbedThumbnail(*args, **kwargs)

    def set_video(self, *args, **kwargs):
        """
        Sets the video of the embed, see `MessageEmbedVideo`.
        """
        self.video = MessageEmbedVideo(*args, **kwargs)

    def set_author(self, *args, **kwargs):
        """
        Sets the author of the embed, see `MessageEmbedAuthor`.
        """
        self.author = MessageEmbedAuthor(*args, **kwargs)

    def add_field(self, *args, **kwargs):
        """
        Adds a new field to the embed, see `MessageEmbedField`.
        """
        self.fields.append(MessageEmbedField(*args, **kwargs))
示例#21
0
class Resumed(GatewayEvent):
    """
    Sent after a resume completes.
    """
    trace = ListField(str, alias='_trace')
示例#22
0
class GuildMember(SlottedModel):
    """
    A GuildMember object.

    Attributes
    ----------
    user : :class:`disco.types.user.User`
        The user object of this member.
    guild_id : snowflake
        The guild this member is part of.
    nick : str
        The nickname of the member.
    mute : bool
        Whether this member is server voice-muted.
    deaf : bool
        Whether this member is server voice-deafened.
    joined_at : datetime
        When this user joined the guild.
    roles : list(snowflake)
        Roles this member is part of.
    """
    user = Field(User)
    guild_id = Field(snowflake)
    nick = Field(text)
    mute = Field(bool)
    deaf = Field(bool)
    joined_at = Field(datetime)
    roles = ListField(snowflake)

    def __str__(self):
        return self.user.__str__()

    @property
    def name(self):
        """
        The nickname of this user if set, otherwise their username
        """
        return self.nick or self.user.username

    def get_voice_state(self):
        """
        Returns
        -------
        Optional[:class:`disco.types.voice.VoiceState`]
            Returns the voice state for the member if they are currently connected
            to the guild's voice server.
        """
        return self.guild.get_voice_state(self)

    def kick(self):
        """
        Kicks the member from the guild.
        """
        self.client.api.guilds_members_kick(self.guild.id, self.user.id)

    def ban(self, delete_message_days=0):
        """
        Bans the member from the guild.

        Args
        ----
        delete_message_days : int
            The number of days to retroactively delete messages for.
        """
        self.guild.create_ban(self, delete_message_days)

    def unban(self):
        """
        Unbans the member from the guild.
        """
        self.guild.delete_ban(self)

    def set_nickname(self, nickname=None):
        """
        Sets the member's nickname (or clears it if None).

        Args
        ----
        nickname : Optional[str]
            The nickname (or none to reset) to set.
        """
        if self.client.state.me.id == self.user.id:
            self.client.api.guilds_members_me_nick(self.guild.id,
                                                   nick=nickname or '')
        else:
            self.client.api.guilds_members_modify(self.guild.id,
                                                  self.user.id,
                                                  nick=nickname or '')

    def modify(self, **kwargs):
        self.client.api.guilds_members_modify(self.guild.id, self.user.id,
                                              **kwargs)

    def add_role(self, role):
        self.client.api.guilds_members_roles_add(self.guild.id, self.user.id,
                                                 to_snowflake(role))

    def remove_role(self, role):
        self.client.api.guilds_members_roles_remove(self.guild.id,
                                                    self.user.id,
                                                    to_snowflake(role))

    @cached_property
    def owner(self):
        return self.guild.owner_id == self.id

    @cached_property
    def mention(self):
        if self.nick:
            return '<@!{}>'.format(self.id)
        return self.user.mention

    @property
    def id(self):
        """
        Alias to the guild members user id.
        """
        return self.user.id

    @cached_property
    def guild(self):
        return self.client.state.guilds.get(self.guild_id)

    @cached_property
    def permissions(self):
        return self.guild.get_permissions(self)
示例#23
0
文件: guild.py 项目: elderlabs/disco2
class Guild(SlottedModel, Permissible):
    """
    A guild object.

    Attributes
    ----------
    id : snowflake
        The id of this guild.
    owner_id : snowflake
        The id of the owner.
    afk_channel_id : snowflake
        The id of the afk channel.
    embed_channel_id : snowflake
        The id of the embed channel.
    system_channel_id : snowflake
        The id of the system channel.
    name : str
        Guild's name.
    icon : str
        Guild's icon hash
    splash : str
        Guild's splash image hash
    region : str
        Voice region.
    afk_timeout : int
        Delay after which users are automatically moved to the afk channel.
    embed_enabled : bool
        Whether the guild's embed is enabled.
    verification_level : int
        The verification level used by the guild.
    mfa_level : int
        The MFA level used by the guild.
    features : list(str)
        Extra features enabled for this guild.
    members : dict(snowflake, :class:`GuildMember`)
        All of the guild's members.
    channels : dict(snowflake, :class:`disco.types.channel.Channel`)
        All of the guild's channels.
    roles : dict(snowflake, :class:`Role`)
        All of the guild's roles.
    emojis : dict(snowflake, :class:`GuildEmoji`)
        All of the guild's emojis.
    voice_states : dict(str, :class:`disco.types.voice.VoiceState`)
        All of the guild's voice states.
    """
    id = Field(snowflake)
    owner_id = Field(snowflake)
    afk_channel_id = Field(snowflake)
    embed_channel_id = Field(snowflake)
    system_channel_id = Field(snowflake)
    name = Field(text)
    icon = Field(text)
    splash = Field(text)
    region = Field(text)
    afk_timeout = Field(int)
    embed_enabled = Field(bool)
    verification_level = Field(enum(VerificationLevel))
    explicit_content_filter = Field(enum(ExplicitContentFilterLevel))
    default_message_notifications = Field(
        enum(DefaultMessageNotificationsLevel))
    mfa_level = Field(int)
    features = ListField(str)
    members = AutoDictField(GuildMember, 'id')
    channels = AutoDictField(Channel, 'id')
    roles = AutoDictField(Role, 'id')
    emojis = AutoDictField(GuildEmoji, 'id')
    voice_states = AutoDictField(VoiceState, 'session_id')
    member_count = Field(int)

    def __init__(self, *args, **kwargs):
        super(Guild, self).__init__(*args, **kwargs)

        self.attach(six.itervalues(self.channels), {'guild_id': self.id})
        self.attach(six.itervalues(self.members), {'guild_id': self.id})
        self.attach(six.itervalues(self.roles), {'guild_id': self.id})
        self.attach(six.itervalues(self.emojis), {'guild_id': self.id})
        self.attach(six.itervalues(self.voice_states), {'guild_id': self.id})

    @cached_property
    def owner(self):
        return self.members.get(self.owner_id)

    def get_permissions(self, member):
        """
        Get the permissions a user has in this guild.

        Returns
        -------
        :class:`disco.types.permissions.PermissionValue`
            Computed permission value for the user.
        """
        if not isinstance(member, GuildMember):
            member = self.get_member(member)

        # Owner has all permissions
        if self.owner_id == member.id:
            return PermissionValue(Permissions.ADMINISTRATOR)

        # Our value starts with the guilds default (@everyone) role permissions
        value = PermissionValue(self.roles.get(self.id).permissions)

        # Iterate over all roles the user has (plus the @everyone role)
        for role in map(self.roles.get, member.roles + [self.id]):
            value += role.permissions

        return value

    def get_voice_state(self, user):
        """
        Attempt to get a voice state for a given user (who should be a member of
        this guild).

        Returns
        -------
        :class:`disco.types.voice.VoiceState`
            The voice state for the user in this guild.
        """
        user = to_snowflake(user)

        for state in six.itervalues(self.voice_states):
            if state.user_id == user:
                return state

    def get_member(self, user):
        """
        Attempt to get a member from a given user.

        Returns
        -------
        :class:`GuildMember`
            The guild member object for the given user.
        """
        user = to_snowflake(user)

        if user not in self.members:
            try:
                self.members[user] = self.client.api.guilds_members_get(
                    self.id, user)
            except APIException:
                return

        return self.members.get(user)

    def create_role(self, **kwargs):
        """
        Create a new role.

        Returns
        -------
        :class:`Role`
            The newly created role.
        """
        return self.client.api.guilds_roles_create(self.id, **kwargs)

    def delete_role(self, role, **kwargs):
        """
        Delete a role.
        """
        self.client.api.guilds_roles_delete(self.id, to_snowflake(role),
                                            **kwargs)

    def update_role(self, role, **kwargs):
        if 'permissions' in kwargs and isinstance(kwargs['permissions'],
                                                  PermissionValue):
            kwargs['permissions'] = kwargs['permissions'].value

        return self.client.api.guilds_roles_modify(self.id, to_snowflake(role),
                                                   **kwargs)

    def request_guild_members(self, query=None, limit=0):
        self.client.gw.request_guild_members(self.id, query, limit)

    def sync(self):
        warnings.warn(
            'Guild.sync has been deprecated in place of Guild.request_guild_members',
            DeprecationWarning)

        self.request_guild_members()

    def get_bans(self):
        return self.client.api.guilds_bans_list(self.id)

    def delete_ban(self, user, **kwargs):
        self.client.api.guilds_bans_delete(self.id, to_snowflake(user),
                                           **kwargs)

    def create_ban(self, user, *args, **kwargs):
        self.client.api.guilds_bans_create(self.id, to_snowflake(user), *args,
                                           **kwargs)

    def create_channel(self, *args, **kwargs):
        warnings.warn(
            'Guild.create_channel will be deprecated soon, please use:'
            ' Guild.create_text_channel or Guild.create_category or Guild.create_voice_channel',
            DeprecationWarning)

        return self.client.api.guilds_channels_create(self.id, *args, **kwargs)

    def create_category(self,
                        name,
                        permission_overwrites=[],
                        position=None,
                        reason=None):
        """
        Creates a category within the guild.
        """
        return self.client.api.guilds_channels_create(
            self.id,
            ChannelType.GUILD_CATEGORY,
            name=name,
            permission_overwrites=permission_overwrites,
            position=position,
            reason=reason,
        )

    def create_text_channel(self,
                            name,
                            permission_overwrites=[],
                            parent_id=None,
                            nsfw=None,
                            position=None,
                            reason=None):
        """
        Creates a text channel within the guild.
        """
        return self.client.api.guilds_channels_create(
            self.id,
            ChannelType.GUILD_TEXT,
            name=name,
            permission_overwrites=permission_overwrites,
            parent_id=parent_id,
            nsfw=nsfw,
            position=position,
            reason=reason,
        )

    def create_voice_channel(self,
                             name,
                             permission_overwrites=[],
                             parent_id=None,
                             bitrate=None,
                             user_limit=None,
                             position=None,
                             reason=None):
        """
        Creates a voice channel within the guild.
        """
        return self.client.api.guilds_channels_create(
            self.id,
            ChannelType.GUILD_VOICE,
            name=name,
            permission_overwrites=permission_overwrites,
            parent_id=parent_id,
            bitrate=bitrate,
            user_limit=user_limit,
            position=position,
            reason=None)

    def leave(self):
        return self.client.api.users_me_guilds_delete(self.id)

    def get_invites(self):
        return self.client.api.guilds_invites_list(self.id)

    def get_emojis(self):
        return self.client.api.guilds_emojis_list(self.id)

    def get_icon_url(self, fmt='webp', size=1024):
        if not self.icon:
            return ''

        return 'https://media.discordapp.net/icons/{}/{}.{}?size={}'.format(
            self.id, self.icon, fmt, size)

    def get_splash_url(self, fmt='webp', size=1024):
        if not self.splash:
            return ''

        return 'https://media.discordapp.net/splashes/{}/{}.{}?size={}'.format(
            self.id, self.splash, fmt, size)

    @property
    def icon_url(self):
        return self.get_icon_url()

    @property
    def splash_url(self):
        return self.get_splash_url()

    @property
    def system_channel(self):
        return self.channels.get(self.system_channel_id)

    @property
    def audit_log(self):
        return self.audit_log_iter()

    def audit_log_iter(self, **kwargs):
        return Paginator(self.client.api.guilds_auditlogs_list, 'before',
                         self.id, **kwargs)

    def get_audit_log_entries(self, *args, **kwargs):
        return self.client.api.guilds_auditlogs_list(self.id, *args, **kwargs)
示例#24
0
class Guild(SlottedModel, Permissible):
    """
    A guild object.

    Attributes
    ----------
    id : snowflake
        The id of this guild.
    owner_id : snowflake
        The id of the owner.
    afk_channel_id : snowflake
        The id of the afk channel.
    embed_channel_id : snowflake
        The id of the embed channel.
    name : str
        Guild's name.
    icon : str
        Guild's icon (as PNG binary data).
    splash : str
        Guild's splash image (as PNG binary data).
    region : str
        Voice region.
    afk_timeout : int
        Delay after which users are automatically moved to the afk channel.
    embed_enabled : bool
        Whether the guild's embed is enabled.
    verification_level : int
        The verification level used by the guild.
    mfa_level : int
        The MFA level used by the guild.
    features : list(str)
        Extra features enabled for this guild.
    members : dict(snowflake, :class:`GuildMember`)
        All of the guild's members.
    channels : dict(snowflake, :class:`disco.types.channel.Channel`)
        All of the guild's channels.
    roles : dict(snowflake, :class:`Role`)
        All of the guild's roles.
    emojis : dict(snowflake, :class:`GuildEmoji`)
        All of the guild's emojis.
    voice_states : dict(str, :class:`disco.types.voice.VoiceState`)
        All of the guild's voice states.
    """
    id = Field(snowflake)
    owner_id = Field(snowflake)
    afk_channel_id = Field(snowflake)
    embed_channel_id = Field(snowflake)
    name = Field(text)
    icon = Field(binary)
    splash = Field(binary)
    region = Field(str)
    afk_timeout = Field(int)
    embed_enabled = Field(bool)
    verification_level = Field(enum(VerificationLevel))
    mfa_level = Field(int)
    features = ListField(str)
    members = AutoDictField(GuildMember, 'id')
    channels = AutoDictField(Channel, 'id')
    roles = AutoDictField(Role, 'id')
    emojis = AutoDictField(GuildEmoji, 'id')
    voice_states = AutoDictField(VoiceState, 'session_id')
    member_count = Field(int)

    synced = Field(bool, default=False)

    def __init__(self, *args, **kwargs):
        super(Guild, self).__init__(*args, **kwargs)

        self.attach(six.itervalues(self.channels), {'guild_id': self.id})
        self.attach(six.itervalues(self.members), {'guild_id': self.id})
        self.attach(six.itervalues(self.roles), {'guild_id': self.id})
        self.attach(six.itervalues(self.emojis), {'guild_id': self.id})
        self.attach(six.itervalues(self.voice_states), {'guild_id': self.id})

    @cached_property
    def owner(self):
        return self.members.get(self.owner_id)

    def get_permissions(self, member):
        """
        Get the permissions a user has in this guild.

        Returns
        -------
        :class:`disco.types.permissions.PermissionValue`
            Computed permission value for the user.
        """
        if not isinstance(member, GuildMember):
            member = self.get_member(member)

        # Owner has all permissions
        if self.owner_id == member.id:
            return PermissionValue(Permissions.ADMINISTRATOR)

        value = PermissionValue(self.roles.get(self.id).permissions)

        for role in map(self.roles.get, member.roles):
            value += role.permissions

        return value

    def get_voice_state(self, user):
        """
        Attempt to get a voice state for a given user (who should be a member of
        this guild).

        Returns
        -------
        :class:`disco.types.voice.VoiceState`
            The voice state for the user in this guild.
        """
        user = to_snowflake(user)

        for state in six.itervalues(self.voice_states):
            if state.user_id == user:
                return state

    def get_member(self, user):
        """
        Attempt to get a member from a given user.

        Returns
        -------
        :class:`GuildMember`
            The guild member object for the given user.
        """
        user = to_snowflake(user)

        if user not in self.members:
            try:
                self.members[user] = self.client.api.guilds_members_get(
                    self.id, user)
            except APIException:
                return

        return self.members.get(user)

    def create_role(self):
        """
        Create a new role.

        Returns
        -------
        :class:`Role`
            The newly created role.
        """
        return self.client.api.guilds_roles_create(self.id)

    def delete_role(self, role):
        """
        Delete a role.
        """
        self.client.api.guilds_roles_delete(self.id, to_snowflake(role))

    def update_role(self, role):
        return self.client.api.guilds_roles_modify(
            self.id, role.id, **{
                'name': role.name,
                'permissions': role.permissions.value,
                'position': role.position,
                'color': role.color,
                'hoist': role.hoist,
                'mentionable': role.mentionable,
            })

    def sync(self):
        if self.synced:
            return

        self.synced = True
        self.client.gw.send(OPCode.REQUEST_GUILD_MEMBERS, {
            'guild_id': self.id,
            'query': '',
            'limit': 0,
        })

    def get_bans(self):
        return self.client.api.guilds_bans_list(self.id)

    def delete_ban(self, user):
        self.client.api.guilds_bans_delete(self.id, to_snowflake(user))

    def create_ban(self, user, delete_message_days=0):
        self.client.api.guilds_bans_create(self.id, to_snowflake(user),
                                           delete_message_days)

    def create_channel(self, *args, **kwargs):
        return self.client.api.guilds_channels_create(self.id, *args, **kwargs)

    def leave(self):
        return self.client.api.users_me_guilds_delete(self.id)
示例#25
0
class Channel(SlottedModel, Permissible):
    """
    Represents a Discord Channel.

    Attributes
    ----------
    id : snowflake
        The channel ID.
    guild_id : Optional[snowflake]
        The guild id this channel is part of.
    name : str
        The channel's name.
    topic : str
        The channel's topic.
    position : int
        The channel's position.
    bitrate : int
        The channel's bitrate.
    recipients: list(:class:`disco.types.user.User`)
        Members of this channel (if this is a DM channel).
    type : :const:`ChannelType`
        The type of this channel.
    overwrites : dict(snowflake, :class:`disco.types.channel.PermissionOverwrite`)
        Channel permissions overwrites.
    """
    id = Field(snowflake)
    guild_id = Field(snowflake)
    name = Field(text)
    topic = Field(text)
    last_message_id = Field(snowflake)
    position = Field(int)
    bitrate = Field(int)
    recipients = ListField(User)
    type = Field(enum(ChannelType))
    overwrites = AutoDictField(PermissionOverwrite,
                               'id',
                               alias='permission_overwrites')

    def __init__(self, *args, **kwargs):
        super(Channel, self).__init__(*args, **kwargs)

        self.attach(six.itervalues(self.overwrites), {
            'channel_id': self.id,
            'channel': self
        })

    def __str__(self):
        return u'#{}'.format(self.name)

    def __repr__(self):
        return u'<Channel {} ({})>'.format(self.id, self)

    def get_permissions(self, user):
        """
        Get the permissions a user has in the channel.

        Returns
        -------
        :class:`disco.types.permissions.PermissionValue`
            Computed permission value for the user.
        """
        if not self.guild_id:
            return Permissions.ADMINISTRATOR

        member = self.guild.members.get(user.id)
        base = self.guild.get_permissions(user)

        for ow in six.itervalues(self.overwrites):
            if ow.id != user.id and ow.id not in member.roles:
                continue

            base -= ow.deny
            base += ow.allow

        return base

    @property
    def mention(self):
        return '<#{}>'.format(self.id)

    @property
    def is_guild(self):
        """
        Whether this channel belongs to a guild.
        """
        return self.type in (ChannelType.GUILD_TEXT, ChannelType.GUILD_VOICE)

    @property
    def is_dm(self):
        """
        Whether this channel is a DM (does not belong to a guild).
        """
        return self.type in (ChannelType.DM, ChannelType.GROUP_DM)

    @property
    def is_voice(self):
        """
        Whether this channel supports voice.
        """
        return self.type in (ChannelType.GUILD_VOICE, ChannelType.GROUP_DM)

    @property
    def messages(self):
        """
        a default :class:`MessageIterator` for the channel.
        """
        return self.messages_iter()

    @cached_property
    def guild(self):
        """
        Guild this channel belongs to (if relevant).
        """
        return self.client.state.guilds.get(self.guild_id)

    def messages_iter(self, **kwargs):
        """
        Creates a new :class:`MessageIterator` for the channel with the given
        keyword arguments.
        """
        return MessageIterator(self.client, self, **kwargs)

    def get_message(self, message):
        return self.client.api.channels_messages_get(self.id,
                                                     to_snowflake(message))

    def get_invites(self):
        """
        Returns
        -------
        list(:class:`disco.types.invite.Invite`)
            All invites for this channel.
        """
        return self.client.api.channels_invites_list(self.id)

    def create_invite(self, *args, **kwargs):
        from disco.types.invite import Invite
        return Invite.create(self, *args, **kwargs)

    def get_pins(self):
        """
        Returns
        -------
        list(:class:`disco.types.message.Message`)
            All pinned messages for this channel.
        """
        return self.client.api.channels_pins_list(self.id)

    def create_pin(self, message):
        self.client.api.channels_pins_create(self.id, to_snowflake(message))

    def delete_pin(self, message):
        self.client.api.channels_pins_delete(self.id, to_snowflake(message))

    def get_webhooks(self):
        return self.client.api.channels_webhooks_list(self.id)

    def create_webhook(self, name=None, avatar=None):
        return self.client.api.channels_webhooks_create(self.id, name, avatar)

    def send_message(self,
                     content,
                     nonce=None,
                     tts=False,
                     attachment=None,
                     embed=None):
        """
        Send a message in this channel.

        Parameters
        ----------
        content : str
            The message contents to send.
        nonce : Optional[snowflake]
            The nonce to attach to the message.
        tts : Optional[bool]
            Whether this is a TTS message.

        Returns
        -------
        :class:`disco.types.message.Message`
            The created message.
        """
        return self.client.api.channels_messages_create(
            self.id, content, nonce, tts, attachment, embed)

    def connect(self, *args, **kwargs):
        """
        Connect to this channel over voice.
        """
        assert self.is_voice, 'Channel must support voice to connect'
        vc = VoiceClient(self)
        vc.connect(*args, **kwargs)
        return vc

    def create_overwrite(self, *args, **kwargs):
        return PermissionOverwrite.create(self, *args, **kwargs)

    def delete_message(self, message):
        """
        Deletes a single message from this channel.

        Args
        ----
        message : snowflake|:class:`disco.types.message.Message`
            The message to delete.
        """
        self.client.api.channels_messages_delete(self.id,
                                                 to_snowflake(message))

    @one_or_many
    def delete_messages(self, messages):
        """
        Deletes a set of messages using the correct API route based on the number
        of messages passed.

        Args
        ----
        messages : list[snowflake|:class:`disco.types.message.Message`]
            List of messages (or message ids) to delete. All messages must originate
            from this channel.
        """
        messages = map(to_snowflake, messages)

        if not messages:
            return

        if self.can(self.client.state.me,
                    Permissions.MANAGE_MESSAGES) and len(messages) > 2:
            for chunk in chunks(messages, 100):
                self.client.api.channels_messages_delete_bulk(self.id, chunk)
        else:
            for msg in messages:
                self.delete_message(msg)

    def delete(self):
        assert (self.is_dm or self.guild.can(
            self.client.state.me,
            Permissions.MANAGE_GUILD)), 'Invalid Permissions'
        self.client.api.channels_delete(self.id)

    def close(self):
        """
        Closes a DM channel. This is intended as a safer version of `delete`,
        enforcing that the channel is actually a DM.
        """
        assert self.is_dm, 'Cannot close non-DM channel'
        self.delete()