mirror of
https://github.com/truewhile/MeBox.git
synced 2026-10-01 12:06:38 +08:00
5976a8d310
- rule/goja.go:纯 Go JS 运行时(goja),脚本编译缓存 + 超时中断(默认10s),
绑定集合对齐 legado evalJS(java/cookie/cache/source/book/result/baseUrl/
chapter/title/src/page/key)
- rule/bridge.go:java 对象函数名与 legado JsExtensions 一一对应(存量书源
硬编码这些名字),全部 Go 原生实现:
网络 ajax/ajaxAll/connect/get/post/head(经 MeBox HTTP 客户端,响应对象
带 body()/code()/url()/header());规则回调 getString/getStringList/
getElements/put/get(桥回当前解析器);编解码 base64/hex/md5(16/32)/
digest/HMac/encodeURI/timeFormat(SimpleDateFormat 转 Go 布局)
- 对称加密:createSymmetricCrypto + aes/des/3des 全家桶,transformation
三段式解析(AES/DES/3DES × CBC/ECB/CTR/OFB/CFB × PKCS5/7/Zero/NoPadding,
ECB 手工块循环),密钥长度自动补齐,decryptStr 自动识别 Base64/Hex
- get(url,headers) 与 get(key) 按 arity 分发(对齐 Kotlin 重载)
- 浏览器/文件/压缩包类函数明确抛不支持(服务端沙箱边界)
- URL 规则 JS:analyzeJs(@result 链式)、{{js}} 内嵌、option js/bodyJs
- execute 记录 Set-Cookie 进 cookie jar(java/cookie.getCookie 可读)
- 测试:编码/摘要/AES 向量/CBC+ECB 往返/ajax httptest/URL JS/沙箱边界,
全部通过;修复 java.get 双注册、测试缺 SetContent 与 md5Encode16 期望值
155 lines
4.9 KiB
Go
155 lines
4.9 KiB
Go
// Package reader — legado 书源兼容的阅读子系统服务层。
|
|
// 本文件对应 legado data/entities/BookSource.kt 的 JSON 结构。
|
|
package reader
|
|
|
|
import (
|
|
"encoding/json"
|
|
"strings"
|
|
)
|
|
|
|
// BookSource 书源 JSON 结构(字段与 legado 实体一致,未知字段忽略)。
|
|
type BookSource struct {
|
|
RawJSON string `json:"-"`
|
|
BookSourceURL string `json:"bookSourceUrl"`
|
|
BookSourceName string `json:"bookSourceName"`
|
|
BookSourceGroup *string `json:"bookSourceGroup"`
|
|
BookSourceType *int `json:"bookSourceType"` // 0文本 1音频 2图片 3文件 4视频
|
|
BookURLPattern *string `json:"bookUrlPattern"`
|
|
CustomOrder *int `json:"customOrder"`
|
|
Enabled *bool `json:"enabled"`
|
|
EnabledExplore *bool `json:"enabledExplore"`
|
|
EnabledCookieJar *bool `json:"enabledCookieJar"`
|
|
ConcurrentRate *string `json:"concurrentRate"`
|
|
Header *string `json:"header"`
|
|
LoginURL *string `json:"loginUrl"`
|
|
BookSourceComment *string `json:"bookSourceComment"`
|
|
LastUpdateTime *int64 `json:"lastUpdateTime"`
|
|
RespondTime *int64 `json:"respondTime"`
|
|
Weight *int `json:"weight"`
|
|
ExploreURL *string `json:"exploreUrl"`
|
|
SearchURL *string `json:"searchUrl"`
|
|
RuleExplore *ExploreRule `json:"ruleExplore"`
|
|
RuleSearch *SearchRule `json:"ruleSearch"`
|
|
RuleBookInfo *BookInfoRule `json:"ruleBookInfo"`
|
|
RuleToc *TocRule `json:"ruleToc"`
|
|
RuleContent *ContentRule `json:"ruleContent"`
|
|
VariableComment *string `json:"variableComment"`
|
|
Variables map[string]any `json:"-"`
|
|
RawVariables *string `json:"variables"`
|
|
}
|
|
|
|
// SearchRule 搜索规则。
|
|
type SearchRule struct {
|
|
CheckKeyWord *string `json:"checkKeyWord"`
|
|
BookList *string `json:"bookList"`
|
|
Name *string `json:"name"`
|
|
Author *string `json:"author"`
|
|
Kind *string `json:"kind"`
|
|
WordCount *string `json:"wordCount"`
|
|
LastChapter *string `json:"lastChapter"`
|
|
Intro *string `json:"intro"`
|
|
CoverURL *string `json:"coverUrl"`
|
|
BookURL *string `json:"bookUrl"`
|
|
}
|
|
|
|
// BookInfoRule 详情规则。
|
|
type BookInfoRule struct {
|
|
Init *string `json:"init"`
|
|
Name *string `json:"name"`
|
|
Author *string `json:"author"`
|
|
Kind *string `json:"kind"`
|
|
WordCount *string `json:"wordCount"`
|
|
LastChapter *string `json:"lastChapter"`
|
|
Intro *string `json:"intro"`
|
|
CoverURL *string `json:"coverUrl"`
|
|
TocURL *string `json:"tocUrl"`
|
|
CanReName *string `json:"canReName"`
|
|
DownloadUrls *string `json:"downloadUrls"`
|
|
}
|
|
|
|
// TocRule 目录规则。
|
|
type TocRule struct {
|
|
PreUpdateJs *string `json:"preUpdateJs"`
|
|
ChapterList *string `json:"chapterList"`
|
|
ChapterName *string `json:"chapterName"`
|
|
ChapterURL *string `json:"chapterUrl"`
|
|
IsVolume *string `json:"isVolume"`
|
|
UpdateTime *string `json:"updateTime"`
|
|
}
|
|
|
|
// ContentRule 正文规则。
|
|
type ContentRule struct {
|
|
Content *string `json:"content"`
|
|
NextContentURL *string `json:"nextContentUrl"`
|
|
WebJs *string `json:"webJs"`
|
|
SourceRegex *string `json:"sourceRegex"`
|
|
ReplaceRegex *string `json:"replaceRegex"`
|
|
ImageStyle *string `json:"imageStyle"`
|
|
PayAction *string `json:"payAction"`
|
|
}
|
|
|
|
// ExploreRule 发现规则。
|
|
type ExploreRule struct {
|
|
BookList *string `json:"bookList"`
|
|
Name *string `json:"name"`
|
|
Author *string `json:"author"`
|
|
Kind *string `json:"kind"`
|
|
WordCount *string `json:"wordCount"`
|
|
LastChapter *string `json:"lastChapter"`
|
|
Intro *string `json:"intro"`
|
|
CoverURL *string `json:"coverUrl"`
|
|
BookURL *string `json:"bookUrl"`
|
|
ExploreURL *string `json:"exploreUrl"`
|
|
ExploreKinds *string `json:"exploreKinds"`
|
|
CheckKeyWord *string `json:"checkKeyWord"`
|
|
}
|
|
|
|
// ParseBookSource 将书源 JSON 解析为结构体。
|
|
func ParseBookSource(raw string) (*BookSource, error) {
|
|
var bs BookSource
|
|
if err := json.Unmarshal([]byte(raw), &bs); err != nil {
|
|
return nil, err
|
|
}
|
|
bs.RawJSON = raw
|
|
if bs.RawVariables != nil && strings.TrimSpace(*bs.RawVariables) != "" {
|
|
_ = json.Unmarshal([]byte(*bs.RawVariables), &bs.Variables)
|
|
}
|
|
return &bs, nil
|
|
}
|
|
|
|
// SourceProps 书源 JSON 原样转为 map(注入 JS 的 `source` 对象)。
|
|
func (b *BookSource) SourceProps() map[string]any {
|
|
if b.RawJSON == "" {
|
|
return nil
|
|
}
|
|
var m map[string]any
|
|
if json.Unmarshal([]byte(b.RawJSON), &m) != nil {
|
|
return nil
|
|
}
|
|
return m
|
|
}
|
|
|
|
// Type 返回书源类型(默认文本)。
|
|
func (b *BookSource) Type() int {
|
|
if b.BookSourceType == nil {
|
|
return 0
|
|
}
|
|
return *b.BookSourceType
|
|
}
|
|
|
|
// SPtr 取字符串指针字段值。
|
|
func SPtr(s *string) string {
|
|
if s == nil {
|
|
return ""
|
|
}
|
|
return *s
|
|
}
|
|
|
|
// IPtr 取整型指针字段值。
|
|
func IPtr(i *int) int {
|
|
if i == nil {
|
|
return 0
|
|
}
|
|
return *i
|
|
}
|