Repository: python-telegram-bot/python-telegram-bot

Issue:
[BUG] Cannot Download a File if it doesnt have a `file_path` or if `custom_path` is not provided to `download()`
<!--
Thanks for reporting issues of python-telegram-bot!

Use this template to notify us if you found a bug.

To make it easier for us to help you please enter detailed information below.

Please note, we only support the latest version of python-telegram-bot and
master branch. Please make sure to upgrade & recreate the issue on the latest
version prior to opening an issue.
-->
### Steps to reproduce
1. Create an operation with the above mentioned aspects

Ex:
```
def run_bot(token):
    def make_pasta(update, context):
        msg = update.message

        if msg.reply_to_message is None:
            msg.reply_text(responses.NOT_A_REPLY)
            return
        if msg.reply_to_message.document is None:
            msg.reply_text(responses.NOT_A_DOC)
            return
        telegram_file = File(msg.reply_to_message.document.file_id)
        telegram_file.download() 

    updater = Updater(token, use_context=True)
    dp = updater.dispatcher

    dp.add_handler(CommandHandler('hello', hello))
    dp.add_handler(CommandHandler('make_pasta', make_pasta))

    print('Log: Seu bot iniciou! (:')
    updater.start_polling()
    updater.idle() 
```
(I know this is not exactly a MWE, sorry)

### Expected behaviour
According to the documentation, it should download the file directly to my current working directory `Download this file. By default, the file is saved in the current working directory with its original filename as reported by Telegram.`

### Actual behaviour
on `telegram/files/file.py`, on the download function, we get a type error since `self.file_path` is NoneType, not str or os.PathLike object

### Configuration
Ubuntu 18.04

python-telegram-bot 12.2.0
certifi 2019.09.11
future 0.18.1
Python 3.7.3 (default, Apr  3 2019, 19:16:38)  [GCC 8.0.1 20180414 (experimental) [trunk revision 259383]]


Discussion:
@GabrielSimonetto Please complete all info as requested in issue template.

Resolving patch:
diff --git a/telegram/files/file.py b/telegram/files/file.py
--- a/telegram/files/file.py
+++ b/telegram/files/file.py
@@ -19,6 +19,7 @@
 """This module contains an object that represents a Telegram File."""
 from base64 import b64decode
 from os.path import basename
+import os
 
 from future.backports.urllib import parse as urllib_parse
 
@@ -76,9 +77,10 @@ def de_json(cls, data, bot):
     def download(self, custom_path=None, out=None, timeout=None):
         """
         Download this file. By default, the file is saved in the current working directory with its
-        original filename as reported by Telegram. If a :attr:`custom_path` is supplied, it will be
-        saved to that path instead. If :attr:`out` is defined, the file contents will be saved to
-        that object using the ``out.write`` method.
+        original filename as reported by Telegram. If the file has no filename, it the file ID will
+        be used as filename. If a :attr:`custom_path` is supplied, it will be saved to that path
+        instead. If :attr:`out` is defined, the file contents will be saved to that object using
+        the ``out.write`` method.
 
         Note:
             :attr:`custom_path` and :attr:`out` are mutually exclusive.
@@ -116,8 +118,10 @@ def download(self, custom_path=None, out=None, timeout=None):
         else:
             if custom_path:
                 filename = custom_path
-            else:
+            elif self.file_path:
                 filename = basename(self.file_path)
+            else:
+                filename = os.path.join(os.getcwd(), self.file_id)
 
             buf = self.bot.request.retrieve(url, timeout=timeout)
             if self._credentials:


Test patch:
diff --git a/tests/test_file.py b/tests/test_file.py
--- a/tests/test_file.py
+++ b/tests/test_file.py
@@ -96,6 +96,22 @@ def test(*args, **kwargs):
             os.close(file_handle)
             os.unlink(custom_path)
 
+    def test_download_no_filename(self, monkeypatch, file):
+        def test(*args, **kwargs):
+            return self.file_content
+
+        file.file_path = None
+
+        monkeypatch.setattr('telegram.utils.request.Request.retrieve', test)
+        out_file = file.download()
+
+        assert out_file[-len(file.file_id):] == file.file_id
+        try:
+            with open(out_file, 'rb') as fobj:
+                assert fobj.read() == self.file_content
+        finally:
+            os.unlink(out_file)
+
     def test_download_file_obj(self, monkeypatch, file):
         def test(*args, **kwargs):
             return self.file_content