This commit is contained in:
abs3nt 2024-02-18 18:51:25 -08:00
parent 567fb54ac2
commit affb5fbaba
Signed by: abs3nt
GPG Key ID: A7BD96A8BAB04C09
22 changed files with 322 additions and 219 deletions

View File

@ -18,7 +18,7 @@ builds:
- goos: windows - goos: windows
goarch: "386" goarch: "386"
ldflags: ldflags:
- -s -w -X git.asdf.cafe/abs3nt/gospt-ng/src/components/cli.Version={{.Version}} - -s -w -X git.asdf.cafe/abs3nt/gspot/src/components/cli.Version=({{.Version}} - {{.Now}})
archives: archives:
- format: tar.gz - format: tar.gz

View File

@ -3,7 +3,7 @@ steps:
image: golang:1.22 image: golang:1.22
commands: commands:
- go mod tidy - go mod tidy
- go build -o gospt-ng - go build -o gspot
publish: publish:
image: goreleaser/goreleaser:nightly image: goreleaser/goreleaser:nightly

View File

@ -1,7 +1,7 @@
build: gospt-ng build: gspot
gospt-ng: $(shell find . -name '*.go') gspot: $(shell find . -name '*.go')
go build -ldflags="-X 'git.asdf.cafe/abs3nt/gospt-ng/src/components/cli.Version=$(shell git rev-parse --short HEAD)'" -o dist/ . go build -ldflags="-X 'git.asdf.cafe/abs3nt/gspot/src/components/cli.Version=$(shell git show -s --date=short --pretty='format:%h (%ad)' HEAD)'" -o dist/ .
run: run:
go run main.go go run main.go
@ -13,11 +13,11 @@ clean:
rm -rf bin rm -rf bin
uninstall: uninstall:
rm -f /usr/bin/gospt-ng rm -f /usr/bin/gspot
rm -f /usr/share/zsh/site-functions/_gospt-ng rm -f /usr/share/zsh/site-functions/_gspot
rm -f /usr/share/bash-completion/completions/gospt-ng rm -f /usr/share/bash-completion/completions/gspot
install: install:
cp ./dist/gospt-ng /usr/bin cp ./dist/gspot /usr/bin
cp ./completions/_gospt-ng /usr/share/zsh/site-functions/_gospt-ng cp ./completions/_gspot /usr/share/zsh/site-functions/_gspot
cp ./completions/gospt-ng /usr/share/bash-completion/completions/gospt-ng cp ./completions/gspot /usr/share/bash-completion/completionsgspotg

View File

@ -1,4 +1,4 @@
#compdef gospt-ng #compdef gspot
_cli_zsh_autocomplete() { _cli_zsh_autocomplete() {
local -a opts local -a opts
@ -17,4 +17,4 @@ _cli_zsh_autocomplete() {
fi fi
} }
compdef _cli_zsh_autocomplete gospt-ng compdef _cli_zsh_autocomplete gspot

2
go.mod
View File

@ -1,4 +1,4 @@
module git.asdf.cafe/abs3nt/gospt-ng module git.asdf.cafe/abs3nt/gspot
go 1.22.0 go 1.22.0

View File

@ -3,10 +3,10 @@ package main
import ( import (
"go.uber.org/fx" "go.uber.org/fx"
"git.asdf.cafe/abs3nt/gospt-ng/src/app" "git.asdf.cafe/abs3nt/gspot/src/app"
"git.asdf.cafe/abs3nt/gospt-ng/src/components/cache" "git.asdf.cafe/abs3nt/gspot/src/components/cache"
"git.asdf.cafe/abs3nt/gospt-ng/src/components/cli" "git.asdf.cafe/abs3nt/gspot/src/components/cli"
"git.asdf.cafe/abs3nt/gospt-ng/src/components/commands" "git.asdf.cafe/abs3nt/gspot/src/components/commands"
) )
func main() { func main() {

View File

@ -9,8 +9,8 @@ import (
"github.com/lmittmann/tint" "github.com/lmittmann/tint"
"go.uber.org/fx" "go.uber.org/fx"
"git.asdf.cafe/abs3nt/gospt-ng/src/config" "git.asdf.cafe/abs3nt/gspot/src/config"
"git.asdf.cafe/abs3nt/gospt-ng/src/services" "git.asdf.cafe/abs3nt/gspot/src/services"
) )
var Services = fx.Options( var Services = fx.Options(
@ -31,7 +31,7 @@ var Config = fx.Options(
fx.Provide( fx.Provide(
func() *config.Config { func() *config.Config {
c := &config.Config{} c := &config.Config{}
gunner.LoadApp(c, "gospt") gunner.LoadApp(c, "gspot")
return c return c
}, },
), ),

View File

@ -35,7 +35,7 @@ type CacheParams struct {
func NewCache(p CacheParams) CacheResult { func NewCache(p CacheParams) CacheResult {
c := &Cache{ c := &Cache{
Root: filepath.Join(os.TempDir(), "gospt.cache"), Root: filepath.Join(os.TempDir(), "gspot.cache"),
Log: p.Log, Log: p.Log,
} }
return CacheResult{ return CacheResult{

View File

@ -9,8 +9,8 @@ import (
"github.com/zmb3/spotify/v2" "github.com/zmb3/spotify/v2"
"go.uber.org/fx" "go.uber.org/fx"
"git.asdf.cafe/abs3nt/gospt-ng/src/components/commands" "git.asdf.cafe/abs3nt/gspot/src/components/commands"
"git.asdf.cafe/abs3nt/gospt-ng/src/components/tui" "git.asdf.cafe/abs3nt/gspot/src/components/tui"
) )
var Version = "dev" var Version = "dev"
@ -23,6 +23,7 @@ func Run(c *commands.Commander, s fx.Shutdowner) {
} }
}() }()
app := &cli.App{ app := &cli.App{
Name: "gspot",
EnableBashCompletion: true, EnableBashCompletion: true,
Version: Version, Version: Version,
Action: func(ctx *cli.Context) error { Action: func(ctx *cli.Context) error {
@ -95,11 +96,20 @@ func Run(c *commands.Commander, s fx.Shutdowner) {
Category: "Sharing", Category: "Sharing",
}, },
{ {
Name: "next", Name: "next",
Aliases: []string{"n", "skip"}, Aliases: []string{"n", "skip"},
Usage: "Skips to the next song", Usage: "Skips to the next song",
Args: true,
ArgsUsage: "amount",
Action: func(cCtx *cli.Context) error { Action: func(cCtx *cli.Context) error {
return c.Next() if cCtx.NArg() > 0 {
amt, err := strconv.Atoi(cCtx.Args().First())
if err != nil {
return err
}
return c.Next(amt, false)
}
return c.Next(1, false)
}, },
Category: "Playback", Category: "Playback",
}, },

View File

@ -12,8 +12,8 @@ import (
func (c *Commander) activateDevice() (spotify.ID, error) { func (c *Commander) activateDevice() (spotify.ID, error) {
var device *spotify.PlayerDevice var device *spotify.PlayerDevice
configDir, _ := os.UserConfigDir() configDir, _ := os.UserConfigDir()
if _, err := os.Stat(filepath.Join(configDir, "gospt/device.json")); err == nil { if _, err := os.Stat(filepath.Join(configDir, "gspot/device.json")); err == nil {
deviceFile, err := os.Open(filepath.Join(configDir, "gospt/device.json")) deviceFile, err := os.Open(filepath.Join(configDir, "gspot/device.json"))
if err != nil { if err != nil {
return "", err return "", err
} }
@ -31,7 +31,7 @@ func (c *Commander) activateDevice() (spotify.ID, error) {
return "", err return "", err
} }
} else { } else {
c.Log.Error("COMMANDER", "failed to activated device", "YOU MUST RUN gospt setdevice FIRST") c.Log.Error("COMMANDER", "failed to activated device", "YOU MUST RUN gspot setdevice FIRST")
} }
return device.ID, nil return device.ID, nil
} }

View File

@ -8,7 +8,7 @@ import (
"github.com/zmb3/spotify/v2" "github.com/zmb3/spotify/v2"
"go.uber.org/fx" "go.uber.org/fx"
"git.asdf.cafe/abs3nt/gospt-ng/src/components/cache" "git.asdf.cafe/abs3nt/gspot/src/components/cache"
) )
type CommanderResult struct { type CommanderResult struct {

View File

@ -42,7 +42,7 @@ func (c *Commander) SetDevice(device spotify.ID) error {
return err return err
} }
configDir, _ := os.UserConfigDir() configDir, _ := os.UserConfigDir()
err = os.WriteFile(filepath.Join(configDir, "gospt/device.json"), out, 0o600) err = os.WriteFile(filepath.Join(configDir, "gspot/device.json"), out, 0o600)
if err != nil { if err != nil {
return err return err
} }

View File

@ -1,25 +1,117 @@
package commands package commands
import ( import (
"strings"
"github.com/zmb3/spotify/v2" "github.com/zmb3/spotify/v2"
) )
func (c *Commander) Next() error { func (c *Commander) Next(amt int, inqueue bool) error {
err := c.Client.Next(c.Context) if inqueue {
if err != nil { for i := 0; i < amt; i++ {
if isNoActiveError(err) { err := c.Client.Next(c.Context)
deviceId, err := c.activateDevice()
if err != nil {
return err
}
err = c.Client.NextOpt(c.Context, &spotify.PlayOptions{
DeviceID: &deviceId,
})
if err != nil { if err != nil {
return err return err
} }
} }
return nil
}
if amt == 1 {
err := c.Client.Next(c.Context)
if err != nil {
if isNoActiveError(err) {
deviceId, err := c.activateDevice()
if err != nil {
return err
}
err = c.Client.NextOpt(c.Context, &spotify.PlayOptions{
DeviceID: &deviceId,
})
if err != nil {
return err
}
}
return err
}
return nil
}
// found := false
// playingIndex := 0
current, err := c.Client.PlayerCurrentlyPlaying(c.Context)
if err != nil {
return err return err
} }
playbackContext := current.PlaybackContext.Type
switch playbackContext {
case "playlist":
found := false
currentTrackIndex := 0
page := 1
for !found {
playlist, err := c.Client.
GetPlaylistItems(
c.Context,
spotify.ID(strings.Split(string(current.PlaybackContext.URI), ":")[2]),
spotify.Limit(50),
spotify.Offset((page-1)*50),
)
if err != nil {
return err
}
for idx, track := range playlist.Items {
if track.Track.Track.ID == current.Item.ID {
currentTrackIndex = idx + (50 * (page - 1))
found = true
break
}
}
page++
}
pos := currentTrackIndex + amt
return c.Client.PlayOpt(c.Context, &spotify.PlayOptions{
PlaybackContext: &current.PlaybackContext.URI,
PlaybackOffset: &spotify.PlaybackOffset{
Position: &pos,
},
})
case "album":
found := false
currentTrackIndex := 0
page := 1
for !found {
playlist, err := c.Client.
GetAlbumTracks(
c.Context,
spotify.ID(strings.Split(string(current.PlaybackContext.URI), ":")[2]),
spotify.Limit(50),
spotify.Offset((page-1)*50),
)
if err != nil {
return err
}
for idx, track := range playlist.Tracks {
if track.ID == current.Item.ID {
currentTrackIndex = idx + (50 * (page - 1))
found = true
break
}
}
page++
}
pos := currentTrackIndex + amt
return c.Client.PlayOpt(c.Context, &spotify.PlayOptions{
PlaybackContext: &current.PlaybackContext.URI,
PlaybackOffset: &spotify.PlaybackOffset{
Position: &pos,
},
})
default:
for i := 0; i < amt; i++ {
err := c.Client.Next(c.Context)
if err != nil {
return err
}
}
}
return nil return nil
} }

View File

@ -44,7 +44,12 @@ func (c *Commander) RadioFromPlaylist(playlist spotify.SimplePlaylist) error {
if pages > 1 { if pages > 1 {
randomPage = frand.Intn(pages-1) + 1 randomPage = frand.Intn(pages-1) + 1
} }
playlistPage, err := c.Client.GetPlaylistItems(c.Context, playlist.ID, spotify.Limit(50), spotify.Offset((randomPage-1)*50)) playlistPage, err := c.Client.GetPlaylistItems(
c.Context,
playlist.ID,
spotify.Limit(50),
spotify.Offset((randomPage-1)*50),
)
if err != nil { if err != nil {
return err return err
} }
@ -287,14 +292,14 @@ func (c *Commander) ClearRadio() error {
} }
_, _ = db.Query("DROP TABLE IF EXISTS radio") _, _ = db.Query("DROP TABLE IF EXISTS radio")
configDir, _ := os.UserConfigDir() configDir, _ := os.UserConfigDir()
os.Remove(filepath.Join(configDir, "gospt/radio.json")) os.Remove(filepath.Join(configDir, "gspot/radio.json"))
_ = c.Client.Pause(c.Context) _ = c.Client.Pause(c.Context)
return nil return nil
} }
func (c *Commander) GetRadioPlaylist(name string) (*spotify.FullPlaylist, *sql.DB, error) { func (c *Commander) GetRadioPlaylist(name string) (*spotify.FullPlaylist, *sql.DB, error) {
configDir, _ := os.UserConfigDir() configDir, _ := os.UserConfigDir()
playlistFile, err := os.ReadFile(filepath.Join(configDir, "gospt/radio.json")) playlistFile, err := os.ReadFile(filepath.Join(configDir, "gspot/radio.json"))
if errors.Is(err, os.ErrNotExist) { if errors.Is(err, os.ErrNotExist) {
return c.CreateRadioPlaylist(name) return c.CreateRadioPlaylist(name)
} }
@ -306,7 +311,7 @@ func (c *Commander) GetRadioPlaylist(name string) (*spotify.FullPlaylist, *sql.D
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
db, err := sql.Open("sqlite", filepath.Join(configDir, "gospt/radio.db")) db, err := sql.Open("sqlite", filepath.Join(configDir, "gspot/radio.db"))
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -325,11 +330,11 @@ func (c *Commander) CreateRadioPlaylist(name string) (*spotify.FullPlaylist, *sq
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
err = os.WriteFile(filepath.Join(configDir, "gospt/radio.json"), raw, 0o600) err = os.WriteFile(filepath.Join(configDir, "gspot/radio.json"), raw, 0o600)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
db, err := sql.Open("sqlite", filepath.Join(configDir, "gospt/radio.db")) db, err := sql.Open("sqlite", filepath.Join(configDir, "gspot/radio.db"))
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

View File

@ -3,7 +3,7 @@ package commands
import ( import (
"fmt" "fmt"
"git.asdf.cafe/abs3nt/gospt-ng/src/components/youtube" "git.asdf.cafe/abs3nt/gspot/src/components/youtube"
) )
func (c *Commander) PrintYoutubeLink() error { func (c *Commander) PrintYoutubeLink() error {

View File

@ -1,120 +0,0 @@
package tui
import (
"github.com/zmb3/spotify/v2"
"git.asdf.cafe/abs3nt/gospt-ng/src/components/commands"
)
func HandlePlayWithContext(commands *commands.Commander, uri *spotify.URI, pos *int) {
err := commands.PlaySongInPlaylist(uri, pos)
if err != nil {
return
}
}
func HandleRadio(commands *commands.Commander, song spotify.SimpleTrack) {
err := commands.RadioGivenSong(song, 0)
if err != nil {
return
}
}
func HandleAlbumRadio(commands *commands.Commander, album spotify.SimpleAlbum) {
err := commands.RadioFromAlbum(album)
if err != nil {
return
}
}
func HandleSeek(commands *commands.Commander, fwd bool) {
err := commands.Seek(fwd)
if err != nil {
return
}
}
func HandleVolume(commands *commands.Commander, up bool) {
vol := 10
if !up {
vol = -10
}
err := commands.ChangeVolume(vol)
if err != nil {
return
}
}
func HandleArtistRadio(commands *commands.Commander, artist spotify.SimpleArtist) {
err := commands.RadioGivenArtist(artist)
if err != nil {
return
}
}
func HandleAlbumArtist(commands *commands.Commander, artist spotify.SimpleArtist) {
err := commands.RadioGivenArtist(artist)
if err != nil {
return
}
}
func HandlePlaylistRadio(commands *commands.Commander, playlist spotify.SimplePlaylist) {
err := commands.RadioFromPlaylist(playlist)
if err != nil {
return
}
}
func HandleLibraryRadio(commands *commands.Commander) {
err := commands.RadioFromSavedTracks()
if err != nil {
return
}
}
func HandlePlayLikedSong(commands *commands.Commander, position int) {
err := commands.PlayLikedSongs(position)
if err != nil {
return
}
}
func HandlePlayTrack(commands *commands.Commander, track spotify.ID) {
err := commands.QueueSong(track)
if err != nil {
return
}
err = commands.Next()
if err != nil {
return
}
}
func HandleNextInQueue(commands *commands.Commander, amt int) {
err := commands.Next()
if err != nil {
return
}
}
func HandleQueueItem(commands *commands.Commander, item spotify.ID) {
err := commands.QueueSong(item)
if err != nil {
return
}
}
func HandleDeleteTrackFromPlaylist(commands *commands.Commander, item, playlist spotify.ID) {
err := commands.DeleteTracksFromPlaylist([]spotify.ID{item}, playlist)
if err != nil {
return
}
}
func HandleSetDevice(commands *commands.Commander, player spotify.PlayerDevice) {
err := commands.SetDevice(player.ID)
if err != nil {
return
}
}

View File

@ -14,7 +14,7 @@ import (
"github.com/charmbracelet/lipgloss" "github.com/charmbracelet/lipgloss"
"github.com/zmb3/spotify/v2" "github.com/zmb3/spotify/v2"
"git.asdf.cafe/abs3nt/gospt-ng/src/components/commands" "git.asdf.cafe/abs3nt/gspot/src/components/commands"
) )
var ( var (
@ -93,37 +93,92 @@ func (m *mainModel) PlayRadio() {
selectedItem := m.list.SelectedItem().(mainItem).SpotifyItem selectedItem := m.list.SelectedItem().(mainItem).SpotifyItem
switch item := selectedItem.(type) { switch item := selectedItem.(type) {
case spotify.SimplePlaylist: case spotify.SimplePlaylist:
go HandlePlaylistRadio(m.commands, item) go func() {
err := m.commands.RadioFromPlaylist(item)
if err != nil {
m.SendMessage(err.Error(), 5*time.Second)
}
}()
return return
case *spotify.SavedTrackPage: case *spotify.SavedTrackPage:
go HandleLibraryRadio(m.commands) go func() {
err := m.commands.RadioFromSavedTracks()
if err != nil {
m.SendMessage(err.Error(), 5*time.Second)
}
}()
return return
case spotify.SimpleAlbum: case spotify.SimpleAlbum:
go HandleAlbumRadio(m.commands, item) go func() {
err := m.commands.RadioFromAlbum(item)
if err != nil {
m.SendMessage(err.Error(), 5*time.Second)
}
}()
return return
case spotify.FullAlbum: case spotify.FullAlbum:
go HandleAlbumRadio(m.commands, item.SimpleAlbum) go func() {
err := m.commands.RadioFromAlbum(item.SimpleAlbum)
if err != nil {
m.SendMessage(err.Error(), 5*time.Second)
}
}()
return return
case spotify.SimpleArtist: case spotify.SimpleArtist:
go HandleArtistRadio(m.commands, item) go func() {
err := m.commands.RadioGivenArtist(item)
if err != nil {
m.SendMessage(err.Error(), 5*time.Second)
}
}()
return return
case spotify.FullArtist: case spotify.FullArtist:
go HandleArtistRadio(m.commands, item.SimpleArtist) go func() {
err := m.commands.RadioGivenArtist(item.SimpleArtist)
if err != nil {
m.SendMessage(err.Error(), 5*time.Second)
}
}()
return return
case spotify.SimpleTrack: case spotify.SimpleTrack:
go HandleRadio(m.commands, item) go func() {
err := m.commands.RadioGivenSong(item, 0)
if err != nil {
m.SendMessage(err.Error(), 5*time.Second)
}
}()
return return
case spotify.FullTrack: case spotify.FullTrack:
go HandleRadio(m.commands, item.SimpleTrack) go func() {
err := m.commands.RadioGivenSong(item.SimpleTrack, 0)
if err != nil {
m.SendMessage(err.Error(), 5*time.Second)
}
}()
return return
case spotify.PlaylistTrack: case spotify.PlaylistTrack:
go HandleRadio(m.commands, item.Track.SimpleTrack) go func() {
err := m.commands.RadioGivenSong(item.Track.SimpleTrack, 0)
if err != nil {
m.SendMessage(err.Error(), 5*time.Second)
}
}()
return return
case spotify.PlaylistItem: case spotify.PlaylistItem:
go HandleRadio(m.commands, item.Track.Track.SimpleTrack) go func() {
err := m.commands.RadioGivenSong(item.Track.Track.SimpleTrack, 0)
if err != nil {
m.SendMessage(err.Error(), 5*time.Second)
}
}()
return return
case spotify.SavedTrack: case spotify.SavedTrack:
go HandleRadio(m.commands, item.SimpleTrack) go func() {
err := m.commands.RadioGivenSong(item.SimpleTrack, 0)
if err != nil {
m.SendMessage(err.Error(), 5*time.Second)
}
}()
return return
} }
} }
@ -254,29 +309,38 @@ func (m *mainModel) SendMessage(msg string, duration time.Duration) {
} }
func (m *mainModel) QueueItem() error { func (m *mainModel) QueueItem() error {
var id spotify.ID
var name string
switch item := m.list.SelectedItem().(mainItem).SpotifyItem.(type) { switch item := m.list.SelectedItem().(mainItem).SpotifyItem.(type) {
case spotify.PlaylistTrack: case spotify.PlaylistTrack:
go m.SendMessage("Adding "+item.Track.Name+" to queue", 2*time.Second) name = item.Track.Name
go HandleQueueItem(m.commands, item.Track.ID) id = item.Track.ID
case spotify.SavedTrack: case spotify.SavedTrack:
go m.SendMessage("Adding "+item.Name+" to queue", 2*time.Second) name = item.Name
go HandleQueueItem(m.commands, item.ID) id = item.ID
case spotify.SimpleTrack: case spotify.SimpleTrack:
go m.SendMessage("Adding "+item.Name+" to queue", 2*time.Second) name = item.Name
go HandleQueueItem(m.commands, item.ID) id = item.ID
case spotify.FullTrack: case spotify.FullTrack:
go m.SendMessage("Adding "+item.Name+" to queue", 2*time.Second) name = item.Name
go HandleQueueItem(m.commands, item.ID) id = item.ID
case *spotify.FullTrack: case *spotify.FullTrack:
go m.SendMessage("Adding "+item.Name+" to queue", 2*time.Second) name = item.Name
go HandleQueueItem(m.commands, item.ID) id = item.ID
case *spotify.SimpleTrack: case *spotify.SimpleTrack:
go m.SendMessage("Adding "+item.Name+" to queue", 2*time.Second) name = item.Name
go HandleQueueItem(m.commands, item.ID) id = item.ID
case *spotify.SimplePlaylist: case *spotify.SimplePlaylist:
go m.SendMessage("Adding "+item.Name+" to queue", 2*time.Second) name = item.Name
go HandleQueueItem(m.commands, item.ID) id = item.ID
} }
go m.SendMessage("Adding "+name+" to queue", 2*time.Second)
go func() {
err := m.commands.QueueSong(id)
if err != nil {
m.SendMessage(err.Error(), 5*time.Second)
}
}()
if m.mode == Queue { if m.mode == Queue {
go func() { go func() {
new_items, err := QueueView(m.commands) new_items, err := QueueView(m.commands)
@ -296,10 +360,13 @@ func (m *mainModel) DeleteTrackFromPlaylist() error {
track := m.list.SelectedItem().(mainItem).SpotifyItem.(spotify.PlaylistTrack).Track track := m.list.SelectedItem().(mainItem).SpotifyItem.(spotify.PlaylistTrack).Track
go m.SendMessage("Deleteing "+track.Name+" from "+m.playlist.Name, 2*time.Second) go m.SendMessage("Deleteing "+track.Name+" from "+m.playlist.Name, 2*time.Second)
go func() { go func() {
HandleDeleteTrackFromPlaylist(m.commands, track.ID, m.playlist.ID) err := m.commands.DeleteTracksFromPlaylist([]spotify.ID{track.ID}, m.playlist.ID)
if err != nil {
m.SendMessage(err.Error(), 5*time.Second)
}
new_items, err := PlaylistView(m.commands, m.playlist) new_items, err := PlaylistView(m.commands, m.playlist)
if err != nil { if err != nil {
return m.SendMessage(err.Error(), 5*time.Second)
} }
m.list.SetItems(new_items) m.list.SetItems(new_items)
}() }()
@ -311,10 +378,13 @@ func (m *mainModel) SelectItem() error {
case Queue: case Queue:
page = 1 page = 1
go func() { go func() {
HandleNextInQueue(m.commands, m.list.Index()) err := m.commands.Next(m.list.Index(), true)
if err != nil {
m.SendMessage(err.Error(), 5*time.Second)
}
new_items, err := QueueView(m.commands) new_items, err := QueueView(m.commands)
if err != nil { if err != nil {
return m.SendMessage(err.Error(), 5*time.Second)
} }
m.list.SetItems(new_items) m.list.SetItems(new_items)
m.list.ResetSelected() m.list.ResetSelected()
@ -471,17 +541,43 @@ func (m *mainModel) SelectItem() error {
m.list.ResetSelected() m.list.ResetSelected()
case Album, ArtistAlbum, SearchArtistAlbum, SearchAlbum: case Album, ArtistAlbum, SearchArtistAlbum, SearchAlbum:
pos := m.list.Cursor() + (m.list.Paginator.Page * m.list.Paginator.TotalPages) pos := m.list.Cursor() + (m.list.Paginator.Page * m.list.Paginator.TotalPages)
go HandlePlayWithContext(m.commands, &m.album.URI, &pos) go func() {
_ = m.commands.PlaySongInPlaylist(&m.album.URI, &pos)
}()
case Playlist, SearchPlaylist: case Playlist, SearchPlaylist:
pos := m.list.Cursor() + (m.list.Paginator.Page * m.list.Paginator.PerPage) pos := m.list.Cursor() + (m.list.Paginator.Page * m.list.Paginator.PerPage)
go HandlePlayWithContext(m.commands, &m.playlist.URI, &pos) go func() {
_ = m.commands.PlaySongInPlaylist(&m.playlist.URI, &pos)
}()
case Tracks: case Tracks:
go HandlePlayLikedSong(m.commands, m.list.Cursor()+(m.list.Paginator.Page*m.list.Paginator.PerPage)) go func() {
err := m.commands.PlayLikedSongs(m.list.Cursor() + (m.list.Paginator.Page * m.list.Paginator.PerPage))
if err != nil {
m.SendMessage(err.Error(), 5*time.Second)
}
}()
case SearchTracks: case SearchTracks:
go HandlePlayTrack(m.commands, m.list.SelectedItem().(mainItem).SpotifyItem.(spotify.FullTrack).ID) go func() {
err := m.commands.QueueSong(m.list.SelectedItem().(mainItem).SpotifyItem.(spotify.FullTrack).ID)
if err != nil {
m.SendMessage(err.Error(), 5*time.Second)
return
}
err = m.commands.Next(1, false)
if err != nil {
m.SendMessage(err.Error(), 5*time.Second)
return
}
}()
case Devices: case Devices:
go HandleSetDevice(m.commands, m.list.SelectedItem().(mainItem).SpotifyItem.(spotify.PlayerDevice)) go func() {
go m.SendMessage("Setting device to "+m.list.SelectedItem().FilterValue(), 2*time.Second) err := m.commands.SetDevice(m.list.SelectedItem().(mainItem).SpotifyItem.(spotify.PlayerDevice).ID)
if err != nil {
m.SendMessage(err.Error(), 5*time.Second)
} else {
m.SendMessage("Setting device to "+m.list.SelectedItem().FilterValue(), 2*time.Second)
}
}()
m.mode = "main" m.mode = "main"
new_items, err := MainView(m.commands) new_items, err := MainView(m.commands)
if err != nil { if err != nil {
@ -654,16 +750,36 @@ func (m *mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
} }
} }
if msg.String() == ">" { if msg.String() == ">" {
go HandleSeek(m.commands, true) go func() {
err := m.commands.Seek(true)
if err != nil {
m.SendMessage(err.Error(), 5*time.Second)
}
}()
} }
if msg.String() == "<" { if msg.String() == "<" {
go HandleSeek(m.commands, false) go func() {
err := m.commands.Seek(false)
if err != nil {
m.SendMessage(err.Error(), 5*time.Second)
}
}()
} }
if msg.String() == "+" { if msg.String() == "+" {
go HandleVolume(m.commands, true) go func() {
err := m.commands.ChangeVolume(10)
if err != nil {
m.SendMessage(err.Error(), 5*time.Second)
}
}()
} }
if msg.String() == "-" { if msg.String() == "-" {
go HandleVolume(m.commands, false) go func() {
err := m.commands.ChangeVolume(-10)
if err != nil {
m.SendMessage(err.Error(), 5*time.Second)
}
}()
} }
// search input // search input
if m.input.Focused() { if m.input.Focused() {
@ -769,7 +885,7 @@ func InitMain(c *commands.Commander, mode Mode) (tea.Model, error) {
mode: mode, mode: mode,
progress: prog, progress: prog,
} }
m.list.Title = "GOSPT" m.list.Title = "GSPOT"
go m.TickPlayback() go m.TickPlayback()
Tick() Tick()
m.list.DisableQuitKeybindings() m.list.DisableQuitKeybindings()

View File

@ -3,7 +3,7 @@ package tui
import ( import (
tea "github.com/charmbracelet/bubbletea" tea "github.com/charmbracelet/bubbletea"
"git.asdf.cafe/abs3nt/gospt-ng/src/components/commands" "git.asdf.cafe/abs3nt/gspot/src/components/commands"
) )
// StartTea the entry point for the UI. Initializes the model. // StartTea the entry point for the UI. Initializes the model.

View File

@ -9,7 +9,7 @@ import (
"github.com/zmb3/spotify/v2" "github.com/zmb3/spotify/v2"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
"git.asdf.cafe/abs3nt/gospt-ng/src/components/commands" "git.asdf.cafe/abs3nt/gspot/src/components/commands"
) )
const regex = `<.*?>` const regex = `<.*?>`

View File

@ -94,7 +94,7 @@ func Search(query string) string {
ctx := context.Background() ctx := context.Background()
confDir, _ := os.UserConfigDir() confDir, _ := os.UserConfigDir()
b, err := os.ReadFile(filepath.Join(confDir, "gospt", "client_secret.json")) b, err := os.ReadFile(filepath.Join(confDir, "gspot", "client_secret.json"))
if err != nil { if err != nil {
log.Fatalf("Unable to read client secret file: %v", err) log.Fatalf("Unable to read client secret file: %v", err)
} }

View File

@ -17,7 +17,7 @@ import (
"golang.org/x/exp/slog" "golang.org/x/exp/slog"
"golang.org/x/oauth2" "golang.org/x/oauth2"
"git.asdf.cafe/abs3nt/gospt-ng/src/config" "git.asdf.cafe/abs3nt/gspot/src/config"
) )
type SpotifyClientResult struct { type SpotifyClientResult struct {
@ -79,8 +79,8 @@ func NewSpotifyClient(conf *config.Config) (c SpotifyClientResult, err error) {
spotifyauth.ScopeStreaming, spotifyauth.ScopeStreaming,
), ),
) )
if _, err := os.Stat(filepath.Join(configDir, "gospt/auth.json")); err == nil { if _, err := os.Stat(filepath.Join(configDir, "gspot/auth.json")); err == nil {
authFilePath := filepath.Join(configDir, "gospt/auth.json") authFilePath := filepath.Join(configDir, "gspot/auth.json")
authFile, err := os.Open(authFilePath) authFile, err := os.Open(authFilePath)
if err != nil { if err != nil {
return SpotifyClientResult{}, err return SpotifyClientResult{}, err
@ -157,7 +157,7 @@ func completeAuth(w http.ResponseWriter, r *http.Request) {
slog.Error("AUTHENTICATOR", "failed to unmarshal", err) slog.Error("AUTHENTICATOR", "failed to unmarshal", err)
os.Exit(1) os.Exit(1)
} }
err = os.WriteFile(filepath.Join(configDir, "gospt/auth.json"), out, 0o600) err = os.WriteFile(filepath.Join(configDir, "gspot/auth.json"), out, 0o600)
if err != nil { if err != nil {
slog.Error("AUTHENTICATOR", "failed to save auth", err) slog.Error("AUTHENTICATOR", "failed to save auth", err)
} }