We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
The torrentleech plugin is not working with their V5 api 
### Expected behaviour:
The first episode of the series is downloaded

### Actual behaviour:
No results are found from the torrentleech search plugin


### Steps to reproduce:
- Step 1: Run flexget with the config supplied in the issue

#### Config:
```
tasks:
  test task:
    series:
      - Rick and Morty:
          begin: S02E01
    discover:
      what:
        - next_series_episodes:
            backfill: yes
      from:
        - torrentleech:
            rss_key: ***********
            username: ***********
            password: ***********
    download: ~/downloads

schedules:
  # Run every 30 minutes
  - tasks: '*'
    schedule:
      minute: "*/20"
```
  
### Additional information:
This seems to be a result of the upgrade to the Torrentleech V5 api. I modified the plugin to use the V4 api and this is working for now as long as they don't remove support for it. Would it be reasonable to put a PR with a Torrentleech plugin that uses the V4 api until support for the V5 api has been implemented? 


- FlexGet version: 2.13.8.dev
- Python version: Python 2.7.14
- Installation method: Latest git version
- Using daemon (yes/no): no
- OS and version: MacOS and Ubuntu Server


--- 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/sites/torrentleech.py`
Content:
```
1 from __future__ import unicode_literals, division, absolute_import
2 from builtins import *  # noqa pylint: disable=unused-import, redefined-builtin
3 from future.moves.urllib.parse import quote
4 
5 import re
6 import logging
7 
8 from requests.exceptions import RequestException
9 
10 from flexget import plugin
11 from flexget.config_schema import one_or_more
12 from flexget.entry import Entry
13 from flexget.event import event
14 from flexget.plugin import PluginError
15 from flexget.plugins.internal.urlrewriting import UrlRewritingError
16 from flexget.utils.soup import get_soup
17 from flexget.utils.search import torrent_availability, normalize_unicode
18 from flexget.utils.tools import parse_filesize
19 
20 log = logging.getLogger('torrentleech')
21 
22 CATEGORIES = {
23     'all': 0,
24 
25     # Movies
26     'Cam': 8,
27     'TS': 9,
28     'R5': 10,
29     'DVDRip': 11,
30     'DVDR': 12,
31     'HD': 13,
32     'BDRip': 14,
33     'Movie Boxsets': 15,
34     'Documentaries': 29,
35 
36     # TV
37     'Episodes': 26,
38     'TV Boxsets': 27,
39     'Episodes HD': 32
40 }
41 
42 
43 class UrlRewriteTorrentleech(object):
44     """
45         Torrentleech urlrewriter and search plugin.
46 
47         torrentleech:
48           rss_key: xxxxxxxxx  (required)
49           username: xxxxxxxx  (required)
50           password: xxxxxxxx  (required)
51           category: HD
52 
53           Category is any combination of: all, Cam, TS, R5,
54           DVDRip, DVDR, HD, BDRip, Movie Boxsets, Documentaries,
55           Episodes, TV BoxSets, Episodes HD
56     """
57 
58     schema = {
59         'type': 'object',
60         'properties': {
61             'rss_key': {'type': 'string'},
62             'username': {'type': 'string'},
63             'password': {'type': 'string'},
64             'category': one_or_more({
65                 'oneOf': [
66                     {'type': 'integer'},
67                     {'type': 'string', 'enum': list(CATEGORIES)},
68                 ]
69             }),
70         },
71         'required': ['rss_key', 'username', 'password'],
72         'additionalProperties': False
73     }
74 
75     # urlrewriter API
76     def url_rewritable(self, task, entry):
77         url = entry['url']
78         if url.endswith('.torrent'):
79             return False
80         if url.startswith('https://www.torrentleech.org/'):
81             return True
82         return False
83 
84     # urlrewriter API
85     def url_rewrite(self, task, entry):
86         if 'url' not in entry:
87             log.error("Didn't actually get a URL...")
88         else:
89             log.debug("Got the URL: %s" % entry['url'])
90         if entry['url'].startswith('https://www.torrentleech.org/torrents/browse/index/query/'):
91             # use search
92             results = self.search(task, entry)
93             if not results:
94                 raise UrlRewritingError("No search results found")
95             # TODO: Search doesn't enforce close match to title, be more picky
96             entry['url'] = results[0]['url']
97 
98     @plugin.internet(log)
99     def search(self, task, entry, config=None):
100         """
101         Search for name from torrentleech.
102         """
103         rss_key = config['rss_key']
104 
105         # build the form request:
106         data = {'username': config['username'], 'password': config['password']}
107         # POST the login form:
108         try:
109             login = task.requests.post('https://www.torrentleech.org/user/account/login/', data=data)
110         except RequestException as e:
111             raise PluginError('Could not connect to torrentleech: %s', str(e))
112 
113         if not isinstance(config, dict):
114             config = {}
115             # sort = SORT.get(config.get('sort_by', 'seeds'))
116             # if config.get('sort_reverse'):
117             # sort += 1
118         categories = config.get('category', 'all')
119         # Make sure categories is a list
120         if not isinstance(categories, list):
121             categories = [categories]
122         # If there are any text categories, turn them into their id number
123         categories = [c if isinstance(c, int) else CATEGORIES[c] for c in categories]
124         filter_url = '/categories/%s' % ','.join(str(c) for c in categories)
125         entries = set()
126         for search_string in entry.get('search_strings', [entry['title']]):
127             query = normalize_unicode(search_string).replace(":", "")
128             # urllib.quote will crash if the unicode string has non ascii characters, so encode in utf-8 beforehand
129             url = ('https://www.torrentleech.org/torrents/browse/index/query/' +
130                    quote(query.encode('utf-8')) + filter_url)
131             log.debug('Using %s as torrentleech search url' % url)
132 
133             page = task.requests.get(url, cookies=login.cookies).content
134             soup = get_soup(page)
135 
136             for tr in soup.find_all("tr", ["even", "odd"]):
137                 # within each even or odd row, find the torrent names
138                 link = tr.find("a", attrs={'href': re.compile('/torrent/\d+')})
139                 log.debug('link phase: %s' % link.contents[0])
140                 entry = Entry()
141                 # extracts the contents of the <a>titlename/<a> tag
142                 entry['title'] = link.contents[0]
143 
144                 # find download link
145                 torrent_url = tr.find("a", attrs={'href': re.compile('/download/\d+/.*')}).get('href')
146                 # parse link and split along /download/12345 and /name.torrent
147                 download_url = re.search('(/download/\d+)/(.+\.torrent)', torrent_url)
148                 # change link to rss and splice in rss_key
149                 torrent_url = 'https://www.torrentleech.org/rss' + download_url.group(1) + '/' \
150                               + rss_key + '/' + download_url.group(2)
151                 log.debug('RSS-ified download link: %s' % torrent_url)
152                 entry['url'] = torrent_url
153 
154                 # us tr object for seeders/leechers
155                 seeders, leechers = tr.find_all('td', ["seeders", "leechers"])
156                 entry['torrent_seeds'] = int(seeders.contents[0])
157                 entry['torrent_leeches'] = int(leechers.contents[0])
158                 entry['search_sort'] = torrent_availability(entry['torrent_seeds'], entry['torrent_leeches'])
159 
160                 # use tr object for size
161                 size = tr.find("td", text=re.compile('([\.\d]+) ([TGMK]?)B')).contents[0]
162                 size = re.search('([\.\d]+) ([TGMK]?)B', size)
163 
164                 entry['content_size'] = parse_filesize(size.group(0))
165 
166                 entries.add(entry)
167 
168         return sorted(entries, reverse=True, key=lambda x: x.get('search_sort'))
169 
170 
171 @event('plugin.register')
172 def register_plugin():
173     plugin.register(UrlRewriteTorrentleech, 'torrentleech', interfaces=['urlrewriter', 'search'], api_ver=2)
174
```
--- 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/sites/torrentleech.py b/flexget/plugins/sites/torrentleech.py
--- a/flexget/plugins/sites/torrentleech.py
+++ b/flexget/plugins/sites/torrentleech.py
@@ -77,7 +77,7 @@
         url = entry['url']
         if url.endswith('.torrent'):
             return False
-        if url.startswith('https://www.torrentleech.org/'):
+        if url.startswith('https://v4.torrentleech.org/'):
             return True
         return False
 
@@ -87,7 +87,7 @@
             log.error("Didn't actually get a URL...")
         else:
             log.debug("Got the URL: %s" % entry['url'])
-        if entry['url'].startswith('https://www.torrentleech.org/torrents/browse/index/query/'):
+        if entry['url'].startswith('https://v4.torrentleech.org/torrents/browse/index/query/'):
             # use search
             results = self.search(task, entry)
             if not results:
@@ -106,7 +106,7 @@
         data = {'username': config['username'], 'password': config['password']}
         # POST the login form:
         try:
-            login = task.requests.post('https://www.torrentleech.org/user/account/login/', data=data)
+            login = task.requests.post('https://v4.torrentleech.org/user/account/login/', data=data)
         except RequestException as e:
             raise PluginError('Could not connect to torrentleech: %s', str(e))
 
@@ -126,7 +126,7 @@
         for search_string in entry.get('search_strings', [entry['title']]):
             query = normalize_unicode(search_string).replace(":", "")
             # urllib.quote will crash if the unicode string has non ascii characters, so encode in utf-8 beforehand
-            url = ('https://www.torrentleech.org/torrents/browse/index/query/' +
+            url = ('https://v4.torrentleech.org/torrents/browse/index/query/' +
                    quote(query.encode('utf-8')) + filter_url)
             log.debug('Using %s as torrentleech search url' % url)
 
@@ -146,7 +146,7 @@
                 # parse link and split along /download/12345 and /name.torrent
                 download_url = re.search('(/download/\d+)/(.+\.torrent)', torrent_url)
                 # change link to rss and splice in rss_key
-                torrent_url = 'https://www.torrentleech.org/rss' + download_url.group(1) + '/' \
+                torrent_url = 'https://v4.torrentleech.org/rss' + download_url.group(1) + '/' \
                               + rss_key + '/' + download_url.group(2)
                 log.debug('RSS-ified download link: %s' % torrent_url)
                 entry['url'] = torrent_url

{"golden_diff": "diff --git a/flexget/plugins/sites/torrentleech.py b/flexget/plugins/sites/torrentleech.py\n--- a/flexget/plugins/sites/torrentleech.py\n+++ b/flexget/plugins/sites/torrentleech.py\n@@ -77,7 +77,7 @@\n         url = entry['url']\n         if url.endswith('.torrent'):\n             return False\n-        if url.startswith('https://www.torrentleech.org/'):\n+        if url.startswith('https://v4.torrentleech.org/'):\n             return True\n         return False\n \n@@ -87,7 +87,7 @@\n             log.error(\"Didn't actually get a URL...\")\n         else:\n             log.debug(\"Got the URL: %s\" % entry['url'])\n-        if entry['url'].startswith('https://www.torrentleech.org/torrents/browse/index/query/'):\n+        if entry['url'].startswith('https://v4.torrentleech.org/torrents/browse/index/query/'):\n             # use search\n             results = self.search(task, entry)\n             if not results:\n@@ -106,7 +106,7 @@\n         data = {'username': config['username'], 'password': config['password']}\n         # POST the login form:\n         try:\n-            login = task.requests.post('https://www.torrentleech.org/user/account/login/', data=data)\n+            login = task.requests.post('https://v4.torrentleech.org/user/account/login/', data=data)\n         except RequestException as e:\n             raise PluginError('Could not connect to torrentleech: %s', str(e))\n \n@@ -126,7 +126,7 @@\n         for search_string in entry.get('search_strings', [entry['title']]):\n             query = normalize_unicode(search_string).replace(\":\", \"\")\n             # urllib.quote will crash if the unicode string has non ascii characters, so encode in utf-8 beforehand\n-            url = ('https://www.torrentleech.org/torrents/browse/index/query/' +\n+            url = ('https://v4.torrentleech.org/torrents/browse/index/query/' +\n                    quote(query.encode('utf-8')) + filter_url)\n             log.debug('Using %s as torrentleech search url' % url)\n \n@@ -146,7 +146,7 @@\n                 # parse link and split along /download/12345 and /name.torrent\n                 download_url = re.search('(/download/\\d+)/(.+\\.torrent)', torrent_url)\n                 # change link to rss and splice in rss_key\n-                torrent_url = 'https://www.torrentleech.org/rss' + download_url.group(1) + '/' \\\n+                torrent_url = 'https://v4.torrentleech.org/rss' + download_url.group(1) + '/' \\\n                               + rss_key + '/' + download_url.group(2)\n                 log.debug('RSS-ified download link: %s' % torrent_url)\n                 entry['url'] = torrent_url\n", "issue": "The torrentleech plugin is not working with their V5 api \n### Expected behaviour:\r\nThe first episode of the series is downloaded\r\n\r\n### Actual behaviour:\r\nNo results are found from the torrentleech search plugin\r\n\r\n\r\n### Steps to reproduce:\r\n- Step 1: Run flexget with the config supplied in the issue\r\n\r\n#### Config:\r\n```\r\ntasks:\r\n  test task:\r\n    series:\r\n      - Rick and Morty:\r\n          begin: S02E01\r\n    discover:\r\n      what:\r\n        - next_series_episodes:\r\n            backfill: yes\r\n      from:\r\n        - torrentleech:\r\n            rss_key: ***********\r\n            username: ***********\r\n            password: ***********\r\n    download: ~/downloads\r\n\r\nschedules:\r\n  # Run every 30 minutes\r\n  - tasks: '*'\r\n    schedule:\r\n      minute: \"*/20\"\r\n```\r\n  \r\n### Additional information:\r\nThis seems to be a result of the upgrade to the Torrentleech V5 api. I modified the plugin to use the V4 api and this is working for now as long as they don't remove support for it. Would it be reasonable to put a PR with a Torrentleech plugin that uses the V4 api until support for the V5 api has been implemented? \r\n\r\n\r\n- FlexGet version: 2.13.8.dev\r\n- Python version: Python 2.7.14\r\n- Installation method: Latest git version\r\n- Using daemon (yes/no): no\r\n- OS and version: MacOS and Ubuntu Server\r\n\n", "before_files": [{"content": "from __future__ import unicode_literals, division, absolute_import\nfrom builtins import *  # noqa pylint: disable=unused-import, redefined-builtin\nfrom future.moves.urllib.parse import quote\n\nimport re\nimport logging\n\nfrom requests.exceptions import RequestException\n\nfrom flexget import plugin\nfrom flexget.config_schema import one_or_more\nfrom flexget.entry import Entry\nfrom flexget.event import event\nfrom flexget.plugin import PluginError\nfrom flexget.plugins.internal.urlrewriting import UrlRewritingError\nfrom flexget.utils.soup import get_soup\nfrom flexget.utils.search import torrent_availability, normalize_unicode\nfrom flexget.utils.tools import parse_filesize\n\nlog = logging.getLogger('torrentleech')\n\nCATEGORIES = {\n    'all': 0,\n\n    # Movies\n    'Cam': 8,\n    'TS': 9,\n    'R5': 10,\n    'DVDRip': 11,\n    'DVDR': 12,\n    'HD': 13,\n    'BDRip': 14,\n    'Movie Boxsets': 15,\n    'Documentaries': 29,\n\n    # TV\n    'Episodes': 26,\n    'TV Boxsets': 27,\n    'Episodes HD': 32\n}\n\n\nclass UrlRewriteTorrentleech(object):\n    \"\"\"\n        Torrentleech urlrewriter and search plugin.\n\n        torrentleech:\n          rss_key: xxxxxxxxx  (required)\n          username: xxxxxxxx  (required)\n          password: xxxxxxxx  (required)\n          category: HD\n\n          Category is any combination of: all, Cam, TS, R5,\n          DVDRip, DVDR, HD, BDRip, Movie Boxsets, Documentaries,\n          Episodes, TV BoxSets, Episodes HD\n    \"\"\"\n\n    schema = {\n        'type': 'object',\n        'properties': {\n            'rss_key': {'type': 'string'},\n            'username': {'type': 'string'},\n            'password': {'type': 'string'},\n            'category': one_or_more({\n                'oneOf': [\n                    {'type': 'integer'},\n                    {'type': 'string', 'enum': list(CATEGORIES)},\n                ]\n            }),\n        },\n        'required': ['rss_key', 'username', 'password'],\n        'additionalProperties': False\n    }\n\n    # urlrewriter API\n    def url_rewritable(self, task, entry):\n        url = entry['url']\n        if url.endswith('.torrent'):\n            return False\n        if url.startswith('https://www.torrentleech.org/'):\n            return True\n        return False\n\n    # urlrewriter API\n    def url_rewrite(self, task, entry):\n        if 'url' not in entry:\n            log.error(\"Didn't actually get a URL...\")\n        else:\n            log.debug(\"Got the URL: %s\" % entry['url'])\n        if entry['url'].startswith('https://www.torrentleech.org/torrents/browse/index/query/'):\n            # use search\n            results = self.search(task, entry)\n            if not results:\n                raise UrlRewritingError(\"No search results found\")\n            # TODO: Search doesn't enforce close match to title, be more picky\n            entry['url'] = results[0]['url']\n\n    @plugin.internet(log)\n    def search(self, task, entry, config=None):\n        \"\"\"\n        Search for name from torrentleech.\n        \"\"\"\n        rss_key = config['rss_key']\n\n        # build the form request:\n        data = {'username': config['username'], 'password': config['password']}\n        # POST the login form:\n        try:\n            login = task.requests.post('https://www.torrentleech.org/user/account/login/', data=data)\n        except RequestException as e:\n            raise PluginError('Could not connect to torrentleech: %s', str(e))\n\n        if not isinstance(config, dict):\n            config = {}\n            # sort = SORT.get(config.get('sort_by', 'seeds'))\n            # if config.get('sort_reverse'):\n            # sort += 1\n        categories = config.get('category', 'all')\n        # Make sure categories is a list\n        if not isinstance(categories, list):\n            categories = [categories]\n        # If there are any text categories, turn them into their id number\n        categories = [c if isinstance(c, int) else CATEGORIES[c] for c in categories]\n        filter_url = '/categories/%s' % ','.join(str(c) for c in categories)\n        entries = set()\n        for search_string in entry.get('search_strings', [entry['title']]):\n            query = normalize_unicode(search_string).replace(\":\", \"\")\n            # urllib.quote will crash if the unicode string has non ascii characters, so encode in utf-8 beforehand\n            url = ('https://www.torrentleech.org/torrents/browse/index/query/' +\n                   quote(query.encode('utf-8')) + filter_url)\n            log.debug('Using %s as torrentleech search url' % url)\n\n            page = task.requests.get(url, cookies=login.cookies).content\n            soup = get_soup(page)\n\n            for tr in soup.find_all(\"tr\", [\"even\", \"odd\"]):\n                # within each even or odd row, find the torrent names\n                link = tr.find(\"a\", attrs={'href': re.compile('/torrent/\\d+')})\n                log.debug('link phase: %s' % link.contents[0])\n                entry = Entry()\n                # extracts the contents of the <a>titlename/<a> tag\n                entry['title'] = link.contents[0]\n\n                # find download link\n                torrent_url = tr.find(\"a\", attrs={'href': re.compile('/download/\\d+/.*')}).get('href')\n                # parse link and split along /download/12345 and /name.torrent\n                download_url = re.search('(/download/\\d+)/(.+\\.torrent)', torrent_url)\n                # change link to rss and splice in rss_key\n                torrent_url = 'https://www.torrentleech.org/rss' + download_url.group(1) + '/' \\\n                              + rss_key + '/' + download_url.group(2)\n                log.debug('RSS-ified download link: %s' % torrent_url)\n                entry['url'] = torrent_url\n\n                # us tr object for seeders/leechers\n                seeders, leechers = tr.find_all('td', [\"seeders\", \"leechers\"])\n                entry['torrent_seeds'] = int(seeders.contents[0])\n                entry['torrent_leeches'] = int(leechers.contents[0])\n                entry['search_sort'] = torrent_availability(entry['torrent_seeds'], entry['torrent_leeches'])\n\n                # use tr object for size\n                size = tr.find(\"td\", text=re.compile('([\\.\\d]+) ([TGMK]?)B')).contents[0]\n                size = re.search('([\\.\\d]+) ([TGMK]?)B', size)\n\n                entry['content_size'] = parse_filesize(size.group(0))\n\n                entries.add(entry)\n\n        return sorted(entries, reverse=True, key=lambda x: x.get('search_sort'))\n\n\n@event('plugin.register')\ndef register_plugin():\n    plugin.register(UrlRewriteTorrentleech, 'torrentleech', interfaces=['urlrewriter', 'search'], api_ver=2)\n", "path": "flexget/plugins/sites/torrentleech.py"}], "after_files": [{"content": "from __future__ import unicode_literals, division, absolute_import\nfrom builtins import *  # noqa pylint: disable=unused-import, redefined-builtin\nfrom future.moves.urllib.parse import quote\n\nimport re\nimport logging\n\nfrom requests.exceptions import RequestException\n\nfrom flexget import plugin\nfrom flexget.config_schema import one_or_more\nfrom flexget.entry import Entry\nfrom flexget.event import event\nfrom flexget.plugin import PluginError\nfrom flexget.plugins.internal.urlrewriting import UrlRewritingError\nfrom flexget.utils.soup import get_soup\nfrom flexget.utils.search import torrent_availability, normalize_unicode\nfrom flexget.utils.tools import parse_filesize\n\nlog = logging.getLogger('torrentleech')\n\nCATEGORIES = {\n    'all': 0,\n\n    # Movies\n    'Cam': 8,\n    'TS': 9,\n    'R5': 10,\n    'DVDRip': 11,\n    'DVDR': 12,\n    'HD': 13,\n    'BDRip': 14,\n    'Movie Boxsets': 15,\n    'Documentaries': 29,\n\n    # TV\n    'Episodes': 26,\n    'TV Boxsets': 27,\n    'Episodes HD': 32\n}\n\n\nclass UrlRewriteTorrentleech(object):\n    \"\"\"\n        Torrentleech urlrewriter and search plugin.\n\n        torrentleech:\n          rss_key: xxxxxxxxx  (required)\n          username: xxxxxxxx  (required)\n          password: xxxxxxxx  (required)\n          category: HD\n\n          Category is any combination of: all, Cam, TS, R5,\n          DVDRip, DVDR, HD, BDRip, Movie Boxsets, Documentaries,\n          Episodes, TV BoxSets, Episodes HD\n    \"\"\"\n\n    schema = {\n        'type': 'object',\n        'properties': {\n            'rss_key': {'type': 'string'},\n            'username': {'type': 'string'},\n            'password': {'type': 'string'},\n            'category': one_or_more({\n                'oneOf': [\n                    {'type': 'integer'},\n                    {'type': 'string', 'enum': list(CATEGORIES)},\n                ]\n            }),\n        },\n        'required': ['rss_key', 'username', 'password'],\n        'additionalProperties': False\n    }\n\n    # urlrewriter API\n    def url_rewritable(self, task, entry):\n        url = entry['url']\n        if url.endswith('.torrent'):\n            return False\n        if url.startswith('https://v4.torrentleech.org/'):\n            return True\n        return False\n\n    # urlrewriter API\n    def url_rewrite(self, task, entry):\n        if 'url' not in entry:\n            log.error(\"Didn't actually get a URL...\")\n        else:\n            log.debug(\"Got the URL: %s\" % entry['url'])\n        if entry['url'].startswith('https://v4.torrentleech.org/torrents/browse/index/query/'):\n            # use search\n            results = self.search(task, entry)\n            if not results:\n                raise UrlRewritingError(\"No search results found\")\n            # TODO: Search doesn't enforce close match to title, be more picky\n            entry['url'] = results[0]['url']\n\n    @plugin.internet(log)\n    def search(self, task, entry, config=None):\n        \"\"\"\n        Search for name from torrentleech.\n        \"\"\"\n        rss_key = config['rss_key']\n\n        # build the form request:\n        data = {'username': config['username'], 'password': config['password']}\n        # POST the login form:\n        try:\n            login = task.requests.post('https://v4.torrentleech.org/user/account/login/', data=data)\n        except RequestException as e:\n            raise PluginError('Could not connect to torrentleech: %s', str(e))\n\n        if not isinstance(config, dict):\n            config = {}\n            # sort = SORT.get(config.get('sort_by', 'seeds'))\n            # if config.get('sort_reverse'):\n            # sort += 1\n        categories = config.get('category', 'all')\n        # Make sure categories is a list\n        if not isinstance(categories, list):\n            categories = [categories]\n        # If there are any text categories, turn them into their id number\n        categories = [c if isinstance(c, int) else CATEGORIES[c] for c in categories]\n        filter_url = '/categories/%s' % ','.join(str(c) for c in categories)\n        entries = set()\n        for search_string in entry.get('search_strings', [entry['title']]):\n            query = normalize_unicode(search_string).replace(\":\", \"\")\n            # urllib.quote will crash if the unicode string has non ascii characters, so encode in utf-8 beforehand\n            url = ('https://v4.torrentleech.org/torrents/browse/index/query/' +\n                   quote(query.encode('utf-8')) + filter_url)\n            log.debug('Using %s as torrentleech search url' % url)\n\n            page = task.requests.get(url, cookies=login.cookies).content\n            soup = get_soup(page)\n\n            for tr in soup.find_all(\"tr\", [\"even\", \"odd\"]):\n                # within each even or odd row, find the torrent names\n                link = tr.find(\"a\", attrs={'href': re.compile('/torrent/\\d+')})\n                log.debug('link phase: %s' % link.contents[0])\n                entry = Entry()\n                # extracts the contents of the <a>titlename/<a> tag\n                entry['title'] = link.contents[0]\n\n                # find download link\n                torrent_url = tr.find(\"a\", attrs={'href': re.compile('/download/\\d+/.*')}).get('href')\n                # parse link and split along /download/12345 and /name.torrent\n                download_url = re.search('(/download/\\d+)/(.+\\.torrent)', torrent_url)\n                # change link to rss and splice in rss_key\n                torrent_url = 'https://v4.torrentleech.org/rss' + download_url.group(1) + '/' \\\n                              + rss_key + '/' + download_url.group(2)\n                log.debug('RSS-ified download link: %s' % torrent_url)\n                entry['url'] = torrent_url\n\n                # us tr object for seeders/leechers\n                seeders, leechers = tr.find_all('td', [\"seeders\", \"leechers\"])\n                entry['torrent_seeds'] = int(seeders.contents[0])\n                entry['torrent_leeches'] = int(leechers.contents[0])\n                entry['search_sort'] = torrent_availability(entry['torrent_seeds'], entry['torrent_leeches'])\n\n                # use tr object for size\n                size = tr.find(\"td\", text=re.compile('([\\.\\d]+) ([TGMK]?)B')).contents[0]\n                size = re.search('([\\.\\d]+) ([TGMK]?)B', size)\n\n                entry['content_size'] = parse_filesize(size.group(0))\n\n                entries.add(entry)\n\n        return sorted(entries, reverse=True, key=lambda x: x.get('search_sort'))\n\n\n@event('plugin.register')\ndef register_plugin():\n    plugin.register(UrlRewriteTorrentleech, 'torrentleech', interfaces=['urlrewriter', 'search'], api_ver=2)\n", "path": "flexget/plugins/sites/torrentleech.py"}]}