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