-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathspoti2saber.py
111 lines (101 loc) · 4.25 KB
/
spoti2saber.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#/usr/bin/env python3
import requests
import os
import json
import string
import argparse
def levenstein(str_1, str_2):
n, m = len(str_1), len(str_2)
if n > m:
str_1, str_2 = str_2, str_1
n, m = m, n
current_row = range(n + 1)
for i in range(1, m + 1):
previous_row, current_row = current_row, [i] + [0] * n
for j in range(1, n + 1):
add, delete, change = previous_row[j] + 1, current_row[j - 1] + 1, previous_row[j - 1]
if str_1[j - 1] != str_2[i - 1]:
change += 1
current_row[j] = min(add, delete, change)
return current_row[n]
def getspotisongs(oauth_token):
print("\nFetching user library\n")
r=requests.get("https://api.spotify.com/v1/me/tracks?limit=50",headers={"Authorization": "Bearer "+oauth_token})
resp=r.json()
songs=[]
while True:
for song in resp['items']:
songs.append({"artist":song['track']['artists'][0]['name'],"track":song['track']['name']})
print(resp['next'])
if not resp['next']:
break
r=requests.get(resp['next'],headers={"Authorization": "Bearer "+oauth_token})
resp=r.json()
return songs
def findurls(songs):
urls={}
for song in songs:
r=requests.get('https://api.beatsaver.com/search/text/0?sortOrder=Relevance',params={"q":song["artist"]+" "+song["track"]})
try:
resp=r.json()
except:
continue
print ("\n"+song["artist"]+" - "+song["track"])
songname=song["artist"]+" - "+song["track"]
songname_rev=song["track"]+" - "+song["artist"]
cnt=0
if 'docs' in resp:
cnt+=1
urls[songname]=[]
for map in resp['docs']:
lev=levenstein(map["name"],songname)
proportion=100-int((lev/(len(map["name"])+len(songname)))*100)
lev_rev=levenstein(map["name"],songname_rev)
proportion_rev=100-int((lev_rev/(len(map["name"])+len(songname)))*100)
ups=map["stats"]["upvotes"]
downs=map["stats"]["downvotes"]
url=map['versions'][0]['downloadURL']
try:
updown=int((ups/(ups+downs))*100)
except ZeroDivisionError:
updown=0
if (lev_rev<lev):
lev=lev_rev
proportion=proportion_rev
print(f'{map["name"]} LEV:{lev}({proportion}) UPDOWN:{updown}% ({ups+downs})')
urls[songname].append({"cnt":cnt,"lev":lev,"proportion":proportion,"updown":updown,"ups":ups,"downs":downs,"url":url,"mapname":map["name"]})
return urls
def processurls(urls,who,limit):
playlist={"playlistTitle":"Spotify "+who,"playlistAuthor":"me","playlistDescription":"","_filename":"Spotify_"+who+".bplist","songs":[]}
for songname in urls:
cnt=0
print("\nSearching for "+songname+":")
for map in urls[songname]:
if map["lev"]==0 and map["updown"]>60:
print(map["mapname"])
playlist["songs"].append({"hash":map["url"].split("/")[-1][:-4],"songName":map["mapname"]})
continue
if map["proportion"]>66 and map["updown"]>60:
print(map["mapname"])
cnt+=1
playlist["songs"].append({"hash":map["url"].split("/")[-1][:-4],"songName":map["mapname"]})
if cnt==limit:
break
return playlist
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('playlist_name', help='Playlist name')
parser.add_argument('oauth_token', help='Spotify OAUTH token')
parser.add_argument('--limit', type=int, default=3, help='Max number of "similar" songs (Default: 3). May flood your playlist with unrelated songs if set too high')
args = parser.parse_args()
who=args.playlist_name
oauth_token=args.oauth_token
limit=args.limit
songs=getspotisongs(oauth_token)
urls=findurls(songs)
playlist=processurls(urls,who,limit)
songs=playlist["songs"]
songsu=[dict(s) for s in set(frozenset(d.items()) for d in songs)]
playlist["songs"]=list(songsu)
with open("Spotify_"+who+".bplist","w") as f:
json.dump(playlist,f)