aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTerrance <[email protected]>2018-10-29 07:58:21 +0000
committerRapptz <[email protected]>2018-11-24 22:38:50 -0500
commita105f8b8cc55eed787994245c4bcc689a59a4df3 (patch)
treea663e054c4fbab60167bcd5a670b4da472462169
parentActually drop copy.copy in Member (diff)
downloaddiscord.py-a105f8b8cc55eed787994245c4bcc689a59a4df3.tar.xz
discord.py-a105f8b8cc55eed787994245c4bcc689a59a4df3.zip
Webhooks: add support for multi-file upload
`Webhook.send()` now accepts a `files` kwarg holding a list of `File` objects, which are included in the HTTP request as `file1`, `file2` and so on. This is an undocumented feature of the Discord API, but is analogous with the client's sending of messages with multiple files.
-rw-r--r--discord/webhook.py36
1 files changed, 28 insertions, 8 deletions
diff --git a/discord/webhook.py b/discord/webhook.py
index 4c631af6..0dfe6ba6 100644
--- a/discord/webhook.py
+++ b/discord/webhook.py
@@ -104,13 +104,20 @@ class WebhookAdapter:
# mocks a ConnectionState for appropriate use for Message
return BaseUser(state=self, data=data)
- def execute_webhook(self, *, payload, wait=False, file=None):
+ def execute_webhook(self, *, payload, wait=False, file=None, files=None):
if file is not None:
multipart = {
'file': file,
'payload_json': utils.to_json(payload)
}
data = None
+ elif files is not None:
+ multipart = {
+ 'payload_json': utils.to_json(payload)
+ }
+ for i, file in enumerate(files, start=1):
+ multipart['file%i' % i] = file
+ data = None
else:
data = payload
multipart = None
@@ -144,12 +151,12 @@ class AsyncWebhookAdapter(WebhookAdapter):
data = utils.to_json(payload)
if multipart:
- file = multipart.pop('file', None)
data = aiohttp.FormData()
- if file:
- data.add_field('file', file[1], filename=file[0], content_type=file[2])
for key, value in multipart.items():
- data.add_field(key, value)
+ if key.startswith('file'):
+ data.add_field(key, value[1], filename=value[0], content_type=value[2])
+ else:
+ data.add_field(key, value)
for tries in range(5):
async with self.session.request(verb, url, headers=headers, data=data) as r:
@@ -561,8 +568,8 @@ class Webhook:
return self._adapter.edit_webhook(**payload)
- def send(self, content=None, *, wait=False, username=None, avatar_url=None,
- tts=False, file=None, embed=None, embeds=None):
+ def send(self, content=None, *, wait=False, username=None, avatar_url=None, tts=False,
+ file=None, files=None, embed=None, embeds=None):
"""|maybecoro|
Sends a message using the webhook.
@@ -596,7 +603,10 @@ class Webhook:
tts: bool
Indicates if the message should be sent using text-to-speech.
file: :class:`File`
- The file to upload.
+ The file to upload. This cannot be mixed with ``files`` parameter.
+ files: List[:class:`File`]
+ A list of files to send with the content. This cannot be mixed with the
+ ``file`` parameter.
embed: :class:`Embed`
The rich embed for the content to send. This cannot be mixed with
``embeds`` parameter.
@@ -624,6 +634,8 @@ class Webhook:
payload = {}
+ if files is not None and file is not None:
+ raise InvalidArgument('Cannot mix file and files keyword arguments.')
if embeds is not None and embed is not None:
raise InvalidArgument('Cannot mix embed and embeds keyword arguments.')
@@ -650,6 +662,14 @@ class Webhook:
return self._adapter.execute_webhook(wait=wait, file=to_pass, payload=payload)
finally:
file.close()
+ elif files is not None:
+ try:
+ to_pass = [(file.filename, file.open_file(), 'application/octet-stream')
+ for file in files]
+ return self._adapter.execute_webhook(wait=wait, files=to_pass, payload=payload)
+ finally:
+ for file in files:
+ file.close()
else:
return self._adapter.execute_webhook(wait=wait, payload=payload)