-
Notifications
You must be signed in to change notification settings - Fork 1
/
script.py
105 lines (89 loc) · 3.67 KB
/
script.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
import spotipy
import requests
import os
import random
import datetime
import pandas as pd
import base64
# Function to refresh access token
def refresh_access_token(refresh_token):
client_id = os.environ['SPOTIPY_CLIENT_ID']
client_secret = os.environ['SPOTIPY_CLIENT_SECRET']
payload = {
'grant_type': 'refresh_token',
'refresh_token': refresh_token,
}
auth_header = {'Authorization': 'Basic ' + base64.b64encode((client_id + ':' + client_secret).encode()).decode()}
response = requests.post('https://accounts.spotify.com/api/token', data=payload, headers=auth_header)
return response.json().get('access_token')
client_id = os.environ['SPOTIPY_CLIENT_ID']
client_secret = os.environ['SPOTIPY_CLIENT_SECRET']
refresh_token = os.environ['SPOTIPY_REFRESH_TOKEN']
new_access_token = refresh_access_token(refresh_token)
# Set up Spotipy
sp = spotipy.Spotify(auth=new_access_token)
# Get all liked songs
# Since i have over 3000 songs, i need to get them in batches
# Spotify's API only allows upto 50 songs at a time
offset = 0
liked_songs = []
while True:
batch = sp.current_user_saved_tracks(offset=offset)
liked_songs += batch['items']
if batch['next'] is None:
break
offset += len(batch['items'])
# Filter songs added more than 90 days ago and create weighted list
# I am choosing three months as my cutoff but you can choose whatever you want
weighted_songs = []
for song in liked_songs:
added_date = datetime.datetime.strptime(song['added_at'], "%Y-%m-%dT%H:%M:%SZ")
added_date = added_date.replace(tzinfo=datetime.timezone.utc) # Add UTC timezone information
age_days = (datetime.datetime.now(datetime.timezone.utc) - added_date).days
if age_days > 90:
# Below I simply use the age in days as the weight
# this is going to repeat the songs as many days old it is
# there are other ways to do this, but this is the simplest
weighted_songs += [song['track']['id']] * age_days
# Shuffle the weighted list and select the top 100 (or desired number)
random.shuffle(weighted_songs)
selected_tracks = weighted_songs[:100]
# get names of selected tracks
selected_tracks_names = [sp.track(track_id)['name'] for track_id in selected_tracks]
selected_tracks_names
# Store these selected tracks in a CSV file for record keeping
# Save a pandas data frame with selected tracks and a today's date and time as a CSV file
df = pd.DataFrame({'date': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
'track_name': selected_tracks_names,
'track_id': selected_tracks})
# if df exists, append to it
# if not, create it
def append_to_csv(df):
try:
existing_df = pd.read_csv('selected_tracks.csv')
df = pd.concat([existing_df, df])
except:
pass
df.to_csv('./selected_tracks.csv', index=False)
append_to_csv(df)
# Finally...
# Create a new playlist or get an existing one
user_id = sp.me()['id']
playlist_name = 'random'
playlists = sp.user_playlists(user_id)
existing_playlist_id = None
# Check if a playlist with the same name already exists
for playlist in playlists['items']:
if playlist['name'] == playlist_name:
existing_playlist_id = playlist['id']
break
# If it exists, clear the tracks
if existing_playlist_id:
sp.playlist_replace_items(existing_playlist_id, [])
playlist_id = existing_playlist_id
else:
# If it doesn't exist, create a new one
playlist = sp.user_playlist_create(user_id, playlist_name, public=True, description="This week's random songs that I haven't listened in a while")
playlist_id = playlist['id']
# Add selected tracks to the playlist
sp.playlist_add_items(playlist_id, selected_tracks)