示例#1
0
    async def set_vanity_invite(self, url: str) -> 'typing.Union[dt_invite.Invite, None]':
        """
        Sets the vanity :class:`.Invite` for this guild.

        :param url: The code to use for this guild.
        :return: The :class:`.Invite` produced.
        """
        if 'vanity-url' not in self.features:
            raise CuriousError("This guild has no vanity URL")

        try:
            resp = await self._bot.http.edit_vanity_url(self.id, url)
        except HTTPException as e:
            if e.error_code != 50020:
                raise

            raise CuriousError("This guild has no vanity URL")

        code = resp.get("code", None)
        if code is None:
            return None

        invite_data = await self._bot.http.get_invite(code)
        invite = dt_invite.Invite(self._bot, **invite_data)

        return invite
示例#2
0
文件: user.py 项目: vault-the/curious
    async def unblock(self):
        """
        Unblocks this user.
        """
        if self._bot.is_bot:
            raise CuriousError("Bots cannot have blocks")

        if self.type_ != FriendType.BLOCKED:
            raise CuriousError("This user is not blocked")

        await self._bot.http.remove_relationship(self.id)
示例#3
0
文件: user.py 项目: vault-the/curious
    async def remove_friend(self):
        """
        Removes this user as a friend.
        """
        if self._bot.is_bot:
            raise CuriousError("Bots cannot have friends")

        if self.type_ != FriendType.FRIEND:
            raise CuriousError("This user is not your friend")

        await self._bot.http.remove_relationship(self.id)
示例#4
0
    async def send(self,
                   content: str = None,
                   *,
                   tts: bool = False,
                   embed: 'Embed' = None) -> 'dt_message.Message':
        """
        Sends a message to this channel.

        This requires SEND_MESSAGES permission in the channel.
        If the content is not a string, it will be automatically stringified.

        .. code:: python

            await channel.send("Hello, world!")

        :param content: The content of the message to send.
        :param tts: Should this message be text to speech?
        :param embed: An embed object to send with this message.
        :return: A new :class:`.Message` object.
        """
        if not self.channel.type.has_messages():
            raise CuriousError("Cannot send messages to a voice channel")

        if self.channel.guild:
            if not self.channel.permissions(
                    self.channel.guild.me).send_messages:
                raise PermissionsError("send_messages")

        if not isinstance(content, str) and content is not None:
            content = str(content)

        # check for empty messages
        if not content:
            if not embed:
                raise CuriousError("Cannot send an empty message")

            if self.channel.guild and not \
                    self.channel.permissions(self.channel.guild.me).embed_links:
                raise PermissionsError("embed_links")
        else:
            if content and len(content) > 2000:
                raise CuriousError("Content must be less than 2000 characters")

        if embed is not None:
            embed = embed.to_dict()

        data = await self.channel._bot.http.send_message(self.channel.id,
                                                         content,
                                                         tts=tts,
                                                         embed=embed)
        obb = self.channel._bot.state.make_message(data, cache=True)

        return obb
示例#5
0
    async def get(self, message_id: int) -> 'dt_message.Message':
        """
        Gets a single message from this channel.

        .. versionchanged:: 0.7.0

            Errors raised are now consistent across bots and userbots.

        :param message_id: The message ID to retrieve.
        :return: A new :class:`.Message` object.
        :raises CuriousError: If the message could not be found.
        """
        if self.channel.guild:
            if not self.channel.permissions(
                    self.channel.guild.me).read_message_history:
                raise PermissionsError("read_message_history")

        cached_message = self.channel._bot.state.find_message(message_id)
        if cached_message is not None:
            return cached_message

        try:
            data = await self.channel._bot.http.get_message(
                self.channel.id, message_id)
        except HTTPException as e:
            # transform into a CuriousError if it wasn't found
            if e.error_code == ErrorCode.UNKNOWN_MESSAGE:
                raise CuriousError("No message found for this ID") from e

            raise

        msg = self.channel._bot.state.make_message(data)

        return msg
示例#6
0
    async def unreact(self,
                      reaction: 'typing.Union[dt_emoji.Emoji, str]',
                      victim: 'dt_member.Member' = None):
        """
        Removes a reaction from a user.

        :param reaction: The reaction to remove.
        :param victim: The victim to remove the reaction of. Can be None to signify ourselves.
        """
        if not self.guild:
            if victim and victim != self:
                raise CuriousError("Cannot delete other reactions in a DM")

        if victim and victim != self:
            if not self.channel.effective_permissions(
                    self.guild.me).manage_messages:
                raise PermissionsError("manage_messages")

        if isinstance(reaction, dt_emoji.Emoji):
            emoji = "{}:{}".format(reaction.name, reaction.id)
        else:
            emoji = reaction

        await self._bot.http.delete_reaction(
            self.channel.id,
            self.id,
            emoji,
            victim=victim.id if victim else None)
示例#7
0
文件: user.py 项目: vault-the/curious
    async def get_recent_mentions(
            self,
            *,
            guild: 'dt_guild.Guild' = None,
            limit: int = 25,
            role_mentions: bool = True,
            everyone_mentions: bool = True) -> 'Sequence[dt_message.Message]':
        """
        Gets a list of recent mentions for this user. 
        
        :param guild: The guild to limit to. If this is None, it will return ALL recent mentions. 
        :param limit: The maximum amount of mentions to return.
        :param role_mentions: Should role mentions be included?
        :param everyone_mentions: Should everyone mentions be included?
        :return: A list of :class:`~.Message` that represents the recent mentions.
        """
        if self.bot:
            raise CuriousError("Bot accounts cannot use this function")

        if guild is not None:
            guild_id = guild.id
        else:
            guild_id = None

        mentions = await self._bot.http.get_mentions(
            guild_id=guild_id,
            limit=limit,
            roles=role_mentions,
            everyone=everyone_mentions)

        messages = []
        for mention in mentions:
            messages.append(self._bot.state.make_message(mention))

        return messages
示例#8
0
    async def edit(self, new_content: str = None, *,
                   embed: Embed = None) -> 'Message':
        """
        Edits this message.

        You must be the owner of this message to edit it.

        :param new_content: The new content for this message.
        :param embed: The new embed to provide.
        :return: This message, but edited with the new content.
        """
        if self.guild is None:
            is_me = self.author not in self.channel.recipients
        else:
            is_me = self.guild.me == self.author

        if not is_me:
            raise CuriousError("Cannot edit messages from other users")

        if embed:
            embed = embed.to_dict()

        # Prevent race conditions by spawning a listener, then waiting for the task once we've
        # sent the HTTP request.
        t = await curio.spawn(self._bot.wait_for("message_update",
                                                 predicate=lambda o, n: n.id == self.id))
        try:
            await self._bot.http.edit_message(self.channel.id, self.id, content=new_content,
                                              embed=embed)
        except:
            await t.cancel()
            raise
        old, new = await t.join()
        return new
示例#9
0
    async def get_message(self, message_id: int) -> 'dt_message.Message':
        """
        Gets a single message from this channel.

        :param message_id: The message ID to retrieve.
        :return: A new :class:`.Message` object.
        """
        if self.guild:
            if not self.permissions(self.guild.me).read_message_history:
                raise PermissionsError("read_message_history")

        if self._bot.user.bot:
            data = await self._bot.http.get_message(self.id, message_id)
        else:
            data = await self._bot.http.get_message_history(self.id,
                                                            around=message_id,
                                                            limit=1)
            if not data:
                raise CuriousError("No messages found for this ID")
            else:
                data = data[0]

        msg = self._bot.state.make_message(data)

        return msg
示例#10
0
    def _update_overwrites(self, overwrites: _typing.List[dict]):
        """
        Updates the overwrites for this channel.

        :param overwrites: A list of overwrite dicts.
        """
        if not self.guild_id:
            raise CuriousError(
                "A channel without a guild cannot have overwrites")

        self._overwrites = {}

        for overwrite in overwrites:
            id_ = int(overwrite["id"])
            type_ = overwrite["type"]

            if type_ == "member":
                obb = self.guild._members.get(id_)
            else:
                obb = self.guild._roles.get(id_)

            self._overwrites[id_] = dt_permissions.Overwrite(
                allow=overwrite["allow"],
                deny=overwrite["deny"],
                obb=obb,
                channel_id=self.id)
            self._overwrites[id_]._immutable = True
示例#11
0
    async def edit(self,
                   new_content: str = None,
                   *,
                   embed: Embed = None) -> 'Message':
        """
        Edits this message.

        You must be the owner of this message to edit it.

        :param new_content: The new content for this message.
        :param embed: The new embed to provide.
        :return: This message, but edited with the new content.
        """
        if self.guild is None:
            is_me = self.author not in self.channel.recipients
        else:
            is_me = self.guild.me == self.author

        if not is_me:
            raise CuriousError("Cannot edit messages from other users")

        if embed:
            embed = embed.to_dict()

        async with self._bot.events.wait_for_manager(
                "message_update", lambda o, n: n.id == self.id):
            await self._bot.http.edit_message(self.channel.id,
                                              self.id,
                                              content=new_content,
                                              embed=embed)
        return self
示例#12
0
文件: user.py 项目: vault-the/curious
    def friends(self) -> typing.Mapping[int, 'RelationshipUser']:
        """
        :return: A mapping of :class:`~.RelationshipUser` that represents the friends for this user.
        """
        if self.bot:
            raise CuriousError("Bots cannot have friends")

        return MappingProxyType(self._bot.state._friends)
示例#13
0
    def delete(self, role: 'dt_role.Role'):
        """
        Deletes a role.
        """
        if role.id not in self._roles:
            raise CuriousError("This role is not part of this guild")

        return role.delete()
示例#14
0
    async def connect(self):
        """
        Connects to voice in this channel.
        """
        if self.type != ChannelType.VOICE:
            raise CuriousError("Cannot connect to a text channel")

        return await self.guild.connect_to_voice(self)
示例#15
0
    def edit(self, channel: 'dt_channel.Channel', **kwargs):
        """
        Edits a channel.
        """
        if channel.id not in self._channels:
            raise CuriousError("This channel is not part of this guild")

        return channel.edit(**kwargs)
示例#16
0
    def delete(self, channel: 'dt_channel.Channel'):
        """
        Deletes a channel.
        """
        if channel.id not in self._channels:
            raise CuriousError("This channel is not part of this guild")

        return channel.delete()
示例#17
0
    def edit(self, role: 'dt_role.Role', **kwargs):
        """
        Edits a role.
        """
        if role.id not in self._roles:
            raise CuriousError("This role is not part of this guild")

        return role.edit(**kwargs)
示例#18
0
    def messages(self) -> 'ChannelMessageWrapper':
        """
        :return: The :class:`.ChannelMessageWrapper` for this channel, if applicable.
        """
        if not self.type.has_messages():
            raise CuriousError("This channel does not have messages")

        if self._messages is None:
            self._messages = ChannelMessageWrapper(self)
        return self._messages
示例#19
0
    async def remove_all_reactions(self) -> None:
        """
        Removes all reactions from a message.
        """
        if not self.guild:
            raise CuriousError("Cannot delete other reactions in a DM")

        if not self.channel.permissions(self.guild.me).manage_messages:
            raise PermissionsError("manage_messages")

        await self._bot.http.delete_all_reactions(self.channel.id, self.id)
示例#20
0
    def voice_members(self) -> '_typing.List[dt_member.Member]':
        """
        :return: A list of members that are in this voice channel.
        """
        if self.type != ChannelType.VOICE:
            raise CuriousError(
                "No members for channels that aren't voice channels")

        return list(
            filter(lambda member: member.voice.channel == self,
                   self.guild.members.values()))
示例#21
0
    def voice_members(self) -> '_typing.List[dt_member.Member]':
        """
        :return: A list of members that are in this voice channel.
        """
        if self.type != ChannelType.VOICE:
            raise CuriousError(
                "No members for channels that aren't voice channels")

        return [
            state.member for state in self.guild._voice_states.values()
            if state.channel_id == self.id
        ]
示例#22
0
    async def send_typing(self) -> None:
        """
        Starts typing in the channel for 5 seconds.
        """
        if not self.type.has_messages():
            raise CuriousError("Cannot send messages to this channel")

        if self.guild:
            if not self.effective_permissions(self.guild.me).send_messages:
                raise PermissionsError("send_message")

        await self._bot.http.send_typing(self.id)
示例#23
0
    async def send_typing(self) -> None:
        """
        Starts typing in the channel for 5 seconds.
        """
        if self.type == ChannelType.VOICE:
            raise CuriousError("Cannot send messages to a voice channel")

        if self.guild:
            if not self.permissions(self.guild.me).send_messages:
                raise PermissionsError("send_message")

        await self._bot.http.send_typing(self.id)
示例#24
0
    async def change_voice_state(self, member: 'dt_member.Member', *,
                                 deaf: bool = None, mute: bool = None):
        """
        Changes the voice state of a member.

        :param member: The :class:`.Member` to change the voice state of.
        :param deaf: Should this member be deafened?
        :param mute: Should this member be muted?
        """
        if member.voice is None:
            raise CuriousError("Cannot change voice state of member not in voice")

        await self._bot.http.edit_member_voice_state(self.id, member.id, deaf=deaf, mute=mute)
        return member.voice
示例#25
0
    async def connect_to_voice(
            self, channel: 'channel.Channel') -> 'voice_client.VoiceClient':
        """
        Connects to a voice channel in this guild.

        :param channel: The :class:`~.Channel` to connect to.
        :return: The :class:`VoiceClient` that was connected to this guild.
        """
        if voice_client is None:
            raise RuntimeError(
                "Cannot to voice - voice support is not installed")

        if channel.guild != self:
            raise CuriousError("Cannot use channel from a different guild")

        if self.voice_client is not None and self.voice_client.open:
            raise CuriousError("Voice client already exists in this guild")

        gw = self._bot._gateways[self.shard_id]
        self.voice_client = await voice_client.VoiceClient.create(
            self._bot, gw, channel)
        await self.voice_client.connect()
        return self.voice_client
示例#26
0
    async def edit(self, **kwargs) -> 'Channel':
        """
        Edits this channel.
        """
        if self.guild is None:
            raise CuriousError("Can only edit guild channels")

        if not self.permissions(self.guild.me).manage_channels:
            raise PermissionsError("manage_channels")

        if "parent" in kwargs:
            kwargs["parent_id"] = kwargs["parent"].id

        await self._bot.http.edit_channel(self.id, **kwargs)
        return self
示例#27
0
    async def add_to_guild(self,
                           guild: 'dt_guild.Guild',
                           *,
                           permissions: int = 0):
        """
        Authorizes this bot to join a guild.

        This requires a userbot client to be used.
        """
        if self._bot.is_bot:
            raise CuriousError("Bots cannot add other bots")

        if self.bot is None:
            raise CuriousError("This application has no bot associated")

        if self.owner is None and not self.public:
            raise CuriousError("This bot is not public")

        if self.requires_code_grant:
            raise CuriousError("This bot requires code grant")

        await self._bot.http.authorize_bot(self.client_id,
                                           guild.id,
                                           permissions=permissions)
示例#28
0
    def get_recent_mentions(self,
                            *,
                            limit: int = 25,
                            everyone_mentions: bool = True,
                            role_mentions: bool = True):
        """
        Gets mentions in this guild.
        """
        if self.me.user.bot is True:
            raise CuriousError("Cannot get recent mentions on bot accounts")

        return self.me.user.get_recent_mentions(
            guild=self,
            limit=limit,
            everyone_mentions=everyone_mentions,
            role_mentions=role_mentions)
示例#29
0
文件: user.py 项目: vault-the/curious
    async def open_private_channel(self) -> 'dt_channel.Channel':
        """
        Opens a private channel with a user.

        :return: The newly created private channel.
        """
        if self.discriminator == "0000":
            raise CuriousError("Cannot open a private channel with a webhook")

        # First, try and access the channel from the channel cache.
        original_channel = self._bot.state.find_channel(self.id)
        if original_channel:
            return original_channel

        # Failing that, open a new private channel.
        channel_data = await self._bot.http.create_private_channel(self.id)
        channel = self._bot.state.make_private_channel(channel_data)
        return channel
示例#30
0
    async def upload_file(self,
                          filename: str,
                          *,
                          message_content: str = None) -> 'dt_message.Message':
        """
        A higher level interface to ``send_file``.

        This allows you to specify one of the following to upload:

            - A filename (str)
            - A file-like object
            - A path-like object

        This will open the file, read it in binary, and upload it to the channel.

        :param filename: The file to send, in the formats specified above.
        :param message_content: Any extra content to be sent with the message.
        :return: The new :class:`~.Message` created.
        """
        if self.type == ChannelType.VOICE:
            raise CuriousError("Cannot send messages to a voice channel")

        if self.guild:
            if not self.permissions(self.guild.me).send_messages:
                raise PermissionsError("send_messages")

            if not self.permissions(self.guild.me).attach_files:
                raise PermissionsError("attach_files")

        if hasattr(filename, "read"):
            # file-like
            file_data = filename.read()
            name = getattr(filename, "name", None)
        else:
            # assume it's pathlike
            path = pathlib.Path(filename)
            name = path.parts[-1]

            with open(path, mode='rb') as f:
                file_data = f.read()

        return await self.send_file(file_data,
                                    name,
                                    message_content=message_content)