nickoala / telepot

Python framework for Telegram Bot API
MIT License
2.43k stars 474 forks source link

can't send file. #32

Closed jinsyu closed 8 years ago

jinsyu commented 8 years ago
  1. I tried to send some files that has korean language. it did not work. so changed file name with urllib.request.quote temporarily. it works. but it is hard to reconize what the file is. Is there any possible way to send file with korean file name, please let me know.
  2. I can't find custom keyboard settings. i want to change size of font, or key block.
nickoala commented 8 years ago

Confirm:

bot.sendPhoto(chat_id, ('기능추가.jpg', f))

to send the file and it failed?

(I don't actually know Korean, and only copy-and-paste some random Korean characters above. Forgive me if it offends anyone :smile: )

show_keyboard = {'keyboard': [['Yes','No'], ['Maybe','Maybe not']]}
bot.sendMessage(chat_id, 'This is a custom keyboard', reply_markup=show_keyboard)

But I don't think you can change the font size.

jinsyu commented 8 years ago

Thanks for reply!

bot.sendDocument(chat_id, open("가나다.doc", 'rb'))

I send Document and it failed. telepot.exception.TelegramError: ('[Error]: Bad Request: Wrong persistent file_id specified: contains wrong characters or have wrong length', 400)

If you have any suggestion, please let me know.

nickoala commented 8 years ago

Hi @jinsyu , just want to let you know that I will be busy over the next few days, and will get back to you as soon as I can.

jinsyu commented 8 years ago

Thanks for replying. Youre telepot is awesome. And easy to use. Im doing programming just for fun. Thanks for distributing thank kind of Api.

On Mar 10, 2016, 6:53 AM -0600, Nick Leenotifications@github.com, wrote:

Hi@jinsyu(https://github.com/jinsyu), just want to let you know that I will be busy over the next few days, and will get back to you as soon as I can.

— Reply to this email directly orview it on GitHub(https://github.com/nickoala/telepot/issues/32#issuecomment-194829837).

nickoala commented 8 years ago

Hey @jinsyu , please confirm which version of Python you were using?

jinsyu commented 8 years ago

I am using python3. 3.5 i think.

    1. 11., 오후 8:57, Nick Lee notifications@github.com 작성:

Hey @jinsyu https://github.com/jinsyu , please confirm which version of Python you were using?

— Reply to this email directly or view it on GitHub https://github.com/nickoala/telepot/issues/32#issuecomment-195645878.

nickoala commented 8 years ago

@jinsyu , just want to let you know that I still remember your issue. I am just occupied by some higher-priority stuff (both of telepot and of life), so haven't be able to get back to you. Give me some more time. I will get back to you as soon as I can.

jinsyu commented 8 years ago

got it. thanks for helping me.

fortunto2 commented 8 years ago

+1 have same error when sending video or documents telepot.exception.TelegramError: (u'[Error]: Bad Request: Wrong persistent file_id specified: contains wrong characters or has wrong length', 400, {u'error_code': 400, u'ok': False, u'description': u'[Error]: Bad Request: Wrong persistent file_id specified: contains wrong characters or has wrong length'})

nickoala commented 8 years ago

Sorry for leaving this issue here for so long. It will be my priority after adding support for Bot API 2.0

fortunto2 commented 8 years ago

thanks, cool) waiting 2.0

Kerrigan29a commented 8 years ago

I had the same error message using tempfile module when trying to send a photo. When I changed the code to store the image in a "normal" file everything worked fine

Problematic code:

with tempfile.NamedTemporaryFile() as f:
    qrcode.png(f)
    f.seek(0, 0)
    self._bot.sendPhoto(chat_id, f)

Changed to:

img_path = "/tmp/img.png"
with open(img_path, mode="w") as f:
    qrcode.png(f)
with open(img_path, mode="r") as f:
    self._bot.sendPhoto(chat_id, f)
nickoala commented 8 years ago

Sorry for the delay. This becomes my priority from this moment on. Expect a resolution before the end of this month.

Toofarto commented 8 years ago

I also noticed that the 80-th character of filename cannot be non-ASCII character (non-ASCII char count as 3 ASCII-character). For example:

bot = telepot.Bot('TOKEN')
output_file = open('sth.mp3', 'rb')
bot.sendDocument(1234567, ("_______________________________________________________________________________後", output_file))

and

bot = telepot.Bot('TOKEN')
output_file = open('sth.mp3', 'rb')
bot.sendDocument(1234567, ("後____________________________________________________________________________壞", output_file))

In both of the cases, the filename of receive side is "unnamed.file". I think the reason is that the size of filename field in telegram bot server is about 80, and it would trigger some problem when the 80-th char is non-ASCII. It is not the fault of telepot, but I will really appreciate if this problem can be solved.

nickoala commented 8 years ago

Telepot was just updated, now at version 7.1. Should be able to send non-ASCII filenames.

@Toofarto's super-long filename problem was not investigated. I suspect it was a Telegram issue, not mine.

Here is a full report ...

Symptoms (Python 2.7)

If you don't supply a unicode string as filename when the filename may be non-ascii, you get something like this (I suspect this is what was reported in issue #59, but @Toofarto did not give the full error, so I cannot be sure):

UnicodeDecodeError: 'ascii' codec can't decode byte 0xea in position 10: ordinal not in range(128)

For Python 2.7, if your filenames can be non-ascii, please always supply a unicode string as filename when sending files. Do not rely on the system guessing the filename for you.

If you do that, the symptoms would be the same as Python 3.4

Symptoms (Python 3.4)

As @jinsyu reported above, you get this error when sending a file with a non-ascii filename:

telepot.exception.TelegramError: ('[Error]: Bad Request: Wrong persistent file_id specified: contains wrong characters or have wrong length', 400)

Looking at the HTTP request, it has this line (note the filename* instead of filename):

Content-Disposition: form-data; name="document"; filename*=utf-8''%EA%B0%80%EB%82%98%EB%8B%A4.txt

This HTTP request was generated by the requests library.

Symptoms (Python 3.4, async version)

Sending a file with a non-ascii filename is successful using the async version, but the filename displayed on the recipient's app is not human-readable stuff, e.g. '%EA%B0%80%EB%82%98%EB%8B%A4.txt

The corresponding line in HTTP request is (note the presence of both filename* and filename):

CONTENT-DISPOSITION: form-data; name="document"; filename="%EA%B0%80%EB%82%98%EB%8B%A4.txt"; filename*=utf-8''%EA%B0%80%EB%82%98%EB%8B%A4.txt

This HTTP request was generated by the aiohttp library.

CURL is good!

I tried sending files by making HTTP requests using cURL. Everything looks good. Recipent received the file and saw the correct filename.

The corresponding line in HTTP request is:

Content-Disposition: form-data; name="document"; filename="가나다.txt"

Who is at fault?

According to some discussions on the web:

It seems requests and aiohttp are both following the standards, and Telegram servers are not interpreting it correctly. CURL works because it just dumps the bytes across, and Telegram servers recognize that.

I don't know enough to say which side is at fault here. I am inclined to trust requests and aiohttp in terms of standards. But telepot's concern is just to work with Telegram servers. I want to generate HTTP requests like the one CURL generates.

Solution

Thanks to @Toofarto pointing me in the right direction, I patched requests and aiohttp to make it work.

For requests, I injected some code around the function format_header_param() to deal with filename parameter specially. The code is in the new module telepot.hack, and doesn't affect any other Python applications using requests.

For aiohttp, I overrode BodyPartWriter to deal with filename parameter specially. The code is in the new module telepot.async.hack, and also doesn't affect any other Python applications using aiohttp.

I really don't like hacks like this. You never know when requests and aiohttp may change their structures. For now, it works. I am going to tell @BotSupport about this possible non-standard-compliancy, and hopefully they will become more compatible with request and aiohttp in the future.

As a last word to Python 2.7 users, if the filename can be non-ascii, always remember to supply an explicit unicode filename when sending files.

nickoala commented 8 years ago

@jinsyu, please close the issue if you are satisfied.

@Kerrigan29a, if you still want me to look into your issue, please open another issue. I have not looked into it yet. It might not be related the current one.

jinsyu commented 8 years ago

Thanks, it works perfect!

nickoala commented 8 years ago

What is the code that causes this error? Are you using the latest version of telepot?

psykonaute commented 8 years ago

My apologies! I think I hit the wrong tab ;-) I’m using nodeJS so it doesn’t belong here at all. You might even want to remove my comment!

On May 19, 2016, at 9:35 AM, Nick Lee notifications@github.com wrote:

What is the code that causes this error? Are you using the latest version of telepot?

— You are receiving this because you commented. Reply to this email directly or view it on GitHub https://github.com/nickoala/telepot/issues/32#issuecomment-220261580

nickoala commented 8 years ago

That's ok. Good luck.

keylook commented 8 years ago

Just a quick note for anyone who's still struggling. Had the same trouble with requests. Problem solved with replacing request of type: req = requests.get(url, data=data, files=files)with a simple long polling request:

final_url = req_url + '/sendSticker' + '?chat_id=' + str(c_id) + '&sticker=' + real_id
req = requests.get(final_url)

This may look a bit ugly, but solves the issue with Python sending extra bytes in file_id