def GET_SUBTILES(url,subtitle_completion1,subtitle_completion2): try: srtsubs_path1 = xbmc.translatePath('special://temp/vstream.viki.French.srt') srtsubs_path2 = xbmc.translatePath('special://temp/vstream.viki.English.srt') if (int(subtitle_completion1)>79 and se=='true'): urlreq=SIGN(url,'/subtitles/fr.srt') req = urllib2.Request(urlreq) req.add_header('User-Agent', UA) response = urllib2.urlopen(req) data=response.read() response.close() with open(srtsubs_path1, "w") as subfile: subfile.write(data) sub = 'true' if (int(subtitle_completion2)>0 and se=='true'): urlreq=SIGN(url,'/subtitles/en.srt') req = urllib2.Request(urlreq) req.add_header('User-Agent', UA) response = urllib2.urlopen(req) data=response.read() response.close() with open(srtsubs_path2, "w") as subfile: subfile.write(data) sub = 'true' else: sub = 'false' #xbmc.executebuiltin('Notification(%s, %s, %d, %s)'%('VIKI®','Subtitles not available or disabled', 4000, md+'DefaultAddonSubtitles.png')) ifVSlog('no subtitles availables') except: pass return srtsubs_path1,srtsubs_path2
def service(): ADDON = addon() interval = ADDON.getSetting('heure_verification') recordIsActivate = ADDON.getSetting('enregistrement_activer') if recordIsActivate == 'false': return pathRecording = 'special://userdata/addon_data/plugin.video.vstream/Enregistrement' path = ''.join([pathRecording]) if not xbmcvfs.exists(path): xbmcvfs.mkdir(path) recordList = xbmcvfs.listdir(path) ADDON.setSetting('path_enregistrement_programmation', path) recordInProgress = False monitor = xbmc.Monitor() while not monitor.abortRequested() and not recordInProgress == True: if monitor.waitForAbort(int(interval)): break hour = datetime.now().strftime('%d-%H-%M') + '.py' if hour in str(recordList): hour = path + '/' + hour hour = xbmc.translatePath(hour) recordInProgress = True VSlog('python ' + hour) command = 'python ' + hour proc = subprocess.Popen(command, stdout=subprocess.PIPE) p_status = proc.wait()
def service(): ADDON = addon() intervalle = ADDON.getSetting('heure_verification') enregistrementIsActif = ADDON.getSetting('enregistrement_activer') if enregistrementIsActif == 'false': return PathProgrammation = "special://userdata/addon_data/plugin.video.vstream/Enregistrement" path = "".join([PathProgrammation]) if not xbmcvfs.exists(path): xbmcvfs.mkdir(path) ListeEnregistrement = xbmcvfs.listdir(path) ADDON.setSetting('path_enregistrement_programmation', path) EnregistrementEnCours = False monitor = xbmc.Monitor() while not monitor.abortRequested() and not EnregistrementEnCours == True: if monitor.waitForAbort(int(intervalle)): break heure = datetime.now().strftime('%d-%H-%M') + '.py' if heure in str(ListeEnregistrement): heure = path + '/' + heure heure = xbmc.translatePath(heure) EnregistrementEnCours = True VSlog('python ' + heure) command ='python ' + heure proc = subprocess.Popen(command, stdout=subprocess.PIPE) p_status = proc.wait()
def service(): ADDON = addon() intervalle = ADDON.getSetting('heure_verification') enregistrementIsActif = ADDON.getSetting('enregistrement_activer') if enregistrementIsActif == 'false': return PathProgrammation = "special://userdata/addon_data/plugin.video.vstream/Enregistrement" path = "".join([PathProgrammation]) if not xbmcvfs.exists(path): xbmcvfs.mkdir(path) ListeEnregistrement = xbmcvfs.listdir(path) ADDON.setSetting('path_enregistrement_programmation', path) EnregistrementEnCours = False monitor = xbmc.Monitor() while not monitor.abortRequested() and not EnregistrementEnCours == True: if monitor.waitForAbort(int(intervalle)): break heure = datetime.now().strftime('%d-%H-%M') + '.py' if heure in str(ListeEnregistrement): heure = path + '/' + heure heure = xbmc.translatePath(heure) EnregistrementEnCours = True VSlog('python ' + heure) command = 'python ' + heure proc = subprocess.Popen(command, stdout=subprocess.PIPE) p_status = proc.wait()
def AddDownload(self, meta): sTitle = meta['title'] sUrl = meta['url'] #titre fichier sTitle = self.__createTitle(sUrl, sTitle) sTitle = self.__createDownloadFilename(sTitle) sTitle = cGui().showKeyBoard(sTitle) if (sTitle != False and len(sTitle) > 0): #chemin de sauvegarde sPath2 = xbmc.translatePath( self.ADDON.getSetting('download_folder')) dialog = xbmcgui.Dialog() sPath = dialog.browse(3, 'Downloadfolder', 'files', '', False, False, sPath2) if (sPath != ''): self.ADDON.setSetting('download_folder', sPath) sDownloadPath = xbmc.translatePath(sPath + '%s' % (sTitle)) if xbmcvfs.exists(sDownloadPath): self.DIALOG.VSinfo('Nom déjà utilisé', sTitle) return self.AddDownload(meta) else: xbmcvfs.File(sDownloadPath, 'w') try: VSlog('Ajout en liste de téléchargement ' + str(sUrl)) meta['title'] = sTitle meta['path'] = sDownloadPath cDb().insert_download(meta) return True except: #print_exc() self.DIALOG.VSinfo('Téléchargement impossible', sTitle) VSlog('Téléchargement impossible') return False
def programmation_enregistrement(self, sUrl): oGui = cGui() ADDON = addon() if 'firstonetv' in sUrl or 'bouygtel' in sUrl or 'heroku' in sUrl: sUrl = sUrl.replace('|Referer=', '" -headers "Referer:').replace( '&User-Agent=Mozilla/5.0+(X11;+Linux+i686)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Ubuntu+Chromium/48.0.2564.116+Chrome/48.0.2564.116+Safari/537.36&X-Requested-With=ShockwaveFlash/28.0.0.137&Origin=https://www.firstonetv.live', '" -headers "User-Agent:Mozilla/5.0+(X11;+Linux+i686)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Ubuntu+Chromium/48.0.2564.116+Chrome/48.0.2564.116+Safari/537.36" -headers "X-Requested-With:ShockwaveFlash/28.0.0.137" -headers "Origin:https://www.firstonetv.live" -sn -c:v copy -c:a copy' ) header = '-fflags +genpts+igndts -y -i "' + sUrl elif '.m3u8' in sUrl: header = '-fflags +genpts+igndts -y -i "' + sUrl + '"' else: header = '-re -reconnect 1 -reconnect_at_eof 1 -reconnect_streamed 1 -reconnect_delay_max 4294 -timeout 2000000000 -f mpegts -re -flags +global_header -fflags +genpts+igndts -y -i "' + sUrl + '" -headers "User-Agent: Mozilla/5.0+(X11;+Linux+i686)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Ubuntu+Chromium/48.0.2564.116+Chrome/48.0.2564.116+Safari/537.36" -sn -c:v libx264 -c:a copy -map 0 -segment_format mpegts -segment_time -1' pathEnregistrement = ADDON.getSetting( 'path_enregistrement_programmation') currentPath = ADDON.getSetting('path_enregistrement').replace( '\\', '/') ffmpeg = ADDON.getSetting('path_ffmpeg').replace('\\', '/') heureFichier = oGui.showKeyBoard( heading= "Heure du debut d'enregistrement au format Date-Heure-Minute") heureFin = oGui.showKeyBoard( heading="Heure du fin d'enregistrement au format Heure-Minute") titre = oGui.showKeyBoard(heading="Titre de l'enregistrement").replace( "'", "\\'") heureDebut = GetTimeObject(heureFichier, '%d-%H-%M') heureFin = GetTimeObject(heureFin, '%H-%M') durer = heureFin - heureDebut marge = ADDON.getSetting('marge_auto') timedelta = datetime.timedelta(minutes=int(marge)) durer = durer + timedelta realPath = xbmc.translatePath(pathEnregistrement + '/' + str(heureFichier) + '.py').replace( '\\', '\\\\') f = xbmcvfs.File(realPath, 'w') read = f.write('''#-*- coding: utf-8 -*- import os,subprocess command = '"''' + ffmpeg + '''" ''' + header + ''' -t ''' + str(durer) + ''' "''' + currentPath + titre + '''.mkv"' proc = subprocess.Popen(command, stdout=subprocess.PIPE) p_status = proc.wait() f = open("''' + currentPath + '''/test.txt",'w') f.write('Finit avec code erreur ' + str(p_status)) f.close()''') f.close() oDialog = dialog().VSinfo( 'Redemarrer Kodi pour prendre en compte la planification', 'Vstream', 10) oGui.setEndOfDirectory()
def AddDownload(self,meta): sTitle = meta['title'] sUrl = meta['url'] #titre fichier sTitle = self.__createTitle(sUrl, sTitle) sTitle = self.__createDownloadFilename(sTitle) sTitle = cGui().showKeyBoard(sTitle) if (sTitle != False and len(sTitle) > 0): #chemin de sauvegarde sPath2 = xbmc.translatePath(self.ADDON.getSetting('download_folder')) dialog = xbmcgui.Dialog() sPath = dialog.browse(3, 'Downloadfolder', 'files', '', False, False , sPath2) if (sPath != ''): self.ADDON.setSetting('download_folder',sPath) sDownloadPath = xbmc.translatePath(sPath + '%s' % (sTitle, )) if xbmcvfs.exists(sDownloadPath): self.DIALOG.VSinfo('Nom deja utilise', sTitle) return self.AddDownload(meta) else: xbmcvfs.File(sDownloadPath, 'w') try: VSlog("Rajout en liste de telechargement " + str(sUrl)) meta['title'] = sTitle meta['path'] = sDownloadPath cDb().insert_download(meta) return True except: #print_exc() self.DIALOG.VSinfo('Telechargement impossible', sTitle) VSlog("Telechargement impossible") return False
def __init__(self): self.__sMovieFolder = xbmc.translatePath( self.ADDON.getSetting('Library_folder_Movies')).decode("utf-8") self.__sTVFolder = xbmc.translatePath( self.ADDON.getSetting('Library_folder_TVs')).decode("utf-8") if not self.__sMovieFolder: #PathCache = cConfig().getSettingCache() #self.__sMovieFolder = os.path.join(PathCache,'Movies\\').decode("utf-8") self.__sMovieFolder = "special://userdata/addon_data/plugin.video.vstream/Films/" self.ADDON.setSetting('Library_folder_Movies', self.__sMovieFolder) if not xbmcvfs.exists(self.__sMovieFolder): xbmcvfs.mkdir(self.__sMovieFolder) if not self.__sTVFolder: #PathCache = cConfig().getSettingCache() #self.__sTVFolder = os.path.join(PathCache,'TVs\\').decode("utf-8") self.__sTVFolder = "special://userdata/addon_data/plugin.video.vstream/Series" Self.ADDON.setSetting('Library_folder_TVs', self.__sTVFolder) if not xbmcvfs.exists(self.__sTVFolder): xbmcvfs.mkdir(self.__sTVFolder) self.__sTitle = ''
def programmation_enregistrement(self, sUrl): oGui = cGui() ADDON = addon() if 'firstonetv' in sUrl or 'bouygtel' in sUrl or 'heroku' in sUrl: sUrl = sUrl.replace('|Referer=','" -headers "Referer:').replace('&User-Agent=Mozilla/5.0+(X11;+Linux+i686)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Ubuntu+Chromium/48.0.2564.116+Chrome/48.0.2564.116+Safari/537.36&X-Requested-With=ShockwaveFlash/28.0.0.137&Origin=https://www.firstonetv.live','" -headers "User-Agent:Mozilla/5.0+(X11;+Linux+i686)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Ubuntu+Chromium/48.0.2564.116+Chrome/48.0.2564.116+Safari/537.36" -headers "X-Requested-With:ShockwaveFlash/28.0.0.137" -headers "Origin:https://www.firstonetv.live" -sn -c:v copy -c:a copy') header = '-fflags +genpts+igndts -y -i "' + sUrl elif '.m3u8' in sUrl: header = '-fflags +genpts+igndts -y -i "' + sUrl +'"' else: header = '-re -reconnect 1 -reconnect_at_eof 1 -reconnect_streamed 1 -reconnect_delay_max 4294 -timeout 2000000000 -f mpegts -re -flags +global_header -fflags +genpts+igndts -y -i "' + sUrl +'" -headers "User-Agent: Mozilla/5.0+(X11;+Linux+i686)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Ubuntu+Chromium/48.0.2564.116+Chrome/48.0.2564.116+Safari/537.36" -sn -c:v libx264 -c:a copy -map 0 -segment_format mpegts -segment_time -1' pathEnregistrement = ADDON.getSetting('path_enregistrement_programmation') currentPath = ADDON.getSetting('path_enregistrement').replace('\\','/') ffmpeg = ADDON.getSetting('path_ffmpeg').replace('\\','/') heureFichier = oGui.showKeyBoard(heading="Heure du debut d'enregistrement au format Date-Heure-Minute") heureFin = oGui.showKeyBoard(heading="Heure du fin d'enregistrement au format Heure-Minute") titre = oGui.showKeyBoard(heading="Titre de l'enregistrement").replace("'","\\'") heureDebut = GetTimeObject(heureFichier,'%d-%H-%M') heureFin = GetTimeObject(heureFin,'%H-%M') durer = heureFin - heureDebut marge = ADDON.getSetting('marge_auto') timedelta = datetime.timedelta(minutes=int(marge)) durer = durer + timedelta realPath = xbmc.translatePath(pathEnregistrement + '/' + str(heureFichier) + '.py').replace('\\','\\\\') f = xbmcvfs.File(realPath,'w') read = f.write('''#-*- coding: utf-8 -*- import os,subprocess command = '"'''+ffmpeg+'''" '''+header+''' -t '''+str(durer)+''' "'''+currentPath+titre+'''.mkv"' proc = subprocess.Popen(command, stdout=subprocess.PIPE) p_status = proc.wait() f = open("'''+currentPath+'''/test.txt",'w') f.write('Finit avec code erreur ' + str(p_status)) f.close()''') f.close() oDialog = dialog().VSinfo('Redemarrer Kodi pour prendre en compte la planification','Vstream',10) oGui.setEndOfDirectory()
class cDb: #os.path.join(self.__oCache,'matrix.db').decode('utf-8') DB = 'special://userdata/addon_data/plugin.video.matrix/matrix.db' #important seul xbmcvfs peux lire le special REALDB = xbmc.translatePath(DB).decode('utf-8') DIALOG = dialog() ADDON = addon() def __init__(self): try: #if not os.path.exists(self.cache): if not xbmcvfs.exists(self.DB): self.db = sqlite.connect(self.REALDB) self.db.row_factory = sqlite.Row self.dbcur = self.db.cursor() self._create_tables() return except: VSlog('Error: Unable to write to %s' % self.REALDB) pass try: self.db = sqlite.connect(self.REALDB) self.db.row_factory = sqlite.Row self.dbcur = self.db.cursor() except: VSlog('Error: Unable to access to %s' % self.REALDB) pass def __del__(self): ''' Cleanup db when object destroyed ''' try: self.dbcur.close() self.db.close() except Exception, e: pass
class cDb: #os.path.join(self.__oCache,'vstream.db').decode("utf-8") DB = "special://userdata/addon_data/plugin.video.vstream/vstream.db" #important seul xbmcvfs peux lire le special REALDB = xbmc.translatePath(DB).decode("utf-8") DIALOG = dialog() def __init__(self): try: #if not os.path.exists(self.cache): if not xbmcvfs.exists(self.DB): self.db = sqlite.connect(self.REALDB) self.db.row_factory = sqlite.Row self.dbcur = self.db.cursor() self._create_tables() return except: VSlog('erreur: Impossible d ecrire sur %s' % self.REALDB ) pass try: self.db = sqlite.connect(self.REALDB) self.db.row_factory = sqlite.Row self.dbcur = self.db.cursor() except: VSlog('erreur: Impossible de ce connecter sur %s' % self.REALDB ) pass def __del__(self): ''' Cleanup db when object destroyed ''' try: self.dbcur.close() self.db.close() except Exception, e: pass
class cParentalCheck: CACHE = "special://userdata/addon_data/plugin.video.adult.stream/parental_cache.db" REALCACHE = xbmc.translatePath(CACHE).decode("utf-8") ADDON = addon() DIALOG = dialog() def __init__(self): try: if not xbmcvfs.exists(self.CACHE): self.db = sqlite.connect(self.REALCACHE) self.db.row_factory = sqlite.Row self.dbcur = self.db.cursor() self.__createdb() except: VSlog("erreur: Impossible d'écrire sur %s" % self.REALCACHE) pass try: self.db = sqlite.connect(self.REALCACHE) self.db.row_factory = sqlite.Row self.dbcur = self.db.cursor() except: VSlog("erreur: Impossible de se connecter sur %s" % self.REALCACHE) pass def __createdb(self): sql_create = "CREATE TABLE IF NOT EXISTS parental (password TEXT, timeset INTEGER);" try: self.dbcur.execute(sql_create) VSlog("Table créée") except: VSlog("erreur: Impossible de créer la table") def _cache_search(self): timestamp = None password = None matchedrow = None sql_select = "SELECT * FROM parental" #print sql_select try: self.dbcur.execute(sql_select) matchedrow = self.dbcur.fetchone() except Exception, e: VSlog('************* Error selecting from cache db: %s' % e, 4) if matchedrow: session_time = 180 sMatchedrow = dict(matchedrow) VSlog('MATCHEDROW: %s' % (str(sMatchedrow))) timestamp = sMatchedrow['timeset'] password = sMatchedrow['password'] if password: try: now = time.time() check = now - 60*session_time if (not timestamp): timestamp = 0 except: now = time.time() check = now - 60*session_time timestamp = 0 VSlog('TIMESTAMP: %s' % (str(timestamp))) VSlog('CHECK: %s' % (str(check))) if (timestamp < check): sCheckParental = self.checkParental() return sCheckParental else: return True else: sCheckParental = self.checkParental() return sCheckParental
class cTVTSvod: BASE_URL = "https://www.tvtsvod.com/" SEARCH_MOVIES = urlparse.urljoin(BASE_URL, "/search.php?search_string=%s") MOVIE_INFO = urlparse.urljoin(BASE_URL, "/video/%s/") CACHE = "special://userdata/addon_data/plugin.video.adult.stream/trans_video_cache.db" #important seul xbmcvfs peux lire le special REALCACHE = xbmc.translatePath(CACHE).decode("utf-8") #enlève les tags html d'une string TAG_RE = re.compile(r'<[^>]+>') #SMALL_RE = re.compile() ADDON = addon() DIALOG = dialog() def __init__(self, debug=False): self.debug = debug self.poster = 'https://img2.vod.com/image2/xfront/%s/%s.xfront.0.jpg' # self.fanart = 'https://caps1cdn.adultempire.com/r/%s/1280/%s_00500_1280.jpg' #self.poster_actor = 'https://imgs1cdn.adultempire.com/actors/%sh.jpg' try: if not xbmcvfs.exists(self.CACHE): self.db = sqlite.connect(self.REALCACHE) self.db.row_factory = sqlite.Row self.dbcur = self.db.cursor() self.__createdb() except: #VSlog("erreur: Impossible d'écrire sur %s" % self.REALCACHE) pass try: self.db = sqlite.connect(self.REALCACHE) self.db.row_factory = sqlite.Row self.dbcur = self.db.cursor() except: VSlog("erreur: Impossible de se connecter sur %s" % self.REALCACHE) pass def __createdb(self): sql_create = "CREATE TABLE IF NOT EXISTS trans_movie ("\ "tvtsvod_id TEXT, "\ "title TEXT, "\ "year INTEGER,"\ "director TEXT, "\ "writer TEXT, "\ "tagline TEXT, "\ "credits TEXT,"\ "vote_average FLOAT, "\ "vote_count TEXT, "\ "runtime TEXT, "\ "overview TEXT,"\ "mpaa TEXT, "\ "premiered TEXT, "\ "genre TEXT, "\ "studio TEXT,"\ "status TEXT,"\ "poster_path TEXT, "\ "trailer TEXT, "\ "backdrop_path TEXT,"\ "playcount INTEGER,"\ "UNIQUE(tvtsvod_id, title, year)"\ ");" try: self.dbcur.execute(sql_create) VSlog("Table créée") except: VSlog("erreur: Impossible de créer la table") # cherche dans les films ou serie l'id par le nom return ID ou False def get_idbyname(self, name, page=1): meta = {} url = self.SEARCH_MOVIES % (page, name) html = client.request(url) fragment = dom_parser2.parse_dom(html, 'div', {'class': 'movie_box'}) if not fragment: return False if fragment: movie_url = dom_parser2.parse_dom(fragment, 'a', req='href') tvtsvod_id = (movie_url[0].attrs['href']).split('/', 5)[4] return tvtsvod_id # Search movie by title. def search_movie_name(self, name): meta = {} name = name.replace('!', '') url = self.SEARCH_MOVIES % (quote_plus(name)) html = client.request(url) fragment = dom_parser2.parse_dom(html, 'div', {'class': 'movie_box'}) if not fragment: meta = {} if fragment: movie_url = dom_parser2.parse_dom(fragment, 'a', req='href') tvtsvod_id = (movie_url[0].attrs['href']).split('/', 5)[4] meta = self.search_movie_id(tvtsvod_id) xbmc.log('DATA URL: %s' % (str(url)), xbmc.LOGNOTICE) xbmc.log('MOVIE NAME: %s' % (str(name)), xbmc.LOGNOTICE) # xbmc.log('MOVIE ID: %s' % (str(tvtsvod_id)), xbmc.LOGNOTICE) return meta # Get the basic movie information for a specific movie id. def search_movie_id(self, movie_id): result = self._call(self.MOVIE_INFO, str(movie_id)) return result def __set_playcount(self, overlay): if int(overlay) == 7: return 1 else: return 0 def _format(self, meta, name): _meta = {} _meta['tvtsvod_id'] = '' _meta['title'] = name _meta['runtime'] = '' _meta['plot'] = '' _meta['year'] = '' _meta['trailer_url'] = '' _meta['genre'] = '' _meta['studio'] = '' _meta['status'] = '' _meta['cast'] = [] _meta['cover_url'] = '' _meta['backdrop_url'] = '' _meta['overlay'] = 6 _meta['playcount'] = 0 if not 'title' in meta: _meta['title'] = name else: _meta['title'] = meta['title'] if 'tvtsvod_id' in meta: _meta['tvtsvod_id'] = meta['tvtsvod_id'] if 'year' in meta: _meta['year'] = meta['year'] if 'runtime' in meta: if meta['runtime'] > 0: _meta['runtime'] = int(meta['runtime']) else: _meta['runtime'] = 0 if 'overview' in meta: _meta['plot'] = meta['overview'] if 'studio' in meta: _meta['studio'] = meta['studio'] if 'genre' in meta: _meta['genre'] = "" for genre in meta['genre']: if _meta['genre'] == "": _meta['genre'] += genre['name'] else: _meta['genre'] += ' / ' + genre['name'] if 'trailer' in meta: _meta['trailer'] = meta['trailer'] else: _meta['trailer'] = "" if 'backdrop_path' in meta: _meta['backdrop_url'] = meta['backdrop_path'] if 'poster_path' in meta: _meta['cover_url'] = meta['poster_path'] if not 'playcount' in meta: _meta['playcount'] = self.__set_playcount(6) else: _meta['playcount'] = meta['playcount'] if 'credits' in meta: meta['credits'] = eval(str(meta['credits'])) licast = [] for cast in meta['credits']['cast']: licast.append((cast['name'], str(cast['actor_url']))) _meta['cast'] = licast return _meta def _clean_title(self, title): title = title.replace(' ', '') title = title.lower() return title def _cache_search(self, media_type, name, tvtsvod_id='', year=''): if media_type == "transmovie": sql_select = "SELECT * FROM trans_movie" if tvtsvod_id: sql_select = sql_select + " WHERE tvtsvod_id = '%s'" % tvtsvod_id else: sql_select = sql_select + " WHERE title = '%s'" % name if year: sql_select = sql_select + " AND year = '%s'" % year #print sql_select try: self.dbcur.execute(sql_select) matchedrow = self.dbcur.fetchone() except Exception, e: VSlog('************* Error selecting from cache db: %s' % e, 4) return None if matchedrow: VSlog('Found meta information by name in cache table') return dict(matchedrow) else: VSlog('No match in local DB') return None
class cDb: #os.path.join(self.__oCache,'adult.stream.db').decode("utf-8") DB = "special://userdata/addon_data/plugin.video.adult.stream/adult.stream.db" #important seul xbmcvfs peux lire le special REALDB = xbmc.translatePath(DB).decode("utf-8") DIALOG = dialog() def __init__(self): try: #if not os.path.exists(self.cache): if not xbmcvfs.exists(self.DB): self.db = sqlite.connect(self.REALDB) self.db.row_factory = sqlite.Row self.dbcur = self.db.cursor() self._create_tables() except: VSlog('erreur: Impossible d ecrire sur %s' % self.REALDB) pass try: self.db = sqlite.connect(self.REALDB) self.db.row_factory = sqlite.Row self.dbcur = self.db.cursor() except: VSlog('erreur: Impossible de ce connecter sur %s' % self.REALDB) pass def __del__(self): ''' Cleanup db when object destroyed ''' try: self.dbcur.close() self.dbcon.close() except: pass def _create_tables(self): sql_create2 = "DROP TABLE history" ''' Create table ''' sql_create = "CREATE TABLE IF NOT EXISTS history (" " addon_id integer PRIMARY KEY AUTOINCREMENT, " "title TEXT, " "disp TEXT, " "icone TEXT, " "isfolder TEXT, " "level TEXT, " "lastwatched TIMESTAMP " ", " "UNIQUE(title)" ");" self.dbcur.execute(sql_create) sql_create = "CREATE TABLE IF NOT EXISTS resume (" " addon_id integer PRIMARY KEY AUTOINCREMENT, " "title TEXT, " "hoster TEXT, " "point TEXT, " "UNIQUE(title, hoster)" ");" self.dbcur.execute(sql_create) sql_create = "CREATE TABLE IF NOT EXISTS watched (" " addon_id integer PRIMARY KEY AUTOINCREMENT, " "title TEXT, " "site TEXT, " "UNIQUE(title, site)" ");" self.dbcur.execute(sql_create) sql_create = "CREATE TABLE IF NOT EXISTS favorite (" " addon_id integer PRIMARY KEY AUTOINCREMENT, " "title TEXT, " "siteurl TEXT, " "site TEXT, " "fav TEXT, " "cat TEXT, " "icon TEXT, " "fanart TEXT, " "UNIQUE(title, site)" ");" self.dbcur.execute(sql_create) #sql_create = "DROP TABLE download" #self.dbcur.execute(sql_create) sql_create = "CREATE TABLE IF NOT EXISTS download (" " addon_id integer PRIMARY KEY AUTOINCREMENT, " "title TEXT, " "url TEXT, " "path TEXT, " "cat TEXT, " "icon TEXT, " "size TEXT," "totalsize TEXT, " "status TEXT, " "UNIQUE(title, path)" ");" self.dbcur.execute(sql_create) VSlog('Table initialized') #Ne pas utiliser cette fonction pour les chemins def str_conv(self, data): if isinstance(data, str): # Must be encoded in UTF-8 data = data.decode('utf8') import unicodedata data = unicodedata.normalize('NFKD', data).encode('ascii', 'ignore') data = data.decode( 'string-escape' ) #ATTENTION : provoque des bugs pour les chemins a cause du caractere '/' return data def insert_history(self, meta): #title = urllib.unquote(meta['title']).decode('ascii', 'ignore') title = self.str_conv(urllib.unquote(meta['title'])) disp = meta['disp'] icon = 'icon.png' try: ex = "INSERT INTO history (title, disp, icone) VALUES (?, ?, ?)" self.dbcur.execute(ex, (title, disp, icon)) self.db.commit() VSlog('SQL INSERT history Successfully') except Exception, e: if 'UNIQUE constraint failed' in e.message: ex = "UPDATE history set title = '%s', disp = '%s', icone= '%s' WHERE title = '%s'" % ( title, disp, icon, title) self.dbcur.execute(ex) self.db.commit() VSlog('SQL UPDATE history Successfully') VSlog('SQL ERROR INSERT') pass self.db.close()
class cTMDb: # https://developers.themoviedb.org/3/genres/get-movie-list # https://developers.themoviedb.org/3/genres/get-tv-list TMDB_GENRES = { 12: 'Aventure', 14: 'Fantastique', 16: 'Animation', 18: 'Drame', 27: 'Horreur', 28: 'Action', 35: 'Comédie', 36: 'Histoire', 37: 'Western', 53: 'Thriller', 80: 'Crime', 99: 'Documentaire', 878: 'Science-Fiction', 9648: 'Mystère', 10402: 'Musique', 10749: 'Romance', 10751: 'Familial', 10752: 'Guerre', 10759: 'Action & Aventure', 10762: 'Kids', 10763: 'News', 10764: 'Realité', 10765: 'Science-Fiction & Fantastique', 10766: 'Feuilleton', 10767: 'Talk', 10768: 'Guerre & Politique', 10769: 'Etranger', 10770: 'Téléfilm' } URL = 'https://api.themoviedb.org/3/' URL_TRAILER = 'plugin://plugin.video.youtube/play/?video_id=%s' # ancien : 'plugin://plugin.video.youtube/?action=play_video&videoid=%s' CACHE = 'special://home/userdata/addon_data/plugin.video.vstream/video_cache.db' # important seul xbmcvfs peux lire le special try: REALCACHE = xbmc.translatePath(CACHE).decode('utf-8') except AttributeError: REALCACHE = xbmc.translatePath(CACHE) ADDON = addon() def __init__(self, api_key='', debug=False, lang='fr'): self.api_key = self.ADDON.getSetting('api_tmdb') self.debug = debug self.lang = lang self.poster = 'https://image.tmdb.org/t/p/%s' % self.ADDON.getSetting( 'poster_tmdb') self.fanart = 'https://image.tmdb.org/t/p/%s' % self.ADDON.getSetting( 'backdrop_tmdb') try: if not xbmcvfs.exists(self.CACHE): # f = open(self.cache, 'w') # f.close() self.db = sqlite.connect(self.REALCACHE) self.db.row_factory = sqlite.Row self.dbcur = self.db.cursor() self.__createdb() return except: VSlog('Error: Unable to write on %s' % self.REALCACHE) pass try: self.db = sqlite.connect(self.REALCACHE) self.db.row_factory = sqlite.Row self.dbcur = self.db.cursor() except: VSlog('Error: Unable to connect to %s' % self.REALCACHE) pass def __createdb(self): sql_create = "CREATE TABLE IF NOT EXISTS movie ("\ "imdb_id TEXT, "\ "tmdb_id TEXT, "\ "title TEXT, "\ "year INTEGER,"\ "director TEXT, "\ "writer TEXT, "\ "tagline TEXT, "\ "credits TEXT,"\ "vote_average FLOAT, "\ "vote_count TEXT, "\ "runtime TEXT, "\ "overview TEXT,"\ "mpaa TEXT, "\ "premiered TEXT, "\ "genre TEXT, "\ "studio TEXT,"\ "status TEXT,"\ "poster_path TEXT, "\ "trailer TEXT, "\ "backdrop_path TEXT,"\ "playcount INTEGER,"\ "UNIQUE(imdb_id, tmdb_id, title, year)"\ ");" try: self.dbcur.execute(sql_create) except: VSlog('Error: Cannot create table') sql_create = "CREATE TABLE IF NOT EXISTS tvshow ("\ "imdb_id TEXT, "\ "tmdb_id TEXT, "\ "title TEXT, "\ "year INTEGER,"\ "director TEXT, "\ "writer TEXT, "\ "credits TEXT,"\ "vote_average FLOAT, "\ "vote_count TEXT, "\ "runtime TEXT, "\ "overview TEXT,"\ "mpaa TEXT, "\ "premiered TEXT, "\ "genre TEXT, "\ "studio TEXT,"\ "status TEXT,"\ "poster_path TEXT,"\ "trailer TEXT, "\ "backdrop_path TEXT,"\ "playcount INTEGER,"\ "UNIQUE(imdb_id, tmdb_id, title)"\ ");" self.dbcur.execute(sql_create) sql_create = "CREATE TABLE IF NOT EXISTS season ("\ "imdb_id TEXT, "\ "tmdb_id TEXT, " \ "season INTEGER, "\ "year INTEGER,"\ "premiered TEXT, "\ "poster_path TEXT,"\ "playcount INTEGER,"\ "UNIQUE(imdb_id, tmdb_id, season)"\ ");" self.dbcur.execute(sql_create) sql_create = "CREATE TABLE IF NOT EXISTS episode ("\ "imdb_id TEXT, "\ "tmdb_id TEXT, "\ "episode_id TEXT, "\ "season INTEGER, "\ "episode INTEGER, "\ "title TEXT, "\ "director TEXT, "\ "writer TEXT, "\ "overview TEXT, "\ "vote_average FLOAT, "\ "premiered TEXT, "\ "poster_path TEXT, "\ "playcount INTEGER, "\ "UNIQUE(imdb_id, tmdb_id, episode_id, title)"\ ");" self.dbcur.execute(sql_create) VSlog('table creee') def __del__(self): """ Cleanup db when object destroyed """ try: self.dbcur.close() self.db.close() except: pass def getToken(self): result = self._call('authentication/token/new', '') total = len(result) if (total > 0): url = 'https://www.themoviedb.org/authenticate/' try: #Si possible on ouvre la page automatiquement dans un navigateur internet. webbrowser.open(url + result['request_token']) except: pass sText = (self.ADDON.VSlang(30421)) % (url, result['request_token']) DIALOG = dialog() oDialog = DIALOG.VSyesno(sText) if (oDialog == 0): return False if (oDialog == 1): result = self._call('authentication/session/new', 'request_token=' + result['request_token']) if 'success' in result and result['success']: self.ADDON.setSetting('tmdb_session', str(result['session_id'])) DIALOG.VSinfo(self.ADDON.VSlang(30000)) return else: DIALOG.VSerror('Erreur' + self.ADDON.VSlang(30000)) return # xbmc.executebuiltin('Container.Refresh') return return # cherche dans les films ou serie l'id par le nom, return ID ou FALSE def get_idbyname(self, name, year='', mediaType='movie', page=1): if year: term = QuotePlus(name) + '&year=' + year else: term = QuotePlus(name) meta = self._call('search/' + str(mediaType), 'query=' + term + '&page=' + str(page)) if 'errors' not in meta and 'status_code' not in meta: # si pas de résultat avec l'année, on teste sans l'année if 'total_results' in meta and meta['total_results'] == 0 and year: meta = self.search_movie_name(name, '') # cherche 1 seul resultat if 'total_results' in meta and meta['total_results'] != 0: tmdb_id = meta['results'][0]['id'] return tmdb_id else: return False return False # Search for movies by title. def search_movie_name(self, name, year='', page=1): name = re.sub(" +", " ", name) # nettoyage du titre if year: term = QuotePlus(name) + '&year=' + year else: term = QuotePlus(name) meta = self._call('search/movie', 'query=' + term + '&page=' + str(page)) if 'errors' not in meta and 'status_code' not in meta: # si pas de résultat avec l'année, on teste sans l'année if 'total_results' in meta and meta['total_results'] == 0 and year: meta = self.search_movie_name(name, '') # cherche 1 seul resultat if 'total_results' in meta and meta['total_results'] != 0: movie = '' # s'il n'y en a qu'un, c'est le bon if meta['total_results'] == 1: movie = meta['results'][0] else: # premiere boucle, recherche la correspondance parfaite sur le nom for searchMovie in meta['results']: if searchMovie['genre_ids'] and 99 not in searchMovie[ 'genre_ids']: if self._clean_title( searchMovie['title']) == self._clean_title( name): movie = searchMovie break # sinon, hors documentaire et année proche if not movie: for searchMovie in meta['results']: if searchMovie[ 'genre_ids'] and 99 not in searchMovie[ 'genre_ids']: # controle supplémentaire sur l'année meme si déjà dans la requete if year: if 'release_date' in searchMovie and searchMovie[ 'release_date']: release_date = searchMovie[ 'release_date'] yy = release_date[:4] if int(year) - int(yy) > 1: continue # plus de deux ans d'écart, c'est pas bon movie = searchMovie break # Rien d'interessant, on prend le premier if not movie: movie = meta['results'][0] # recherche de toutes les infos tmdb_id = movie['id'] meta = self.search_movie_id(tmdb_id) else: meta = {} return meta # Search for TV shows by title. def search_tvshow_name(self, name, year='', page=1, genre=''): if year: term = QuotePlus(name) + '&year=' + year else: term = QuotePlus(name) meta = self._call('search/tv', 'query=' + term + '&page=' + str(page)) if 'errors' not in meta and 'status_code' not in meta: # si pas de résultat avec l'année, on teste sans l'année if 'total_results' in meta and meta['total_results'] == 0 and year: meta = self.search_tvshow_name(name, '') # cherche 1 seul resultat if 'total_results' in meta and meta['total_results'] != 0: movie = '' # s'il n'y en a qu'un, c'est le bon if meta['total_results'] == 1: movie = meta['results'][0] else: # premiere boucle, recherche la correspondance parfaite sur le nom for searchMovie in meta['results']: if genre == '' or genre in searchMovie['genre_ids']: movieName = searchMovie['name'] if self._clean_title( movieName) == self._clean_title(name): movie = searchMovie break # sinon, hors documentaire et année proche if not movie: for searchMovie in meta['results']: if genre and genre in searchMovie['genre_ids']: # controle supplémentaire sur l'année meme si déjà dans la requete if year: if 'release_date' in searchMovie and searchMovie[ 'release_date']: release_date = searchMovie[ 'release_date'] yy = release_date[:4] if int(year) - int(yy) > 1: continue # plus de deux ans d'écart, c'est pas bon movie = searchMovie break # Rien d'interessant, on prend le premier if not movie: movie = meta['results'][0] # recherche de toutes les infos tmdb_id = movie['id'] meta = self.search_tvshow_id(tmdb_id) else: meta = {} return meta # Get the basic movie information for a specific movie id. def search_movie_id( self, movie_id, append_to_response='append_to_response=trailers,credits'): result = self._call('movie/' + str(movie_id), append_to_response) result['tmdb_id'] = movie_id return result # obj(**self._call('movie/' + str(movie_id), append_to_response)) # Get the primary information about a TV series by id. def search_tvshow_id( self, show_id, append_to_response='append_to_response=external_ids,videos,credits' ): result = self._call('tv/' + str(show_id), append_to_response) result['tmdb_id'] = show_id return result def _format(self, meta, name): _meta = {} _meta['imdb_id'] = '' _meta['tmdb_id'] = '' _meta['tvdb_id'] = '' _meta['title'] = name _meta['media_type'] = '' _meta['rating'] = 0 _meta['votes'] = 0 _meta['duration'] = 0 _meta['plot'] = '' _meta['mpaa'] = '' _meta['premiered'] = '' _meta['year'] = '' _meta['trailer'] = '' _meta['tagline'] = '' _meta['genre'] = '' _meta['studio'] = '' _meta['status'] = '' _meta['credits'] = '' _meta['cast'] = [] _meta['director'] = '' _meta['writer'] = '' _meta['poster_path'] = '' _meta['cover_url'] = '' _meta['backdrop_path'] = '' _meta['backdrop_url'] = '' _meta['episode'] = 0 _meta['playcount'] = 0 if 'title' in meta and meta['title']: _meta['title'] = meta['title'] elif 'name' in meta and meta['name']: _meta['title'] = meta['name'] if 'id' in meta: _meta['tmdb_id'] = meta['id'] if 'tmdb_id' in meta: _meta['tmdb_id'] = meta['tmdb_id'] if 'imdb_id' in meta: _meta['imdb_id'] = meta['imdb_id'] elif 'external_ids' in meta: _meta['imdb_id'] = meta['external_ids']['imdb_id'] if 'mpaa' in meta: _meta['mpaa'] = meta['mpaa'] if 'media_type' in meta: _meta['media_type'] = meta['media_type'] if 'release_date' in meta: _meta['premiered'] = meta['release_date'] if 'premiered' in meta and meta['premiered']: _meta['premiered'] = meta['premiered'] elif 's_premiered' in meta and meta['s_premiered']: _meta['premiered'] = meta['s_premiered'] if 'year' in meta: _meta['year'] = meta['year'] elif 's_year' in meta: _meta['year'] = meta['s_year'] else: try: if 'premiered' in _meta and _meta['premiered']: _meta['year'] = int(_meta['premiered'][:4]) elif 'first_air_date' in meta and meta['first_air_date']: _meta['year'] = int(meta['first_air_date'][:4]) elif 'air_date' in meta and meta['air_date']: _meta['year'] = int(meta['air_date'][:4]) except: pass if 'rating' in meta: _meta['rating'] = meta['rating'] elif 'vote_average' in meta: _meta['rating'] = meta['vote_average'] if 'votes' in meta: _meta['votes'] = meta['votes'] elif 'vote_count' in meta: _meta['votes'] = meta['vote_count'] try: duration = 0 if 'runtime' in meta and meta['runtime']: duration = int(meta['runtime']) elif 'episode_run_time' in meta and meta['episode_run_time']: duration = int(meta['episode_run_time'][0]) if duration < 300: # en minutes duration *= 60 # Convertir les minutes TMDB en secondes pour KODI _meta['duration'] = duration except: _meta['duration'] = 0 if 'overview' in meta: _meta['plot'] = meta['overview'] if 'studio' in meta: _meta['studio'] = meta['studio'] elif 'production_companies' in meta: _meta['studio'] = '' for studio in meta['production_companies']: if _meta['studio'] == '': _meta['studio'] += studio['name'] else: _meta['studio'] += ' / ' + studio['name'] if 'genre' in meta: listeGenre = meta['genre'] if '{' in listeGenre: meta['genres'] = eval(listeGenre) else: _meta['genre'] = listeGenre if 'genres' in meta: # _meta['genre'] = '' for genre in meta['genres']: if _meta['genre'] == '': _meta['genre'] += genre['name'] else: _meta['genre'] += ' / ' + genre['name'] elif 'genre_ids' in meta: genres = self.getGenresFromIDs(meta['genre_ids']) _meta['genre'] = '' for genre in genres: if _meta['genre'] == '': _meta['genre'] += genre else: _meta['genre'] += ' / ' + genre trailer_id = '' if 'trailer' in meta and meta['trailer']: # Lecture du cache _meta['trailer'] = meta['trailer'] elif 'trailers' in meta: # Trailer d'un film retourné par TMDB try: # Recherche de la BA en français trailers = meta['trailers']['youtube'] for trailer in trailers: if trailer['type'] == 'Trailer': if 'VF' in trailer['name']: trailer_id = trailer['source'] break # pas de trailer français, on prend le premier if not trailer_id: trailer_id = meta['trailers']['youtube'][0]['source'] _meta['trailer'] = self.URL_TRAILER % trailer_id except: pass elif 'videos' in meta and meta[ 'videos']: # Trailer d'une série retourné par TMDB try: # Recherche de la BA en français trailers = meta['videos'] if len(trailers['results']) > 0: for trailer in trailers['results']: if trailer['type'] == 'Trailer' and trailer[ 'site'] == 'YouTube': trailer_id = trailer[ 'key'] # Au moins c'est un trailer, pas forcement français if 'fr' in trailer['iso_639_1']: trailer_id = trailer['key'] break # pas de trailer, on prend la premiere vidéo disponible if not trailer_id: trailer_id = meta['videos'][0]['key'] _meta['trailer'] = self.URL_TRAILER % trailer_id except: pass if 'backdrop_path' in meta and meta['backdrop_path']: _meta['backdrop_path'] = meta['backdrop_path'] _meta['backdrop_url'] = self.fanart + str(meta['backdrop_path']) if 'poster_path' in meta and meta['poster_path']: _meta['poster_path'] = meta['poster_path'] _meta['cover_url'] = self.poster + str(meta['poster_path']) # special saisons if 's_poster_path' in meta and meta['s_poster_path']: _meta['poster_path'] = meta['s_poster_path'] _meta['cover_url'] = self.poster + str(meta['s_poster_path']) if 'playcount' in meta: _meta['playcount'] = meta['playcount'] if _meta['playcount'] == 6: # Anciennement 6 = unwatched _meta['playcount'] = 0 else: _meta['playcount'] = 0 if 'tagline' in meta and meta['tagline']: _meta['tagline'] = meta['tagline'] if 'status' in meta: _meta['status'] = meta['status'] if 'writer' in meta and meta['writer']: _meta['writer'] = meta['writer'] if 'director' in meta and meta['director']: _meta['director'] = meta['director'] if 'credits' in meta and meta['credits']: # Transformation compatible pour lecture depuis le cache et retour de TMDB strmeta = str(meta['credits']) listCredits = eval(strmeta) casts = listCredits['cast'] if len(casts) > 0: licast = [] _meta['credits'] = "{u'cast': " + str(casts) + '}' # _meta['credits'] = 'u\'cast\': ' + str(casts) + '' for cast in casts: licast.append((cast['name'], cast['character'], self.poster + str(cast['profile_path']), str(cast['id']))) _meta['cast'] = licast if 'crew' in listCredits: for crew in listCredits['crew']: if crew['job'] == 'Director': _meta['director'] = crew['name'] elif crew['department'] == 'Writing': if _meta['writer'] != '': _meta['writer'] += ' / ' _meta['writer'] += '%s (%s)' % (crew['job'], crew['name']) elif crew[ 'department'] == 'Production' and 'Producer' in crew[ 'job']: if _meta['writer'] != '': _meta['writer'] += ' / ' _meta['writer'] += '%s (%s)' % (crew['job'], crew['name']) return _meta def _clean_title(self, title): title = re.sub('[^%s]' % (string.ascii_lowercase + string.digits), '', title.lower()) return title def _cache_search(self, media_type, name, tmdb_id='', year='', season='', episode=''): if media_type == 'movie': sql_select = 'SELECT * FROM movie' if tmdb_id: sql_select = sql_select + ' WHERE tmdb_id = \'%s\'' % tmdb_id else: sql_select = sql_select + ' WHERE title = \'%s\'' % name if year: sql_select = sql_select + ' AND year = %s' % year elif media_type == 'tvshow' or media_type == 'anime': sql_select = 'SELECT * FROM tvshow' if season: sql_select = 'SELECT *, season.poster_path as s_poster_path, season.premiered as s_premiered, ' \ 'season.year as s_year FROM tvshow LEFT JOIN season ON tvshow.imdb_id = season.imdb_id ' if tmdb_id: sql_select = sql_select + ' WHERE tvshow.tmdb_id = \'%s\'' % tmdb_id else: sql_select = sql_select + ' WHERE tvshow.title = \'%s\'' % name if year: sql_select = sql_select + ' AND tvshow.year = %s' % year if season: sql_select = sql_select + ' AND season.season = \'%s\'' % season try: self.dbcur.execute(sql_select) matchedrow = self.dbcur.fetchone() except Exception as e: VSlog('************* Error selecting from cache db: %s' % e, 4) return None if matchedrow: VSlog('Found meta information by name in cache table') return dict(matchedrow) else: VSlog('No match in local DB') return None def _cache_save(self, meta, name, media_type, season, year): if media_type == 'tvshow' or media_type == 'anime': return self._cache_save_tvshow(meta, name, 'tvshow', season, year) # sauvegarde de la durée en minutes, pour le retrouver en minutes comme le fait TMDB runtime = 0 if 'duration' in meta and meta['duration']: runtime = int(meta['duration']) / 60 # sauvegarde movie dans la BDD # year n'est pas forcement l'année du film mais l'année utilisée pour la recherche try: sql = 'INSERT INTO %s (imdb_id, tmdb_id, title, year, credits, writer, director, tagline, vote_average, vote_count, runtime, ' \ 'overview, mpaa, premiered, genre, studio, status, poster_path, trailer, backdrop_path, playcount) ' \ 'VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' % media_type self.dbcur.execute( sql, (meta['imdb_id'], meta['tmdb_id'], name, year, meta['credits'], meta['writer'], meta['director'], meta['tagline'], meta['rating'], meta['votes'], runtime, meta['plot'], meta['mpaa'], meta['premiered'], meta['genre'], meta['studio'], meta['status'], meta['poster_path'], meta['trailer'], meta['backdrop_path'], 0)) self.db.commit() VSlog('SQL INSERT Successfully') except Exception as e: VSlog('SQL ERROR INSERT') pass # Cache pour les séries (et animes) def _cache_save_tvshow(self, meta, name, media_type, season, year): # ecrit les saisons dans la BDD if 'seasons' in meta: self._cache_save_season(meta, season) del meta['seasons'] # sauvegarde de la durée en minutes, pour le retrouver en minutes comme le fait TMDB runtime = 0 if 'duration' in meta and meta['duration']: runtime = int(meta['duration']) / 60 # sauvegarde tvshow dans la BDD try: sql = 'INSERT INTO %s (imdb_id, tmdb_id, title, year, credits, writer, director, vote_average, vote_count, runtime, ' \ 'overview, mpaa, premiered, genre, studio, status, poster_path, trailer, backdrop_path, playcount) ' \ 'VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' % media_type self.dbcur.execute( sql, (meta['imdb_id'], meta['tmdb_id'], name, year, meta['credits'], meta['writer'], meta['director'], meta['rating'], meta['votes'], runtime, meta['plot'], meta['mpaa'], meta['premiered'], meta['genre'], meta['studio'], meta['status'], meta['poster_path'], meta['trailer'], meta['backdrop_path'], 0)) self.db.commit() VSlog('SQL INSERT Successfully') except Exception as e: VSlog('SQL ERROR INSERT') pass def _cache_save_season(self, meta, season): for s in meta['seasons']: if s['season_number'] != None and ( '%02d' % int(s['season_number'])) == season: meta['s_poster_path'] = s['poster_path'] meta['s_premiered'] = s['air_date'] meta['s_year'] = s['air_date'] try: sql = 'INSERT INTO season (imdb_id, tmdb_id, season, year, premiered, poster_path, playcount) VALUES ' \ '(?, ?, ?, ?, ?, ?, ?) ' self.dbcur.execute( sql, (meta['imdb_id'], s['id'], s['season_number'], s['air_date'], s['air_date'], s['poster_path'], 6)) self.db.commit() VSlog('SQL INSERT Successfully') except Exception: VSlog('SQL ERROR INSERT') pass def get_meta(self, media_type, name, imdb_id='', tmdb_id='', year='', season='', episode='', update=False): """ Main method to get meta data for movie or tvshow. Will lookup by name/year if no IMDB ID supplied. Args: media_type (str): 'movie' or 'tvshow' name (str): full name of movie/tvshow you are searching Kwargs: imdb_id (str): IMDB ID tmdb_id (str): TMDB ID year (str): 4 digit year of video, recommended to include the year whenever possible to maximize correct search results. season (int) episode (int) Returns: DICT of meta data or None if cannot be found. """ name = re.sub(" +", " ", name) # nettoyage du titre VSlog('Attempting to retrieve meta data for %s: %s %s %s %s' % (media_type, name, year, imdb_id, tmdb_id)) # recherche dans la base de données if not update: meta = self._cache_search(media_type, self._clean_title(name), tmdb_id, year, season, episode) if meta: meta = self._format(meta, name) return meta # recherche online meta = {} if media_type == 'movie': if tmdb_id: meta = self.search_movie_id(tmdb_id) elif name: meta = self.search_movie_name(name, year) elif media_type == 'tvshow': if tmdb_id: meta = self.search_tvshow_id(tmdb_id) elif name: meta = self.search_tvshow_name(name, year) elif media_type == 'anime': if tmdb_id: meta = self.search_tvshow_id(tmdb_id) elif name: meta = self.search_tvshow_name(name, year, genre=16) # Mise en forme des metas si trouvé if meta and 'tmdb_id' in meta: meta = self._format(meta, name) # sauvegarde dans un cache self._cache_save(meta, self._clean_title(name), media_type, season, year) else: # initialise un meta vide meta = self._format(meta, name) return meta def getUrl(self, url, page=1, term=''): # return url api exemple 'movie/popular' page en cours try: if term: term = term + '&page=' + str(page) else: term = 'page=' + str(page) result = self._call(url, term) except: return False return result def _call(self, action, append_to_response): url = '%s%s?api_key=%s&%s&language=%s' % ( self.URL, action, self.api_key, append_to_response, self.lang) oRequestHandler = cRequestHandler(url) #Permets de régler les problemes d'accents. name = oRequestHandler.request() if '/lists' in action: try: name = unicode(name, 'utf-8') except: pass name = unicodedata.normalize('NFD', name).encode( 'ascii', 'ignore').decode('unicode_escape') name = name.encode('utf-8') data = json.loads(name) return data def getPostUrl(self, action, post): tmdb_session = self.ADDON.getSetting('tmdb_session') if not tmdb_session: return sUrl = '%s%s?api_key=%s&session_id=%s' % (self.URL, action, self.api_key, tmdb_session) sPost = json.dumps(post) headers = {'Content-Type': 'application/json'} req = urllib2.Request(sUrl, sPost, headers) response = urllib2.urlopen(req) data = json.loads(response.read()) return data # retourne la liste des genres en Texte, à partir des IDs def getGenresFromIDs(self, genresID): sGenres = [] for gid in genresID: genre = self.TMDB_GENRES.get(gid) if genre: sGenres.append(genre) return sGenres
# except urllib2.HTTPError as e: # if e.code == 503: # if CloudflareBypass().check(e.headers): # cookies = e.headers['Set-Cookie'] # cookies = cookies.split(';')[0] # sHtmlContent = CloudflareBypass().GetHtml(sUrl,e.read(),cookies) #Heavy method # sHtmlContent = CloudflareBypass().GetHtml(sUrl) #For memory #http://www.jsfuck.com/ PathCache = xbmc.translatePath( xbmcaddon.Addon('plugin.video.vstream').getAddonInfo("profile")) UA = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0' def GetPrevchar(string, pos): if (pos - 1) < 0: return '' return string[pos - 1] #Fonction to return only one parameter from a string with correct closed [] () "" and '' def GetItemAlone(string, separator=' '): l = len(string) - 1 ret = ''
class cDb: DB = 'special://home/userdata/addon_data/plugin.video.vstream/vstream.db' # important seul xbmcvfs peux lire le special try: REALDB = xbmc.translatePath(DB).decode('utf-8') except AttributeError: REALDB = xbmc.translatePath(DB) DIALOG = dialog() ADDON = addon() def __init__(self): try: if not xbmcvfs.exists(self.DB): self.db = sqlite.connect(self.REALDB) self.db.row_factory = sqlite.Row self.dbcur = self.db.cursor() self._create_tables() return except: VSlog('Error: Unable to write to %s' % self.REALDB) pass try: self.db = sqlite.connect(self.REALDB) self.db.row_factory = sqlite.Row self.dbcur = self.db.cursor() except: VSlog('Error: Unable to access to %s' % self.REALDB) pass def __del__(self): ''' Cleanup db when object destroyed ''' try: self.dbcur.close() self.db.close() except Exception: pass def _create_tables(self): # sql_create2 = 'DROP TABLE history' ''' Create table ''' sql_create = "CREATE TABLE IF NOT EXISTS history ("\ "addon_id integer PRIMARY KEY AUTOINCREMENT, "\ "title TEXT, "\ "disp TEXT, "\ "icone TEXT, "\ "isfolder TEXT, "\ "level TEXT, "\ "lastwatched TIMESTAMP "", "\ "UNIQUE(title)"\ ");" self.dbcur.execute(sql_create) sql_create = "CREATE TABLE IF NOT EXISTS resume ("\ "addon_id integer PRIMARY KEY AUTOINCREMENT, "\ "title TEXT, "\ "hoster TEXT, "\ "point TEXT, "\ "UNIQUE(title, hoster)"\ ");" self.dbcur.execute(sql_create) sql_create = "CREATE TABLE IF NOT EXISTS watched ("\ "addon_id integer PRIMARY KEY AUTOINCREMENT, "\ "title TEXT, "\ "site TEXT, "\ "UNIQUE(title, site)"\ ");" self.dbcur.execute(sql_create) sql_create = "CREATE TABLE IF NOT EXISTS favorite ("\ "addon_id integer PRIMARY KEY AUTOINCREMENT, "\ "title TEXT, "\ "siteurl TEXT, "\ "site TEXT, "\ "fav TEXT, "\ "cat TEXT, "\ "icon TEXT, "\ "fanart TEXT, "\ "UNIQUE(title, site)"\ ");" self.dbcur.execute(sql_create) sql_create = "CREATE TABLE IF NOT EXISTS download ("\ "addon_id integer PRIMARY KEY AUTOINCREMENT, "\ "title TEXT, "\ "url TEXT, "\ "path TEXT, "\ "cat TEXT, "\ "icon TEXT, "\ "size TEXT,"\ "totalsize TEXT, "\ "status TEXT, "\ "UNIQUE(title, path)"\ ");" self.dbcur.execute(sql_create) VSlog('Table initialized') # Ne pas utiliser cette fonction pour les chemins def str_conv(self, data): if isinstance(data, str): # Must be encoded in UTF-8 try: data = data.decode('utf8') except AttributeError: pass import unicodedata data = unicodedata.normalize('NFKD', data).encode('ascii', 'ignore') data = data.decode( 'string-escape' ) # ATTENTION: provoque des bugs pour les chemins a cause du caractere '/' return data # *********************************** # History fonctions # *********************************** def insert_history(self, meta): # title = Unquote(meta['title']).decode('ascii', 'ignore') title = self.str_conv(Unquote(meta['title'])) disp = meta['disp'] icon = 'icon.png' try: ex = 'INSERT INTO history (title, disp, icone) VALUES (?, ?, ?)' self.dbcur.execute(ex, (title, disp, icon)) self.db.commit() VSlog('SQL INSERT history Successfully') except Exception as e: if 'UNIQUE constraint failed' in e.message: ex = "UPDATE history set title = '%s', disp = '%s', icone= '%s' WHERE title = '%s'" % ( title, disp, icon, title) self.dbcur.execute(ex) self.db.commit() VSlog('SQL UPDATE history Successfully') VSlog('SQL ERROR INSERT') pass def get_history(self): sql_select = 'SELECT * FROM history' try: self.dbcur.execute(sql_select) # matchedrow = self.dbcur.fetchone() matchedrow = self.dbcur.fetchall() return matchedrow except Exception: VSlog('SQL ERROR EXECUTE') return None def del_history(self): from resources.lib.gui.gui import cGui oGui = cGui() oInputParameterHandler = cInputParameterHandler() if oInputParameterHandler.exist('searchtext'): sql_delete = "DELETE FROM history WHERE title = '%s'" % ( oInputParameterHandler.getValue('searchtext')) else: sql_delete = 'DELETE FROM history;' try: self.dbcur.execute(sql_delete) self.db.commit() self.DIALOG.VSinfo(self.ADDON.VSlang(30041)) oGui.updateDirectory() return False, False except Exception: VSlog('SQL ERROR DELETE') return False, False # *********************************** # Watched fonctions # *********************************** def insert_watched(self, meta): title = meta['title'] if not title: return site = QuotePlus(meta['site']) ex = 'INSERT INTO watched (title, site) VALUES (?, ?)' self.dbcur.execute(ex, (title, site)) try: self.db.commit() VSlog('SQL INSERT watched Successfully') except Exception: VSlog('SQL ERROR INSERT') pass def get_watched(self, meta): title = meta['title'] if not title: return None sql_select = "SELECT * FROM watched WHERE title = '%s'" % title try: self.dbcur.execute(sql_select) # matchedrow = self.dbcur.fetchone() matchedrow = self.dbcur.fetchall() if matchedrow: return 1 return 0 except Exception: VSlog('SQL ERROR EXECUTE') return None def del_watched(self, meta): title = meta['title'] if not title: return sql_select = "DELETE FROM watched WHERE title = '%s'" % title try: self.dbcur.execute(sql_select) self.db.commit() return False, False except Exception: VSlog('SQL ERROR EXECUTE') return False, False # *********************************** # Resume fonctions # *********************************** def insert_resume(self, meta): title = self.str_conv(meta['title']) site = QuotePlus(meta['site']) # hoster = meta['hoster'] point = meta['point'] ex = "DELETE FROM resume WHERE hoster = '%s'" % site self.dbcur.execute(ex) ex = 'INSERT INTO resume (title, hoster, point) VALUES (?, ?, ?)' self.dbcur.execute(ex, (title, site, point)) try: self.db.commit() VSlog('SQL INSERT resume Successfully') except Exception: VSlog('SQL ERROR INSERT') pass def get_resume(self, meta): # title = self.str_conv(meta['title']) site = QuotePlus(meta['site']) sql_select = "SELECT * FROM resume WHERE hoster = '%s'" % site try: self.dbcur.execute(sql_select) # matchedrow = self.dbcur.fetchone() matchedrow = self.dbcur.fetchall() return matchedrow except Exception: VSlog('SQL ERROR EXECUTE') return None def del_resume(self, meta): site = QuotePlus(meta['site']) sql_select = "DELETE FROM resume WHERE hoster = '%s'" % site try: self.dbcur.execute(sql_select) self.db.commit() return False, False except Exception: VSlog('SQL ERROR EXECUTE') return False, False # *********************************** # Bookmark fonctions # *********************************** def insert_bookmark(self, meta): title = self.str_conv(meta['title']) siteurl = QuotePlus(meta['siteurl']) try: sIcon = meta['icon'].decode('UTF-8') except: sIcon = meta['icon'] try: ex = 'INSERT INTO favorite (title, siteurl, site, fav, cat, icon, fanart) VALUES (?, ?, ?, ?, ?, ?, ?)' self.dbcur.execute(ex, (title, siteurl, meta['site'], meta['fav'], meta['cat'], sIcon, meta['fanart'])) self.db.commit() self.DIALOG.VSinfo(self.ADDON.VSlang(30042), meta['title']) VSlog('SQL INSERT favorite Successfully') except Exception as e: if 'UNIQUE constraint failed' in e.message: self.DIALOG.VSinfo(self.ADDON.VSlang(30043), meta['title']) VSlog('SQL ERROR INSERT') pass def get_bookmark(self): sql_select = 'SELECT * FROM favorite' try: self.dbcur.execute(sql_select) # matchedrow = self.dbcur.fetchone() matchedrow = self.dbcur.fetchall() return matchedrow except Exception: VSlog('SQL ERROR EXECUTE') return None def del_bookmark(self): from resources.lib.gui.gui import cGui oGui = cGui() oInputParameterHandler = cInputParameterHandler() if oInputParameterHandler.exist('sCat'): sql_delete = "DELETE FROM favorite WHERE cat = '%s'" % ( oInputParameterHandler.getValue('sCat')) if oInputParameterHandler.exist('sMovieTitle'): siteUrl = oInputParameterHandler.getValue('siteUrl') sMovieTitle = oInputParameterHandler.getValue('sMovieTitle') siteUrl = QuotePlus(siteUrl) title = self.str_conv(sMovieTitle) title = title.replace("'", r"''") sql_delete = "DELETE FROM favorite WHERE siteurl = '%s' AND title = '%s'" % ( siteUrl, title) if oInputParameterHandler.exist('sAll'): sql_delete = 'DELETE FROM favorite;' try: self.dbcur.execute(sql_delete) self.db.commit() self.DIALOG.VSinfo(self.ADDON.VSlang(30044)) oGui.updateDirectory() return False, False except Exception: VSlog('SQL ERROR EXECUTE') return False, False # *********************************** # Download fonctions # *********************************** def insert_download(self, meta): title = self.str_conv(meta['title']) url = QuotePlus(meta['url']) sIcon = QuotePlus(meta['icon']) sPath = meta['path'] ex = 'INSERT INTO download (title, url, path, cat, icon, size, totalsize, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?)' self.dbcur.execute(ex, (title, url, sPath, meta['cat'], sIcon, '', '', 0)) try: self.db.commit() VSlog('SQL INSERT download Successfully') self.DIALOG.VSinfo(self.ADDON.VSlang(30042), meta['title']) except Exception: VSlog('SQL ERROR INSERT') pass def get_download(self, meta=''): if meta == '': sql_select = 'SELECT * FROM download' else: url = QuotePlus(meta['url']) sql_select = "SELECT * FROM download WHERE url = '%s' AND status = '0'" % url try: self.dbcur.execute(sql_select) matchedrow = self.dbcur.fetchall() return matchedrow except Exception: VSlog('SQL ERROR EXECUTE') return None def clean_download(self): sql_select = "DELETE FROM download WHERE status = '2'" try: self.dbcur.execute(sql_select) self.db.commit() return False, False except Exception: VSlog('SQL ERROR EXECUTE') return False, False def reset_download(self, meta): url = QuotePlus(meta['url']) sql_select = "UPDATE download SET status = '0' WHERE status = '2' AND url = '%s'" % url try: self.dbcur.execute(sql_select) self.db.commit() return False, False except Exception: VSlog('SQL ERROR EXECUTE') return False, False def del_download(self, meta): if len(meta['url']) > 1: url = QuotePlus(meta['url']) sql_select = "DELETE FROM download WHERE url = '%s'" % url elif len(meta['path']) > 1: path = meta['path'] sql_select = "DELETE FROM download WHERE path = '%s'" % path else: return try: self.dbcur.execute(sql_select) self.db.commit() return False, False except Exception: VSlog('SQL ERROR EXECUTE') return False, False def cancel_download(self): sql_select = "UPDATE download SET status = '0' WHERE status = '1'" try: self.dbcur.execute(sql_select) self.db.commit() return False, False except Exception: VSlog('SQL ERROR EXECUTE') return False, False def update_download(self, meta): path = meta['path'] size = meta['size'] totalsize = meta['totalsize'] status = meta['status'] sql_select = "UPDATE download set size = '%s', totalsize = '%s', status= '%s' WHERE path = '%s'" % ( size, totalsize, status, path) try: self.dbcur.execute(sql_select) self.db.commit() return False, False except Exception: VSlog('SQL ERROR EXECUTE') return False, False
class cTMDb: URL = "http://api.themoviedb.org/3/" CACHE = "special://userdata/addon_data/plugin.video.vstream/video_cache.db" #important seul xbmcvfs peux lire le special REALCACHE = xbmc.translatePath(CACHE).decode("utf-8") ADDON = addon() DIALOG = dialog() def __init__(self, api_key='', debug=False, lang='fr'): self.api_key = self.ADDON.getSetting('api_tmdb') self.debug = debug self.lang = lang self.poster = 'https://image.tmdb.org/t/p/%s' % self.ADDON.getSetting( 'poster_tmdb') self.fanart = 'https://image.tmdb.org/t/p/%s' % self.ADDON.getSetting( 'backdrop_tmdb') #self.cache = cConfig().getFileCache() try: #if not os.path.exists(self.cache): if not xbmcvfs.exists(self.CACHE): #f = open(self.cache,'w') #f.close() self.db = sqlite.connect(self.REALCACHE) self.db.row_factory = sqlite.Row self.dbcur = self.db.cursor() self.__createdb() except: VSlog('erreur: Impossible d ecrire sur %s' % self.REALCACHE) pass try: self.db = sqlite.connect(self.REALCACHE) self.db.row_factory = sqlite.Row self.dbcur = self.db.cursor() except: VSlog('erreur: Impossible de ce connecter sur %s' % self.REALCACHE) pass def __createdb(self): sql_create = "CREATE TABLE IF NOT EXISTS movie ("\ "imdb_id TEXT, "\ "tmdb_id TEXT, "\ "title TEXT, "\ "year INTEGER,"\ "director TEXT, "\ "writer TEXT, "\ "tagline TEXT, "\ "credits TEXT,"\ "vote_average FLOAT, "\ "vote_count TEXT, "\ "runtime TEXT, "\ "overview TEXT,"\ "mpaa TEXT, "\ "premiered TEXT, "\ "genre TEXT, "\ "studio TEXT,"\ "status TEXT,"\ "poster_path TEXT, "\ "trailer TEXT, "\ "backdrop_path TEXT,"\ "playcount INTEGER,"\ "UNIQUE(imdb_id, tmdb_id, title, year)"\ ");" try: self.dbcur.execute(sql_create) except: VSlog("erreur: ne peux pas creer de table") sql_create = "CREATE TABLE IF NOT EXISTS tvshow ("\ "imdb_id TEXT, "\ "tmdb_id TEXT, "\ "title TEXT, "\ "year INTEGER,"\ "director TEXT, "\ "writer TEXT, "\ "credits TEXT,"\ "vote_average FLOAT, "\ "vote_count TEXT, "\ "runtime TEXT, "\ "overview TEXT,"\ "mpaa TEXT, "\ "premiered TEXT, "\ "genre TEXT, "\ "studio TEXT,"\ "status TEXT,"\ "poster_path TEXT,"\ "trailer TEXT, "\ "backdrop_path TEXT,"\ "playcount INTEGER,"\ "UNIQUE(imdb_id, tmdb_id, title)"\ ");" self.dbcur.execute(sql_create) sql_create = "CREATE TABLE IF NOT EXISTS season ("\ "imdb_id TEXT, "\ "tmdb_id TEXT, " \ "season INTEGER, "\ "year INTEGER,"\ "premiered TEXT, "\ "poster_path TEXT,"\ "playcount INTEGER,"\ "UNIQUE(imdb_id, tmdb_id, season)"\ ");" self.dbcur.execute(sql_create) sql_create = "CREATE TABLE IF NOT EXISTS episode ("\ "imdb_id TEXT, "\ "tmdb_id TEXT, "\ "episode_id TEXT, "\ "season INTEGER, "\ "episode INTEGER, "\ "title TEXT, "\ "director TEXT, "\ "writer TEXT, "\ "overview TEXT, "\ "vote_average FLOAT, "\ "premiered TEXT, "\ "poster_path TEXT, "\ "playcount INTEGER, "\ "UNIQUE(imdb_id, tmdb_id, episode_id, title)"\ ");" self.dbcur.execute(sql_create) VSlog("table creer") def __del__(self): ''' Cleanup db when object destroyed ''' try: self.dbcur.close() self.dbcon.close() except: pass def getToken(self): result = self._call('authentication/token/new', '') total = len(result) if (total > 0): #self.__Token = result['token'] url = 'https://www.themoviedb.org/authenticate/' sText = (self.ADDON.VSlang(30421)) % (url, result['request_token']) oDialog = self.DIALOG.VSyesno(sText) if (oDialog == 0): return False if (oDialog == 1): #print url result = self._call('authentication/session/new', 'request_token=' + result['request_token']) if 'success' in result and result['success']: self.ADDON.setSetting('tmdb_session', str(result['session_id'])) self.DIALOG.VSinfo(self.ADDON.VSlang(30000)) return else: self.DIALOG.VSerror('Erreur' + self.ADDON.VSlang(30000)) return #xbmc.executebuiltin("Container.Refresh") return return #cherche dans les films ou serie l'id par le nom return ID ou FALSE def get_idbyname(self, name, year='', type='movie', page=1): meta = {} if year: term = quote_plus(name) + '&year=' + year else: term = quote_plus(name) meta = self._call('search/' + str(type), 'query=' + term + '&page=' + str(page)) #teste sans l'année if 'errors' not in meta and 'status_code' not in meta: if 'total_results' in meta and meta['total_results'] == 0 and year: #meta = self.get_movie_idbyname(name,'') meta = self.search_movie_name(name, '') #cherche 1 seul resultat if 'total_results' in meta and meta['total_results'] != 0: tmdb_id = meta['results'][0]['id'] return tmdb_id else: return False return False # Search for movies by title. def search_movie_name(self, name, year='', page=1): meta = {} if year: term = quote_plus(name) + '&year=' + year else: term = quote_plus(name) meta = self._call('search/movie', 'query=' + term + '&page=' + str(page)) #teste sans l'année if 'errors' not in meta and 'status_code' not in meta: if 'total_results' in meta and meta['total_results'] == 0 and year: meta = self.search_movie_name(name, '') #cherche 1 seul resultat if 'total_results' in meta and meta['total_results'] != 0: tmdb_id = meta['results'][0]['id'] #cherche toutes les infos meta = self.search_movie_id(tmdb_id) else: meta = {} return meta # Search for TV shows by title. def search_tvshow_name(self, name, year='', page=1): meta = {} if year: term = quote_plus(name) + '&year=' + year else: term = quote_plus(name) meta = self._call('search/tv', 'query=' + term + '&page=' + str(page)) if 'errors' not in meta and 'status_code' not in meta: if 'total_results' in meta and meta['total_results'] == 0 and year: meta = self.search_tvshow_name(name, '') #cherche 1 seul resultat if 'total_results' in meta and meta['total_results'] != 0: tmdb_id = meta['results'][0]['id'] #cherche toutes les infos meta = self.search_tvshow_id(tmdb_id) else: meta = {} return meta # Get the basic movie information for a specific movie id. def search_movie_id( self, movie_id, append_to_response="append_to_response=trailers,credits"): result = self._call('movie/' + str(movie_id), append_to_response) return result #obj(**self._call('movie/' + str(movie_id), append_to_response)) # Get the primary information about a TV series by id. def search_tvshow_id( self, show_id, append_to_response="append_to_response=external_ids,credits"): result = self._call('tv/' + str(show_id), append_to_response) return result def __set_playcount(self, overlay): if int(overlay) == 7: return 1 else: return 0 def _format(self, meta, name): _meta = {} _meta['imdb_id'] = '' _meta['tvdb_id'] = '' _meta['title'] = name _meta['rating'] = 0 _meta['duration'] = '' _meta['plot'] = '' _meta['mpaa'] = '' _meta['premiered'] = '' _meta['year'] = '' _meta['trailer_url'] = '' _meta['genre'] = '' _meta['studio'] = '' _meta['status'] = '' _meta['cast'] = [] _meta['cover_url'] = '' _meta['backdrop_url'] = '' _meta['overlay'] = 6 _meta['episode'] = 0 _meta['playcount'] = 0 if not 'title' in meta: _meta['title'] = name else: _meta['title'] = meta['title'] if 'tmdb_id' in meta: _meta['tmdb_id'] = meta['tmdb_id'] if 'imdb_id' in meta: _meta['imdb_id'] = meta['imdb_id'] if 'year' in meta: _meta['year'] = meta['year'] if 'premiered' in meta: _meta['premiered'] = meta['premiered'] if 'vote_average' in meta: _meta['rating'] = meta['vote_average'] if 'vote_count' in meta: _meta['votes'] = meta['vote_count'] if 'runtime' in meta: if meta['runtime'] > 0: _meta['duration'] = int(meta['runtime']) else: _meta['duration'] = 0 if 'overview' in meta: _meta['plot'] = meta['overview'] if 'production_companies' in meta: _meta['studio'] = "" for studio in meta['production_companies']: if _meta['studio'] == "": _meta['studio'] += studio['name'] else: _meta['studio'] += ' / ' + studio['name'] if 'genre' in meta: _meta['genre'] = "" for genre in eval(meta['genre']): if _meta['genre'] == "": _meta['genre'] += genre['name'] else: _meta['genre'] += ' / ' + genre['name'] if 'trailer' in meta: _meta['trailer'] = meta['trailer'] else: _meta['trailer'] = "" if 'backdrop_path' in meta: _meta['backdrop_url'] = self.fanart + str(meta['backdrop_path']) if 'poster_path' in meta: _meta['cover_url'] = self.poster + str(meta['poster_path']) if not 'playcount' in meta: _meta['playcount'] = self.__set_playcount(6) else: _meta['playcount'] = meta['playcount'] if 'tagline' in meta: _meta['tagline'] = meta['tagline'] # if 'cast' in meta: # xbmc.log("passeeeeeeeeeeeeeeeeeee") # _meta['cast'] = json.loads(_meta['cast']) if 'credits' in meta: meta['credits'] = eval(str(meta['credits'])) licast = [] for cast in meta['credits']['cast']: licast.append( (cast['name'], cast['character'], self.poster + str(cast['profile_path']), str(cast['id']))) #licast.append((cast['name'], cast['character'], self.poster+str(cast['profile_path']))) _meta['cast'] = licast _meta['writer'] = "" for crew in meta['credits']['crew']: if crew['job'] == 'Director': _meta['director'] = crew['name'] else: if _meta['writer'] == "": _meta['writer'] += '%s (%s)' % (crew['job'], crew['name']) else: _meta['writer'] += ' / %s (%s)' % (crew['job'], crew['name']) #special saisons if 's_poster_path' in meta: _meta['cover_url'] = self.poster + str(meta['s_poster_path']) if 's_premiered' in meta: _meta['premiered'] = meta['s_premiered'] if 's_year' in meta: _meta['year'] = meta['s_year'] return _meta def _clean_title(self, title): title = title.replace(' ', '') title = title.lower() return title def _cache_search(self, media_type, name, tmdb_id='', year='', season='', episode=''): if media_type == "movie": sql_select = "SELECT * FROM movie" if tmdb_id: sql_select = sql_select + " WHERE tmdb_id = '%s'" % tmdb_id else: sql_select = sql_select + " WHERE title = '%s'" % name if year: sql_select = sql_select + " AND year = %s" % year elif media_type == "tvshow": sql_select = "SELECT * FROM tvshow" if season: sql_select = "SELECT *, season.poster_path as s_poster_path, season.premiered as s_premiered, season.year as s_year FROM tvshow LEFT JOIN season ON tvshow.imdb_id = season.imdb_id" if tmdb_id: sql_select = sql_select + " WHERE tvshow.tmdb_id = '%s'" % tmdb_id else: sql_select = sql_select + " WHERE tvshow.title = '%s'" % name if year: sql_select = sql_select + " AND tvshow.year = %s" % year if season: sql_select = sql_select + " AND season.season = '%s'" % season #print sql_select try: self.dbcur.execute(sql_select) matchedrow = self.dbcur.fetchone() except Exception, e: VSlog('************* Error selecting from cache db: %s' % e, 4) return None if matchedrow: VSlog('Found meta information by name in cache table') return dict(matchedrow) else: VSlog('No match in local DB') return None
def main(self, env): if (env == 'urlresolver'): addon('script.module.urlresolver').openSettings() return elif (env == 'metahandler'): addon('script.module.metahandler').openSettings() return elif (env == 'changelog_old'): try: sUrl = 'https://raw.githubusercontent.com/Kodi-vStream/venom-xbmc-addons/master/plugin.video.vstream/changelog.txt' oRequest = urllib2.Request(sUrl) oResponse = urllib2.urlopen(oRequest) sContent = oResponse.read() self.TextBoxes('vStream Changelog', sContent) except: self.DIALOG.VSerror("%s,%s" % (self.ADDON.VSlang(30205), sUrl)) return elif (env == 'changelog'): class XMLDialog(xbmcgui.WindowXMLDialog): def __init__(self, *args, **kwargs): xbmcgui.WindowXMLDialog.__init__( self ) pass def onInit(self): self.container = self.getControl(6) self.button = self.getControl(5) self.getControl(3).setVisible(False) self.getControl(1).setLabel('ChangeLog') self.button.setLabel('OK') sUrl = 'https://api.github.com/repos/Kodi-vStream/venom-xbmc-addons/commits' oRequest = urllib2.Request(sUrl) oResponse = urllib2.urlopen(oRequest) sContent = oResponse.read() result = json.loads(sContent) listitems = [] for item in result: #autor icon = item['author']['avatar_url'] login = item['author']['login'] #message try: desc = item['commit']['message'].encode("utf-8") except: desc = 'None' listitem = xbmcgui.ListItem(label = login, label2 = desc) listitem.setArt({'icon' : icon, 'thumb' : icon}) listitems.append(listitem) self.container.addItems(listitems) self.setFocus(self.container) def onClick(self, controlId): self.close() return def onFocus(self, controlId): self.controlId = controlId def _close_dialog( self ): self.close() #path = cConfig().getAddonPath() path = "special://home/addons/plugin.video.vstream" wd = XMLDialog('DialogSelect.xml', path, "Default") wd.doModal() del wd return elif (env == 'soutient'): try: sUrl = 'https://raw.githubusercontent.com/Kodi-vStream/venom-xbmc-addons/master/plugin.video.vstream/soutient.txt' oRequest = urllib2.Request(sUrl) oResponse = urllib2.urlopen(oRequest) sContent = oResponse.read() self.TextBoxes('vStream Soutient', sContent) except: self.DIALOG.VSerror("%s,%s" % (self.ADDON.VSlang(30205), sUrl)) return elif (env == 'addon'): if self.DIALOG.VSyesno("Êtes-vous sûr ?"): #cached_Cache = cConfig().getFileCache() #cached_Cache = xbmc.translatePath(cached_Cache).decode("utf-8") cached_Cache = "special://home/userdata/addon_data/plugin.video.vstream/video_cache.db" #self.ClearDir2(cached_Cache,True) try: xbmcvfs.delete(cached_Cache) self.DIALOG.VSinfo('Clear Addon Cache, Successful[CR](Important relancer vStream)') except: self.DIALOG.VSerror('Clear Addon Cache, Error') return elif (env == 'clean'): liste = ['Historiques', 'Lecture en cours', 'Marqués vues', 'Marque-Pages', 'Téléchargements'] ret = self.DIALOG.select('BDD à supprimer', liste) #cached_DB = cConfig().getFileDB() cached_DB = "special://home/userdata/addon_data/plugin.video.vstream/vstream.db" #important seul xbmcvfs peux lire le special cached_DB = xbmc.translatePath(cached_DB).decode("utf-8") sql_drop = "" if ret > -1: if ret == 0: sql_drop = "DROP TABLE history" elif ret == 1: sql_drop = "DROP TABLE resume" elif ret == 2: sql_drop = "DROP TABLE watched" elif ret == 3: sql_drop = "DROP TABLE favorite" elif ret == 4: sql_drop = "DROP TABLE download" try: db = sqlite.connect(cached_DB) dbcur = db.cursor() dbcur.execute(sql_drop) db.commit() dbcur.close() db.close() self.DIALOG.VSok("Suppression BDD, Successful[CR](Important relancer vStream)") except: self.DIALOG.VSerror("Suppresion BDD, Error") return elif (env == 'xbmc'): if self.DIALOG.VSyesno('Êtes-vous sûr ?'): #temp = xbmc.translatePath('special://temp/').decode("utf-8") path = "special://temp/" #self.ClearDir(temp,True) try: xbmcvfs.rmdir(path, True) self.DIALOG.VSok('Clear Temp Cache, Successful[CR](Important relancer Kodi)') except: self.DIALOG.VSerror('Clear Temp Cache, Error') return elif (env == 'fi'): if self.DIALOG.VSyesno('Êtes-vous sûr ?'): #path = xbmc.translatePath('special://temp/').decode("utf-8") path = "special://temp/archive_cache/" try: xbmcvfs.rmdir(path, True) self.DIALOG.VSok('Clear Archive_cache Cache, Successful[CR](Important relancer Kodi)') except: self.DIALOG.VSerror('Clear Archive_cache Cache, Error') # filenames = next(os.walk(path))[2] # for i in filenames: # if ".fi" in i: # os.remove(os.path.join(path, i)) return elif (env == 'uplog'): if self.DIALOG.VSyesno('Êtes-vous sûr ?'): #path = xbmc.translatePath('special://logpath/').decode("utf-8") path = "special://logpath/kodi.log" UA = 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0' headers = { 'User-Agent' : UA } #filenames = next(os.walk(path))[2] #for i in filenames: if xbmcvfs.exists(path): post_data = {} cUrl = 'http://slexy.org/index.php/submit' #logop = open(path + i,'rb') logop = xbmcvfs.File(path, 'rb') result = logop.read() logop.close() post_data['raw_paste'] = result post_data['author'] = 'kodi.log' post_data['language'] = 'text' post_data['permissions'] = 1 #private post_data['expire'] = 259200 #3j post_data['submit'] = 'Submit+Paste' request = urllib2.Request(cUrl,urllib.urlencode(post_data),headers) reponse = urllib2.urlopen(request) code = reponse.geturl().replace('http://slexy.org/view/','') reponse.close() self.ADDON.setSetting('service_log', code) self.DIALOG.VSok('Ce code doit être transmis lorsque vous ouvrez une issue veuillez le noter:' + ' ' + code) return elif (env == 'search'): from resources.lib.handler.pluginHandler import cPluginHandler valid = '[COLOR green][x][/COLOR]' class XMLDialog(xbmcgui.WindowXMLDialog): ADDON = addon() def __init__(self, *args, **kwargs): xbmcgui.WindowXMLDialog.__init__( self ) pass def onInit(self): self.container = self.getControl(6) self.button = self.getControl(5) self.getControl(3).setVisible(False) self.getControl(1).setLabel(self.ADDON.VSlang(30094)) self.button.setLabel('OK') listitems = [] oPluginHandler = cPluginHandler() aPlugins = oPluginHandler.getAllPlugins() for aPlugin in aPlugins: #teste si deja dans le dsip sPluginSettingsName = 'plugin_' +aPlugin[1] bPlugin = self.ADDON.getSetting(sPluginSettingsName) #icon = os.path.join(unicode(cConfig().getRootArt(), 'utf-8'), 'sites', aPlugin[1]+'.png') icon = "special://home/addons/plugin.video.vstream/resources/art/sites/%s.png" % aPlugin[1] stitle = aPlugin[0].replace('[COLOR violet]','').replace('[COLOR orange]','').replace('[/COLOR]','').replace('[COLOR dodgerblue]','').replace('[COLOR coral]','') if (bPlugin == 'true'): stitle = ('%s %s') % (stitle, valid) listitem = xbmcgui.ListItem(label = stitle, label2 = aPlugin[2]) listitem.setArt({'icon' : icon, 'thumb' : icon}) listitem.setProperty('Addon.Summary', aPlugin[2]) listitem.setProperty('sitename', aPlugin[1]) if (bPlugin == 'true'): listitem.select(True) listitems.append(listitem) self.container.addItems(listitems) self.setFocus(self.container) def onClick(self, controlId): if controlId == 5: self.close() return elif controlId == 99: window = xbmcgui.Window(xbmcgui.getCurrentWindowId()) del window self.close() return elif controlId == 7: window = xbmcgui.Window(xbmcgui.getCurrentWindowId()) del window self.close() return elif controlId == 6: item = self.container.getSelectedItem() if item.isSelected() == True: label = item.getLabel().replace(valid,'') item.setLabel(label) item.select(False) sPluginSettingsName = ('plugin_%s') % (item.getProperty('sitename')) self.ADDON.setSetting(sPluginSettingsName, str('false')) else : label = ('%s %s') % (item.getLabel(), valid) item.setLabel(label) item.select(True) sPluginSettingsName = ('plugin_%s') % (item.getProperty('sitename')) self.ADDON.setSetting(sPluginSettingsName, str('true')) return def onFocus(self, controlId): self.controlId = controlId def _close_dialog( self ): self.close() # def onAction( self, action ): # if action.getId() in ( 9, 10, 92, 216, 247, 257, 275, 61467, 61448, ): # self.close() #path = cConfig().getAddonPath() path = "special://home/addons/plugin.video.vstream" wd = XMLDialog('DialogSelect.xml', path, "Default") wd.doModal() del wd return elif (env == 'thumb'): if self.DIALOG.VSyesno('Êtes-vous sûr ? Ceci effacera toutes les thumbnails '): text = False #path = xbmc.translatePath('special://userdata/Thumbnails/').decode("utf-8") path = "special://userdata/Thumbnails/" path_DB = "special://userdata/Database" try: xbmcvfs.rmdir(path, True) text = 'Clear Thumbnail Folder, Successful[CR]' except: text = 'Clear Thumbnail Folder, Error[CR]' #for i in os.listdir(path): # folders = os.path.join(path, i).encode('utf-8') # if os.path.isdir(folders): # p = next(os.walk(folders))[2] # for x in p: # os.remove(os.path.join(folders, x).encode('utf-8')) #filenames = next(os.walk(path2))[2] folder, items = xbmcvfs.listdir(path_DB) items.sort() for sItemName in items: if "extures" in sItemName: cached_Cache = "/".join([path_DB, sItemName]) try: xbmcvfs.delete(cached_Cache) text += 'Clear Thumbnail DB, Successful[CR]' except: text += 'Clear Thumbnail DB, Error[CR]' if text: text = "%s (Important relancer Kodi)" % text self.DIALOG.VSok(text) # for x in filenames: # if "exture" in x: # con = sqlite.connect(os.path.join(path2, x).encode('utf-8')) # cursor = con.cursor() # cursor.execute("DELETE FROM texture") # con.commit() # cursor.close() # con.close() return elif (env == 'sauv'): #dialog.select('Choose a playlist', ['Playlist #1', 'Playlist #2, 'Playlist #3']) select = self.DIALOG.VSselect(['Import','Export']) DB = "special://home/userdata/addon_data/plugin.video.vstream/vstream.db" if select >= 0: #new = self.DIALOG.browse(3, 'vStream', 'files') new = self.DIALOG.browse(3, 'vStream', "files") if new: try: if select == 0: xbmcvfs.delete(DB) #copy(source, destination)--copy file to destination, returns true/false. xbmcvfs.copy(new + 'vstream.db', DB) elif select == 1: #copy(source, destination)--copy file to destination, returns true/false. xbmcvfs.copy(DB, new + 'vstream.db') self.DIALOG.VSinfo('Import/Export DB, Successful') except: self.DIALOG.VSerror('Import/Export DB, Error') return else: return return
class cDEFAULT: CACHE = "special://userdata/addon_data/plugin.video.adult.stream/video_cache.db" CACHE_FILE = xbmc.translatePath( os.path.join( 'special://home/userdata/addon_data/plugin.video.adult.stream/', 'video_cache.db')) #important seul xbmcvfs peux lire le special REALCACHE = xbmc.translatePath(CACHE).decode("utf-8") #enlève les tags html d'une string TAG_RE = re.compile(r'<[^>]+>') #SMALL_RE = re.compile() ADDON = addon() DIALOG = dialog() def __init__(self, debug=False): self.debug = debug # if xbmcvfs.exists(self.CACHE_FILE): # statInfo = os.stat(self.CACHE_FILE) # statInfo = float(statInfo.st_size/1000) # if (statInfo > 10): # os.remove(self.CACHE_FILE) # xbmc.log('DB SIZE: %s' % (str(statInfo)), xbmc.LOGNOTICE) try: if not xbmcvfs.exists(self.CACHE): self.db = sqlite.connect(self.REALCACHE) self.db.row_factory = sqlite.Row self.dbcur = self.db.cursor() self.__createdb() except: #VSlog("erreur: Impossible d'écrire sur %s" % self.REALCACHE) pass try: self.db = sqlite.connect(self.REALCACHE) self.db.row_factory = sqlite.Row self.dbcur = self.db.cursor() except: VSlog("erreur: Impossible de se connecter sur %s" % self.REALCACHE) pass def __createdb(self): sql_create = "CREATE TABLE IF NOT EXISTS porn_movie ("\ "aebn_id INTEGER, "\ "title TEXT, "\ "year INTEGER,"\ "director TEXT, "\ "writer TEXT, "\ "tagline TEXT, "\ "credits TEXT,"\ "vote_average FLOAT, "\ "vote_count TEXT, "\ "runtime TEXT, "\ "overview TEXT,"\ "mpaa TEXT, "\ "premiered TEXT, "\ "genre TEXT, "\ "studio TEXT,"\ "status TEXT,"\ "poster_path TEXT, "\ "trailer TEXT, "\ "backdrop_path TEXT,"\ "playcount INTEGER,"\ "UNIQUE(aebn_id, title, year)"\ ");" try: self.dbcur.execute(sql_create) VSlog("Table créée") except: VSlog("erreur: Impossible de créer la table") sql_create = "CREATE TABLE IF NOT EXISTS trans_movie ("\ "aebn_id INTEGER, "\ "title TEXT, "\ "year INTEGER,"\ "director TEXT, "\ "writer TEXT, "\ "tagline TEXT, "\ "credits TEXT,"\ "vote_average FLOAT, "\ "vote_count TEXT, "\ "runtime TEXT, "\ "overview TEXT,"\ "mpaa TEXT, "\ "premiered TEXT, "\ "genre TEXT, "\ "studio TEXT,"\ "status TEXT,"\ "poster_path TEXT, "\ "trailer TEXT, "\ "backdrop_path TEXT,"\ "playcount INTEGER,"\ "UNIQUE(aebn_id, title, year)"\ ");" try: self.dbcur.execute(sql_create) VSlog("Table créée") except: VSlog("erreur: Impossible de créer la table") sql_create = "CREATE TABLE IF NOT EXISTS gay_movie ("\ "aebn_id INTEGER, "\ "title TEXT, "\ "year INTEGER,"\ "director TEXT, "\ "writer TEXT, "\ "tagline TEXT, "\ "credits TEXT,"\ "vote_average FLOAT, "\ "vote_count TEXT, "\ "runtime TEXT, "\ "overview TEXT,"\ "mpaa TEXT, "\ "premiered TEXT, "\ "genre TEXT, "\ "studio TEXT,"\ "status TEXT,"\ "poster_path TEXT, "\ "trailer TEXT, "\ "backdrop_path TEXT,"\ "playcount INTEGER,"\ "UNIQUE(aebn_id, title, year)"\ ");" try: self.dbcur.execute(sql_create) VSlog("Table créée") except: VSlog("erreur: Impossible de créer la table") def __del__(self): ''' Cleanup db when object destroyed ''' try: self.dbcur.close() self.dbcon.close() except: pass # Search movie by title. def search_movie_name(self, media_type, name): meta = cAEBN().search_movie_name(media_type, name) return meta def __set_playcount(self, overlay): if int(overlay) == 7: return 1 else: return 0 def __set_playcount(self, overlay): if int(overlay) == 7: return 1 else: return 0 def _format(self, meta, name): _meta = {} _meta['aebn_id'] = '' _meta['title'] = name _meta['runtime'] = '' _meta['plot'] = '' _meta['year'] = '' _meta['trailer_url'] = '' _meta['genre'] = '' _meta['studio'] = '' _meta['status'] = '' # _meta['cast'] = [] _meta['cover_url'] = '' _meta['backdrop_url'] = '' _meta['overlay'] = 6 _meta['playcount'] = 0 if not 'title' in meta: _meta['title'] = name else: _meta['title'] = meta['title'] if 'aebn_id' in meta: _meta['aebn_id'] = meta['aebn_id'] if 'year' in meta: _meta['year'] = meta['year'] if 'runtime' in meta: if meta['runtime'] > 0: _meta['runtime'] = int(meta['runtime']) else: _meta['runtime'] = 0 if 'overview' in meta: _meta['plot'] = meta['overview'] if 'studio' in meta: _meta['studio'] = meta['studio'] if 'genre' in meta: _meta['genre'] = "" i = 1 for genre in eval(meta['genre']): if (i < 6): if _meta['genre'] == "": _meta['genre'] += genre['name'] else: _meta['genre'] += ' / ' + genre['name'] i += 1 if 'trailer' in meta: _meta['trailer'] = meta['trailer'] else: _meta['trailer'] = "" if 'backdrop_path' in meta: _meta['backdrop_url'] = meta['backdrop_path'] if 'poster_path' in meta: _meta['cover_url'] = meta['poster_path'] if not 'playcount' in meta: _meta['playcount'] = self.__set_playcount(6) else: _meta['playcount'] = meta['playcount'] # if 'credits' in meta: # meta['credits'] = eval(str(meta['credits'])) # licast = [] # for cast in meta['credits']['cast']: # licast.append((cast['name'], urlparse.urljoin(self.AEBN_URL, str(cast['actor_img'])))) # _meta['cast'] = licast return _meta def _clean_title(self, title): title = title.replace(' ', '') title = title.replace("'", "") title = title.lower() return title def _cache_search(self, media_type, name, aebn_id='', year=''): if media_type == "pornmovie": sql_select = "SELECT * FROM porn_movie" elif media_type == "transmovie": sql_select = "SELECT * FROM trans_movie" elif media_type == "gaymovie": sql_select = "SELECT * FROM gay_movie" if aebn_id: sql_select = sql_select + " WHERE aebn_id = '%s'" % aebn_id else: sql_select = sql_select + " WHERE title = '%s'" % name # if year: # sql_select = sql_select + " AND year = '%s'" % year #print sql_select try: self.dbcur.execute(sql_select) matchedrow = self.dbcur.fetchone() except Exception, e: VSlog('************* Error selecting from cache db: %s' % e, 4) return None if matchedrow: VSlog('Found meta information by name in cache table') return dict(matchedrow) else: VSlog('No match in local DB') return None