1package commands 2 3import ( 4 "fmt" 5 "strconv" 6 7 "github.com/ambientsound/visp/log" 8 spotify_tracklist "github.com/ambientsound/visp/spotify/tracklist" 9 "github.com/google/uuid" 10 "github.com/zmb3/spotify" 11 12 "github.com/ambientsound/visp/api" 13) 14 15// Write saves a local tracklist to Spotify. 16type Write struct { 17 command 18 api api.API 19 name string 20 new bool 21 public bool 22} 23 24// NewWrite returns Write. 25func NewWrite(api api.API) Command { 26 return &Write{ 27 api: api, 28 } 29} 30 31// Parse implements Command. 32func (cmd *Write) Parse() error { 33 lit := cmd.ScanRemainderAsIdentifier() 34 35 cmd.setTabComplete(lit, []string{strconv.Quote(cmd.api.List().Name())}) 36 37 if len(lit) > 0 { 38 cmd.name = lit 39 } 40 41 // TODO: private/public? 42 43 return nil 44} 45 46// Exec implements Command. 47func (cmd *Write) Exec() error { 48 client, err := cmd.api.Spotify() 49 if err != nil { 50 return err 51 } 52 53 tracklist := cmd.api.Tracklist() 54 if tracklist == nil { 55 return fmt.Errorf("only track lists can be saved to Spotify") 56 } 57 58 // Copy tracklist, assign new name, and save that one 59 if len(cmd.name) > 0 { 60 tracklist = tracklist.Copy() 61 tracklist.SetID(uuid.New().String()) 62 tracklist.SetName(cmd.name) 63 cmd.api.Db().Cache(tracklist) 64 } 65 66 row := cmd.api.Db().RowByID(tracklist.ID()) 67 if row == nil { 68 return fmt.Errorf("internal error: tracklist not cached in database") 69 } 70 71 user, err := client.CurrentUser() 72 if err != nil { 73 return err 74 } 75 76 ids := make([]spotify.ID, 0, tracklist.Len()) 77 for _, track := range tracklist.Tracks() { 78 ids = append(ids, track.ID) 79 } 80 81 if !tracklist.HasRemote() { 82 remotelist, err := client.CreatePlaylistForUser(user.ID, tracklist.Name(), "", cmd.public) 83 if err != nil { 84 return fmt.Errorf("create remote playlist: %w", err) 85 } 86 87 tracklist.SetID(remotelist.ID.String()) 88 tracklist.SetName(remotelist.Name) 89 tracklist.SetRemote(true) 90 row.SetID(tracklist.ID()) 91 92 // Re-index original list in database if working on the old copy 93 94 cmd.api.SetList(tracklist) 95 96 snapshot, err := spotify_tracklist.AddTracksToPlaylist(client, remotelist.ID, ids) 97 if err != nil { 98 return fmt.Errorf("add tracks to remote playlist: %w", err) 99 } 100 _ = snapshot // todo: add and use this? 101 102 log.Infof("Created playlist '%s' with %d tracks", remotelist.Name, len(ids)) 103 104 } else { 105 106 id := spotify.ID(tracklist.ID()) 107 err := client.ChangePlaylistName(id, tracklist.Name()) 108 if err != nil { 109 return fmt.Errorf("change remote playlist name: %w", err) 110 } 111 112 err = spotify_tracklist.ReplacePlaylistTracks(client, id, ids) 113 if err != nil { 114 return fmt.Errorf("write new track list to to remote playlist: %w", err) 115 } 116 117 log.Infof("Wrote changes to remote playlist '%s' with %d tracks", tracklist.Name(), len(ids)) 118 } 119 120 tracklist.SetSyncedToRemote() 121 122 return nil 123} 124