Skip to content

Commit e3ab3b4

Browse files
committed
feat: Add scheduled_event field to discord.Invite
Signed-off-by: Mathieu C <McCuber04@outlook.de> Signed-off-by: Mathieu Corsham <McCuber04@outlook.de>
1 parent 383dddf commit e3ab3b4

File tree

3 files changed

+105
-53
lines changed

3 files changed

+105
-53
lines changed

discord/abc.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -964,15 +964,15 @@ async def move(
964964
async def create_invite(
965965
self,
966966
*,
967-
reason: Optional[str] = None,
968967
max_age: int = 0,
969968
max_uses: int = 0,
970969
temporary: bool = False,
971970
unique: bool = True,
972971
target_event: Optional[GuildScheduledEvent] = None,
973972
target_type: Optional[InviteTargetType] = None,
974973
target_user: Optional[User] = None,
975-
target_application_id: Optional[int] = None
974+
target_application_id: Optional[int] = None,
975+
reason: Optional[str] = None,
976976
) -> Invite:
977977
"""|coro|
978978

discord/http.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,9 @@ def __init__(
8686
multipart: Optional[List[Dict[str, Any]]] = None,
8787
files: Optional[Sequence[File]] = None
8888
):
89-
self.payload = payload
90-
self.multipart = multipart
91-
self.files = files
89+
self.payload: Optional[Dict[str, Any]] = payload
90+
self.multipart: Optional[List[Dict[str, Any]]] = multipart
91+
self.files: Optional[Sequence[File]] = files
9292

9393
def __enter__(self):
9494
return self
@@ -1702,7 +1702,7 @@ def delete_automod_rule(self, guild_id: int, rule_id: int, reason: str = None):
17021702
# Misc
17031703
def application_info(self):
17041704
return self.request(Route('GET', '/oauth2/applications/@me'))
1705-
1705+
17061706
async def get_gateway(self, *, encoding='json', v=10, zlib=True):
17071707
try:
17081708
data = await self.request(Route('GET', '/gateway'))
@@ -1726,11 +1726,15 @@ async def get_bot_gateway(self, *, encoding='json', v=10, zlib=True):
17261726
value = '{0}?encoding={1}&v={2}'
17271727
return data['shards'], value.format(data['url'], encoding, v)
17281728

1729-
def get_user(self, user_id):
1729+
def get_voice_regions(self):
1730+
return self.request(Route('GET', '/voice/regions'))
1731+
1732+
def get_user(self, user_id: int):
17301733
return self.request(Route('GET', '/users/{user_id}', user_id=user_id))
17311734

1732-
def get_user_profile(self, user_id):
1735+
def get_user_profile(self, user_id: int):
17331736
return self.request(Route('GET', '/users/{user_id}/profile', user_id=user_id))
17341737

17351738
def get_all_nitro_stickers(self):
1736-
return self.request(Route('GET', '/sticker-packs'))
1739+
return self.request(Route('GET', '/sticker-packs'))
1740+

discord/invite.py

Lines changed: 92 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,11 @@
2323
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2424
DEALINGS IN THE SOFTWARE.
2525
"""
26+
from __future__ import annotations
2627

27-
from typing import Optional, TYPE_CHECKING
28+
29+
from typing import Optional, List, TYPE_CHECKING
30+
from typing_extensions import Literal
2831

2932
from .asset import Asset
3033
from .welcome_screen import WelcomeScreen
@@ -34,6 +37,8 @@
3437
from .enums import ChannelType, VerificationLevel, try_enum
3538

3639
if TYPE_CHECKING:
40+
from datetime import datetime
41+
3742
from .state import ConnectionState
3843
from .scheduled_event import GuildScheduledEvent
3944

@@ -88,7 +93,7 @@ def __repr__(self):
8893
@property
8994
def mention(self):
9095
""":class:`str`: The string that allows you to mention the channel."""
91-
return '<#%s>' % self.id
96+
return f'<#{self.id}>'
9297

9398
@property
9499
def created_at(self):
@@ -142,47 +147,54 @@ class PartialInviteGuild:
142147
__slots__ = ('_state', 'features', 'icon', 'banner', 'id', 'name', 'splash',
143148
'verification_level', 'description', 'welcome_screen')
144149

145-
def __init__(self, state: 'ConnectionState', data, id):
146-
self._state = state
147-
self.id = id
148-
self.name = data['name']
149-
self.features = data.get('features', [])
150-
self.icon = data.get('icon')
151-
self.banner = data.get('banner')
152-
self.splash = data.get('splash')
153-
self.verification_level = try_enum(VerificationLevel, data.get('verification_level'))
154-
self.description = data.get('description')
150+
def __init__(self, state: ConnectionState, data, id):
151+
self._state: ConnectionState = state
152+
self.id: int = id
153+
self.name: str = data['name']
154+
self.features: List[str] = data.get('features', [])
155+
self.icon: Optional[str] = data.get('icon')
156+
self.banner: Optional[str] = data.get('banner')
157+
self.splash: Optional[str] = data.get('splash')
158+
self.verification_level: VerificationLevel = try_enum(VerificationLevel, data.get('verification_level'))
159+
self.description: Optional[str] = data.get('description')
160+
self.welcome_screen: Optional[WelcomeScreen]
155161
welcome_screen = data.get('welcome_screen', None)
156162
if welcome_screen:
157163
self.welcome_screen = WelcomeScreen(state=state, guild=self._state._get_guild(self.id) or self, data=welcome_screen)
158164
else:
159165
self.welcome_screen = None
160166

161-
def __str__(self):
167+
def __str__(self) -> str:
162168
return self.name
163169

164-
def __repr__(self):
170+
def __repr__(self) -> str:
165171
return '<{0.__class__.__name__} id={0.id} name={0.name!r} features={0.features} ' \
166172
'description={0.description!r}>'.format(self)
167173

168174
@property
169-
def created_at(self):
175+
def created_at(self) -> datetime:
170176
""":class:`datetime.datetime`: Returns the guild's creation time in UTC."""
171177
return snowflake_time(self.id)
172178

173179
@property
174-
def icon_url(self):
180+
def icon_url(self) -> Asset:
175181
""":class:`Asset`: Returns the guild's icon asset."""
176182
return self.icon_url_as()
177183

178-
def is_icon_animated(self):
184+
def is_icon_animated(self) -> bool:
179185
""":class:`bool`: Returns ``True`` if the guild has an animated icon.
180186
181187
.. versionadded:: 1.4
182188
"""
183189
return bool(self.icon and self.icon.startswith('a_'))
184190

185-
def icon_url_as(self, *, format=None, static_format='webp', size=1024):
191+
def icon_url_as(
192+
self,
193+
*,
194+
format: Literal['webp', 'jpeg', 'jpg', 'png', 'gif'] = None,
195+
static_format: Literal['webp', 'jpeg', 'jpg', 'png'] = 'webp',
196+
size: int =1024
197+
) -> Asset:
186198
"""The same operation as :meth:`Guild.icon_url_as`.
187199
188200
Returns
@@ -193,11 +205,16 @@ def icon_url_as(self, *, format=None, static_format='webp', size=1024):
193205
return Asset._from_guild_icon(self._state, self, format=format, static_format=static_format, size=size)
194206

195207
@property
196-
def banner_url(self):
208+
def banner_url(self) -> Asset:
197209
""":class:`Asset`: Returns the guild's banner asset."""
198210
return self.banner_url_as()
199211

200-
def banner_url_as(self, *, format='webp', size=2048):
212+
def banner_url_as(
213+
self,
214+
*,
215+
format: Literal['webp', 'jpeg', 'jpg', 'png'] = 'webp',
216+
size: int = 2048
217+
) -> Asset:
201218
"""The same operation as :meth:`Guild.banner_url_as`.
202219
203220
Returns
@@ -208,11 +225,16 @@ def banner_url_as(self, *, format='webp', size=2048):
208225
return Asset._from_guild_image(self._state, self.id, self.banner, 'banners', format=format, size=size)
209226

210227
@property
211-
def splash_url(self):
228+
def splash_url(self) -> Asset:
212229
""":class:`Asset`: Returns the guild's invite splash asset."""
213230
return self.splash_url_as()
214231

215-
def splash_url_as(self, *, format='webp', size=2048):
232+
def splash_url_as(
233+
self,
234+
*,
235+
format: Literal['webp', 'jpeg', 'jpg', 'png'] = 'webp',
236+
size: int = 2048
237+
) -> Asset:
216238
"""The same operation as :meth:`Guild.splash_url_as`.
217239
218240
Returns
@@ -222,6 +244,7 @@ def splash_url_as(self, *, format='webp', size=2048):
222244
"""
223245
return Asset._from_guild_image(self._state, self.id, self.splash, 'splashes', format=format, size=size)
224246

247+
225248
class Invite(Hashable):
226249
r"""Represents a Discord :class:`Guild` or :class:`abc.GuildChannel` invite.
227250
@@ -265,6 +288,8 @@ class Invite(Hashable):
265288
+------------------------------------+----------------------------------------------------------+
266289
| :attr:`approximate_presence_count` | :meth:`Client.fetch_invite` |
267290
+------------------------------------+----------------------------------------------------------+
291+
| :attr:`scheduled_event` | :meth:`Client.fetch_invite` |
292+
+------------------------------------+----------------------------------------------------------+
268293
269294
If it's not in the table above then it is available by all methods.
270295
@@ -296,41 +321,44 @@ class Invite(Hashable):
296321
approximate_presence_count: Optional[:class:`int`]
297322
The approximate number of members currently active in the guild.
298323
This includes idle, dnd, online, and invisible members. Offline members are excluded.
324+
scheduled_event: Optional[:class:`GuildScheduledEvent`]
325+
The scheduled event attached to this invite link, if any.
299326
channel: Union[:class:`abc.GuildChannel`, :class:`Object`, :class:`PartialInviteChannel`]
300327
The channel the invite is for.
301328
"""
302329

303330
__slots__ = ('max_age', 'code', 'guild', 'revoked', 'created_at', 'uses',
304331
'temporary', 'max_uses', 'inviter', 'channel', '_state',
305332
'approximate_member_count', 'approximate_presence_count',
306-
'event')
333+
'scheduled_event')
307334

308335
BASE = 'https://discord.gg'
309336

310-
def __init__(self, *, state: 'ConnectionState', data):
337+
def __init__(self, *, state: ConnectionState, data) -> None:
311338
self._state = state
312339
self.max_age = data.get('max_age')
313340
self.code = data.get('code')
314341
self.guild = data.get('guild')
315-
self.revoked = data.get('revoked')
316-
self.created_at = parse_time(data.get('created_at'))
317-
self.temporary = data.get('temporary')
318-
self.uses = data.get('uses')
319-
self.max_uses = data.get('max_uses')
320-
self.approximate_presence_count = data.get('approximate_presence_count')
321-
self.approximate_member_count = data.get('approximate_member_count')
342+
self.revoked: Optional[bool] = data.get('revoked')
343+
self.created_at: datetime = parse_time(data.get('created_at'))
344+
self.temporary: Optional[bool] = data.get('temporary')
345+
self.uses: Optional[int] = data.get('uses')
346+
self.max_uses: Optional[int] = data.get('max_uses')
347+
self.approximate_presence_count: Optional[int] = data.get('approximate_presence_count')
348+
self.approximate_member_count: Optional[int] = data.get('approximate_member_count')
322349

323350
inviter_data = data.get('inviter')
324351
self.inviter = None if inviter_data is None else self._state.store_user(inviter_data)
325352
self.channel = data.get('channel')
353+
self.scheduled_event: Optional[GuildScheduledEvent]
326354
guild_scheduled_event = data.get('guild_scheduled_event', None)
327355
if guild_scheduled_event is not None:
328-
self.event: Optional['GuildScheduledEvent'] = state.store_event(guild=self.guild, data=guild_scheduled_event)
356+
self.scheduled_event = state.store_event(guild=self.guild, data=guild_scheduled_event)
329357
else:
330-
self.event = None
358+
self.scheduled_event = None
331359

332360
@classmethod
333-
def from_incomplete(cls, *, state, data):
361+
def from_incomplete(cls, *, state: ConnectionState, data) -> Invite:
334362
try:
335363
guild_id = int(data['guild']['id'])
336364
except KeyError:
@@ -358,7 +386,7 @@ def from_incomplete(cls, *, state, data):
358386
return cls(state=state, data=data)
359387

360388
@classmethod
361-
def from_gateway(cls, *, state, data):
389+
def from_gateway(cls, *, state: ConnectionState, data) -> Invite:
362390
guild_id = _get_as_snowflake(data, 'guild_id')
363391
guild = state._get_guild(guild_id)
364392
channel_id = _get_as_snowflake(data, 'channel_id')
@@ -372,28 +400,29 @@ def from_gateway(cls, *, state, data):
372400
data['channel'] = channel
373401
return cls(state=state, data=data)
374402

375-
def __str__(self):
403+
def __str__(self) -> str:
376404
return self.url
377405

378-
def __repr__(self):
379-
return '<Invite code={0.code!r} guild={0.guild!r} ' \
380-
'online={0.approximate_presence_count} ' \
381-
'members={0.approximate_member_count}>'.format(self)
406+
def __repr__(self) -> str:
407+
return f'<Invite code={self.code!r} guild={self.guild!r} ' \
408+
f'online={self.approximate_presence_count} ' \
409+
f'members={self.approximate_member_count} ' \
410+
f'scheduled_event={self.scheduled_event}>'
382411

383-
def __hash__(self):
412+
def __hash__(self) -> int:
384413
return hash(self.code)
385414

386415
@property
387-
def id(self):
416+
def id(self) -> str:
388417
""":class:`str`: Returns the proper code portion of the invite."""
389418
return self.code
390419

391420
@property
392421
def url(self):
393422
""":class:`str`: A property that retrieves the invite URL."""
394-
return self.BASE + '/' + self.code
423+
return f"{self.BASE}/{self.code}{f'?event={self.scheduled_event.id}' if self.scheduled_event else ''}"
395424

396-
async def delete(self, *, reason=None):
425+
async def delete(self, *, reason: Optional[str] = None) -> None:
397426
"""|coro|
398427
399428
Revokes the instant invite.
@@ -416,3 +445,22 @@ async def delete(self, *, reason=None):
416445
"""
417446

418447
await self._state.http.delete_invite(self.code, reason=reason)
448+
449+
def set_scheduled_event(self, event: GuildScheduledEvent) -> None:
450+
"""Links the given scheduled event to this invite.
451+
452+
.. note::
453+
454+
Scheduled events aren't actually associated with invites on the API.
455+
Any guild channel invite can have an event attached to it. Using
456+
:meth:`abc.GuildChannel.create_invite`, :meth:`Client.fetch_invite`,
457+
or this method, you can link scheduled events.
458+
459+
.. versionadded:: 2.0
460+
461+
Parameters
462+
----------
463+
event: :class:`ScheduledEvent`
464+
The scheduled event object to link.
465+
"""
466+
self.scheduled_event = event

0 commit comments

Comments
 (0)