[MerlinEPGCenter] - implement workaround to fix zapping to channel when alternatives...
[enigma2-plugins.git] / mytube / src / MyTubeService.py
1 # -*- coding: iso-8859-1 -*-
2 from Tools.Log import Log
3
4 from __init__ import decrypt_block
5 from socket import gaierror, error
6 import os, httplib
7 from urllib import quote
8 from httplib import HTTPConnection, CannotSendRequest, BadStatusLine
9
10 HTTPConnection.debuglevel = 1
11
12 from Plugins.SystemPlugins.TubeLib.youtube.Base import buildYoutube, loadCredentials, saveCredentials
13 from Plugins.SystemPlugins.TubeLib.youtube.Search import Search
14 from Plugins.SystemPlugins.TubeLib.youtube.Videos import Videos
15 from Plugins.SystemPlugins.TubeLib.youtube.VideoCategories import VideoCategories
16 from Plugins.SystemPlugins.TubeLib.youtube.YoutubeAuth import YoutubeAuth
17
18 from Tools.Directories import resolveFilename, SCOPE_CONFIG
19
20 def validate_cert(cert, key):
21         buf = decrypt_block(cert[8:], key)
22         if buf is None:
23                 return None
24         return buf[36:107] + cert[139:196]
25
26 def get_rnd():
27         try:
28                 rnd = os.urandom(8)
29                 return rnd
30         except:
31                 return None
32
33 class GoogleSuggestions():
34         def __init__(self):
35                 self.hl = "en"
36                 self.conn = None
37
38         def prepareQuery(self):
39                 self.prepQuerry = "/complete/search?output=chrome&client=chrome&"
40                 if self.hl is not None:
41                         self.prepQuerry = self.prepQuerry + "hl=" + self.hl + "&"
42                 self.prepQuerry = self.prepQuerry + "jsonp=self.gotSuggestions&q="
43                 print "[MyTube - GoogleSuggestions] prepareQuery:",self.prepQuerry
44
45         def getSuggestions(self, queryString):
46                 self.prepareQuery()
47                 if queryString is not "":
48                         query = self.prepQuerry + quote(queryString)
49                         self.conn = HTTPConnection("google.com")
50                         try:
51                                 self.conn = HTTPConnection("google.com")
52                                 self.conn.request("GET", query, "", {"Accept-Encoding": "UTF-8"})
53                         except (CannotSendRequest, gaierror, error):
54                                 self.conn.close()
55                                 print "[MyTube - GoogleSuggestions] Can not send request for suggestions"
56                                 return None
57                         else:
58                                 try:
59                                         response = self.conn.getresponse()
60                                 except BadStatusLine:
61                                         self.conn.close()
62                                         print "[MyTube - GoogleSuggestions] Can not get a response from google"
63                                         return None
64                                 else:
65                                         if response.status == 200:
66                                                 data = response.read()
67                                                 header = response.getheader("Content-Type", "text/xml; charset=ISO-8859-1")
68                                                 charset = "ISO-8859-1"
69                                                 try:
70                                                         charset = header.split(";")[1].split("=")[1]
71                                                         print "[MyTube - GoogleSuggestions] Got charset %s" %charset
72                                                 except:
73                                                         print "[MyTube - GoogleSuggestions] No charset in Header, falling back to %s" %charset
74                                                 data = data.decode(charset).encode("utf-8")
75                                                 self.conn.close()
76                                                 return data
77                                         else:
78                                                 self.conn.close()
79                                                 return None
80                 else:
81                         return None
82
83 class MyTubePlayerService():
84         YT_CREDENTIALS_FILE = resolveFilename(SCOPE_CONFIG, "youtube-credentials-oauth2.json")
85
86         cached_auth_request = {}
87         current_auth_token = None
88         yt_service = None
89
90         def __init__(self):
91                 print "[MyTube] MyTubePlayerService - init"
92                 self.feedentries = []
93                 self.feed = None
94                 self.onReady = []
95                 self._ready = False
96                 self._youtube = None
97                 self._currentQuery = None
98                 self._categories = []
99                 self._categoriesQuery = None
100                 self._ytauth = None
101                 self._authenticated = False
102
103         def addReadyCallback(self, callback):
104                 self.onReady.append(callback)
105                 if self.ready:
106                         callback(self.ready)
107
108         def _onReady(self):
109                 Log.w()
110                 for fnc in self.onReady:
111                         fnc(self._ready)
112
113         def isReady(self):
114                 return self._ready
115
116         def setReady(self, ready):
117                 Log.w()
118                 self._ready = ready
119                 self._onReady()
120
121         ready = property(isReady, setReady)
122
123         def startService(self):
124                 print "[MyTube] MyTubePlayerService - startService"
125                 self._youtube = buildYoutube()
126                 self._authenticated = False
127                 self.loadCategories()
128                 self.setReady(True)
129
130         def startAuthenticatedService(self, userCodeCallback):
131                 credentials = loadCredentials(self.YT_CREDENTIALS_FILE)
132                 if not credentials or credentials.invalid:
133                         self.startAuthFlow(userCodeCallback)
134                 else:
135                         self._onCredentialsReady(credentials)
136
137         def startAuthFlow(self, userCodeCallback):
138                 Log.w()
139                 self._ytauth = YoutubeAuth()
140                 self._ytauth.onUserCodeReady.append(userCodeCallback)
141                 self._ytauth.onCredentialsReady.append(self._onCredentialsReady)
142                 self._ytauth.startAuthFlow()
143
144         def cancelAuthFlow(self):
145                 if self._ytauth:
146                         self._ytauth.cancelAuthFlow()
147
148         def _onCredentialsReady(self, credentials):
149                 saveCredentials(self.YT_CREDENTIALS_FILE, credentials)
150                 self._ytauth = None
151                 self._youtube = buildYoutube(credentials=credentials)
152                 self._authenticated = True
153                 self.loadCategories()
154                 self.setReady(True)
155
156         def stopService(self):
157                 self.onReady = []
158                 self.cancelAuthFlow()
159                 print "[MyTube] MyTubePlayerService - stopService"
160
161         def supportsSSL(self):
162                 return 'HTTPSConnection' in dir(httplib)
163
164         def is_auth(self):
165                 return self._authenticated
166
167         def getCategories(self):
168                 return self._categories
169
170         def loadCategories(self):
171                 categories = VideoCategories(self._youtube)
172                 self._categoriesQuery = categories.list(self._onCategoriesReady)
173
174         def _onCategoriesReady(self, success, data):
175                 if success:
176                         self._categories = data
177                 else:
178                         Log.w(data)
179
180         def getFeed(self, callback = None, errorback = None, chart=None, videoCategoryId=None, ids=[]):
181                 Log.i()
182                 self.feedentries = []
183                 self._currentQuery = Videos(self._youtube)
184                 return self._currentQuery.list(callback, chart=chart, videoCategoryId=videoCategoryId, ids=ids)
185
186         def search(self, searchTerm=None, startIndex=1, maxResults=50,
187                                         orderby=Search.ORDER_RELEVANCE, time='all_time',
188                                         lr="", categories="", relatedToVideoId=None,
189                                         safeSearch=Search.SAFE_SEARCH_NONE, channelId=None,
190                                         callback=None):
191                 Log.d()
192                 self._currentQuery = Search(self._youtube)
193                 return self._currentQuery.list(callback, searchTerm=searchTerm, order=orderby, maxResults=maxResults, relatedToVideoId=relatedToVideoId, channelId=channelId, safeSearch=safeSearch)
194
195         def SubscribeToUser(self, username):
196                 try:
197                         new_subscription = self.yt_service.AddSubscriptionToChannel(username_to_subscribe_to=username)
198         
199                         if isinstance(new_subscription, gdata.youtube.YouTubeSubscriptionEntry):
200                                 print '[MyTube] MyTubePlayerService: New subscription added'
201                                 return _('New subscription added')
202                         
203                         return _('Unknown error')
204                 except gdata.service.RequestError as req:
205                         return str('Error: ' + str(req[0]["body"]))
206                 except Exception as e:
207                         return str('Error: ' + e)
208         
209         def addToFavorites(self, video_id):
210                 try:
211                         video_entry = self.yt_service.GetYouTubeVideoEntry(video_id=video_id)
212                         response = self.yt_service.AddVideoEntryToFavorites(video_entry)
213                         
214                         # The response, if succesfully posted is a YouTubeVideoEntry
215                         if isinstance(response, gdata.youtube.YouTubeVideoEntry):
216                                 print '[MyTube] MyTubePlayerService: Video successfully added to favorites'
217                                 return _('Video successfully added to favorites')       
218         
219                         return _('Unknown error')
220                 except gdata.service.RequestError as req:
221                         return str('Error: ' + str(req[0]["body"]))
222                 except Exception as e:
223                         return str('Error: ' + e)
224         
225         def getTitle(self):
226                 return ""
227
228         def getEntries(self):
229                 return self.feedentries
230
231         def itemCount(self):
232                 return ""
233
234         def getTotalResults(self):
235                 return self._currentQuery and self._currentQuery.getTotalResults()
236
237         def hasNextPage(self):
238                 return self._currentQuery and self._currentQuery.hasNextPage()
239
240         def getNextPage(self):
241                 return self._currentQuery and self._currentQuery.nextPage()
242
243         def getCurrentPage(self):
244                 return 1
245
246 myTubeService = MyTubePlayerService()
247