mirror of
https://github.com/truewhile/MeBox.git
synced 2026-10-01 20:16:36 +08:00
b8e6418326
- internal/service/reader/rule/:逐方法移植 legado analyzeRule 包 (AnalyzeRule/AnalyzeByJSoup/AnalyzeByJSonPath/AnalyzeByXPath/ AnalyzeByRegex/AnalyzeUrl/RuleAnalyzer),JS 规则留 P2 接入点 - 书源导入(JSON数组/对象/Base64/URL)、多源聚合搜索(legado 四档 排序合并)、详情/目录/正文(nextContentUrl 翻页合并) - 数据模型 4 表注册迁移;/api/reader/* 路由组(书源/搜索/书架/进度/调试) - 单测 + httptest 全链路端到端测试 - docs/reader-ui-spec.md:legado UI 交互仿制规格(供 P1 前端使用)
150 lines
5.3 KiB
Go
150 lines
5.3 KiB
Go
// Package repository — 阅读子系统仓储(书源 / 书架 / 章节 / 替换规则)。
|
|
package repository
|
|
|
|
import (
|
|
"context"
|
|
|
|
"gorm.io/gorm"
|
|
|
|
"github.com/truewhile/MeBox/internal/model"
|
|
)
|
|
|
|
// ReaderRepository 阅读子系统 GORM 封装。
|
|
type ReaderRepository struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
// ListSources 书源列表(按 customOrder 排序)。
|
|
func (r *ReaderRepository) ListSources(ctx context.Context) ([]model.ReaderBookSource, error) {
|
|
var out []model.ReaderBookSource
|
|
err := r.db.WithContext(ctx).Order("custom_order ASC, updated_at DESC").Find(&out).Error
|
|
return out, err
|
|
}
|
|
|
|
// GetSource 按 ID 取书源。
|
|
func (r *ReaderRepository) GetSource(ctx context.Context, id string) (*model.ReaderBookSource, error) {
|
|
var out model.ReaderBookSource
|
|
if err := r.db.WithContext(ctx).First(&out, "id = ?", id).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return &out, nil
|
|
}
|
|
|
|
// GetSourceByURL 按书源 URL 取书源(导入去重用)。
|
|
func (r *ReaderRepository) GetSourceByURL(ctx context.Context, sourceURL string) (*model.ReaderBookSource, error) {
|
|
var out model.ReaderBookSource
|
|
err := r.db.WithContext(ctx).First(&out, "source_url = ?", sourceURL).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &out, nil
|
|
}
|
|
|
|
// CreateSource 新增书源。
|
|
func (r *ReaderRepository) CreateSource(ctx context.Context, src *model.ReaderBookSource) error {
|
|
return r.db.WithContext(ctx).Create(src).Error
|
|
}
|
|
|
|
// UpdateSource 更新书源字段。
|
|
func (r *ReaderRepository) UpdateSource(ctx context.Context, src *model.ReaderBookSource) error {
|
|
return r.db.WithContext(ctx).Save(src).Error
|
|
}
|
|
|
|
// DeleteSource 删除书源。
|
|
func (r *ReaderRepository) DeleteSource(ctx context.Context, id string) error {
|
|
return r.db.WithContext(ctx).Delete(&model.ReaderBookSource{}, "id = ?", id).Error
|
|
}
|
|
|
|
// ListBooks 用户书架(按 order 排序)。
|
|
func (r *ReaderRepository) ListBooks(ctx context.Context, userID string) ([]model.ReaderBook, error) {
|
|
var out []model.ReaderBook
|
|
err := r.db.WithContext(ctx).Where("user_id = ?", userID).Order("`order` ASC, updated_at DESC").Find(&out).Error
|
|
return out, err
|
|
}
|
|
|
|
// GetBook 按 ID 取书。
|
|
func (r *ReaderRepository) GetBook(ctx context.Context, id string) (*model.ReaderBook, error) {
|
|
var out model.ReaderBook
|
|
if err := r.db.WithContext(ctx).First(&out, "id = ?", id).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return &out, nil
|
|
}
|
|
|
|
// FindBookByURL 按用户 + 书源 + 书 URL 查书(加书架去重)。
|
|
func (r *ReaderRepository) FindBookByURL(ctx context.Context, userID, origin, bookURL string) (*model.ReaderBook, error) {
|
|
var out model.ReaderBook
|
|
err := r.db.WithContext(ctx).First(&out, "user_id = ? AND origin = ? AND book_url = ?", userID, origin, bookURL).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &out, nil
|
|
}
|
|
|
|
// CreateBook / UpdateBook / DeleteBook。
|
|
func (r *ReaderRepository) CreateBook(ctx context.Context, b *model.ReaderBook) error {
|
|
return r.db.WithContext(ctx).Create(b).Error
|
|
}
|
|
|
|
func (r *ReaderRepository) UpdateBook(ctx context.Context, b *model.ReaderBook) error {
|
|
return r.db.WithContext(ctx).Save(b).Error
|
|
}
|
|
|
|
func (r *ReaderRepository) DeleteBook(ctx context.Context, userID, id string) error {
|
|
return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
|
if err := tx.Delete(&model.ReaderBook{}, "id = ? AND user_id = ?", id, userID).Error; err != nil {
|
|
return err
|
|
}
|
|
return tx.Delete(&model.ReaderChapter{}, "book_id = ?", id).Error
|
|
})
|
|
}
|
|
|
|
// ReplaceChapters 覆盖式刷新章节列表。
|
|
func (r *ReaderRepository) ReplaceChapters(ctx context.Context, bookID string, chapters []model.ReaderChapter) error {
|
|
return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
|
if err := tx.Delete(&model.ReaderChapter{}, "book_id = ?", bookID).Error; err != nil {
|
|
return err
|
|
}
|
|
if len(chapters) == 0 {
|
|
return nil
|
|
}
|
|
return tx.CreateInBatches(chapters, 500).Error
|
|
})
|
|
}
|
|
|
|
// ListChapters 按序取章节。
|
|
func (r *ReaderRepository) ListChapters(ctx context.Context, bookID string) ([]model.ReaderChapter, error) {
|
|
var out []model.ReaderChapter
|
|
err := r.db.WithContext(ctx).Where("book_id = ?", bookID).Order("`index` ASC").Find(&out).Error
|
|
return out, err
|
|
}
|
|
|
|
// GetChapter 取指定章节。
|
|
func (r *ReaderRepository) GetChapter(ctx context.Context, bookID string, index int) (*model.ReaderChapter, error) {
|
|
var out model.ReaderChapter
|
|
if err := r.db.WithContext(ctx).First(&out, "book_id = ? AND `index` = ?", bookID, index).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return &out, nil
|
|
}
|
|
|
|
// ListReplaceRules 用户替换规则(按 order 排序)。
|
|
func (r *ReaderRepository) ListReplaceRules(ctx context.Context, userID string) ([]model.ReaderReplaceRule, error) {
|
|
var out []model.ReaderReplaceRule
|
|
err := r.db.WithContext(ctx).Where("user_id = ?", userID).Order("`order` DESC, created_at ASC").Find(&out).Error
|
|
return out, err
|
|
}
|
|
|
|
// CreateReplaceRule / UpdateReplaceRule / DeleteReplaceRule。
|
|
func (r *ReaderRepository) CreateReplaceRule(ctx context.Context, rule *model.ReaderReplaceRule) error {
|
|
return r.db.WithContext(ctx).Create(rule).Error
|
|
}
|
|
|
|
func (r *ReaderRepository) UpdateReplaceRule(ctx context.Context, rule *model.ReaderReplaceRule) error {
|
|
return r.db.WithContext(ctx).Save(rule).Error
|
|
}
|
|
|
|
func (r *ReaderRepository) DeleteReplaceRule(ctx context.Context, userID, id string) error {
|
|
return r.db.WithContext(ctx).Delete(&model.ReaderReplaceRule{}, "id = ? AND user_id = ?", id, userID).Error
|
|
}
|