We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Incompatibility with Libtorrent version 1.1.3 and above
### Actual behaviour:
flexget crashes when converting magnet URI to a torrent file with libtorrent versions 1.1.3 and higher

### Steps to reproduce:
upgrade libtorrent to 1.1.3 or higher (I'm using 1.1.4 but the change occurred in 1.1.3)
download torrent with convert_magnet plugin 

#### Config:
```
tasks:
  stage:
    convert_magnet: yes
    rss: http://xxx.xxx/rss
    accept_all: yes
    download:
      path: /home/flexget/test/
```
  
#### Log:
```
2017-10-09 15:36 VERBOSE  task_queue                    There are 1 tasks to execute. Shutdown will commence when they have completed.
2017-10-09 15:36 VERBOSE  details       stage           Produced 74 entries.
2017-10-09 15:36 INFO     series        stage           identified_by has locked in to type `ep` for Lucifer
2017-10-09 15:36 VERBOSE  task          stage           ACCEPTED: `Lucifer S03E02 1080p HDTV X264 DIMENSION` by series plugin because choosing best available quality
2017-10-09 15:36 VERBOSE  task          stage           ACCEPTED: `Lucifer S03E01 1080p HDTV X264 DIMENSION` by series plugin because choosing best available quality
2017-10-09 15:36 INFO     convert_magnet stage           Converting entry Lucifer S03E02 1080p HDTV X264 DIMENSION magnet URI to a torrent file
2017-10-09 15:36 INFO     convert_magnet stage           lt_ver caught
2017-10-09 15:36 CRITICAL task          stage           BUG: Unhandled error in plugin convert_magnet: 'str' object has no attribute 'to_bytes'
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/flexget/task.py", line 486, in __run_plugin
    return method(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/flexget/event.py", line 23, in __call__
    return self.func(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/flexget/plugins/modify/convert_magnet.py", line 93, in on_task_download
    torrent_file = self.magnet_to_torrent(entry['url'], converted_path, timeout)
  File "/usr/local/lib/python2.7/dist-packages/flexget/plugins/modify/convert_magnet.py", line 41, in magnet_to_torrent
    params['info_hash'] = params['info_hash'].to_bytes()
AttributeError: 'str' object has no attribute 'to_bytes'
```

### Additional information:

- FlexGet version: 2.10.97
- Python version: 2.7.13
- Installation method: pip
- Using daemon (yes/no): no
- OS and version: Debian Stretch 9.1
- Link to crash log: see above

flexget/plugins/modify/convert_magnet.py line 40 converts the info_hash to bytes if the libtorrent version is above 0.16.13.  The comments seem to indicate this was done as a work around because the info_hash value did not comply with the defined structure.  according to the release notes on libtorrent v1.1.3 this has been corrected, info_hash is now a string value which does not contain the attribute to_bytes, this causes the crash.  Since the underlying issue in libtorrent has been corrected, the info_hash value can be used as is without converting to_bytes if the libtorrent versions above 1.1.3.  Standby for PR


### References: 
https://github.com/arvidn/libtorrent/releases/tag/libtorrent-1_1_3
https://github.com/arvidn/libtorrent/commit/2e367ea53b1ce36d42eec73d12056ca4cd8029a4



--- 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/plugins/modify/convert_magnet.py`
Content:
```
1 from __future__ import unicode_literals, division, absolute_import
2 from builtins import *  # noqa pylint: disable=unused-import, redefined-builtin
3 import os
4 import time
5 import logging
6 
7 from flexget import plugin
8 from flexget.event import event
9 from flexget.utils.tools import parse_timedelta
10 from flexget.utils.pathscrub import pathscrub
11 
12 log = logging.getLogger('convert_magnet')
13 
14 
15 class ConvertMagnet(object):
16     """Convert magnet only entries to a torrent file"""
17 
18     schema = {
19         "oneOf": [
20             # Allow convert_magnet: no form to turn off plugin altogether
21             {"type": "boolean"},
22             {
23                 "type": "object",
24                 "properties": {
25                     "timeout": {"type": "string", "format": "interval"},
26                     "force": {"type": "boolean"}
27                 },
28                 "additionalProperties": False
29             }
30         ]
31     }
32 
33     def magnet_to_torrent(self, magnet_uri, destination_folder, timeout):
34         import libtorrent
35         params = libtorrent.parse_magnet_uri(magnet_uri)
36         session = libtorrent.session()
37         lt_version = [int(v) for v in libtorrent.version.split('.')]
38         if lt_version > [0,16,13,0]:
39             # for some reason the info_hash needs to be bytes but it's a struct called sha1_hash
40             params['info_hash'] = params['info_hash'].to_bytes()
41         handle = libtorrent.add_magnet_uri(session, magnet_uri, params)
42         log.debug('Acquiring torrent metadata for magnet %s', magnet_uri)
43         timeout_value = timeout
44         while not handle.has_metadata():
45             time.sleep(0.1)
46             timeout_value -= 0.1
47             if timeout_value <= 0:
48                 raise plugin.PluginError('Timed out after {} seconds trying to magnetize'.format(timeout))
49         log.debug('Metadata acquired')
50         torrent_info = handle.get_torrent_info()
51         torrent_file = libtorrent.create_torrent(torrent_info)
52         torrent_path = pathscrub(os.path.join(destination_folder, torrent_info.name() + ".torrent"))
53         with open(torrent_path, "wb") as f:
54             f.write(libtorrent.bencode(torrent_file.generate()))
55         log.debug('Torrent file wrote to %s', torrent_path)
56         return torrent_path
57 
58     def prepare_config(self, config):
59         if not isinstance(config, dict):
60             config = {}
61         config.setdefault('timeout', '30 seconds')
62         config.setdefault('force', False)
63         return config
64 
65     @plugin.priority(255)
66     def on_task_start(self, task, config):
67         if config is False:
68             return
69         try:
70             import libtorrent  # noqa
71         except ImportError:
72             raise plugin.DependencyError('convert_magnet', 'libtorrent', 'libtorrent package required', log)
73 
74     @plugin.priority(130)
75     def on_task_download(self, task, config):
76         if config is False:
77             return
78         config = self.prepare_config(config)
79         # Create the conversion target directory
80         converted_path = os.path.join(task.manager.config_base, 'converted')
81 
82         timeout = parse_timedelta(config['timeout']).total_seconds()
83 
84         if not os.path.isdir(converted_path):
85             os.mkdir(converted_path)
86 
87         for entry in task.accepted:
88             if entry['url'].startswith('magnet:'):
89                 entry.setdefault('urls', [entry['url']])
90                 try:
91                     log.info('Converting entry {} magnet URI to a torrent file'.format(entry['title']))
92                     torrent_file = self.magnet_to_torrent(entry['url'], converted_path, timeout)
93                 except (plugin.PluginError, TypeError) as e:
94                     log.error('Unable to convert Magnet URI for entry %s: %s', entry['title'], e)
95                     if config['force']:
96                         entry.fail('Magnet URI conversion failed')
97                     continue
98                 # Windows paths need an extra / prepended to them for url
99                 if not torrent_file.startswith('/'):
100                     torrent_file = '/' + torrent_file
101                 entry['url'] = torrent_file
102                 entry['file'] = torrent_file
103                 # make sure it's first in the list because of how download plugin works
104                 entry['urls'].insert(0, 'file://{}'.format(torrent_file))
105 
106 
107 @event('plugin.register')
108 def register_plugin():
109     plugin.register(ConvertMagnet, 'convert_magnet', api_ver=2)
110
```
--- 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/plugins/modify/convert_magnet.py b/flexget/plugins/modify/convert_magnet.py
--- a/flexget/plugins/modify/convert_magnet.py
+++ b/flexget/plugins/modify/convert_magnet.py
@@ -35,7 +35,7 @@
         params = libtorrent.parse_magnet_uri(magnet_uri)
         session = libtorrent.session()
         lt_version = [int(v) for v in libtorrent.version.split('.')]
-        if lt_version > [0,16,13,0]:
+        if lt_version > [0,16,13,0] and lt_version < [1,1,3,0]:
             # for some reason the info_hash needs to be bytes but it's a struct called sha1_hash
             params['info_hash'] = params['info_hash'].to_bytes()
         handle = libtorrent.add_magnet_uri(session, magnet_uri, params)

{"golden_diff": "diff --git a/flexget/plugins/modify/convert_magnet.py b/flexget/plugins/modify/convert_magnet.py\n--- a/flexget/plugins/modify/convert_magnet.py\n+++ b/flexget/plugins/modify/convert_magnet.py\n@@ -35,7 +35,7 @@\n         params = libtorrent.parse_magnet_uri(magnet_uri)\n         session = libtorrent.session()\n         lt_version = [int(v) for v in libtorrent.version.split('.')]\n-        if lt_version > [0,16,13,0]:\n+        if lt_version > [0,16,13,0] and lt_version < [1,1,3,0]:\n             # for some reason the info_hash needs to be bytes but it's a struct called sha1_hash\n             params['info_hash'] = params['info_hash'].to_bytes()\n         handle = libtorrent.add_magnet_uri(session, magnet_uri, params)\n", "issue": "Incompatibility with Libtorrent version 1.1.3 and above\n### Actual behaviour:\r\nflexget crashes when converting magnet URI to a torrent file with libtorrent versions 1.1.3 and higher\r\n\r\n### Steps to reproduce:\r\nupgrade libtorrent to 1.1.3 or higher (I'm using 1.1.4 but the change occurred in 1.1.3)\r\ndownload torrent with convert_magnet plugin \r\n\r\n#### Config:\r\n```\r\ntasks:\r\n  stage:\r\n    convert_magnet: yes\r\n    rss: http://xxx.xxx/rss\r\n    accept_all: yes\r\n    download:\r\n      path: /home/flexget/test/\r\n```\r\n  \r\n#### Log:\r\n```\r\n2017-10-09 15:36 VERBOSE  task_queue                    There are 1 tasks to execute. Shutdown will commence when they have completed.\r\n2017-10-09 15:36 VERBOSE  details       stage           Produced 74 entries.\r\n2017-10-09 15:36 INFO     series        stage           identified_by has locked in to type `ep` for Lucifer\r\n2017-10-09 15:36 VERBOSE  task          stage           ACCEPTED: `Lucifer S03E02 1080p HDTV X264 DIMENSION` by series plugin because choosing best available quality\r\n2017-10-09 15:36 VERBOSE  task          stage           ACCEPTED: `Lucifer S03E01 1080p HDTV X264 DIMENSION` by series plugin because choosing best available quality\r\n2017-10-09 15:36 INFO     convert_magnet stage           Converting entry Lucifer S03E02 1080p HDTV X264 DIMENSION magnet URI to a torrent file\r\n2017-10-09 15:36 INFO     convert_magnet stage           lt_ver caught\r\n2017-10-09 15:36 CRITICAL task          stage           BUG: Unhandled error in plugin convert_magnet: 'str' object has no attribute 'to_bytes'\r\nTraceback (most recent call last):\r\n  File \"/usr/local/lib/python2.7/dist-packages/flexget/task.py\", line 486, in __run_plugin\r\n    return method(*args, **kwargs)\r\n  File \"/usr/local/lib/python2.7/dist-packages/flexget/event.py\", line 23, in __call__\r\n    return self.func(*args, **kwargs)\r\n  File \"/usr/local/lib/python2.7/dist-packages/flexget/plugins/modify/convert_magnet.py\", line 93, in on_task_download\r\n    torrent_file = self.magnet_to_torrent(entry['url'], converted_path, timeout)\r\n  File \"/usr/local/lib/python2.7/dist-packages/flexget/plugins/modify/convert_magnet.py\", line 41, in magnet_to_torrent\r\n    params['info_hash'] = params['info_hash'].to_bytes()\r\nAttributeError: 'str' object has no attribute 'to_bytes'\r\n```\r\n\r\n### Additional information:\r\n\r\n- FlexGet version: 2.10.97\r\n- Python version: 2.7.13\r\n- Installation method: pip\r\n- Using daemon (yes/no): no\r\n- OS and version: Debian Stretch 9.1\r\n- Link to crash log: see above\r\n\r\nflexget/plugins/modify/convert_magnet.py line 40 converts the info_hash to bytes if the libtorrent version is above 0.16.13.  The comments seem to indicate this was done as a work around because the info_hash value did not comply with the defined structure.  according to the release notes on libtorrent v1.1.3 this has been corrected, info_hash is now a string value which does not contain the attribute to_bytes, this causes the crash.  Since the underlying issue in libtorrent has been corrected, the info_hash value can be used as is without converting to_bytes if the libtorrent versions above 1.1.3.  Standby for PR\r\n\r\n\r\n### References: \r\nhttps://github.com/arvidn/libtorrent/releases/tag/libtorrent-1_1_3\r\nhttps://github.com/arvidn/libtorrent/commit/2e367ea53b1ce36d42eec73d12056ca4cd8029a4\r\n\r\n\n", "before_files": [{"content": "from __future__ import unicode_literals, division, absolute_import\nfrom builtins import *  # noqa pylint: disable=unused-import, redefined-builtin\nimport os\nimport time\nimport logging\n\nfrom flexget import plugin\nfrom flexget.event import event\nfrom flexget.utils.tools import parse_timedelta\nfrom flexget.utils.pathscrub import pathscrub\n\nlog = logging.getLogger('convert_magnet')\n\n\nclass ConvertMagnet(object):\n    \"\"\"Convert magnet only entries to a torrent file\"\"\"\n\n    schema = {\n        \"oneOf\": [\n            # Allow convert_magnet: no form to turn off plugin altogether\n            {\"type\": \"boolean\"},\n            {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"timeout\": {\"type\": \"string\", \"format\": \"interval\"},\n                    \"force\": {\"type\": \"boolean\"}\n                },\n                \"additionalProperties\": False\n            }\n        ]\n    }\n\n    def magnet_to_torrent(self, magnet_uri, destination_folder, timeout):\n        import libtorrent\n        params = libtorrent.parse_magnet_uri(magnet_uri)\n        session = libtorrent.session()\n        lt_version = [int(v) for v in libtorrent.version.split('.')]\n        if lt_version > [0,16,13,0]:\n            # for some reason the info_hash needs to be bytes but it's a struct called sha1_hash\n            params['info_hash'] = params['info_hash'].to_bytes()\n        handle = libtorrent.add_magnet_uri(session, magnet_uri, params)\n        log.debug('Acquiring torrent metadata for magnet %s', magnet_uri)\n        timeout_value = timeout\n        while not handle.has_metadata():\n            time.sleep(0.1)\n            timeout_value -= 0.1\n            if timeout_value <= 0:\n                raise plugin.PluginError('Timed out after {} seconds trying to magnetize'.format(timeout))\n        log.debug('Metadata acquired')\n        torrent_info = handle.get_torrent_info()\n        torrent_file = libtorrent.create_torrent(torrent_info)\n        torrent_path = pathscrub(os.path.join(destination_folder, torrent_info.name() + \".torrent\"))\n        with open(torrent_path, \"wb\") as f:\n            f.write(libtorrent.bencode(torrent_file.generate()))\n        log.debug('Torrent file wrote to %s', torrent_path)\n        return torrent_path\n\n    def prepare_config(self, config):\n        if not isinstance(config, dict):\n            config = {}\n        config.setdefault('timeout', '30 seconds')\n        config.setdefault('force', False)\n        return config\n\n    @plugin.priority(255)\n    def on_task_start(self, task, config):\n        if config is False:\n            return\n        try:\n            import libtorrent  # noqa\n        except ImportError:\n            raise plugin.DependencyError('convert_magnet', 'libtorrent', 'libtorrent package required', log)\n\n    @plugin.priority(130)\n    def on_task_download(self, task, config):\n        if config is False:\n            return\n        config = self.prepare_config(config)\n        # Create the conversion target directory\n        converted_path = os.path.join(task.manager.config_base, 'converted')\n\n        timeout = parse_timedelta(config['timeout']).total_seconds()\n\n        if not os.path.isdir(converted_path):\n            os.mkdir(converted_path)\n\n        for entry in task.accepted:\n            if entry['url'].startswith('magnet:'):\n                entry.setdefault('urls', [entry['url']])\n                try:\n                    log.info('Converting entry {} magnet URI to a torrent file'.format(entry['title']))\n                    torrent_file = self.magnet_to_torrent(entry['url'], converted_path, timeout)\n                except (plugin.PluginError, TypeError) as e:\n                    log.error('Unable to convert Magnet URI for entry %s: %s', entry['title'], e)\n                    if config['force']:\n                        entry.fail('Magnet URI conversion failed')\n                    continue\n                # Windows paths need an extra / prepended to them for url\n                if not torrent_file.startswith('/'):\n                    torrent_file = '/' + torrent_file\n                entry['url'] = torrent_file\n                entry['file'] = torrent_file\n                # make sure it's first in the list because of how download plugin works\n                entry['urls'].insert(0, 'file://{}'.format(torrent_file))\n\n\n@event('plugin.register')\ndef register_plugin():\n    plugin.register(ConvertMagnet, 'convert_magnet', api_ver=2)\n", "path": "flexget/plugins/modify/convert_magnet.py"}], "after_files": [{"content": "from __future__ import unicode_literals, division, absolute_import\nfrom builtins import *  # noqa pylint: disable=unused-import, redefined-builtin\nimport os\nimport time\nimport logging\n\nfrom flexget import plugin\nfrom flexget.event import event\nfrom flexget.utils.tools import parse_timedelta\nfrom flexget.utils.pathscrub import pathscrub\n\nlog = logging.getLogger('convert_magnet')\n\n\nclass ConvertMagnet(object):\n    \"\"\"Convert magnet only entries to a torrent file\"\"\"\n\n    schema = {\n        \"oneOf\": [\n            # Allow convert_magnet: no form to turn off plugin altogether\n            {\"type\": \"boolean\"},\n            {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"timeout\": {\"type\": \"string\", \"format\": \"interval\"},\n                    \"force\": {\"type\": \"boolean\"}\n                },\n                \"additionalProperties\": False\n            }\n        ]\n    }\n\n    def magnet_to_torrent(self, magnet_uri, destination_folder, timeout):\n        import libtorrent\n        params = libtorrent.parse_magnet_uri(magnet_uri)\n        session = libtorrent.session()\n        lt_version = [int(v) for v in libtorrent.version.split('.')]\n        if lt_version > [0,16,13,0] and lt_version < [1,1,3,0]:\n            # for some reason the info_hash needs to be bytes but it's a struct called sha1_hash\n            params['info_hash'] = params['info_hash'].to_bytes()\n        handle = libtorrent.add_magnet_uri(session, magnet_uri, params)\n        log.debug('Acquiring torrent metadata for magnet %s', magnet_uri)\n        timeout_value = timeout\n        while not handle.has_metadata():\n            time.sleep(0.1)\n            timeout_value -= 0.1\n            if timeout_value <= 0:\n                raise plugin.PluginError('Timed out after {} seconds trying to magnetize'.format(timeout))\n        log.debug('Metadata acquired')\n        torrent_info = handle.get_torrent_info()\n        torrent_file = libtorrent.create_torrent(torrent_info)\n        torrent_path = pathscrub(os.path.join(destination_folder, torrent_info.name() + \".torrent\"))\n        with open(torrent_path, \"wb\") as f:\n            f.write(libtorrent.bencode(torrent_file.generate()))\n        log.debug('Torrent file wrote to %s', torrent_path)\n        return torrent_path\n\n    def prepare_config(self, config):\n        if not isinstance(config, dict):\n            config = {}\n        config.setdefault('timeout', '30 seconds')\n        config.setdefault('force', False)\n        return config\n\n    @plugin.priority(255)\n    def on_task_start(self, task, config):\n        if config is False:\n            return\n        try:\n            import libtorrent  # noqa\n        except ImportError:\n            raise plugin.DependencyError('convert_magnet', 'libtorrent', 'libtorrent package required', log)\n\n    @plugin.priority(130)\n    def on_task_download(self, task, config):\n        if config is False:\n            return\n        config = self.prepare_config(config)\n        # Create the conversion target directory\n        converted_path = os.path.join(task.manager.config_base, 'converted')\n\n        timeout = parse_timedelta(config['timeout']).total_seconds()\n\n        if not os.path.isdir(converted_path):\n            os.mkdir(converted_path)\n\n        for entry in task.accepted:\n            if entry['url'].startswith('magnet:'):\n                entry.setdefault('urls', [entry['url']])\n                try:\n                    log.info('Converting entry {} magnet URI to a torrent file'.format(entry['title']))\n                    torrent_file = self.magnet_to_torrent(entry['url'], converted_path, timeout)\n                except (plugin.PluginError, TypeError) as e:\n                    log.error('Unable to convert Magnet URI for entry %s: %s', entry['title'], e)\n                    if config['force']:\n                        entry.fail('Magnet URI conversion failed')\n                    continue\n                # Windows paths need an extra / prepended to them for url\n                if not torrent_file.startswith('/'):\n                    torrent_file = '/' + torrent_file\n                entry['url'] = torrent_file\n                entry['file'] = torrent_file\n                # make sure it's first in the list because of how download plugin works\n                entry['urls'].insert(0, 'file://{}'.format(torrent_file))\n\n\n@event('plugin.register')\ndef register_plugin():\n    plugin.register(ConvertMagnet, 'convert_magnet', api_ver=2)\n", "path": "flexget/plugins/modify/convert_magnet.py"}]}