We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Error message "Failed parsing provider" & "list index out of range"
**Describe the bug**
Error message:

`2020-12-05 07:52:25 ERROR    SEARCHQUEUE-BACKLOG-260586 :: [Beyond-HD] :: [ce68da5] Failed parsing provider.
Traceback (most recent call last):
  File "/Applications/Medusa/medusa/providers/torrent/html/beyondhd.py", line 128, in parse
    download_url = urljoin(self.url, cells[2].find('a')['href'])
IndexError: list index out of range`

**Medusa (please complete the following information):**
 - OS: macOS Catalina 10.15,.7
 - Branch: master
 - Commit: ce68da57b3878591f77c21bb2acf28e6a58269fa
 - Python version: 3.8.5
 - Database version: 44.17




--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `medusa/providers/torrent/html/beyondhd.py`
Content:
```
1 # coding=utf-8
2 
3 """Provider code for Beyond-hd."""
4 
5 from __future__ import unicode_literals
6 
7 import logging
8 
9 from medusa import tv
10 from medusa.bs4_parser import BS4Parser
11 from medusa.helper.common import convert_size
12 from medusa.logger.adapters.style import BraceAdapter
13 from medusa.providers.torrent.torrent_provider import TorrentProvider
14 
15 from requests.compat import urljoin
16 
17 log = BraceAdapter(logging.getLogger(__name__))
18 log.logger.addHandler(logging.NullHandler())
19 
20 
21 class BeyondHDProvider(TorrentProvider):
22     """Beyond-hd Torrent provider."""
23 
24     def __init__(self):
25         """Initialize the class."""
26         super(BeyondHDProvider, self).__init__('Beyond-HD')
27 
28         self.enable_cookies = True
29         self.cookies = ''
30         self.required_cookies = ('remember_web_[**long_hash**]',)
31 
32         self.url = 'https://beyond-hd.me'
33         self.urls = {
34             'login': urljoin(self.url, 'login'),
35             'search': urljoin(self.url, 'torrents'),
36         }
37 
38         # Proper Strings
39         self.proper_strings = ['PROPER', 'REPACK', 'REAL', 'RERIP']
40 
41         # Miscellaneous Options
42 
43         # Cache
44         self.cache = tv.Cache(self)
45 
46     def search(self, search_strings, *args, **kwargs):
47         """
48         Search a provider and parse the results.
49 
50         :param search_strings: A dict with mode (key) and the search value (value)
51         :returns: A list of search results (structure)
52         """
53         results = []
54         if not self.login():
55             return results
56 
57         for mode in search_strings:
58             log.debug('Search mode: {0}', mode)
59 
60             for search_string in search_strings[mode]:
61 
62                 search_params = {
63                     'categories[]': 2,
64                     'sorting': 'created_at',
65                     'qty': '100',
66                     'direction': 'desc',
67                     'doSearch': 'Search'
68                 }
69 
70                 if mode != 'RSS':
71                     log.debug('Search string: {search}',
72                               {'search': search_string})
73                     search_params['search'] = search_string
74 
75                 if mode == 'season':
76                     search_params['pack'] = 1
77 
78                 response = self.session.get(self.urls['search'], params=search_params)
79                 if not response or not response.text:
80                     log.debug('No data returned from provider')
81                     continue
82 
83                 results += self.parse(response.text, mode)
84 
85         return results
86 
87     def parse(self, data, mode):
88         """
89         Parse search results for items.
90 
91         :param data: The raw response from a search
92         :param mode: The current mode used to search, e.g. RSS
93 
94         :return: A list of items found
95         """
96         # Units
97         units = ['B', 'KIB', 'MIB', 'GIB', 'TIB', 'PIB']
98 
99         items = []
100 
101         with BS4Parser(data, 'html5lib') as html:
102             if html.find('div', class_='table-torrents'):
103                 theme = 'modern'
104                 torrent_table = html.find('div', class_='table-torrents').find('table')
105             else:
106                 theme = 'classic'
107                 torrent_table = html.find('div', class_='table-responsive').find('table')
108 
109             torrent_rows = torrent_table('tr') if torrent_table else []
110             labels = [label.get_text(strip=True) for label in torrent_rows[0]('th')]
111             # For the classic theme, the tr don't match the td.
112             if theme == 'classic':
113                 del labels[3]
114 
115             # Continue only if one release is found
116             if len(torrent_rows) < 2:
117                 log.debug('Data returned from provider does not contain any torrents')
118                 return items
119 
120             for result in torrent_rows[1:]:
121                 cells = result('td')
122 
123                 try:
124                     if len(cells) < 2:
125                         continue
126 
127                     link = cells[1].find('a')
128                     download_url = urljoin(self.url, cells[2].find('a')['href'])
129                     title = link.get_text(strip=True)
130                     if not all([title, download_url]):
131                         continue
132 
133                     seeders = int(cells[labels.index('S')].find('span').get_text())
134                     leechers = int(cells[labels.index('L')].find('span').get_text())
135 
136                     # Filter unseeded torrent
137                     if seeders < self.minseed:
138                         if mode != 'RSS':
139                             log.debug("Discarding torrent because it doesn't meet the"
140                                       ' minimum seeders: {0}. Seeders: {1}',
141                                       title, seeders)
142                         continue
143 
144                     torrent_size = cells[labels.index('Size')].find('span').get_text()
145                     size = convert_size(torrent_size, units=units) or -1
146 
147                     pubdate_raw = cells[labels.index('Age')].find('span').get_text()
148                     pubdate = self.parse_pubdate(pubdate_raw, human_time=True)
149 
150                     item = {
151                         'title': title,
152                         'link': download_url,
153                         'size': size,
154                         'seeders': seeders,
155                         'leechers': leechers,
156                         'pubdate': pubdate,
157                     }
158                     if mode != 'RSS':
159                         log.debug('Found result: {0} with {1} seeders and {2} leechers',
160                                   title, seeders, leechers)
161 
162                     items.append(item)
163                 except (AttributeError, TypeError, KeyError, ValueError, IndexError):
164                     log.exception('Failed parsing provider.')
165 
166         return items
167 
168     def login(self):
169         """Login method used for logging in before doing search and torrent downloads."""
170         return self.cookie_login('Login now')
171 
172     def check_required_cookies(self):
173         """
174         Check if we have the required cookies in the requests sessions object.
175 
176         Meaning that we've already successfully authenticated once, and we don't need to go through this again.
177         Note! This doesn't mean the cookies are correct!
178         """
179         return False
180 
181 
182 provider = BeyondHDProvider()
183
```
--- 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/medusa/providers/torrent/html/beyondhd.py b/medusa/providers/torrent/html/beyondhd.py
--- a/medusa/providers/torrent/html/beyondhd.py
+++ b/medusa/providers/torrent/html/beyondhd.py
@@ -121,7 +121,7 @@
                 cells = result('td')
 
                 try:
-                    if len(cells) < 2:
+                    if len(cells) < 3:
                         continue
 
                     link = cells[1].find('a')

{"golden_diff": "diff --git a/medusa/providers/torrent/html/beyondhd.py b/medusa/providers/torrent/html/beyondhd.py\n--- a/medusa/providers/torrent/html/beyondhd.py\n+++ b/medusa/providers/torrent/html/beyondhd.py\n@@ -121,7 +121,7 @@\n                 cells = result('td')\n \n                 try:\n-                    if len(cells) < 2:\n+                    if len(cells) < 3:\n                         continue\n \n                     link = cells[1].find('a')\n", "issue": "Error message \"Failed parsing provider\" & \"list index out of range\"\n**Describe the bug**\r\nError message:\r\n\r\n`2020-12-05 07:52:25 ERROR    SEARCHQUEUE-BACKLOG-260586 :: [Beyond-HD] :: [ce68da5] Failed parsing provider.\r\nTraceback (most recent call last):\r\n  File \"/Applications/Medusa/medusa/providers/torrent/html/beyondhd.py\", line 128, in parse\r\n    download_url = urljoin(self.url, cells[2].find('a')['href'])\r\nIndexError: list index out of range`\r\n\r\n**Medusa (please complete the following information):**\r\n - OS: macOS Catalina 10.15,.7\r\n - Branch: master\r\n - Commit: ce68da57b3878591f77c21bb2acf28e6a58269fa\r\n - Python version: 3.8.5\r\n - Database version: 44.17\r\n\r\n\r\n\n", "before_files": [{"content": "# coding=utf-8\n\n\"\"\"Provider code for Beyond-hd.\"\"\"\n\nfrom __future__ import unicode_literals\n\nimport logging\n\nfrom medusa import tv\nfrom medusa.bs4_parser import BS4Parser\nfrom medusa.helper.common import convert_size\nfrom medusa.logger.adapters.style import BraceAdapter\nfrom medusa.providers.torrent.torrent_provider import TorrentProvider\n\nfrom requests.compat import urljoin\n\nlog = BraceAdapter(logging.getLogger(__name__))\nlog.logger.addHandler(logging.NullHandler())\n\n\nclass BeyondHDProvider(TorrentProvider):\n    \"\"\"Beyond-hd Torrent provider.\"\"\"\n\n    def __init__(self):\n        \"\"\"Initialize the class.\"\"\"\n        super(BeyondHDProvider, self).__init__('Beyond-HD')\n\n        self.enable_cookies = True\n        self.cookies = ''\n        self.required_cookies = ('remember_web_[**long_hash**]',)\n\n        self.url = 'https://beyond-hd.me'\n        self.urls = {\n            'login': urljoin(self.url, 'login'),\n            'search': urljoin(self.url, 'torrents'),\n        }\n\n        # Proper Strings\n        self.proper_strings = ['PROPER', 'REPACK', 'REAL', 'RERIP']\n\n        # Miscellaneous Options\n\n        # Cache\n        self.cache = tv.Cache(self)\n\n    def search(self, search_strings, *args, **kwargs):\n        \"\"\"\n        Search a provider and parse the results.\n\n        :param search_strings: A dict with mode (key) and the search value (value)\n        :returns: A list of search results (structure)\n        \"\"\"\n        results = []\n        if not self.login():\n            return results\n\n        for mode in search_strings:\n            log.debug('Search mode: {0}', mode)\n\n            for search_string in search_strings[mode]:\n\n                search_params = {\n                    'categories[]': 2,\n                    'sorting': 'created_at',\n                    'qty': '100',\n                    'direction': 'desc',\n                    'doSearch': 'Search'\n                }\n\n                if mode != 'RSS':\n                    log.debug('Search string: {search}',\n                              {'search': search_string})\n                    search_params['search'] = search_string\n\n                if mode == 'season':\n                    search_params['pack'] = 1\n\n                response = self.session.get(self.urls['search'], params=search_params)\n                if not response or not response.text:\n                    log.debug('No data returned from provider')\n                    continue\n\n                results += self.parse(response.text, mode)\n\n        return results\n\n    def parse(self, data, mode):\n        \"\"\"\n        Parse search results for items.\n\n        :param data: The raw response from a search\n        :param mode: The current mode used to search, e.g. RSS\n\n        :return: A list of items found\n        \"\"\"\n        # Units\n        units = ['B', 'KIB', 'MIB', 'GIB', 'TIB', 'PIB']\n\n        items = []\n\n        with BS4Parser(data, 'html5lib') as html:\n            if html.find('div', class_='table-torrents'):\n                theme = 'modern'\n                torrent_table = html.find('div', class_='table-torrents').find('table')\n            else:\n                theme = 'classic'\n                torrent_table = html.find('div', class_='table-responsive').find('table')\n\n            torrent_rows = torrent_table('tr') if torrent_table else []\n            labels = [label.get_text(strip=True) for label in torrent_rows[0]('th')]\n            # For the classic theme, the tr don't match the td.\n            if theme == 'classic':\n                del labels[3]\n\n            # Continue only if one release is found\n            if len(torrent_rows) < 2:\n                log.debug('Data returned from provider does not contain any torrents')\n                return items\n\n            for result in torrent_rows[1:]:\n                cells = result('td')\n\n                try:\n                    if len(cells) < 2:\n                        continue\n\n                    link = cells[1].find('a')\n                    download_url = urljoin(self.url, cells[2].find('a')['href'])\n                    title = link.get_text(strip=True)\n                    if not all([title, download_url]):\n                        continue\n\n                    seeders = int(cells[labels.index('S')].find('span').get_text())\n                    leechers = int(cells[labels.index('L')].find('span').get_text())\n\n                    # Filter unseeded torrent\n                    if seeders < self.minseed:\n                        if mode != 'RSS':\n                            log.debug(\"Discarding torrent because it doesn't meet the\"\n                                      ' minimum seeders: {0}. Seeders: {1}',\n                                      title, seeders)\n                        continue\n\n                    torrent_size = cells[labels.index('Size')].find('span').get_text()\n                    size = convert_size(torrent_size, units=units) or -1\n\n                    pubdate_raw = cells[labels.index('Age')].find('span').get_text()\n                    pubdate = self.parse_pubdate(pubdate_raw, human_time=True)\n\n                    item = {\n                        'title': title,\n                        'link': download_url,\n                        'size': size,\n                        'seeders': seeders,\n                        'leechers': leechers,\n                        'pubdate': pubdate,\n                    }\n                    if mode != 'RSS':\n                        log.debug('Found result: {0} with {1} seeders and {2} leechers',\n                                  title, seeders, leechers)\n\n                    items.append(item)\n                except (AttributeError, TypeError, KeyError, ValueError, IndexError):\n                    log.exception('Failed parsing provider.')\n\n        return items\n\n    def login(self):\n        \"\"\"Login method used for logging in before doing search and torrent downloads.\"\"\"\n        return self.cookie_login('Login now')\n\n    def check_required_cookies(self):\n        \"\"\"\n        Check if we have the required cookies in the requests sessions object.\n\n        Meaning that we've already successfully authenticated once, and we don't need to go through this again.\n        Note! This doesn't mean the cookies are correct!\n        \"\"\"\n        return False\n\n\nprovider = BeyondHDProvider()\n", "path": "medusa/providers/torrent/html/beyondhd.py"}], "after_files": [{"content": "# coding=utf-8\n\n\"\"\"Provider code for Beyond-hd.\"\"\"\n\nfrom __future__ import unicode_literals\n\nimport logging\n\nfrom medusa import tv\nfrom medusa.bs4_parser import BS4Parser\nfrom medusa.helper.common import convert_size\nfrom medusa.logger.adapters.style import BraceAdapter\nfrom medusa.providers.torrent.torrent_provider import TorrentProvider\n\nfrom requests.compat import urljoin\n\nlog = BraceAdapter(logging.getLogger(__name__))\nlog.logger.addHandler(logging.NullHandler())\n\n\nclass BeyondHDProvider(TorrentProvider):\n    \"\"\"Beyond-hd Torrent provider.\"\"\"\n\n    def __init__(self):\n        \"\"\"Initialize the class.\"\"\"\n        super(BeyondHDProvider, self).__init__('Beyond-HD')\n\n        self.enable_cookies = True\n        self.cookies = ''\n        self.required_cookies = ('remember_web_[**long_hash**]',)\n\n        self.url = 'https://beyond-hd.me'\n        self.urls = {\n            'login': urljoin(self.url, 'login'),\n            'search': urljoin(self.url, 'torrents'),\n        }\n\n        # Proper Strings\n        self.proper_strings = ['PROPER', 'REPACK', 'REAL', 'RERIP']\n\n        # Miscellaneous Options\n\n        # Cache\n        self.cache = tv.Cache(self)\n\n    def search(self, search_strings, *args, **kwargs):\n        \"\"\"\n        Search a provider and parse the results.\n\n        :param search_strings: A dict with mode (key) and the search value (value)\n        :returns: A list of search results (structure)\n        \"\"\"\n        results = []\n        if not self.login():\n            return results\n\n        for mode in search_strings:\n            log.debug('Search mode: {0}', mode)\n\n            for search_string in search_strings[mode]:\n\n                search_params = {\n                    'categories[]': 2,\n                    'sorting': 'created_at',\n                    'qty': '100',\n                    'direction': 'desc',\n                    'doSearch': 'Search'\n                }\n\n                if mode != 'RSS':\n                    log.debug('Search string: {search}',\n                              {'search': search_string})\n                    search_params['search'] = search_string\n\n                if mode == 'season':\n                    search_params['pack'] = 1\n\n                response = self.session.get(self.urls['search'], params=search_params)\n                if not response or not response.text:\n                    log.debug('No data returned from provider')\n                    continue\n\n                results += self.parse(response.text, mode)\n\n        return results\n\n    def parse(self, data, mode):\n        \"\"\"\n        Parse search results for items.\n\n        :param data: The raw response from a search\n        :param mode: The current mode used to search, e.g. RSS\n\n        :return: A list of items found\n        \"\"\"\n        # Units\n        units = ['B', 'KIB', 'MIB', 'GIB', 'TIB', 'PIB']\n\n        items = []\n\n        with BS4Parser(data, 'html5lib') as html:\n            if html.find('div', class_='table-torrents'):\n                theme = 'modern'\n                torrent_table = html.find('div', class_='table-torrents').find('table')\n            else:\n                theme = 'classic'\n                torrent_table = html.find('div', class_='table-responsive').find('table')\n\n            torrent_rows = torrent_table('tr') if torrent_table else []\n            labels = [label.get_text(strip=True) for label in torrent_rows[0]('th')]\n            # For the classic theme, the tr don't match the td.\n            if theme == 'classic':\n                del labels[3]\n\n            # Continue only if one release is found\n            if len(torrent_rows) < 2:\n                log.debug('Data returned from provider does not contain any torrents')\n                return items\n\n            for result in torrent_rows[1:]:\n                cells = result('td')\n\n                try:\n                    if len(cells) < 3:\n                        continue\n\n                    link = cells[1].find('a')\n                    download_url = urljoin(self.url, cells[2].find('a')['href'])\n                    title = link.get_text(strip=True)\n                    if not all([title, download_url]):\n                        continue\n\n                    seeders = int(cells[labels.index('S')].find('span').get_text())\n                    leechers = int(cells[labels.index('L')].find('span').get_text())\n\n                    # Filter unseeded torrent\n                    if seeders < self.minseed:\n                        if mode != 'RSS':\n                            log.debug(\"Discarding torrent because it doesn't meet the\"\n                                      ' minimum seeders: {0}. Seeders: {1}',\n                                      title, seeders)\n                        continue\n\n                    torrent_size = cells[labels.index('Size')].find('span').get_text()\n                    size = convert_size(torrent_size, units=units) or -1\n\n                    pubdate_raw = cells[labels.index('Age')].find('span').get_text()\n                    pubdate = self.parse_pubdate(pubdate_raw, human_time=True)\n\n                    item = {\n                        'title': title,\n                        'link': download_url,\n                        'size': size,\n                        'seeders': seeders,\n                        'leechers': leechers,\n                        'pubdate': pubdate,\n                    }\n                    if mode != 'RSS':\n                        log.debug('Found result: {0} with {1} seeders and {2} leechers',\n                                  title, seeders, leechers)\n\n                    items.append(item)\n                except (AttributeError, TypeError, KeyError, ValueError, IndexError):\n                    log.exception('Failed parsing provider.')\n\n        return items\n\n    def login(self):\n        \"\"\"Login method used for logging in before doing search and torrent downloads.\"\"\"\n        return self.cookie_login('Login now')\n\n    def check_required_cookies(self):\n        \"\"\"\n        Check if we have the required cookies in the requests sessions object.\n\n        Meaning that we've already successfully authenticated once, and we don't need to go through this again.\n        Note! This doesn't mean the cookies are correct!\n        \"\"\"\n        return False\n\n\nprovider = BeyondHDProvider()\n", "path": "medusa/providers/torrent/html/beyondhd.py"}]}