Files
nu-api/api.go

195 lines
5.2 KiB
Go

package nuapi
import (
"context"
"fmt"
"path"
"strconv"
"strings"
"time"
"git.tordarus.net/tordarus/adverr/v2"
"github.com/PuerkitoBio/goquery"
)
type Api struct {
UserAgent string
Cookie string
}
func NewApi(cookie string) *Api {
return &Api{
Cookie: cookie,
UserAgent: "Mozilla/5.0 (X11; Linux x86_64; rv:141.0) Gecko/20100101 Firefox/141.0",
}
}
func (api *Api) GetReadingList(ctx context.Context, listIndex int) (*ReadingList, error) {
doc, err := api.GetWithCookie(ctx, fmt.Sprintf("https://www.novelupdates.com/reading-list/?list=%d", listIndex))
if err != nil {
return nil, ErrApiRequestFailed.Wrap(err)
}
listID := ReadingListID(doc.Find("#cssmenu ul li.active a").Text())
selection := doc.Find("table tbody tr")
entries := make([]ReadingListEntry, 0, selection.Length())
selection.Each(func(i int, s *goquery.Selection) {
link := s.Find("td:nth-child(2) a:first-child")
href, ok := link.Attr("href")
if !ok {
return
}
novelID := NovelID(path.Base(href))
novel := NovelEntry{
NovelID: novelID,
Name: link.Text(),
}
currentChapterLink := s.Find("td:nth-child(3) a")
currentChapter := ReadingListChapterEntry{
NovelID: novelID,
ID: ChapterID(currentChapterLink.Text()),
Link: currentChapterLink.AttrOr("href", ""),
}
latestChapterLink := s.Find("td:nth-child(3) a")
latestChapter := ReadingListChapterEntry{
NovelID: novelID,
ID: ChapterID(latestChapterLink.Text()),
Link: latestChapterLink.AttrOr("href", ""),
}
entries = append(entries, ReadingListEntry{
Novel: novel,
CurrentChapter: currentChapter,
LatestChapter: latestChapter,
})
})
return &ReadingList{
ID: listID,
Entries: entries,
}, nil
}
func (api *Api) GetNovelByID(novelID NovelID) (*Novel, error) {
doc, err := api.Get(fmt.Sprintf("https://www.novelupdates.com/series/%s/", novelID))
if err != nil {
return nil, ErrApiRequestFailed.Wrap(err)
}
title := doc.Find(".seriestitlenu").Text()
description := strings.TrimSpace(doc.Find("#editdescription").Text())
cover := doc.Find(".wpb_wrapper img").AttrOr("src", "")
associatedNamesHtml, err := doc.Find("#editassociated").Html()
if err != nil {
return nil, ErrApiElementNotFound.Wrap(err, "#editassociated")
}
associatedNames := strings.Split(strings.TrimSpace(associatedNamesHtml), "<br/>")
novelType := NovelType(doc.Find("#showtype a.genre.type").Text())
originalLanguage := Language(strings.ToLower(strings.Trim(doc.Find("#showtype a.genre.type + span").Text(), "()")))
genreElems := doc.Find("#seriesgenre a.genre")
genres := make([]GenreID, 0, genreElems.Length())
genreElems.Each(func(i int, s *goquery.Selection) {
href, ok := s.Attr("href")
if !ok {
return
}
genres = append(genres, GenreID(path.Base(href)))
})
tagElems := doc.Find("#showtags a.genre")
tags := make([]TagID, 0, genreElems.Length())
tagElems.Each(func(i int, s *goquery.Selection) {
href, ok := s.Attr("href")
if !ok {
return
}
tags = append(tags, TagID(path.Base(href)))
})
return &Novel{
ID: novelID,
Name: title,
AssociatedNames: associatedNames,
Description: description,
Cover: cover,
Type: novelType,
OriginalLanguage: originalLanguage,
Genres: genres,
Tags: tags,
}, nil
}
func (api *Api) GetChapterEntriesByNovelID(ctx context.Context, novelID NovelID, traverser ChapterEntryTraverser) (<-chan NovelChapterEntry, error) {
doc, err := api.Get(fmt.Sprintf("https://www.novelupdates.com/series/%s/?pg=%d", novelID, 1))
if err != nil {
return nil, err
}
pageCount, err := api.getPageCount(doc)
if err != nil {
return nil, err
}
out := make(chan NovelChapterEntry, 15)
go traverser(ctx, api, novelID, pageCount, out)
return out, nil
}
func (api *Api) getPageCount(doc *goquery.Document) (int, error) {
pagination := doc.Find(".digg_pagination")
if pagination.Length() <= 0 {
return 1, nil
}
pageCount, err := strconv.ParseInt(pagination.Find("a:nth-last-child(2)").Text(), 10, 64)
if err != nil {
adverr.Println(ErrApiElementNotFound.Wrap(err, ".digg_pagination a:nth-child(5)"))
return 0, err
}
return int(pageCount), nil
}
func (api *Api) getChapterEntriesByPageIndex(novelID NovelID, pageIndex int) ([]NovelChapterEntry, error) {
doc, err := api.Get(fmt.Sprintf("https://www.novelupdates.com/series/%s/?pg=%d", novelID, pageIndex))
if err != nil {
return nil, ErrApiRequestFailed.Wrap(err)
}
entryElems := doc.Find("#myTable tbody tr")
entries := make([]NovelChapterEntry, 0, entryElems.Length())
entryElems.Each(func(i int, s *goquery.Selection) {
td3 := s.Find("td:nth-child(3) a")
fmt.Printf("%#v\n", adverr.Must(s.Find("td:nth-child(3)").Html()))
chapterID := strings.TrimSpace(td3.Text())
groupID := path.Base(s.Find("td:nth-child(2) a").AttrOr("href", ""))
link := "https:" + td3.AttrOr("href", "")
date, err := time.Parse("01/02/2006", strings.TrimSpace(s.Find("td:first-child").Text()))
if err != nil {
adverr.Println(ErrApiElementNotFound.Wrap(err, "td:first-child"))
return
}
entries = append(entries, NovelChapterEntry{
NovelID: novelID,
ID: chapterID,
Link: link,
Date: date,
Group: groupID,
})
})
return entries, nil
}