need run main fetch command then run indexer then LinkerPatternGenerator then link_pattern command in the main
137 lines
5 KiB
Python
137 lines
5 KiB
Python
from DataBase import *
|
|
from SpotifyWebAPI import find_song, update_access_token
|
|
|
|
from rapidfuzz import fuzz
|
|
from tqdm import tqdm
|
|
|
|
|
|
def spotify_pattern_generator():
|
|
update_access_token()
|
|
|
|
local_library = get_data("local_library")
|
|
spotify_library = get_data("tracks")
|
|
|
|
def find_local_songs_on_spotify(local_lib):
|
|
total = len(local_library)
|
|
found_tracks_map = {}
|
|
with tqdm(total=total, desc='Searching local songs on spotify') as pbar:
|
|
for track_id, track in local_lib.items():
|
|
search_pattern = f"{track['name']} {track['artist']} {track['album']}"
|
|
found_tracks = find_song(search_pattern)
|
|
found_tracks_map[track_id] = found_tracks[0:1]
|
|
pbar.update(1)
|
|
return found_tracks_map
|
|
|
|
spotify_found_tracks = find_local_songs_on_spotify(local_library)
|
|
spotify_user_track = {track['track']['id']: {"local_mappings": []} for track in spotify_library}
|
|
|
|
spotify_pattern = {}
|
|
for local_id, found_items in spotify_found_tracks.items():
|
|
spotify_pattern[local_id] = {"score": 0.0, "items": []}
|
|
|
|
if not len(found_items):
|
|
continue
|
|
|
|
for found_item in found_items:
|
|
spotify_track_id = found_item['id']
|
|
if spotify_track_id in spotify_user_track:
|
|
spotify_pattern[local_id]['items'].append(spotify_track_id)
|
|
spotify_user_track[spotify_track_id]['local_mappings'].append(local_id)
|
|
|
|
for spotify_id, track_local_mappings in spotify_user_track.items():
|
|
score = len(track_local_mappings['local_mappings'])
|
|
for local_id in track_local_mappings['local_mappings']:
|
|
spotify_pattern[local_id]['score'] = 1 / score
|
|
|
|
save_data(spotify_pattern, "link_pattern_spotify")
|
|
|
|
|
|
def fuzzy_pattern_generator():
|
|
local_library = get_data("local_library")
|
|
track_descriptions = get_data("tracks")
|
|
|
|
def get_matched(src_pattern, patterns):
|
|
result = {}
|
|
for target_pattern in patterns:
|
|
similarity_score = fuzz.token_set_ratio(src_pattern, target_pattern)
|
|
result[target_pattern] = similarity_score / 100
|
|
|
|
sorted_results = sorted(result.items(), key=lambda item: item[1], reverse=True)
|
|
return sorted_results
|
|
|
|
def resolve_tracks(s_patterns, t_patterns):
|
|
|
|
pattern_map = {}
|
|
|
|
total = len(s_patterns)
|
|
with tqdm(total=total, desc='Progress') as pbar:
|
|
for s_pattern in s_patterns:
|
|
res = get_matched(s_pattern, t_patterns)
|
|
matched = {"score": 0, "items": []}
|
|
if len(res):
|
|
matched['items'] = res[0:min(len(res), 4)]
|
|
matched['score'] = res[0][1]
|
|
pattern_map[s_pattern] = matched
|
|
pbar.update(1)
|
|
|
|
return pattern_map
|
|
|
|
source_patterns = []
|
|
for track in track_descriptions:
|
|
artists = get_artists_str(track['track']['artists'])
|
|
pattern = f"{track['track']['name']} {artists}"
|
|
source_patterns.append(pattern)
|
|
|
|
target_patterns = [local['path'] for _, local in local_library.items()]
|
|
|
|
fuzzy_pattern = resolve_tracks(source_patterns, target_patterns)
|
|
save_data(fuzzy_pattern, "link_pattern_fuzzy")
|
|
|
|
|
|
def fuzzy_tag_pattern_generator():
|
|
local_library = get_data("local_library")
|
|
spotify_library = get_data("tracks")
|
|
mappings = {}
|
|
|
|
def fuzzy_tags_ratio(first: SongTags, second: SongTags):
|
|
title_ratio = fuzz.token_set_ratio(first.title, second.title) / 100
|
|
artist_ratio = fuzz.token_set_ratio(first.artist, second.artist) / 100
|
|
album_ratio = fuzz.token_set_ratio(first.album, second.album) / 100
|
|
return title_ratio, artist_ratio, album_ratio
|
|
|
|
with tqdm(total=len(local_library), desc='fuzzy_tag_pattern_generator') as pbar:
|
|
for local_track_id, local_track in local_library.items():
|
|
mapping = mappings.get(local_track_id, {"score": 1.0, "items": []})
|
|
ratios = []
|
|
for remote_track in spotify_library:
|
|
track = remote_track['track']
|
|
|
|
tag1 = SongTags(local_track['name'], local_track['artist'], local_track['album'])
|
|
tag2 = SongTags(track['name'], get_artists_str(track['artists']), track['album']['name'])
|
|
|
|
ratios.append((fuzzy_tags_ratio(tag1, tag2), track['id']))
|
|
|
|
filtered_ratios = []
|
|
threshold = 0.8
|
|
for ratio in ratios:
|
|
if all([val > threshold for val in ratio[0]]):
|
|
filtered_ratios.append((sum(i for i in ratio[0]) / len(ratio[0]), ratio[1]))
|
|
|
|
filtered_ratios.sort(reverse=True, key=lambda x: x[0])
|
|
if len(filtered_ratios):
|
|
mapping['items'] = [filtered_ratios[0][1]]
|
|
|
|
mappings[local_track_id] = mapping
|
|
pbar.update(1)
|
|
|
|
save_data(mappings, "link_pattern_tags")
|
|
|
|
|
|
def run_pattern_generators():
|
|
#fuzzy_pattern_generator()
|
|
#spotify_pattern_generator()
|
|
fuzzy_tag_pattern_generator()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
run_pattern_generators()
|