Extensions/Mytube:MyTubeService.py
[enigma2-plugins.git] / mytube / src / MyTubeService.py
1 # -*- coding: iso-8859-1 -*-
2 from __init__ import _
3 import gdata.youtube
4 import gdata.youtube.service
5 from gdata.service import BadAuthentication
6 from Tools.LoadPixmap import LoadPixmap
7 from Components.config import config, Config, ConfigSelection, ConfigText, getConfigListEntry, ConfigSubsection, ConfigYesNo, ConfigIP, ConfigNumber
8 from Components.ConfigList import ConfigListScreen
9 from Components.config import KEY_DELETE, KEY_BACKSPACE, KEY_LEFT, KEY_RIGHT, KEY_HOME, KEY_END, KEY_TOGGLEOW, KEY_ASCII, KEY_TIMEOUT
10
11 from twisted.web import client
12 from twisted.internet import reactor
13 from urllib2 import Request, URLError, HTTPError, urlopen as urlopen2
14 from socket import gaierror,error
15 import re, os, sys, socket
16 import urllib
17 from urllib import FancyURLopener, quote
18 import cookielib
19 from httplib import HTTPConnection,CannotSendRequest,BadStatusLine,HTTPException
20 HTTPConnection.debuglevel = 1
21
22 std_headers = {
23         'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2',
24         'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
25         'Accept': 'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5',
26         'Accept-Language': 'en-us,en;q=0.5',
27 }
28
29 #config.plugins.mytube = ConfigSubsection()
30 #config.plugins.mytube.general = ConfigSubsection()
31 #config.plugins.mytube.general.useHTTPProxy = ConfigYesNo(default = False)
32 #config.plugins.mytube.general.ProxyIP = ConfigIP(default=[0,0,0,0])
33 #config.plugins.mytube.general.ProxyPort = ConfigNumber(default=8080)
34
35 class MyOpener(FancyURLopener):
36         version = 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.12) Gecko/20070731 Ubuntu/dapper-security Firefox/1.5.0.12'
37
38
39 class GoogleSuggestions():
40         def __init__(self, callback, ds = None, json = None, hl = None):
41                 self.callback = callback
42                 self.conn = HTTPConnection("google.com")
43                 self.prepQuerry = "/complete/search?"
44                 if ds is not None:
45                         self.prepQuerry = self.prepQuerry + "ds=" + ds + "&"
46                 if json is not None:
47                         self.prepQuerry = self.prepQuerry + "json=" + json + "&"
48                 if hl is not None:
49                         self.prepQuerry = self.prepQuerry + "hl=" + hl + "&"
50                 self.prepQuerry = self.prepQuerry + "jsonp=self.gotSuggestions&q="
51
52         def gotSuggestions(self, suggestslist):
53                 self.callback(suggestslist)
54
55         def getSuggestions(self, querryString):
56                 if querryString is not "":
57                         querry = self.prepQuerry + quote(querryString)
58                         try:
59                                 self.conn.request("GET", querry)
60                         except (CannotSendRequest, gaierror, error):
61                                 print "[YTB] Can not send request for suggestions"
62                                 self.callback(None)
63                         else:
64                                 try:
65                                         response = self.conn.getresponse()
66                                 except BadStatusLine:
67                                         print "[YTB] Can not get a response from google"
68                                         self.callback(None)
69                                 else:
70                                         if response.status == 200:
71                                                 data = response.read()
72                                                 exec data
73                                         else:
74                                                 self.callback(None)
75                         self.conn.close()
76                 else:
77                         self.callback(None)
78
79
80 class MyTubeFeedEntry():
81         def __init__(self, feed, entry, favoritesFeed = False):
82                 self.feed = feed
83                 self.entry = entry
84                 self.favoritesFeed = favoritesFeed
85                 self.thumbnail = {}
86                 self.myopener = MyOpener()
87                 urllib.urlopen = MyOpener().open
88                 """if config.plugins.mytube.general.useHTTPProxy.value is True:
89                         proxy = {'http': 'http://'+str(config.plugins.mytube.general.ProxyIP.getText())+':'+str(config.plugins.mytube.general.ProxyPort.value)}
90                         self.myopener = MyOpener(proxies=proxy)
91                         urllib.urlopen = MyOpener(proxies=proxy).open
92                 else:
93                         self.myopener = MyOpener()
94                         urllib.urlopen = MyOpener().open"""
95                 
96         def isPlaylistEntry(self):
97                 return False
98
99         def getTubeId(self):
100                 #print "[MyTubeFeedEntry] getTubeId"
101                 ret = None
102                 if self.entry.media.player:
103                         ret = self.entry.media.player.url.split("=").pop()
104                 return ret
105
106         def getTitle(self):
107                 #print "[MyTubeFeedEntry] getTitle",self.entry.media.title.text
108                 return self.entry.media.title.text
109
110         def getDescription(self):
111                 #print "[MyTubeFeedEntry] getDescription"
112                 if self.entry.media is not None and self.entry.media.description is not None:
113                         return self.entry.media.description.text
114                 return "not vailable"
115
116         def getThumbnailUrl(self, index = 0):
117                 #print "[MyTubeFeedEntry] getThumbnailUrl"
118                 if index < len(self.entry.media.thumbnail):
119                         return self.entry.media.thumbnail[index].url
120                 return None
121
122         def getPublishedDate(self):
123                 if self.entry.published is not None:
124                         return self.entry.published.text
125                 return "unknown"
126
127         def getViews(self):
128                 if self.entry.statistics is not None:
129                         return self.entry.statistics.view_count
130                 return "not available"
131         
132         def getDuration(self):
133                 if self.entry.media is not None and self.entry.media.duration is not None:
134                         return self.entry.media.duration.seconds
135                 else:
136                         return 0
137
138         def getRatingAverage(self):
139                 if self.entry.rating is not None:
140                         return self.entry.rating.average
141                 return 0
142
143
144         def getNumRaters(self):
145                 if self.entry.rating is not None:
146                         return self.entry.rating.num_raters
147                 return ""       
148
149         def getAuthor(self):
150                 authors = []
151                 for author in self.entry.author:
152                         authors.append(author.name.text)
153                 author = ", ".join(authors)
154                 return author
155
156         def PrintEntryDetails(self):
157                 EntryDetails = { 'Title': None, 'TubeID': None, 'Published': None, 'Published': None, 'Description': None, 'Category': None, 'Tags': None, 'Duration': None, 'Views': None, 'Rating': None, 'Thumbnails': None}
158                 EntryDetails['Title'] = self.entry.media.title.text
159                 EntryDetails['TubeID'] = self.getTubeId()
160                 EntryDetails['Description'] = self.getDescription()
161                 EntryDetails['Category'] = self.entry.media.category[0].text
162                 EntryDetails['Tags'] = self.entry.media.keywords.text
163                 EntryDetails['Published'] = self.getPublishedDate()
164                 EntryDetails['Views'] = self.getViews()
165                 EntryDetails['Duration'] = self.getDuration()
166                 EntryDetails['Rating'] = self.getNumRaters()
167                 EntryDetails['RatingAverage'] = self.getRatingAverage()
168                 EntryDetails['Author'] = self.getAuthor()
169                 # show thumbnails
170                 list = []
171                 for thumbnail in self.entry.media.thumbnail:
172                         print 'Thumbnail url: %s' % thumbnail.url
173                         list.append(str(thumbnail.url))
174                 EntryDetails['Thumbnails'] = list
175                 #print EntryDetails
176                 return EntryDetails
177
178
179         def getVideoUrl(self):
180                 mrl = None
181                 isHDAvailable = False
182                 video_id = str(self.getTubeId())
183                 watch_url = "http://www.youtube.com/watch?v=" + video_id
184                 watchrequest = Request(watch_url, None, std_headers)
185                 try:
186                         print "trying to find out if a HD Stream is available"
187                         watchvideopage = urlopen2(watchrequest).read()
188                 except (urllib2.URLError, httplib.HTTPException, socket.error), err:
189                         print "[MyTube] Error: Unable to retrieve watchpage"
190                         print "[MyTube] Error code: ", str(err)
191                         print "[MyTube] No valid mp4-url found"
192                         return mrl
193
194                 if "isHDAvailable = true" in watchvideopage:
195                         isHDAvailable = True
196                         print "HD AVAILABLE"
197                 else:
198                         print "HD Stream NOT AVAILABLE"
199
200                 # Get video info
201                 info_url = 'http://www.youtube.com/get_video_info?&video_id=%s&el=detailpage&ps=default&eurl=&gl=US&hl=en' % video_id
202                 inforequest = Request(info_url, None, std_headers)
203                 try:
204                         print "getting video_info_webpage",info_url
205                         infopage = urlopen2(inforequest).read()
206                 except (urllib2.URLError, httplib.HTTPException, socket.error), err:
207                         print "[MyTube] Error: Unable to retrieve infopage"
208                         print "[MyTube] Error code: ", str(err)
209                         print "[MyTube] No valid mp4-url found"
210                         return mrl
211
212                 mobj = re.search(r'(?m)&token=([^&]+)(?:&|$)', infopage)
213                 if mobj is None:
214                         # was there an error ?
215                         mobj = re.search(r'(?m)&reason=([^&]+)(?:&|$)', infopage)
216                         if mobj is None:
217                                 print 'ERROR: unable to extract "t" parameter for unknown reason'
218                         else:
219                                 reason = urllib.unquote_plus(mobj.group(1))
220                                 print 'ERROR: YouTube said: %s' % reason.decode('utf-8')
221                         return mrl
222         
223                 token = urllib.unquote(mobj.group(1))
224                 myurl = 'http://www.youtube.com/get_video?video_id=%s&t=%s&eurl=&el=detailpage&ps=default&gl=US&hl=en' % (video_id, token)
225                 if isHDAvailable is True:
226                         mrl = '%s&fmt=%s' % (myurl, '22')
227                         print "[MyTube] GOT HD URL: ", mrl
228                 else:
229                         mrl = '%s&fmt=%s' % (myurl, '18')
230                         print "[MyTube] GOT SD URL: ", mrl
231
232                 return mrl
233
234         def getRelatedVideos(self):
235                 print "[MyTubeFeedEntry] getResponseVideos()"
236                 for link in self.entry.link:
237                         #print "Related link: ", link.rel.endswith
238                         if link.rel.endswith("video.related"):
239                                 print "Found Related: ", link.href
240                                 return link.href
241
242         def getResponseVideos(self):
243                 print "[MyTubeFeedEntry] getResponseVideos()"
244                 for link in self.entry.link:
245                         #print "Responses link: ", link.rel.endswith
246                         if link.rel.endswith("video.responses"):
247                                 print "Found Responses: ", link.href
248                                 return link.href
249
250 class MyTubePlayerService():
251 #       Do not change the client_id and developer_key in the login-section!
252 #       ClientId: ytapi-dream-MyTubePlayer-i0kqrebg-0
253 #       DeveloperKey: AI39si4AjyvU8GoJGncYzmqMCwelUnqjEMWTFCcUtK-VUzvWygvwPO-sadNwW5tNj9DDCHju3nnJEPvFy4WZZ6hzFYCx8rJ6Mw
254         def __init__(self):
255                 print "[MyTube] MyTubePlayerService - init"
256                 self.feedentries = []
257                 self.feed = None
258                 
259         def startService(self):
260                 print "[MyTube] MyTubePlayerService - startService"
261                 self.yt_service = gdata.youtube.service.YouTubeService()
262                 self.yt_service.developer_key = 'AI39si4AjyvU8GoJGncYzmqMCwelUnqjEMWTFCcUtK-VUzvWygvwPO-sadNwW5tNj9DDCHju3nnJEPvFy4WZZ6hzFYCx8rJ6Mw'
263                 self.yt_service.client_id = 'ytapi-dream-MyTubePlayer-i0kqrebg-0'
264                 self.loggedIn = False
265                 #os.environ['http_proxy'] = 'http://169.229.50.12:3128'
266                 #proxy = os.environ.get('http_proxy')
267                 #print "FOUND ENV PROXY-->",proxy
268                 #for a in os.environ.keys():
269                 #       print a
270
271         def stopService(self):
272                 print "[MyTube] MyTubePlayerService - stopService"
273                 del self.ytService
274                 self.loggedIn = False
275
276         def isLoggedIn(self):
277                 return self.loggedIn
278
279         def getFeed(self, url):
280                 print "[MyTube] MyTubePlayerService - getFeed:",url
281                 self.feedentries = []
282                 self.feed = self.yt_service.GetYouTubeVideoFeed(url)
283                 for entry in self.feed.entry:
284                         MyFeedEntry = MyTubeFeedEntry(self, entry)
285                         self.feedentries.append(MyFeedEntry)
286                 return self.feed                        
287
288         def search(self, searchTerms, startIndex = 1, maxResults = 25,
289                                         orderby = "relevance", racy = "include", 
290                                         author = "", lr = "", categories = "", sortOrder = "ascending"):
291                 print "[MyTube] MyTubePlayerService - search()"
292                 self.feedentries = []
293                 query = gdata.youtube.service.YouTubeVideoQuery()
294                 query.vq = searchTerms
295                 query.orderby = orderby
296                 query.racy = racy
297                 query.sortorder = sortOrder
298                 if lr is not None:
299                         query.lr = lr
300                 if categories[0] is not None:
301                         query.categories = categories
302                 query.start_index = startIndex
303                 query.max_results = maxResults
304                 try:
305                         feed = self.yt_service.YouTubeQuery(query)
306                 except gaierror:
307                         feed = None
308                 if feed is not None:
309                         self.feed = feed
310                         for entry in self.feed.entry:
311                                 MyFeedEntry = MyTubeFeedEntry(self, entry)
312                                 self.feedentries.append(MyFeedEntry)
313                 return self.feed                
314
315         def getTitle(self):
316                 return self.feed.title.text
317
318         def getEntries(self):
319                 return self.feedentries
320
321         def itemCount(self):
322                 return self.feed.items_per_page.text
323
324         def getTotalResults(self):
325                 return self.feed.total_results.text
326         
327         def getNextFeedEntriesURL(self):
328                 for link in self.feed.link:
329                         if link.rel == "next":
330                                 return link.href
331                 return None
332
333
334 myTubeService = MyTubePlayerService()