From 4ac43a291594af91635b7649f53a5b5d580f5968 Mon Sep 17 00:00:00 2001 From: sterling-tenn Date: Sun, 25 Jun 2023 20:40:04 -0400 Subject: [PATCH 1/3] loved field --- itunestoND.py | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/itunestoND.py b/itunestoND.py index c85de86..e5bc439 100644 --- a/itunestoND.py +++ b/itunestoND.py @@ -28,12 +28,13 @@ def determine_userID(nd_p): conn.close() return users[0][0] -def update_playstats(d1, id, playcount, playdate, rating=0): +def update_playstats(d1, id, playcount, playdate, rating=0, loved=0): d1.setdefault(id, {}) d1[id].setdefault('play count', 0) d1[id].setdefault('play date', datetime.datetime.fromordinal(1)) d1[id]['play count'] += playcount d1[id]['rating'] = rating + d1[id]['loved'] = loved if playdate > d1[id]['play date']: d1[id].update({'play date': playdate}) @@ -53,8 +54,9 @@ def write_to_annotation(dictionary_with_stats, entry_type): play_count = this_entry['play count'] play_date = this_entry['play date'].strftime('%Y-%m-%d %H:%M:%S') # YYYY-MM-DD 24:mm:ss rating = this_entry['rating'] + loved = this_entry['loved'] - annotation_entries.append((generate_annotation_id(), userID, item_id, entry_type, play_count, play_date, rating, 0, None)) + annotation_entries.append((generate_annotation_id(), userID, item_id, entry_type, play_count, play_date, rating, loved, None)) conn = sqlite3.connect(nddb_path) cur = conn.cursor() @@ -64,24 +66,16 @@ def write_to_annotation(dictionary_with_stats, entry_type): # cur.executemany('INSERT INTO consumers VALUES (?,?,?,?)', purchases) # cur.execute("INSERT INTO consumers VALUES (1,'John Doe','john.doe@xyz.com','A')") -_ = None -while _ != 'proceed': - print() - print('This script will migrate certain data from your ITunes library to your Navidrome database.', - "Back up all your data in case it doesn't work properly on your setup. NO WARRANTIES. NO PROMISES.", - "The script will DELETE existing data you have in your Navidrome database so it can start \"fresh\".", sep='\n') - print() +def update_created_at_fields(): + return - _ = input('Type PROCEED to continue, or Q to quit: ').lower() - - if _ == 'q': print('Good bye.'); sys.exit(0) - -nddb_path = get_db_path('Navidrome database') -itdb_path = get_db_path('Itunes database') +nddb_path = "navidrome.db" +itdb_path = 'Library.xml' print('\nParsing Itunes library. This may take a while.') with open(itdb_path, 'r', encoding="utf-8") as f: soup = BeautifulSoup(f, 'lxml-xml') it_root_music_path = unquote(soup.find('key', text='Music Folder').next_sibling.text) +it_root_music_path = "file://localhost/C:/Users/sterl/Music/Music/" # example output of previous line: 'file://localhost/C:/Users/REDACTED/Music/iTunes/iTunes Music/' songs = soup.dict.dict.find_all('dict') # yields result set of media files to loop through @@ -134,6 +128,10 @@ def write_to_annotation(dictionary_with_stats, entry_type): it_song_ID = int(it_song_entry.find('key', string='Track ID').next_sibling.text) songID_correlation.update({it_song_ID: song_id}) + loved = it_song_entry.find('key', string='Loved') + if(loved != None): loved = 1 + else: loved = 0 + try: # get rating, play count & date from Itunes song_rating = int(it_song_entry.find('key', string='Rating').next_sibling.text) song_rating = int(song_rating / 20) @@ -147,8 +145,7 @@ def write_to_annotation(dictionary_with_stats, entry_type): update_playstats(artists, artist_id, play_count, last_played) update_playstats(albums, album_id, play_count, last_played) - update_playstats(files, song_id, play_count, last_played, rating=song_rating) - + update_playstats(files, song_id, play_count, last_played, rating=song_rating, loved=loved) conn.close() From eb4637b5b1c964208537838497d30483d74ca9ed Mon Sep 17 00:00:00 2001 From: sterling-tenn Date: Sun, 25 Jun 2023 21:37:34 -0400 Subject: [PATCH 2/3] update created_at fields --- itunestoND.py | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/itunestoND.py b/itunestoND.py index e5bc439..34cd000 100644 --- a/itunestoND.py +++ b/itunestoND.py @@ -28,15 +28,17 @@ def determine_userID(nd_p): conn.close() return users[0][0] -def update_playstats(d1, id, playcount, playdate, rating=0, loved=0): +def update_playstats(d1, id, playcount, playdate, dateadded, rating=0, loved=0): d1.setdefault(id, {}) d1[id].setdefault('play count', 0) d1[id].setdefault('play date', datetime.datetime.fromordinal(1)) + d1[id].setdefault('date added', datetime.datetime.fromordinal(1)) d1[id]['play count'] += playcount d1[id]['rating'] = rating d1[id]['loved'] = loved if playdate > d1[id]['play date']: d1[id].update({'play date': playdate}) + if dateadded > d1[id]['date added']: d1[id].update({'date added': dateadded}) def generate_annotation_id(): # random hex number 32 characters long character_pool = string.hexdigits[:16] @@ -66,8 +68,15 @@ def write_to_annotation(dictionary_with_stats, entry_type): # cur.executemany('INSERT INTO consumers VALUES (?,?,?,?)', purchases) # cur.execute("INSERT INTO consumers VALUES (1,'John Doe','john.doe@xyz.com','A')") -def update_created_at_fields(): - return +def update_created_at_fields(dictionary_with_stats): + conn = sqlite3.connect(nddb_path) + cur = conn.cursor() + + for item_id in dictionary_with_stats: + this_entry = dictionary_with_stats[item_id] + cur.execute('UPDATE media_file SET created_at = ? WHERE id = ?', (this_entry['date added'], item_id)) + conn.commit() + conn.close() nddb_path = "navidrome.db" itdb_path = 'Library.xml' @@ -141,12 +150,13 @@ def update_created_at_fields(): play_count = int(it_song_entry.find('key', string='Play Count').next_sibling.text) last_played = it_song_entry.find('key', string='Play Date UTC').next_sibling.text[:-1] # slice off the trailing 'Z' last_played = datetime.datetime.strptime(last_played, '%Y-%m-%dT%H:%M:%S') # convert from string to datetime object. Example string: '2020-01-19T02:24:14Z' + date_added = it_song_entry.find('key', string='Date Added').next_sibling.text[:-1] + date_added = datetime.datetime.strptime(date_added, '%Y-%m-%dT%H:%M:%S') except AttributeError: continue - update_playstats(artists, artist_id, play_count, last_played) - update_playstats(albums, album_id, play_count, last_played) - update_playstats(files, song_id, play_count, last_played, rating=song_rating, loved=loved) - + update_playstats(artists, artist_id, play_count, last_played, date_added) + update_playstats(albums, album_id, play_count, last_played, date_added) + update_playstats(files, song_id, play_count, last_played, date_added, rating=song_rating, loved=loved) conn.close() @@ -158,6 +168,8 @@ def update_created_at_fields(): write_to_annotation(albums, 'album') print('Album records saved to database.') +update_created_at_fields(files) + with open('IT_file_correlations.py', 'w') as f: f.write('# Following python dictionary correlates the itunes integer ID to the Navidrome file ID for each song.\n') f.write('# {ITUNES ID: ND ID} is the format. \n\n') From 826ffd4b0231bf09231c6b1fde7c497aaf17da74 Mon Sep 17 00:00:00 2001 From: sterling-tenn Date: Sun, 25 Jun 2023 21:41:37 -0400 Subject: [PATCH 3/3] revert stuff back to original --- itunestoND.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/itunestoND.py b/itunestoND.py index 34cd000..a12a2b8 100644 --- a/itunestoND.py +++ b/itunestoND.py @@ -78,13 +78,24 @@ def update_created_at_fields(dictionary_with_stats): conn.commit() conn.close() -nddb_path = "navidrome.db" -itdb_path = 'Library.xml' +_ = None +while _ != 'proceed': + print() + print('This script will migrate certain data from your ITunes library to your Navidrome database.', + "Back up all your data in case it doesn't work properly on your setup. NO WARRANTIES. NO PROMISES.", + "The script will DELETE existing data you have in your Navidrome database so it can start \"fresh\".", sep='\n') + print() + + _ = input('Type PROCEED to continue, or Q to quit: ').lower() + + if _ == 'q': print('Good bye.'); sys.exit(0) + +nddb_path = get_db_path('Navidrome database') +itdb_path = get_db_path('Itunes database') print('\nParsing Itunes library. This may take a while.') with open(itdb_path, 'r', encoding="utf-8") as f: soup = BeautifulSoup(f, 'lxml-xml') it_root_music_path = unquote(soup.find('key', text='Music Folder').next_sibling.text) -it_root_music_path = "file://localhost/C:/Users/sterl/Music/Music/" # example output of previous line: 'file://localhost/C:/Users/REDACTED/Music/iTunes/iTunes Music/' songs = soup.dict.dict.find_all('dict') # yields result set of media files to loop through