Skip to content

Commit

Permalink
Merge pull request #3 from very-doge-wow/fix-wrong-artists
Browse files Browse the repository at this point in the history
Fix wrong artists
  • Loading branch information
very-doge-wow committed Jan 1, 2024
2 parents 15a4ef7 + 9689597 commit f05957d
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 36 deletions.
46 changes: 44 additions & 2 deletions app.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import base64
import re
import threading
import time

Expand Down Expand Up @@ -141,23 +142,32 @@ def playlists_amazon():
def migrate_playlist():
original_playlist_id = request.form.get('submitValue')
settings.PROGRESS = 0
settings.FAILED_TRACKS = ""
settings.TRACK_TRANSLATION = []
settings.DESTINATION_PLAYLIST_URL = ""

# get the playlist from amazon API (including tracks)
original_playlist = get_paginated_track_list(playlist={}, playlist_id=original_playlist_id, cursor=None)

# we only need artist and name of the tracks
tracks = []
for edge in original_playlist['tracks']['edges']:
# sanitize for better search results
title = re.sub(r'\[.*\]', '', edge['node']['title'])
title = re.sub(r'\(.*\)', '', title)
title = re.sub(r'-?\s?Demo\s(Version)?', '', title)
track = {
'artist': edge['node']['artists'][0]['name'],
'title': edge['node']['title'],
'title': title,
}
tracks.append(track)

# create new playlist at spotify if not exists
new_playlist_id = create_spotify_playlist(name=original_playlist['title'])

thread = threading.Thread(target=add_tracks_to_spotify_playlist, name="migration", args=[session['spotify_access_token'], new_playlist_id, tracks])
settings.TRACK_TRANSLATION = tracks

thread = threading.Thread(target=add_tracks_to_spotify_playlist, name="migration", args=[session['spotify_access_token'], new_playlist_id])
thread.start()

return render_template(template_name_or_list='migrate.html', content=original_playlist)
Expand All @@ -166,3 +176,35 @@ def migrate_playlist():
@app.route('/api/progress', methods=['GET'])
def api_progress():
return {'progress': settings.PROGRESS}


@app.route('/api/failed', methods=['GET'])
def api_failed():
return {'failed': settings.FAILED_TRACKS}


@app.route('/api/tracks', methods=['GET'])
def api_tracks():
tracks = []
for track in settings.TRACK_TRANSLATION:
result = {
'source': {
'title': track['title'],
'artist': track['artist']
}
}
if track.get('translation'):
result['destination'] = {
'title': track['translation']['title'],
'artist': track['translation']['artist']
}
tracks.append(result)

html = "<table class=\"w3-table-all w3-hoverable\"><thead><tr><th>Amazon Music</th><th>Spotify</th></tr></thead><tbody>"
for track in tracks:
destination = ""
if track.get('destination'):
destination = f"{track['destination']['artist']} - {track['destination']['title']}"
html += f"<tr><td>{track['source']['artist']} - {track['source']['title']}</td><td>{destination}</td></tr>"
html += "</tbody></table>"
return {'translation': html}
6 changes: 6 additions & 0 deletions settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,9 @@

# storage for progress
PROGRESS = 0
# storage for failed migration of songs
FAILED_TRACKS = ""
# stores source tracks and their destination tracks
TRACK_TRANSLATION = []
# stores target playlist url after creation
DESTINATION_PLAYLIST_URL = ""
60 changes: 44 additions & 16 deletions templates/migrate.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,63 @@
{% block header %}Amazify - Migrate Amazon Playlist to Spotify{% endblock %}
{% block content %}
<script>
var intervalId = setInterval(function() {
var intervalProgress = setInterval(function() {
fetch('/api/progress')
.then(response => response.json())
.then(data => document.getElementById('migration').value = data.progress)
.catch(error => console.error('Error:', error));
}, 500);

var intervalFailed = setInterval(function() {
fetch('/api/failed')
.then(response => response.json())
.then(data => document.getElementById('failed-tracks').innerHTML = data.failed)
.catch(error => console.error('Error:', error));
}, 500);

var intervalTranslation = setInterval(function() {
fetch('/api/tracks')
.then(response => response.json())
.then(data => document.getElementById('track-translation-table').innerHTML = data.translation)
.catch(error => console.error('Error:', error));
}, 500);
</script>

<!--<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">-->
<style>
.w3-table,.w3-table-all{border-collapse:collapse;border-spacing:0;width:100%;display:table}.w3-table-all{border:1px solid #ccc}
.w3-bordered tr,.w3-table-all tr{border-bottom:1px solid #ddd}.w3-striped tbody tr:nth-child(even){background-color:#f1f1f1}
.w3-table-all tr:nth-child(odd){background-color:#fff}.w3-table-all tr:nth-child(even){background-color:#f1f1f1}
.w3-hoverable tbody tr:hover,.w3-ul.w3-hoverable li:hover{background-color:#ccc}.w3-centered tr th,.w3-centered tr td{text-align:center}
.w3-table td,.w3-table th,.w3-table-all td,.w3-table-all th{padding:8px 8px;display:table-cell;text-align:left;vertical-align:top}
.w3-table th:first-child,.w3-table td:first-child,.w3-table-all th:first-child,.w3-table-all td:first-child{padding-left:16px}
.w3-hoverable tbody tr:hover,.w3-ul.w3-hoverable li:hover{background-color:#ccc}.w3-centered tr th,.w3-centered tr td{text-align:center}
</style>

<div class="media fadeitin">
<div class="mr-4">
<a href="{{content['url']}}" target="_blank"><img class="media-object" width="150" src="{{content['images'][0]['url']}}" /></a>
</div>
<div class="media-body">
<h4><a class="text-dark nounderline" href="{{content['url']}}" target="_blank">{{content['title']}}</a></h4>
<label for="migration">Migration progress:</label>
<progress id="migration" style="width: 100%" value="{{ session['progress'] }}" max="100"></progress>
<dl class="dl-horizontal">
<dt>Id</dt><dd>{{content['id']}}</dd>
<dt>TrackCount</dt><dd>{{content['trackCount']}}</dd>
<dt>Visibility</dt><dd>{{content['visibility']}}</dd>
<dt>Duration</dt><dd>{{content['duration']}}</dd>
<dt>Amazon Url</dt><dd><a href="{{content['url']}}" target="_blank">{{content['url']}}</a></dd>
</dl>
<h5>Tracks</h5>
<ul>
{% for track in content['tracks']['edges'] %}
<li>{{ track['node']['artists'][0]['name'] }} - {{ track['node']['title'] }}</li>
{% endfor %}
<h4><a class="text-dark nounderline" href="{{content['url']}}" target="_blank">{{content['title']}}</a></h4>
<label for="migration">Migration progress:</label>
<progress id="migration" style="width: 100%" value="{{ session['progress'] }}" max="100"></progress>
<h6>Failed Tracks (if any)</h6>
<ul id="failed-tracks" style="color: red">
<!--Will be filled using JS-->
</ul>
<dl class="dl-horizontal">
<dt>Id</dt><dd>{{content['id']}}</dd>
<dt>TrackCount</dt><dd>{{content['trackCount']}}</dd>
<dt>Visibility</dt><dd>{{content['visibility']}}</dd>
<dt>Duration</dt><dd>{{content['duration']}}</dd>
<dt>Amazon Url</dt><dd><a href="{{content['url']}}" target="_blank">{{content['url']}}</a></dd>
<dt>Spotify Url</dt><dd><a href="{{ session['destination'] }}" target="_blank">{{ session['destination'] }}</a></dd>
</dl>
<h6>Track Translation</h6>
<div id="track-translation-table">
<!--Will be filled using JS-->
</div>
</div>
</div>
{% endblock %}
48 changes: 30 additions & 18 deletions util.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,31 +88,50 @@ def create_spotify_playlist(name: str):
logging.error("could not create new playlist in spotify")
logging.error(response.text)

playlist_id = json.loads(response.text)['id']
payload = json.loads(response.text)
playlist_id = payload['id']
settings.DESTINATION_PLAYLIST_URL = payload['external_urls']['spotify']
session['destination'] = settings.DESTINATION_PLAYLIST_URL
return playlist_id


def add_tracks_to_spotify_playlist(spotify_access_token: str, playlist_id: str, tracks: list[dict]):
def add_tracks_to_spotify_playlist(spotify_access_token: str, playlist_id: str):
count = 0
for track in tracks:
# first get track id
logging.debug(f"length of tracks: {len(settings.TRACK_TRANSLATION)}")
for track in settings.TRACK_TRANSLATION:
# update progress
count += 1
settings.PROGRESS = (count / len(settings.TRACK_TRANSLATION)) * 100
logging.debug(f"track count: {count}")
logging.debug(f"progress: {settings.PROGRESS}")

# get track id
logging.debug(f"Searching for track: {track['artist']} - {track['title']}")
url = f'{SPOTIFY_BASE_ENDPOINT}/search'
params = {
'q': f'remaster%20track:{track["title"]}%20artist:{track["artist"]}',
'q': f'{track["title"]} - {track["artist"]}',
'type': 'track',
'limit': 2,
'limit': 1,
}

headers = {
'Authorization': f'Bearer {spotify_access_token}'
}
response = requests.get(url, params=params, headers=headers)
results = json.loads(response.text)['tracks']['items']
# sort results by popularity and use most popular
result = sorted(results, key=lambda d: d['popularity'])[0]
spotify_track_id = result['id']
# might return inaccurate results if track is not actually present in spotify
logging.debug(f'Found track on spotify: {result["artists"][0]["name"]} - {result["name"]}')

if len(results) == 0:
logging.error(f"Could not find the track on spotify, skipping...")
settings.FAILED_TRACKS += f"<li>{track['artist']} - {track['title']}</li>"
continue

spotify_track_id = results[0]['id']
logging.debug(f'Found track on spotify: {results[0]["artists"][0]["name"]} - {results[0]["name"]}')

track['translation'] = {
'artist': results[0]["artists"][0]["name"],
'title': results[0]["name"],
}

# add track to playlist
url = f'{SPOTIFY_BASE_ENDPOINT}/playlists/{playlist_id}/tracks'
Expand All @@ -131,10 +150,3 @@ def add_tracks_to_spotify_playlist(spotify_access_token: str, playlist_id: str,
if response.status_code != 201:
logging.error("couldn't add track {track['artist'] - track['title']} to playlist")
logging.error(response.text)

# write progress to session
count += 1
settings.PROGRESS = (count / len(tracks)) * 100
print(f"length of tracks: {len(tracks)}")
print(f"track count: {count}")
print(f"progress: {settings.PROGRESS}")

0 comments on commit f05957d

Please sign in to comment.