From 4fd340bf2275058b4a8ad0814bb9fcd900004d4a Mon Sep 17 00:00:00 2001 From: axolotlmaid Date: Wed, 25 Sep 2024 19:56:34 +0100 Subject: [PATCH] feat: add lastfm route and workers --- .env.example | 6 ++++- cmd/backend/main.go | 2 ++ internal/handler/lastfm.go | 12 +++++++++ internal/model/lastfm.go | 27 +++++++++++++++++++ internal/server/router.go | 2 ++ internal/service/lastfm.go | 55 ++++++++++++++++++++++++++++++++++++++ internal/worker/lastfm.go | 20 ++++++++++++++ internal/worker/worker.go | 5 ++++ 8 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 internal/handler/lastfm.go create mode 100644 internal/model/lastfm.go create mode 100644 internal/service/lastfm.go create mode 100644 internal/worker/lastfm.go create mode 100644 internal/worker/worker.go diff --git a/.env.example b/.env.example index 19c8da3..791847c 100644 --- a/.env.example +++ b/.env.example @@ -1,2 +1,6 @@ # Port for the server -PORT=8888 \ No newline at end of file +PORT=8888 +# Your last.fm username +LASTFM_USERNAME="axolotlmaid" +# API Key for last.fm +LASTFM_API_KEY="API_KEY_GOES_HERE" \ No newline at end of file diff --git a/cmd/backend/main.go b/cmd/backend/main.go index d0c6679..48737be 100644 --- a/cmd/backend/main.go +++ b/cmd/backend/main.go @@ -8,6 +8,7 @@ import ( "github.com/lmittmann/tint" "backend/internal/server" + "backend/internal/worker" ) func main() { @@ -19,5 +20,6 @@ func main() { slog.Error("Error loading .env file", slog.Any("error", err)) } + go worker.StartWorkers() server.NewRouter() } diff --git a/internal/handler/lastfm.go b/internal/handler/lastfm.go new file mode 100644 index 0000000..1224707 --- /dev/null +++ b/internal/handler/lastfm.go @@ -0,0 +1,12 @@ +package handler + +import ( + "backend/internal/worker" + "encoding/json" + "net/http" +) + +func HandleGetCurrentlyPlaying(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(worker.LastFMData) +} diff --git a/internal/model/lastfm.go b/internal/model/lastfm.go new file mode 100644 index 0000000..f417067 --- /dev/null +++ b/internal/model/lastfm.go @@ -0,0 +1,27 @@ +package model + +type LastFMAPI struct { + RecentTracks struct { + TrackList []struct { + Artist struct { + Text string `json:"#text"` + } `json:"artist"` + Name string `json:"name"` + Image []struct { + Text string `json:"#text"` + } `json:"image"` + Url string `json:"url"` + Attributes *struct { + NowPlaying string `json:"nowplaying"` + } `json:"@attr,omitempty"` + } `json:"track"` + } `json:"recenttracks"` +} + +type LastFMData struct { + Song string `json:"song"` + Artist string `json:"artist"` + Image string `json:"image"` + Url string `json:"url"` + Playing bool `json:"playing"` +} diff --git a/internal/server/router.go b/internal/server/router.go index cde73e8..91857f6 100644 --- a/internal/server/router.go +++ b/internal/server/router.go @@ -29,6 +29,8 @@ func NewRouter() { r.Get("/visitor-counter", handler.HandleGetVisitorCounter) r.Patch("/visitor-counter", handler.HandlePatchVisitorCounter) + r.Get("/currently-playing", handler.HandleGetCurrentlyPlaying) + slog.Info("Starting server", slog.Any("port", os.Getenv("PORT"))) http.ListenAndServe(":"+os.Getenv("PORT"), r) } diff --git a/internal/service/lastfm.go b/internal/service/lastfm.go new file mode 100644 index 0000000..36f5599 --- /dev/null +++ b/internal/service/lastfm.go @@ -0,0 +1,55 @@ +package service + +import ( + "backend/internal/model" + "encoding/json" + "fmt" + "io" + "log/slog" + "net/http" + "os" +) + +func GetLastFMData() model.LastFMData { + data := model.LastFMData{ + Song: "api error", + Artist: "???", + Image: "/missing.webp", + Url: "https://www.last.fm/user/axolotlmaid" + os.Getenv("LASTFM_USERNAME"), + Playing: false, + } + + url := fmt.Sprintf("http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user=%s&api_key=%s&format=json&limit=1", os.Getenv("LASTFM_USERNAME"), os.Getenv("LASTFM_API_KEY")) + res, err := http.Get(url) + if err != nil { + slog.Error("Error requesting last.fm API", slog.Any("error", err)) + return data + } + + body, err := io.ReadAll(res.Body) + if err != nil { + slog.Error("Error reading body", slog.Any("error", err)) + return data + } + + var lastfmJSON model.LastFMAPI + + err = json.Unmarshal(body, &lastfmJSON) + if err != nil { + slog.Error("Error unmarshalling JSON", slog.Any("error", err)) + return data + } + + lastfmData := lastfmJSON.RecentTracks.TrackList[0] + + if lastfmData.Attributes != nil { + data.Playing = true + } + + data.Song = lastfmData.Name + data.Artist = lastfmData.Artist.Text + data.Image = lastfmData.Image[2].Text + data.Url = lastfmData.Url + + return data +} diff --git a/internal/worker/lastfm.go b/internal/worker/lastfm.go new file mode 100644 index 0000000..9917902 --- /dev/null +++ b/internal/worker/lastfm.go @@ -0,0 +1,20 @@ +package worker + +import ( + "backend/internal/model" + "backend/internal/service" + "log/slog" + "time" +) + +var LastFMData model.LastFMData + +func StartLastFMWorker() { + slog.Info("Starting last.fm worker...") + LastFMData = service.GetLastFMData() + + for range time.Tick(30 * time.Second) { + slog.Info("Requesting last.fm...") + LastFMData = service.GetLastFMData() + } +} diff --git a/internal/worker/worker.go b/internal/worker/worker.go new file mode 100644 index 0000000..7d50800 --- /dev/null +++ b/internal/worker/worker.go @@ -0,0 +1,5 @@ +package worker + +func StartWorkers() { + go StartLastFMWorker() +}