From ff534148b9518ee7705d88f98a279e6de0de6e52 Mon Sep 17 00:00:00 2001 From: Ratan Sunder Parai Date: Fri, 13 Nov 2015 12:17:39 +0600 Subject: [PATCH] implemented cache database --- addon.py | 45 ++++++++---- addon.xml | 2 +- changelog.txt | 4 ++ resources/lib/cinehub.py | 103 ++++++++++++++++++++++++++-- resources/lib/tmdbscraper.py | 129 +++++++++++++++++++++++++++++++---- 5 files changed, 252 insertions(+), 31 deletions(-) diff --git a/addon.py b/addon.py index c0e5fe8..33ee5ca 100644 --- a/addon.py +++ b/addon.py @@ -110,10 +110,17 @@ def showMoviesList(page=1): url = '{0}?action=play&video={1}'.format(__url__, movie.url) - li = xbmcgui.ListItem(label=movie.title, thumbnailImage=movie.posterImage) + bPosterImage = "https://image.tmdb.org/t/p/w396" + movie.posterImage + bBackdropImage = "https://image.tmdb.org/t/p/w780" + movie.backdropImage - li.setArt({ 'poster': movie.posterImage, 'fanart' : movie.backdropImage, 'thumb' : movie.posterImage }) + sPosterImage = "https://image.tmdb.org/t/p/w185" + movie.posterImage + + print "sPosterImage: " + sPosterImage + + li = xbmcgui.ListItem(label=movie.title, thumbnailImage=sPosterImage) + + li.setArt({ 'poster': bPosterImage, 'fanart' : bBackdropImage, 'thumb' : sPosterImage }) info = { 'genre': movie.genres, @@ -139,7 +146,7 @@ def showMoviesList(page=1): # add contex menu cm =[] - msg = 'RunPlugin({0}?action=addToLibrary&title={1}&year={2}&url={3})'.format(__url__, urllib.quote_plus(movie.title), movie.year, movie.url) + msg = 'RunPlugin({0}?action=addToLibrary&imdbid={1}&title={2}&year={3}&url={4})'.format(__url__, movie.imdbid, urllib.quote_plus(movie.title), movie.year, movie.url) cm.append(('Add To Library', msg)) li.addContextMenuItems(cm, False) @@ -190,20 +197,24 @@ def router(paramstring): elif params['action'] == 'playStream': print "all params : " + params['title'] - play_stream(params['title'], params['year'], params['video']) + + if params.has_key('imdbid'): + play_stream(params['title'], params['year'], params['video'], params['imdbid']) + else: + play_stream(params['title'], params['year'], params['video']) elif params['action']=='recentMoviesWithPage': showMoviesList(params['page']) elif params['action'] == 'addToLibrary': print "plugin.video.cinehub: " + params['title'] - addMovieToLibrary(params['title'], params['year'], params['url']) + addMovieToLibrary(params['title'], params['year'], params['url'], params['imdbid']) else: showCatagoryList() -def addMovieToLibrary(title, year , url): +def addMovieToLibrary(title, year , url, imdbid): # get movie folder location # @@ -211,7 +222,6 @@ def addMovieToLibrary(title, year , url): # xbmc.translatePath() is used for translating "speciall://sample" path to full path for writing to disk # xbmcaddon.Addon().getSetting('id') is for reading movie libray info from setting library_folder = os.path.join(xbmc.translatePath(xbmcaddon.Addon().getSetting('movie_library'))) - print "Movie library path: " + library_folder # make movie directory if not already created xbmcvfs.mkdir(library_folder) @@ -230,7 +240,7 @@ def addMovieToLibrary(title, year , url): file = xbmcvfs.File(movie_file, 'w') - content = '%s?action=playStream&title=%s&year=%s&video=%s' % (__url__, urllib.quote_plus(title), year, url) + content = '%s?action=playStream&imdbid=%s&title=%s&year=%s&video=%s' % (__url__, imdbid, urllib.quote_plus(title), year, url) file.write(str(content)) @@ -247,7 +257,7 @@ def play_video(path): # Pass the item to the Kodi player. xbmcplugin.setResolvedUrl(addon_handle, True, listitem=play_item) -def play_stream(title, year, path): +def play_stream(title, year, path, imdbid=''): # get movie info mInfo = movieinfo() @@ -256,7 +266,13 @@ def play_stream(title, year, path): name = '%s (%s)' % (title, str(year)) scrobber = tmdbscraper() - movie = scrobber.getMovieInfo(name) + + print "imdbid from play_stream " + imdbid + + if imdbid: + movie = scrobber.getMovieInfo(name, imdbid=imdbid) + else: + movie = scrobber.getMovieInfo(name) info = { 'genre': movie.genres, @@ -274,12 +290,17 @@ def play_stream(title, year, path): 'director' : movie.director, 'writer' : movie.writer } - play_item = xbmcgui.ListItem(label=movie.title, thumbnailImage=movie.posterImage, path=path) + + sPosterImage = "https://image.tmdb.org/t/p/w185" + movie.posterImage + + print "sPosterImage url while playing: " + sPosterImage + + play_item = xbmcgui.ListItem(label=movie.title, thumbnailImage=sPosterImage, path=path) play_item.setInfo('video', info) - play_item.setArt({'thumb' : movie.posterImage }) + play_item.setArt({'thumb' : sPosterImage }) # Pass the item to the Kodi player. xbmcplugin.setResolvedUrl(addon_handle, True, listitem=play_item) diff --git a/addon.xml b/addon.xml index a2249cd..edc2d22 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@  - + diff --git a/changelog.txt b/changelog.txt index fe48668..49ada10 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,7 @@ +v1.2.0 +- The addon is getting faster and responce time is getting lower :p +- implemented cache so that you can remember movie information in lightning speed. But don't try to break the sound barrier, you are not quite ready yet! + v1.1.12 - better movie recognition diff --git a/resources/lib/cinehub.py b/resources/lib/cinehub.py index c07c209..7d8a89d 100644 --- a/resources/lib/cinehub.py +++ b/resources/lib/cinehub.py @@ -26,11 +26,62 @@ from tmdbscraper import tmdbscraper import threading import xbmcaddon +import os +import xbmc +import sqlite3 +import sys class cinehub: # movie list movieList = [] + + # path to database + dburl = urldb = os.path.join(xbmc.translatePath("special://userdata/addon_data/plugin.video.cinehub/cinehubdb.db")) + + def __init__(self): + + dbcon = sqlite3.connect(self.dburl) + + # for dic output + # dbcon.row_factory = sqlite3.Row + + # get cursor + dbcur = dbcon.cursor() + + # create database if not already created + try: + #create link_url table + dbcur.execute("CREATE TABLE url_matcher (link_url text , video_url text)") + + #create movie_info table + dbcur.execute('''CREATE TABLE movie_info + ( + url text, + title text, + imdbid text, + genres text, + rating real, + runtime integer, + tagline text, + totalVote integer, + releaseDate text, + overview text, + posterImage text, + backdropImage text, + year integer, + writer text, + director text, + castandrole text + )''') + + # commit change + dbcon.commit() + except: + pass + + #close the database connection + dbcon.close() # function to call the getMovieList with appropiate URL and page number def getSearchedMovieList(self, movieName): @@ -89,15 +140,24 @@ def getMovieList(self, url): return self.movieList def worker(self, name, url, session): - resolvedUrl = self.getVideoLink(session, url) + # get cursor + dbcon = sqlite3.connect(self.dburl) + dbcur = dbcon.cursor() + + resolvedUrl = self.matchUrl(session, url, dbcon, dbcur) + + # close the connection + dbcon.close() # if resolvedUrl is none then stop the thread and do nothing - if resolvedUrl == None: + if resolvedUrl == None or resolvedUrl == "": return + # save movie info into database + # now try to get meta info from tmdb database scrapper = tmdbscraper() - mMovieInfo = scrapper.getMovieInfo(name) + mMovieInfo = scrapper.getMovieInfo(name, videoUrl=resolvedUrl) # add previously resolved url to the list mMovieInfo.url = resolvedUrl @@ -106,9 +166,28 @@ def worker(self, name, url, session): # add the movieino object to the movie list self.movieList.append(mMovieInfo) + def matchUrl(self, session, url, dbcon, dbcur): + # check if the url is already being parsed + t = (url,) + dbcur.execute("SELECT * FROM url_matcher WHERE link_url = ? " , t) + + result = dbcur.fetchone() + + + # if we found it + if result : + # close the connection + dbcon.close() + # return the parsed video url + print "found in databse: " + url + return result[1] + + # if not found in database fetch the link + print "Not found in databae. starting query for url" + return self.getVideoLink(session, url, dbcur, dbcon) # get playable video link for the movie if available # if no link is available then return nothing - def getVideoLink(self, session, URL): + def getVideoLink(self, session, URL, dbcur, dbcon): # get html file result = session.get(URL).content @@ -134,11 +213,26 @@ def getVideoLink(self, session, URL): if link.lower().find("sample") != -1 or link.lower().find("trailer") != -1 : pass else: + print "inserting into database" + t = (URL, link) + dbcur.execute("INSERT INTO url_matcher VALUES (?, ?)", t) + dbcon.commit() + dbcon.close() + print "insert successful" + print "Link is : " + link return link else: tdId += 5 + except sqlite3.OperationalError: + raise + except: break + # if no link found insert empty link to database + t = (URL, '') + dbcur.execute("INSERT INTO url_matcher VALUES (?, ?)", t) + dbcon.commit() + dbcon.close() # Login to the cinehub24 server def doLogin(self): @@ -171,5 +265,6 @@ def doLogin(self): # TODO return session_requests + \ No newline at end of file diff --git a/resources/lib/tmdbscraper.py b/resources/lib/tmdbscraper.py index 185e902..c4e2e50 100644 --- a/resources/lib/tmdbscraper.py +++ b/resources/lib/tmdbscraper.py @@ -24,12 +24,21 @@ import re import urllib import base64 - +import os +import xbmc +import sqlite3 class tmdbscraper: + # path to database + dburl = urldb = os.path.join(xbmc.translatePath("special://userdata/addon_data/plugin.video.cinehub/cinehubdb.db")) + API = base64.urlsafe_b64decode("N2U5MTYyMjM1NWFjZjI3NDM3ODQzNjcyMzRlOTFhODU=") + def __init__(self): + self.dbcon = sqlite3.connect(self.dburl) + self.dbcur = self.dbcon.cursor() + def searchMovie(self, name, year=""): URL = "http://api.themoviedb.org/3/search/movie?api_key="+self.API+"&query=" + urllib.quote_plus(name) + "&year=" + str(year) result = urlopen(URL) @@ -40,7 +49,65 @@ def searchMovie(self, name, year=""): return moviejson['results'][0]['id'] - def getMovieInfo(self, name): + def getMovieInfoFromCache(self, res): + ''' + return movieinfo object created from database result + ''' + + print "return movieinfo object" + + result = [] + for m in res: + result.append(m) + + + myMovieInfo = movieinfo() + + myMovieInfo.title = result[1] + myMovieInfo.imdbid = result[2] + myMovieInfo.genres = result[3] + myMovieInfo.rating = result[4] + myMovieInfo.runtime = result[5] + myMovieInfo.tagline = result[6] + myMovieInfo.totalVote = result[7] + myMovieInfo.releaseDate = result[8] + myMovieInfo. overview = result[9] + myMovieInfo.posterImage = result[10] + myMovieInfo.backdropImage = result[11] + myMovieInfo.year = result[12] + myMovieInfo.writer = result[13] + myMovieInfo.director = result[14] + myMovieInfo.castandrole = eval(result[15]) + + return myMovieInfo + + def getMovieInfo(self, name, imdbid='', videoUrl=''): + # check if the info is available in cache + print "checking if imdbid is provided..." + print "imdbid = " + imdbid + if imdbid: + print "got imdbid" + t = (imdbid,) + searchQuery = "SELECT * FROM movie_info WHERE imdbid = ?" + self.dbcur.execute(searchQuery, t ) + result =self.dbcur.fetchone() + + if result: + return self.getMovieInfoFromCache(result) + + print "no imdbid provided." + print "check if videoUrl is provided" + if videoUrl: + print "got videoUrl: " + videoUrl + t = (videoUrl, ) + searchQuery = "SELECT * FROM movie_info WHERE url = ?" + self.dbcur.execute(searchQuery, t) + result =self.dbcur.fetchone() + print "check if match found" + if result: + print "match found with the name of movie : " + name + return self.getMovieInfoFromCache(result) + # create movieinfo object to return myMovieInfo = movieinfo() @@ -70,6 +137,18 @@ def getMovieInfo(self, name): else: searchYear = "" + # check if any movie info is avaiable in name, year pair + # if year is available for better recognition + if searchYear != "": + print "searchYear: " + searchYear + t = (searchName, searchYear) + searchQuery = "SELECT * FROM movie_info WHERE title=? AND year=?" + self.dbcur.execute(searchQuery, t) + result =self.dbcur.fetchone() + if result: + return self.getMovieInfoFromCache(result) + + # invoke search movieId = self.searchMovie(searchName, searchYear) @@ -107,11 +186,11 @@ def getMovieInfo(self, name): myMovieInfo.genres = genres try: - myMovieInfo.posterImage = "https://image.tmdb.org/t/p/w396" + mJson['poster_path'] + myMovieInfo.posterImage = mJson['poster_path'] except: pass try: - myMovieInfo.backdropImage = "https://image.tmdb.org/t/p/w780" + mJson['backdrop_path'] + myMovieInfo.backdropImage = mJson['backdrop_path'] except: pass @@ -121,18 +200,40 @@ def getMovieInfo(self, name): except: pass - listCast = cJson['cast'] - - castName = [] - castChar = [] - for cast in listCast: - name = cast['name'] - castName.append(name) - character = cast['character'] - castChar.append(character) + if cJson.has_key('cast'): + listCast = cJson['cast'] + + castName = [] + castChar = [] + for cast in listCast: + name = cast['name'] + castName.append(name) + character = cast['character'] + castChar.append(character) + + myMovieInfo.castandrole = zip(castName, castChar) - myMovieInfo.castandrole = zip(castName, castChar) + self.saveMovieCache(myMovieInfo, videoUrl) return myMovieInfo + + def saveMovieCache(self, myMovieInfo, url): + print "save movie info to database" + t = (url ,myMovieInfo.title ,myMovieInfo.imdbid ,str(myMovieInfo.genres) ,myMovieInfo.rating ,myMovieInfo.runtime ,myMovieInfo.tagline ,myMovieInfo.totalVote ,myMovieInfo.releaseDate ,myMovieInfo.overview ,myMovieInfo.posterImage ,myMovieInfo.backdropImage ,myMovieInfo.year ,myMovieInfo.writer ,myMovieInfo.director , str(myMovieInfo.castandrole)) + insertQuery = '''INSERT INTO movie_info + (url ,title ,imdbid ,genres ,rating ,runtime ,tagline ,totalVote ,releaseDate ,overview ,posterImage ,backdropImage ,year ,writer ,director ,castandrole) + VALUES + (? , ? , ? , ? , ? , ? , ? , ? , ? , ?, ? , ?, ?, ?, ? , ?) + ''' + self.dbcon.text_factory = str + self.dbcur.execute(insertQuery, t) + + self.dbcon.commit() + + def __del__(self): + try: + self.dbcon.close() + except: + pass \ No newline at end of file