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