diff --git a/discord/client.py b/discord/client.py index 07d86703f..9b32a64ed 100644 --- a/discord/client.py +++ b/discord/client.py @@ -1307,7 +1307,7 @@ class Client: data = await self.http.get_template(code) return Template(data=data, state=self._connection) # type: ignore - async def fetch_guild(self, guild_id: int, /) -> Guild: + async def fetch_guild(self, guild_id: int, /, *, with_counts: bool = True) -> Guild: """|coro| Retrieves a :class:`.Guild` from an ID. @@ -1325,6 +1325,13 @@ class Client: ``guild_id`` parameter is now positional-only. + with_counts: Optional[:class:`bool`] + Whether to include count information in the guild. This fills the + :attr:`.Guild.approximate_member_count` and :attr:`.Guild.approximate_presence_count` + attributes without needing any privileged intents. Defaults to ``True``. + + .. versionadded:: 2.0 + Parameters ----------- guild_id: :class:`int` @@ -1342,7 +1349,7 @@ class Client: :class:`.Guild` The guild from the ID. """ - data = await self.http.get_guild(guild_id) + data = await self.http.get_guild(guild_id, with_counts=with_counts) return Guild(data=data, state=self._connection) async def create_guild( diff --git a/discord/guild.py b/discord/guild.py index 091c72f6f..d5d037155 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -255,6 +255,18 @@ class Guild(Hashable): .. versionchanged:: 2.0 This field is now an enum instead of an :class:`int`. + + approximate_member_count: Optional[:class:`int`] + The approximate number of members in the guild. This is ``None`` unless the guild is obtained + using :meth:`Client.fetch_guild` with ``with_counts=True``. + + .. versionadded:: 2.0 + approximate_presence_count: Optional[:class:`int`] + The approximate number of members currently active in the guild. + Offline members are excluded. This is ``None`` unless the guild is obtained using + :meth:`Client.fetch_guild` with ``with_counts=True``. + + .. versionchanged:: 2.0 """ __slots__ = ( @@ -297,6 +309,8 @@ class Guild(Hashable): '_stage_instances', '_scheduled_events', '_threads', + 'approximate_member_count', + 'approximate_presence_count', ) _PREMIUM_GUILD_LIMITS: ClassVar[Dict[Optional[int], _GuildLimit]] = { @@ -463,6 +477,8 @@ class Guild(Hashable): self._public_updates_channel_id: Optional[int] = utils._get_as_snowflake(guild, 'public_updates_channel_id') self.nsfw_level: NSFWLevel = try_enum(NSFWLevel, guild.get('nsfw_level', 0)) self.mfa_level: MFALevel = try_enum(MFALevel, guild.get('mfa_level', 0)) + self.approximate_presence_count: Optional[int] = guild.get('approximate_presence_count') + self.approximate_member_count: Optional[int] = guild.get('approximate_member_count') self._stage_instances: Dict[int, StageInstance] = {} for s in guild.get('stage_instances', []): diff --git a/discord/http.py b/discord/http.py index bd65508c8..3fed678a2 100644 --- a/discord/http.py +++ b/discord/http.py @@ -1075,8 +1075,9 @@ class HTTPClient: def leave_guild(self, guild_id: Snowflake) -> Response[None]: return self.request(Route('DELETE', '/users/@me/guilds/{guild_id}', guild_id=guild_id)) - def get_guild(self, guild_id: Snowflake) -> Response[guild.Guild]: - return self.request(Route('GET', '/guilds/{guild_id}', guild_id=guild_id)) + def get_guild(self, guild_id: Snowflake, *, with_counts: bool = True) -> Response[guild.Guild]: + params = {'with_counts': int(with_counts)} + return self.request(Route('GET', '/guilds/{guild_id}', guild_id=guild_id), params=params) def delete_guild(self, guild_id: Snowflake) -> Response[None]: return self.request(Route('DELETE', '/guilds/{guild_id}', guild_id=guild_id))