Skip to content

Commit b70033b

Browse files
authored
Merge pull request #1085 from interactions-py/unstable
chore: Merge unstable to stable
2 parents 348def8 + 47c4e83 commit b70033b

File tree

14 files changed

+344
-96
lines changed

14 files changed

+344
-96
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ repos:
2929
- id: check-merge-conflict
3030
name: Merge Conflicts
3131
- repo: https://github.com/psf/black
32-
rev: 22.6.0
32+
rev: 22.8.0
3333
hooks:
3434
- id: black
3535
name: Black Formatting

interactions/api/gateway/client.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -959,16 +959,18 @@ async def _send_packet(self, data: Dict[str, Any]) -> None:
959959
"""
960960
_data = dumps(data) if isinstance(data, dict) else data
961961
packet: str = _data.decode("utf-8") if isinstance(_data, bytes) else _data
962+
log.debug(packet)
962963

963-
if data["op"] != OpCodeType.HEARTBEAT.value:
964-
# This is because the ratelimiter limits already accounts for this.
965-
await self._ratelimiter.block()
964+
async with self.reconnect_lock: # needs to lock while it reconnects.
966965

967-
if self._client is not None: # this mitigates against another edge case.
968-
self._last_send = perf_counter()
969-
log.debug(packet)
966+
if data["op"] != OpCodeType.HEARTBEAT.value:
967+
# This is because the ratelimiter limits already accounts for this.
968+
await self._ratelimiter.block()
970969

971-
await self._client.send_str(packet)
970+
if self._client is not None: # this mitigates against another edge case.
971+
self._last_send = perf_counter()
972+
973+
await self._client.send_str(packet)
972974

973975
async def __identify(
974976
self, shard: Optional[List[Tuple[int]]] = None, presence: Optional[ClientPresence] = None

interactions/api/http/channel.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,3 +307,72 @@ async def delete_stage_instance(self, channel_id: int, reason: Optional[str] = N
307307
return await self._req.request(
308308
Route("DELETE", f"/stage-instances/{channel_id}"), reason=reason
309309
)
310+
311+
async def create_tag(
312+
self,
313+
channel_id: int,
314+
name: str,
315+
emoji_id: Optional[int] = None,
316+
emoji_name: Optional[str] = None,
317+
) -> dict:
318+
"""
319+
Create a new tag.
320+
321+
.. note::
322+
Can either have an emoji_id or an emoji_name, but not both.
323+
emoji_id is meant for custom emojis, emoji_name is meant for unicode emojis.
324+
325+
:param channel_id: Channel ID snowflake.
326+
:param name: The name of the tag
327+
:param emoji_id: The ID of the emoji to use for the tag
328+
:param emoji_name: The name of the emoji to use for the tag
329+
"""
330+
331+
_dct = {"name": name}
332+
if emoji_id:
333+
_dct["emoji_id"] = emoji_id
334+
if emoji_name:
335+
_dct["emoji_name"] = emoji_name
336+
337+
return await self._req.request(Route("POST", f"/channels/{channel_id}/tags"), json=_dct)
338+
339+
async def edit_tag(
340+
self,
341+
channel_id: int,
342+
tag_id: int,
343+
name: str,
344+
emoji_id: Optional[int] = None,
345+
emoji_name: Optional[str] = None,
346+
) -> dict:
347+
"""
348+
Update a tag.
349+
350+
.. note::
351+
Can either have an emoji_id or an emoji_name, but not both.
352+
emoji_id is meant for custom emojis, emoji_name is meant for unicode emojis.
353+
354+
:param channel_id: Channel ID snowflake.
355+
:param tag_id: The ID of the tag to update.
356+
:param name: The new name of the tag
357+
:param emoji_id: The ID of the emoji to use for the tag
358+
:param emoji_name: The name of the emoji to use for the tag
359+
"""
360+
361+
_dct = {"name": name}
362+
if emoji_id:
363+
_dct["emoji_id"] = emoji_id
364+
if emoji_name:
365+
_dct["emoji_name"] = emoji_name
366+
367+
return await self._req.request(
368+
Route("PUT", f"/channels/{channel_id}/tags/{tag_id}"), json=_dct
369+
)
370+
371+
async def delete_tag(self, channel_id: int, tag_id: int) -> dict:
372+
"""
373+
Delete a forum tag.
374+
375+
:param channel_id: Channel ID snowflake.
376+
:param tag_id: The ID of the tag to delete
377+
"""
378+
return await self._req.request(Route("DELETE", f"/channels/{channel_id}/tags/{tag_id}"))

interactions/api/http/guild.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -473,21 +473,21 @@ async def create_guild_ban(
473473
self,
474474
guild_id: int,
475475
user_id: int,
476-
delete_message_days: Optional[int] = 0,
476+
delete_message_seconds: Optional[int] = 0,
477477
reason: Optional[str] = None,
478478
) -> None:
479479
"""
480480
Bans a person from the guild, and optionally deletes previous messages sent by them.
481481
482482
:param guild_id: Guild ID snowflake
483483
:param user_id: User ID snowflake
484-
:param delete_message_days: Number of days to delete messages, from 0 to 7. Defaults to 0
484+
:param delete_message_seconds: Number of seconds to delete messages for, between 0 and 604800. Default to 0
485485
:param reason: Optional reason to ban.
486486
"""
487487

488488
return await self._req.request(
489489
Route("PUT", f"/guilds/{guild_id}/bans/{user_id}"),
490-
json={"delete_message_days": delete_message_days},
490+
json={"delete_message_seconds": delete_message_seconds},
491491
reason=reason,
492492
)
493493

Lines changed: 20 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
from typing import List
22

33
from ...api.cache import Cache
4-
from ..models import Snowflake
54
from .request import _Request
65
from .route import Route
76

@@ -16,15 +15,14 @@ class ScheduledEventRequest:
1615
def __init__(self) -> None:
1716
pass
1817

19-
async def create_scheduled_event(self, guild_id: Snowflake, payload: dict) -> dict:
18+
async def create_scheduled_event(self, guild_id: int, payload: dict) -> dict:
2019
"""
2120
Creates a scheduled event.
2221
2322
:param guild_id: Guild ID snowflake.
2423
:param payload: The dictionary containing the parameters and values to edit the associated event.
2524
:return: A dictionary containing the new guild scheduled event object on success.
2625
"""
27-
guild_id = int(guild_id)
2826
valid_keys = (
2927
"channel_id",
3028
"name",
@@ -42,50 +40,42 @@ async def create_scheduled_event(self, guild_id: Snowflake, payload: dict) -> di
4240
)
4341

4442
async def get_scheduled_event(
45-
self, guild_id: Snowflake, guild_scheduled_event_id: Snowflake, with_user_count: bool
43+
self, guild_id: int, guild_scheduled_event_id: int, with_user_count: bool
4644
) -> dict:
4745
"""
4846
Gets a guild scheduled event.
4947
5048
:param guild_id: Guild ID snowflake.
5149
:param guild_scheduled_event_id: Guild Scheduled Event ID snowflake.
52-
:param with_user_count: A boolean to include number of users subscribed to the associated event, if given.
50+
:param with_user_count: Whether the number of users subscribed to the events is returned.
5351
:return: A dictionary containing the guild scheduled event object on success.
5452
"""
55-
guild_id, event_id = int(guild_id), int(guild_scheduled_event_id)
56-
params = {}
57-
if with_user_count:
58-
params["with_user_count"] = str(with_user_count)
5953

6054
return await self._req.request(
6155
Route(
6256
"GET",
6357
"/guilds/{guild_id}/scheduled-events/{event_id}",
6458
guild_id=guild_id,
65-
event_id=event_id,
59+
event_id=guild_scheduled_event_id,
6660
),
67-
params=params,
61+
params={"with_user_count": str(with_user_count).lower()},
6862
)
6963

70-
async def get_scheduled_events(self, guild_id: Snowflake, with_user_count: bool) -> List[dict]:
64+
async def get_scheduled_events(self, guild_id: int, with_user_count: bool) -> List[dict]:
7165
"""
7266
Gets all guild scheduled events in a guild.
7367
7468
:param guild_id: Guild ID snowflake.
75-
:param with_user_count: A boolean to include number of users subscribed to the associated event, if given.
69+
:param with_user_count: Whether the number of users subscribed to the associated event is returned.
7670
:return: A List of a dictionary containing the guild scheduled event objects on success.
7771
"""
78-
guild_id = int(guild_id)
79-
params = {}
80-
if with_user_count:
81-
params["with_user_count"] = with_user_count
82-
8372
return await self._req.request(
84-
Route("GET", "/guilds/{guild_id}/scheduled-events", guild_id=guild_id), params=params
73+
Route("GET", "/guilds/{guild_id}/scheduled-events", guild_id=guild_id),
74+
params={"with_user_count": str(with_user_count).lower()},
8575
)
8676

8777
async def modify_scheduled_event(
88-
self, guild_id: Snowflake, guild_scheduled_event_id: Snowflake, payload: dict
78+
self, guild_id: int, guild_scheduled_event_id: int, payload: dict
8979
) -> dict:
9080
"""
9181
Modifies a scheduled event.
@@ -95,7 +85,6 @@ async def modify_scheduled_event(
9585
:param payload: The dictionary containing the parameters and values to edit the associated event.
9686
:return: A dictionary containing the updated guild scheduled event object on success.
9787
"""
98-
guild_id, event_id = int(guild_id), int(guild_scheduled_event_id)
9988
valid_keys = (
10089
"channel_id",
10190
"name",
@@ -112,40 +101,37 @@ async def modify_scheduled_event(
112101
"PATCH",
113102
"/guilds/{guild_id}/scheduled-events/{event_id}",
114103
guild_id=guild_id,
115-
event_id=event_id,
104+
event_id=guild_scheduled_event_id,
116105
),
117106
json=data,
118107
)
119108

120-
async def delete_scheduled_event(
121-
self, guild_id: Snowflake, guild_scheduled_event_id: Snowflake
122-
) -> None:
109+
async def delete_scheduled_event(self, guild_id: int, guild_scheduled_event_id: int) -> None:
123110
"""
124111
Deletes a guild scheduled event.
125112
126113
:param guild_id: Guild ID snowflake.
127114
:param guild_scheduled_event_id: Guild Scheduled Event ID snowflake.
128115
:return: Nothing on success.
129116
"""
130-
guild_id, event_id = int(guild_id), int(guild_scheduled_event_id)
131117

132118
return await self._req.request(
133119
Route(
134120
"DELETE",
135121
"/guilds/{guild_id}/scheduled-events/{event_id}",
136122
guild_id=guild_id,
137-
event_id=event_id,
123+
event_id=guild_scheduled_event_id,
138124
)
139125
)
140126

141127
async def get_scheduled_event_users(
142128
self,
143-
guild_id: Snowflake,
144-
guild_scheduled_event_id: Snowflake,
129+
guild_id: int,
130+
guild_scheduled_event_id: int,
145131
limit: int = 100,
146132
with_member: bool = False,
147-
before: Snowflake = None,
148-
after: Snowflake = None,
133+
before: int = None,
134+
after: int = None,
149135
) -> dict:
150136
"""
151137
Get the registered users of a scheduled event.
@@ -158,22 +144,21 @@ async def get_scheduled_event_users(
158144
:param after: Considers only users after given user ID snowflake. Defaults to None.
159145
:return: Returns a list of guild scheduled event user objects on success.
160146
"""
161-
guild_id, event_id = int(guild_id), int(guild_scheduled_event_id)
162147
params = {
163148
"limit": limit,
164149
"with_member": with_member,
165150
}
166151
if before:
167-
params["before"] = int(before)
152+
params["before"] = before
168153
if after:
169-
params["after"] = int(after)
154+
params["after"] = after
170155

171156
return await self._req.request(
172157
Route(
173158
"GET",
174159
"/guilds/{guild_id}/scheduled-events/{event_id}/users",
175160
guild_id=guild_id,
176-
event_id=event_id,
161+
event_id=guild_scheduled_event_id,
177162
),
178163
params=params,
179164
)

interactions/api/http/thread.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
from typing import Dict, List, Optional
22

3+
from aiohttp import MultipartWriter
4+
35
from ...api.cache import Cache
6+
from ...utils.missing import MISSING
47
from ..models.channel import Channel
8+
from ..models.misc import File
59
from .request import _Request
610
from .route import Route
711

@@ -189,3 +193,62 @@ async def create_thread(
189193
self.cache[Channel].add(Channel(**request))
190194

191195
return request
196+
197+
async def create_thread_in_forum(
198+
self,
199+
channel_id: int,
200+
name: str,
201+
auto_archive_duration: int,
202+
message_payload: dict,
203+
applied_tags: List[str] = None,
204+
files: Optional[List[File]] = MISSING,
205+
rate_limit_per_user: Optional[int] = None,
206+
reason: Optional[str] = None,
207+
) -> dict:
208+
"""
209+
From a given Forum channel, create a Thread with a message to start with.
210+
211+
:param channel_id: The ID of the channel to create this thread in
212+
:param name: The name of the thread
213+
:param auto_archive_duration: duration in minutes to automatically archive the thread after recent activity,
214+
can be set to: 60, 1440, 4320, 10080
215+
:param message_payload: The payload/dictionary contents of the first message in the forum thread.
216+
:param applied_tags: List of tag ids that can be applied to the forum, if any.
217+
:param files: An optional list of files to send attached to the message.
218+
:param rate_limit_per_user: Seconds a user has to wait before sending another message (0 to 21600), if given.
219+
:param reason: An optional reason for the audit log
220+
:return: Returns a Thread in a Forum object with a starting Message.
221+
"""
222+
query = {"use_nested_fields": 1}
223+
224+
payload = {"name": name, "auto_archive_duration": auto_archive_duration}
225+
if rate_limit_per_user:
226+
payload["rate_limit_per_user"] = rate_limit_per_user
227+
if applied_tags:
228+
payload["applied_tags"] = applied_tags
229+
230+
data = None
231+
if files is not MISSING and len(files) > 0:
232+
233+
data = MultipartWriter("form-data")
234+
part = data.append_json(payload)
235+
part.set_content_disposition("form-data", name="payload_json")
236+
payload = None
237+
238+
for id, file in enumerate(files):
239+
part = data.append(
240+
file._fp,
241+
)
242+
part.set_content_disposition(
243+
"form-data", name=f"files[{str(id)}]", filename=file._filename
244+
)
245+
else:
246+
payload.update(message_payload)
247+
248+
return await self._req.request(
249+
Route("POST", f"/channels/{channel_id}/threads"),
250+
json=payload,
251+
data=data,
252+
params=query,
253+
reason=reason,
254+
)

0 commit comments

Comments
 (0)