feat: add article page
This commit is contained in:
@ -6,10 +6,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/PuerkitoBio/goquery"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/rramiachraf/dumb/data"
|
||||
"github.com/rramiachraf/dumb/utils"
|
||||
@ -67,7 +64,7 @@ func annotations(l *utils.Logger) http.HandlerFunc {
|
||||
}
|
||||
|
||||
body := data.Response.Referent.Annotations[0].Body
|
||||
body.HTML = cleanBody(body.HTML)
|
||||
body.HTML = utils.CleanBody(body.HTML)
|
||||
|
||||
w.Header().Set("content-type", "application/json")
|
||||
encoder := json.NewEncoder(w)
|
||||
@ -82,31 +79,3 @@ func annotations(l *utils.Logger) http.HandlerFunc {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func cleanBody(body string) string {
|
||||
if doc, err := goquery.NewDocumentFromReader(strings.NewReader(body)); err == nil {
|
||||
doc.Find("iframe").Each(func(i int, s *goquery.Selection) {
|
||||
src, exists := s.Attr("src")
|
||||
if exists {
|
||||
html := fmt.Sprintf(`<a id="iframed-link" href="%s">Link</a>`, src)
|
||||
s.ReplaceWithHtml(html)
|
||||
}
|
||||
})
|
||||
|
||||
doc.Find("img").Each(func(i int, s *goquery.Selection) {
|
||||
src, exists := s.Attr("src")
|
||||
if exists {
|
||||
re := regexp.MustCompile(`(?i)https:\/\/images\.(rapgenius|genius)\.com\/`)
|
||||
pSrc := re.ReplaceAllString(src, "/images/")
|
||||
s.SetAttr("src", pSrc)
|
||||
}
|
||||
})
|
||||
|
||||
if source, err := doc.Html(); err == nil {
|
||||
body = source
|
||||
}
|
||||
}
|
||||
|
||||
re := regexp.MustCompile(`https?:\/\/[a-z]*.?genius.com`)
|
||||
return re.ReplaceAllString(body, "")
|
||||
}
|
||||
|
68
handlers/article.go
Normal file
68
handlers/article.go
Normal file
@ -0,0 +1,68 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/PuerkitoBio/goquery"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/rramiachraf/dumb/data"
|
||||
"github.com/rramiachraf/dumb/utils"
|
||||
"github.com/rramiachraf/dumb/views"
|
||||
)
|
||||
|
||||
func article(l *utils.Logger) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
articleSlug := mux.Vars(r)["article"]
|
||||
|
||||
if a, err := getCache[data.Article](articleSlug); err == nil {
|
||||
views.ArticlePage(a).Render(context.Background(), w)
|
||||
return
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("https://genius.com/a/%s", articleSlug)
|
||||
|
||||
resp, err := utils.SendRequest(url)
|
||||
if err != nil {
|
||||
l.Error(err.Error())
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
views.ErrorPage(500, "cannot reach Genius servers").Render(context.Background(), w)
|
||||
return
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode == http.StatusNotFound {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
views.ErrorPage(404, "page not found").Render(context.Background(), w)
|
||||
return
|
||||
}
|
||||
|
||||
doc, err := goquery.NewDocumentFromReader(resp.Body)
|
||||
if err != nil {
|
||||
l.Error(err.Error())
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
views.ErrorPage(500, "something went wrong").Render(context.Background(), w)
|
||||
return
|
||||
}
|
||||
|
||||
cf := doc.Find(".cloudflare_content").Length()
|
||||
if cf > 0 {
|
||||
l.Error("cloudflare got in the way")
|
||||
views.ErrorPage(500, "cloudflare is detected").Render(context.Background(), w)
|
||||
return
|
||||
}
|
||||
|
||||
var a data.Article
|
||||
if err = a.Parse(doc); err != nil {
|
||||
l.Error(err.Error())
|
||||
}
|
||||
|
||||
views.ArticlePage(a).Render(context.Background(), w)
|
||||
|
||||
if err = setCache(articleSlug, a); err != nil {
|
||||
l.Error(err.Error())
|
||||
}
|
||||
}
|
||||
}
|
55
handlers/article_test.go
Normal file
55
handlers/article_test.go
Normal file
@ -0,0 +1,55 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/PuerkitoBio/goquery"
|
||||
|
||||
"github.com/rramiachraf/dumb/utils"
|
||||
)
|
||||
|
||||
func TestArticle(t *testing.T) {
|
||||
url := "/a/genius-celebrates-hip-hops-50th-anniversary-with-a-look-back-at-the-music-thats-defined-this-site"
|
||||
title := "Genius Celebrates Hip-Hop’s 50th Anniversary With A Look Back At The Music That’s Defined This Site"
|
||||
subtitle := "The first post in a yearlong look at the genre’s storied history."
|
||||
|
||||
r, err := http.NewRequest(http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
l := utils.NewLogger(os.Stdout)
|
||||
m := New(l, &assets{})
|
||||
|
||||
m.ServeHTTP(rr, r)
|
||||
|
||||
defer rr.Result().Body.Close()
|
||||
|
||||
if rr.Result().StatusCode != http.StatusOK {
|
||||
t.Fatalf("expected %d, got %d\n", http.StatusOK, rr.Result().StatusCode)
|
||||
}
|
||||
|
||||
doc, err := goquery.NewDocumentFromReader(rr.Result().Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
articleTitle := doc.Find("#article-title").First().Text()
|
||||
if articleTitle != title {
|
||||
t.Fatalf("expected %q, got %q\n", title, articleTitle)
|
||||
}
|
||||
|
||||
articleSubtitle := doc.Find("#article-subtitle").First().Text()
|
||||
if articleSubtitle != subtitle {
|
||||
t.Fatalf("expected %q, got %q\n", subtitle, articleSubtitle)
|
||||
}
|
||||
|
||||
articleBody := doc.Find("#article-body").First().Text()
|
||||
if len(articleBody) == 0 {
|
||||
t.Fatal("missing article body\n")
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
type cachable interface {
|
||||
data.Album | data.Song | data.Annotation | data.Artist | []byte
|
||||
data.Album | data.Song | data.Annotation | data.Artist | data.Article | []byte
|
||||
}
|
||||
|
||||
var c, _ = bigcache.New(context.Background(), bigcache.DefaultConfig(time.Hour*24))
|
||||
|
@ -29,6 +29,7 @@ func New(logger *utils.Logger, staticFiles static) *mux.Router {
|
||||
{Path: "/robots.txt", Handler: robotsHandler},
|
||||
{Path: "/albums/{artist}/{albumName}", Handler: album},
|
||||
{Path: "/artists/{artist}", Handler: artist},
|
||||
{Path: "/a/{article}", Handler: article},
|
||||
{Path: "/images/{filename}.{ext}", Handler: imageProxy},
|
||||
{Path: "/search", Handler: search},
|
||||
{Path: "/{annotation-id}/{artist-song}/{verse}/annotations", Handler: annotations},
|
||||
|
Reference in New Issue
Block a user