2 from Plugins.Plugin import PluginDescriptor
3 from twisted.web.client import downloadPage
4 from enigma import loadPic
5 from Screens.Screen import Screen
6 from Components.ActionMap import ActionMap
7 from Components.Pixmap import Pixmap
8 from Components.Label import Label
9 from Components.ScrollLabel import ScrollLabel
10 from Components.Button import Button
11 from Components.AVSwitch import AVSwitch
12 from Components.MenuList import MenuList
13 from Components.Language import language
14 from Components.ProgressBar import ProgressBar
21 <screen name="OFDb" position="90,95" size="560,420" title="Internet Movie Database Details Plugin" >
22 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
23 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
24 <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
25 <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
26 <widget name="key_red" position="0,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#9f1313" transparent="1" />
27 <widget name="key_green" position="140,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
28 <widget name="key_yellow" position="280,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#a08500" transparent="1" />
29 <widget name="key_blue" position="420,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#18188b" transparent="1" />
30 <widget name="titellabel" position="10,40" size="330,45" valign="center" font="Regular;22"/>
31 <widget name="detailslabel" position="105,90" size="445,140" font="Regular;18" />
32 <widget name="castlabel" position="10,235" size="540,155" font="Regular;18" />
33 <widget name="extralabel" position="10,40" size="540,350" font="Regular;18" />
34 <widget name="ratinglabel" position="340,62" size="210,20" halign="center" font="Regular;18" foregroundColor="#f0b400"/>
35 <widget name="statusbar" position="10,404" size="540,16" font="Regular;16" foregroundColor="#cccccc" />
36 <widget name="poster" position="4,90" size="96,140" alphatest="on" />
37 <widget name="menu" position="10,115" size="540,275" zPosition="3" scrollbarMode="showOnDemand" />
38 <widget name="starsbg" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/OFDb/starsbar_empty.png" position="340,40" zPosition="0" size="210,21" transparent="1" alphatest="on" />
39 <widget name="stars" position="340,40" size="210,21" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/OFDb/starsbar_filled.png" transparent="1" />
42 def __init__(self, session, eventName, args = None):
44 Screen.__init__(self, session)
45 self.eventName = eventName
46 self.dictionary_init()
47 self["poster"] = Pixmap()
48 self["stars"] = ProgressBar()
49 self["starsbg"] = Pixmap()
51 self["starsbg"].hide()
53 self["titellabel"] = Label("The Internet Movie Database")
54 self["detailslabel"] = ScrollLabel("")
55 self["castlabel"] = ScrollLabel("")
56 self["extralabel"] = ScrollLabel("")
57 self["statusbar"] = Label("")
58 self["ratinglabel"] = Label("")
60 self["menu"] = MenuList(self.resultlist)
62 self["key_red"] = Button(self._("Exit"))
63 self["key_green"] = Button("")
64 self["key_yellow"] = Button("")
65 self["key_blue"] = Button("")
66 # 0 = multiple query selection menu page
68 # 2 = extra infos page
71 self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "MovieSelectionActions", "DirectionActions"],
73 "ok": self.showDetails,
75 "down": self.pageDown,
78 "green": self.showMenu,
79 "yellow": self.showDetails,
80 "blue": self.showExtras,
81 "showEventInfo": self.showDetails
86 def dictionary_init(self):
87 syslang = language.getLanguage()
88 if syslang.find("de") is -1:
89 self.OFDBlanguage = "" # set to empty ("") for english version
91 self.OFDBlanguage = "german." # it's a subdomain, so add a '.' at the end
95 self.dict[" as "]=" als "
96 self.dict["Ambiguous results"]="Kein eindeutiger Treffer"
97 self.dict["Please select the matching entry"]="Bitte passenden Eintrag auswählen"
98 self.dict["No OFDb match."]="Keine passenden Einträge gefunden."
99 self.dict["OFDb query failed!"]="OFDb-Query fehlgeschlagen!"
100 self.dict["No details found."]="Keine Details gefunden."
101 self.dict["no user rating yet"]="noch keine Nutzerwertung"
102 self.dict["Cast: "]="Darsteller: "
103 self.dict["No cast list found in the database."]="Keine Darstellerliste in der Datenbank gefunden."
104 self.dict["Exit"]="Beenden"
105 self.dict["Extra Info"]="Zusatzinfos"
106 self.dict["Title Menu"]="Titelauswahl"
108 self.htmltags = re.compile('<.*?>')
110 self.generalinfomask = re.compile(
111 '<title>OFDb - (?P<title>.*?)</title>.*?'
112 '(?P<g_original>Originaltitel):[\s\S]*?class=\"Daten\">(?P<original>.*?)</td>'
113 '(?:.*?(?P<g_country>Herstellungsland):[\s\S]*?class="Daten">(?P<country>.*?)(?:\.\.\.|</td>))*'
114 '(?:.*?(?P<g_year>Erscheinungsjahr):[\s\S]*?class="Daten">(?P<year>.*?)</td>)*'
115 '(?:.*?(?P<g_director>Regie):[\s\S]*?class="Daten">(?P<director>.*?)(?:\.\.\.|</td>))*'
118 def _(self, in_string):
119 out_string = in_string
120 if ((self.OFDBlanguage).find("german")) != -1:
121 out_string = self.dict.get(in_string, in_string)
124 def resetLabels(self):
125 self["detailslabel"].setText("")
126 self["ratinglabel"].setText("")
127 self["titellabel"].setText("")
128 self["castlabel"].setText("")
129 self["titellabel"].setText("")
130 self["extralabel"].setText("")
131 self.ratingstars = -1
135 self["menu"].instance.moveSelection(self["menu"].instance.moveUp)
137 self["castlabel"].pageUp()
138 self["detailslabel"].pageUp()
140 self["extralabel"].pageUp()
144 self["menu"].instance.moveSelection(self["menu"].instance.moveDown)
146 self["castlabel"].pageDown()
147 self["detailslabel"].pageDown()
149 self["extralabel"].pageDown()
152 if ( self.Page is 1 or self.Page is 2 ) and self.resultlist:
155 self["starsbg"].hide()
156 self["ratinglabel"].hide()
157 self["castlabel"].hide()
158 self["poster"].hide()
159 self["extralabel"].hide()
160 self["titellabel"].setText(self._("Ambiguous results"))
161 self["detailslabel"].setText(self._("Please select the matching entry"))
162 self["detailslabel"].show()
163 self["key_blue"].setText("")
164 self["key_green"].setText(self._("Title Menu"))
165 self["key_yellow"].setText(self._("Details"))
168 def showDetails(self):
169 self["ratinglabel"].show()
170 self["castlabel"].show()
171 self["detailslabel"].show()
173 if self.resultlist and self.Page == 0:
174 link = self["menu"].getCurrent()[1]
175 title = self["menu"].getCurrent()[0]
176 self["statusbar"].setText("Re-Query OFDb: "+title+"...")
177 localfile = "/home/root/ofdbquery2.html"
178 fetchurl = "http://www.ofdb.de/film/" + link
179 print "[OFDb] downloading query " + fetchurl + " to " + localfile
180 downloadPage(fetchurl,localfile).addCallback(self.OFDBquery2).addErrback(self.fetchFailed)
186 self["extralabel"].hide()
187 self["poster"].show()
188 if self.ratingstars > 0:
189 self["starsbg"].show()
191 self["stars"].setValue(self.ratingstars)
195 def showExtras(self):
197 self["extralabel"].show()
198 self["detailslabel"].hide()
199 self["castlabel"].hide()
200 self["poster"].hide()
202 self["starsbg"].hide()
203 self["ratinglabel"].hide()
208 if self.eventName is "":
209 s = self.session.nav.getCurrentService()
211 event = info.getEvent(0) # 0 = now, 1 = next
213 self.eventName = event.getEventName()
215 pos = self.eventName.index("(")
216 self.eventName=self.eventName[0:pos]
220 if self.eventName is not "":
221 self["statusbar"].setText("Query OFDb: " + self.eventName + "...")
223 self.eventName = urllib.quote(self.eventName)
225 self.eventName = urllib.quote(self.eventName.decode('utf8').encode('ascii','ignore'))
226 localfile = "/home/root/ofdbquery.html"
227 fetchurl = "http://www.ofdb.de/view.php?page=suchergebnis&Kat=DTitel&SText=" + self.eventName
228 print "[OFDb] Downloading Query " + fetchurl + " to " + localfile
229 downloadPage(fetchurl,localfile).addCallback(self.OFDBquery).addErrback(self.fetchFailed)
231 self["statusbar"].setText("Could't get Eventname -_-")
233 def fetchFailed(self,string):
234 print "[OFDb] fetch failed " + string
235 self["statusbar"].setText("OFDb Download failed -_-")
237 def html2utf8(self,in_html):
238 htmlentitynumbermask = re.compile('(&#(\d{1,5}?);)')
239 htmlentitynamemask = re.compile('(&(\D{1,5}?);)')
241 entities = htmlentitynamemask.finditer(in_html)
245 entitydict[x.group(1)] = x.group(2)
247 for key, name in entitydict.items():
248 entitydict[key] = htmlentitydefs.name2codepoint[name]
250 entities = htmlentitynumbermask.finditer(in_html)
253 entitydict[x.group(1)] = x.group(2)
255 for key, codepoint in entitydict.items():
256 in_html = in_html.replace(key, (unichr(int(codepoint)).encode('utf8')))
258 self.inhtml = in_html
260 def OFDBquery(self,string):
262 self["statusbar"].setText("OFDb Download completed")
264 self.html2utf8(open("/home/root/ofdbquery.html", "r").read())
266 self.generalinfos = self.generalinfomask.search(self.inhtml)
268 if self.generalinfos:
271 if re.search("<title>OFDb - Suchergebnis</title>", self.inhtml):
272 searchresultmask = re.compile("<br>(\d{1,3}\.) <a href=\"film/(.*?)\"(?:.*?)\)\">(.*?)</a>", re.DOTALL)
273 searchresults = searchresultmask.finditer(self.inhtml)
276 for x in searchresults:
277 self.resultlist.append((self.htmltags.sub('',x.group(3)), x.group(2)))
278 self["menu"].l.setList(self.resultlist)
279 if len(self.resultlist) == 1:
281 self["extralabel"].hide()
283 elif len(self.resultlist) > 1:
287 self["detailslabel"].setText(self._("No OFDb match."))
288 self["statusbar"].setText("No OFDb match")
290 self["detailslabel"].setText(self._("OFDb query failed!"))
292 def OFDBquery2(self,string):
293 self["statusbar"].setText("OFDb Re-Download completed")
294 self.html2utf8(open("/home/root/ofdbquery2.html", "r").read())
295 self.generalinfos = self.generalinfomask.search(self.inhtml)
301 Detailstext = self._("No details found.")
302 if self.generalinfos:
303 self["key_yellow"].setText(self._("Details"))
304 self["statusbar"].setText("OFDb Details parsed ^^")
306 Titeltext = self.generalinfos.group("title")
307 if len(Titeltext) > 57:
308 Titeltext = Titeltext[0:54] + "..."
309 self["titellabel"].setText(Titeltext)
313 genreblockmask = re.compile('Genre\(s\):(?:[\s\S]*?)class=\"Daten\">(.*?)</tr>', re.DOTALL)
314 genreblock = genreblockmask.findall(self.inhtml)
315 genremask = re.compile('\">(.*?)</a')
317 genres = genremask.finditer(genreblock[0])
319 Detailstext += "Genre: "
321 Detailstext += self.htmltags.sub('', x.group(1)) + " "
323 detailscategories = ["director", "year", "country", "original"]
325 for category in detailscategories:
326 if self.generalinfos.group('g_'+category):
327 Detailstext += "\n" + self.generalinfos.group('g_'+category) + ": " + self.htmltags.sub('', self.generalinfos.group(category).replace("<br>",' '))
329 self["detailslabel"].setText(Detailstext)
331 #if self.generalinfos.group("alternativ"):
332 #Detailstext += "\n" + self.generalinfos.group("g_alternativ") + ": " + self.htmltags.sub('',(self.generalinfos.group("alternativ").replace('\n','').replace("<br>",'\n').replace(" ",' ')))
334 ratingmask = re.compile('<td>[\s\S]*notenskala.*(?P<g_rating>Note: )(?P<rating>\d.\d{2,2})[\s\S]*</td>', re.DOTALL)
335 rating = ratingmask.search(self.inhtml)
336 Ratingtext = self._("no user rating yet")
338 Ratingtext = rating.group("g_rating") + rating.group("rating") + " / 10"
339 self.ratingstars = int(10*round(float(rating.group("rating")),1))
341 self["stars"].setValue(self.ratingstars)
342 self["starsbg"].show()
343 self["ratinglabel"].setText(Ratingtext)
345 castblockmask = re.compile('Darsteller:[\s\S]*?class=\"Daten\">(.*?)(?:\.\.\.|\xbb)', re.DOTALL)
346 castblock = castblockmask.findall(self.inhtml)
347 castmask = re.compile('\">(.*?)</a')
350 cast = castmask.finditer(castblock[0])
353 Casttext += "\n" + self.htmltags.sub('', x.group(1))
354 if Casttext is not "":
355 Casttext = self._("Cast: ") + Casttext
357 Casttext = self._("No cast list found in the database.")
358 self["castlabel"].setText(Casttext)
361 postermask = re.compile('<img src=\"(http://img.ofdb.de/film.*?)\" alt', re.DOTALL)
362 posterurl = postermask.search(self.inhtml).group(1)
363 if posterurl.find("jpg") > 0:
364 self["statusbar"].setText("Downloading Movie Poster: "+posterurl+"...")
365 localfile = "/home/root/poster.jpg"
366 print "[OFDb] downloading poster " + posterurl + " to " + localfile
367 downloadPage(posterurl,localfile).addCallback(self.OFDBPoster).addErrback(self.fetchFailed)
369 self.OFDBPoster("kein Poster")
371 self["detailslabel"].setText(Detailstext)
373 def OFDBPoster(self,string):
374 self["statusbar"].setText("OFDb Details parsed ^^")
376 filename = "/home/root/poster.jpg"
378 filename = "/usr/lib/enigma2/python/Plugins/Extensions/OFDb/no_poster.png"
379 pixmap = loadPic(filename, 96,140, AVSwitch().getAspectRatioSetting()/2,1,0,0)
380 if pixmap is not None:
381 self["poster"].instance.setPixmap(pixmap.__deref__())
382 self["poster"].show()
384 def createSummary(self):
387 class OFDbLCDScreen(Screen):
389 <screen position="0,0" size="132,64" title="OFDb Plugin">
390 <widget name="headline" position="4,0" size="128,22" font="Regular;20"/>
391 <widget source="session.Event_Now" render="Label" position="6,26" size="120,34" font="Regular;14" >
392 <convert type="EventName">Name</convert>
396 def __init__(self, session, parent):
397 Screen.__init__(self, session)
398 self["headline"] = Label("OFDb Plugin")
400 def main(session, eventName="", **kwargs):
401 session.open(OFDB, eventName)
403 def Plugins(**kwargs):
405 wherelist = [PluginDescriptor.WHERE_EVENTINFO, PluginDescriptor.WHERE_PLUGINMENU]
406 return PluginDescriptor(name="OFDb Details",
407 description=_("Query details from the Online-Filmdatenbank"),
411 except AttributeError:
412 wherelist = [PluginDescriptor.WHERE_EXTENSIONSMENU, PluginDescriptor.WHERE_PLUGINMENU]
413 return PluginDescriptor(name="OFDb Details",
414 description=_("Query details from the Online-Filmdatenbank"),