eternnoir / pyTelegramBotAPI

Python Telegram bot api.
GNU General Public License v2.0
8.12k stars 2.03k forks source link

Bad Request: field \\"parse_mode\\" must be of type String" #571

Closed MasterGroosha closed 6 years ago

MasterGroosha commented 6 years ago

Please answer these questions before submitting your issue. Thanks!

  1. What version of pyTelegramBotAPI are you using? 3.6.5
  2. What OS are you using? Ubuntu 16.10
  3. What version of python are you using? 3.5

Latest pyTelegramBotAPI is bugged. Whenevery you run answer_inline_query you crash with {"ok":false,"error_code":400,"description":"Bad Request: field \\"parse_mode\\" must be of type String"} error

Badiboy commented 6 years ago

Any example of your "answer code"?

MasterGroosha commented 6 years ago

@Badiboy

@bot.inline_handler(func=lambda query: True)
def inline(query):
    android = telebot.types.InlineQueryResultCachedDocument(
        id="android",
        title="Telegram Android Localizaton",
        description="android",
        document_file_id="BQADAgADlAEAAgZsSUhcA2wI",
        caption="android",
    )

    desktop = telebot.types.InlineQueryResultCachedDocument(
        id="desktop",
        title="Telegram Desktop Localizaton",
        description="Desktop",
        document_file_id="BQADAgADlAEAAgZsSUh",
        caption="desktop"
    )
    android_x = telebot.types.InlineQueryResultCachedDocument(
        id="android_x",
        title="Telegram X Localizaton",
        description="x",
        document_file_id="BQADAgADlAEAAgZsSUhcA",
        caption="X"
    )
    bot.answer_inline_query(query.id, [android, desktop, android_x], cache_time=300)
Badiboy commented 6 years ago

I had a look, but I see the only problem: InlineQueryResultCachedDocument() constructor does not have the parse_mode parameter to request at all (while Bot API has such parameter). This is the problem for one who want to use it, but it's not your case.

As far as I see, for this case nothing is passed to the request to server regarding the parse_mode. Can you set the logger level to "DEBUG" and see the exact request details? If there is anything regarding the parse_mode?

MasterGroosha commented 6 years ago

Well, according to this, parse_mode is not set to anything, right? Neither in CachedDocument nor in BaseCached.

MasterGroosha commented 6 years ago

@Badiboy Hmm... I got into answer_inline_query method in apihelper.py and did print(payload). Besides other arguments it shows me "parse_mode":null string which is very strange.

Badiboy commented 6 years ago

Mmm, sorry. I looked at outdated sources. Here everything is passed.

class InlineQueryResultCachedDocument(BaseInlineQueryResultCached):
    def __init__(self, id, document_file_id, title, description=None, caption=None, parse_mode=None, reply_markup=None, input_message_content=None):
...
        self.payload_dic['parse_mode'] = parse_mode

I should investigate what happens once again...

MasterGroosha commented 6 years ago

Most likely this commit broke inline mode

Badiboy commented 6 years ago

In the latest code I see it's fixed from self.parse_mode = parse_mode to self.payload_dic['parse_mode'] = parse_mode I think we need new release...

Badiboy commented 6 years ago

3.6.6 released. @MasterGroosha , can you check if the problem is solved?

MasterGroosha commented 6 years ago

@Badiboy as far as I see, no, the problem is not solved. I get the same error even with 3.6.6 (tested with PyCharm on Windows and Python 3.6.5)

rmed commented 6 years ago

Encountered the same issue today while working with InlineQueryResultCachedPhoto. Seems like the Telegram API does not like the null value, so as a workaround I'd suggest adding parse_mode='' as an argument, which should be ignored by the API.

After checking the commit @MasterGroosha mentioned I think the problem lies in how the cached version of the inline query results are managed. The non-cached classes (such as InlineQueryResultPhoto) do not send the parse_mode when the argument is empty (See example).

This is not the case for BaseInlineQueryResultCached, which sends the JSON "as is" without checking those special arguments (See here)