--- /dev/null
+brackets*
+*/seed/seed
+secrets.sh
+vendor/
--- /dev/null
+package client
+
+import (
+ "context"
+ "fmt"
+ "github.com/zmb3/spotify"
+ "golang.org/x/oauth2/clientcredentials"
+ "os"
+)
+
+func Get() (*spotify.Client, error) {
+ config := &clientcredentials.Config{
+ ClientID: os.Getenv("SPOTIFY_ID"),
+ ClientSecret: os.Getenv("SPOTIFY_SECRET"),
+ TokenURL: spotify.TokenURL,
+ }
+
+ token, err := config.Token(context.Background())
+ if err != nil {
+ return nil, fmt.Errorf("client: %w", err)
+ }
+
+ client := spotify.Authenticator{}.NewClient(token)
+ return &client, nil
+}
--- /dev/null
+package db
+
+import (
+ "database/sql"
+ "sync"
+)
+
+// A DB that can be locked, as SQLite can't be concurrently written to.
+type DB struct {
+ Db *sql.DB
+ Mu *sync.Mutex
+}
+
+func New() (*DB, error) {
+ db, err := sql.Open("sqlite3", "brackets.sqlite")
+ if err != nil {
+ return nil, err
+ }
+ return &DB{Db: db, Mu: &sync.Mutex{}}, err
+}
--- /dev/null
+module git.jacobcasper.com/brackets
+
+go 1.14
+
+require (
+ github.com/mattn/go-sqlite3 v2.0.3+incompatible
+ github.com/zmb3/spotify v0.0.0-20200413172747-49e8144a06f7
+ golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
+)
--- /dev/null
+cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
+github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
+github.com/zmb3/spotify v0.0.0-20200413172747-49e8144a06f7 h1:EsuM9MBGEmyCEQn2Tz4bO6IyUCgCovK3eZm9rrBJ9FE=
+github.com/zmb3/spotify v0.0.0-20200413172747-49e8144a06f7/go.mod h1:CYu0Uo+YYMlUX39zUTsCU9j3SpK3l1eB8oLykXF7R7w=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e h1:bRhVy7zSSasaqNksaRZiA5EEI+Ei4I1nO5Jh72wfHlg=
+golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
+golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
--- /dev/null
+package main
+
+import (
+ "git.jacobcasper.com/brackets/client"
+ "git.jacobcasper.com/brackets/db"
+ _ "github.com/mattn/go-sqlite3"
+ "log"
+)
+
+func main() {
+
+ db, err := db.New()
+ if err != nil {
+ log.Fatal("Could not open db: ", err.Error())
+ }
+
+ client, err := client.Get()
+ if err != nil {
+ log.Fatal("Could not get client: ", err.Error())
+ }
+
+ _, page, err := client.FeaturedPlaylists()
+
+ for _, playlist := range page.Playlists {
+ tracks, err := client.GetPlaylistTracks(playlist.ID)
+ if err != nil {
+ log.Printf("Couldn't retrieve playlist %s.", string(playlist.ID))
+ }
+ for _, trackPage := range tracks.Tracks {
+ for _, artist := range trackPage.Track.Artists {
+ db.Mu.Lock()
+ db.Db.Exec("INSERT INTO ARTIST (ID, NAME) VALUES (?, ?)", artist.ID, artist.Name)
+ db.Mu.Unlock()
+ }
+ }
+ }
+}