Last.fm plugin (#12) * Init Last.fm plugin * Fix Unix timestamp parsing * go mod tidy
Anirudh Oppiliappan x@icyphox.sh
Sat, 11 Dec 2021 21:05:18 +0530
4 files changed,
169 insertions(+),
1 deletions(-)
A
plugins/lastfm.go
@@ -0,0 +1,56 @@
+package plugins + +import ( + "strings" + + "git.icyphox.sh/paprika/plugins/lastfm" + "github.com/dgraph-io/badger/v3" + "gopkg.in/irc.v3" +) + +func init() { + Register(LastFM{}) +} + +type LastFM struct{} + +func (LastFM) Triggers() []string { + return []string{ + ".lfm", + ".np", + } +} + +func (LastFM) Execute(m *irc.Message) (string, error) { + parts := strings.SplitN(m.Trailing(), " ", 2) + trigger := parts[0] + + switch trigger { + case ".lfm": + if len(parts) == 2 { + arg := parts[1] + err := lastfm.Setup(arg, m.Prefix.Name) + if err != nil { + return "Database error", err + } + return "Successfully set Last.fm username", nil + } else { + return "usage: .lfm <username>", nil + } + case ".np": + user, err := lastfm.GetUser(m.Prefix.Name) + if err == badger.ErrKeyNotFound { + return "User not found. Set it using '.lfm <username>'", nil + } else if err != nil { + return "Database error", err + } + + np, err := lastfm.NowPlaying(user) + if err != nil { + return "Listenbrainz error", err + } + return np, nil + } + + panic("Unreachable!") +}
A
plugins/lastfm/db.go
@@ -0,0 +1,26 @@
+package lastfm + +import ( + "fmt" + + "git.icyphox.sh/paprika/database" +) + +// Store the Last.fm username against the nick. +func Setup(lfmUser, nick string) error { + err := database.DB.Set( + []byte(fmt.Sprintf("lfm/%s", nick)), + []byte(lfmUser), + ) + return err +} + +// Gets the Last.fm username from the DB. +func GetUser(nick string) (string, error) { + nick = fmt.Sprintf("lfm/%s", nick) + user, err := database.DB.Get([]byte(nick)) + if err != nil { + return "", err + } + return string(user), nil +}
A
plugins/lastfm/nowplaying.go
@@ -0,0 +1,84 @@
+package lastfm + +import ( + "encoding/json" + "fmt" + "net/http" + "strconv" + "time" + + "git.icyphox.sh/paprika/config" + "github.com/dustin/go-humanize" +) + +type ListenInfo struct { + RecentTracks struct { + Track []struct { + Artist struct { + Text string `json:"#text"` + } `json:"artist"` + Album struct { + Text string `json:"#text"` + } `json:"album"` + Name string `json:"name"` + Date struct { + UnixTimestamp string `json:"uts"` + } `json:"date"` + Attr struct { + NowPlaying string `json:"nowplaying"` + } `json:"@attr"` + } `json:"track"` + } `json:"recenttracks"` +} + +func getRecentTracks(url string) (*ListenInfo, error) { + li := ListenInfo{} + r, err := http.Get(url) + if err != nil { + return nil, err + } else if r.StatusCode != 200 { + return nil, fmt.Errorf("non-200 response from Last.fm") + } + + json.NewDecoder(r.Body).Decode(&li) + defer r.Body.Close() + + return &li, err +} + +func NowPlaying(user string) (string, error) { + key := config.C.ApiKeys["lastfm-key"] + url := fmt.Sprintf( + "https://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user=%s&api_key=%s&format=json", + user, + key, + ) + + rt, err := getRecentTracks(url) + if err != nil { + return "", err + } + + track := rt.RecentTracks.Track[0] + if rt.RecentTracks.Track[0].Attr.NowPlaying == "true" { + return fmt.Sprintf( + "%s is currently listening to \"%s\" by \x02%s\x02, from the album \x02%s\x02", + user, + track.Name, + track.Artist.Text, + track.Album.Text, + ), nil + } else { + strT := track.Date.UnixTimestamp + ts, _ := strconv.Atoi(strT) + t := time.Unix(int64(ts), 0) + return fmt.Sprintf( + "%s listened to \"%s\" by \x02%s\x02, from the album \x02%s\x02, %s", + user, + track.Name, + track.Artist.Text, + track.Album.Text, + humanize.Time(t), + ), nil + } +}
M
plugins/listenbrainz.go
→
plugins/listenbrainz.go
@@ -16,7 +16,9 @@
type Listenbrainz struct{} func (Listenbrainz) Triggers() []string { - return []string{".np", ".lbz"} + // TODO: removing .np from here until we figure out how + // it can co-exist with Last.fm + return []string{".lbz"} } func (Listenbrainz) Execute(m *irc.Message) (string, error) {