feat: replace text/template with templ and refactor code

This commit is contained in:
rramiachraf
2024-03-04 14:59:47 +01:00
parent 5390a2878d
commit e2d5ef044b
43 changed files with 836 additions and 851 deletions

74
data/album.go Normal file
View File

@ -0,0 +1,74 @@
package data
import (
"encoding/json"
"strings"
"github.com/PuerkitoBio/goquery"
)
type Album struct {
Artist string
Name string
Image string
About [2]string
Tracks []Track
}
type Track struct {
Title string
Url string
}
type albumMetadata struct {
Album struct {
Id int `json:"id"`
Image string `json:"cover_art_thumbnail_url"`
Name string `json:"name"`
Description string `json:"description_preview"`
Artist `json:"artist"`
}
AlbumAppearances []AlbumAppearances `json:"album_appearances"`
}
type AlbumAppearances struct {
Id int `json:"id"`
TrackNumber int `json:"track_number"`
Song struct {
Title string `json:"title"`
Url string `json:"url"`
}
}
type Artist struct {
Name string `json:"name"`
}
func (a *Album) parseAlbumData(doc *goquery.Document) {
pageMetadata, exists := doc.Find("meta[itemprop='page_data']").Attr("content")
if !exists {
return
}
var albumMetadataFromPage albumMetadata
json.Unmarshal([]byte(pageMetadata), &albumMetadataFromPage)
albumData := albumMetadataFromPage.Album
a.Artist = albumData.Artist.Name
a.Name = albumData.Name
a.Image = albumData.Image
a.About[0] = albumData.Description
//a.About[1] = truncateText(albumData.Description)
a.About[1] = ""
for _, track := range albumMetadataFromPage.AlbumAppearances {
url := strings.Replace(track.Song.Url, "https://genius.com", "", -1)
a.Tracks = append(a.Tracks, Track{Title: track.Song.Title, Url: url})
}
}
func (a *Album) Parse(doc *goquery.Document) {
a.parseAlbumData(doc)
}

15
data/annotation.go Normal file
View File

@ -0,0 +1,15 @@
package data
type AnnotationsResponse struct {
Response struct {
Referent struct {
Annotations []Annotation `json:"annotations"`
} `json:"referent"`
} `json:"response"`
}
type Annotation struct {
Body struct {
Html string `json:"html"`
} `json:"body"`
}

112
data/lyrics.go Normal file
View File

@ -0,0 +1,112 @@
package data
import (
"encoding/json"
"fmt"
"strings"
"github.com/PuerkitoBio/goquery"
"github.com/sirupsen/logrus"
)
type Song struct {
Artist string
Title string
Image string
Lyrics string
Credits map[string]string
About [2]string
Album string
LinkToAlbum 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
}
Album struct {
Url string `json:"url"`
Name string `json:"name"`
}
CustomPerformances []customPerformance `json:"custom_performances"`
}
}
}
type customPerformance struct {
Label string
Artists []struct {
Name string
}
}
func (s *Song) parseLyrics(doc *goquery.Document) {
doc.Find("[data-lyrics-container='true']").Each(func(i int, ss *goquery.Selection) {
h, err := ss.Html()
if err != nil {
logrus.Errorln("unable to parse lyrics", err)
}
s.Lyrics += h
})
}
func (s *Song) parseSongData(doc *goquery.Document) {
attr, exists := doc.Find("meta[property='twitter:app:url:iphone']").Attr("content")
if exists {
songID := strings.Replace(attr, "genius://songs/", "", 1)
u := fmt.Sprintf("https://genius.com/api/songs/%s?text_format=plain", songID)
res, err := sendRequest(u)
if err != nil {
logrus.Errorln(err)
}
defer res.Body.Close()
var data songResponse
decoder := json.NewDecoder(res.Body)
err = decoder.Decode(&data)
if err != nil {
logrus.Errorln(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)
s.Album = songData.Album.Name
s.LinkToAlbum = strings.Replace(songData.Album.Url, "https://genius.com", "", -1)
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) {
s.parseLyrics(doc)
s.parseSongData(doc)
}

16
data/proxy.go Normal file
View File

@ -0,0 +1,16 @@
package data
import (
"fmt"
"net/url"
)
func ExtractImageURL(image string) string {
u, err := url.Parse(image)
if err != nil {
return ""
}
return fmt.Sprintf("/images%s", u.Path)
}

28
data/search.go Normal file
View File

@ -0,0 +1,28 @@
package data
type SearchResponse struct {
Response struct {
Sections sections
}
}
type result struct {
ArtistNames string `json:"artist_names"`
Title string
Path string
Thumbnail string `json:"song_art_image_thumbnail_url"`
}
type hits []struct {
Result result
}
type sections []struct {
Type string
Hits hits
}
type SearchResults struct {
Query string
Sections sections
}

46
data/utils.go Normal file
View File

@ -0,0 +1,46 @@
package data
import (
"net"
"net/http"
"net/url"
"time"
"github.com/caffix/cloudflare-roundtripper/cfrt"
)
const UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36"
var client = &http.Client{
Timeout: 20 * time.Second,
Transport: &http.Transport{
DialContext: (&net.Dialer{
Timeout: 15 * time.Second,
KeepAlive: 15 * time.Second,
DualStack: true,
}).DialContext,
},
}
func sendRequest(u string) (*http.Response, error) {
url, err := url.Parse(u)
if err != nil {
return nil, err
}
client.Transport, err = cfrt.New(client.Transport)
if err != nil {
return nil, err
}
req := &http.Request{
Method: http.MethodGet,
URL: url,
Header: map[string][]string{
"Accept-Language": {"en-US"},
"User-Agent": {UA},
},
}
return client.Do(req)
}