273176a57c
Serves a page including the album name, artist, track list, and credits. Each of the tracks have links to the lyrics page, provided there is one available.
140 lines
2.9 KiB
Go
140 lines
2.9 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/PuerkitoBio/goquery"
|
|
"github.com/gorilla/mux"
|
|
)
|
|
|
|
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)
|
|
|
|
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)
|
|
}
|
|
|
|
func albumHandler(w http.ResponseWriter, r *http.Request) {
|
|
artist := mux.Vars(r)["artist"]
|
|
albumName := mux.Vars(r)["albumName"]
|
|
|
|
id := fmt.Sprintf("%s/%s", artist, albumName)
|
|
|
|
if data, err := getCache(id); err == nil {
|
|
render("album", w, data)
|
|
return
|
|
}
|
|
|
|
url := fmt.Sprintf("https://genius.com/albums/%s/%s", artist, albumName)
|
|
|
|
resp, err := sendRequest(url)
|
|
if err != nil {
|
|
logger.Errorln(err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
render("error", w, map[string]string{
|
|
"Status": "500",
|
|
"Error": "cannot reach genius servers",
|
|
})
|
|
return
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode == http.StatusNotFound {
|
|
w.WriteHeader(http.StatusNotFound)
|
|
render("error", w, map[string]string{
|
|
"Status": "404",
|
|
"Error": "page not found",
|
|
})
|
|
return
|
|
}
|
|
|
|
doc, err := goquery.NewDocumentFromReader(resp.Body)
|
|
if err != nil {
|
|
logger.Errorln(err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
render("error", w, map[string]string{
|
|
"Status": "500",
|
|
"Error": "something went wrong",
|
|
})
|
|
return
|
|
}
|
|
|
|
cf := doc.Find(".cloudflare_content").Length()
|
|
if cf > 0 {
|
|
logger.Errorln("cloudflare got in the way")
|
|
render("error", w, map[string]string{
|
|
"Status": "500",
|
|
"Error": "damn cloudflare, issue #21 on GitHub",
|
|
})
|
|
return
|
|
}
|
|
|
|
var a album
|
|
a.parse(doc)
|
|
|
|
render("album", w, a)
|
|
|
|
setCache(id, a)
|
|
}
|