def __tvmaze_search(show_d, season_n=None, episode_n=None): folder = show_d['folder'] query = {"tvmaze": None, "imdb": None, "folder": show_d['folder']} query_type = None if "tvmaze" in show_d: if show_d["tvmaze"] and "id" in show_d["tvmaze"]: query["tvmaze"] = str(show_d["tvmaze"]["id"]) if show_d['imdb']: query["imdb"] = show_d['imdb'] for type in ["tvmaze", "imdb", "folder"]: if not query[type]: continue pr.info(f"searching tvmaze for [{show_d['folder']}] ", end_line=False) pr.color_brackets(f"as [{query[type]}] ", "green", end_line=False) if season_n: season_n = season_number_to_year( show_d, season_n) # Converts to year if required pr.output(f"-season {season_n}", end_line=False) if episode_n: pr.output(f" -episode {episode_n}", end_line=False) search = tvmaze.tvmaze_search(query[type], season=season_n, episode=episode_n) data = search.data() try: if "status" in data: if data['status'] == "404": pr.color_brackets(" [response false]!", "yellow") if "_links" in data: #tvmaze data success pr.color_brackets(" [got data]!", "green") return data except: pr.color_brackets(" [script error] !", "red") return None
def check_status(): pr.info("confirming episode status flags...") need_save = False for ep in __flatten_eps(): if ep["status"] == "deleted": if ftool.is_existing_file(ep['full_path']): pr.warning(f"not deleted: [{ep['full_path']}]") si = ep["season_index"] ei = ep["episode_index"] show_d = db.data(ep["show"]) show_d["seasons"][si]["episodes"][ei]['status'] = "ok" db.update(ep["show"], db.data(ep["show"], key=None)) need_save = True else: if not ftool.is_existing_file(ep['full_path']): pr.info(f"found deleted: [{ep['full_path']}]") si = ep["season_index"] ei = ep["episode_index"] show_d = db.data(ep["show"]) show_d["seasons"][si]["episodes"][ei]['status'] = "deleted" db.update(ep["show"], db.data(ep["show"], key=None)) need_save = True if need_save: db.save() ftool.copy_dbs_to_webserver("tv")
def omdb_force_update(show_s): success_count = 0 pr.info("force-updating omdb-data for {}".format(show_s)) show_d = db.data(show_s) nfo_imdb = tvtool.nfo_to_imdb(show_d) if nfo_imdb: if show_d["imdb"] != nfo_imdb: show_d["imdb"] = nfo_imdb need_update = True pr.info( f"found new (hopefully) imdb-id [{nfo_imdb}] in nfo for {show_s}" ) omdb_result = tvtool.omdb_search_show(show_d) show_d["omdb"] = omdb_result season_index = 0 for season_d in show_d["seasons"]: omdb_result = tvtool.omdb_search_season(show_d, season_d["folder"]) show_d["seasons"][season_index]["omdb"] = omdb_result episode_index = 0 for episode_d in season_d["episodes"]: if episode_d["status"] == "deleted": continue omdb_result = tvtool.omdb_search_episode(show_d, season_d["folder"], episode_d["file"]) show_d["seasons"][season_index]["episodes"][episode_index][ "omdb"] = omdb_result episode_index += 1 season_index += 1 db.update(show_d["folder"], show_d, key=None) db.save() ftool.copy_dbs_to_webserver("tv")
def show_season_path_from_ep_s(ep_s, create_if_missing=True): show_s = guess_ds_folder(ep_s) if show_s.lower().startswith("marvels agents of"): show_s = "Marvels Agents of S.H.I.E.L.D" if db.exists(show_s): # Will compare lowercase strings... show_folder = db.data(show_s, "folder") else: pr.warning(f"could not determine show for episode, guessed [{show_s}]") show_folder = show_s season_n = guess_season(ep_s) path = _show_path_season(show_folder, season_n) if ftool.is_existing_folder(_show_path(show_folder)): pr.info(f"show path exists [{_show_path(show_folder)}]") if not ftool.is_existing_folder(path): pr.warning(f"path does not exist [{path}]") if create_if_missing: script_name = os.path.basename(__file__) if user_input.yes_no(f"create path {path}?", script_name=script_name): os.makedirs(path) return path else: return None else: pr.info(f"found existing path: [{path}]") return path
def omdb_update(): pr.info("trying to omdb-search for missing data") save_db = False success_count = 0 for show_s in db.list_shows(): if in_skip_list(show_s): pr.info(f"skipping {show_s}, in skip list...") continue need_update = False show_d = db.data(show_s) nfo_imdb = tvtool.nfo_to_imdb(show_d) if nfo_imdb: if show_d["imdb"] != nfo_imdb: show_d["imdb"] = nfo_imdb need_update = True pr.info( f"found new (hopefully) imdb-id [{nfo_imdb}] in nfo for {show_s}" ) if not show_d["omdb"]: omdb_result = tvtool.omdb_search_show(show_d) if omdb_result: show_d["omdb"] = omdb_result need_update = True success_count += 1 season_index = 0 for season_d in show_d["seasons"]: if not season_d["omdb"]: omdb_result = tvtool.omdb_search_season( show_d, season_d["folder"]) if omdb_result: show_d["seasons"][season_index]["omdb"] = omdb_result need_update = True success_count += 1 episode_index = 0 for episode_d in season_d["episodes"]: if episode_d["status"] == "deleted": continue if not episode_d["omdb"]: omdb_result = tvtool.omdb_search_episode( show_d, season_d["folder"], episode_d["file"]) if omdb_result: need_update = True success_count += 1 show_d["seasons"][season_index]["episodes"][ episode_index]["omdb"] = omdb_result episode_index += 1 season_index += 1 if need_update: save_db = True db.update(show_d["folder"], show_d, key=None) pr.info("done!") if success_count > 0: pr.info("successfully updated omdb-data for {} items".format( success_count)) if save_db: db.save() ftool.copy_dbs_to_webserver("tv")
def determine_letter(folder): folder = folder.replace(" ", ".") let = folder[0:1] for prefix in ['The.', 'An.', 'A.']: if folder.startswith(prefix): let = folder[len(prefix):len(prefix) + 1] if let is "V" or let is "W": return "VW" pr.info("guessed letter: {}".format(let)) return let
def add_nfo_manual(show, replace=False): show_s = to_show_s(show) path = _show_path(show_s) pr.info("add imdb-id for [{}]: ".format(show_s), end_line=False) imdb_input = input("") re_imdb = re.compile("tt\d{1,}") imdb_id = re_imdb.search(imdb_input) if imdb_id: id = imdb_id.group(0) ftool.create_nfo(path, id, "tv", replace)
def update(self, table, column, value, column_to_match, match_data): query = f"UPDATE {table} SET {column} = %s WHERE {table}.{column_to_match} = %s" data = (value, match_data) if self.__run_query(query, data): self.__commit() pr.info(f"updated: {match_data} : {column} = {value}") return True else: pr.warning(f"failed update: {match_data} : {column} = {value}") return False
def save(self): with open(self._db_file, 'w', encoding='utf8') as outfile: str_ = json.dumps(self._loaded_db, indent=4, sort_keys=True, separators=(',', ': '), ensure_ascii=False) outfile.write(to_unicode(str_)) pr.info("saved database to {}!".format(self._db_file)) if self.backup_to_ds(): pr.info("backed up database!") else: pr.warning("could not backup database!")
def new_episode(show, season, ep_file_name): episode = { 'file' : ep_file_name, 'status' : "ok" } episode['date_scanned'] = datetime.datetime.now().strftime("%d %b %Y %H:%M") episode['se'] = tvtool.guess_season_episode(episode['file']) episode['subs'] = { 'sv' : tvtool.has_subtitle(show, ep_file_name, "sv"), 'en' : tvtool.has_subtitle(show, ep_file_name, "en") } episode['omdb'] = tvtool.omdb_search_episode(show, season, episode['file']) episode['tvmaze'] = tvtool.tvmaze_search_episode(show, season, episode['file']) pr.info(f"Adding new episode: {episode['se']} : {episode['file']}") return episode
def update(self, movie_folder, key, data): if not self.exists(movie_folder): pr.warning("update: {} is not in database!".format(movie_folder)) else: try: self._loaded_db[movie_folder][key] = data if key is 'omdb': data = "omdb-search" pr.info("Updated {} : {} = {}".format(movie_folder, key, data)) except: pr.warning("update: Could not update {}!".format(movie_folder))
def _load_db(self): if filetools.is_file_empty(self._db_file): self._loaded_db = {} pr.warning("creating empty database") else: try: with open(self._db_file, 'r') as db: self._loaded_db = json.load(db) pr.info("loaded database file: [ {} ]".format(self._db_file)) except: pr.error("Could not open file: {0}".format(self._db_file)) self._loaded_db = None
def update(self, show_folder, data, key = None): if not self.exists(show_folder): pr.warning("update: {} is not in database!".format(show_folder)) else: try: if key: self._loaded_db[show_folder][key] = data if key is 'omdb': data = "omdb-search" pr.info("updated {} : {} = {}".format(show_folder, key, data)) else: self._loaded_db[show_folder] = data pr.info("updated {} with new data!".format(show_folder, data)) except: pr.warning("update: Could not update {}!".format(show_folder))
def db_maintainance(): pr.info("running moviedb maintainance...") need_save = False for mov in mlist: if db.movie_data(mov, 'status') == "deleted": continue full_path = os.path.join(mov_root, db.movie_data(mov, 'letter'), db.movie_data(mov, 'folder')) # Update movies with missing status if not db.movie_data(mov, 'status'): if os.path.isdir(full_path): db.update(mov, 'status', "ok") need_save = True if not db.movie_data(mov, 'nfo') or not db.movie_data(mov, 'imdb'): if try_add_nfo(mov): need_save = True # Try to update missing omdb-data data = db.movie_data(mov, 'omdb') if not data or 'Error' in data: if update_omdb_search(mov): need_save = True # Wrong title... elif "Title" in data and data['Title'].startswith("#"): pr.warning(f"{mov} has faulty title: [{data['Title']}]") if update_omdb_search(mov): if "Title" in data and not data['Title'].startswith("#"): need_save = True elif data['Title'].startswith("#"): pr.info("omdb data still contains faulty title, using folder as title") title = mtool.determine_title(db.movie_data(mov, 'folder')) pr.info(f"guessed title: [{title}]") data['Title'] = title db.update(mov, 'omdb', data) need_save = True sub_data = db.movie_data(mov, 'subs') for lang in ['en', 'sv']: if not sub_data[lang]: sub = mtool.has_subtitle(full_path, lang) if sub: pr.info(f"found [{lang}] sub for {mov}") sub_data[lang] = sub db.update(mov, 'subs', sub_data) need_save = True if need_save: db.save() ftool.copy_dbs_to_webserver("movie") else: pr.info("nothing updated")
def check_nfo(): global shows skiplist = ["Vad Blir Det For Mat"] for show in shows: if show.startswith("@"): # Diskstation continue if show in skiplist: pr.info(f"in skiplist: [{show}]") continue if tvtool.has_nfo(show): if tvtool.nfo_to_imdb(show): pr.info("{} has tvshow.nfo".format(show)) else: pr.warning("{} has non-imdb tvshow.nfo".format(show)) tvtool.add_nfo_manual(show, replace=True) else: tvtool.add_nfo_manual(show)
def new_movie(letter, movie): fp = os.path.join(mov_root, letter, movie) mov = {'letter': letter, 'folder': movie} date = ftool.get_creation_date(fp, convert=True) mov['date_created'] = date.strftime( "%d %b %Y") if date is not None else None mov['date_scanned'] = datetime.datetime.now().strftime("%d %b %Y %H:%M") mov['nfo'] = mtool.has_nfo(fp) mov['imdb'] = mtool.nfo_to_imdb(fp) mov['omdb'] = mtool.omdb_search(mov) mov['subs'] = { 'sv': mtool.has_subtitle(fp, "sv"), 'en': mtool.has_subtitle(fp, "en") } mov['video'] = mtool.get_vid_file(fp) mov['status'] = "ok" pr.info(f"added [{movie}] to database!") db.add(mov)
def insert(self, table, columns = [], data=[]): if len(columns) != len(data): pr.warning("columns and data doesnt match!") return query = f"INSERT INTO {table} (" for column in columns: query += f"{column}," query = query[:-1] + ") VALUES (" for column in columns: query += r"%s," query = query[:-1] + ")" result = self.__run_query(query, tuple(data)) if result: self.__commit() pr.info(f"inserted {data} into table {table}") return True else: return False
def se_upper(): need_save = False for ep in __flatten_eps(): if not ep["se"] or ep["status"] == "deleted": continue if ep["se"].startswith("s"): si = ep["season_index"] ei = ep["episode_index"] show_d = db.data(ep["show"]) pr.info( f"found lowercase: {show_d['seasons'][si]['episodes'][ei]['se']}" ) show_d["seasons"][si]["episodes"][ei]["se"] = ep["se"].upper() db.update(ep["show"], show_d, key=None) pr.info(f"upper: {ep['se'].upper()}") need_save = True if need_save: db.save() ftool.copy_dbs_to_webserver("tv")
def omdb_search(movie): folder = movie['folder'] pr.info(f"searching OMDb for [{folder}] ", end_line=False) if movie['imdb'] is not None: pr.color_brackets(f"as [{movie['imdb']}] >", "green", end_line=False) omdb_search = omdb.omdb_search(str(movie['imdb'])) else: title = determine_title(folder, replace_dots_with='+') year = determine_year(folder) pr.color_brackets(f"as [{title}] >", "green", end_line=False) omdb_search = omdb.omdb_search(title, type="movie", year=year) data = omdb_search.data() try: if data['Response'] == "False": pr.color_brackets(" [response false]!", "yellow") return None pr.color_brackets(" [got data]!", "green") return data except: pr.color_brackets(" [script error] !", "red") return None
def select(self, table, columns = [], column_to_match = None, match_data = None): column_string = "" if not columns: column_string = "*" else: for column in columns: column_string = f"{column_string},{column}" column_string = column_string.strip(',') query = f"SELECT {column_string} FROM {table} WHERE {column_to_match} = %s" data = (match_data,) result = self.__run_query(query, data) result_list = [] if result: self.__commit() pr.info(f"selected: {columns}") for column_string in self.cursor: print(f"result: {str(column_string)}") result_list.append(str(column_string)) return result else: pr.warning(f"failed select query") return False
def find_ep_data(key, data): pr.info(f"showing all eps where [{key} == {data}]") found = 0 eps = __flatten_eps() for ep in eps: if ep[key] == data: pr.info(ep["file"]) found += 1 pr.info(f"scan done, found [{found}] eps")
def __omdb_search(show_d, season_n=None, episode_n=None): folder = show_d['folder'] query = None if show_d['imdb']: query = show_d['imdb'] else: query = show_d['folder'] pr.info(f"searching omdb for [{show_d['folder']}] ", end_line=False) pr.color_brackets(f"as [{query}] ", "green", end_line=False) if season_n: pr.output(f"-season {season_n}", end_line=False) if episode_n: pr.output(f" -episode {episode_n}", end_line=False) search = omdb.omdb_search(query, season=season_n, episode=episode_n) data = search.data() try: if data['Response'] == "False": pr.color_brackets("> [response false]!", "yellow") return None pr.color_brackets("> [got data]!", "green") return data except: pr.color_brackets("> [script error] !", "red") return None
def new_show(folder): show = { 'folder' : folder } pr.info(f"found new show [{folder}] !") fp = os.path.join(tv_root, folder) date = ftool.get_creation_date(fp, convert=True) show['date_created'] = date.strftime("%d %b %Y") if date is not None else None show['date_scanned'] = datetime.datetime.now().strftime("%d %b %Y %H:%M") show['status'] = "ok" show['seasons'] = [] show['nfo'] = tvtool.has_nfo(folder) show['imdb'] = tvtool.nfo_to_imdb(folder) show['omdb'] = tvtool.omdb_search_show(show) show['tvmaze'] = tvtool.tvmaze_search_show(show) for s in tvtool.get_season_folder_list(folder): season = { 'folder' : s, 'status' : "ok" } season['omdb'] = tvtool.omdb_search_season(show, season['folder']) season['tvmaze'] = tvtool.tvmaze_search_season(show, season['folder']) season['episodes'] = [] show['seasons'].append(season) for e in tvtool.get_episodes(folder, s): episode = new_episode(show, s, e) season['episodes'].append(episode) pr.info(f"added [{folder}] to database!") db.add(show)
def scan_all_subtitles(): pr.info("scanning for subs") save_db = False new_count = 0 for ep in __flatten_eps(): if ep["status"] == "deleted": continue si = ep["season_index"] ei = ep["episode_index"] if not "subs" in ep: show_d = db.data(ep["show"]) show_d["seasons"][si]["episodes"][ei]['subs'] = { 'sv': None, 'en': None } ep["subs"] = {'sv': None, 'en': None} db.update(ep["show"], show_d, key=None) save_db = True if not ep['subs']['sv']: sv_srt_file = tvtool.has_subtitle(ep["show"], ep["file"], "sv") if sv_srt_file: show_d = db.data(ep["show"]) show_d["seasons"][si]["episodes"][ei]['subs'][ 'sv'] = sv_srt_file db.update(ep["show"], show_d, key=None) pr.info(f"found [{sv_srt_file}]") save_db = True if not ep['subs']['en']: en_srt_file = tvtool.has_subtitle(ep["show"], ep["file"], "en") if en_srt_file: show_d = db.data(ep["show"]) show_d["seasons"][si]["episodes"][ei]['subs'][ 'en'] = en_srt_file db.update(ep["show"], show_d, key=None) pr.info(f"found [{en_srt_file}]") save_db = True pr.info("done!") if save_db: db.save() ftool.copy_dbs_to_webserver("tv")
def scan_for_deleted_movies(): pr.info("scanning for deleted movies...") need_save = False for mov in mlist: if db.movie_data(mov, 'status') == "deleted": continue path_to_check = os.path.join(mov_root, db.movie_data(mov, 'letter'), db.movie_data(mov, 'folder')) if not os.path.isdir(path_to_check): pr.info("folder deleted: {}".format(path_to_check)) db.update(mov, 'status', "deleted") need_save = True if need_save: db.save() ftool.copy_dbs_to_webserver("movie") else: pr.info("nothing updated")
def add_season(self, show_s, season_d): if self.load_success(): show_d = self._loaded_db[show_s] show_d['seasons'].append(season_d) pr.info(f"added {season_d['folder']} to {show_s}")
episode = new_episode(show, s, e) season['episodes'].append(episode) pr.info(f"added [{folder}] to database!") db.add(show) parser = argparse.ArgumentParser(description='tv scanner') parser.add_argument('-m', '--max', dest='max', default=None, help='max new shows to scan') args = parser.parse_args() new_show_count = 0 new_episode_count = 0 try: max_scan = int(args.max) pr.info(f"will scan max {max_scan} new shows") except: max_scan = None # Scan for new shows... for show_s in show_folder_list: if show_s.startswith("@"): # Diskstation continue; if max_scan and new_show_count >= max_scan: pr.info("max new show scan limit reached! breaking") break; pr.info(f"scanning [{show_s}]") if not db.exists(show_s): new_show(show_s) new_show_count += 1 continue; # new_show() adds all new eps and seasons
mov['imdb'] = mtool.nfo_to_imdb(fp) mov['omdb'] = mtool.omdb_search(mov) mov['subs'] = { 'sv': mtool.has_subtitle(fp, "sv"), 'en': mtool.has_subtitle(fp, "en") } mov['video'] = mtool.get_vid_file(fp) mov['status'] = "ok" pr.info(f"added [{movie}] to database!") db.add(mov) # Scan for new movies... for letter in letters: if letter in _valid_letters: pr.info(f"scanning {letter}") movies = os.listdir(os.path.join(mov_root, letter)) movies.sort() for movie in movies: if movie.startswith("@"): # Diskstation continue if not db.exists(movie): new_movie(letter, movie) new_count += 1 else: continue pr.info(f"done scanning. found ({new_count}) new movies.") if new_count > 0: db.save() ftool.copy_dbs_to_webserver("movie")