# -*- coding: utf-8 -*- ################################################################################################## import logging import xbmc import artwork ################################################################################################## log = logging.getLogger("EMBY."+__name__) ################################################################################################## class KodiItems(object): def __init__(self): self.artwork = artwork.Artwork() self.kodi_version = int(xbmc.getInfoLabel('System.BuildVersion')[:2]) def create_entry_path(self): self.cursor.execute("select coalesce(max(idPath),0) from path") kodi_id = self.cursor.fetchone()[0] + 1 return kodi_id def create_entry_file(self): self.cursor.execute("select coalesce(max(idFile),0) from files") kodi_id = self.cursor.fetchone()[0] + 1 return kodi_id def create_entry_person(self): self.cursor.execute("select coalesce(max(actor_id),0) from actor") kodi_id = self.cursor.fetchone()[0] + 1 return kodi_id def create_entry_genre(self): self.cursor.execute("select coalesce(max(genre_id),0) from genre") kodi_id = self.cursor.fetchone()[0] + 1 return kodi_id def create_entry_studio(self): self.cursor.execute("select coalesce(max(studio_id),0) from studio") kodi_id = self.cursor.fetchone()[0] + 1 return kodi_id def create_entry_bookmark(self): self.cursor.execute("select coalesce(max(idBookmark),0) from bookmark") kodi_id = self.cursor.fetchone()[0] + 1 return kodi_id def create_entry_tag(self): self.cursor.execute("select coalesce(max(tag_id),0) from tag") kodi_id = self.cursor.fetchone()[0] + 1 return kodi_id def add_path(self, path): path_id = self.get_path(path) if path_id is None: # Create a new entry path_id = self.create_entry_path() query = ( ''' INSERT INTO path(idPath, strPath) VALUES (?, ?) ''' ) self.cursor.execute(query, (path_id, path)) return path_id def get_path(self, path): query = ' '.join(( "SELECT idPath", "FROM path", "WHERE strPath = ?" )) self.cursor.execute(query, (path,)) try: path_id = self.cursor.fetchone()[0] except TypeError: path_id = None return path_id def update_path(self, path_id, path, media_type, scraper): query = ' '.join(( "UPDATE path", "SET strPath = ?, strContent = ?, strScraper = ?, noUpdate = ?", "WHERE idPath = ?" )) self.cursor.execute(query, (path, media_type, scraper, 1, path_id)) def remove_path(self, path_id): self.cursor.execute("DELETE FROM path WHERE idPath = ?", (path_id,)) def add_file(self, filename, path_id): query = ' '.join(( "SELECT idFile", "FROM files", "WHERE strFilename = ?", "AND idPath = ?" )) self.cursor.execute(query, (filename, path_id,)) try: file_id = self.cursor.fetchone()[0] except TypeError: # Create a new entry file_id = self.create_entry_file() query = ( ''' INSERT INTO files(idFile, idPath, strFilename) VALUES (?, ?, ?) ''' ) self.cursor.execute(query, (file_id, path_id, filename)) return file_id def update_file(self, file_id, filename, path_id, date_added): query = ' '.join(( "UPDATE files", "SET idPath = ?, strFilename = ?, dateAdded = ?", "WHERE idFile = ?" )) self.cursor.execute(query, (path_id, filename, date_added, file_id)) def remove_file(self, path, filename): path_id = self.get_path(path) if path_id is not None: query = ' '.join(( "DELETE FROM files", "WHERE idPath = ?", "AND strFilename = ?" )) self.cursor.execute(query, (path_id, filename,)) def get_filename(self, file_id): query = ' '.join(( "SELECT strFilename", "FROM files", "WHERE idFile = ?" )) self.cursor.execute(query, (file_id,)) try: filename = self.cursor.fetchone()[0] except TypeError: filename = "" return filename def add_people(self, kodi_id, people, media_type): def add_thumbnail(person_id, person, type_): thumbnail = person['imageurl'] if thumbnail: art = type_.lower() if "writing" in art: art = "writer" self.artwork.add_update_art(thumbnail, person_id, art, "thumb", self.cursor) def add_link(link_type, person_id, kodi_id, media_type): query = ( "INSERT OR REPLACE INTO " + link_type + "(actor_id, media_id, media_type)" "VALUES (?, ?, ?)" ) self.cursor.execute(query, (person_id, kodi_id, media_type)) cast_order = 1 if self.kodi_version > 14: for person in people: name = person['Name'] type_ = person['Type'] person_id = self._get_person(name) # Link person to content if type_ == "Actor": role = person.get('Role') query = ( ''' INSERT OR REPLACE INTO actor_link( actor_id, media_id, media_type, role, cast_order) VALUES (?, ?, ?, ?, ?) ''' ) self.cursor.execute(query, (person_id, kodi_id, media_type, role, cast_order)) cast_order += 1 elif type_ == "Director": add_link("director_link", person_id, kodi_id, media_type) elif type_ in ("Writing", "Writer"): add_link("writer_link", person_id, kodi_id, media_type) elif type_ == "Artist": add_link("actor_link", person_id, kodi_id, media_type) add_thumbnail(person_id, person, type_) else: # TODO: Remove Helix code when Krypton is RC for person in people: name = person['Name'] type_ = person['Type'] query = ' '.join(( "SELECT idActor", "FROM actors", "WHERE strActor = ?", "COLLATE NOCASE" )) self.cursor.execute(query, (name,)) try: person_id = self.cursor.fetchone()[0] except TypeError: # Cast entry does not exists self.cursor.execute("select coalesce(max(idActor),0) from actors") person_id = self.cursor.fetchone()[0] + 1 query = "INSERT INTO actors(idActor, strActor) values(?, ?)" self.cursor.execute(query, (person_id, name)) log.debug("Add people to media, processing: %s", name) finally: # Link person to content if type_ == "Actor": role = person.get('Role') if media_type == "movie": query = ( ''' INSERT OR REPLACE INTO actorlinkmovie( idActor, idMovie, strRole, iOrder) VALUES (?, ?, ?, ?) ''' ) elif media_type == "tvshow": query = ( ''' INSERT OR REPLACE INTO actorlinktvshow( idActor, idShow, strRole, iOrder) VALUES (?, ?, ?, ?) ''' ) elif media_type == "episode": query = ( ''' INSERT OR REPLACE INTO actorlinkepisode( idActor, idEpisode, strRole, iOrder) VALUES (?, ?, ?, ?) ''' ) else: return # Item is invalid self.cursor.execute(query, (person_id, kodi_id, role, cast_order)) cast_order += 1 elif type_ == "Director": if media_type == "movie": query = ( ''' INSERT OR REPLACE INTO directorlinkmovie(idDirector, idMovie) VALUES (?, ?) ''' ) elif media_type == "tvshow": query = ( ''' INSERT OR REPLACE INTO directorlinktvshow(idDirector, idShow) VALUES (?, ?) ''' ) elif media_type == "musicvideo": query = ( ''' INSERT OR REPLACE INTO directorlinkmusicvideo(idDirector, idMVideo) VALUES (?, ?) ''' ) elif media_type == "episode": query = ( ''' INSERT OR REPLACE INTO directorlinkepisode(idDirector, idEpisode) VALUES (?, ?) ''' ) else: return # Item is invalid self.cursor.execute(query, (person_id, kodi_id)) elif type_ in ("Writing", "Writer"): if media_type == "movie": query = ( ''' INSERT OR REPLACE INTO writerlinkmovie(idWriter, idMovie) VALUES (?, ?) ''' ) elif media_type == "episode": query = ( ''' INSERT OR REPLACE INTO writerlinkepisode(idWriter, idEpisode) VALUES (?, ?) ''' ) else: return # Item is invalid self.cursor.execute(query, (person_id, kodi_id)) elif type_ == "Artist": query = ( ''' INSERT OR REPLACE INTO artistlinkmusicvideo(idArtist, idMVideo) VALUES (?, ?) ''' ) self.cursor.execute(query, (person_id, kodi_id)) add_thumbnail(person_id, person, type_) def _add_person(self, name): person_id = self.create_entry_person() query = "INSERT INTO actor(actor_id, name) values(?, ?)" self.cursor.execute(query, (person_id, name)) log.debug("Add people to media, processing: %s", name) return person_id def _get_person(self, name): query = ' '.join(( "SELECT actor_id", "FROM actor", "WHERE name = ?", "COLLATE NOCASE" )) self.cursor.execute(query, (name,)) try: person_id = self.cursor.fetchone()[0] except TypeError: person_id = self._add_person(name) return person_id def add_genres(self, kodi_id, genres, media_type): if self.kodi_version > 14: # Delete current genres for clean slate query = ' '.join(( "DELETE FROM genre_link", "WHERE media_id = ?", "AND media_type = ?" )) self.cursor.execute(query, (kodi_id, media_type,)) # Add genres for genre in genres: genre_id = self._get_genre(genre) query = ( ''' INSERT OR REPLACE INTO genre_link( genre_id, media_id, media_type) VALUES (?, ?, ?) ''' ) self.cursor.execute(query, (genre_id, kodi_id, media_type)) else: # TODO: Remove Helix code when Krypton is RC # Delete current genres for clean slate if media_type == "movie": self.cursor.execute("DELETE FROM genrelinkmovie WHERE idMovie = ?", (kodi_id,)) elif media_type == "tvshow": self.cursor.execute("DELETE FROM genrelinktvshow WHERE idShow = ?", (kodi_id,)) elif media_type == "musicvideo": self.cursor.execute("DELETE FROM genrelinkmusicvideo WHERE idMVideo = ?", (kodi_id,)) # Add genres for genre in genres: query = ' '.join(( "SELECT idGenre", "FROM genre", "WHERE strGenre = ?", "COLLATE NOCASE" )) self.cursor.execute(query, (genre,)) try: genre_id = self.cursor.fetchone()[0] except TypeError: # Create genre in database self.cursor.execute("select coalesce(max(idGenre),0) from genre") genre_id = self.cursor.fetchone()[0] + 1 query = "INSERT INTO genre(idGenre, strGenre) values(?, ?)" self.cursor.execute(query, (genre_id, genre)) log.debug("Add Genres to media, processing: %s", genre) finally: # Assign genre to item if media_type == "movie": query = ( ''' INSERT OR REPLACE into genrelinkmovie(idGenre, idMovie) VALUES (?, ?) ''' ) elif media_type == "tvshow": query = ( ''' INSERT OR REPLACE into genrelinktvshow(idGenre, idShow) VALUES (?, ?) ''' ) elif media_type == "musicvideo": query = ( ''' INSERT OR REPLACE into genrelinkmusicvideo(idGenre, idMVideo) VALUES (?, ?) ''' ) else: return # Item is invalid self.cursor.execute(query, (genre_id, kodi_id)) def _add_genre(self, genre): genre_id = self.create_entry_genre() query = "INSERT INTO genre(genre_id, name) values(?, ?)" self.cursor.execute(query, (genre_id, genre)) log.debug("Add Genres to media, processing: %s", genre) return genre_id def _get_genre(self, genre): query = ' '.join(( "SELECT genre_id", "FROM genre", "WHERE name = ?", "COLLATE NOCASE" )) self.cursor.execute(query, (genre,)) try: genre_id = self.cursor.fetchone()[0] except TypeError: genre_id = self._add_genre(genre) return genre_id def add_studios(self, kodi_id, studios, media_type): if self.kodi_version > 14: for studio in studios: studio_id = self._get_studio(studio) query = ( ''' INSERT OR REPLACE INTO studio_link(studio_id, media_id, media_type) VALUES (?, ?, ?) ''') self.cursor.execute(query, (studio_id, kodi_id, media_type)) else: # TODO: Remove Helix code when Krypton is RC for studio in studios: query = ' '.join(( "SELECT idstudio", "FROM studio", "WHERE strstudio = ?", "COLLATE NOCASE" )) self.cursor.execute(query, (studio,)) try: studio_id = self.cursor.fetchone()[0] except TypeError: # Studio does not exists. self.cursor.execute("select coalesce(max(idstudio),0) from studio") studio_id = self.cursor.fetchone()[0] + 1 query = "INSERT INTO studio(idstudio, strstudio) values(?, ?)" self.cursor.execute(query, (studio_id, studio)) log.debug("Add Studios to media, processing: %s", studio) finally: # Assign studio to item if media_type == "movie": query = ( ''' INSERT OR REPLACE INTO studiolinkmovie(idstudio, idMovie) VALUES (?, ?) ''') elif media_type == "musicvideo": query = ( ''' INSERT OR REPLACE INTO studiolinkmusicvideo(idstudio, idMVideo) VALUES (?, ?) ''') elif media_type == "tvshow": query = ( ''' INSERT OR REPLACE INTO studiolinktvshow(idstudio, idShow) VALUES (?, ?) ''') elif media_type == "episode": query = ( ''' INSERT OR REPLACE INTO studiolinkepisode(idstudio, idEpisode) VALUES (?, ?) ''') self.cursor.execute(query, (studio_id, kodi_id)) def _add_studio(self, studio): studio_id = self.create_entry_studio() query = "INSERT INTO studio(studio_id, name) values(?, ?)" self.cursor.execute(query, (studio_id, studio)) log.debug("Add Studios to media, processing: %s", studio) return studio_id def _get_studio(self, studio): query = ' '.join(( "SELECT studio_id", "FROM studio", "WHERE name = ?", "COLLATE NOCASE" )) self.cursor.execute(query, (studio,)) try: studio_id = self.cursor.fetchone()[0] except TypeError: studio_id = self._add_studio(studio) return studio_id def add_streams(self, file_id, streams, runtime): # First remove any existing entries self.cursor.execute("DELETE FROM streamdetails WHERE idFile = ?", (file_id,)) if streams: # Video details for track in streams['video']: query = ( ''' INSERT INTO streamdetails( idFile, iStreamType, strVideoCodec, fVideoAspect, iVideoWidth, iVideoHeight, iVideoDuration ,strStereoMode) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ''' ) self.cursor.execute(query, (file_id, 0, track['codec'], track['aspect'], track['width'], track['height'], runtime, track['video3DFormat'])) # Audio details for track in streams['audio']: query = ( ''' INSERT INTO streamdetails( idFile, iStreamType, strAudioCodec, iAudioChannels, strAudioLanguage) VALUES (?, ?, ?, ?, ?) ''' ) self.cursor.execute(query, (file_id, 1, track['codec'], track['channels'], track['language'])) # Subtitles details for track in streams['subtitle']: query = ( ''' INSERT INTO streamdetails(idFile, iStreamType, strSubtitleLanguage) VALUES (?, ?, ?) ''' ) self.cursor.execute(query, (file_id, 2, track)) def add_playstate(self, file_id, resume, total, playcount, date_played): # Delete existing resume point self.cursor.execute("DELETE FROM bookmark WHERE idFile = ?", (file_id,)) # Set watched count self.set_playcount(file_id, playcount, date_played) if resume: bookmark_id = self.create_entry_bookmark() query = ( ''' INSERT INTO bookmark( idBookmark, idFile, timeInSeconds, totalTimeInSeconds, player, type) VALUES (?, ?, ?, ?, ?, ?) ''' ) self.cursor.execute(query, (bookmark_id, file_id, resume, total, "DVDPlayer", 1)) def set_playcount(self, file_id, playcount, date_played): query = ' '.join(( "UPDATE files", "SET playCount = ?, lastPlayed = ?", "WHERE idFile = ?" )) self.cursor.execute(query, (playcount, date_played, file_id)) def add_tags(self, kodi_id, tags, media_type): if self.kodi_version > 14: query = ' '.join(( "DELETE FROM tag_link", "WHERE media_id = ?", "AND media_type = ?" )) self.cursor.execute(query, (kodi_id, media_type)) # Add tags log.debug("Adding Tags: %s", tags) for tag in tags: tag_id = self.get_tag(kodi_id, tag, media_type) else: # TODO: Remove Helix code when Krypton is RC query = ' '.join(( "DELETE FROM taglinks", "WHERE idMedia = ?", "AND media_type = ?" )) self.cursor.execute(query, (kodi_id, media_type)) # Add tags log.debug("Adding Tags: %s", tags) for tag in tags: tag_id = self.get_tag_old(kodi_id, tag, media_type) def _add_tag(self, tag): tag_id = self.create_entry_tag() query = "INSERT INTO tag(tag_id, name) values(?, ?)" self.cursor.execute(query, (tag_id, tag)) log.debug("Create tag_id: %s name: %s", tag_id, tag) return tag_id def get_tag(self, kodi_id, tag, media_type): if self.kodi_version > 14: query = ' '.join(( "SELECT tag_id", "FROM tag", "WHERE name = ?", "COLLATE NOCASE" )) self.cursor.execute(query, (tag,)) try: tag_id = self.cursor.fetchone()[0] except TypeError: tag_id = self._add_tag(tag) query = ( ''' INSERT OR REPLACE INTO tag_link(tag_id, media_id, media_type) VALUES (?, ?, ?) ''' ) self.cursor.execute(query, (tag_id, kodi_id, media_type)) else: # TODO: Remove Helix code when Krypton is RC tag_id = self.get_tag_old(kodi_id, tag, media_type) return tag_id def get_tag_old(self, kodi_id, tag, media_type): # TODO: Remove Helix code when Krypton is RC query = ' '.join(( "SELECT idTag", "FROM tag", "WHERE strTag = ?", "COLLATE NOCASE" )) self.cursor.execute(query, (tag,)) try: tag_id = self.cursor.fetchone()[0] except TypeError: # Create the tag self.cursor.execute("select coalesce(max(idTag),0) from tag") tag_id = self.cursor.fetchone()[0] + 1 query = "INSERT INTO tag(idTag, strTag) values(?, ?)" self.cursor.execute(query, (tag_id, tag)) log.debug("Create idTag: %s name: %s", tag_id, tag) finally: # Assign tag to item query = ( ''' INSERT OR REPLACE INTO taglinks( idTag, idMedia, media_type) VALUES (?, ?, ?) ''' ) self.cursor.execute(query, (tag_id, kodi_id, media_type)) return tag_id def remove_tag(self, kodi_id, tag, media_type): if self.kodi_version > 14: query = ' '.join(( "SELECT tag_id", "FROM tag", "WHERE name = ?", "COLLATE NOCASE" )) self.cursor.execute(query, (tag,)) try: tag_id = self.cursor.fetchone()[0] except TypeError: return else: query = ' '.join(( "DELETE FROM tag_link", "WHERE media_id = ?", "AND media_type = ?", "AND tag_id = ?" )) self.cursor.execute(query, (kodi_id, media_type, tag_id,)) else: # TODO: Remove Helix code when Krypton is RC query = ' '.join(( "SELECT idTag", "FROM tag", "WHERE strTag = ?", "COLLATE NOCASE" )) self.cursor.execute(query, (tag,)) try: tag_id = self.cursor.fetchone()[0] except TypeError: return else: query = ' '.join(( "DELETE FROM taglinks", "WHERE idMedia = ?", "AND media_type = ?", "AND idTag = ?" )) self.cursor.execute(query, (kodi_id, media_type, tag_id,))