b1bad7a518d5534e8159ef2b9b9135121acb473e
[plugin.video.netflix.git] / resources / lib / NetflixHttpSubRessourceHandler.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 # Module: NetflixHttpSubRessourceHandler
4 # Created on: 07.03.2017
5
6 from urllib2 import urlopen, URLError
7 from time import sleep
8
9 class NetflixHttpSubRessourceHandler:
10     """ Represents the callable internal server routes & translates/executes them to requests for Netflix"""
11
12     def __init__ (self, kodi_helper, netflix_session):
13         """Sets up credentials & video_list_cache cache
14         Assigns the netflix_session/kodi_helper instacnes
15         Does the initial login if we have user data
16
17         Parameters
18         ----------
19         kodi_helper : :obj:`KodiHelper`
20             instance of the KodiHelper class
21
22         netflix_session : :obj:`NetflixSession`
23             instance of the NetflixSession class
24         """
25         self.kodi_helper = kodi_helper
26         self.netflix_session = netflix_session
27         self.credentials = self.kodi_helper.get_credentials()
28         self.profiles = []
29         self.prefetch_login()
30         self.video_list_cache = {}
31         self.lolomo = None
32
33     def prefetch_login (self):
34         """Check if we have stored credentials.
35         If so, do the login before the user requests it
36         If that is done, we cache the profiles
37         """
38         if self._network_availble():
39             if self.credentials['email'] != '' and self.credentials['password'] != '':
40                 if self.netflix_session.is_logged_in(account=self.credentials):
41                     self.netflix_session.refresh_session_data(account=self.credentials)
42                     self.profiles = self.netflix_session.profiles
43                 else:
44                     self.netflix_session.login(account=self.credentials)
45                     self.profiles = self.netflix_session.profiles
46             else:
47                 self.profiles = []
48         else:
49             sleep(1)
50             self.prefetch_login()
51
52     def is_logged_in (self, params):
53         """Existing login proxy function
54
55         Parameters
56         ----------
57         params : :obj:`dict` of :obj:`str`
58             Request params
59
60         Returns
61         -------
62         :obj:`Requests.Response`
63             Response of the remote call
64         """
65         if self.credentials['email'] == '' or self.credentials['password'] == '':
66             return False
67         return self.netflix_session.is_logged_in(account=self.credentials)
68
69     def logout (self, params):
70         """Logout proxy function
71
72         Parameters
73         ----------
74         params : :obj:`dict` of :obj:`str`
75             Request params
76
77         Returns
78         -------
79         :obj:`Requests.Response`
80             Response of the remote call
81         """
82         self.profiles = []
83         self.credentials = {'email': '', 'password': ''}
84         self.lolomo = None
85         return self.netflix_session.logout()
86
87     def login (self, params):
88         """Logout proxy function
89
90         Parameters
91         ----------
92         params : :obj:`dict` of :obj:`str`
93             Request params
94
95         Returns
96         -------
97         :obj:`Requests.Response`
98             Response of the remote call
99         """
100         email = params.get('email', [''])[0]
101         password = params.get('password', [''])[0]
102         if email != '' and password != '':
103             self.credentials = {'email': email, 'password': password}
104             _ret = self.netflix_session.login(account=self.credentials)
105             self.profiles = self.netflix_session.profiles
106             return _ret
107         return None
108
109     def list_profiles (self, params):
110         """Returns the cached list of profiles
111
112         Parameters
113         ----------
114         params : :obj:`dict` of :obj:`str`
115             Request params
116
117         Returns
118         -------
119         :obj:`dict` of :obj:`str`
120             List of profiles
121         """
122         return self.profiles
123
124     def get_esn (self, params):
125         """ESN getter function
126
127         Parameters
128         ----------
129         params : :obj:`dict` of :obj:`str`
130             Request params
131
132         Returns
133         -------
134         :obj:`str`
135             Exracted ESN
136         """
137         return self.netflix_session.esn
138
139     def fetch_video_list_ids (self, params):
140         """Video list ids proxy function (caches video lists)
141
142         Parameters
143         ----------
144         params : :obj:`dict` of :obj:`str`
145             Request params
146
147         Returns
148         -------
149         :obj:`list`
150             Transformed response of the remote call
151         """
152         cached_list = self.video_list_cache.get(self.netflix_session.user_data['guid'], None)
153         if cached_list != None:
154             self.kodi_helper.log('Serving cached list for user: ' + self.netflix_session.user_data['guid'])
155             return cached_list
156         video_list_ids_raw = self.netflix_session.fetch_video_list_ids()
157
158         if 'error' in video_list_ids_raw:
159             return video_list_ids_raw
160         return self.netflix_session.parse_video_list_ids(response_data=video_list_ids_raw)
161
162     def fetch_video_list (self, params):
163         """Video list proxy function
164
165         Parameters
166         ----------
167         params : :obj:`dict` of :obj:`str`
168             Request params
169
170         Returns
171         -------
172         :obj:`list`
173             Transformed response of the remote call
174         """
175         list_id = params.get('list_id', [''])[0]
176         raw_video_list = self.netflix_session.fetch_video_list(list_id=list_id)
177         if 'error' in raw_video_list:
178             return raw_video_list
179         # parse the video list ids
180         if 'videos' in raw_video_list.get('value', {}).keys():
181             return self.netflix_session.parse_video_list(response_data=raw_video_list)
182         return []
183
184     def fetch_episodes_by_season (self, params):
185         """Episodes for season proxy function
186
187         Parameters
188         ----------
189         params : :obj:`dict` of :obj:`str`
190             Request params
191
192         Returns
193         -------
194         :obj:`list`
195             Transformed response of the remote call
196         """
197         raw_episode_list = self.netflix_session.fetch_episodes_by_season(season_id=params.get('season_id')[0])
198         if 'error' in raw_episode_list:
199             return raw_episode_list
200         return self.netflix_session.parse_episodes_by_season(response_data=raw_episode_list)
201
202     def fetch_seasons_for_show (self, params):
203         """Season for show proxy function
204
205         Parameters
206         ----------
207         params : :obj:`dict` of :obj:`str`
208             Request params
209
210         Returns
211         -------
212         :obj:`list`
213             Transformed response of the remote call
214         """
215         show_id = params.get('show_id', [''])[0]
216         raw_season_list = self.netflix_session.fetch_seasons_for_show(id=show_id)
217         if 'error' in raw_season_list:
218             return raw_season_list
219         # check if we have sesons, announced shows that are not available yet have none
220         if 'seasons' not in raw_season_list.get('value', {}):
221               return []
222         return self.netflix_session.parse_seasons(id=show_id, response_data=raw_season_list)
223
224     def rate_video (self, params):
225         """Video rating proxy function
226
227         Parameters
228         ----------
229         params : :obj:`dict` of :obj:`str`
230             Request params
231
232         Returns
233         -------
234         :obj:`Requests.Response`
235             Response of the remote call
236         """
237         video_id = params.get('video_id', [''])[0]
238         rating = params.get('rating', [''])[0]
239         return self.netflix_session.rate_video(video_id=video_id, rating=rating)
240
241     def remove_from_list (self, params):
242         """Remove from my list proxy function
243
244         Parameters
245         ----------
246         params : :obj:`dict` of :obj:`str`
247             Request params
248
249         Returns
250         -------
251         :obj:`Requests.Response`
252             Response of the remote call
253         """
254         video_id = params.get('video_id', [''])[0]
255         return self.netflix_session.remove_from_list(video_id=video_id)
256
257     def add_to_list (self, params):
258         """Add to my list proxy function
259
260         Parameters
261         ----------
262         params : :obj:`dict` of :obj:`str`
263             Request params
264
265         Returns
266         -------
267         :obj:`Requests.Response`
268             Response of the remote call
269         """
270         video_id = params.get('video_id', [''])[0]
271         return self.netflix_session.add_to_list(video_id=video_id)
272
273     def fetch_metadata (self, params):
274         """Metadata proxy function
275
276         Parameters
277         ----------
278         params : :obj:`dict` of :obj:`str`
279             Request params
280
281         Returns
282         -------
283         :obj:`Requests.Response`
284             Response of the remote call
285         """
286         video_id = params.get('video_id', [''])[0]
287         return self.netflix_session.fetch_metadata(id=video_id)
288
289     def switch_profile (self, params):
290         """Switch profile proxy function
291
292         Parameters
293         ----------
294         params : :obj:`dict` of :obj:`str`
295             Request params
296
297         Returns
298         -------
299         :obj:`Requests.Response`
300             Response of the remote call
301         """
302         profile_id = params.get('profile_id', [''])[0]
303         self.lolomo = None
304         return self.netflix_session.switch_profile(profile_id=profile_id, account=self.credentials)
305
306     def get_user_data (self, params):
307         """User data getter function
308
309         Parameters
310         ----------
311         params : :obj:`dict` of :obj:`str`
312             Request params
313
314         Returns
315         -------
316         :obj:`str`
317             Exracted User Data
318         """
319         return self.netflix_session.user_data
320
321     def search (self, params):
322         """Search proxy function
323
324         Parameters
325         ----------
326         params : :obj:`dict` of :obj:`str`
327             Request params
328
329         Returns
330         -------
331         :obj:`list`
332             Transformed response of the remote call
333         """
334         term = params.get('term', [''])[0]
335         has_search_results = False
336         raw_search_results = self.netflix_session.fetch_search_results(search_str=term)
337         # check for any errors
338         if 'error' in raw_search_results:
339             return raw_search_results
340
341         # determine if we found something
342         if 'search' in raw_search_results['value']:
343             for key in raw_search_results['value']['search'].keys():
344                 if self.netflix_session._is_size_key(key=key) == False:
345                     has_search_results = raw_search_results['value']['search'][key]['titles']['length'] > 0
346                     if has_search_results == False:
347                         if raw_search_results['value']['search'][key].get('suggestions', False) != False:
348                             for entry in raw_search_results['value']['search'][key]['suggestions']:
349                                 if self.netflix_session._is_size_key(key=entry) == False:
350                                     if raw_search_results['value']['search'][key]['suggestions'][entry]['relatedvideos']['length'] > 0:
351                                         has_search_results = True
352
353         # display that we haven't found a thing
354         if has_search_results == False:
355             return []
356
357         # list the search results
358         search_results = self.netflix_session.parse_search_results(response_data=raw_search_results)
359         # add more menaingful data to the search results
360         raw_search_contents = self.netflix_session.fetch_video_list_information(video_ids=search_results.keys())
361         # check for any errors
362         if 'error' in raw_search_contents:
363             return raw_search_contents
364         return self.netflix_session.parse_video_list(response_data=raw_search_contents)
365
366     def _network_availble(self):
367         """Check if the network is available
368         Returns
369         -------
370         bool
371             Network can be accessed
372         """
373         try:
374             urlopen('http://216.58.192.142', timeout=1)
375             return True
376         except URLError as err:
377             return False