We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[BUG] Upate.to_dict includes Update._effective_message
### Steps to reproduce
1. Send a message to the bot.

2.
```python
import json
from telegram import Bot

update = Bot('TOKEN').get_updates()[-1]
update.effective_chat
update.effective_user
update.effective_message
print(json.dumps(update.to_dict(), indent=2))
```
### Expected behaviour
```
{
  "update_id": 601206924,
  "message": {
    "message_id": 3030,
    "date": 1591742976,
    "chat": {
      "id": 447493381,
      "type": "private",
      "first_name": "\u041d\u0438\u043a\u043e\u043b\u0430\u0439"
    },
    "text": "1",
    "entities": [],
    "caption_entities": [],
    "photo": [],
    "new_chat_members": [],
    "new_chat_photo": [],
    "delete_chat_photo": false,
    "group_chat_created": false,
    "supergroup_chat_created": false,
    "channel_chat_created": false,
    "from": {
      "id": 447493381,
      "first_name": "\u041d\u0438\u043a\u043e\u043b\u0430\u0439",
      "is_bot": false,
      "language_code": "en"
    }
  }
}
```

### Actual behaviour
```
{
  "update_id": 601206924,
  "message": {
    "message_id": 3030,
    "date": 1591742976,
    "chat": {
      "id": 447493381,
      "type": "private",
      "first_name": "\u041d\u0438\u043a\u043e\u043b\u0430\u0439"
    },
    "text": "1",
    "entities": [],
    "caption_entities": [],
    "photo": [],
    "new_chat_members": [],
    "new_chat_photo": [],
    "delete_chat_photo": false,
    "group_chat_created": false,
    "supergroup_chat_created": false,
    "channel_chat_created": false,
    "from": {
      "id": 447493381,
      "first_name": "\u041d\u0438\u043a\u043e\u043b\u0430\u0439",
      "is_bot": false,
      "language_code": "en"
    }
  },
  "_effective_user": {
    "id": 447493381,
    "first_name": "\u041d\u0438\u043a\u043e\u043b\u0430\u0439",
    "is_bot": false,
    "language_code": "en"
  },
  "_effective_chat": {
    "id": 447493381,
    "type": "private",
    "first_name": "\u041d\u0438\u043a\u043e\u043b\u0430\u0439"
  },
  "_effective_message": {
    "message_id": 3030,
    "date": 1591742976,
    "chat": {
      "id": 447493381,
      "type": "private",
      "first_name": "\u041d\u0438\u043a\u043e\u043b\u0430\u0439"
    },
    "text": "1",
    "entities": [],
    "caption_entities": [],
    "photo": [],
    "new_chat_members": [],
    "new_chat_photo": [],
    "delete_chat_photo": false,
    "group_chat_created": false,
    "supergroup_chat_created": false,
    "channel_chat_created": false,
    "from": {
      "id": 447493381,
      "first_name": "\u041d\u0438\u043a\u043e\u043b\u0430\u0439",
      "is_bot": false,
      "language_code": "en"
    }
  }
}
```

This also applies to effective_* attributes of other classes, e.g. `Message.effective_attachment`

### Configuration
**Operating System:** windows 10


**Version of Python, python-telegram-bot & dependencies:**
```
python-telegram-bot 12.7
certifi 2020.04.05.1
future 0.18.2
Python 3.8.3 (tags/v3.8.3:6f8c832, May 13 2020, 22:37:02) [MSC v.1924 64 bit (AMD64)]
```

### Proposed solution
Make `TelegramObject.to_dict` ignore all attributes starting with an underscore rather than a fixed list.
https://github.com/python-telegram-bot/python-telegram-bot/blob/a42b68933c3628b9b98c83927661eddb61d1571a/telegram/base.py#L56-L67

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `telegram/base.py`
Content:
```
1 #!/usr/bin/env python
2 #
3 # A library that provides a Python interface to the Telegram Bot API
4 # Copyright (C) 2015-2020
5 # Leandro Toledo de Souza <devs@python-telegram-bot.org>
6 #
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU Lesser Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU Lesser Public License for more details.
16 #
17 # You should have received a copy of the GNU Lesser Public License
18 # along with this program.  If not, see [http://www.gnu.org/licenses/].
19 """Base class for Telegram Objects."""
20 
21 try:
22     import ujson as json
23 except ImportError:
24     import json
25 
26 
27 class TelegramObject(object):
28     """Base class for most telegram objects."""
29 
30     _id_attrs = ()
31 
32     def __str__(self):
33         return str(self.to_dict())
34 
35     def __getitem__(self, item):
36         return self.__dict__[item]
37 
38     @classmethod
39     def de_json(cls, data, bot):
40         if not data:
41             return None
42 
43         data = data.copy()
44 
45         return data
46 
47     def to_json(self):
48         """
49         Returns:
50             :obj:`str`
51 
52         """
53 
54         return json.dumps(self.to_dict())
55 
56     def to_dict(self):
57         data = dict()
58 
59         for key in iter(self.__dict__):
60             if key in ('bot',
61                        '_id_attrs',
62                        '_credentials',
63                        '_decrypted_credentials',
64                        '_decrypted_data',
65                        '_decrypted_secret'):
66                 continue
67 
68             value = self.__dict__[key]
69             if value is not None:
70                 if hasattr(value, 'to_dict'):
71                     data[key] = value.to_dict()
72                 else:
73                     data[key] = value
74 
75         if data.get('from_user'):
76             data['from'] = data.pop('from_user', None)
77         return data
78 
79     def __eq__(self, other):
80         if isinstance(other, self.__class__):
81             return self._id_attrs == other._id_attrs
82         return super(TelegramObject, self).__eq__(other)  # pylint: disable=no-member
83 
84     def __hash__(self):
85         if self._id_attrs:
86             return hash((self.__class__, self._id_attrs))  # pylint: disable=no-member
87         return super(TelegramObject, self).__hash__()
88
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/telegram/base.py b/telegram/base.py
--- a/telegram/base.py
+++ b/telegram/base.py
@@ -57,12 +57,7 @@
         data = dict()
 
         for key in iter(self.__dict__):
-            if key in ('bot',
-                       '_id_attrs',
-                       '_credentials',
-                       '_decrypted_credentials',
-                       '_decrypted_data',
-                       '_decrypted_secret'):
+            if key == 'bot' or key.startswith('_'):
                 continue
 
             value = self.__dict__[key]

{"golden_diff": "diff --git a/telegram/base.py b/telegram/base.py\n--- a/telegram/base.py\n+++ b/telegram/base.py\n@@ -57,12 +57,7 @@\n         data = dict()\n \n         for key in iter(self.__dict__):\n-            if key in ('bot',\n-                       '_id_attrs',\n-                       '_credentials',\n-                       '_decrypted_credentials',\n-                       '_decrypted_data',\n-                       '_decrypted_secret'):\n+            if key == 'bot' or key.startswith('_'):\n                 continue\n \n             value = self.__dict__[key]\n", "issue": "[BUG] Upate.to_dict includes Update._effective_message\n### Steps to reproduce\r\n1. Send a message to the bot.\r\n\r\n2.\r\n```python\r\nimport json\r\nfrom telegram import Bot\r\n\r\nupdate = Bot('TOKEN').get_updates()[-1]\r\nupdate.effective_chat\r\nupdate.effective_user\r\nupdate.effective_message\r\nprint(json.dumps(update.to_dict(), indent=2))\r\n```\r\n### Expected behaviour\r\n```\r\n{\r\n  \"update_id\": 601206924,\r\n  \"message\": {\r\n    \"message_id\": 3030,\r\n    \"date\": 1591742976,\r\n    \"chat\": {\r\n      \"id\": 447493381,\r\n      \"type\": \"private\",\r\n      \"first_name\": \"\\u041d\\u0438\\u043a\\u043e\\u043b\\u0430\\u0439\"\r\n    },\r\n    \"text\": \"1\",\r\n    \"entities\": [],\r\n    \"caption_entities\": [],\r\n    \"photo\": [],\r\n    \"new_chat_members\": [],\r\n    \"new_chat_photo\": [],\r\n    \"delete_chat_photo\": false,\r\n    \"group_chat_created\": false,\r\n    \"supergroup_chat_created\": false,\r\n    \"channel_chat_created\": false,\r\n    \"from\": {\r\n      \"id\": 447493381,\r\n      \"first_name\": \"\\u041d\\u0438\\u043a\\u043e\\u043b\\u0430\\u0439\",\r\n      \"is_bot\": false,\r\n      \"language_code\": \"en\"\r\n    }\r\n  }\r\n}\r\n```\r\n\r\n### Actual behaviour\r\n```\r\n{\r\n  \"update_id\": 601206924,\r\n  \"message\": {\r\n    \"message_id\": 3030,\r\n    \"date\": 1591742976,\r\n    \"chat\": {\r\n      \"id\": 447493381,\r\n      \"type\": \"private\",\r\n      \"first_name\": \"\\u041d\\u0438\\u043a\\u043e\\u043b\\u0430\\u0439\"\r\n    },\r\n    \"text\": \"1\",\r\n    \"entities\": [],\r\n    \"caption_entities\": [],\r\n    \"photo\": [],\r\n    \"new_chat_members\": [],\r\n    \"new_chat_photo\": [],\r\n    \"delete_chat_photo\": false,\r\n    \"group_chat_created\": false,\r\n    \"supergroup_chat_created\": false,\r\n    \"channel_chat_created\": false,\r\n    \"from\": {\r\n      \"id\": 447493381,\r\n      \"first_name\": \"\\u041d\\u0438\\u043a\\u043e\\u043b\\u0430\\u0439\",\r\n      \"is_bot\": false,\r\n      \"language_code\": \"en\"\r\n    }\r\n  },\r\n  \"_effective_user\": {\r\n    \"id\": 447493381,\r\n    \"first_name\": \"\\u041d\\u0438\\u043a\\u043e\\u043b\\u0430\\u0439\",\r\n    \"is_bot\": false,\r\n    \"language_code\": \"en\"\r\n  },\r\n  \"_effective_chat\": {\r\n    \"id\": 447493381,\r\n    \"type\": \"private\",\r\n    \"first_name\": \"\\u041d\\u0438\\u043a\\u043e\\u043b\\u0430\\u0439\"\r\n  },\r\n  \"_effective_message\": {\r\n    \"message_id\": 3030,\r\n    \"date\": 1591742976,\r\n    \"chat\": {\r\n      \"id\": 447493381,\r\n      \"type\": \"private\",\r\n      \"first_name\": \"\\u041d\\u0438\\u043a\\u043e\\u043b\\u0430\\u0439\"\r\n    },\r\n    \"text\": \"1\",\r\n    \"entities\": [],\r\n    \"caption_entities\": [],\r\n    \"photo\": [],\r\n    \"new_chat_members\": [],\r\n    \"new_chat_photo\": [],\r\n    \"delete_chat_photo\": false,\r\n    \"group_chat_created\": false,\r\n    \"supergroup_chat_created\": false,\r\n    \"channel_chat_created\": false,\r\n    \"from\": {\r\n      \"id\": 447493381,\r\n      \"first_name\": \"\\u041d\\u0438\\u043a\\u043e\\u043b\\u0430\\u0439\",\r\n      \"is_bot\": false,\r\n      \"language_code\": \"en\"\r\n    }\r\n  }\r\n}\r\n```\r\n\r\nThis also applies to effective_* attributes of other classes, e.g. `Message.effective_attachment`\r\n\r\n### Configuration\r\n**Operating System:** windows 10\r\n\r\n\r\n**Version of Python, python-telegram-bot & dependencies:**\r\n```\r\npython-telegram-bot 12.7\r\ncertifi 2020.04.05.1\r\nfuture 0.18.2\r\nPython 3.8.3 (tags/v3.8.3:6f8c832, May 13 2020, 22:37:02) [MSC v.1924 64 bit (AMD64)]\r\n```\r\n\r\n### Proposed solution\r\nMake `TelegramObject.to_dict` ignore all attributes starting with an underscore rather than a fixed list.\r\nhttps://github.com/python-telegram-bot/python-telegram-bot/blob/a42b68933c3628b9b98c83927661eddb61d1571a/telegram/base.py#L56-L67\n", "before_files": [{"content": "#!/usr/bin/env python\n#\n# A library that provides a Python interface to the Telegram Bot API\n# Copyright (C) 2015-2020\n# Leandro Toledo de Souza <devs@python-telegram-bot.org>\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU Lesser Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU Lesser Public License for more details.\n#\n# You should have received a copy of the GNU Lesser Public License\n# along with this program.  If not, see [http://www.gnu.org/licenses/].\n\"\"\"Base class for Telegram Objects.\"\"\"\n\ntry:\n    import ujson as json\nexcept ImportError:\n    import json\n\n\nclass TelegramObject(object):\n    \"\"\"Base class for most telegram objects.\"\"\"\n\n    _id_attrs = ()\n\n    def __str__(self):\n        return str(self.to_dict())\n\n    def __getitem__(self, item):\n        return self.__dict__[item]\n\n    @classmethod\n    def de_json(cls, data, bot):\n        if not data:\n            return None\n\n        data = data.copy()\n\n        return data\n\n    def to_json(self):\n        \"\"\"\n        Returns:\n            :obj:`str`\n\n        \"\"\"\n\n        return json.dumps(self.to_dict())\n\n    def to_dict(self):\n        data = dict()\n\n        for key in iter(self.__dict__):\n            if key in ('bot',\n                       '_id_attrs',\n                       '_credentials',\n                       '_decrypted_credentials',\n                       '_decrypted_data',\n                       '_decrypted_secret'):\n                continue\n\n            value = self.__dict__[key]\n            if value is not None:\n                if hasattr(value, 'to_dict'):\n                    data[key] = value.to_dict()\n                else:\n                    data[key] = value\n\n        if data.get('from_user'):\n            data['from'] = data.pop('from_user', None)\n        return data\n\n    def __eq__(self, other):\n        if isinstance(other, self.__class__):\n            return self._id_attrs == other._id_attrs\n        return super(TelegramObject, self).__eq__(other)  # pylint: disable=no-member\n\n    def __hash__(self):\n        if self._id_attrs:\n            return hash((self.__class__, self._id_attrs))  # pylint: disable=no-member\n        return super(TelegramObject, self).__hash__()\n", "path": "telegram/base.py"}], "after_files": [{"content": "#!/usr/bin/env python\n#\n# A library that provides a Python interface to the Telegram Bot API\n# Copyright (C) 2015-2020\n# Leandro Toledo de Souza <devs@python-telegram-bot.org>\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU Lesser Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU Lesser Public License for more details.\n#\n# You should have received a copy of the GNU Lesser Public License\n# along with this program.  If not, see [http://www.gnu.org/licenses/].\n\"\"\"Base class for Telegram Objects.\"\"\"\n\ntry:\n    import ujson as json\nexcept ImportError:\n    import json\n\n\nclass TelegramObject(object):\n    \"\"\"Base class for most telegram objects.\"\"\"\n\n    _id_attrs = ()\n\n    def __str__(self):\n        return str(self.to_dict())\n\n    def __getitem__(self, item):\n        return self.__dict__[item]\n\n    @classmethod\n    def de_json(cls, data, bot):\n        if not data:\n            return None\n\n        data = data.copy()\n\n        return data\n\n    def to_json(self):\n        \"\"\"\n        Returns:\n            :obj:`str`\n\n        \"\"\"\n\n        return json.dumps(self.to_dict())\n\n    def to_dict(self):\n        data = dict()\n\n        for key in iter(self.__dict__):\n            if key == 'bot' or key.startswith('_'):\n                continue\n\n            value = self.__dict__[key]\n            if value is not None:\n                if hasattr(value, 'to_dict'):\n                    data[key] = value.to_dict()\n                else:\n                    data[key] = value\n\n        if data.get('from_user'):\n            data['from'] = data.pop('from_user', None)\n        return data\n\n    def __eq__(self, other):\n        if isinstance(other, self.__class__):\n            return self._id_attrs == other._id_attrs\n        return super(TelegramObject, self).__eq__(other)  # pylint: disable=no-member\n\n    def __hash__(self):\n        if self._id_attrs:\n            return hash((self.__class__, self._id_attrs))  # pylint: disable=no-member\n        return super(TelegramObject, self).__hash__()\n", "path": "telegram/base.py"}]}