From 42e06256955bb244da7e26614a9f209f795bf8a3 Mon Sep 17 00:00:00 2001 From: Solomon Victorino Date: Sat, 6 Apr 2024 00:14:51 -0600 Subject: [PATCH] feat: support direct annotation links --- handlers/annotations.go | 2 +- handlers/handler.go | 6 ++++-- handlers/lyrics.go | 10 ++++++++-- handlers/lyrics_test.go | 13 ++++++++++++- static/script.js | 13 +++++++++++-- 5 files changed, 36 insertions(+), 8 deletions(-) diff --git a/handlers/annotations.go b/handlers/annotations.go index 8033506..43d251a 100644 --- a/handlers/annotations.go +++ b/handlers/annotations.go @@ -18,7 +18,7 @@ import ( func annotations(l *logrus.Logger) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - id := mux.Vars(r)["id"] + id := mux.Vars(r)["annotation-id"] if a, err := getCache[data.Annotation]("annotation:" + id); err == nil { encoder := json.NewEncoder(w) diff --git a/handlers/handler.go b/handlers/handler.go index c81d929..137a53c 100644 --- a/handlers/handler.go +++ b/handlers/handler.go @@ -16,13 +16,15 @@ func New(logger *logrus.Logger) *mux.Router { r.Use(mustHeaders) r.Handle("/", templ.Handler(views.HomePage())) - r.HandleFunc("/{id}-lyrics", lyrics(logger)).Methods("GET") r.HandleFunc("/albums/{artist}/{albumName}", album(logger)).Methods("GET") r.HandleFunc("/images/{filename}.{ext}", imageProxy(logger)).Methods("GET") r.HandleFunc("/search", search(logger)).Methods("GET") - r.HandleFunc("/{id}/{artist-song}/{verse}/annotations", annotations(logger)).Methods("GET") + r.HandleFunc("/{annotation-id}/{artist-song}/{verse}/annotations", annotations(logger)).Methods("GET") r.HandleFunc("/instances.json", instances(logger)).Methods("GET") r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("static")))) + r.PathPrefix("/{annotation-id}/{artist-song}-lyrics").HandlerFunc(lyrics(logger)).Methods("GET") + r.PathPrefix("/{annotation-id}/{artist-song}").HandlerFunc(lyrics(logger)).Methods("GET") + r.PathPrefix("/{annotation-id}").HandlerFunc(lyrics(logger)).Methods("GET") r.NotFoundHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNotFound) views.ErrorPage(404, "page not found").Render(context.Background(), w) diff --git a/handlers/lyrics.go b/handlers/lyrics.go index 966e1fb..bb0c138 100644 --- a/handlers/lyrics.go +++ b/handlers/lyrics.go @@ -14,14 +14,20 @@ import ( func lyrics(l *logrus.Logger) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - id := mux.Vars(r)["id"] + // prefer artist-song over annotation-id for cache key when available + id := mux.Vars(r)["artist-song"] + if id == "" { + id = mux.Vars(r)["annotation-id"] + } else { + id = id + "-lyrics" + } if s, err := getCache[data.Song](id); err == nil { views.LyricsPage(s).Render(context.Background(), w) return } - url := fmt.Sprintf("https://genius.com/%s-lyrics", id) + url := fmt.Sprintf("https://genius.com/%s", id) resp, err := sendRequest(url) if err != nil { l.Errorln(err) diff --git a/handlers/lyrics_test.go b/handlers/lyrics_test.go index 7c2445a..006386f 100644 --- a/handlers/lyrics_test.go +++ b/handlers/lyrics_test.go @@ -10,7 +10,18 @@ import ( ) func TestLyrics(t *testing.T) { - url := "/The-silver-seas-catch-yer-own-train-lyrics" + urls := []string{"/The-silver-seas-catch-yer-own-train-lyrics", + "/1784308/The-silver-seas-catch-yer-own-train", + "/1784308/The-silver-seas-catch-yer-own-train-lyrics", + "/1784308/The-silver-seas-catch-yer-own-train/Baby-you-and-i-are-not-the-same-you-say-you-like-sun-i-like-the-rain", + "/1784308/The-silver-seas-catch-yer-own-train-lyrics/Baby-you-and-i-are-not-the-same-you-say-you-like-sun-i-like-the-rain", + "/1784308"} + for _, url := range urls { + t.Run(url, func(t *testing.T) { testLyrics(t, url) }) + } +} + +func testLyrics(t *testing.T, url string) { title := "The Silver Seas" artist := "Catch Yer Own Train" diff --git a/static/script.js b/static/script.js index 65bffdd..c8e955a 100644 --- a/static/script.js +++ b/static/script.js @@ -8,8 +8,17 @@ function showAbout() { fullAbout && [fullAbout, summary].forEach(item => item.onclick = showAbout) -document.querySelectorAll("#lyrics a").forEach(item => { - item.addEventListener("click", getAnnotation) +window.addEventListener("load", () => { + document.querySelectorAll("#lyrics a").forEach(item => { + item.addEventListener("click", getAnnotation) + }) + + const linkedAnnotationId = window.location.pathname.match(new RegExp("/(\\d+)"))?.[1] + if (linkedAnnotationId) { + const target = document.querySelector(`a[href^="/${linkedAnnotationId}"][class^="ReferentFragmentdesktop__ClickTarget"] > span`) + target?.click() + target?.scrollIntoView() + } }) function getAnnotation(e) {