Expose more information from partial invites, along with counts.
This adds the following information. * `PartialInviteGuild` to replace `Object` patching * `PartialInviteChannel` to replace `Object` patching * Invite.approximate_member_count and Invite.approximate_presence_count The new partial objects provide better documentation on what is expected when you fetch random invites. Fixes #1830
This commit is contained in:
		| @@ -35,7 +35,7 @@ from .permissions import Permissions, PermissionOverwrite | ||||
| from .role import Role | ||||
| from .file import File | ||||
| from .colour import Color, Colour | ||||
| from .invite import Invite | ||||
| from .invite import Invite, PartialInviteChannel, PartialInviteGuild | ||||
| from .object import Object | ||||
| from .reaction import Reaction | ||||
| from . import utils, opus, abc | ||||
|   | ||||
| @@ -882,7 +882,7 @@ class Client: | ||||
|  | ||||
|     # Invite management | ||||
|  | ||||
|     async def get_invite(self, url): | ||||
|     async def get_invite(self, url, *, with_counts=True): | ||||
|         """|coro| | ||||
|  | ||||
|         Gets an :class:`Invite` from a discord.gg URL or ID. | ||||
| @@ -890,13 +890,17 @@ class Client: | ||||
|         Note | ||||
|         ------ | ||||
|         If the invite is for a guild you have not joined, the guild and channel | ||||
|         attributes of the returned invite will be :class:`Object` with the names | ||||
|         patched in. | ||||
|         attributes of the returned :class:`Invite` will be :class:`PartialInviteGuild` and | ||||
|         :class:`PartialInviteChannel` respectively. | ||||
|  | ||||
|         Parameters | ||||
|         ----------- | ||||
|         url : str | ||||
|         url: :class:`str` | ||||
|             The discord invite ID or URL (must be a discord.gg URL). | ||||
|         with_counts: :class:`bool` | ||||
|             Whether to include count information in the invite. This fills the | ||||
|             :attr:`Invite.approximate_member_count` and :attr:`Invite.approximate_presence_count` | ||||
|             fields. | ||||
|  | ||||
|         Raises | ||||
|         ------- | ||||
| @@ -912,7 +916,7 @@ class Client: | ||||
|         """ | ||||
|  | ||||
|         invite_id = self._resolve_invite(url) | ||||
|         data = await self.http.get_invite(invite_id) | ||||
|         data = await self.http.get_invite(invite_id, with_counts=with_counts) | ||||
|         return Invite.from_incomplete(state=self._connection, data=data) | ||||
|  | ||||
|     async def delete_invite(self, invite): | ||||
|   | ||||
| @@ -83,7 +83,7 @@ class Guild(Hashable): | ||||
|         The timeout to get sent to the AFK channel. | ||||
|     afk_channel: Optional[:class:`VoiceChannel`] | ||||
|         The channel that denotes the AFK channel. None if it doesn't exist. | ||||
|     icon: :class:`str` | ||||
|     icon: Optional[:class:`str`] | ||||
|         The guild's icon. | ||||
|     id: :class:`int` | ||||
|         The guild's ID. | ||||
| @@ -114,7 +114,7 @@ class Guild(Hashable): | ||||
|         - ``VERIFIED``: Guild is a "verified" server. | ||||
|         - ``MORE_EMOJI``: Guild is allowed to have more than 50 custom emoji. | ||||
|  | ||||
|     splash: :class:`str` | ||||
|     splash: Optional[:class:`str`] | ||||
|         The guild's invite splash. | ||||
|     """ | ||||
|  | ||||
|   | ||||
| @@ -647,8 +647,11 @@ class HTTPClient: | ||||
|  | ||||
|         return self.request(r, reason=reason, json=payload) | ||||
|  | ||||
|     def get_invite(self, invite_id): | ||||
|         return self.request(Route('GET', '/invite/{invite_id}', invite_id=invite_id)) | ||||
|     def get_invite(self, invite_id, *, with_counts=True): | ||||
|         params = { | ||||
|             'with_counts': int(with_counts) | ||||
|         } | ||||
|         return self.request(Route('GET', '/invite/{invite_id}', invite_id=invite_id), params=params) | ||||
|  | ||||
|     def invites_from(self, guild_id): | ||||
|         return self.request(Route('GET', '/guilds/{guild_id}/invites', guild_id=guild_id)) | ||||
|   | ||||
| @@ -27,6 +27,141 @@ DEALINGS IN THE SOFTWARE. | ||||
| from .utils import parse_time | ||||
| from .mixins import Hashable | ||||
| from .object import Object | ||||
| from .enums import ChannelType, VerificationLevel, try_enum | ||||
| from collections import namedtuple | ||||
|  | ||||
| class PartialInviteChannel(namedtuple('PartialInviteChannel', 'id name type')): | ||||
|     """Represents a "partial" invite channel. | ||||
|  | ||||
|     This model will be given when the user is not part of the | ||||
|     guild the :class:`Invite` resolves to. | ||||
|  | ||||
|     .. container:: operations | ||||
|  | ||||
|         .. describe:: x == y | ||||
|  | ||||
|             Checks if two partial channels are the same. | ||||
|  | ||||
|         .. describe:: x != y | ||||
|  | ||||
|             Checks if two partial channels are not the same. | ||||
|  | ||||
|         .. describe:: hash(x) | ||||
|  | ||||
|             Return the partial channel's hash. | ||||
|  | ||||
|         .. describe:: str(x) | ||||
|  | ||||
|             Returns the partial channel's name. | ||||
|  | ||||
|     Attributes | ||||
|     ----------- | ||||
|     name: :class:`str` | ||||
|         The partial channel's name. | ||||
|     id: :class:`int` | ||||
|         The partial channel's ID. | ||||
|     type: :class:`ChannelType` | ||||
|         The partial channel's type. | ||||
|     """ | ||||
|  | ||||
|     __slots__ = () | ||||
|  | ||||
|     def __str__(self): | ||||
|         return self.name | ||||
|  | ||||
|     @property | ||||
|     def mention(self): | ||||
|         """:class:`str` : The string that allows you to mention the channel.""" | ||||
|         return '<#%s>' % self.id | ||||
|  | ||||
|     @property | ||||
|     def created_at(self): | ||||
|         """Returns the channel's creation time in UTC.""" | ||||
|         return utils.snowflake_time(self.id) | ||||
|  | ||||
| class PartialInviteGuild(namedtuple('PartialInviteGuild', 'features icon id name splash verification_level')): | ||||
|     """Represents a "partial" invite guild. | ||||
|  | ||||
|     This model will be given when the user is not part of the | ||||
|     guild the :class:`Invite` resolves to. | ||||
|  | ||||
|     .. container:: operations | ||||
|  | ||||
|         .. describe:: x == y | ||||
|  | ||||
|             Checks if two partial guilds are the same. | ||||
|  | ||||
|         .. describe:: x != y | ||||
|  | ||||
|             Checks if two partial guilds are not the same. | ||||
|  | ||||
|         .. describe:: hash(x) | ||||
|  | ||||
|             Return the partial guild's hash. | ||||
|  | ||||
|         .. describe:: str(x) | ||||
|  | ||||
|             Returns the partial guild's name. | ||||
|  | ||||
|     Attributes | ||||
|     ----------- | ||||
|     name: :class:`str` | ||||
|         The partial guild's name. | ||||
|     id: :class:`int` | ||||
|         The partial guild's ID. | ||||
|     verification_level: :class:`VerificationLevel` | ||||
|         The partial guild's verification level. | ||||
|     features: List[:class:`str`] | ||||
|         A list of features the guild has. See :attr:`Guild.features` for more information. | ||||
|     icon: Optional[:class:`str`] | ||||
|         The partial guild's icon. | ||||
|     splash: Optional[:class:`str`] | ||||
|         The partial guild's invite splash. | ||||
|     """ | ||||
|  | ||||
|     __slots__ = () | ||||
|  | ||||
|     def __str__(self): | ||||
|         return self.name | ||||
|  | ||||
|     @property | ||||
|     def created_at(self): | ||||
|         """Returns the guild's creation time in UTC.""" | ||||
|         return utils.snowflake_time(self.id) | ||||
|  | ||||
|     @property | ||||
|     def icon_url(self): | ||||
|         """Returns the URL version of the guild's icon. Returns an empty string if it has no icon.""" | ||||
|         return self.icon_url_as() | ||||
|  | ||||
|     def icon_url_as(self, *, format='webp', size=1024): | ||||
|         """:class:`str`: The same operation as :meth:`Guild.icon_url_as`.""" | ||||
|         if not valid_icon_size(size): | ||||
|             raise InvalidArgument("size must be a power of 2 between 16 and 2048") | ||||
|         if format not in VALID_ICON_FORMATS: | ||||
|             raise InvalidArgument("format must be one of {}".format(VALID_ICON_FORMATS)) | ||||
|  | ||||
|         if self.icon is None: | ||||
|             return '' | ||||
|  | ||||
|         return 'https://cdn.discordapp.com/icons/{0.id}/{0.icon}.{1}?size={2}'.format(self, format, size) | ||||
|  | ||||
|     @property | ||||
|     def splash_url(self): | ||||
|         """Returns the URL version of the guild's invite splash. Returns an empty string if it has no splash.""" | ||||
|         return self.splash_url_as() | ||||
|  | ||||
|     def splash_url_as(self, *, format='webp', size=2048): | ||||
|         """:class:`str`: The same operation as :meth:`Guild.splash_url_as`.""" | ||||
|         if not valid_icon_size(size): | ||||
|             raise InvalidArgument("size must be a power of 2 between 16 and 2048") | ||||
|         if format not in VALID_ICON_FORMATS: | ||||
|             raise InvalidArgument("format must be one of {}".format(VALID_ICON_FORMATS)) | ||||
|  | ||||
|         if self.splash is None: | ||||
|             return '' | ||||
|  | ||||
|         return 'https://cdn.discordapp.com/splashes/{0.id}/{0.splash}.{1}?size={2}'.format(self, format, size) | ||||
|  | ||||
| class Invite(Hashable): | ||||
|     """Represents a Discord :class:`Guild` or :class:`abc.GuildChannel` invite. | ||||
| @@ -58,7 +193,7 @@ class Invite(Hashable): | ||||
|         How long the before the invite expires in seconds. A value of 0 indicates that it doesn't expire. | ||||
|     code: :class:`str` | ||||
|         The URL fragment used for the invite. | ||||
|     guild: :class:`Guild` | ||||
|     guild: Union[:class:`Guild`, :class:`PartialInviteGuild`] | ||||
|         The guild the invite is for. | ||||
|     revoked: :class:`bool` | ||||
|         Indicates if the invite has been revoked. | ||||
| @@ -73,13 +208,19 @@ class Invite(Hashable): | ||||
|         How many times the invite can be used. | ||||
|     inviter: :class:`User` | ||||
|         The user who created the invite. | ||||
|     channel: :class:`abc.GuildChannel` | ||||
|     approximate_member_count: Optional[:class:`int`] | ||||
|         The approximate number of members in the guild. | ||||
|     approximate_presence_count: Optional[:class:`int`] | ||||
|         The approximate number of members currently active in the guild. | ||||
|         This includes idle, dnd, online, and invisible members. Offline members are excluded. | ||||
|     channel: Union[:class:`abc.GuildChannel`, :class:`PartialInviteChannel`] | ||||
|         The channel the invite is for. | ||||
|     """ | ||||
|  | ||||
|  | ||||
|     __slots__ = ('max_age', 'code', 'guild', 'revoked', 'created_at', 'uses', | ||||
|                  'temporary', 'max_uses', 'inviter', 'channel', '_state') | ||||
|                  'temporary', 'max_uses', 'inviter', 'channel', '_state', | ||||
|                  'approximate_member_count', 'approximate_presence_count' ) | ||||
|  | ||||
|     def __init__(self, *, state, data): | ||||
|         self._state = state | ||||
| @@ -91,6 +232,8 @@ class Invite(Hashable): | ||||
|         self.temporary = data.get('temporary') | ||||
|         self.uses = data.get('uses') | ||||
|         self.max_uses = data.get('max_uses') | ||||
|         self.approximate_presence_count = data.get('approximate_presence_count') | ||||
|         self.approximate_member_count = data.get('approximate_member_count') | ||||
|  | ||||
|         inviter_data = data.get('inviter') | ||||
|         self.inviter = None if inviter_data is None else self._state.store_user(inviter_data) | ||||
| @@ -104,17 +247,16 @@ class Invite(Hashable): | ||||
|         if guild is not None: | ||||
|             channel = guild.get_channel(channel_id) | ||||
|         else: | ||||
|             guild = Object(id=guild_id) | ||||
|             channel = Object(id=channel_id) | ||||
|             guild.name = data['guild']['name'] | ||||
|  | ||||
|             guild.splash = data['guild']['splash'] | ||||
|             guild.splash_url = '' | ||||
|             if guild.splash: | ||||
|                 guild.splash_url = 'https://cdn.discordapp.com/splashes/{0.id}/{0.splash}.jpg?size=2048'.format(guild) | ||||
|  | ||||
|             channel.name = data['channel']['name'] | ||||
|  | ||||
|             channel_data = data['channel'] | ||||
|             guild_data = data['guild'] | ||||
|             channel_type = try_enum(ChannelType, channel_data['type']) | ||||
|             channel = PartialInviteChannel(id=channel_id, name=channel_data['name'], type=channel_type) | ||||
|             guild = PartialInviteGuild(id=guild_id, | ||||
|                                        name=guild_data['name'], | ||||
|                                        features=guild_data.get('features', []), | ||||
|                                        icon=guild_data.get('icon'), | ||||
|                                        splash=guild_data.get('splash'), | ||||
|                                        verification_level=try_enum(VerificationLevel, guild_data.get('verification_level'))) | ||||
|         data['guild'] = guild | ||||
|         data['channel'] = channel | ||||
|         return cls(state=state, data=data) | ||||
|   | ||||
							
								
								
									
										11
									
								
								docs/api.rst
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										11
									
								
								docs/api.rst
									
									
									
									
									
								
							| @@ -2035,6 +2035,17 @@ GroupChannel | ||||
|     .. autocomethod:: typing | ||||
|         :async-with: | ||||
|  | ||||
| PartialInviteGuild | ||||
| ~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| .. autoclass:: PartialInviteGuild() | ||||
|     :members: | ||||
|  | ||||
| PartialInviteChannel | ||||
| ~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| .. autoclass:: PartialInviteChannel() | ||||
|     :members: | ||||
|  | ||||
| Invite | ||||
| ~~~~~~~ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user