131 lines
3.4 KiB
Go
131 lines
3.4 KiB
Go
package scrape
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"time"
|
|
|
|
"github.com/PuerkitoBio/goquery"
|
|
"github.com/dustin/go-humanize"
|
|
)
|
|
|
|
type listenbrainz struct {
|
|
Name string
|
|
}
|
|
|
|
type listenbrainzMbidMapping struct {
|
|
RecordingMbid string `json:"recording_mbid"`
|
|
ReleaseMbid string `json:"release_mbid"`
|
|
Artists []struct {
|
|
ArtistMbid string `json:"artist_mbid"`
|
|
Name string `json:"artist_credit_name"`
|
|
} `json:"artists"`
|
|
CoverArtArchiveID int64 `json:"caa_id"`
|
|
}
|
|
|
|
type listenbrainzTrackAdditionalInfo struct {
|
|
URL string `json:"origin_url"`
|
|
}
|
|
|
|
type listenbrainzTrackMetadata struct {
|
|
Name string `json:"track_name"`
|
|
Artist string `json:"artist_name"`
|
|
ReleaseName string `json:"release_name"`
|
|
AdditionalInfo listenbrainzTrackAdditionalInfo `json:"additional_info"`
|
|
MbidMapping *listenbrainzMbidMapping `json:"mbid_mapping"`
|
|
}
|
|
|
|
type listenbrainzListen struct {
|
|
TrackMetadata listenbrainzTrackMetadata `json:"track_metadata"`
|
|
Timestamp int64 `json:"listened_at"`
|
|
}
|
|
|
|
type listenbrainzReactProps struct {
|
|
Listens []listenbrainzListen `json:"listens"`
|
|
}
|
|
|
|
func (s *listenbrainz) GetNowPlaying(username string) (response *ScrobblerResponse, err error) {
|
|
encodedUsername := url.PathEscape(username)
|
|
resp, err := http.Get(fmt.Sprintf("https://listenbrainz.org/user/%s/", encodedUsername))
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
doc, err := goquery.NewDocumentFromReader(resp.Body)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
reactPropsJson := doc.Find("#page-react-props").Text()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
var reactProps listenbrainzReactProps
|
|
json.Unmarshal([]byte(reactPropsJson), &reactProps)
|
|
|
|
if len(reactProps.Listens) < 1 {
|
|
err = errors.New("no listens recorded")
|
|
return
|
|
}
|
|
|
|
lastPlayed := reactProps.Listens[0]
|
|
|
|
track := Track{
|
|
Name: lastPlayed.TrackMetadata.Name,
|
|
StreamURL: &lastPlayed.TrackMetadata.AdditionalInfo.URL,
|
|
}
|
|
|
|
artist := &Artist{
|
|
Name: lastPlayed.TrackMetadata.Artist,
|
|
}
|
|
|
|
album := &Album{
|
|
Name: lastPlayed.TrackMetadata.ReleaseName,
|
|
}
|
|
|
|
var coverURL *string
|
|
|
|
if lastPlayed.TrackMetadata.MbidMapping != nil {
|
|
trackUrl := fmt.Sprintf("https://musicbrainz.org/recording/%s", lastPlayed.TrackMetadata.MbidMapping.RecordingMbid)
|
|
track.URL = &trackUrl
|
|
albumUrl := fmt.Sprintf("https://musicbrainz.org/release/%s", lastPlayed.TrackMetadata.MbidMapping.ReleaseMbid)
|
|
album.URL = &albumUrl
|
|
coverURLstr := fmt.Sprintf("https://coverartarchive.org/release/%s/%d.jpg", lastPlayed.TrackMetadata.MbidMapping.ReleaseMbid, lastPlayed.TrackMetadata.MbidMapping.CoverArtArchiveID)
|
|
coverURL = &coverURLstr
|
|
artistURL := fmt.Sprintf("https://musicbrainz.org/artist/%s", lastPlayed.TrackMetadata.MbidMapping.Artists[0].ArtistMbid)
|
|
artist.URL = &artistURL
|
|
}
|
|
|
|
var timestamp time.Time
|
|
|
|
if lastPlayed.Timestamp == 0 {
|
|
timestamp = time.Now()
|
|
} else {
|
|
timestamp = time.Unix(lastPlayed.Timestamp, 0)
|
|
}
|
|
|
|
response = &ScrobblerResponse{
|
|
FromScrobbler: FromScrobbler{
|
|
Name: s.Name,
|
|
UserURL: fmt.Sprintf("https://listenbrainz.org/user/%s/", encodedUsername),
|
|
},
|
|
Cover: coverURL,
|
|
Artist: artist,
|
|
Track: track,
|
|
Album: album,
|
|
TimestampMs: timestamp.UnixMilli(),
|
|
EstTimestamp: humanize.Time(timestamp),
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
var Listenbrainz = listenbrainz{
|
|
Name: "ListenBrainz",
|
|
}
|