From 23d48f1d5285bf5d963c509f3a7e3b70bea0e1bd Mon Sep 17 00:00:00 2001 From: simon Date: Sun, 4 Apr 2021 13:29:42 +0700 Subject: [PATCH] exporting movie library to csv --- config.sample | 7 ++- interface.py | 16 ++++-- src/db_export.py | 128 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 146 insertions(+), 5 deletions(-) create mode 100644 src/db_export.py diff --git a/config.sample b/config.sample index 5b01b7c..4967691 100644 --- a/config.sample +++ b/config.sample @@ -5,5 +5,10 @@ sortpath = /media/movie/movie/temp moviepath = /media/movie/movie-archive tvpath = /media/movie/tv ext = mp4 mkv avi m4v -log_file = /home/user/logs/rename.log +log_folder = /home/user/logs/media_organize movie_db_api = aaaabbbbccccdddd1111222233333444 + +[emby] +emby_url = http://media.local:8096/emby +emby_user_id = aaaa1111bbbb2222cccc3333dddd4444 +emby_api_key = eeee5555ffff6666gggg7777hhhh8888 \ No newline at end of file diff --git a/interface.py b/interface.py index d99124b..dc68137 100755 --- a/interface.py +++ b/interface.py @@ -11,13 +11,18 @@ from time import sleep import src.tvsort as tvsort import src.tvsort_id as tvsort_id import src.moviesort as moviesort +import src.db_export as db_export def get_config(): """ read out config file and return config dict """ # build path root_folder = path.dirname(sys.argv[0]) - config_path = path.join(root_folder, 'config') + if root_folder == '/sbin': + # running interactive + config_path = 'config' + else: + config_path = path.join(root_folder, 'config') # parse config_parser = configparser.ConfigParser() config_parser.read(config_path) @@ -28,7 +33,7 @@ def get_config(): config["sortpath"] = config_parser.get('media', 'sortpath') config["moviepath"] = config_parser.get('media', 'moviepath') config["tvpath"] = config_parser.get('media', 'tvpath') - config["log_file"] = config_parser.get('media', 'log_file') + config["log_folder"] = config_parser.get('media', 'log_folder') config["movie_db_api"] = config_parser.get('media', 'movie_db_api') # ext ext_str = config_parser.get('media', 'ext') @@ -96,6 +101,8 @@ def sel_handler(menu_item, config): moviesort.main(config) elif menu_item == 'TV shows': tvsort.main(config, tvsort_id) + elif menu_item == 'DB export': + db_export.main(config) def curses_main(stdscr, menu, config): @@ -133,9 +140,10 @@ def curses_main(stdscr, menu, config): def main(): """ main wraps the curses menu """ # setup - menu = ['All', 'Movies', 'TV shows', 'Exit'] + menu = ['All', 'Movies', 'TV shows', 'DB export', 'Exit'] config = get_config() - logging.basicConfig(filename=config["log_file"],level=logging.INFO,format='%(asctime)s:%(message)s') + log_file = path.join(config["log_folder"], 'rename.log') + logging.basicConfig(filename=log_file,level=logging.INFO,format='%(asctime)s:%(message)s') # endless loop while True: pending = get_pending_all(config) diff --git a/src/db_export.py b/src/db_export.py new file mode 100644 index 0000000..429fa97 --- /dev/null +++ b/src/db_export.py @@ -0,0 +1,128 @@ +""" export collection from emby to CSV """ + +import csv +from os import path +import requests + + +def get_items(config): + """ get json from emby """ + emby_url = config['emby_url'] + emby_user_id = config['emby_user_id'] + emby_api_key = config['emby_api_key'] + # movies + url = (f'{emby_url}/Users/{emby_user_id}/Items?api_key={emby_api_key}' + + '&Recursive=true&IncludeItemTypes=Movie' + + '&fields=Genres,MediaStreams,Overview,ProviderIds' + + '&SortBy=DateCreated&SortOrder=Descending') + r = requests.get(url) + all_movies = r.json()['Items'] + # episodes + url = (f'{emby_url}/Users/{emby_user_id}/Items?api_key={emby_api_key}' + + '&IncludeItemTypes=Episode&Recursive=true&StartIndex=0' + + '&Fields=DateCreated,MediaStreams,MediaSources' + '&SortBy=DateCreated&SortOrder=Descending&IsMissing=false') + + r = requests.get(url) + all_episodes = r.json()['Items'] + return all_movies, all_episodes + + +def parse_movies(all_movies): + """ loop through the movies """ + movie_info_csv = [] + movie_tech_csv = [] + movie_seen = [] + for movie in all_movies: + # general + movie_name = movie['Name'] + overview = movie['Overview'] + imdb = movie['ProviderIds']['Imdb'] + played = movie['UserData']['Played'] + genres = ', '.join(movie['Genres']) + # media + for i in movie['MediaSources']: + if i['Protocol'] == 'File': + file_name = path.basename(i['Path']) + year = path.splitext(file_name)[0][-5:-1] + duration_min = round(i['RunTimeTicks'] / 600000000) + filesize_MB = round(i['Size'] / 1024 / 1024) + for j in i['MediaStreams']: + if j['Type'] == 'Video': + image_width = j['Width'] + image_height = j['Height'] + avg_bitrate_MB = round(j['BitRate'] / 1024 / 1024, 2) + codec = j['Codec'] + # found it + break + # found it + break + # info csv + info_dict = {} + info_dict['movie_name'] = movie_name + info_dict['year'] = year + info_dict['imdb'] = imdb + info_dict['genres'] = genres + info_dict['overview'] = overview + info_dict['duration_min'] = duration_min + movie_info_csv.append(info_dict) + # technical csv + tech_dict = {} + tech_dict['file_name'] = file_name + tech_dict['duration_min'] = duration_min + tech_dict['filesize_MB'] = filesize_MB + tech_dict['image_width'] = image_width + tech_dict['image_height'] = image_height + tech_dict['avg_bitrate_MB'] = avg_bitrate_MB + tech_dict['codec'] = codec + movie_tech_csv.append(tech_dict) + # seen or unseen + if played == True: + icon = '[X]' + elif played == False: + icon = '[ ]' + seen_line = f'{icon} {movie_name} ({year})' + movie_seen.append(seen_line) + + return movie_info_csv, movie_tech_csv, movie_seen + + +def write_movie_files(movie_info_csv, movie_tech_csv, movie_seen, config): + """ writes the csv files to disk """ + log_folder = config['log_folder'] + + # movie info + movie_info_sorted = sorted(movie_info_csv, key=lambda k: k['movie_name']) + file_path = path.join(log_folder, 'movie-info.csv') + # open and write + with open(file_path, 'w') as f: + # take fieldnames from first line + fieldnames = movie_info_sorted[0].keys() + csv_writer = csv.DictWriter(f, fieldnames) + csv_writer.writeheader() + csv_writer.writerows(movie_info_sorted) + + # movie tech + movie_tech_csv_sorted = sorted(movie_tech_csv, key=lambda k: k['file_name']) + file_path = path.join(log_folder, 'movie-tech.csv') + # open and write + with open(file_path, 'w') as f: + # take fieldnames from first line + fieldnames = movie_tech_csv_sorted[0].keys() + csv_writer = csv.DictWriter(f, fieldnames) + csv_writer.writeheader() + csv_writer.writerows(movie_tech_csv_sorted) + + # movie by new + file_path = path.join(log_folder, 'movienew') + with open(file_path, 'w') as f: + f.writelines(movie_seen) + + +def main(config): + """ write collection to csv """ + # get data + all_movies, _ = get_items(config) + # write movies + movie_info_csv, movie_tech_csv, movie_seen = parse_movies(all_movies) + write_movie_files(movie_info_csv, movie_tech_csv, movie_seen, config)