Skip to content

Commit a9d084a

Browse files
Add Discogs label thumbnail repair + Spotify rate limit handling
- New RepairDiscogsLabelThumbnails: replaces Discogs thumbnails with Spotify playlist images (runs 20 per cycle alongside existing managers) - Add spotifyDo helper with 429 retry for all Spotify API calls Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 5c7858c commit a9d084a

File tree

1 file changed

+64
-3
lines changed

1 file changed

+64
-3
lines changed

functions/manage-playlists/main.go

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ import (
1616
"net/http"
1717
"net/url"
1818
"os"
19+
"strconv"
1920
"strings"
21+
"time"
2022
)
2123

2224
type App struct {
@@ -133,6 +135,7 @@ func Handler() error {
133135

134136
if oauthToken != "" {
135137
app.RepairTerminatedThumbnails(oauthToken)
138+
app.RepairDiscogsLabelThumbnails(oauthToken)
136139
app.ArchiveTerminatedPlaylists(oauthToken)
137140
}
138141

@@ -251,6 +254,41 @@ func (client *App) RepairTerminatedThumbnails(accessToken string) {
251254
}
252255
}
253256

257+
func (client *App) RepairDiscogsLabelThumbnails(accessToken string) {
258+
rows, err := client.SQLDriver.Query(`
259+
SELECT l.label_id, p.spotify_playlist FROM dg_labels l
260+
JOIN dg_playlists p ON l.label_id = p.label_id AND p.num = 1
261+
WHERE l.thumbnail_medium IS NULL
262+
OR l.thumbnail_medium = ''
263+
OR l.thumbnail_medium NOT LIKE '%spotify%'
264+
LIMIT 20`)
265+
if err != nil {
266+
fmt.Println("RepairDiscogsLabelThumbnails query error:", err)
267+
return
268+
}
269+
defer rows.Close()
270+
271+
for rows.Next() {
272+
var labelID, playlistID string
273+
if err := rows.Scan(&labelID, &playlistID); err != nil {
274+
continue
275+
}
276+
imageURL, err := getSpotifyPlaylistImage(accessToken, playlistID)
277+
if err != nil || imageURL == "" {
278+
fmt.Printf("[DG] No Spotify image for label %s: %v\n", labelID, err)
279+
continue
280+
}
281+
_, err = client.SQLDriver.Exec(
282+
"UPDATE dg_labels SET thumbnail_medium = ? WHERE label_id = ?",
283+
imageURL, labelID)
284+
if err != nil {
285+
fmt.Printf("[DG] Failed to update thumbnail for label %s: %v\n", labelID, err)
286+
continue
287+
}
288+
fmt.Printf("[DG] Repaired thumbnail for label %s\n", labelID)
289+
}
290+
}
291+
254292
func (client *App) ArchiveTerminatedPlaylists(accessToken string) {
255293
rows, err := client.SQLDriver.Query(`
256294
SELECT e.channel_name, p.spotify_playlist FROM yt_channels e
@@ -286,11 +324,34 @@ func (client *App) ArchiveTerminatedPlaylists(accessToken string) {
286324
}
287325
}
288326

327+
// spotifyDo executes an HTTP request with Spotify 429 rate-limit retry.
328+
func spotifyDo(req *http.Request) (*http.Response, error) {
329+
for i := 0; i < 3; i++ {
330+
resp, err := http.DefaultClient.Do(req)
331+
if err != nil {
332+
return nil, err
333+
}
334+
if resp.StatusCode != 429 {
335+
return resp, nil
336+
}
337+
resp.Body.Close()
338+
wait := 5
339+
if s := resp.Header.Get("Retry-After"); s != "" {
340+
if v, err := strconv.Atoi(s); err == nil {
341+
wait = v
342+
}
343+
}
344+
fmt.Printf("[Rate limited] waiting %ds\n", wait)
345+
time.Sleep(time.Duration(wait) * time.Second)
346+
}
347+
return nil, fmt.Errorf("rate limited after 3 retries")
348+
}
349+
289350
func getSpotifyPlaylistName(accessToken, playlistID string) (string, error) {
290351
req, _ := http.NewRequest("GET",
291352
"https://api.spotify.com/v1/playlists/"+playlistID+"?fields=name", nil)
292353
req.Header.Set("Authorization", "Bearer "+accessToken)
293-
resp, err := http.DefaultClient.Do(req)
354+
resp, err := spotifyDo(req)
294355
if err != nil {
295356
return "", err
296357
}
@@ -312,7 +373,7 @@ func renameSpotifyPlaylist(accessToken, playlistID, newName string) error {
312373
strings.NewReader(string(payload)))
313374
req.Header.Set("Authorization", "Bearer "+accessToken)
314375
req.Header.Set("Content-Type", "application/json")
315-
resp, err := http.DefaultClient.Do(req)
376+
resp, err := spotifyDo(req)
316377
if err != nil {
317378
return err
318379
}
@@ -328,7 +389,7 @@ func getSpotifyPlaylistImage(accessToken, playlistID string) (string, error) {
328389
req, _ := http.NewRequest("GET",
329390
"https://api.spotify.com/v1/playlists/"+playlistID+"?fields=images", nil)
330391
req.Header.Set("Authorization", "Bearer "+accessToken)
331-
resp, err := http.DefaultClient.Do(req)
392+
resp, err := spotifyDo(req)
332393
if err != nil {
333394
return "", err
334395
}

0 commit comments

Comments
 (0)