Skip to content

Commit 6eb2461

Browse files
authored
Merge pull request #139 from eunwoo1104/anothercat/files-in-edit
Implement files in editing messages
2 parents 3c63f9f + 0db7dd5 commit 6eb2461

File tree

3 files changed

+67
-40
lines changed

3 files changed

+67
-40
lines changed

discord_slash/context.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ async def send(self,
140140
.. warning::
141141
- Since Release 1.0.9, this is completely changed. If you are migrating from older version, please make sure to fix the usage.
142142
- You can't use both ``embed`` and ``embeds`` at the same time, also applies to ``file`` and ``files``.
143-
- You cannot send files in the initial response
143+
- If you send files in the initial response, this will defer if it's not been deferred, and then PATCH with the message
144144
145145
:param content: Content of the response.
146146
:type content: str
@@ -193,15 +193,15 @@ async def send(self,
193193
initial_message = False
194194
if not self.responded:
195195
initial_message = True
196-
if files:
197-
raise error.IncorrectFormat("You cannot send files in the initial response!")
196+
if files and not self.deferred:
197+
await self.defer(hidden=hidden)
198198
if self.deferred:
199199
if self._deferred_hidden != hidden:
200200
self._logger.warning(
201201
"deferred response might not be what you set it to! (hidden / visible) "
202202
"This is because it was deferred in a different state"
203203
)
204-
resp = await self._http.edit(base, self.__token)
204+
resp = await self._http.edit(base, self.__token, files = files)
205205
self.deferred = False
206206
else:
207207
json_data = {
@@ -216,6 +216,9 @@ async def send(self,
216216
self.responded = True
217217
else:
218218
resp = await self._http.post_followup(base, self.__token, files=files)
219+
if files:
220+
for file in files:
221+
file.close()
219222
if not hidden:
220223
smsg = model.SlashMessage(state=self.bot._connection,
221224
data=resp,
@@ -228,4 +231,4 @@ async def send(self,
228231
self.message = smsg
229232
return smsg
230233
else:
231-
return resp
234+
return resp

discord_slash/http.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ def post_followup(self, _resp, token, files: typing.List[discord.File] = None):
9696
:return: Coroutine
9797
"""
9898
if files:
99-
return self.post_with_files(_resp, files, token)
99+
return self.request_with_files(_resp, files, token, "POST")
100100
return self.command_response(token, True, "POST", json=_resp)
101101

102102
def post_initial_response(self, _resp, interaction_id, token):
@@ -130,27 +130,31 @@ def command_response(self, token, use_webhook, method, interaction_id= None, url
130130
route = CustomRoute(method, req_url)
131131
return self._discord.http.request(route, **kwargs)
132132

133-
def post_with_files(self, _resp, files: typing.List[discord.File], token):
133+
def request_with_files(self, _resp, files: typing.List[discord.File], token, method, url_ending = ""):
134134

135135
form = aiohttp.FormData()
136136
form.add_field("payload_json", json.dumps(_resp))
137137
for x in range(len(files)):
138138
name = f"file{x if len(files) > 1 else ''}"
139139
sel = files[x]
140140
form.add_field(name, sel.fp, filename=sel.filename, content_type="application/octet-stream")
141-
return self.command_response(token, True, "POST", data=form, files=files)
141+
return self.command_response(token, True, method, data=form, files=files, url_ending=url_ending)
142142

143-
def edit(self, _resp, token, message_id="@original"):
143+
def edit(self, _resp, token, message_id="@original", files: typing.List[discord.File] = None):
144144
"""
145145
Sends edit command response PATCH request to Discord API.
146146
147147
:param _resp: Edited response.
148148
:type _resp: dict
149149
:param token: Command message token.
150150
:param message_id: Message ID to edit. Default initial message.
151+
:param files: Files. Default ``None``
152+
:type files: List[discord.File]
151153
:return: Coroutine
152154
"""
153155
req_url = f"/messages/{message_id}"
156+
if files:
157+
return self.request_with_files(_resp, files, token, "PATCH", url_ending = req_url)
154158
return self.command_response(token, True, "PATCH", url_ending = req_url, json=_resp)
155159

156160

discord_slash/model.py

Lines changed: 51 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -284,39 +284,59 @@ def __init__(self, *, state, channel, data, _http: http.SlashCommandRequest, int
284284
self._http = _http
285285
self.__interaction_token = interaction_token
286286

287+
async def _slash_edit(self, **fields):
288+
"""
289+
An internal function
290+
"""
291+
_resp = {}
292+
293+
content = fields.get("content")
294+
if content:
295+
_resp["content"] = str(content)
296+
297+
embed = fields.get("embed")
298+
embeds = fields.get("embeds")
299+
file = fields.get("file")
300+
files = fields.get("files")
301+
302+
if embed and embeds:
303+
raise error.IncorrectFormat("You can't use both `embed` and `embeds`!")
304+
if file and files:
305+
raise error.IncorrectFormat("You can't use both `file` and `files`!")
306+
if file:
307+
files = [file]
308+
if embed:
309+
embeds = [embed]
310+
if embeds:
311+
if not isinstance(embeds, list):
312+
raise error.IncorrectFormat("Provide a list of embeds.")
313+
elif len(embeds) > 10:
314+
raise error.IncorrectFormat("Do not provide more than 10 embeds.")
315+
_resp["embeds"] = [x.to_dict() for x in embeds]
316+
317+
allowed_mentions = fields.get("allowed_mentions")
318+
_resp["allowed_mentions"] = allowed_mentions.to_dict() if allowed_mentions else \
319+
self._state.allowed_mentions.to_dict() if self._state.allowed_mentions else {}
320+
321+
await self._http.edit(_resp, self.__interaction_token, self.id, files = files)
322+
323+
delete_after = fields.get("delete_after")
324+
if delete_after:
325+
await self.delete(delay=delete_after)
326+
if files:
327+
for file in files:
328+
file.close()
329+
330+
287331
async def edit(self, **fields):
288332
"""Refer :meth:`discord.Message.edit`."""
289-
try:
290-
await super().edit(**fields)
291-
except discord.Forbidden:
292-
_resp = {}
293-
294-
content = str(fields.get("content"))
295-
if content:
296-
_resp["content"] = str(content)
297-
298-
embed = fields.get("embed")
299-
embeds = fields.get("embeds")
300-
if embed and embeds:
301-
raise error.IncorrectFormat("You can't use both `embed` and `embeds`!")
302-
if embed:
303-
embeds = [embed]
304-
if embeds:
305-
if not isinstance(embeds, list):
306-
raise error.IncorrectFormat("Provide a list of embeds.")
307-
elif len(embeds) > 10:
308-
raise error.IncorrectFormat("Do not provide more than 10 embeds.")
309-
_resp["embeds"] = [x.to_dict() for x in embeds]
310-
311-
allowed_mentions = fields.get("allowed_mentions")
312-
_resp["allowed_mentions"] = allowed_mentions.to_dict() if allowed_mentions else \
313-
self._state.allowed_mentions.to_dict() if self._state.allowed_mentions else {}
314-
315-
await self._http.edit(_resp, self.__interaction_token, self.id)
316-
317-
delete_after = fields.get("delete_after")
318-
if delete_after:
319-
await self.delete(delay=delete_after)
333+
if "file" in fields or "files" in fields:
334+
await self._slash_edit(**fields)
335+
else:
336+
try:
337+
await super().edit(**fields)
338+
except discord.Forbidden:
339+
await self._slash_edit(**fields)
320340

321341
async def delete(self, *, delay=None):
322342
"""Refer :meth:`discord.Message.delete`."""

0 commit comments

Comments
 (0)