SeriesPlugin 1.0: First public version
[enigma2-plugins.git] / seriesplugin / src / identifiers / Wunschliste.py
1 # by betonme @2012
2
3 # Imports
4 from Components.config import config
5
6 from Tools.BoundFunction import boundFunction
7
8 from urllib import urlencode
9
10 from HTMLParser import HTMLParser
11
12 from datetime import datetime
13
14 import re
15 from sys import maxint
16
17 # Internal
18 from Plugins.Extensions.SeriesPlugin.IdentifierBase import IdentifierBase
19 from Plugins.Extensions.SeriesPlugin.Channels import compareChannels
20 from Plugins.Extensions.SeriesPlugin.Logger import splog
21
22 from iso8601 import parse_date
23
24 # Constants
25 SERIESLISTURL     = "http://www.wunschliste.de/ajax/search_dropdown.pl?"
26 EPISODEIDURLPRINT = "http://www.wunschliste.de/epg_print.pl?"
27
28 # (Season.Episode) - EpisodeTitle
29 # (21.84) Folge 4985
30 # (105) Folge 105
31 # (4.11/4.11) Mama ist die Beste/Rund um die Uhr
32 # Galileo: Die schaerfste Chili der Welt
33 # Galileo: Jumbo auf Achse: Muelltonnenkoch
34 # Gute Zeiten, schlechte Zeiten: Folgen 4985 - 4988 (21.84) - Sa 05.05., 11.00:00 Uhr / RTL
35 #CompiledRegexpPrintTitle = re.compile( '(\(.*\) )?(.+)')
36
37 CompiledRegexpEpisode = re.compile( '((\d+)[\.x])?(\d+)')
38
39 class WLPrintParser(HTMLParser):
40         def __init__(self):
41                 HTMLParser.__init__(self)
42                 self.tr= False
43                 self.td= False
44                 self.data = []
45                 self.list = []
46
47         def handle_starttag(self, tag, attributes):
48                 if tag == 'td':
49                         self.td= True
50                 elif tag == 'tr':
51                         self.tr= True
52
53         def handle_endtag(self, tag):
54                 if tag == 'td':
55                         self.td= False
56                 elif tag == 'tr':
57                         self.tr= False
58                         self.list.append(self.data)
59                         self.data= []
60
61         def handle_data(self, data):
62                 if self.tr and self.td:
63                         self.data.append(data)
64
65
66 class Wunschliste(IdentifierBase):
67         def __init__(self):
68                 IdentifierBase.__init__(self)
69                 
70                 self.license = False
71
72         @classmethod
73         def knowsToday(cls):
74                 return True
75
76         @classmethod
77         def knowsFuture(cls):
78                 return True
79
80         def getEpisode(self, name, begin, end=None, service=None, channels=[]):
81                 # On Success: Return a single season, episode, title tuple
82                 # On Failure: Return a empty list or String or None
83                 
84                 self.begin = begin
85                 self.end = end
86                 self.service = service
87                 self.channels = channels
88                 
89                 self.returnvalue = None
90                 
91                 # Check preconditions
92                 if not name:
93                         splog(_("Skip Wunschliste: No show name specified"))
94                         return _("Skip Wunschliste: No show name specified")
95                 if not begin:
96                         splog(_("Skip Wunschliste: No begin timestamp specified"))
97                         return _("Skip Wunschliste: No begin timestamp specified")
98                 
99                 splog("WunschlistePrint getEpisode")
100                 
101                 while name:     
102                         ids = self.getSeries(name)
103                         
104                         while ids:
105                                 idserie = ids.pop()
106                                 
107                                 if idserie and len(idserie) == 2:
108                                         id, self.series = idserie
109                                         
110                                         result = self.getNextPage( id )
111                                         if result:
112                                                 return result
113                                         
114                         else:
115                                 name = self.getAlternativeSeries(name)
116                 
117                 else:
118                         return ( self.returnvalue or _("No matching series found") )
119
120         def getSeries(self, name):
121                 url = SERIESLISTURL + urlencode({ 'q' : re.sub("[^a-zA-Z0-9*]", " ", name) })
122                 data = self.getPage( url )
123                 
124                 if data and isinstance(data, basestring):
125                         data = self.parseSeries(data)
126                         self.doCache(url, data)
127                 
128                 if data and isinstance(data, list):
129                         splog("WunschlistePrint ids", data)
130                         return data
131
132         def parseSeries(self, data):
133                 serieslist = []
134                 for line in data.splitlines():
135                         values = line.split("|")
136                         if len(values) == 3:
137                                 idname, countryyear, id = values
138                                 splog(id, idname)
139                                 serieslist.append( (id, idname) )
140                         else:
141                                 splog("WunschlistePrint: ParseError: " + str(line))
142                 serieslist.reverse()
143                 return serieslist
144
145         def parseNextPage(self, data):
146                 # Handle malformed HTML issues
147                 #data = data.replace('"','&')
148                 data = data.replace('&','&')
149                 parser = WLPrintParser()
150                 parser.feed(data)
151                 #splog(parser.list)
152                 return parser.list
153
154         def getNextPage(self, id):
155                 splog("WunschlistePrint getNextPage")
156                 
157                 url = EPISODEIDURLPRINT + urlencode({ 's' : id })
158                 data = self.getPage( url )
159                 
160                 if data and isinstance(data, basestring):
161                         data = self.parseNextPage(data)
162                         self.doCache(url, data)
163                 
164                 if data and isinstance(data, list):
165                         trs = data
166                         
167                         yepisode = None
168                         ydelta = maxint
169                         year = str(datetime.today().year)
170                         
171                         for tds in trs:
172                                 if tds and len(tds) >= 5:
173                                         #print tds
174                                         xchannel, xday, xdate, xbegin, xend = tds[:5]
175                                         xtitle = "".join(tds[4:])
176                                         xbegin   = datetime.strptime( xdate+year+xbegin, "%d.%m.%Y%H.%M Uhr" )
177                                         #xend     = datetime.strptime( xdate+xend, "%d.%m.%Y%H.%M Uhr" )
178                                         #splog(xchannel, xdate, xbegin, xend, xtitle)
179                                         #splog(datebegin, xbegin, abs((datebegin - xbegin)))
180                                         
181                                         #Py2.6
182                                         delta = abs(self.begin - xbegin)
183                                         delta = delta.seconds + delta.days * 24 * 3600
184                                         #Py2.7 delta = abs(self.begin - xbegin).total_seconds()
185                                         splog(self.begin, xbegin, delta, int(config.plugins.seriesplugin.max_time_drift.value)*60)
186                                         
187                                         if delta <= int(config.plugins.seriesplugin.max_time_drift.value) * 60:
188                                                 
189                                                 if compareChannels(self.channels, xchannel, self.service):
190                                                 
191                                                         if delta < ydelta:
192                                                                 
193                                                                 print len(tds), tds
194                                                                 if len(tds) >= 7:
195                                                                         xepisode, xtitle = tds[5:7]
196                                                                 
197                                                                         if xepisode:
198                                                                                 result = CompiledRegexpEpisode.search(xepisode)
199                                                                                 
200                                                                                 if result and len(result.groups()) >= 3:
201                                                                                         xseason = result and result.group(2) or "1"
202                                                                                         xepisode = result and result.group(3) or "0"
203                                                                                 else:
204                                                                                         xseason = "1"
205                                                                                         xepisode = "0"
206                                                                         else:
207                                                                                 xseason = "1"
208                                                                                 xepisode = "0"
209                                                                 
210                                                                 elif len(tds) == 6:
211                                                                         xtitle = tds[5]
212                                                                         xseason = "0"
213                                                                         xepisode = "0"
214                                                                 
215                                                                 yepisode = (xseason, xepisode, xtitle.decode('ISO-8859-1').encode('utf8'), self.series.decode('ISO-8859-1').encode('utf8'))
216                                                                 ydelta = delta
217                                                         
218                                                         else: #if delta >= ydelta:
219                                                                 break
220                                                 
221                                                 else:
222                                                         self.returnvalue = _("Check the channel name")
223                                                 
224                                         elif yepisode:
225                                                 break
226                         
227                         if yepisode:
228                                 return ( yepisode )