We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Notify (Pushbullet) Plugin Error.
Hi, since last week i have this error in my log. Up to this point everything worked without problems.
```
2019-11-13 10:30 ERROR    notify_entry  NexBox    'x-ratelimit-reset'
Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/flexget/components/notify/notify.py", line 104, in send_notification
    send_notification(*args, **kwargs)
  File "/usr/local/lib/python3.5/dist-packages/flexget/components/notify/notification_framework.py", line 124, in send_notification
    title, message, rendered_config
  File "/usr/local/lib/python3.5/dist-packages/flexget/components/notify/notifiers/pushbullet.py", line 89, in notify
    self.send_push(key, title, message, config.get('url'), d, 'device_iden')
  File "/usr/local/lib/python3.5/dist-packages/flexget/components/notify/notifiers/pushbullet.py", line 130, in send_push
    int(response.headers['X-Ratelimit-Reset'])
  File "/usr/local/lib/python3.5/dist-packages/requests/structures.py", line 52, in __getitem__
    return self._store[key.lower()][1]
KeyError: 'x-ratelimit-reset'
```
Flexget: 2.21.32
API: 1.5.0

Same with Flexget 3.0.8 and Python 3.8
Notify (Pushbullet) Plugin Error.
Hi, since last week i have this error in my log. Up to this point everything worked without problems.
```
2019-11-13 10:30 ERROR    notify_entry  NexBox    'x-ratelimit-reset'
Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/flexget/components/notify/notify.py", line 104, in send_notification
    send_notification(*args, **kwargs)
  File "/usr/local/lib/python3.5/dist-packages/flexget/components/notify/notification_framework.py", line 124, in send_notification
    title, message, rendered_config
  File "/usr/local/lib/python3.5/dist-packages/flexget/components/notify/notifiers/pushbullet.py", line 89, in notify
    self.send_push(key, title, message, config.get('url'), d, 'device_iden')
  File "/usr/local/lib/python3.5/dist-packages/flexget/components/notify/notifiers/pushbullet.py", line 130, in send_push
    int(response.headers['X-Ratelimit-Reset'])
  File "/usr/local/lib/python3.5/dist-packages/requests/structures.py", line 52, in __getitem__
    return self._store[key.lower()][1]
KeyError: 'x-ratelimit-reset'
```
Flexget: 2.21.32
API: 1.5.0

Same with Flexget 3.0.8 and Python 3.8

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `flexget/components/notify/notifiers/pushbullet.py`
Content:
```
1 import base64
2 import datetime
3 import logging
4 
5 from requests.exceptions import RequestException
6 
7 from flexget import plugin
8 from flexget.config_schema import one_or_more
9 from flexget.event import event
10 from flexget.plugin import PluginWarning
11 from flexget.utils.requests import Session as RequestSession
12 from flexget.utils.requests import TimedLimiter
13 
14 plugin_name = 'pushbullet'
15 log = logging.getLogger(plugin_name)
16 
17 PUSHBULLET_URL = 'https://api.pushbullet.com/v2/pushes'
18 
19 requests = RequestSession(max_retries=3)
20 requests.add_domain_limiter(TimedLimiter('pushbullet.com', '5 seconds'))
21 
22 
23 class PushbulletNotifier:
24     """
25     Example::
26 
27     notify:
28       entries:
29         via:
30           pushbullet:
31             apikey: <API_KEY>
32             [device: <DEVICE_IDEN> (can also be a list of device ids, or don't specify any ids to send to all devices)]
33             [email: <EMAIL_ADDRESS> (can also be a list of user email addresses)]
34             [channel: <CHANNEL_TAG> (you can only specify device / email or channel tag, cannot use both)]
35 
36     Configuration parameters are also supported from entries (eg. through set).
37     """
38 
39     schema = {
40         'type': 'object',
41         'properties': {
42             'api_key': one_or_more({'type': 'string'}),
43             'device': one_or_more({'type': 'string'}),
44             'email': one_or_more({'type': 'string', 'format': 'email'}),
45             'url': {'type': 'string'},
46             'channel': {'type': 'string'},
47             'file_template': {'type': 'string'},
48         },
49         'required': ['api_key'],
50         'oneOf': [
51             {'required': ['device']},
52             {'required': ['channel']},
53             {'required': ['email']},
54             {
55                 'not': {
56                     'anyOf': [
57                         {'required': ['device']},
58                         {'required': ['channel']},
59                         {'required': ['email']},
60                     ]
61                 }
62             },
63         ],
64         'error_oneOf': 'One (and only one) of `email`, `device` or `channel` are allowed.',
65         'additionalProperties': False,
66     }
67 
68     def notify(self, title, message, config):
69         """
70         Send a Pushbullet notification
71         """
72         if config.get('device') and not isinstance(config['device'], list):
73             config['device'] = [config['device']]
74 
75         if config.get('email') and not isinstance(config['email'], list):
76             config['email'] = [config['email']]
77 
78         if not isinstance(config['api_key'], list):
79             config['api_key'] = [config['api_key']]
80 
81         for key in config['api_key']:
82             if config.get('channel'):
83                 self.send_push(
84                     key, title, message, config.get('url'), config.get('channel'), 'channel_tag'
85                 )
86             elif config.get('device'):
87                 for d in config['device']:
88                     self.send_push(key, title, message, config.get('url'), d, 'device_iden')
89             elif config.get('email'):
90                 for e in config['email']:
91                     self.send_push(key, title, message, config.get('url'), e, 'email')
92             else:
93                 self.send_push(key, title, message, config.get('url'))
94 
95     def send_push(self, api_key, title, body, url=None, destination=None, destination_type=None):
96         push_type = 'link' if url else 'note'
97         notification = {'type': push_type, 'title': title, 'body': body}
98         if url:
99             notification['url'] = url
100         if destination:
101             notification[destination_type] = destination
102 
103         # Make the request
104         headers = {
105             'Authorization': b'Basic ' + base64.b64encode(api_key.encode('ascii')),
106             'Content-Type': 'application/json',
107             'Accept': 'application/json',
108             'User-Agent': 'Flexget',
109         }
110         try:
111             response = requests.post(PUSHBULLET_URL, headers=headers, json=notification)
112         except RequestException as e:
113             if e.response is not None:
114                 if e.response.status_code == 429:
115                     reset_time = datetime.datetime.fromtimestamp(
116                         int(e.response.headers['X-Ratelimit-Reset'])
117                     ).strftime('%Y-%m-%d %H:%M:%S')
118                     message = (
119                         'Monthly Pushbullet database operations limit reached. Next reset: %s'
120                         % reset_time
121                     )
122                 else:
123                     message = e.response.json()['error']['message']
124             else:
125                 message = str(e)
126             raise PluginWarning(message)
127 
128         reset_time = datetime.datetime.fromtimestamp(
129             int(response.headers['X-Ratelimit-Reset'])
130         ).strftime('%Y-%m-%d %H:%M:%S')
131         remaining = response.headers['X-Ratelimit-Remaining']
132         log.debug(
133             'Pushbullet notification sent. Database operations remaining until next reset: %s. '
134             'Next reset at: %s',
135             remaining,
136             reset_time,
137         )
138 
139 
140 @event('plugin.register')
141 def register_plugin():
142     plugin.register(PushbulletNotifier, plugin_name, api_ver=2, interfaces=['notifiers'])
143
```
--- 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/flexget/components/notify/notifiers/pushbullet.py b/flexget/components/notify/notifiers/pushbullet.py
--- a/flexget/components/notify/notifiers/pushbullet.py
+++ b/flexget/components/notify/notifiers/pushbullet.py
@@ -112,13 +112,12 @@
         except RequestException as e:
             if e.response is not None:
                 if e.response.status_code == 429:
-                    reset_time = datetime.datetime.fromtimestamp(
-                        int(e.response.headers['X-Ratelimit-Reset'])
-                    ).strftime('%Y-%m-%d %H:%M:%S')
-                    message = (
-                        'Monthly Pushbullet database operations limit reached. Next reset: %s'
-                        % reset_time
-                    )
+                    reset_time = e.response.headers.get('X-Ratelimit-Reset')
+                    if reset_time:
+                        reset_time = datetime.datetime.fromtimestamp(int(reset_time)).strftime(
+                            '%Y-%m-%d %H:%M:%S'
+                        )
+                        message = f'Monthly Pushbullet database operations limit reached. Next reset: {reset_time}'
                 else:
                     message = e.response.json()['error']['message']
             else:

{"golden_diff": "diff --git a/flexget/components/notify/notifiers/pushbullet.py b/flexget/components/notify/notifiers/pushbullet.py\n--- a/flexget/components/notify/notifiers/pushbullet.py\n+++ b/flexget/components/notify/notifiers/pushbullet.py\n@@ -112,13 +112,12 @@\n         except RequestException as e:\n             if e.response is not None:\n                 if e.response.status_code == 429:\n-                    reset_time = datetime.datetime.fromtimestamp(\n-                        int(e.response.headers['X-Ratelimit-Reset'])\n-                    ).strftime('%Y-%m-%d %H:%M:%S')\n-                    message = (\n-                        'Monthly Pushbullet database operations limit reached. Next reset: %s'\n-                        % reset_time\n-                    )\n+                    reset_time = e.response.headers.get('X-Ratelimit-Reset')\n+                    if reset_time:\n+                        reset_time = datetime.datetime.fromtimestamp(int(reset_time)).strftime(\n+                            '%Y-%m-%d %H:%M:%S'\n+                        )\n+                        message = f'Monthly Pushbullet database operations limit reached. Next reset: {reset_time}'\n                 else:\n                     message = e.response.json()['error']['message']\n             else:\n", "issue": "Notify (Pushbullet) Plugin Error.\nHi, since last week i have this error in my log. Up to this point everything worked without problems.\r\n```\r\n2019-11-13 10:30 ERROR    notify_entry  NexBox    'x-ratelimit-reset'\r\nTraceback (most recent call last):\r\n  File \"/usr/local/lib/python3.5/dist-packages/flexget/components/notify/notify.py\", line 104, in send_notification\r\n    send_notification(*args, **kwargs)\r\n  File \"/usr/local/lib/python3.5/dist-packages/flexget/components/notify/notification_framework.py\", line 124, in send_notification\r\n    title, message, rendered_config\r\n  File \"/usr/local/lib/python3.5/dist-packages/flexget/components/notify/notifiers/pushbullet.py\", line 89, in notify\r\n    self.send_push(key, title, message, config.get('url'), d, 'device_iden')\r\n  File \"/usr/local/lib/python3.5/dist-packages/flexget/components/notify/notifiers/pushbullet.py\", line 130, in send_push\r\n    int(response.headers['X-Ratelimit-Reset'])\r\n  File \"/usr/local/lib/python3.5/dist-packages/requests/structures.py\", line 52, in __getitem__\r\n    return self._store[key.lower()][1]\r\nKeyError: 'x-ratelimit-reset'\r\n```\r\nFlexget: 2.21.32\r\nAPI: 1.5.0\r\n\r\nSame with Flexget 3.0.8 and Python 3.8\nNotify (Pushbullet) Plugin Error.\nHi, since last week i have this error in my log. Up to this point everything worked without problems.\r\n```\r\n2019-11-13 10:30 ERROR    notify_entry  NexBox    'x-ratelimit-reset'\r\nTraceback (most recent call last):\r\n  File \"/usr/local/lib/python3.5/dist-packages/flexget/components/notify/notify.py\", line 104, in send_notification\r\n    send_notification(*args, **kwargs)\r\n  File \"/usr/local/lib/python3.5/dist-packages/flexget/components/notify/notification_framework.py\", line 124, in send_notification\r\n    title, message, rendered_config\r\n  File \"/usr/local/lib/python3.5/dist-packages/flexget/components/notify/notifiers/pushbullet.py\", line 89, in notify\r\n    self.send_push(key, title, message, config.get('url'), d, 'device_iden')\r\n  File \"/usr/local/lib/python3.5/dist-packages/flexget/components/notify/notifiers/pushbullet.py\", line 130, in send_push\r\n    int(response.headers['X-Ratelimit-Reset'])\r\n  File \"/usr/local/lib/python3.5/dist-packages/requests/structures.py\", line 52, in __getitem__\r\n    return self._store[key.lower()][1]\r\nKeyError: 'x-ratelimit-reset'\r\n```\r\nFlexget: 2.21.32\r\nAPI: 1.5.0\r\n\r\nSame with Flexget 3.0.8 and Python 3.8\n", "before_files": [{"content": "import base64\nimport datetime\nimport logging\n\nfrom requests.exceptions import RequestException\n\nfrom flexget import plugin\nfrom flexget.config_schema import one_or_more\nfrom flexget.event import event\nfrom flexget.plugin import PluginWarning\nfrom flexget.utils.requests import Session as RequestSession\nfrom flexget.utils.requests import TimedLimiter\n\nplugin_name = 'pushbullet'\nlog = logging.getLogger(plugin_name)\n\nPUSHBULLET_URL = 'https://api.pushbullet.com/v2/pushes'\n\nrequests = RequestSession(max_retries=3)\nrequests.add_domain_limiter(TimedLimiter('pushbullet.com', '5 seconds'))\n\n\nclass PushbulletNotifier:\n    \"\"\"\n    Example::\n\n    notify:\n      entries:\n        via:\n          pushbullet:\n            apikey: <API_KEY>\n            [device: <DEVICE_IDEN> (can also be a list of device ids, or don't specify any ids to send to all devices)]\n            [email: <EMAIL_ADDRESS> (can also be a list of user email addresses)]\n            [channel: <CHANNEL_TAG> (you can only specify device / email or channel tag, cannot use both)]\n\n    Configuration parameters are also supported from entries (eg. through set).\n    \"\"\"\n\n    schema = {\n        'type': 'object',\n        'properties': {\n            'api_key': one_or_more({'type': 'string'}),\n            'device': one_or_more({'type': 'string'}),\n            'email': one_or_more({'type': 'string', 'format': 'email'}),\n            'url': {'type': 'string'},\n            'channel': {'type': 'string'},\n            'file_template': {'type': 'string'},\n        },\n        'required': ['api_key'],\n        'oneOf': [\n            {'required': ['device']},\n            {'required': ['channel']},\n            {'required': ['email']},\n            {\n                'not': {\n                    'anyOf': [\n                        {'required': ['device']},\n                        {'required': ['channel']},\n                        {'required': ['email']},\n                    ]\n                }\n            },\n        ],\n        'error_oneOf': 'One (and only one) of `email`, `device` or `channel` are allowed.',\n        'additionalProperties': False,\n    }\n\n    def notify(self, title, message, config):\n        \"\"\"\n        Send a Pushbullet notification\n        \"\"\"\n        if config.get('device') and not isinstance(config['device'], list):\n            config['device'] = [config['device']]\n\n        if config.get('email') and not isinstance(config['email'], list):\n            config['email'] = [config['email']]\n\n        if not isinstance(config['api_key'], list):\n            config['api_key'] = [config['api_key']]\n\n        for key in config['api_key']:\n            if config.get('channel'):\n                self.send_push(\n                    key, title, message, config.get('url'), config.get('channel'), 'channel_tag'\n                )\n            elif config.get('device'):\n                for d in config['device']:\n                    self.send_push(key, title, message, config.get('url'), d, 'device_iden')\n            elif config.get('email'):\n                for e in config['email']:\n                    self.send_push(key, title, message, config.get('url'), e, 'email')\n            else:\n                self.send_push(key, title, message, config.get('url'))\n\n    def send_push(self, api_key, title, body, url=None, destination=None, destination_type=None):\n        push_type = 'link' if url else 'note'\n        notification = {'type': push_type, 'title': title, 'body': body}\n        if url:\n            notification['url'] = url\n        if destination:\n            notification[destination_type] = destination\n\n        # Make the request\n        headers = {\n            'Authorization': b'Basic ' + base64.b64encode(api_key.encode('ascii')),\n            'Content-Type': 'application/json',\n            'Accept': 'application/json',\n            'User-Agent': 'Flexget',\n        }\n        try:\n            response = requests.post(PUSHBULLET_URL, headers=headers, json=notification)\n        except RequestException as e:\n            if e.response is not None:\n                if e.response.status_code == 429:\n                    reset_time = datetime.datetime.fromtimestamp(\n                        int(e.response.headers['X-Ratelimit-Reset'])\n                    ).strftime('%Y-%m-%d %H:%M:%S')\n                    message = (\n                        'Monthly Pushbullet database operations limit reached. Next reset: %s'\n                        % reset_time\n                    )\n                else:\n                    message = e.response.json()['error']['message']\n            else:\n                message = str(e)\n            raise PluginWarning(message)\n\n        reset_time = datetime.datetime.fromtimestamp(\n            int(response.headers['X-Ratelimit-Reset'])\n        ).strftime('%Y-%m-%d %H:%M:%S')\n        remaining = response.headers['X-Ratelimit-Remaining']\n        log.debug(\n            'Pushbullet notification sent. Database operations remaining until next reset: %s. '\n            'Next reset at: %s',\n            remaining,\n            reset_time,\n        )\n\n\n@event('plugin.register')\ndef register_plugin():\n    plugin.register(PushbulletNotifier, plugin_name, api_ver=2, interfaces=['notifiers'])\n", "path": "flexget/components/notify/notifiers/pushbullet.py"}], "after_files": [{"content": "import base64\nimport datetime\nimport logging\n\nfrom requests.exceptions import RequestException\n\nfrom flexget import plugin\nfrom flexget.config_schema import one_or_more\nfrom flexget.event import event\nfrom flexget.plugin import PluginWarning\nfrom flexget.utils.requests import Session as RequestSession\nfrom flexget.utils.requests import TimedLimiter\n\nplugin_name = 'pushbullet'\nlog = logging.getLogger(plugin_name)\n\nPUSHBULLET_URL = 'https://api.pushbullet.com/v2/pushes'\n\nrequests = RequestSession(max_retries=3)\nrequests.add_domain_limiter(TimedLimiter('pushbullet.com', '5 seconds'))\n\n\nclass PushbulletNotifier:\n    \"\"\"\n    Example::\n\n    notify:\n      entries:\n        via:\n          pushbullet:\n            apikey: <API_KEY>\n            [device: <DEVICE_IDEN> (can also be a list of device ids, or don't specify any ids to send to all devices)]\n            [email: <EMAIL_ADDRESS> (can also be a list of user email addresses)]\n            [channel: <CHANNEL_TAG> (you can only specify device / email or channel tag, cannot use both)]\n\n    Configuration parameters are also supported from entries (eg. through set).\n    \"\"\"\n\n    schema = {\n        'type': 'object',\n        'properties': {\n            'api_key': one_or_more({'type': 'string'}),\n            'device': one_or_more({'type': 'string'}),\n            'email': one_or_more({'type': 'string', 'format': 'email'}),\n            'url': {'type': 'string'},\n            'channel': {'type': 'string'},\n            'file_template': {'type': 'string'},\n        },\n        'required': ['api_key'],\n        'oneOf': [\n            {'required': ['device']},\n            {'required': ['channel']},\n            {'required': ['email']},\n            {\n                'not': {\n                    'anyOf': [\n                        {'required': ['device']},\n                        {'required': ['channel']},\n                        {'required': ['email']},\n                    ]\n                }\n            },\n        ],\n        'error_oneOf': 'One (and only one) of `email`, `device` or `channel` are allowed.',\n        'additionalProperties': False,\n    }\n\n    def notify(self, title, message, config):\n        \"\"\"\n        Send a Pushbullet notification\n        \"\"\"\n        if config.get('device') and not isinstance(config['device'], list):\n            config['device'] = [config['device']]\n\n        if config.get('email') and not isinstance(config['email'], list):\n            config['email'] = [config['email']]\n\n        if not isinstance(config['api_key'], list):\n            config['api_key'] = [config['api_key']]\n\n        for key in config['api_key']:\n            if config.get('channel'):\n                self.send_push(\n                    key, title, message, config.get('url'), config.get('channel'), 'channel_tag'\n                )\n            elif config.get('device'):\n                for d in config['device']:\n                    self.send_push(key, title, message, config.get('url'), d, 'device_iden')\n            elif config.get('email'):\n                for e in config['email']:\n                    self.send_push(key, title, message, config.get('url'), e, 'email')\n            else:\n                self.send_push(key, title, message, config.get('url'))\n\n    def send_push(self, api_key, title, body, url=None, destination=None, destination_type=None):\n        push_type = 'link' if url else 'note'\n        notification = {'type': push_type, 'title': title, 'body': body}\n        if url:\n            notification['url'] = url\n        if destination:\n            notification[destination_type] = destination\n\n        # Make the request\n        headers = {\n            'Authorization': b'Basic ' + base64.b64encode(api_key.encode('ascii')),\n            'Content-Type': 'application/json',\n            'Accept': 'application/json',\n            'User-Agent': 'Flexget',\n        }\n        try:\n            response = requests.post(PUSHBULLET_URL, headers=headers, json=notification)\n        except RequestException as e:\n            if e.response is not None:\n                if e.response.status_code == 429:\n                    reset_time = e.response.headers.get('X-Ratelimit-Reset')\n                    if reset_time:\n                        reset_time = datetime.datetime.fromtimestamp(int(reset_time)).strftime(\n                            '%Y-%m-%d %H:%M:%S'\n                        )\n                        message = f'Monthly Pushbullet database operations limit reached. Next reset: {reset_time}'\n                else:\n                    message = e.response.json()['error']['message']\n            else:\n                message = str(e)\n            raise PluginWarning(message)\n\n        reset_time = datetime.datetime.fromtimestamp(\n            int(response.headers['X-Ratelimit-Reset'])\n        ).strftime('%Y-%m-%d %H:%M:%S')\n        remaining = response.headers['X-Ratelimit-Remaining']\n        log.debug(\n            'Pushbullet notification sent. Database operations remaining until next reset: %s. '\n            'Next reset at: %s',\n            remaining,\n            reset_time,\n        )\n\n\n@event('plugin.register')\ndef register_plugin():\n    plugin.register(PushbulletNotifier, plugin_name, api_ver=2, interfaces=['notifiers'])\n", "path": "flexget/components/notify/notifiers/pushbullet.py"}]}