From 71e3b6e02919e4205688b7bbe89b4649d7cee2e8 Mon Sep 17 00:00:00 2001 From: qvalentin Date: Sat, 9 Sep 2023 15:19:11 +0200 Subject: [PATCH 1/5] Add api for annotations this only returns the first available annotation for now annotation content is returned in html format, so it can easily be inserted in the frontend displaying the annotation in the frontend is still a TODO --- annotations.go | 104 +++++++++++++++++++++++++++++++++++++++++++++++ main.go | 1 + static/script.js | 15 ++++++- 3 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 annotations.go diff --git a/annotations.go b/annotations.go new file mode 100644 index 0000000..374d473 --- /dev/null +++ b/annotations.go @@ -0,0 +1,104 @@ +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" + "regexp" + "strings" + + "github.com/gorilla/mux" +) + +type annotationsResponse struct { + Response struct { + Referent struct { + Annotations []struct { + Body struct { + Html string `json:"html"` + } `json:"body"` + } `json:"annotations"` + } `json:"referent"` + } `json:"response"` +} + +func annotationsHandler(w http.ResponseWriter, r *http.Request) { + id := mux.Vars(r)["id"] + url := fmt.Sprintf("https://genius.com/api/referents/%s?text_format=html", id) + 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 + } + + buf := new(bytes.Buffer) + _, err = buf.ReadFrom(resp.Body) + if err != nil { + logger.Errorln("Error paring genius api response", err) + w.WriteHeader(http.StatusInternalServerError) + render("error", w, map[string]string{ + "Status": "500", + "Error": "Parsing error", + }) + return + } + + var data annotationsResponse + err = json.Unmarshal(buf.Bytes(), &data) + if err != nil { + logger.Errorf("could not unmarshal json: %s\n", err) + w.WriteHeader(http.StatusInternalServerError) + render("error", w, map[string]string{ + "Status": "500", + "Error": "Could not parse genius api response", + }) + return + } + + w.Header().Set("content-type", "application/json") + body := data.Response.Referent.Annotations[0].Body + body.Html = cleanBody(body.Html) + response, err := json.Marshal(body) + + if err != nil { + logger.Errorf("could not marshal json: %s\n", err) + w.WriteHeader(http.StatusInternalServerError) + render("error", w, map[string]string{ + "Status": "500", + "Error": "Could not parse genius api response", + }) + return + } + + _, err = w.Write(response) + if err != nil { + logger.Errorln("Error sending response: ", err) + } +} + +func cleanBody(body string) string { + var withCleanedImageLinks = strings.Replace(body, "https://images.rapgenius.com/", "/images/", -1) + + var re = regexp.MustCompile(`https?:\/\/[a-z]*.?genius.com`) + var withCleanedLinks = re.ReplaceAllString(withCleanedImageLinks, "") + + return withCleanedLinks +} diff --git a/main.go b/main.go index 0161943..d819a0a 100644 --- a/main.go +++ b/main.go @@ -29,6 +29,7 @@ func main() { r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { render("home", w, nil) }) r.HandleFunc("/search", searchHandler).Methods("GET") r.HandleFunc("/{id}-lyrics", lyricsHandler) + r.HandleFunc("/{id}/{artist-song}/{verse}/annotations", annotationsHandler) r.HandleFunc("/images/{filename}.{ext}", proxyHandler) r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("static")))) r.NotFoundHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { diff --git a/static/script.js b/static/script.js index 1a45d35..fec2af0 100644 --- a/static/script.js +++ b/static/script.js @@ -14,6 +14,17 @@ document.querySelectorAll("#lyrics a").forEach(item => { function getAnnotation(e) { e.preventDefault() - //const uri = e.target.parentElement.getAttribute("href") - console.log("Annotations are not yet implemented!") + const uri = e.target.parentElement.getAttribute("href") + console.log("Annotations are not yet implemented!", uri) + + xhr = new XMLHttpRequest() + xhr.open("GET", uri + "/annotations") + xhr.send() + xhr.onreadystatechange = function() { + if (this.readyState == 4 && this.status == 200) { + json = JSON.parse(this.responseText) + alert(json.html) + // TODO: display annotations properly + } + } } From acb2695db0bfc8cf0c7d9d72c40569b502a7c778 Mon Sep 17 00:00:00 2001 From: qvalentin Date: Sat, 9 Sep 2023 15:42:53 +0200 Subject: [PATCH 2/5] Enable css for annotations --- static/style.css | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/static/style.css b/static/style.css index 2696a9e..0855014 100644 --- a/static/style.css +++ b/static/style.css @@ -56,7 +56,6 @@ body { cursor: initial; } -/*** NOT YET IMPLEMENTED #lyrics a { background-color: #ddd; color: inherit; @@ -65,7 +64,6 @@ body { #lyrics a:hover { background-color: #ccc; } -***/ nav { background-color: #ffcd38; @@ -327,6 +325,15 @@ footer a:hover { color: #ccc; } + #lyrics a { + background-color: #272d44; + color: inherit; + } + + #lyrics a:hover { + background-color: #32384f; + } + #metadata h1 { color: #ddd; } From e40ca5dca9b577ba08869ba50305452fd84e8e5e Mon Sep 17 00:00:00 2001 From: qvalentin Date: Sat, 9 Sep 2023 18:11:00 +0200 Subject: [PATCH 3/5] Show annotations in the frontend --- static/script.js | 6 ++---- static/style.css | 12 +++++++++++- views/lyrics.tmpl | 2 ++ 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/static/script.js b/static/script.js index fec2af0..32e6827 100644 --- a/static/script.js +++ b/static/script.js @@ -15,16 +15,14 @@ document.querySelectorAll("#lyrics a").forEach(item => { function getAnnotation(e) { e.preventDefault() const uri = e.target.parentElement.getAttribute("href") - console.log("Annotations are not yet implemented!", uri) xhr = new XMLHttpRequest() xhr.open("GET", uri + "/annotations") xhr.send() xhr.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { - json = JSON.parse(this.responseText) - alert(json.html) - // TODO: display annotations properly + const parsedReponse = JSON.parse(this.responseText) + document.getElementById("annotations").innerHTML = parsedReponse.html } } } diff --git a/static/style.css b/static/style.css index 0855014..8b27ae7 100644 --- a/static/style.css +++ b/static/style.css @@ -147,13 +147,17 @@ a { gap: 0.5rem; } -#about p { +#about p, #annotations p, #annotations h2 { font-size: 1.4rem; color: #171717; line-height: 1.8rem; cursor: pointer; } +#annotations blockquote { + background-color: #272d44; +} + .hidden { display: none; } @@ -348,10 +352,16 @@ footer a:hover { } #about p, + #annotations p, + #annotations h2, #credits summary { color: #ccc; } + #annotations blockquote { + background-color: #272d44; + } + #home h1, #error h1 { color: #eee; } diff --git a/views/lyrics.tmpl b/views/lyrics.tmpl index d665d73..a829131 100644 --- a/views/lyrics.tmpl +++ b/views/lyrics.tmpl @@ -17,6 +17,8 @@
{{.Lyrics}}
+
+

About

From 5158221f35c14dd8dc2c33ee8ab270478d64b200 Mon Sep 17 00:00:00 2001 From: qvalentin Date: Wed, 13 Sep 2023 18:32:35 +0200 Subject: [PATCH 4/5] Show annotations in between lyrics --- annotations.go | 23 +++++++++++++++++++++++ static/script.js | 11 ++++++++++- static/style.css | 25 ++++++++++++++----------- views/lyrics.tmpl | 2 -- 4 files changed, 47 insertions(+), 14 deletions(-) diff --git a/annotations.go b/annotations.go index 374d473..f77d35c 100644 --- a/annotations.go +++ b/annotations.go @@ -25,6 +25,28 @@ type annotationsResponse struct { func annotationsHandler(w http.ResponseWriter, r *http.Request) { id := mux.Vars(r)["id"] + + if data, err := getCache(id); err == nil { + + response, err := json.Marshal(data) + + if err != nil { + logger.Errorf("could not marshal json: %s\n", err) + w.WriteHeader(http.StatusInternalServerError) + render("error", w, map[string]string{ + "Status": "500", + "Error": "Could not parse genius api response", + }) + return + } + w.Header().Set("content-type", "application/json") + _, err = w.Write(response) + if err != nil { + logger.Errorln("Error sending response: ", err) + } + return + } + url := fmt.Sprintf("https://genius.com/api/referents/%s?text_format=html", id) resp, err := sendRequest(url) @@ -88,6 +110,7 @@ func annotationsHandler(w http.ResponseWriter, r *http.Request) { return } + setCache(id, body) _, err = w.Write(response) if err != nil { logger.Errorln("Error sending response: ", err) diff --git a/static/script.js b/static/script.js index 32e6827..327ae5a 100644 --- a/static/script.js +++ b/static/script.js @@ -15,6 +15,11 @@ document.querySelectorAll("#lyrics a").forEach(item => { function getAnnotation(e) { e.preventDefault() const uri = e.target.parentElement.getAttribute("href") + const presentAnnotation = document.getElementById(uri) + if (presentAnnotation) { + presentAnnotation.remove() + return + } xhr = new XMLHttpRequest() xhr.open("GET", uri + "/annotations") @@ -22,7 +27,11 @@ function getAnnotation(e) { xhr.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { const parsedReponse = JSON.parse(this.responseText) - document.getElementById("annotations").innerHTML = parsedReponse.html + const annotationDiv = document.createElement('div'); + annotationDiv.innerHTML = parsedReponse.html + annotationDiv.id = uri + annotationDiv.className = "annotation" + e.target.parentElement.insertAdjacentElement('afterend', annotationDiv) } } } diff --git a/static/style.css b/static/style.css index 8b27ae7..c142d64 100644 --- a/static/style.css +++ b/static/style.css @@ -56,7 +56,7 @@ body { cursor: initial; } -#lyrics a { +#lyrics a, .annotation { background-color: #ddd; color: inherit; } @@ -147,15 +147,23 @@ a { gap: 0.5rem; } -#about p, #annotations p, #annotations h2 { +#about p { font-size: 1.4rem; color: #171717; line-height: 1.8rem; cursor: pointer; } -#annotations blockquote { - background-color: #272d44; +.annotation { + padding: 1rem; +} + +.annotation img { + max-width: 100%; +} + +.annotation ul { + padding-left: 1em; } .hidden { @@ -329,11 +337,12 @@ footer a:hover { color: #ccc; } - #lyrics a { + #lyrics a, .annotation { background-color: #272d44; color: inherit; } + #lyrics a:hover { background-color: #32384f; } @@ -352,16 +361,10 @@ footer a:hover { } #about p, - #annotations p, - #annotations h2, #credits summary { color: #ccc; } - #annotations blockquote { - background-color: #272d44; - } - #home h1, #error h1 { color: #eee; } diff --git a/views/lyrics.tmpl b/views/lyrics.tmpl index a829131..d665d73 100644 --- a/views/lyrics.tmpl +++ b/views/lyrics.tmpl @@ -17,8 +17,6 @@
{{.Lyrics}}
-
-

About

From bd0273491b3bfee94c588c8f452681649a7bcc5b Mon Sep 17 00:00:00 2001 From: qvalentin Date: Sat, 9 Dec 2023 16:26:33 +0100 Subject: [PATCH 5/5] Fix height of images in annotations --- static/style.css | 1 + 1 file changed, 1 insertion(+) diff --git a/static/style.css b/static/style.css index c142d64..37ef7f4 100644 --- a/static/style.css +++ b/static/style.css @@ -160,6 +160,7 @@ a { .annotation img { max-width: 100%; + height: auto; } .annotation ul {