Compare commits

2 Commits

Author SHA1 Message Date
5f8a9b7b14 chore(db): use context & add db helper 2025-08-10 13:15:46 -04:00
13df4ae706 feat(utils): add pkg utils 2025-08-10 13:10:14 -04:00
4 changed files with 45 additions and 16 deletions

View File

@@ -3,7 +3,7 @@ FROM alpine AS alpine
RUN apk update && apk add --no-cache ca-certificates tzdata RUN apk update && apk add --no-cache ca-certificates tzdata
# Build Image # Build Image
FROM golang:1.24 AS build FROM golang:1.21 AS build
# Create Package Directory # Create Package Directory
RUN mkdir -p /opt/antholume RUN mkdir -p /opt/antholume

View File

@@ -53,12 +53,10 @@ func countEPUBWords(filepath string) (int64, error) {
rf := rc.Rootfiles[0] rf := rc.Rootfiles[0]
var completeCount int64 var completeCount int64
for _, item := range rf.Itemrefs { for _, item := range rf.Spine.Itemrefs {
f, _ := item.Open() f, _ := item.Open()
doc, _ := goquery.NewDocumentFromReader(f) doc, _ := goquery.NewDocumentFromReader(f)
doc.Find("script, style, noscript, iframe").Remove() completeCount = completeCount + int64(len(strings.Fields(doc.Text())))
words := len(strings.Fields(doc.Text()))
completeCount = completeCount + int64(words)
} }
return completeCount, nil return completeCount, nil

View File

@@ -87,7 +87,7 @@ func GetWordCount(filepath string) (*int64, error) {
} }
return &totalWords, nil return &totalWords, nil
} else { } else {
return nil, fmt.Errorf("invalid extension: %s", fileExtension) return nil, fmt.Errorf("Invalid extension: %s", fileExtension)
} }
} }

View File

@@ -4,11 +4,14 @@ import (
"fmt" "fmt"
"io" "io"
"net/url" "net/url"
"regexp"
"strings" "strings"
"github.com/PuerkitoBio/goquery" "github.com/PuerkitoBio/goquery"
) )
var commentRE = regexp.MustCompile(`(?s)<!--(.*?)-->`)
func searchAnnasArchive(query string) ([]SearchItem, error) { func searchAnnasArchive(query string) ([]SearchItem, error) {
searchURL := "https://annas-archive.org/search?index=&q=%s&ext=epub&sort=&lang=en" searchURL := "https://annas-archive.org/search?index=&q=%s&ext=epub&sort=&lang=en"
url := fmt.Sprintf(searchURL, url.QueryEscape(query)) url := fmt.Sprintf(searchURL, url.QueryEscape(query))
@@ -29,34 +32,62 @@ func parseAnnasArchive(body io.ReadCloser) ([]SearchItem, error) {
// Normalize Results // Normalize Results
var allEntries []SearchItem var allEntries []SearchItem
doc.Find(".js-aarecord-list-outer > div > div").Each(func(ix int, rawBook *goquery.Selection) { doc.Find("#aarecord-list > div.justify-center").Each(func(ix int, rawBook *goquery.Selection) {
rawBook = getAnnasArchiveBookSelection(rawBook)
// Parse Details // Parse Details
details := rawBook.Find("div:nth-child(3)").Text() details := rawBook.Find("div:nth-child(2) > div:nth-child(1)").Text()
detailsSplit := strings.Split(details, " · ") detailsSplit := strings.Split(details, ", ")
// Invalid Details // Invalid Details
if len(detailsSplit) < 3 { if len(detailsSplit) < 4 {
return return
} }
// Parse MD5 // Parse MD5
titleAuthorDetails := rawBook.Find("div a") itemHref, _ := rawBook.Find("a").Attr("href")
titleEl := titleAuthorDetails.Eq(0)
itemHref, _ := titleEl.Attr("href")
hrefArray := strings.Split(itemHref, "/") hrefArray := strings.Split(itemHref, "/")
id := hrefArray[len(hrefArray)-1] id := hrefArray[len(hrefArray)-1]
allEntries = append(allEntries, SearchItem{ allEntries = append(allEntries, SearchItem{
ID: id, ID: id,
Title: titleEl.Text(), Title: rawBook.Find("h3").First().Text(),
Author: titleAuthorDetails.Eq(1).Text(), Author: rawBook.Find("div:nth-child(2) > div:nth-child(4)").First().Text(),
Language: detailsSplit[0], Language: detailsSplit[0],
FileType: detailsSplit[1], FileType: detailsSplit[1],
FileSize: detailsSplit[2], FileSize: detailsSplit[3],
}) })
}) })
// Return Results // Return Results
return allEntries, nil return allEntries, nil
} }
// getAnnasArchiveBookSelection parses potentially commented out HTML. For some reason
// Annas Archive comments out blocks "below the fold". They aren't rendered until you
// scroll. This attempts to parse the commented out HTML.
func getAnnasArchiveBookSelection(rawBook *goquery.Selection) *goquery.Selection {
rawHTML, err := rawBook.Html()
if err != nil {
return rawBook
}
strippedHTML := strings.TrimSpace(rawHTML)
if !strings.HasPrefix(strippedHTML, "<!--") || !strings.HasSuffix(strippedHTML, "-->") {
return rawBook
}
allMatches := commentRE.FindAllStringSubmatch(strippedHTML, -1)
if len(allMatches) != 1 || len(allMatches[0]) != 2 {
return rawBook
}
captureGroup := allMatches[0][1]
docReader := strings.NewReader(captureGroup)
doc, err := goquery.NewDocumentFromReader(docReader)
if err != nil {
return rawBook
}
return doc.Selection
}