|
|
@@ -0,0 +1,349 @@
|
|
|
+# JS 变量和函数
|
|
|
+
|
|
|
+[[toc]]
|
|
|
+
|
|
|
+Legado 使用 [Rhino v1.8.0](https://github.com/mozilla/rhino) 作为 JavaScript 引擎,支持在源规则中调用
|
|
|
+Java 类和方法。本文档列出所有可用的内置变量、对象属性和扩展函数。
|
|
|
+
|
|
|
+## 1. Rhino 引擎概览
|
|
|
+
|
|
|
+| 构造函数 | 函数 | 调用类 | 说明 |
|
|
|
+|:---------------|:------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------|:--------------------------|
|
|
|
+| `JavaImporter` | `importClass` `importPackage` | [ImporterTopLevel](https://github.com/mozilla/rhino/blob/master/rhino/src/main/java/org/mozilla/javascript/ImporterTopLevel.java) | 导入 Java 类到 JavaScript |
|
|
|
+| — | `getClass` | [NativeJavaTopPackage](https://github.com/mozilla/rhino/blob/master/rhino/src/main/java/org/mozilla/javascript/NativeJavaTopPackage.java) | 默认导入 JavaScript 中的 Java 类 |
|
|
|
+| `JavaAdapter` | — | [JavaAdapter](https://github.com/mozilla/rhino/blob/master/rhino/src/main/java/org/mozilla/javascript/JavaAdapter.java) | 继承 Java 类 |
|
|
|
+
|
|
|
+- [Rhino 运行时](https://github.com/mozilla/rhino/blob/master/rhino/src/main/java/org/mozilla/javascript/ScriptRuntime.java)
|
|
|
+ 懒加载导入的 Java 类和方法
|
|
|
+- [ECMAScript 兼容性表格](https://mozilla.github.io/rhino/compat/engines.html)
|
|
|
+
|
|
|
+::: warning 注意事项
|
|
|
+
|
|
|
+- `java` 变量已被 Legado 修改,调用 `java.*` 下的包请使用 `Packages.java.*`
|
|
|
+- 在源规则中使用 `@js`、`<js>`、<code v-pre>{{}}</code> 可调用 Legado 内置的类和方法
|
|
|
+- 为安全起见,部分 Java
|
|
|
+ 类调用被屏蔽,见 [RhinoClassShutter](https://github.com/HapeLee/legado-with-MD3/blob/master/modules/rhino/src/main/java/com/script/rhino/RhinoClassShutter.kt)
|
|
|
+- 不同源规则中支持调用的 Java 类和方法可能不同
|
|
|
+- `const` 声明的变量不支持块级作用域,循环中使用会出现值不变的问题,请改用 `var`
|
|
|
+ :::
|
|
|
+
|
|
|
+## 2. 内置变量 (Built-in Variables)
|
|
|
+
|
|
|
+以下变量在源规则的 JS 执行环境中自动可用。
|
|
|
+
|
|
|
+| 变量 | 类型 | 作用域 | 说明 |
|
|
|
+|:-----------------|:---------------|:----|:-------------------------------------------------------------------------------------------------------------------------------|
|
|
|
+| `java` | `Object` | 全局 | 扩展工具对象,提供网络请求、加解密、文件操作等方法 |
|
|
|
+| `baseUrl` | `String` | 全局 | 当前请求的 URL |
|
|
|
+| `result` | `Any` | 全局 | 上一步规则的执行结果 |
|
|
|
+| `book` | `Book` | 全局 | [书籍对象](https://github.com/HapeLee/legado-with-MD3/blob/master/app/src/main/java/io/legado/app/data/entities/Book.kt) |
|
|
|
+| `rssArticle` | `RssArticle` | 全局 | [RSS 文章对象](https://github.com/HapeLee/legado-with-MD3/blob/master/app/src/main/java/io/legado/app/data/entities/RssArticle.kt) |
|
|
|
+| `chapter` | `BookChapter` | 全局 | [章节对象](https://github.com/HapeLee/legado-with-MD3/blob/master/app/src/main/java/io/legado/app/data/entities/BookChapter.kt) |
|
|
|
+| `source` | `BaseSource` | 全局 | [源对象](https://github.com/HapeLee/legado-with-MD3/blob/master/app/src/main/java/io/legado/app/data/entities/BaseSource.kt) |
|
|
|
+| `cookie` | `CookieStore` | 全局 | [Cookie 操作对象](https://github.com/HapeLee/legado-with-MD3/blob/master/app/src/main/java/io/legado/app/help/http/CookieStore.kt) |
|
|
|
+| `cache` | `CacheManager` | 全局 | [缓存操作对象](https://github.com/HapeLee/legado-with-MD3/blob/master/app/src/main/java/io/legado/app/help/CacheManager.kt) |
|
|
|
+| `title` | `String` | 全局 | 当前章节标题 |
|
|
|
+| `src` | `String` | 全局 | 请求返回的源码 |
|
|
|
+| `nextChapterUrl` | `String` | 全局 | 下一章节 URL |
|
|
|
+
|
|
|
+## 3. java 对象方法
|
|
|
+
|
|
|
+`java` 对象是 Legado 暴露给 JS 环境的核心工具对象,聚合了多个扩展类的方法。
|
|
|
+
|
|
|
+### 3.1 RSS 扩展 ([RssJsExtensions](https://github.com/HapeLee/legado-with-MD3/blob/master/app/src/main/java/io/legado/app/ui/rss/read/RssJsExtensions.kt))
|
|
|
+
|
|
|
+::: warning 作用域限制
|
|
|
+只能在订阅源 `shouldOverrideUrlLoading` 规则中使用。URL 跳转拦截规则不能执行耗时操作。
|
|
|
+:::
|
|
|
+
|
|
|
+```js
|
|
|
+java.searchBook(bookName: String) // 调用 Legado 搜索
|
|
|
+java.addBook(bookUrl: String) // 添加书架
|
|
|
+```
|
|
|
+
|
|
|
+### 3.2 URL 解析 ([AnalyzeUrl](https://github.com/HapeLee/legado-with-MD3/blob/master/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt))
|
|
|
+
|
|
|
+通过 `java.` 调用,仅在 `登录检查 JS` 规则中有效。
|
|
|
+
|
|
|
+| 方法 | 返回值 | 说明 |
|
|
|
+|:---------------------------------------------------|:--------------|:--------------------|
|
|
|
+| `initUrl()` | — | 重新解析 URL |
|
|
|
+| `getHeaderMap().putAll(source.getHeaderMap(true))` | — | 重新设置登录头 |
|
|
|
+| `getStrResponse(jsStr, sourceRegex)` | `StrResponse` | 返回文本类型的访问结果 |
|
|
|
+| `getResponse()` | `Response` | 返回 Response 类型的访问结果 |
|
|
|
+
|
|
|
+### 3.3 规则解析 ([AnalyzeRule](https://github.com/HapeLee/legado-with-MD3/blob/master/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt))
|
|
|
+
|
|
|
+```js
|
|
|
+// 获取文本/文本列表
|
|
|
+java.getString(ruleStr: String?, mContent: Any? = null, isUrl: Boolean = false)
|
|
|
+java.getStringList(ruleStr: String?, mContent: Any? = null, isUrl: Boolean = false)
|
|
|
+
|
|
|
+// 设置解析内容
|
|
|
+java.setContent(content: Any?, baseUrl: String? = null)
|
|
|
+
|
|
|
+// 获取 Element/Element 列表
|
|
|
+java.getElement(ruleStr: String)
|
|
|
+java.getElements(ruleStr: String)
|
|
|
+
|
|
|
+// 重新搜索书籍/重新获取目录 url(只能在刷新目录之前使用)
|
|
|
+java.reGetBook()
|
|
|
+java.refreshTocUrl()
|
|
|
+
|
|
|
+// 变量存取
|
|
|
+java.get(key)
|
|
|
+java.put(key, value)
|
|
|
+```
|
|
|
+
|
|
|
+### 3.4 扩展工具 ([JsExtensions](https://github.com/HapeLee/legado-with-MD3/blob/master/app/src/main/java/io/legado/app/help/JsExtensions.kt))
|
|
|
+
|
|
|
+#### 链接解析
|
|
|
+
|
|
|
+| 方法 | 返回值 | 说明 |
|
|
|
+|:---------------------------|:---------|:----------------------|
|
|
|
+| `java.toURL(url)` | `JsURL` | 将字符串解析为 URL 对象 |
|
|
|
+| `java.toURL(url, baseUrl)` | `JsURL` | 基于 baseUrl 解析相对 URL |
|
|
|
+| `java.getWebViewUA()` | `String` | 获取 WebView User-Agent |
|
|
|
+
|
|
|
+#### 网络请求
|
|
|
+
|
|
|
+| 方法 | 返回值 | 说明 |
|
|
|
+|:--------------------------------------------------------------|:----------------------|:------------------------------------------------------------------|
|
|
|
+| `java.ajax(urlStr)` | `String` | GET 请求,返回响应体 |
|
|
|
+| `java.ajaxAll(urlList)` | `Array<StrResponse>` | 批量请求 |
|
|
|
+| `java.connect(urlStr)` | `StrResponse` | 返回 `body()` `code()` `message()` `headers()` `raw()` `toString()` |
|
|
|
+| `java.post(url, body, headerMap)` | `Connection.Response` | POST 请求 |
|
|
|
+| `java.get(url, headerMap)` | `Connection.Response` | GET 请求 |
|
|
|
+| `java.head(url, headerMap)` | `Connection.Response` | HEAD 请求 |
|
|
|
+| `java.webView(html, url, js)` | `String?` | 使用 WebView 访问网络 |
|
|
|
+| `java.webViewGetOverrideUrl(html, url, js, overrideUrlRegex)` | `String?` | 使用 WebView 获取跳转 URL |
|
|
|
+| `java.webViewGetSource(html, url, js, sourceRegex)` | `String?` | 使用 WebView 获取资源 URL |
|
|
|
+| `java.startBrowser(url, title)` | — | 使用内置浏览器打开链接 |
|
|
|
+| `java.startBrowserAwait(url, title, refetchAfterSuccess)` | `StrResponse` | 使用内置浏览器打开链接,等待结果 |
|
|
|
+
|
|
|
+#### 调试与提示
|
|
|
+
|
|
|
+| 方法 | 说明 |
|
|
|
+|:-------------------------------------|:---------|
|
|
|
+| `java.log(msg)` | 输出日志 |
|
|
|
+| `java.logType(var)` | 输出变量类型 |
|
|
|
+| `java.getVerificationCode(imageUrl)` | 弹出验证码输入框 |
|
|
|
+| `java.longToast(msg)` | 长时间提示 |
|
|
|
+| `java.toast(msg)` | 短时间提示 |
|
|
|
+
|
|
|
+#### 脚本导入
|
|
|
+
|
|
|
+| 方法 | 说明 |
|
|
|
+|:----------------------------------|:-------------------------------------------|
|
|
|
+| `java.importScript(url)` | 从网络加载脚本 |
|
|
|
+| `java.importScript(relativePath)` | 从相对路径加载(支持 `android/data/{package}/cache`) |
|
|
|
+| `java.importScript(absolutePath)` | 从绝对路径加载 |
|
|
|
+
|
|
|
+#### 文件缓存
|
|
|
+
|
|
|
+```js
|
|
|
+java.cacheFile(url) // 缓存网络文件
|
|
|
+java.cacheFile(url, saveTime) // 缓存并指定保存时间
|
|
|
+eval(String(java.cacheFile(url))) // 缓存并执行
|
|
|
+cache.delete(java.md5Encode16(url)) // 使缓存失效
|
|
|
+```
|
|
|
+
|
|
|
+#### 编码与转换
|
|
|
+
|
|
|
+| 分类 | 方法 | 说明 |
|
|
|
+|:----------|:-------------------------------------------|:---------------------|
|
|
|
+| URI | `java.encodeURI(str, enc?)` | URI 编码,默认 UTF-8 |
|
|
|
+| Base64 | `java.base64Decode(str, charset?)` | Base64 解码为字符串 |
|
|
|
+| Base64 | `java.base64DecodeToByteArray(str, flags)` | Base64 解码为 ByteArray |
|
|
|
+| Base64 | `java.base64Encode(str, flags)` | Base64 编码 |
|
|
|
+| ByteArray | `java.strToBytes(str, charset?)` | 字符串转 ByteArray |
|
|
|
+| ByteArray | `java.bytesToStr(bytes, charset?)` | ByteArray 转字符串 |
|
|
|
+| Hex | `java.hexDecodeToByteArray(hex)` | Hex 解码为 ByteArray |
|
|
|
+| Hex | `java.hexDecodeToString(hex)` | Hex 解码为字符串 |
|
|
|
+| Hex | `java.hexEncodeToString(utf8)` | 字符串转 Hex |
|
|
|
+
|
|
|
+#### 标识与格式化
|
|
|
+
|
|
|
+| 方法 | 返回值 | 说明 |
|
|
|
+|:---------------------------------------|:----------|:--------------|
|
|
|
+| `java.randomUUID()` | `String` | 生成 UUID |
|
|
|
+| `java.androidId()` | `String` | 获取 Android ID |
|
|
|
+| `java.t2s(text)` | `String` | 繁体转简体 |
|
|
|
+| `java.s2t(text)` | `String` | 简体转繁体 |
|
|
|
+| `java.timeFormatUTC(time, format, sh)` | `String?` | UTC 时间格式化 |
|
|
|
+| `java.timeFormat(time)` | `String` | 时间格式化 |
|
|
|
+| `java.htmlFormat(str)` | `String` | HTML 格式化 |
|
|
|
+
|
|
|
+#### 文件操作
|
|
|
+
|
|
|
+::: tip 路径限制
|
|
|
+所有文件读写删除操作均使用相对路径,只能操作阅读缓存目录 `android/data/{package}/cache/` 内的文件。
|
|
|
+:::
|
|
|
+
|
|
|
+| 方法 | 返回值 | 说明 |
|
|
|
+|:----------------------------|:---------|:------------|
|
|
|
+| `downloadFile(url)` | `String` | 文件下载,返回文件路径 |
|
|
|
+| `unArchiveFile(zipPath)` | `String` | 文件解压,返回解压路径 |
|
|
|
+| `unzipFile(zipPath)` | `String` | ZIP 解压 |
|
|
|
+| `unrarFile(zipPath)` | `String` | RAR 解压 |
|
|
|
+| `un7zFile(zipPath)` | `String` | 7Z 解压 |
|
|
|
+| `getTxtInFolder(unzipPath)` | `String` | 读取文件夹内所有文件 |
|
|
|
+| `readTxtFile(path)` | `String` | 读取文本文件 |
|
|
|
+| `deleteFile(path)` | — | 删除文件 |
|
|
|
+
|
|
|
+#### 外部链接跳转
|
|
|
+
|
|
|
+| 方法 | 说明 |
|
|
|
+|:------------------------------|:-------------------------|
|
|
|
+| `java.openUrl(url)` | 跳转外部链接(HTTP 或 scheme) |
|
|
|
+| `java.openUrl(url, mimeType)` | 指定 MIME 类型跳转,如 `video/*` |
|
|
|
+
|
|
|
+### 3.5 加解密 ([JsEncodeUtils](https://github.com/HapeLee/legado-with-MD3/blob/master/app/src/main/java/io/legado/app/help/JsEncodeUtils.kt))
|
|
|
+
|
|
|
+提供在 JavaScript 环境中快捷调用 crypto
|
|
|
+算法的函数,由 [hutool-crypto](https://www.hutool.cn/docs/#/crypto/概述) 实现(当前版本 5.8.22)。
|
|
|
+
|
|
|
+::: warning 输入类型
|
|
|
+如果输入参数不是 Utf8String,可先调用 `java.hexDecodeToByteArray` 或 `java.base64DecodeToByteArray`
|
|
|
+转成 ByteArray。
|
|
|
+:::
|
|
|
+
|
|
|
+#### 对称加密
|
|
|
+
|
|
|
+```js
|
|
|
+// 创建 Cipher,key/iv 支持 ByteArray | Utf8String
|
|
|
+java.createSymmetricCrypto(transformation, key, iv)
|
|
|
+
|
|
|
+// data 支持 ByteArray | Base64String | HexString | InputStream
|
|
|
+cipher.decrypt(data) // 解密为 ByteArray
|
|
|
+cipher.decryptStr(data) // 解密为字符串
|
|
|
+cipher.encrypt(data) // 加密为 ByteArray
|
|
|
+cipher.encryptBase64(data) // 加密为 Base64
|
|
|
+cipher.encryptHex(data) // 加密为 Hex
|
|
|
+```
|
|
|
+
|
|
|
+#### 非对称加密
|
|
|
+
|
|
|
+```js
|
|
|
+java.createAsymmetricCrypto(transformation)
|
|
|
+ .setPublicKey(key)
|
|
|
+ .setPrivateKey(key)
|
|
|
+
|
|
|
+cipher.decrypt(data, usePublicKey: Boolean? = true)
|
|
|
+cipher.decryptStr(data, usePublicKey: Boolean? = true)
|
|
|
+cipher.encrypt(data, usePublicKey: Boolean? = true)
|
|
|
+cipher.encryptBase64(data, usePublicKey: Boolean? = true)
|
|
|
+cipher.encryptHex(data, usePublicKey: Boolean? = true)
|
|
|
+```
|
|
|
+
|
|
|
+#### 签名
|
|
|
+
|
|
|
+```js
|
|
|
+java.createSign(algorithm)
|
|
|
+ .setPublicKey(key)
|
|
|
+ .setPrivateKey(key)
|
|
|
+
|
|
|
+sign.sign(data)
|
|
|
+sign.signHex(data)
|
|
|
+```
|
|
|
+
|
|
|
+#### 摘要与 HMAC
|
|
|
+
|
|
|
+| 方法 | 返回值 | 说明 |
|
|
|
+|:----------------------------------------|:----------|:-------------|
|
|
|
+| `java.digestHex(data, algorithm)` | `String?` | 摘要(Hex) |
|
|
|
+| `java.digestBase64Str(data, algorithm)` | `String?` | 摘要(Base64) |
|
|
|
+| `java.md5Encode(str)` | `String` | MD5(32 位) |
|
|
|
+| `java.md5Encode16(str)` | `String` | MD5(16 位) |
|
|
|
+| `java.HMacHex(data, algorithm, key)` | `String` | HMAC(Hex) |
|
|
|
+| `java.HMacBase64(data, algorithm, key)` | `String` | HMAC(Base64) |
|
|
|
+
|
|
|
+## 4. book 对象
|
|
|
+
|
|
|
+在 JS 中或 <code v-pre>{{}}</code> 中使用 `book.属性` 的方式获取。
|
|
|
+
|
|
|
+| 属性 | 类型 | 说明 |
|
|
|
+|:---------------------|:----------|:--------------------|
|
|
|
+| `bookUrl` | `String` | 详情页 URL(本地源为完整文件路径) |
|
|
|
+| `tocUrl` | `String` | 目录页 URL |
|
|
|
+| `origin` | `String` | 源 URL |
|
|
|
+| `originName` | `String` | 源名称或本地书籍文件名 |
|
|
|
+| `name` | `String` | 书籍名称 |
|
|
|
+| `author` | `String` | 作者名称 |
|
|
|
+| `kind` | `String` | 分类信息 |
|
|
|
+| `customTag` | `String` | 分类信息(用户修改) |
|
|
|
+| `coverUrl` | `String` | 封面 URL |
|
|
|
+| `customCoverUrl` | `String` | 封面 URL(用户修改) |
|
|
|
+| `intro` | `String` | 简介内容 |
|
|
|
+| `customIntro` | `String` | 简介内容(用户修改) |
|
|
|
+| `charset` | `String` | 自定义字符集名称(仅本地书籍) |
|
|
|
+| `type` | `Int` | 0: text, 1: audio |
|
|
|
+| `group` | `Int` | 自定义分组索引号 |
|
|
|
+| `latestChapterTitle` | `String` | 最新章节标题 |
|
|
|
+| `latestChapterTime` | `Long` | 最新章节更新时间 |
|
|
|
+| `lastCheckTime` | `Long` | 最近一次更新书籍信息的时间 |
|
|
|
+| `lastCheckCount` | `Int` | 最近一次发现新章节数量 |
|
|
|
+| `totalChapterNum` | `Int` | 书籍目录总数 |
|
|
|
+| `durChapterTitle` | `String` | 当前章节名称 |
|
|
|
+| `durChapterIndex` | `Int` | 当前章节索引 |
|
|
|
+| `durChapterPos` | `Long` | 当前阅读进度 |
|
|
|
+| `durChapterTime` | `Long` | 最近一次阅读时间 |
|
|
|
+| `canUpdate` | `Boolean` | 刷新书架时是否更新 |
|
|
|
+| `order` | `Int` | 手动排序 |
|
|
|
+| `originOrder` | `Int` | 源排序 |
|
|
|
+| `variable` | `String?` | 自定义书籍变量 |
|
|
|
+
|
|
|
+## 5. chapter 对象
|
|
|
+
|
|
|
+| 属性 | 类型 | 说明 |
|
|
|
+|:--------------|:----------|:-----------|
|
|
|
+| `url` | `String` | 章节地址 |
|
|
|
+| `title` | `String` | 章节标题 |
|
|
|
+| `baseUrl` | `String` | 用于拼接相对 URL |
|
|
|
+| `bookUrl` | `String` | 书籍地址 |
|
|
|
+| `index` | `Int` | 章节序号 |
|
|
|
+| `resourceUrl` | `String` | 音频真实 URL |
|
|
|
+| `tag` | `String` | 标签 |
|
|
|
+| `start` | `Long` | 章节起始位置 |
|
|
|
+| `end` | `Long` | 章节终止位置 |
|
|
|
+| `variable` | `String?` | 变量 |
|
|
|
+
|
|
|
+## 6. source 对象
|
|
|
+
|
|
|
+| 方法 | 返回值 | 说明 |
|
|
|
+|:--------------------------------------|:----------|:----------|
|
|
|
+| `source.getKey()` | `String` | 获取源 URL |
|
|
|
+| `source.setVariable(variable)` | — | 设置源变量 |
|
|
|
+| `source.getVariable()` | `String?` | 获取源变量 |
|
|
|
+| `source.getLoginHeader()` | `String?` | 获取登录头 |
|
|
|
+| `source.getLoginHeaderMap().get(key)` | `String?` | 获取登录头某一键值 |
|
|
|
+| `source.putLoginHeader(header)` | — | 保存登录头 |
|
|
|
+| `source.removeLoginHeader()` | — | 清除登录头 |
|
|
|
+| `source.getLoginInfo()` | `String?` | 获取登录信息 |
|
|
|
+| `source.getLoginInfoMap().get(key)` | `String?` | 获取登录信息键值 |
|
|
|
+| `source.removeLoginInfo()` | — | 清除登录信息 |
|
|
|
+
|
|
|
+## 7. cookie 对象
|
|
|
+
|
|
|
+| 方法 | 返回值 | 说明 |
|
|
|
+|:------------------------------------|:----------|:------------|
|
|
|
+| `cookie.getCookie(url)` | `String` | 获取全部 cookie |
|
|
|
+| `cookie.getKey(url, key)` | `String?` | 获取某一键值 |
|
|
|
+| `cookie.setCookie(url, cookie)` | — | 设置 cookie |
|
|
|
+| `cookie.replaceCookie(url, cookie)` | — | 替换 cookie |
|
|
|
+| `cookie.removeCookie(url)` | — | 删除 cookie |
|
|
|
+
|
|
|
+## 8. cache 对象
|
|
|
+
|
|
|
+saveTime 单位:秒,可省略。保存至数据库和缓存文件(50MB),内容较大时请使用 `getFile` / `putFile`。
|
|
|
+
|
|
|
+| 方法 | 返回值 | 说明 |
|
|
|
+|:---------------------------------------|:----------|:--------|
|
|
|
+| `cache.put(key, value, saveTime?)` | — | 保存到数据库 |
|
|
|
+| `cache.get(key)` | `String?` | 从数据库读取 |
|
|
|
+| `cache.delete(key)` | — | 删除数据库缓存 |
|
|
|
+| `cache.putFile(key, value, saveTime?)` | — | 缓存文件内容 |
|
|
|
+| `cache.getFile(key)` | `String?` | 读取文件缓存 |
|
|
|
+| `cache.putMemory(key, value)` | — | 保存到内存 |
|
|
|
+| `cache.getFromMemory(key)` | `Any?` | 从内存读取 |
|
|
|
+| `cache.deleteMemory(key)` | — | 删除内存缓存 |
|