dumb/data/lyrics.go

146 lines
3.0 KiB
Go
Raw Normal View History

package data
2022-06-30 21:32:56 +01:00
import (
"encoding/json"
2022-06-30 21:32:56 +01:00
"fmt"
"strings"
2022-06-30 21:32:56 +01:00
"github.com/PuerkitoBio/goquery"
"github.com/rramiachraf/dumb/utils"
2022-06-30 21:32:56 +01:00
)
type Song struct {
2024-03-04 17:41:01 +01:00
Artist string
Title string
Image string
Lyrics string
Credits map[string]string
About [2]string
2024-06-08 15:16:13 +02:00
Album AlbumPreview
2022-06-30 21:32:56 +01:00
}
type songResponse struct {
Response struct {
Song struct {
ArtistNames string `json:"artist_names"`
Image string `json:"song_art_image_thumbnail_url"`
Title string
Description struct {
Plain string
}
Album struct {
2024-03-04 17:41:01 +01:00
URL string `json:"url"`
Name string `json:"name"`
Image string `json:"cover_art_url"`
}
CustomPerformances []customPerformance `json:"custom_performances"`
2024-06-08 15:16:13 +02:00
WriterArtists []struct {
Name string
} `json:"writer_artists"`
2024-06-08 15:16:13 +02:00
ProducerArtists []struct {
Name string
} `json:"producer_artists"`
}
}
}
type customPerformance struct {
Label string
Artists []struct {
Name string
}
}
2024-05-02 21:29:50 +01:00
func (s *Song) parseLyrics(doc *goquery.Document) error {
var htmlError error
2022-06-30 21:32:56 +01:00
doc.Find("[data-lyrics-container='true']").Each(func(i int, ss *goquery.Selection) {
h, err := ss.Html()
if err != nil {
2024-05-02 21:29:50 +01:00
htmlError = err
2022-06-30 21:32:56 +01:00
}
s.Lyrics += h
2022-06-30 21:32:56 +01:00
})
2024-05-02 21:29:50 +01:00
if htmlError != nil {
return htmlError
}
return nil
2022-06-30 21:32:56 +01:00
}
2024-05-02 21:29:50 +01:00
func (s *Song) parseSongData(doc *goquery.Document) error {
attr, exists := doc.Find("meta[property='twitter:app:url:iphone']").Attr("content")
2022-06-30 21:32:56 +01:00
if exists {
songID := strings.Replace(attr, "genius://songs/", "", 1)
u := fmt.Sprintf("https://genius.com/api/songs/%s?text_format=plain", songID)
2022-06-30 21:32:56 +01:00
res, err := utils.SendRequest(u)
if err != nil {
2024-05-02 21:29:50 +01:00
return err
}
2022-06-30 21:32:56 +01:00
defer res.Body.Close()
var data songResponse
decoder := json.NewDecoder(res.Body)
err = decoder.Decode(&data)
if err != nil {
2024-05-02 21:29:50 +01:00
return err
}
songData := data.Response.Song
s.Artist = songData.ArtistNames
s.Image = songData.Image
s.Title = songData.Title
s.About[0] = songData.Description.Plain
s.About[1] = truncateText(songData.Description.Plain)
s.Credits = make(map[string]string)
2024-03-04 17:41:01 +01:00
s.Album.Name = songData.Album.Name
s.Album.URL = strings.Replace(songData.Album.URL, "https://genius.com", "", -1)
s.Album.Image = ExtractImageURL(songData.Album.Image)
s.Credits["Writers"] = joinNames(songData.WriterArtists)
s.Credits["Producers"] = joinNames(songData.ProducerArtists)
for _, perf := range songData.CustomPerformances {
s.Credits[perf.Label] = joinNames(perf.Artists)
}
}
2024-05-02 21:29:50 +01:00
return nil
}
func joinNames(data []struct {
Name string
2024-06-08 15:16:13 +02:00
},
) string {
var names []string
for _, hasName := range data {
names = append(names, hasName.Name)
}
return strings.Join(names, ", ")
}
func truncateText(text string) string {
textArr := strings.Split(text, "")
if len(textArr) > 250 {
return strings.Join(textArr[0:250], "") + "..."
}
return text
}
2024-05-02 21:29:50 +01:00
func (s *Song) Parse(doc *goquery.Document) error {
if err := s.parseLyrics(doc); err != nil {
return err
}
if err := s.parseSongData(doc); err != nil {
return err
}
return nil
2022-06-30 21:32:56 +01:00
}