diff options
Diffstat (limited to 'commands.go')
-rw-r--r-- | commands.go | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/commands.go b/commands.go index 55582a0..5a2c71b 100644 --- a/commands.go +++ b/commands.go @@ -3,6 +3,7 @@ package senpai import ( "errors" "fmt" + "net/url" "sort" "strconv" "strings" @@ -11,6 +12,8 @@ import ( "git.sr.ht/~taiite/senpai/irc" "git.sr.ht/~taiite/senpai/ui" "github.com/gdamore/tcell/v2" + "github.com/godbus/dbus/v5" + "golang.org/x/net/context" ) var ( @@ -57,6 +60,11 @@ func init() { Desc: "send an action (reply to last query if sent from home)", Handle: commandDoMe, }, + "NP": { + AllowHome: true, + Desc: "send the current song that is being played on the system", + Handle: commandDoNP, + }, "MSG": { AllowHome: true, MinArgs: 2, @@ -343,6 +351,14 @@ func commandDoMe(app *App, args []string) (err error) { return nil } +func commandDoNP(app *App, args []string) (err error) { + song := getSong() + if song == "" { + return fmt.Errorf("no song was detected") + } + return commandDoMe(app, []string{fmt.Sprintf("np: %s", song)}) +} + func commandDoMsg(app *App, args []string) (err error) { target := args[0] content := args[1] @@ -775,3 +791,81 @@ func (app *App) handleInput(buffer, content string) error { return cmd.Handle(app, args) } + +func getSong() string { + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + + bus, err := dbus.ConnectSessionBus(dbus.WithContext(ctx)) + if err != nil { + return "" + } + defer bus.Close() + + var names []string + if err := bus.BusObject().CallWithContext(ctx, "org.freedesktop.DBus.ListNames", 0).Store(&names); err != nil { + return "" + } + song := "" + for _, name := range names { + if !strings.HasPrefix(name, "org.mpris.MediaPlayer2.") { + continue + } + var playing bool + o := bus.Object(name, "/org/mpris/MediaPlayer2") + var status string + if err := o.CallWithContext(ctx, "org.freedesktop.DBus.Properties.Get", 0, "org.mpris.MediaPlayer2.Player", "PlaybackStatus").Store(&status); err != nil { + continue + } + switch status { + case "Playing": + playing = true + case "Paused": + playing = false + default: + continue + } + var metadata map[string]dbus.Variant + if err := o.CallWithContext(ctx, "org.freedesktop.DBus.Properties.Get", 0, "org.mpris.MediaPlayer2.Player", "Metadata").Store(&metadata); err != nil { + continue + } + var trackURL string + var title string + var album string + var artist string + if e, ok := metadata["xesam:title"].Value().(string); ok { + title = e + } + if e, ok := metadata["xesam:album"].Value().(string); ok { + album = e + } + if e, ok := metadata["xesam:url"].Value().(string); ok { + trackURL = e + } + if e, ok := metadata["xesam:artist"].Value().([]string); ok && len(e) > 0 { + artist = e[0] + } + if title == "" { + continue + } + var sb strings.Builder + fmt.Fprintf(&sb, "\x02%s\x02", title) + if artist != "" { + fmt.Fprintf(&sb, " by \x02%s\x02", artist) + } + if album != "" { + fmt.Fprintf(&sb, " from \x02%s\x02", album) + } + if u, err := url.Parse(trackURL); err == nil { + switch u.Scheme { + case "http", "https": + fmt.Fprintf(&sb, " — %s", trackURL) + } + } + song = sb.String() + if playing { + return song + } + } + return song +} |