-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
161 lines (136 loc) · 4.38 KB
/
main.go
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package main
import (
"bufio"
"context"
"encoding/csv"
"fmt"
"net/http"
"os"
"os/exec"
"path/filepath"
"strings"
"time"
"github.com/joho/godotenv"
"github.com/zmb3/spotify/v2"
spotifyauth "github.com/zmb3/spotify/v2/auth"
)
// Spotify API endpoint URLs
const (
SPOTIFY_API_URL = "https://api.spotify.com/v1"
SPOTIFY_SEARCH_URL = SPOTIFY_API_URL + "/search"
SPOTIFY_PLAYLISTS_URL = SPOTIFY_API_URL + "/users/%s/playlists"
)
var State = "playlister-" + time.Now().String()
func createAuthClient() (*spotify.Client, error) {
auth := spotifyauth.New(
spotifyauth.WithClientID(os.Getenv("SPOTIFY_CLIENT_ID")),
spotifyauth.WithClientSecret(os.Getenv("SPOTIFY_CLIENT_SECRET")),
spotifyauth.WithRedirectURL("http://localhost:8008/callback"),
spotifyauth.WithScopes(spotifyauth.ScopePlaylistModifyPrivate),
)
authURL := auth.AuthURL(State)
fmt.Printf("Please log in to Spotify by visiting the following page in your web browser:\n\n%s\n\n", authURL)
err := exec.Command("open", "-a", "Google Chrome", authURL).Run()
if err != nil {
fmt.Println(err)
return nil, err
}
// start a web server to listen for the callback request
authChan := make(chan *spotify.Client)
errChan := make(chan error)
go func() {
http.HandleFunc("/callback", func(_ http.ResponseWriter, r *http.Request) {
// get the authorization code from the query parameters
code := r.URL.Query().Get("code")
// exchange the authorization code for an access token
token, err := auth.Exchange(r.Context(), code)
if err != nil {
errChan <- fmt.Errorf("failed to exchange authorization code: %v", err)
return
}
// create a Spotify client using the access token
client := spotify.New(auth.Client(r.Context(), token))
authChan <- client
})
if err := http.ListenAndServe(":8008", nil); err != nil {
errChan <- fmt.Errorf("failed to start HTTP server: %v", err)
}
}()
// wait for the authentication process to complete
select {
case client := <-authChan:
return client, nil
case err := <-errChan:
return nil, err
}
}
func main() {
// Load environment variables
err := godotenv.Load()
if err != nil {
fmt.Println("Error loading .env file")
}
// primt for csv path
inputReader := bufio.NewReader(os.Stdin)
fmt.Print("Enter the path for the csv file you want to playlist: ")
csvFilePath, _ := inputReader.ReadString('\n')
csvFilePath = strings.TrimSuffix(csvFilePath, "\n")
if csvFilePath == "" {
fmt.Println("Please provide a path to a CSV file using the -csv flag")
return
}
file, err := os.Open(csvFilePath)
if err != nil {
fmt.Printf("Failed to open CSV file: %v\n", err)
return
}
defer file.Close()
reader := csv.NewReader(file)
records, err := reader.ReadAll()
if err != nil {
fmt.Printf("Failed to read CSV file: %v\n", err)
return
}
// create a Spotify client using client credentials flow
client, err := createAuthClient()
if err != nil {
fmt.Printf("Failed to create Spotify client: %v\n", err)
return
}
ctx := context.Background()
user, err := client.CurrentUser(ctx)
if err != nil {
fmt.Printf("failed to get current user: %v", err)
}
// create a new playlist with the name of the CSV file
playlistName := strings.TrimSuffix(filepath.Base(csvFilePath), filepath.Ext(csvFilePath))
playlist, err := client.CreatePlaylistForUser(ctx, user.ID, playlistName, "", false, false)
if err != nil {
fmt.Printf("Failed to create playlist '%s': %v\n", playlistName, err)
return
}
// add each track from the CSV file to the playlist
for _, record := range records[1:] {
// search for the track using the artist and track name fields
query := fmt.Sprintf("%s %s", record[1], record[0])
searchResp, err := client.Search(ctx, query, spotify.SearchTypeTrack)
if err != nil {
fmt.Printf("Failed to search for track '%s': %v\n", record[1], err)
continue
}
// throw in slight delay to avoid rate limiting
// time.Sleep(100 * time.Millisecond)
// add the first search result to the playlist
if len(searchResp.Tracks.Tracks) > 0 {
trackID := searchResp.Tracks.Tracks[0].ID
_, err := client.AddTracksToPlaylist(ctx, playlist.ID, trackID)
if err != nil {
fmt.Printf("Failed to add track '%s - %s' to playlist: %v\n", record[1], record[0], err)
continue
}
fmt.Printf("Added track '%s - %s' to playlist\n", record[1], record[0])
} else {
fmt.Printf("Could not find track '%s- %s'\n", record[1], record[0])
}
}
}