Skip to content
This repository has been archived by the owner on Jun 2, 2019. It is now read-only.

KeyError exception in __init__.py line 792 #184

Closed
carloalbertobarbano opened this issue Nov 21, 2016 · 15 comments
Closed

KeyError exception in __init__.py line 792 #184

carloalbertobarbano opened this issue Nov 21, 2016 · 15 comments

Comments

@carloalbertobarbano
Copy link

carloalbertobarbano commented Nov 21, 2016

Telepot throws an exception while retrieveing messages from telegram servers. Here's the traceback:

(traceback from OSX)

Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/telepot/__init__.py", line 792, in get_from_telegram_server offset = max([relay_to_collector(update) for update in result]) + 1 File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/telepot/__init__.py", line 792, in <listcomp> offset = max([relay_to_collector(update) for update in result]) + 1 File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/telepot/__init__.py", line 779, in relay_to_collector 'chosen_inline_result']) File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/telepot/__init__.py", line 61, in _find_first_key raise KeyError(keys) KeyError: ['message', 'edited_message', 'callback_query', 'inline_query', 'chosen_inline_result']

Here's the code:

bot_token = "xxxxxxxxxxxxx"

#mock handle function
def handle(msg):
    chat_id = msg['chat']['id']
    type = msg['chat']['type']
    message_id = msg['message_id']
 
    bot.sendMessage(chat_id, "Test")

bot = telepot.Bot(bot_token)
bot.message_loop(handle) #Exception thrown here

while 1:
	time.sleep(10)

My bot no longer receives messages

@Shayan123456
Copy link

Yeah When I send message to bot from Channel I receive this error Too:
line 61, in _find_first_key raise KeyError(keys) KeyError: ['message', 'edited_message', 'callback_query', 'inline_query', 'chosen_inline_result']

@carloalbertobarbano
Copy link
Author

carloalbertobarbano commented Nov 21, 2016

@Shayan123456 @nickoala The issue is related to Telegram Channels.
They're not supported by telepot so the bot crashes, but the messages remains in the telegram's queue (that's why my bot crashes on startup).
We need support for channels in telepot.

Here's a sample message that will make it crash (from https://api.telegram.org/botXXXXXXXXXXX/getUpdates):

{"update_id":441783091,` "channel_post":{"message_id":1291,"chat":{"id":<channel_id>,"title":"<channel_title>","username":"<username>","type":"channel"},"date":1479733054,"text":"<some long unicode message>"}}

My bot was added as a channel admin.

So the exception is thrown as the message type is "channel_post" (or also "edit_channel_post") which is not included in https://github.com/nickoala/telepot/blob/master/telepot/__init__.py at line 776

Here's quick and dirty fix: replace relay_to_collector function in init.py at line 774 with this one:

def relay_to_collector(update):
            key = _find_first_key(update, ['message',
                                           'channel_post',
                                           'edited_channel_post',
                                           'edited_message',
                                           'callback_query',
                                           'inline_query',
                                           'chosen_inline_result'])
            collect_queue.put(update[key])
            return update['update_id']

This will at least prevent the bot from crashing on startup.
Thanks to https://github.com/ruste96 for this fix

@nickoala
Copy link
Owner

This seems to be related to the changes in Bot API 2.3. Expect an update on or before Nov 30.

@R0bertoG
Copy link

R0bertoG commented Nov 21, 2016

Can I suggest a better error message?
Something like:

def _find_first_key(d, keys):
    for k in keys:
        if k in d:
            return k
    raise KeyError("Server returns a key that it's not in " + str(keys))

Maybe even return what is the name of the not expected key. I was coding when the error started to happen and I spent sometime until I undernstood what the problems was.

@efazati
Copy link

efazati commented Nov 21, 2016

I have same error
how can fix this?



Traceback (most recent call last):
  File "/home/argus/10days/pahlevon/env/lib/python2.7/site-packages/telepot/__init__.py", line 761, in get_from_telegram_server
    offset = max([relay_to_collector(update) for update in result]) + 1
  File "/home/argus/10days/pahlevon/env/lib/python2.7/site-packages/telepot/__init__.py", line 748, in relay_to_collector
    'chosen_inline_result'])
  File "/home/argus/10days/pahlevon/env/lib/python2.7/site-packages/telepot/__init__.py", line 61, in _find_first_key
    raise KeyError(keys)
KeyError: ['message', 'edited_message', 'callback_query', 'inline_query', 'chosen_inline_result']

@carloalbertobarbano
Copy link
Author

carloalbertobarbano commented Nov 21, 2016

Okay so here's the solution to fix telepot with the new API (2.3):

Replace function relay_to_collector in file init.py at line 774 with:

def relay_to_collector(update):
            key = _find_first_key(update, ['message',
                                           'channel_post',
                                           'edited_channel_post',
                                           'edited_message',
                                           'callback_query',
                                           'inline_query',
                                           'chosen_inline_result'])
            collect_queue.put(update[key])
            return update['update_id']

Now in your bot's code to find out the chat type you can do:

def handle(msg):
    type = msg['chat']['type']

    if type == "private":
          #message from msg['chat']['first_name']
    else:
          #message from msg['chat']['title']

I'd wait until the next release of telepot to mark this issue as closed.

@efazati
Copy link

efazati commented Nov 21, 2016

@carloalbertobarbano I use something like this

class AppManager(telepot.helper.ChatHandler):
    def __init__(self, *args, **kwargs):
        super(AppManager, self).__init__(*args, **kwargs)


    def on_chat_message(self, msg):
        content_type, chat_type, chat_id = telepot.glance(msg)

        user, is_first_time = get_or_create_user(self.sender, msg, True)


@carloalbertobarbano
Copy link
Author

carloalbertobarbano commented Nov 21, 2016

@efazati you have to edit the telepot library yourself for now. Just replace the function in this file https://github.com/nickoala/telepot/blob/master/telepot/__init__.py as described above.

You can find the correct path for that file on your machine in the traceback of the exception

@efazati
Copy link

efazati commented Nov 21, 2016

@carloalbertobarbano I did change that code, but what about handle in my code? i use with this method and i dont have method like your handle

i mean this


def handle(msg):
    type = msg['chat']['type']

    if type == "private":
          #message from msg['chat']['first_name']
    else:
          #message from msg['chat']['title'

@carloalbertobarbano
Copy link
Author

carloalbertobarbano commented Nov 21, 2016

@efazati That was just a sample. You can use telepot in the way you are used to without further changes.
For any doubts about implementation refer to the Telepot Api Reference http://telepot.readthedocs.io/en/latest/reference.html or contact the author @nickoala

Let's keep this thread for this library bug only and free from other implementation-specific issues.

@gonardfreeman
Copy link

For all who dont want to wait update u can fix this problem by theyself, just add at 780 string at init.py (in relay_to_collector(update) this function) to list one value 'channel_post'

@gonardfreeman
Copy link

Oh, im sort of slowpoke)) sorry)

@96Octavian
Copy link

Following this issue, how could I know which channel my bot has been added to? Is there a way?

@nickoala
Copy link
Owner

@96Octavian, when a bot is added to a group, it receives a new_chat_member. But when added to a channel ...... I am not sure what notification you will get, if you get any notification at all. 🤔

On the other hand, I have updated telepot (10.2) to encompass Bot API 2.3. Just do:

pip install telepot --upgrade

This issue should be no more. Thanks everyone for using telepot 😊

@snowcat404
Copy link

Telepot throws an exception while retrieveing messages from telegram servers. Here's the traceback:

(traceback from OSX)

Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/telepot/__init__.py", line 792, in get_from_telegram_server offset = max([relay_to_collector(update) for update in result]) + 1 File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/telepot/__init__.py", line 792, in <listcomp> offset = max([relay_to_collector(update) for update in result]) + 1 File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/telepot/__init__.py", line 779, in relay_to_collector 'chosen_inline_result']) File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/telepot/__init__.py", line 61, in _find_first_key raise KeyError(keys) KeyError: ['message', 'edited_message', 'callback_query', 'inline_query', 'chosen_inline_result']

Here's the code:

bot_token = "xxxxxxxxxxxxx"

#mock handle function
def handle(msg):
    chat_id = msg['chat']['id']
    type = msg['chat']['type']
    message_id = msg['message_id']
 
    bot.sendMessage(chat_id, "Test")

bot = telepot.Bot(bot_token)
bot.message_loop(handle) #Exception thrown here

while 1:
	time.sleep(10)

My bot no longer receives messages

Same error in the latest bot API update when working with polls.
`

@Shayan123456 @nickoala The issue is related to Telegram Channels.
They're not supported by telepot so the bot crashes, but the messages remains in the telegram's queue (that's why my bot crashes on startup).
We need support for channels in telepot.

Here's a sample message that will make it crash (from https://api.telegram.org/botXXXXXXXXXXX/getUpdates):

{"update_id":441783091,` "channel_post":{"message_id":1291,"chat":{"id":<channel_id>,"title":"<channel_title>","username":"<username>","type":"channel"},"date":1479733054,"text":"<some long unicode message>"}}

My bot was added as a channel admin.

So the exception is thrown as the message type is "channel_post" (or also "edit_channel_post") which is not included in https://github.com/nickoala/telepot/blob/master/telepot/__init__.py at line 776

Here's quick and dirty fix: replace relay_to_collector function in init.py at line 774 with this one:

def relay_to_collector(update):
            key = _find_first_key(update, ['message',
                                           'channel_post',
                                           'edited_channel_post',
                                           'edited_message',
                                           'callback_query',
                                           'inline_query',
                                           'chosen_inline_result'])
            collect_queue.put(update[key])
            return update['update_id']

This will at least prevent the bot from crashing on startup.
Thanks to https://github.com/ruste96 for this fix

got a monkey patch like this for the Bot API 4.2 poll update?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants