def __call_trakt(self, url, extra_data=None, cache_limit=.25, cached=True): if not cached: cache_limit = 0 data={'username': self.username, 'password': self.sha1password} if extra_data: data.update(extra_data) url = '%s%s%s' % (self.protocol, BASE_URL, url) log_utils.log('Trakt Call: %s, data: %s' % (url, data), xbmc.LOGDEBUG) db_connection = DB_Connection() created, cached_result = db_connection.get_cached_url(url) if cached_result and (time.time() - created) < (60 * 60 * cache_limit): result = cached_result log_utils.log('Returning cached result for: %s' % (url), xbmc.LOGDEBUG) else: try: f=urllib2.urlopen(url, json.dumps(data), self.timeout) result=f.read() db_connection.cache_url(url, result) except (ssl.SSLError,socket.timeout) as e: if cached_result: result = cached_result log_utils.log('Temporary Trakt Error (%s). Using Cached Page Instead.' % (str(e)), xbmc.LOGWARNING) else: raise TransientTraktError('Temporary Trakt Error: '+str(e)) except urllib2.URLError as e: if isinstance(e, urllib2.HTTPError): if e.code in TEMP_ERRORS: if cached_result: result = cached_result log_utils.log('Temporary Trakt Error (%s). Using Cached Page Instead.' % (str(e)), xbmc.LOGWARNING) else: raise TransientTraktError('Temporary Trakt Error: '+str(e)) elif e.code == 404: return else: raise elif isinstance(e.reason, socket.timeout) or isinstance(e.reason, ssl.SSLError): if cached_result: result = cached_result log_utils.log('Temporary Trakt Error (%s). Using Cached Page Instead' % (str(e)), xbmc.LOGWARNING) else: raise TransientTraktError('Temporary Trakt Error: '+str(e)) else: raise TraktError('Trakt Error: '+str(e)) response=json.loads(result) if 'status' in response and response['status']=='failure': if 'message' in response: raise TraktError(response['message']) if 'error' in response: raise TraktError(response['error']) else: raise TraktError() else: #log_utils.log('Trakt Response: %s' % (response), xbmc.LOGDEBUG) return response
def __init__(self): self.db_connection = DB_Connection()
class SRT_Scraper(): def __init__(self): self.db_connection = DB_Connection() def get_tvshow_id(self, title, year=None): match_title = title.lower() rows = self.db_connection.get_related_url(VIDEO_TYPES.TVSHOW, title, year, SRT_SOURCE) if rows: tvshow_id = rows[0][0] log_utils.log('Returning local tvshow id: |%s|%s|%s|' % (title, year, tvshow_id), log_utils.LOGDEBUG) return tvshow_id html = self.__get_cached_url(BASE_URL, 24) regex = re.compile('option\s+value="(\d+)"\s*>(.*?)</option') site_matches = [] for item in regex.finditer(html): tvshow_id, site_title = item.groups() # strip year off title and assign it to year if it exists r = re.search('(\s*\((\d{4})\))$', site_title) if r: site_title = site_title.replace(r.group(1), '') site_year = r.group(2) else: site_year = None # print 'show: |%s|%s|%s|' % (tvshow_id, site_title, site_year) if match_title == site_title.lower(): if year is None or year == site_year: self.db_connection.set_related_url(VIDEO_TYPES.TVSHOW, title, year, SRT_SOURCE, tvshow_id) return tvshow_id site_matches.append((tvshow_id, site_title, site_year)) if not site_matches: return None elif len(site_matches) == 1: self.db_connection.set_related_url(VIDEO_TYPES.TVSHOW, title, year, SRT_SOURCE, site_matches[0][0]) return site_matches[0][0] else: # there were multiple title matches and year was passed but no exact year matches found for match in site_matches: # return the match that has no year specified if match[2] is None: self.db_connection.set_related_url(VIDEO_TYPES.TVSHOW, title, year, SRT_SOURCE, match[0]) return match[0] def get_season_subtitles(self, language, tvshow_id, season): url = BASE_URL + '/ajax_loadShow.php?show=%s&season=%s&langs=&hd=%s&hi=%s' % (tvshow_id, season, 0, 0) html = self.__get_cached_url(url, .25) # print html.decode('ascii', 'ignore') req_hi = kodi.get_setting('subtitle-hi') == 'true' req_hd = kodi.get_setting('subtitle-hd') == 'true' items = [] regex = re.compile('<td>(\d+)</td><td>(\d+)</td><td>.*?</td><td>(.*?)</td><td.*?>(.*?)</td>.*?<td.*?>(.+?)</td><td.*?>(.*?)</td><td.*?>(.*?)</td><td.*?>(.*?)</td><td.*?><a\s+href="(.*?)">.+?</td>', re.DOTALL) for match in regex.finditer(html): season, episode, srt_lang, version, completed, hi, corrected, hd, srt_url = match.groups() if not language or language == srt_lang and (not req_hi or hi) and (not req_hd or hd): item = {} item['season'] = season item['episode'] = episode item['language'] = srt_lang item['version'] = version if completed.lower() == 'completed': item['completed'] = True item['percent'] = '100' else: item['completed'] = False r = re.search('([\d.]+)%', completed) if r: item['percent'] = r.group(1) else: item['percent'] = '0' item['hi'] = True if hi else False item['corrected'] = True if corrected else False item['hd'] = True if hd else False item['url'] = srt_url items.append(item) return items def get_episode_subtitles(self, language, tvshow_id, season, episode): subtitles = self.get_season_subtitles(language, tvshow_id, season) items = [] for subtitle in subtitles: if subtitle['episode'] == str(episode): items.append(subtitle) return items def download_subtitle(self, url): url = BASE_URL + url (response, srt) = self.__get_url(url) if not hasattr(response, 'info') or 'Content-Disposition' not in response.info(): return cd = response.info()['Content-Disposition'] r = re.search('filename="(.*)"', cd) if r: filename = r.group(1) else: filename = 'addic7ed_subtitle.srt' filename = re.sub('[^\x00-\x7F]', '', filename) final_path = os.path.join(kodi.get_setting('subtitle-folder'), filename) final_path = kodi.translate_path(final_path) if not xbmcvfs.exists(os.path.dirname(final_path)): try: try: xbmcvfs.mkdirs(os.path.dirname(final_path)) except: os.mkdir(os.path.dirname(final_path)) except: log_utils.log('Failed to create directory %s' % os.path.dirname(final_path), log_utils.LOGERROR) raise with open(final_path, 'w') as f: f.write(srt) return final_path def __get_url(self, url): try: req = urllib2.Request(url) host = BASE_URL.replace('http://', '') req.add_header('User-Agent', USER_AGENT) req.add_header('Host', host) req.add_header('Referer', BASE_URL) response = urllib2.urlopen(req, timeout=10) body = response.read() parser = HTMLParser.HTMLParser() body = parser.unescape(body) except Exception as e: kodi.notify(msg='Failed to connect to URL: %s' % (url), duration=5000) log_utils.log('Failed to connect to URL %s: (%s)' % (url, e), log_utils.LOGERROR) return ('', '') return (response, body) def __get_cached_url(self, url, cache=8): log_utils.log('Fetching Cached URL: %s' % url, log_utils.LOGDEBUG) before = time.time() _created, _res_header, html = self.db_connection.get_cached_url(url, cache_limit=cache) if html: log_utils.log('Returning cached result for: %s' % (url), log_utils.LOGDEBUG) return html log_utils.log('No cached url found for: %s' % url, log_utils.LOGDEBUG) req = urllib2.Request(url) host = BASE_URL.replace('http://', '') req.add_header('User-Agent', USER_AGENT) req.add_header('Host', host) req.add_header('Referer', BASE_URL) try: body = self.__http_get_with_retry(url, req) body = body.decode('utf-8') parser = HTMLParser.HTMLParser() body = parser.unescape(body) except Exception as e: kodi.notify(msg='Failed to connect to URL: %s' % (url), duration=5000) log_utils.log('Failed to connect to URL %s: (%s)' % (url, e), log_utils.LOGERROR) return '' self.db_connection.cache_url(url, body) after = time.time() log_utils.log('Cached Url Fetch took: %.2f secs' % (after - before), log_utils.LOGDEBUG) return body def __http_get_with_retry(self, url, request): log_utils.log('Fetching URL: %s' % request.get_full_url(), log_utils.LOGDEBUG) retries = 0 html = None while retries <= MAX_RETRIES: try: response = urllib2.urlopen(request, timeout=10) html = response.read() # if no exception, jump out of the loop break except socket.timeout: retries += 1 log_utils.log('Retry #%s for URL %s because of timeout' % (retries, url), log_utils.LOGWARNING) continue except urllib2.HTTPError as e: # if it's a temporary code, retry if e.code in TEMP_ERRORS: retries += 1 log_utils.log('Retry #%s for URL %s because of HTTP Error %s' % (retries, url, e.code), log_utils.LOGWARNING) continue # if it's not pass it back up the stack else: raise else: raise response.close() return html
def __get_cached_url(self, url, cache_limit=8): utils.log('Fetching Cached URL: %s' % url, xbmc.LOGDEBUG) before = time.time() db_connection=DB_Connection() html = db_connection.get_cached_url(url, cache_limit) if html: utils.log('Returning cached result for: %s' % (url), xbmc.LOGDEBUG) return html utils.log('No cached url found for: %s' % url, xbmc.LOGDEBUG) req = urllib2.Request(url) host = re.sub('http://', '', self.base_url) req.add_header('User-Agent', USER_AGENT) req.add_unredirected_header('Host', host) req.add_unredirected_header('Referer', self.base_url) try: body = self.__http_get_with_retry_2(url, req) if '<title>Are You a Robot?</title>' in body: utils.log('bot detection') # download the captcha image and save it to a file for use later captchaimgurl = 'http://' + host + '/CaptchaSecurityImages.php' captcha_save_path = xbmc.translatePath('special://userdata/addon_data/plugin.video.1channel/CaptchaSecurityImage.jpg') req = urllib2.Request(captchaimgurl) host = re.sub('http://', '', self.base_url) req.add_header('User-Agent', USER_AGENT) req.add_header('Host', host) req.add_header('Referer', self.base_url) response = urllib2.urlopen(req) the_img = response.read() with open(captcha_save_path, 'wb') as f: f.write(the_img) # now pop open dialog for input # TODO: make the size and loc configurable img = xbmcgui.ControlImage(550, 15, 240, 100, captcha_save_path) wdlg = xbmcgui.WindowDialog() wdlg.addControl(img) wdlg.show() kb = xbmc.Keyboard('', 'Type the letters in the image', False) kb.doModal() capcode = kb.getText() if (kb.isConfirmed()): userInput = kb.getText() if userInput != '': # post back user string wdlg.removeControl(img) capcode = kb.getText() data = {'security_code':capcode, 'not_robot':'I\'m Human! I Swear!'} data = urllib.urlencode(data) roboturl = 'http://' + host + '/are_you_a_robot.php' req = urllib2.Request(roboturl) host = re.sub('http://', '', self.base_url) req.add_header('User-Agent', USER_AGENT) req.add_header('Host', host) req.add_header('Referer', self.base_url) response = urllib2.urlopen(req, data) body = self.__get_url(url) elif userInput == '': dialog = xbmcgui.Dialog() dialog.ok("Robot Check", "You must enter text in the image to continue") wdlg.close() body = unicode(body, 'windows-1252') parser = HTMLParser.HTMLParser() body = parser.unescape(body) except Exception as e: dialog = xbmcgui.Dialog() dialog.ok("Connection failed", "Failed to connect to url", url) utils.log('Failed to connect to URL %s: %s' % (url, str(e)), xbmc.LOGERROR) return '' db_connection.cache_url(url, body) after = time.time() utils.log('Cached Url Fetch took: %.2f secs' % (after - before), xbmc.LOGDEBUG) return body
def __get_cached_url(self, url, cache_limit=8): utils.log('Fetching Cached URL: %s' % url, xbmc.LOGDEBUG) before = time.time() db_connection = DB_Connection() html = db_connection.get_cached_url(url, cache_limit) if html: utils.log('Returning cached result for: %s' % (url), xbmc.LOGDEBUG) return html utils.log('No cached url found for: %s' % url, xbmc.LOGDEBUG) req = urllib2.Request(url) host = re.sub('http://', '', self.base_url) req.add_header('User-Agent', USER_AGENT) req.add_unredirected_header('Host', host) req.add_unredirected_header('Referer', self.base_url) try: body = self.__http_get_with_retry_2(url, req) if '<title>Are You a Robot?</title>' in body: utils.log('bot detection') # download the captcha image and save it to a file for use later captchaimgurl = 'http://' + host + '/CaptchaSecurityImages.php' captcha_save_path = xbmc.translatePath( 'special://userdata/addon_data/plugin.video.1channel/CaptchaSecurityImage.jpg' ) req = urllib2.Request(captchaimgurl) host = re.sub('http://', '', self.base_url) req.add_header('User-Agent', USER_AGENT) req.add_header('Host', host) req.add_header('Referer', self.base_url) response = urllib2.urlopen(req) the_img = response.read() with open(captcha_save_path, 'wb') as f: f.write(the_img) # now pop open dialog for input # TODO: make the size and loc configurable img = xbmcgui.ControlImage(550, 15, 240, 100, captcha_save_path) wdlg = xbmcgui.WindowDialog() wdlg.addControl(img) wdlg.show() kb = xbmc.Keyboard('', 'Type the letters in the image', False) kb.doModal() capcode = kb.getText() if (kb.isConfirmed()): userInput = kb.getText() if userInput != '': # post back user string wdlg.removeControl(img) capcode = kb.getText() data = { 'security_code': capcode, 'not_robot': 'I\'m Human! I Swear!' } data = urllib.urlencode(data) roboturl = 'http://' + host + '/are_you_a_robot.php' req = urllib2.Request(roboturl) host = re.sub('http://', '', self.base_url) req.add_header('User-Agent', USER_AGENT) req.add_header('Host', host) req.add_header('Referer', self.base_url) response = urllib2.urlopen(req, data) body = self.__get_url(url) elif userInput == '': dialog = xbmcgui.Dialog() dialog.ok("Robot Check", "You must enter text in the image to continue") wdlg.close() body = unicode(body, 'windows-1252', 'ignore') parser = HTMLParser.HTMLParser() body = parser.unescape(body) except Exception as e: dialog = xbmcgui.Dialog() dialog.ok("Connection failed", "Failed to connect to url", url) utils.log('Failed to connect to URL %s: %s' % (url, str(e)), xbmc.LOGERROR) return '' db_connection.cache_url(url, body) after = time.time() utils.log('Cached Url Fetch took: %.2f secs' % (after - before), xbmc.LOGDEBUG) return body
def __call_trakt(self, url, method=None, data=None, params=None, auth=True, cache_limit=.25, cached=True): res_headers = {} if not cached: cache_limit = 0 if self.offline: db_cache_limit = int(time.time()) / 60 / 60 else: if cache_limit > 8: db_cache_limit = cache_limit else: db_cache_limit = 8 json_data = json.dumps(data) if data else None headers = {'Content-Type': 'application/json', 'trakt-api-key': V2_API_KEY, 'trakt-api-version': 2} url = '%s%s%s' % (self.protocol, BASE_URL, url) if params: url = url + '?' + urllib.urlencode(params) db_connection = DB_Connection() created, cached_headers, cached_result = db_connection.get_cached_url(url, json_data, db_cache_limit) if cached_result and (self.offline or (time.time() - created) < (60 * 60 * cache_limit)): result = cached_result res_headers = dict(cached_headers) log_utils.log('***Using cached result for: %s' % (url), log_utils.LOGDEBUG) else: auth_retry = False while True: try: if auth: headers.update({'Authorization': 'Bearer %s' % (self.token)}) log_utils.log('***Trakt Call: %s, header: %s, data: %s cache_limit: %s cached: %s' % (url, headers, json_data, cache_limit, cached), log_utils.LOGDEBUG) request = urllib2.Request(url, data=json_data, headers=headers) if method is not None: request.get_method = lambda: method.upper() response = urllib2.urlopen(request, timeout=self.timeout) result = '' while True: data = response.read() if not data: break result += data res_headers = dict(response.info().items()) db_connection.cache_url(url, result, json_data, response.info().items()) break except (ssl.SSLError, socket.timeout) as e: if cached_result: result = cached_result log_utils.log('Temporary Trakt Error (%s). Using Cached Page Instead.' % (str(e)), log_utils.LOGWARNING) else: raise TransientTraktError('Temporary Trakt Error: ' + str(e)) except urllib2.URLError as e: if isinstance(e, urllib2.HTTPError): if e.code in TEMP_ERRORS: if cached_result: result = cached_result log_utils.log('Temporary Trakt Error (%s). Using Cached Page Instead.' % (str(e)), log_utils.LOGWARNING) break else: raise TransientTraktError('Temporary Trakt Error: ' + str(e)) elif e.code == 401 or e.code == 405: # token is fine, profile is private if e.info().getheader('X-Private-User') == 'true': raise TraktAuthError('Object is No Longer Available (%s)' % (e.code)) # auth failure retry or a token request elif auth_retry or url.endswith('/oauth/token'): self.token = None kodi.set_setting('trakt_oauth_token', '') kodi.set_setting('trakt_refresh_token', '') raise TraktAuthError('Trakt Call Authentication Failed (%s)' % (e.code)) # first try token fail, try to refresh token else: result = self.refresh_token(kodi.get_setting('trakt_refresh_token')) self.token = result['access_token'] kodi.set_setting('trakt_oauth_token', result['access_token']) kodi.set_setting('trakt_refresh_token', result['refresh_token']) auth_retry = True elif e.code == 404: raise TraktNotFoundError('Object Not Found (%s)' % (e.code)) else: raise elif isinstance(e.reason, socket.timeout) or isinstance(e.reason, ssl.SSLError): if cached_result: result = cached_result log_utils.log('Temporary Trakt Error (%s). Using Cached Page Instead' % (str(e)), log_utils.LOGWARNING) break else: raise TransientTraktError('Temporary Trakt Error: ' + str(e)) else: raise TraktError('Trakt Error: ' + str(e)) except: raise try: js_data = json.loads(result) if 'x-sort-by' in res_headers and 'x-sort-how' in res_headers: js_data = utils2.sort_list(res_headers['x-sort-by'], res_headers['x-sort-how'], js_data) except ValueError: js_data = '' if result: log_utils.log('Invalid JSON Trakt API Response: %s - |%s|' % (url, js_data), log_utils.LOGERROR) # log_utils.log('Trakt Response: %s' % (response), xbmc.LOGDEBUG) return js_data
SORT_FIELDS = [ (SORT_LIST[int(kodi.get_setting('sort1_field'))], SORT_SIGNS[kodi.get_setting('sort1_order')]), (SORT_LIST[int(kodi.get_setting('sort2_field'))], SORT_SIGNS[kodi.get_setting('sort2_order')]), (SORT_LIST[int(kodi.get_setting('sort3_field'))], SORT_SIGNS[kodi.get_setting('sort3_order')]), (SORT_LIST[int(kodi.get_setting('sort4_field'))], SORT_SIGNS[kodi.get_setting('sort4_order')]), (SORT_LIST[int(kodi.get_setting('sort5_field'))], SORT_SIGNS[kodi.get_setting('sort5_order')]), (SORT_LIST[int(kodi.get_setting('sort6_field'))], SORT_SIGNS[kodi.get_setting('sort6_order')])] last_check = datetime.datetime.fromtimestamp(0) TOKEN = kodi.get_setting('trakt_oauth_token') use_https = kodi.get_setting('use_https') == 'true' trakt_timeout = int(kodi.get_setting('trakt_timeout')) list_size = int(kodi.get_setting('list_size')) trakt_api = Trakt_API(TOKEN, use_https, list_size, trakt_timeout) db_connection = DB_Connection() THEME_LIST = ['Shine', 'Luna_Blue', 'Iconic', 'Simple', 'SALTy', 'SALTy (Blended)', 'SALTy (Blue)', 'SALTy (Frog)', 'SALTy (Green)', 'SALTy (Macaw)', 'SALTier (Green)', 'SALTier (Orange)', 'SALTier (Red)', 'IGDB', 'Simply Elegant', 'IGDB Redux'] THEME = THEME_LIST[int(kodi.get_setting('theme'))] if xbmc.getCondVisibility('System.HasAddon(script.salts.themepak)'): themepak_path = xbmcaddon.Addon('script.salts.themepak').getAddonInfo('path') else: themepak_path = kodi.get_path() THEME_PATH = os.path.join(themepak_path, 'art', 'themes', THEME) PLACE_POSTER = os.path.join(kodi.get_path(), 'resources', 'place_poster.png') def art(name): path = os.path.join(THEME_PATH, name) if not xbmcvfs.exists(path): if name == 'fanart.jpg':
def __call_trakt(self, url, method=None, data=None, params=None, auth=True, cache_limit=0.25, cached=True): if not cached: cache_limit = 0 db_cache_limit = cache_limit if cache_limit > 8 else 8 json_data = json.dumps(data) if data else None headers = {"Content-Type": "application/json", "trakt-api-key": V2_API_KEY, "trakt-api-version": 2} url = "%s%s%s" % (self.protocol, BASE_URL, url) if params: url = url + "?" + urllib.urlencode(params) db_connection = DB_Connection() created, cached_result = db_connection.get_cached_url(url, json_data, db_cache_limit) if cached_result and (time.time() - created) < (60 * 60 * cache_limit): result = cached_result log_utils.log("Returning cached result for: %s" % (url), log_utils.LOGDEBUG) else: auth_retry = False while True: try: if auth: headers.update({"Authorization": "Bearer %s" % (self.token)}) log_utils.log( "Trakt Call: %s, header: %s, data: %s cache_limit: %s cached: %s" % (url, headers, data, cache_limit, cached), log_utils.LOGDEBUG, ) request = urllib2.Request(url, data=json_data, headers=headers) if method is not None: request.get_method = lambda: method.upper() f = urllib2.urlopen(request, timeout=self.timeout) result = "" while True: data = f.read() if not data: break result += data db_connection.cache_url(url, result, json_data) break except (ssl.SSLError, socket.timeout) as e: if cached_result: result = cached_result log_utils.log( "Temporary Trakt Error (%s). Using Cached Page Instead." % (str(e)), log_utils.LOGWARNING ) else: raise TransientTraktError("Temporary Trakt Error: " + str(e)) except urllib2.URLError as e: if isinstance(e, urllib2.HTTPError): if e.code in TEMP_ERRORS: if cached_result: result = cached_result log_utils.log( "Temporary Trakt Error (%s). Using Cached Page Instead." % (str(e)), log_utils.LOGWARNING, ) break else: raise TransientTraktError("Temporary Trakt Error: " + str(e)) elif e.code == 401 or e.code == 405: if auth_retry or url.endswith("/token"): self.token = None kodi.set_setting("trakt_oauth_token", "") kodi.set_setting("trakt_refresh_token", "") raise TraktAuthError("Trakt Call Authentication Failed (%s)" % (e.code)) else: result = self.get_token() self.token = result["access_token"] kodi.set_setting("trakt_oauth_token", result["access_token"]) kodi.set_setting("trakt_refresh_token", result["refresh_token"]) auth_retry = True elif e.code == 404: raise TraktNotFoundError() else: raise elif isinstance(e.reason, socket.timeout) or isinstance(e.reason, ssl.SSLError): if cached_result: result = cached_result log_utils.log( "Temporary Trakt Error (%s). Using Cached Page Instead" % (str(e)), log_utils.LOGWARNING ) break else: raise TransientTraktError("Temporary Trakt Error: " + str(e)) else: raise TraktError("Trakt Error: " + str(e)) except: raise try: response = json.loads(result) except ValueError: response = "" if result: log_utils.log("Invalid JSON Trakt API Response: %s - |%s|" % (url, result), log_utils.LOGERROR) # log_utils.log('Trakt Response: %s' % (response), xbmc.LOGDEBUG) return response
def __get_db_connection(self): worker_id = threading.current_thread().ident if not self.__db_connection or self.__worker_id != worker_id: self.__db_connection = DB_Connection() self.__worker_id = worker_id return self.__db_connection
You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. """ import json import xbmc import xbmcgui import xbmcaddon import utils from utils import MODES from db_utils import DB_Connection ADDON = xbmcaddon.Addon(id='plugin.video.1channel_bp') utils.log('Service: Installed Version: %s' % (ADDON.getAddonInfo('version'))) db_connection = DB_Connection() db_connection.init_database() class Service(xbmc.Player): def __init__(self, *args, **kwargs): xbmc.Player.__init__(self, *args, **kwargs) self.reset() self.last_run = 0 self.DB = '' utils.log('Service: starting...') def reset(self): utils.log('Service: Resetting...') win = xbmcgui.Window(10000) win.clearProperty('1ch.playing.title')
def __call_trakt(self, url, method=None, data=None, params=None, auth=True, cache_limit=.25, cached=True): res_headers = {} if not cached: cache_limit = 0 db_cache_limit = cache_limit if cache_limit > 8 else 8 json_data = json.dumps(data) if data else None headers = {'Content-Type': 'application/json', 'trakt-api-key': V2_API_KEY, 'trakt-api-version': 2} url = '%s%s%s' % (self.protocol, BASE_URL, url) if params: url = url + '?' + urllib.urlencode(params) db_connection = DB_Connection() created, cached_result = db_connection.get_cached_url(url, json_data, db_cache_limit) if cached_result and (time.time() - created) < (60 * 60 * cache_limit): result = cached_result log_utils.log('Returning cached result for: %s' % (url), log_utils.LOGDEBUG) else: auth_retry = False while True: try: if auth: headers.update({'Authorization': 'Bearer %s' % (self.token)}) log_utils.log('Trakt Call: %s, header: %s, data: %s cache_limit: %s cached: %s' % (url, headers, data, cache_limit, cached), log_utils.LOGDEBUG) request = urllib2.Request(url, data=json_data, headers=headers) if method is not None: request.get_method = lambda: method.upper() response = urllib2.urlopen(request, timeout=self.timeout) result = '' while True: data = response.read() if not data: break result += data res_headers = dict(response.info().items()) db_connection.cache_url(url, result, json_data) break except (ssl.SSLError, socket.timeout) as e: if cached_result: result = cached_result log_utils.log('Temporary Trakt Error (%s). Using Cached Page Instead.' % (str(e)), log_utils.LOGWARNING) else: raise TransientTraktError('Temporary Trakt Error: ' + str(e)) except urllib2.URLError as e: if isinstance(e, urllib2.HTTPError): if e.code in TEMP_ERRORS: if cached_result: result = cached_result log_utils.log('Temporary Trakt Error (%s). Using Cached Page Instead.' % (str(e)), log_utils.LOGWARNING) break else: raise TransientTraktError('Temporary Trakt Error: ' + str(e)) elif e.code == 401 or e.code == 405: # token is fine, profile is private if e.info().getheader('X-Private-User') == 'true': raise TraktAuthError('Object is No Longer Available (%s)' % (e.code)) # auth failure retry or a token request elif auth_retry or url.endswith('/token'): self.token = None kodi.set_setting('trakt_oauth_token', '') kodi.set_setting('trakt_refresh_token', '') raise TraktAuthError('Trakt Call Authentication Failed (%s)' % (e.code)) # first try token fail, try to refresh token else: result = self.get_token() self.token = result['access_token'] kodi.set_setting('trakt_oauth_token', result['access_token']) kodi.set_setting('trakt_refresh_token', result['refresh_token']) auth_retry = True elif e.code == 404: raise TraktNotFoundError('Object Not Found (%s)' % (e.code)) else: raise elif isinstance(e.reason, socket.timeout) or isinstance(e.reason, ssl.SSLError): if cached_result: result = cached_result log_utils.log('Temporary Trakt Error (%s). Using Cached Page Instead' % (str(e)), log_utils.LOGWARNING) break else: raise TransientTraktError('Temporary Trakt Error: ' + str(e)) else: raise TraktError('Trakt Error: ' + str(e)) except: raise try: js_data = json.loads(result) if 'x-sort-by' in res_headers and 'x-sort-how' in res_headers: js_data = self.__sort_list(res_headers['x-sort-by'], res_headers['x-sort-how'], js_data) except ValueError: js_data = '' if result: log_utils.log('Invalid JSON Trakt API Response: %s - |%s|' % (url, js_data), log_utils.LOGERROR) # log_utils.log('Trakt Response: %s' % (response), xbmc.LOGDEBUG) return js_data
def __call_trakt(self, url, data = None, params=None, auth=True, cache_limit=.25, cached=True): if not cached: cache_limit = 0 db_cache_limit = cache_limit if cache_limit > 8 else 8 json_data=json.dumps(data) if data else None headers = {'Content-Type': 'application/json', 'trakt-api-key': V2_API_KEY, 'trakt-api-version': 2} if auth: headers.update({'trakt-user-login': self.username, 'trakt-user-token': self.token}) url = '%s%s%s' % (self.protocol, BASE_URL, url) if params: url = url + '?' + urllib.urlencode(params) log_utils.log('Trakt Call: %s, header: %s, data: %s' % (url, headers, data), xbmc.LOGDEBUG) db_connection = DB_Connection() created, cached_result = db_connection.get_cached_url(url, db_cache_limit) if cached_result and (time.time() - created) < (60 * 60 * cache_limit): result = cached_result log_utils.log('Returning cached result for: %s' % (url), xbmc.LOGDEBUG) else: login_retry=False while True: try: request = urllib2.Request(url, data = json_data, headers = headers ) f=urllib2.urlopen(request, timeout = self.timeout) result=f.read() db_connection.cache_url(url, result) break except (ssl.SSLError,socket.timeout) as e: if cached_result: result = cached_result log_utils.log('Temporary Trakt Error (%s). Using Cached Page Instead.' % (str(e)), xbmc.LOGWARNING) else: raise TransientTraktError('Temporary Trakt Error: '+str(e)) except urllib2.URLError as e: if isinstance(e, urllib2.HTTPError): if e.code in TEMP_ERRORS: if cached_result: result = cached_result log_utils.log('Temporary Trakt Error (%s). Using Cached Page Instead.' % (str(e)), xbmc.LOGWARNING) break else: raise TransientTraktError('Temporary Trakt Error: '+str(e)) elif e.code == 401: if login_retry or url.endswith('login'): raise else: self.token = self.login() xbmcaddon.Addon('plugin.video.salts').setSetting('trakt_token', self.token) login_retry=True else: raise elif isinstance(e.reason, socket.timeout) or isinstance(e.reason, ssl.SSLError): if cached_result: result = cached_result log_utils.log('Temporary Trakt Error (%s). Using Cached Page Instead' % (str(e)), xbmc.LOGWARNING) break else: raise TransientTraktError('Temporary Trakt Error: '+str(e)) else: raise TraktError('Trakt Error: '+str(e)) else: raise response=json.loads(result) if 'status' in response and response['status']=='failure': if 'message' in response: raise TraktError(response['message']) if 'error' in response: raise TraktError(response['error']) else: raise TraktError() else: #log_utils.log('Trakt Response: %s' % (response), xbmc.LOGDEBUG) return response
def __call_trakt(self, url, data=None, params=None, auth=True, cache_limit=.25, cached=True): if not cached: cache_limit = 0 db_cache_limit = cache_limit if cache_limit > 8 else 8 json_data = json.dumps(data) if data else None headers = {'Content-Type': 'application/json', 'trakt-api-key': V2_API_KEY, 'trakt-api-version': 2} url = '%s%s%s' % (self.protocol, BASE_URL, url) if params: url = url + '?' + urllib.urlencode(params) db_connection = DB_Connection() created, cached_result = db_connection.get_cached_url(url, db_cache_limit) if cached_result and (time.time() - created) < (60 * 60 * cache_limit): result = cached_result log_utils.log('Returning cached result for: %s' % (url), log_utils.LOGDEBUG) else: auth_retry = False while True: try: if auth: headers.update({'Authorization': 'Bearer %s' % (self.token)}) log_utils.log('Trakt Call: %s, header: %s, data: %s' % (url, headers, data), log_utils.LOGDEBUG) request = urllib2.Request(url, data=json_data, headers=headers) f = urllib2.urlopen(request, timeout=self.timeout) result = '' while True: data = f.read() if not data: break result += data db_connection.cache_url(url, result) break except (ssl.SSLError, socket.timeout) as e: if cached_result: result = cached_result log_utils.log('Temporary Trakt Error (%s). Using Cached Page Instead.' % (str(e)), log_utils.LOGWARNING) else: raise TransientTraktError('Temporary Trakt Error: ' + str(e)) except urllib2.URLError as e: if isinstance(e, urllib2.HTTPError): if e.code in TEMP_ERRORS: if cached_result: result = cached_result log_utils.log('Temporary Trakt Error (%s). Using Cached Page Instead.' % (str(e)), log_utils.LOGWARNING) break else: raise TransientTraktError('Temporary Trakt Error: ' + str(e)) elif e.code == 401 or e.code == 405: if auth_retry or url.endswith('/token'): self.token = None kodi.set_setting('trakt_oauth_token', '') kodi.set_setting('trakt_refresh_token', '') raise TraktError('Trakt Call Authentication Failed (%s)' % (e.code)) else: result = self.get_token() self.token = result['access_token'] kodi.set_setting('trakt_oauth_token', result['access_token']) kodi.set_setting('trakt_refresh_token', result['refresh_token']) auth_retry = True elif e.code == 404: raise TraktNotFoundError() else: raise elif isinstance(e.reason, socket.timeout) or isinstance(e.reason, ssl.SSLError): if cached_result: result = cached_result log_utils.log('Temporary Trakt Error (%s). Using Cached Page Instead' % (str(e)), log_utils.LOGWARNING) break else: raise TransientTraktError('Temporary Trakt Error: ' + str(e)) else: raise TraktError('Trakt Error: ' + str(e)) except: raise response = json.loads(result) if 'status' in response and response['status'] == 'failure': if 'message' in response: raise TraktError(response['message']) if 'error' in response: raise TraktError(response['error']) else: raise TraktError() else: # log_utils.log('Trakt Response: %s' % (response), xbmc.LOGDEBUG) return response
""" import json import xbmc import xbmcgui import xbmcaddon import utils from utils import MODES from db_utils import DB_Connection ADDON = xbmcaddon.Addon(id='plugin.video.1channel') utils.log('Service: Installed Version: %s' % (ADDON.getAddonInfo('version'))) LASTPLAYEDFILE = xbmc.translatePath(xbmcaddon.Addon().getAddonInfo('profile')).decode('utf-8') + 'lastplayed.txt' TMPLASTPLAY = xbmc.translatePath(xbmcaddon.Addon().getAddonInfo('profile')).decode('utf-8') + 'lastplayedtmp.txt' db_connection = DB_Connection() db_connection.init_database() class Service(xbmc.Player): def __init__(self, *args, **kwargs): xbmc.Player.__init__(self, *args, **kwargs) self.reset() self.last_run = 0 self.DB = '' utils.log('Service: starting...') def reset(self): utils.log('Service: Resetting...') win = xbmcgui.Window(10000) win.clearProperty('1ch.playing.title')
class SRT_Scraper(): def __init__(self): self.db_connection = DB_Connection() def get_tvshow_id(self, title, year=None): match_title = title.lower() rows = self.db_connection.get_related_url(VIDEO_TYPES.TVSHOW, title, year, SRT_SOURCE) if rows: tvshow_id = rows[0][0] logger.log( 'Returning local tvshow id: |%s|%s|%s|' % (title, year, tvshow_id), log_utils.LOGDEBUG) return tvshow_id html = self.__get_cached_url(BASE_URL, 24) regex = re.compile('option\s+value="(\d+)"\s*>(.*?)</option') site_matches = [] for item in regex.finditer(html): tvshow_id, site_title = item.groups() # strip year off title and assign it to year if it exists r = re.search('(\s*\((\d{4})\))$', site_title) if r: site_title = site_title.replace(r.group(1), '') site_year = r.group(2) else: site_year = None # print 'show: |%s|%s|%s|' % (tvshow_id, site_title, site_year) if match_title == site_title.lower(): if year is None or year == site_year: self.db_connection.set_related_url(VIDEO_TYPES.TVSHOW, title, year, SRT_SOURCE, tvshow_id) return tvshow_id site_matches.append((tvshow_id, site_title, site_year)) if not site_matches: return None elif len(site_matches) == 1: self.db_connection.set_related_url(VIDEO_TYPES.TVSHOW, title, year, SRT_SOURCE, site_matches[0][0]) return site_matches[0][0] else: # there were multiple title matches and year was passed but no exact year matches found for match in site_matches: # return the match that has no year specified if match[2] is None: self.db_connection.set_related_url(VIDEO_TYPES.TVSHOW, title, year, SRT_SOURCE, match[0]) return match[0] def get_season_subtitles(self, language, tvshow_id, season): url = BASE_URL + '/ajax_loadShow.php?show=%s&season=%s&langs=&hd=%s&hi=%s' % ( tvshow_id, season, 0, 0) html = self.__get_cached_url(url, .25) # print html.decode('ascii', 'ignore') req_hi = kodi.get_setting('subtitle-hi') == 'true' req_hd = kodi.get_setting('subtitle-hd') == 'true' items = [] regex = re.compile( '<td>(\d+)</td><td>(\d+)</td><td>.*?</td><td>(.*?)</td><td.*?>(.*?)</td>.*?<td.*?>(.+?)</td><td.*?>(.*?)</td><td.*?>(.*?)</td><td.*?>(.*?)</td><td.*?><a\s+href="(.*?)">.+?</td>', re.DOTALL) for match in regex.finditer(html): season, episode, srt_lang, version, completed, hi, corrected, hd, srt_url = match.groups( ) if not language or language == srt_lang and ( not req_hi or hi) and (not req_hd or hd): item = {} item['season'] = season item['episode'] = episode item['language'] = srt_lang item['version'] = version if completed.lower() == 'completed': item['completed'] = True item['percent'] = '100' else: item['completed'] = False r = re.search('([\d.]+)%', completed) if r: item['percent'] = r.group(1) else: item['percent'] = '0' item['hi'] = True if hi else False item['corrected'] = True if corrected else False item['hd'] = True if hd else False item['url'] = srt_url items.append(item) return items def get_episode_subtitles(self, language, tvshow_id, season, episode): subtitles = self.get_season_subtitles(language, tvshow_id, season) items = [] for subtitle in subtitles: if subtitle['episode'] == str(episode): items.append(subtitle) return items def download_subtitle(self, url): url = BASE_URL + url (response, srt) = self.__get_url(url) if not hasattr(response, 'info') or 'Content-Disposition' not in response.info(): return cd = response.info()['Content-Disposition'] r = re.search('filename="(.*)"', cd) if r: filename = r.group(1) else: filename = 'addic7ed_subtitle.srt' filename = re.sub('[^\x00-\x7F]', '', filename) filename = re.sub('[<>:"/\\|?*]', '_', filename) filename = re.sub('_+', '_', filename) final_path = os.path.join(kodi.get_setting('subtitle-folder'), filename) final_path = kodi.translate_path(final_path) if not xbmcvfs.exists(os.path.dirname(final_path)): try: try: xbmcvfs.mkdirs(os.path.dirname(final_path)) except: os.makedirs(os.path.dirname(final_path)) except: logger.log( 'Failed to create directory %s' % os.path.dirname(final_path), log_utils.LOGERROR) raise with open(final_path, 'w') as f: f.write(srt) return final_path def __get_url(self, url): try: req = urllib2.Request(url) host = BASE_URL.replace('http://', '') req.add_header('User-Agent', USER_AGENT) req.add_header('Host', host) req.add_header('Referer', BASE_URL) response = urllib2.urlopen(req, timeout=10) body = response.read() body = utils2.cleanse_title(body) body = body.encode('utf-8') except Exception as e: kodi.notify(msg='Failed to connect to URL: %s' % (url), duration=5000) logger.log('Failed to connect to URL %s: (%s)' % (url, e), log_utils.LOGERROR) return ('', '') return (response, body) def __get_cached_url(self, url, cache=8): logger.log('Fetching Cached URL: %s' % url, log_utils.LOGDEBUG) before = time.time() _created, _res_header, html = self.db_connection.get_cached_url( url, cache_limit=cache) if html: logger.log('Returning cached result for: %s' % (url), log_utils.LOGDEBUG) return html.decode('utf-8') logger.log('No cached url found for: %s' % url, log_utils.LOGDEBUG) req = urllib2.Request(url) host = BASE_URL.replace('http://', '') req.add_header('User-Agent', USER_AGENT) req.add_header('Host', host) req.add_header('Referer', BASE_URL) try: response = urllib2.urlopen(req, timeout=10) html = response.read() html = utils2.cleanse_title(html) except Exception as e: kodi.notify(msg='Failed to connect to URL: %s' % (url), duration=5000) logger.log('Failed to connect to URL %s: (%s)' % (url, e), log_utils.LOGERROR) return '' self.db_connection.cache_url(url, html) after = time.time() logger.log('Cached Url Fetch took: %.2f secs' % (after - before), log_utils.LOGDEBUG) return html
def _get_db_connection(): global _db_connection if _db_connection is None: _db_connection = DB_Connection() return _db_connection