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

Issue:
Bot tries to assign user id to anonymous channel post
<!--
Thanks for reporting issues of python-telegram-bot!
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. Add a bot to a channel that doesn't have post signing.
2. Post something to that channel.
3. Bot tries to assign a user id to the update, bot gets an AttributeError because there is no user.

### Expected behaviour
The bot checks if the user is in the update before trying to get the id.
### Actual behaviour
An AttributeError is thrown and the bot fails to process the update.
### Configuration
**Operating System:**
macOS Sierra

**Version of Python, python-telegram-bot & dependencies:**
```
python-telegram-bot 6.1.0
urllib3 1.20
certifi 2017.04.17
future 0.16.0
Python 3.6.0 (default, Dec 24 2016, 08:01:42)  [GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)]
```

### Logs
```
Traceback (most recent call last):
  File "/Users/jelle/.venv/lib/python3.6/site-packages/telegram/ext/dispatcher.py", line 264, in process_update
    if handler.check_update(update):
  File "/Users/jelle/.venv/lib/python3.6/site-packages/telegram/ext/conversationhandler.py", line 181, in check_update
    key = self._get_key(update)
  File "/Users/jelle/.venv/lib/python3.6/site-packages/telegram/ext/conversationhandler.py", line 164, in _get_key
    key.append(user.id)
AttributeError: 'NoneType' object has no attribute 'id'
```
Bot tries to assign user id to anonymous channel post
<!--
Thanks for reporting issues of python-telegram-bot!
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. Add a bot to a channel that doesn't have post signing.
2. Post something to that channel.
3. Bot tries to assign a user id to the update, bot gets an AttributeError because there is no user.

### Expected behaviour
The bot checks if the user is in the update before trying to get the id.
### Actual behaviour
An AttributeError is thrown and the bot fails to process the update.
### Configuration
**Operating System:**
macOS Sierra

**Version of Python, python-telegram-bot & dependencies:**
```
python-telegram-bot 6.1.0
urllib3 1.20
certifi 2017.04.17
future 0.16.0
Python 3.6.0 (default, Dec 24 2016, 08:01:42)  [GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)]
```

### Logs
```
Traceback (most recent call last):
  File "/Users/jelle/.venv/lib/python3.6/site-packages/telegram/ext/dispatcher.py", line 264, in process_update
    if handler.check_update(update):
  File "/Users/jelle/.venv/lib/python3.6/site-packages/telegram/ext/conversationhandler.py", line 181, in check_update
    key = self._get_key(update)
  File "/Users/jelle/.venv/lib/python3.6/site-packages/telegram/ext/conversationhandler.py", line 164, in _get_key
    key.append(user.id)
AttributeError: 'NoneType' object has no attribute 'id'
```
Message.from is not mandatory due to channels
Currently it's a required attribute in the Message constructor. We should fix that.

CC: @tsnoam 


Discussion:
@pingiun This is related to #637. They should be fixed together.
@pingiun This is related to #637. They should be fixed together.
If `from_user` in the Message constructor is made optional by providing a default of `None`, won't this break people who use the `from_user` argument without keyword?
Can confirm that some tests fail if from_user becomes a positional argument, how can we make it optional but remain compatibility?

Resolving patch:
diff --git a/telegram/ext/conversationhandler.py b/telegram/ext/conversationhandler.py
--- a/telegram/ext/conversationhandler.py
+++ b/telegram/ext/conversationhandler.py
@@ -160,7 +160,7 @@ def _get_key(self, update):
         if self.per_chat:
             key.append(chat.id)
 
-        if self.per_user:
+        if self.per_user and user is not None:
             key.append(user.id)
 
         if self.per_message:


Test patch:
diff --git a/tests/test_conversationhandler.py b/tests/test_conversationhandler.py
--- a/tests/test_conversationhandler.py
+++ b/tests/test_conversationhandler.py
@@ -330,6 +330,12 @@ def test_perChatMessageWithoutChat(self):
         update = Update(0, callback_query=cbq)
         handler.check_update(update)
 
+    def test_channelMessageWithoutChat(self):
+        handler = ConversationHandler(entry_points=[CommandHandler('start', self.start_end)], states={}, fallbacks=[])
+        message = Message(0, None, None, Chat(0, Chat.CHANNEL, "Misses Test"))
+        update = Update(0, message=message)
+        handler.check_update(update)
+
 
 if __name__ == '__main__':
     unittest.main()