We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
TypeError: cafile must be None or a byte string?
### Before submitting your issue:

Enable debug logging in Medusa settings, reproduce the error (be sure to disable after the bug is fixed)

Branch/Commit: Latest (Saturday 29th Oct)
OS: Debian Linux (FeralHosting Seedbox)
What you did: Updated to the latest commit
What happened: Medusa won't run - spits out this log (below)
What you expected: For it to run
Logs:

```
 python ~/.sickrage/SickBeard.py -d -p 10101
Traceback (most recent call last):
  File "/media/sdq1/home/whipcracker/.sickrage/SickBeard.py", line 9, in <module>
    from start import Application
  File "/media/sdq1/home/whipcracker/.sickrage/start.py", line 104, in <module>
    from medusa.server.core import AppWebServer
  File "/media/sdq1/home/whipcracker/.sickrage/medusa/server/core.py", line 17, in <module>
    from .web import CalendarHandler, KeyHandler, LoginHandler, LogoutHandler
  File "/media/sdq1/home/whipcracker/.sickrage/medusa/server/web/__init__.py", line 7, in <module>
    from .home import Home, HomeAddShows, HomeChangeLog, HomeIRC, HomeNews, HomePostProcess
  File "/media/sdq1/home/whipcracker/.sickrage/medusa/server/web/home/__init__.py", line 4, in <module>
    from .add_shows import HomeAddShows
  File "/media/sdq1/home/whipcracker/.sickrage/medusa/server/web/home/add_shows.py", line 29, in <module>
    from ....show.recommendations.trakt import TraktPopular
  File "/media/sdq1/home/whipcracker/.sickrage/medusa/show/recommendations/trakt.py", line 170, in <module>
    tvdb_api_v2 = get_tvdbv2_api()
  File "/media/sdq1/home/whipcracker/.sickrage/medusa/show/recommendations/trakt.py", line 41, in get_tvdbv2_api
    access_token = auth_api.login_post(authentication_string)
  File "/media/sdq1/home/whipcracker/.sickrage/lib/tvdbapiv2/apis/authentication_api.py", line 124, in login_post
    callback=params.get('callback'))
  File "/media/sdq1/home/whipcracker/.sickrage/lib/tvdbapiv2/api_client.py", line 324, in call_api
    response_type, auth_settings, callback)
  File "/media/sdq1/home/whipcracker/.sickrage/lib/tvdbapiv2/api_client.py", line 150, in __call_api
    post_params=post_params, body=body)
  File "/media/sdq1/home/whipcracker/.sickrage/lib/tvdbapiv2/api_client.py", line 360, in request
    body=body)
  File "/media/sdq1/home/whipcracker/.sickrage/lib/tvdbapiv2/rest.py", line 208, in POST
    body=body)
  File "/media/sdq1/home/whipcracker/.sickrage/lib/tvdbapiv2/rest.py", line 143, in request
    headers=headers)
  File "/media/sdq1/home/whipcracker/.sickrage/lib/requests/packages/urllib3/request.py", line 73, in request
    **urlopen_kw)
  File "/media/sdq1/home/whipcracker/.sickrage/lib/requests/packages/urllib3/request.py", line 151, in request_encode_body
    return self.urlopen(method, url, **extra_kw)
  File "/media/sdq1/home/whipcracker/.sickrage/lib/requests/packages/urllib3/poolmanager.py", line 165, in urlopen
    response = conn.urlopen(method, u.request_uri, **kw)
  File "/media/sdq1/home/whipcracker/.sickrage/lib/requests/packages/urllib3/connectionpool.py", line 578, in urlopen
    chunked=chunked)
  File "/media/sdq1/home/whipcracker/.sickrage/lib/requests/packages/urllib3/connectionpool.py", line 351, in _make_request
    self._validate_conn(conn)
  File "/media/sdq1/home/whipcracker/.sickrage/lib/requests/packages/urllib3/connectionpool.py", line 814, in _validate_conn
    conn.connect()
  File "/media/sdq1/home/whipcracker/.sickrage/lib/requests/packages/urllib3/connection.py", line 289, in connect
    ssl_version=resolved_ssl_version)
  File "/media/sdq1/home/whipcracker/.sickrage/lib/requests/packages/urllib3/contrib/pyopenssl.py", line 328, in ssl_wrap_socket
    ctx.load_verify_locations(ca_certs, ca_cert_dir)
  File "/usr/lib/python2.7/dist-packages/OpenSSL/SSL.py", line 303, in load_verify_locations
    raise TypeError("cafile must be None or a byte string")
TypeError: cafile must be None or a byte string

```

I've tried deleting the folder and tried a new git clone, but I have the same issue. Never been a problem until the new update. Hope someone can help!


--- 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/show/recommendations/trakt.py`
Content:
```
1 # coding=utf-8
2 #
3 # This file is part of Medusa.
4 #
5 # Medusa is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # Medusa is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with Medusa. If not, see <http://www.gnu.org/licenses/>.
17 from __future__ import unicode_literals
18 
19 import medusa as app
20 import requests
21 from simpleanidb import Anidb
22 from traktor import (TokenExpiredException, TraktApi, TraktException)
23 from tvdbapiv2 import (ApiClient, AuthenticationApi, SeriesApi)
24 from .recommended import RecommendedShow
25 from ... import logger
26 from ...helper.common import try_int
27 from ...helper.exceptions import MultipleShowObjectsException, ex
28 from ...indexers.indexer_config import INDEXER_TVDBV2
29 
30 
31 def get_tvdbv2_api():
32     """Initiate the tvdb api v2."""
33     api_base_url = 'https://api.thetvdb.com'
34 
35     # client_id = 'username'  # (optional! Only required for the /user routes)
36     # client_secret = 'pass'  # (optional! Only required for the /user routes)
37     apikey = '0629B785CE550C8D'
38 
39     authentication_string = {'apikey': apikey, 'username': '', 'userpass': ''}
40     unauthenticated_client = ApiClient(api_base_url)
41     auth_api = AuthenticationApi(unauthenticated_client)
42     access_token = auth_api.login_post(authentication_string)
43     auth_client = ApiClient(api_base_url, 'Authorization', 'Bearer ' + access_token.token)
44     series_api = SeriesApi(auth_client)
45 
46     return series_api
47 
48 
49 class TraktPopular(object):
50     """This class retrieves a speficed recommended show list from Trakt.
51 
52     The list of returned shows is mapped to a RecommendedShow object
53     """
54 
55     def __init__(self):
56         """Initialize the trakt recommended list object."""
57         self.cache_subfolder = __name__.split('.')[-1] if '.' in __name__ else __name__
58         self.session = requests.Session()
59         self.recommender = "Trakt Popular"
60         self.default_img_src = 'trakt-default.png'
61         self.anidb = Anidb(cache_dir=app.CACHE_DIR)
62 
63     def _create_recommended_show(self, show_obj):
64         """Create the RecommendedShow object from the returned showobj."""
65         rec_show = RecommendedShow(self,
66                                    show_obj['show']['ids'], show_obj['show']['title'],
67                                    INDEXER_TVDBV2,  # indexer
68                                    show_obj['show']['ids']['tvdb'],
69                                    **{'rating': show_obj['show']['rating'],
70                                       'votes': try_int(show_obj['show']['votes'], '0'),
71                                       'image_href': 'http://www.trakt.tv/shows/{0}'.format(show_obj['show']['ids']['slug']),
72                                       # Adds like: {'tmdb': 62126, 'tvdb': 304219, 'trakt': 79382, 'imdb': 'tt3322314',
73                                       # 'tvrage': None, 'slug': 'marvel-s-luke-cage'}
74                                       'ids': show_obj['show']['ids']
75                                       }
76                                    )
77 
78         use_default = None
79         image = None
80         try:
81             image = tvdb_api_v2.series_id_images_query_get(show_obj['show']['ids']['tvdb'], key_type='poster').data[0].file_name
82         except Exception:
83             use_default = self.default_img_src
84             logger.log('Missing poster on TheTVDB for show %s' % (show_obj['show']['title']), logger.DEBUG)
85 
86         rec_show.cache_image('http://thetvdb.com/banners/{0}'.format(image), default=use_default)
87         # As the method below requires allot of resources, i've only enabled it when
88         # the shows language or country is 'jp' (japanese). Looks a litle bit akward,
89         # but alternative is allot of resource used
90         if 'jp' in [show_obj['show']['country'], show_obj['show']['language']]:
91             rec_show.check_if_anime(self.anidb, show_obj['show']['ids']['tvdb'])
92 
93         return rec_show
94 
95     @staticmethod
96     def fetch_and_refresh_token(trakt_api, path):
97         """Fetch shows from trakt and store the refresh token when needed."""
98         try:
99             library_shows = trakt_api.request(path) or []
100             if trakt_api.access_token_refreshed:
101                 app.TRAKT_ACCESS_TOKEN = trakt_api.access_token
102                 app.TRAKT_REFRESH_TOKEN = trakt_api.refresh_token
103         except TokenExpiredException:
104             app.TRAKT_ACCESS_TOKEN = ''
105             raise
106 
107         return library_shows
108 
109     def fetch_popular_shows(self, page_url=None, trakt_list=None):  # pylint: disable=too-many-nested-blocks,too-many-branches
110         """Get a list of popular shows from different Trakt lists based on a provided trakt_list.
111 
112         :param page_url: the page url opened to the base api url, for retreiving a specific list
113         :param trakt_list: a description of the trakt list
114         :return: A list of RecommendedShow objects, an empty list of none returned
115         :throw: ``Exception`` if an Exception is thrown not handled by the libtrats exceptions
116         """
117         trending_shows = []
118         removed_from_medusa = []
119 
120         # Create a trakt settings dict
121         trakt_settings = {'trakt_api_secret': app.TRAKT_API_SECRET, 'trakt_api_key': app.TRAKT_API_KEY,
122                           'trakt_access_token': app.TRAKT_ACCESS_TOKEN}
123 
124         trakt_api = TraktApi(timeout=app.TRAKT_TIMEOUT, ssl_verify=app.SSL_VERIFY, **trakt_settings)
125 
126         try:  # pylint: disable=too-many-nested-blocks
127             not_liked_show = ''
128             if app.TRAKT_ACCESS_TOKEN != '':
129                 library_shows = self.fetch_and_refresh_token(trakt_api, 'sync/watched/shows?extended=noseasons') + \
130                     self.fetch_and_refresh_token(trakt_api, 'sync/collection/shows?extended=full')
131 
132                 medusa_shows = [show.indexerid for show in app.showList if show.indexerid]
133                 removed_from_medusa = [lshow['show']['ids']['tvdb'] for lshow in library_shows if lshow['show']['ids']['tvdb'] not in medusa_shows]
134 
135                 if app.TRAKT_BLACKLIST_NAME is not None and app.TRAKT_BLACKLIST_NAME:
136                     not_liked_show = trakt_api.request('users/' + app.TRAKT_USERNAME + '/lists/' +
137                                                        app.TRAKT_BLACKLIST_NAME + '/items') or []
138                 else:
139                     logger.log('Trakt blacklist name is empty', logger.DEBUG)
140 
141             if trakt_list not in ['recommended', 'newshow', 'newseason']:
142                 limit_show = '?limit=' + str(100 + len(not_liked_show)) + '&'
143             else:
144                 limit_show = '?'
145 
146             shows = self.fetch_and_refresh_token(trakt_api, page_url + limit_show + 'extended=full,images') or []
147 
148             for show in shows:
149                 try:
150                     if 'show' not in show:
151                         show['show'] = show
152 
153                     if not_liked_show:
154                         if show['show']['ids']['tvdb'] not in (show['show']['ids']['tvdb']
155                                                                for show in not_liked_show if show['type'] == 'show'):
156                             trending_shows.append(self._create_recommended_show(show))
157                     else:
158                         trending_shows.append(self._create_recommended_show(show))
159 
160                 except MultipleShowObjectsException:
161                     continue
162 
163             blacklist = app.TRAKT_BLACKLIST_NAME not in ''
164 
165         except TraktException as e:
166             logger.log('Could not connect to Trakt service: %s' % ex(e), logger.WARNING)
167             raise
168 
169         return blacklist, trending_shows, removed_from_medusa
170 
171 tvdb_api_v2 = get_tvdbv2_api()
172
```
--- 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/show/recommendations/trakt.py b/medusa/show/recommendations/trakt.py
--- a/medusa/show/recommendations/trakt.py
+++ b/medusa/show/recommendations/trakt.py
@@ -59,6 +59,7 @@
         self.recommender = "Trakt Popular"
         self.default_img_src = 'trakt-default.png'
         self.anidb = Anidb(cache_dir=app.CACHE_DIR)
+        self.tvdb_api_v2 = get_tvdbv2_api()
 
     def _create_recommended_show(self, show_obj):
         """Create the RecommendedShow object from the returned showobj."""
@@ -78,7 +79,7 @@
         use_default = None
         image = None
         try:
-            image = tvdb_api_v2.series_id_images_query_get(show_obj['show']['ids']['tvdb'], key_type='poster').data[0].file_name
+            image = self.tvdb_api_v2.series_id_images_query_get(show_obj['show']['ids']['tvdb'], key_type='poster').data[0].file_name
         except Exception:
             use_default = self.default_img_src
             logger.log('Missing poster on TheTVDB for show %s' % (show_obj['show']['title']), logger.DEBUG)
@@ -167,5 +168,3 @@
             raise
 
         return blacklist, trending_shows, removed_from_medusa
-
-tvdb_api_v2 = get_tvdbv2_api()

{"golden_diff": "diff --git a/medusa/show/recommendations/trakt.py b/medusa/show/recommendations/trakt.py\n--- a/medusa/show/recommendations/trakt.py\n+++ b/medusa/show/recommendations/trakt.py\n@@ -59,6 +59,7 @@\n         self.recommender = \"Trakt Popular\"\n         self.default_img_src = 'trakt-default.png'\n         self.anidb = Anidb(cache_dir=app.CACHE_DIR)\n+        self.tvdb_api_v2 = get_tvdbv2_api()\n \n     def _create_recommended_show(self, show_obj):\n         \"\"\"Create the RecommendedShow object from the returned showobj.\"\"\"\n@@ -78,7 +79,7 @@\n         use_default = None\n         image = None\n         try:\n-            image = tvdb_api_v2.series_id_images_query_get(show_obj['show']['ids']['tvdb'], key_type='poster').data[0].file_name\n+            image = self.tvdb_api_v2.series_id_images_query_get(show_obj['show']['ids']['tvdb'], key_type='poster').data[0].file_name\n         except Exception:\n             use_default = self.default_img_src\n             logger.log('Missing poster on TheTVDB for show %s' % (show_obj['show']['title']), logger.DEBUG)\n@@ -167,5 +168,3 @@\n             raise\n \n         return blacklist, trending_shows, removed_from_medusa\n-\n-tvdb_api_v2 = get_tvdbv2_api()\n", "issue": "TypeError: cafile must be None or a byte string?\n### Before submitting your issue:\n\nEnable debug logging in Medusa settings, reproduce the error (be sure to disable after the bug is fixed)\n\nBranch/Commit: Latest (Saturday 29th Oct)\nOS: Debian Linux (FeralHosting Seedbox)\nWhat you did: Updated to the latest commit\nWhat happened: Medusa won't run - spits out this log (below)\nWhat you expected: For it to run\nLogs:\n\n```\n python ~/.sickrage/SickBeard.py -d -p 10101\nTraceback (most recent call last):\n  File \"/media/sdq1/home/whipcracker/.sickrage/SickBeard.py\", line 9, in <module>\n    from start import Application\n  File \"/media/sdq1/home/whipcracker/.sickrage/start.py\", line 104, in <module>\n    from medusa.server.core import AppWebServer\n  File \"/media/sdq1/home/whipcracker/.sickrage/medusa/server/core.py\", line 17, in <module>\n    from .web import CalendarHandler, KeyHandler, LoginHandler, LogoutHandler\n  File \"/media/sdq1/home/whipcracker/.sickrage/medusa/server/web/__init__.py\", line 7, in <module>\n    from .home import Home, HomeAddShows, HomeChangeLog, HomeIRC, HomeNews, HomePostProcess\n  File \"/media/sdq1/home/whipcracker/.sickrage/medusa/server/web/home/__init__.py\", line 4, in <module>\n    from .add_shows import HomeAddShows\n  File \"/media/sdq1/home/whipcracker/.sickrage/medusa/server/web/home/add_shows.py\", line 29, in <module>\n    from ....show.recommendations.trakt import TraktPopular\n  File \"/media/sdq1/home/whipcracker/.sickrage/medusa/show/recommendations/trakt.py\", line 170, in <module>\n    tvdb_api_v2 = get_tvdbv2_api()\n  File \"/media/sdq1/home/whipcracker/.sickrage/medusa/show/recommendations/trakt.py\", line 41, in get_tvdbv2_api\n    access_token = auth_api.login_post(authentication_string)\n  File \"/media/sdq1/home/whipcracker/.sickrage/lib/tvdbapiv2/apis/authentication_api.py\", line 124, in login_post\n    callback=params.get('callback'))\n  File \"/media/sdq1/home/whipcracker/.sickrage/lib/tvdbapiv2/api_client.py\", line 324, in call_api\n    response_type, auth_settings, callback)\n  File \"/media/sdq1/home/whipcracker/.sickrage/lib/tvdbapiv2/api_client.py\", line 150, in __call_api\n    post_params=post_params, body=body)\n  File \"/media/sdq1/home/whipcracker/.sickrage/lib/tvdbapiv2/api_client.py\", line 360, in request\n    body=body)\n  File \"/media/sdq1/home/whipcracker/.sickrage/lib/tvdbapiv2/rest.py\", line 208, in POST\n    body=body)\n  File \"/media/sdq1/home/whipcracker/.sickrage/lib/tvdbapiv2/rest.py\", line 143, in request\n    headers=headers)\n  File \"/media/sdq1/home/whipcracker/.sickrage/lib/requests/packages/urllib3/request.py\", line 73, in request\n    **urlopen_kw)\n  File \"/media/sdq1/home/whipcracker/.sickrage/lib/requests/packages/urllib3/request.py\", line 151, in request_encode_body\n    return self.urlopen(method, url, **extra_kw)\n  File \"/media/sdq1/home/whipcracker/.sickrage/lib/requests/packages/urllib3/poolmanager.py\", line 165, in urlopen\n    response = conn.urlopen(method, u.request_uri, **kw)\n  File \"/media/sdq1/home/whipcracker/.sickrage/lib/requests/packages/urllib3/connectionpool.py\", line 578, in urlopen\n    chunked=chunked)\n  File \"/media/sdq1/home/whipcracker/.sickrage/lib/requests/packages/urllib3/connectionpool.py\", line 351, in _make_request\n    self._validate_conn(conn)\n  File \"/media/sdq1/home/whipcracker/.sickrage/lib/requests/packages/urllib3/connectionpool.py\", line 814, in _validate_conn\n    conn.connect()\n  File \"/media/sdq1/home/whipcracker/.sickrage/lib/requests/packages/urllib3/connection.py\", line 289, in connect\n    ssl_version=resolved_ssl_version)\n  File \"/media/sdq1/home/whipcracker/.sickrage/lib/requests/packages/urllib3/contrib/pyopenssl.py\", line 328, in ssl_wrap_socket\n    ctx.load_verify_locations(ca_certs, ca_cert_dir)\n  File \"/usr/lib/python2.7/dist-packages/OpenSSL/SSL.py\", line 303, in load_verify_locations\n    raise TypeError(\"cafile must be None or a byte string\")\nTypeError: cafile must be None or a byte string\n\n```\n\nI've tried deleting the folder and tried a new git clone, but I have the same issue. Never been a problem until the new update. Hope someone can help!\n\n", "before_files": [{"content": "# coding=utf-8\n#\n# This file is part of Medusa.\n#\n# Medusa is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# Medusa is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with Medusa. If not, see <http://www.gnu.org/licenses/>.\nfrom __future__ import unicode_literals\n\nimport medusa as app\nimport requests\nfrom simpleanidb import Anidb\nfrom traktor import (TokenExpiredException, TraktApi, TraktException)\nfrom tvdbapiv2 import (ApiClient, AuthenticationApi, SeriesApi)\nfrom .recommended import RecommendedShow\nfrom ... import logger\nfrom ...helper.common import try_int\nfrom ...helper.exceptions import MultipleShowObjectsException, ex\nfrom ...indexers.indexer_config import INDEXER_TVDBV2\n\n\ndef get_tvdbv2_api():\n    \"\"\"Initiate the tvdb api v2.\"\"\"\n    api_base_url = 'https://api.thetvdb.com'\n\n    # client_id = 'username'  # (optional! Only required for the /user routes)\n    # client_secret = 'pass'  # (optional! Only required for the /user routes)\n    apikey = '0629B785CE550C8D'\n\n    authentication_string = {'apikey': apikey, 'username': '', 'userpass': ''}\n    unauthenticated_client = ApiClient(api_base_url)\n    auth_api = AuthenticationApi(unauthenticated_client)\n    access_token = auth_api.login_post(authentication_string)\n    auth_client = ApiClient(api_base_url, 'Authorization', 'Bearer ' + access_token.token)\n    series_api = SeriesApi(auth_client)\n\n    return series_api\n\n\nclass TraktPopular(object):\n    \"\"\"This class retrieves a speficed recommended show list from Trakt.\n\n    The list of returned shows is mapped to a RecommendedShow object\n    \"\"\"\n\n    def __init__(self):\n        \"\"\"Initialize the trakt recommended list object.\"\"\"\n        self.cache_subfolder = __name__.split('.')[-1] if '.' in __name__ else __name__\n        self.session = requests.Session()\n        self.recommender = \"Trakt Popular\"\n        self.default_img_src = 'trakt-default.png'\n        self.anidb = Anidb(cache_dir=app.CACHE_DIR)\n\n    def _create_recommended_show(self, show_obj):\n        \"\"\"Create the RecommendedShow object from the returned showobj.\"\"\"\n        rec_show = RecommendedShow(self,\n                                   show_obj['show']['ids'], show_obj['show']['title'],\n                                   INDEXER_TVDBV2,  # indexer\n                                   show_obj['show']['ids']['tvdb'],\n                                   **{'rating': show_obj['show']['rating'],\n                                      'votes': try_int(show_obj['show']['votes'], '0'),\n                                      'image_href': 'http://www.trakt.tv/shows/{0}'.format(show_obj['show']['ids']['slug']),\n                                      # Adds like: {'tmdb': 62126, 'tvdb': 304219, 'trakt': 79382, 'imdb': 'tt3322314',\n                                      # 'tvrage': None, 'slug': 'marvel-s-luke-cage'}\n                                      'ids': show_obj['show']['ids']\n                                      }\n                                   )\n\n        use_default = None\n        image = None\n        try:\n            image = tvdb_api_v2.series_id_images_query_get(show_obj['show']['ids']['tvdb'], key_type='poster').data[0].file_name\n        except Exception:\n            use_default = self.default_img_src\n            logger.log('Missing poster on TheTVDB for show %s' % (show_obj['show']['title']), logger.DEBUG)\n\n        rec_show.cache_image('http://thetvdb.com/banners/{0}'.format(image), default=use_default)\n        # As the method below requires allot of resources, i've only enabled it when\n        # the shows language or country is 'jp' (japanese). Looks a litle bit akward,\n        # but alternative is allot of resource used\n        if 'jp' in [show_obj['show']['country'], show_obj['show']['language']]:\n            rec_show.check_if_anime(self.anidb, show_obj['show']['ids']['tvdb'])\n\n        return rec_show\n\n    @staticmethod\n    def fetch_and_refresh_token(trakt_api, path):\n        \"\"\"Fetch shows from trakt and store the refresh token when needed.\"\"\"\n        try:\n            library_shows = trakt_api.request(path) or []\n            if trakt_api.access_token_refreshed:\n                app.TRAKT_ACCESS_TOKEN = trakt_api.access_token\n                app.TRAKT_REFRESH_TOKEN = trakt_api.refresh_token\n        except TokenExpiredException:\n            app.TRAKT_ACCESS_TOKEN = ''\n            raise\n\n        return library_shows\n\n    def fetch_popular_shows(self, page_url=None, trakt_list=None):  # pylint: disable=too-many-nested-blocks,too-many-branches\n        \"\"\"Get a list of popular shows from different Trakt lists based on a provided trakt_list.\n\n        :param page_url: the page url opened to the base api url, for retreiving a specific list\n        :param trakt_list: a description of the trakt list\n        :return: A list of RecommendedShow objects, an empty list of none returned\n        :throw: ``Exception`` if an Exception is thrown not handled by the libtrats exceptions\n        \"\"\"\n        trending_shows = []\n        removed_from_medusa = []\n\n        # Create a trakt settings dict\n        trakt_settings = {'trakt_api_secret': app.TRAKT_API_SECRET, 'trakt_api_key': app.TRAKT_API_KEY,\n                          'trakt_access_token': app.TRAKT_ACCESS_TOKEN}\n\n        trakt_api = TraktApi(timeout=app.TRAKT_TIMEOUT, ssl_verify=app.SSL_VERIFY, **trakt_settings)\n\n        try:  # pylint: disable=too-many-nested-blocks\n            not_liked_show = ''\n            if app.TRAKT_ACCESS_TOKEN != '':\n                library_shows = self.fetch_and_refresh_token(trakt_api, 'sync/watched/shows?extended=noseasons') + \\\n                    self.fetch_and_refresh_token(trakt_api, 'sync/collection/shows?extended=full')\n\n                medusa_shows = [show.indexerid for show in app.showList if show.indexerid]\n                removed_from_medusa = [lshow['show']['ids']['tvdb'] for lshow in library_shows if lshow['show']['ids']['tvdb'] not in medusa_shows]\n\n                if app.TRAKT_BLACKLIST_NAME is not None and app.TRAKT_BLACKLIST_NAME:\n                    not_liked_show = trakt_api.request('users/' + app.TRAKT_USERNAME + '/lists/' +\n                                                       app.TRAKT_BLACKLIST_NAME + '/items') or []\n                else:\n                    logger.log('Trakt blacklist name is empty', logger.DEBUG)\n\n            if trakt_list not in ['recommended', 'newshow', 'newseason']:\n                limit_show = '?limit=' + str(100 + len(not_liked_show)) + '&'\n            else:\n                limit_show = '?'\n\n            shows = self.fetch_and_refresh_token(trakt_api, page_url + limit_show + 'extended=full,images') or []\n\n            for show in shows:\n                try:\n                    if 'show' not in show:\n                        show['show'] = show\n\n                    if not_liked_show:\n                        if show['show']['ids']['tvdb'] not in (show['show']['ids']['tvdb']\n                                                               for show in not_liked_show if show['type'] == 'show'):\n                            trending_shows.append(self._create_recommended_show(show))\n                    else:\n                        trending_shows.append(self._create_recommended_show(show))\n\n                except MultipleShowObjectsException:\n                    continue\n\n            blacklist = app.TRAKT_BLACKLIST_NAME not in ''\n\n        except TraktException as e:\n            logger.log('Could not connect to Trakt service: %s' % ex(e), logger.WARNING)\n            raise\n\n        return blacklist, trending_shows, removed_from_medusa\n\ntvdb_api_v2 = get_tvdbv2_api()\n", "path": "medusa/show/recommendations/trakt.py"}], "after_files": [{"content": "# coding=utf-8\n#\n# This file is part of Medusa.\n#\n# Medusa is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# Medusa is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with Medusa. If not, see <http://www.gnu.org/licenses/>.\nfrom __future__ import unicode_literals\n\nimport medusa as app\nimport requests\nfrom simpleanidb import Anidb\nfrom traktor import (TokenExpiredException, TraktApi, TraktException)\nfrom tvdbapiv2 import (ApiClient, AuthenticationApi, SeriesApi)\nfrom .recommended import RecommendedShow\nfrom ... import logger\nfrom ...helper.common import try_int\nfrom ...helper.exceptions import MultipleShowObjectsException, ex\nfrom ...indexers.indexer_config import INDEXER_TVDBV2\n\n\ndef get_tvdbv2_api():\n    \"\"\"Initiate the tvdb api v2.\"\"\"\n    api_base_url = 'https://api.thetvdb.com'\n\n    # client_id = 'username'  # (optional! Only required for the /user routes)\n    # client_secret = 'pass'  # (optional! Only required for the /user routes)\n    apikey = '0629B785CE550C8D'\n\n    authentication_string = {'apikey': apikey, 'username': '', 'userpass': ''}\n    unauthenticated_client = ApiClient(api_base_url)\n    auth_api = AuthenticationApi(unauthenticated_client)\n    access_token = auth_api.login_post(authentication_string)\n    auth_client = ApiClient(api_base_url, 'Authorization', 'Bearer ' + access_token.token)\n    series_api = SeriesApi(auth_client)\n\n    return series_api\n\n\nclass TraktPopular(object):\n    \"\"\"This class retrieves a speficed recommended show list from Trakt.\n\n    The list of returned shows is mapped to a RecommendedShow object\n    \"\"\"\n\n    def __init__(self):\n        \"\"\"Initialize the trakt recommended list object.\"\"\"\n        self.cache_subfolder = __name__.split('.')[-1] if '.' in __name__ else __name__\n        self.session = requests.Session()\n        self.recommender = \"Trakt Popular\"\n        self.default_img_src = 'trakt-default.png'\n        self.anidb = Anidb(cache_dir=app.CACHE_DIR)\n        self.tvdb_api_v2 = get_tvdbv2_api()\n\n    def _create_recommended_show(self, show_obj):\n        \"\"\"Create the RecommendedShow object from the returned showobj.\"\"\"\n        rec_show = RecommendedShow(self,\n                                   show_obj['show']['ids'], show_obj['show']['title'],\n                                   INDEXER_TVDBV2,  # indexer\n                                   show_obj['show']['ids']['tvdb'],\n                                   **{'rating': show_obj['show']['rating'],\n                                      'votes': try_int(show_obj['show']['votes'], '0'),\n                                      'image_href': 'http://www.trakt.tv/shows/{0}'.format(show_obj['show']['ids']['slug']),\n                                      # Adds like: {'tmdb': 62126, 'tvdb': 304219, 'trakt': 79382, 'imdb': 'tt3322314',\n                                      # 'tvrage': None, 'slug': 'marvel-s-luke-cage'}\n                                      'ids': show_obj['show']['ids']\n                                      }\n                                   )\n\n        use_default = None\n        image = None\n        try:\n            image = self.tvdb_api_v2.series_id_images_query_get(show_obj['show']['ids']['tvdb'], key_type='poster').data[0].file_name\n        except Exception:\n            use_default = self.default_img_src\n            logger.log('Missing poster on TheTVDB for show %s' % (show_obj['show']['title']), logger.DEBUG)\n\n        rec_show.cache_image('http://thetvdb.com/banners/{0}'.format(image), default=use_default)\n        # As the method below requires allot of resources, i've only enabled it when\n        # the shows language or country is 'jp' (japanese). Looks a litle bit akward,\n        # but alternative is allot of resource used\n        if 'jp' in [show_obj['show']['country'], show_obj['show']['language']]:\n            rec_show.check_if_anime(self.anidb, show_obj['show']['ids']['tvdb'])\n\n        return rec_show\n\n    @staticmethod\n    def fetch_and_refresh_token(trakt_api, path):\n        \"\"\"Fetch shows from trakt and store the refresh token when needed.\"\"\"\n        try:\n            library_shows = trakt_api.request(path) or []\n            if trakt_api.access_token_refreshed:\n                app.TRAKT_ACCESS_TOKEN = trakt_api.access_token\n                app.TRAKT_REFRESH_TOKEN = trakt_api.refresh_token\n        except TokenExpiredException:\n            app.TRAKT_ACCESS_TOKEN = ''\n            raise\n\n        return library_shows\n\n    def fetch_popular_shows(self, page_url=None, trakt_list=None):  # pylint: disable=too-many-nested-blocks,too-many-branches\n        \"\"\"Get a list of popular shows from different Trakt lists based on a provided trakt_list.\n\n        :param page_url: the page url opened to the base api url, for retreiving a specific list\n        :param trakt_list: a description of the trakt list\n        :return: A list of RecommendedShow objects, an empty list of none returned\n        :throw: ``Exception`` if an Exception is thrown not handled by the libtrats exceptions\n        \"\"\"\n        trending_shows = []\n        removed_from_medusa = []\n\n        # Create a trakt settings dict\n        trakt_settings = {'trakt_api_secret': app.TRAKT_API_SECRET, 'trakt_api_key': app.TRAKT_API_KEY,\n                          'trakt_access_token': app.TRAKT_ACCESS_TOKEN}\n\n        trakt_api = TraktApi(timeout=app.TRAKT_TIMEOUT, ssl_verify=app.SSL_VERIFY, **trakt_settings)\n\n        try:  # pylint: disable=too-many-nested-blocks\n            not_liked_show = ''\n            if app.TRAKT_ACCESS_TOKEN != '':\n                library_shows = self.fetch_and_refresh_token(trakt_api, 'sync/watched/shows?extended=noseasons') + \\\n                    self.fetch_and_refresh_token(trakt_api, 'sync/collection/shows?extended=full')\n\n                medusa_shows = [show.indexerid for show in app.showList if show.indexerid]\n                removed_from_medusa = [lshow['show']['ids']['tvdb'] for lshow in library_shows if lshow['show']['ids']['tvdb'] not in medusa_shows]\n\n                if app.TRAKT_BLACKLIST_NAME is not None and app.TRAKT_BLACKLIST_NAME:\n                    not_liked_show = trakt_api.request('users/' + app.TRAKT_USERNAME + '/lists/' +\n                                                       app.TRAKT_BLACKLIST_NAME + '/items') or []\n                else:\n                    logger.log('Trakt blacklist name is empty', logger.DEBUG)\n\n            if trakt_list not in ['recommended', 'newshow', 'newseason']:\n                limit_show = '?limit=' + str(100 + len(not_liked_show)) + '&'\n            else:\n                limit_show = '?'\n\n            shows = self.fetch_and_refresh_token(trakt_api, page_url + limit_show + 'extended=full,images') or []\n\n            for show in shows:\n                try:\n                    if 'show' not in show:\n                        show['show'] = show\n\n                    if not_liked_show:\n                        if show['show']['ids']['tvdb'] not in (show['show']['ids']['tvdb']\n                                                               for show in not_liked_show if show['type'] == 'show'):\n                            trending_shows.append(self._create_recommended_show(show))\n                    else:\n                        trending_shows.append(self._create_recommended_show(show))\n\n                except MultipleShowObjectsException:\n                    continue\n\n            blacklist = app.TRAKT_BLACKLIST_NAME not in ''\n\n        except TraktException as e:\n            logger.log('Could not connect to Trakt service: %s' % ex(e), logger.WARNING)\n            raise\n\n        return blacklist, trending_shows, removed_from_medusa\n", "path": "medusa/show/recommendations/trakt.py"}]}