fix: use the open REST API to extact data instead of lyrics page

This commit is contained in:
rramiachraf 2023-03-12 12:37:35 +01:00
parent dd0ee8723b
commit 213f90d779
2 changed files with 64 additions and 29 deletions

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"strings" "strings"
@ -18,6 +19,27 @@ type song struct {
About [2]string About [2]string
} }
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
}
CustomPerformances []customPerformance `json:"custom_performances"`
}
}
}
type customPerformance struct {
Label string
Artists []struct {
Name string
}
}
func (s *song) parseLyrics(doc *goquery.Document) { func (s *song) parseLyrics(doc *goquery.Document) {
doc.Find("[data-lyrics-container='true']").Each(func(i int, ss *goquery.Selection) { doc.Find("[data-lyrics-container='true']").Each(func(i int, ss *goquery.Selection) {
h, err := ss.Html() h, err := ss.Html()
@ -28,44 +50,57 @@ func (s *song) parseLyrics(doc *goquery.Document) {
}) })
} }
func (s *song) parseMetadata(doc *goquery.Document) { func (s *song) parseSongData(doc *goquery.Document) {
artist := doc.Find("a[class*='Artist']").First().Text() attr, exists := doc.Find("meta[property='twitter:app:url:iphone']").Attr("content")
title := doc.Find("h1[class*='Title']").First().Text()
image, exists := doc.Find("meta[property='og:image']").Attr("content")
if exists { if exists {
s.Image = extractURL(image) songID := strings.Replace(attr, "genius://songs/", "", 1)
u := fmt.Sprintf("https://genius.com/api/songs/%s?text_format=plain", songID)
res, err := http.Get(u)
if err != nil {
logger.Errorln(err)
} }
s.Title = title defer res.Body.Close()
s.Artist = artist
}
func (s *song) parseCredits(doc *goquery.Document) { var data songResponse
credits := make(map[string]string) decoder := json.NewDecoder(res.Body)
err = decoder.Decode(&data)
doc.Find("[class*='SongInfo__Credit']").Each(func(i int, ss *goquery.Selection) { if err != nil {
key := ss.Children().First().Text() logger.Errorln(err)
value := ss.Children().Last().Text()
credits[key] = value
})
s.Credits = credits
}
func (s *song) parseAbout(doc *goquery.Document) {
s.About[0] = doc.Find("[class*='SongDescription__Content']").Text()
summary := strings.Split(s.About[0], "")
if len(summary) > 250 {
s.About[1] = strings.Join(summary[0:250], "") + "..."
} }
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)
for _, perf := range songData.CustomPerformances {
var artists []string
for _, artist := range perf.Artists {
artists = append(artists, artist.Name)
}
s.Credits[perf.Label] = strings.Join(artists, ", ")
}
}
}
func truncateText(text string) string {
textArr := strings.Split(text, "")
if len(textArr) > 250 {
return strings.Join(textArr[0:250], "") + "..."
}
return text
} }
func (s *song) parse(doc *goquery.Document) { func (s *song) parse(doc *goquery.Document) {
s.parseLyrics(doc) s.parseLyrics(doc)
s.parseMetadata(doc) s.parseSongData(doc)
s.parseCredits(doc)
s.parseAbout(doc)
} }
func lyricsHandler(w http.ResponseWriter, r *http.Request) { func lyricsHandler(w http.ResponseWriter, r *http.Request) {

View File

@ -11,7 +11,7 @@
{{template "navbar"}} {{template "navbar"}}
<div id="container"> <div id="container">
<div id="metadata"> <div id="metadata">
<img src="{{.Image}}"/> <img src="{{extractURL .Image}}"/>
<h2>{{.Artist}}</h2> <h2>{{.Artist}}</h2>
<h1>{{.Title}}</h1> <h1>{{.Title}}</h1>
</div> </div>