feat(comics): add xkcd comics
All checks were successful
functions / build (push) Successful in 1m36s
All checks were successful
functions / build (push) Successful in 1m36s
This commit is contained in:
parent
cfdad534f0
commit
96cf231814
2 changed files with 66 additions and 17 deletions
|
@ -6,6 +6,7 @@ import (
|
|||
"log/slog"
|
||||
"math/rand/v2"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/PuerkitoBio/goquery"
|
||||
spinhttp "github.com/fermyon/spin/sdk/go/v2/http"
|
||||
|
@ -22,8 +23,9 @@ type MonkeyUserEntry struct {
|
|||
}
|
||||
|
||||
type Comic struct {
|
||||
Title string `json:"title"`
|
||||
URL string `json:"url"`
|
||||
Source string `json:"source"`
|
||||
Title string `json:"title"`
|
||||
URL string `json:"url"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
@ -31,12 +33,69 @@ func init() {
|
|||
|
||||
router.GET("/comics/random", randomComic)
|
||||
router.GET("/comics/monkeyuser", monkeyUserComic)
|
||||
router.GET("/comics/xkcd", xkcdComic)
|
||||
|
||||
spinhttp.Handle(router.ServeHTTP)
|
||||
}
|
||||
|
||||
func randomComic(w http.ResponseWriter, re *http.Request, params httprouter.Params) {
|
||||
monkeyUserComic(w, re, params)
|
||||
possibleHandlers := []httprouter.Handle{
|
||||
xkcdComic,
|
||||
monkeyUserComic,
|
||||
}
|
||||
|
||||
possibleHandlers[rand.IntN(len(possibleHandlers))](w, re, params)
|
||||
}
|
||||
|
||||
func xkcdComic(w http.ResponseWriter, re *http.Request, _ httprouter.Params) {
|
||||
pageResponse, err := spinhttp.Get("https://c.xkcd.com/random/comic/")
|
||||
if err != nil {
|
||||
slog.Error("failed to fetch xkcd comic page", slog.String("err", err.Error()))
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
slog.Info("Fetched xkcd comic page", slog.Int("status", pageResponse.StatusCode))
|
||||
|
||||
defer pageResponse.Body.Close()
|
||||
if pageResponse.StatusCode != http.StatusOK {
|
||||
http.Error(w, pageResponse.Status, pageResponse.StatusCode)
|
||||
return
|
||||
}
|
||||
|
||||
comicDoc, err := goquery.NewDocumentFromReader(pageResponse.Body)
|
||||
if err != nil {
|
||||
slog.Error("failed to parse comic page", slog.String("err", err.Error()))
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
slog.Info("Extracting comic info")
|
||||
|
||||
ref := Comic{
|
||||
Source: "xkcd",
|
||||
Title: comicDoc.Find("#ctitle").Text(),
|
||||
URL: comicDoc.Find("#comic > img").AttrOr("src", ""),
|
||||
}
|
||||
|
||||
parsed, err := url.Parse(ref.URL)
|
||||
if err != nil {
|
||||
slog.Error("failed to parse comic URL", slog.String("err", err.Error()))
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
if parsed.Scheme == "" {
|
||||
parsed.Scheme = "https"
|
||||
ref.URL = parsed.String()
|
||||
}
|
||||
|
||||
w.Header().Add(contentTypeHeader, "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
if err := json.NewEncoder(w).Encode(ref); err != nil {
|
||||
slog.Error("failed to encode image ref", slog.String("err", err.Error()))
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
func monkeyUserComic(w http.ResponseWriter, re *http.Request, _ httprouter.Params) {
|
||||
|
@ -86,21 +145,11 @@ func monkeyUserComic(w http.ResponseWriter, re *http.Request, _ httprouter.Param
|
|||
}
|
||||
|
||||
ref := Comic{
|
||||
Title: entry.Title,
|
||||
Source: "monkeyuser",
|
||||
Title: entry.Title,
|
||||
URL: fmt.Sprintf("https://www.monkeyuser.com%s", comicDoc.Find("div.content > p > img").AttrOr("src", "")),
|
||||
}
|
||||
|
||||
comicDoc.Find("div.content > p > img").Each(func(_ int, s *goquery.Selection) {
|
||||
for _, node := range s.Nodes {
|
||||
for _, attr := range node.Attr {
|
||||
if attr.Key == "src" {
|
||||
ref.URL = fmt.Sprintf("https://www.monkeyuser.com%s", attr.Val)
|
||||
break
|
||||
}
|
||||
}
|
||||
slog.Info("found URL", slog.String("url", ref.URL))
|
||||
}
|
||||
})
|
||||
|
||||
w.Header().Add(contentTypeHeader, "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
if err := json.NewEncoder(w).Encode(ref); err != nil {
|
||||
|
|
|
@ -12,7 +12,7 @@ component = "comics"
|
|||
|
||||
[component.comics]
|
||||
source = "main.wasm"
|
||||
allowed_outbound_hosts = [ "https://www.monkeyuser.com" ]
|
||||
allowed_outbound_hosts = [ "https://www.monkeyuser.com", "https://c.xkcd.com" ]
|
||||
[component.comics.build]
|
||||
command = "tinygo build -target=wasip1 -gc=leaking -no-debug -scheduler=none -buildmode=c-shared -o main.wasm main.go"
|
||||
watch = ["**/*.go", "go.mod"]
|
||||
|
|
Loading…
Add table
Reference in a new issue