SeriesPlugin 2.2.2: Bulk update
[enigma2-plugins.git] / seriesplugin / src / IdentifierBase.py
1 # -*- coding: utf-8 -*-
2 # by betonme @2012
3
4 from collections import defaultdict
5
6 from thread import start_new_thread
7
8 #TODO Implement Twisted handler
9 #Twisted 12.x
10 #from twisted.web.client import getPage as twGetPage
11 #Twisted 8.x
12 #from twisted.web.client import _parse, HTTPClientFactory
13 #from twisted.internet import reactor
14 #Twisted All
15 #from twisted.python.failure import Failure
16
17 from time import sleep
18 import socket
19
20 #import urllib2
21 from urllib import urlencode
22 from urllib2 import urlopen, URLError, Request, build_opener, HTTPCookieProcessor
23
24 from Components.config import config
25 from Tools.BoundFunction import boundFunction
26
27 # Internal
28 from ModuleBase import ModuleBase
29 from Cacher import Cacher, INTER_QUERY_TIME
30 from Channels import ChannelsBase
31 from Logger import splog
32 from Analytics import Analytics
33
34
35 class MyException(Exception):
36     pass
37
38 class IdentifierBase(ModuleBase, Cacher, ChannelsBase, Analytics):
39         def __init__(self):
40                 ModuleBase.__init__(self)
41                 Cacher.__init__(self)
42                 ChannelsBase.__init__(self)
43                 Analytics.__init__(self)
44                 
45                 socket.setdefaulttimeout(5)
46                 
47                 self.max_time_drift = int(config.plugins.seriesplugin.max_time_drift.value) * 60
48                 
49                 self.name = ""
50                 self.begin = None
51                 self.end = None
52                 self.channel = ""
53                 self.ids = []
54                 
55                 self.knownids = []
56                 
57                 self.returnvalue = None
58                 
59                 self.search_depth = 0;
60
61         ################################################
62         # Helper function
63         def getAlternativeSeries(self, name):
64                 
65                 self.search_depth += 1
66                 if( self.search_depth < config.plugins.seriesplugin.search_depths.value ):
67                         return " ".join(name.split(" ")[:-1])
68                 else:
69                         return ""
70
71         def filterKnownIds(self, newids):
72                 # Filter already checked series
73                 filteredids = [elem for elem in newids if elem not in self.knownids]
74                 
75                 # Add new ids to knownid list
76                 self.knownids.extend(filteredids)
77                 
78                 return filteredids
79
80
81         ################################################
82         # URL functions
83         def getPage(self, url, headers={}, expires=INTER_QUERY_TIME, counter=0):
84                 response = None
85                 
86                 splog("SSBase getPage", url)
87                 
88                 cached = self.getCached(url, expires)
89                 
90                 self.sendAnalytics(url, True if cached else False)
91                 
92                 if cached:
93                         splog("SSBase cached")
94                         response = cached
95                 
96                 else:
97                         splog("SSBase not cached")
98                         
99                         try:
100                                 req = Request(url, headers=headers)
101                                 response = urlopen(req, timeout=15).read()
102                                 
103                                 #splog("SSBase response to cache: ", response) 
104                                 if response:
105                                         self.doCachePage(url, response)
106                         
107                         except URLError as e:
108                                  # For Python 2.6
109                                 if counter > 2:
110                                         splog("SSBase URLError counter > 2")
111                                         raise MyException("There was an URLError: %r" % e)
112                                 elif hasattr(e, "code"):
113                                         splog("SSBase URLError code")
114                                         print e.code, e.msg, counter
115                                         sleep(2)
116                                         return self.getPage(url, headers, expires, counter+1)
117                                 else:
118                                         splog("SSBase URLError else")
119                                         raise MyException("There was an URLError: %r" % e)
120                         
121                         except socket.timeout as e:
122                                  # For Python 2.7
123                                 if counter > 2:
124                                         splog("SSBase URLError counter > 2")
125                                         raise MyException("There was an SocketTimeout: %r" % e)
126                                 elif hasattr(e, "code"):
127                                         splog("SSBase URLError code")
128                                         print e.code, e.msg, counter
129                                         sleep(2)
130                                         return self.getPage(url, headers, expires, counter+1)
131                                 else:
132                                         splog("SSBase URLError else")
133                                         raise MyException("There was an SocketTimeout: %r" % e)
134                         
135                 splog("SSBase success")
136                 return response
137         
138         ################################################
139         # Service prototypes
140         @classmethod
141         def knowsElapsed(cls):
142                 # True: Service knows elapsed air dates
143                 # False: Service doesn't know elapsed air dates
144                 return False
145
146         @classmethod
147         def knowsToday(cls):
148                 # True: Service knows today air dates
149                 # False: Service doesn't know today air dates
150                 return False
151
152         @classmethod
153         def knowsFuture(cls):
154                 # True: Service knows future air dates
155                 # False: Service doesn't know future air dates
156                 return False
157
158         ################################################
159         # To be implemented by subclass
160         def getEpisode(self, name, begin, end, service):
161                 # On Success: Return a single season, episode, title tuple
162                 # On Failure: Return a empty list or String or None
163                 return None