From 2e03927f2c9ddd954db65a4fcd36d9b7fd8c19a2 Mon Sep 17 00:00:00 2001 From: Rapptz Date: Sat, 21 Nov 2015 01:31:51 -0500 Subject: [PATCH] Merge send_raw_file and send_file --- discord/client.py | 67 ++++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/discord/client.py b/discord/client.py index 9d1ae27c0..abff50f95 100644 --- a/discord/client.py +++ b/discord/client.py @@ -679,49 +679,33 @@ class Client(object): log.debug(request_logging_format.format(response=response)) _verify_successful_response(response) - def send_file(self, destination, filename): + def send_file(self, destination, fp, filename=None): """Sends a message to the destination given with the file given. The destination parameter follows the same rules as :meth:`send_message`. - Note that this requires proper permissions in order to work. - This function raises :exc:`HTTPException` if the request failed. - - :param destination: The location to send the message. - :param filename: The file to send. - :return: The :class:`Message` sent. - """ - - channel_id = self._resolve_destination(destination) + The ``fp`` parameter should be either a string denoting the location for a + file or a *file-like object*. The *file-like object* passed is **not closed** + at the end of execution. You are responsible for closing it yourself. - url = '{base}/{id}/messages'.format(base=endpoints.CHANNELS, id=channel_id) - response = None - - with open(filename, 'rb') as f: - files = { - 'file': (filename, f) - } - response = requests.post(url, files=files, headers=self.headers) - - log.debug(request_logging_format.format(response=response)) - _verify_successful_response(response) - data = response.json() - log.debug(request_success_log.format(response=response, json=response.text, data=filename)) - channel = self.get_channel(data.get('channel_id')) - message = Message(channel=channel, **data) - return message + .. note:: - def send_raw_file(self, destination, filename, file): - """Sends a message to the destination given with the file object given. + If the file-like object passed is opened via ``open`` then the modes + 'rb' should be used. - The destination parameter follows the same rules as :meth:`send_message`. + The ``filename`` parameter is the filename of the file. + If this is not given then it defaults to ``fp.name`` or if ``fp`` is a string + then the ``filename`` will default to the string given. You can overwrite + this value by passing this in. Note that this requires proper permissions in order to work. This function raises :exc:`HTTPException` if the request failed. + It also raises :exc:`InvalidArgument` if ``fp.name`` is an invalid + default for ``filename``. :param destination: The location to send the message. - :param filename: The name of the file to send. - :param file: The file object to send. + :param fp: The *file-like object* or file path to send. + :param filename: The filename of the file. Defaults to ``fp.name`` if it's available. :return: The :class:`Message` sent. """ @@ -730,10 +714,23 @@ class Client(object): url = '{base}/{id}/messages'.format(base=endpoints.CHANNELS, id=channel_id) response = None - files = { - 'file': (filename, file) - } - response = requests.post(url, files=files, headers=self.headers) + try: + # attempt to open the file and send the request + with open(fp, 'rb') as f: + files = { + 'file': (fp if filename is None else filename, f) + } + response = requests.post(url, files=files, headers=self.headers) + except TypeError: + # if we got a TypeError then this is probably a file-like object + fname = getattr(fp, 'name', None) if filename is None else filename + if fname is None: + raise InvalidArgument('file-like object has no name attribute and no filename was specified') + + files = { + 'file': (fname, fp) + } + response = requests.post(url, files=files, headers=self.headers) log.debug(request_logging_format.format(response=response)) _verify_successful_response(response)