From 6028e7d8c2ae80f94b6b845afab0695cc9fa7c33 Mon Sep 17 00:00:00 2001 From: nite Date: Sun, 20 Apr 2025 01:13:51 +1000 Subject: [PATCH] add metadatas --- .gitignore | 1 + .goreleaser.yaml | 31 +++++++++++++++++++++++++ cmd/version.go | 22 ++++++++++++++++++ downloader/bilinovel.go | 51 +++++++++++++++++++++++++++++++++++++---- model/struct.go | 5 ++++ 5 files changed, 105 insertions(+), 5 deletions(-) create mode 100644 .goreleaser.yaml create mode 100644 cmd/version.go diff --git a/.gitignore b/.gitignore index fcff2aa..960cbb7 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ novels/ +dist/ diff --git a/.goreleaser.yaml b/.goreleaser.yaml new file mode 100644 index 0000000..1aa201c --- /dev/null +++ b/.goreleaser.yaml @@ -0,0 +1,31 @@ +project_name: bilinovel-downloader +before: + hooks: + - templ generate +builds: + - env: + - CGO_ENABLED=0 + goos: + - windows + - linux + - darwin + goarch: + - amd64 + - arm64 + - arm + - "386" + ldflags: + - -s -w -X bilinovel-downloader/cmd.Version={{ .Version }} + flags: + - -trimpath +archives: + - format: tar.gz + format_overrides: + - format: zip + goos: windows + wrap_in_directory: true +release: + draft: true +upx: + - enabled: true + compress: best diff --git a/cmd/version.go b/cmd/version.go new file mode 100644 index 0000000..926c29e --- /dev/null +++ b/cmd/version.go @@ -0,0 +1,22 @@ +package cmd + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +const ( + Version = "dev" +) + +var versionCmd = &cobra.Command{ + Use: "version", + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("version: ", Version) + }, +} + +func init() { + RootCmd.AddCommand(versionCmd) +} diff --git a/downloader/bilinovel.go b/downloader/bilinovel.go index caef9ea..36e0a7c 100644 --- a/downloader/bilinovel.go +++ b/downloader/bilinovel.go @@ -41,6 +41,7 @@ func GetNovel(novelId int) (*model.Novel, error) { novel.Title = strings.TrimSpace(doc.Find(".book-title").First().Text()) novel.Description = strings.TrimSpace(doc.Find(".book-summary>content").First().Text()) + novel.Id = novelId doc.Find(".authorname>a").Each(func(i int, s *goquery.Selection) { novel.Authors = append(novel.Authors, strings.TrimSpace(s.Text())) @@ -49,7 +50,7 @@ func GetNovel(novelId int) (*model.Novel, error) { novel.Authors = append(novel.Authors, strings.TrimSpace(s.Text())) }) - volumes, err := GetNovelVolumes(novelId) + volumes, err := getNovelVolumes(novelId) if err != nil { return nil, fmt.Errorf("failed to get novel volumes: %v", err) } @@ -59,7 +60,7 @@ func GetNovel(novelId int) (*model.Novel, error) { } func GetVolume(novelId int, volumeId int) (*model.Volume, error) { - novelUrl := fmt.Sprintf("https://www.bilinovel.com/novel/%v/vol_%v.html", novelId, volumeId) + novelUrl := fmt.Sprintf("https://www.bilinovel.com/novel/%v/catalog", novelId) resp, err := utils.Request().Get(novelUrl) if err != nil { return nil, fmt.Errorf("failed to get novel info: %v", err) @@ -73,11 +74,42 @@ func GetVolume(novelId int, volumeId int) (*model.Volume, error) { return nil, fmt.Errorf("failed to parse html: %v", err) } + seriesIdx := 0 + doc.Find("a.volume-cover-img").Each(func(i int, s *goquery.Selection) { + if s.AttrOr("href", "") == fmt.Sprintf("/novel/%v/vol_%v.html", novelId, volumeId) { + seriesIdx = i + 1 + } + }) + + novelTitle := strings.TrimSpace(doc.Find(".book-title").First().Text()) + + if seriesIdx == 0 { + return nil, fmt.Errorf("volume not found: %v", volumeId) + } + + volumeUrl := fmt.Sprintf("https://www.bilinovel.com/novel/%v/vol_%v.html", novelId, volumeId) + resp, err = utils.Request().Get(volumeUrl) + if err != nil { + return nil, fmt.Errorf("failed to get novel info: %v", err) + } + if resp.StatusCode() != http.StatusOK { + return nil, fmt.Errorf("failed to get novel info: %v", resp.Status()) + } + + doc, err = goquery.NewDocumentFromReader(bytes.NewReader(resp.Body())) + if err != nil { + return nil, fmt.Errorf("failed to parse html: %v", err) + } + volume := &model.Volume{} + volume.NovelId = novelId + volume.NovelTitle = novelTitle + volume.Id = volumeId + volume.SeriesIdx = seriesIdx volume.Title = strings.TrimSpace(doc.Find(".book-title").First().Text()) volume.Description = strings.TrimSpace(doc.Find(".book-summary>content").First().Text()) volume.Cover = doc.Find(".book-cover").First().AttrOr("src", "") - volume.Url = novelUrl + volume.Url = volumeUrl volume.Chapters = make([]*model.Chapter, 0) doc.Find(".authorname>a").Each(func(i int, s *goquery.Selection) { @@ -97,7 +129,7 @@ func GetVolume(novelId int, volumeId int) (*model.Volume, error) { return volume, nil } -func GetNovelVolumes(novelId int) ([]*model.Volume, error) { +func getNovelVolumes(novelId int) ([]*model.Volume, error) { catelogUrl := fmt.Sprintf("https://www.bilinovel.com/novel/%v/catalog", novelId) resp, err := utils.Request().Get(catelogUrl) if err != nil { @@ -124,7 +156,7 @@ func GetNovelVolumes(novelId int) ([]*model.Volume, error) { }) volumes := make([]*model.Volume, 0) - for _, volumeIdStr := range volumeIds { + for i, volumeIdStr := range volumeIds { volumeId, err := strconv.Atoi(volumeIdStr) if err != nil { return nil, fmt.Errorf("failed to convert volume id: %v", err) @@ -133,6 +165,7 @@ func GetNovelVolumes(novelId int) ([]*model.Volume, error) { if err != nil { return nil, fmt.Errorf("failed to get volume info: %v", err) } + volume.SeriesIdx = i volumes = append(volumes, volume) } @@ -497,6 +530,14 @@ func CreateContentOPF(dirPath string, uuid string, volume *model.Volume) error { Property: "dcterms:modified", Value: time.Now().UTC().Format("2006-01-02T15:04:05Z"), }, + { + Name: "calibre:series", + Content: volume.NovelTitle, + }, + { + Name: "calibre:series_index", + Content: strconv.Itoa(volume.SeriesIdx), + }, }, } manifest := &model.Manifest{ diff --git a/model/struct.go b/model/struct.go index 490f720..11335b1 100644 --- a/model/struct.go +++ b/model/struct.go @@ -11,15 +11,20 @@ type Chapter struct { } type Volume struct { + Id int + SeriesIdx int Title string Url string Cover string Description string Authors []string Chapters []*Chapter + NovelId int + NovelTitle string } type Novel struct { + Id int Title string Description string Authors []string