Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 22 additions & 7 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ jobs:
- uses: actions/checkout@v5
- name: Test controller
run: bash tests/controller_test.sh
- name: Test template rendering
run: bash tests/template_test.sh
- name: Validate release tag
if: startsWith(github.ref, 'refs/tags/v')
run: |
version="$(sed -n 's/^versionName=//p' template.properties)"
test "$GITHUB_REF_NAME" = "v$version" || {
echo "Tag $GITHUB_REF_NAME does not match template version v$version" >&2
exit 1
}

binaries:
needs: test
Expand Down Expand Up @@ -50,7 +60,7 @@ jobs:
name: oxidebot-binary-${{ matrix.target }}
if-no-files-found: error
retention-days: 1
path: runner/target/${{ matrix.target }}/release/my_oxidebot
path: runner/target/${{ matrix.target }}/release/oxidebot_app

manager:
needs: test
Expand All @@ -68,9 +78,10 @@ jobs:
working-directory: manager-app
run: |
./gradlew assembleDebug
version="$(sed -n 's/^version=//p' ../module.prop)"
version="$(sed -n 's/^versionName=//p' ../template.properties)"
module_id="$(sed -n 's/^moduleId=//p' ../template.properties)"
mkdir -p dist
cp app/build/outputs/apk/debug/app-debug.apk "dist/OxideBot-Manager-${version}-debug.apk"
cp app/build/outputs/apk/debug/app-debug.apk "dist/${module_id}-manager-v${version}-debug.apk"
- uses: actions/upload-artifact@v7
with:
name: oxidebot-manager
Expand Down Expand Up @@ -103,13 +114,15 @@ jobs:
- name: Build module ZIP
run: BINARY_DIR=runner/target bash build.sh
- name: Verify module ZIP
run: unzip -t build/oxidebot-root-*.zip
run: unzip -t build/*.zip
- uses: actions/upload-artifact@v7
with:
name: oxidebot-module
if-no-files-found: error
retention-days: 1
path: build/*.zip
path: |
build/*.zip
build/update.json

bundle:
needs: [module, manager]
Expand Down Expand Up @@ -165,9 +178,10 @@ jobs:
OXIDEBOT_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
run: |
./gradlew assembleRelease
version="$(sed -n 's/^version=//p' ../module.prop)"
version="$(sed -n 's/^versionName=//p' ../template.properties)"
module_id="$(sed -n 's/^moduleId=//p' ../template.properties)"
mkdir -p dist
cp app/build/outputs/apk/release/app-release.apk "dist/OxideBot-Manager-${version}.apk"
cp app/build/outputs/apk/release/app-release.apk "dist/${module_id}-manager-v${version}.apk"
- uses: actions/upload-artifact@v7
with:
name: oxidebot-manager-release
Expand All @@ -194,4 +208,5 @@ jobs:
uses: softprops/action-gh-release@v2
with:
fail_on_unmatched_files: true
generate_release_notes: true
files: dist/*
9 changes: 3 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
# 更新记录
# Changelog

## v1.0.0
## 0.1.0

- 全新模块架构,统一支持 Magisk、KernelSU、SukiSU Ultra 与 APatch。
- 新增响应式模块 WebUI 和配套原生 Android 管理 App。
- 新增安全的环境变量编辑、完整状态展示、日志查看与服务动作按钮。
- 新增多 ABI 打包、进程 supervisor、日志轮换和异常退出自动恢复。
- Replace this entry with the first release notes for your own OxideBot application.
244 changes: 176 additions & 68 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,111 +1,219 @@
# OxideBot for Root
# OxideBot Root App Template

面向现代 Android Root 生态重新设计的 OxideBot 后台运行模块。一个安装包支持
Magisk、KernelSU、SukiSU Ultra 和 APatch;同时提供模块 WebUI、Root 管理器中的动作按钮、
命令行控制器,以及使用同一界面的原生 Android 管理 App。
这是一个用于创建“自己的 OxideBot Android Root 应用”的 GitHub Template Repository,
不是一个预先实现好业务功能的通用机器人。

## 功能
OxideBot 本身是 Rust Bot 框架。你需要选择 Bot 适配器、编写 Handler,并把自己的应用代码
放进 `runner/`。本模板负责把这份代码交叉编译成 Android ELF,再打包成兼容 Magisk、
KernelSU、SukiSU Ultra 和 APatch 的模块,同时生成模块 WebUI 和配套 Android 管理 App。

- 支持 `arm64-v8a`、`armeabi-v7a`、`x86_64`、`x86` 四种 Android ABI。
- 开机延迟启动和轻量 supervisor;进程异常退出后带退避策略自动恢复。
- 启动、停止、重启、启用/关闭开机启动、实时状态、运行时长和日志查看。
- 现代响应式 WebUI,可直接在 KernelSU、SukiSU Ultra、APatch 等兼容管理器中打开。
- 原生 Android 管理 App,为 Magisk 等场景提供完整图形界面;App 只允许调用模块控制器。
- 环境变量使用持久化的 `env.conf`,模块更新不会覆盖 Token、数据库或日志。
- 配置按纯 `KEY=value` 解析,不执行 shell 命令替换;默认权限为 `0600`。
- 日志达到 2 MiB 时轮换,保留三份历史日志。
## 从模板开始

## 安装和首次运行

1. 从 Releases 下载 `oxidebot-root-v*.zip`,在 Root 管理器中选择“从本地安装”。
2. 重启 Android。
3. KernelSU / SukiSU / APatch 用户可在模块卡片中打开 WebUI;其他用户安装配套 APK。
4. 在「配置」页填写:
1. 点击 GitHub 仓库页面上的 **Use this template**。
2. 创建你自己的仓库,不要直接 fork 后沿用本模板的模块 ID。
3. 首先编辑 [`template.properties`](template.properties):

```properties
TELEGRAM_BOT_TOKEN=123456:your-token
RUST_LOG=info
moduleId=my_oxidebot
moduleName=My OxideBot
moduleAuthor=your-github-name
moduleDescription=My custom OxideBot application for Android Root
versionName=0.1.0
versionCode=1
applicationId=dev.example.myoxidebot
appName=My OxideBot
requiredEnv=TELEGRAM_BOT_TOKEN
repository=your-name/your-repository
```

5. 保存后回到首页点击「启动服务」。
4. 编辑 `runner/Cargo.toml`,加入你的 Bot 适配器、Handler 或业务 crate。
5. 用你自己的实现替换 `runner/src/example_handler.rs`,并在 `runner/src/main.rs` 注册。
6. 推送到 `main`。GitHub Actions 会构建四种 ABI、模块 ZIP 和测试 APK。
7. 测试完成并配置正式 Android 签名后,推送与 `versionName` 一致的 `v*` tag 发布。

## 模板配置

| 配置 | 用途 | 约束 |
|---|---|---|
| `moduleId` | Root 模块 ID、数据目录名 | 字母开头,只使用字母、数字、`.`、`_`、`-` |
| `moduleName` | Root 管理器和 WebUI 显示名称 | 建议保持简短、唯一 |
| `moduleAuthor` | `module.prop` 作者 | GitHub 用户名或组织名 |
| `moduleDescription` | 模块简介 | 不要换行 |
| `versionName` | 模块、APK 和 Release 版本 | 推荐 SemVer,例如 `0.1.0` |
| `versionCode` | Android/Root 数字版本 | 每次发布递增的整数 |
| `applicationId` | Android APK 唯一包名 | 例如 `io.github.alice.mybot` |
| `appName` | Android 桌面名称 | 可以与 `moduleName` 相同 |
| `requiredEnv` | 启动前必须非空的环境变量 | 逗号分隔,例如 `BOT_TOKEN,API_KEY`;可留空 |
| `repository` | 本地构建生成的 Release URL | `owner/repository`;Actions 中会自动使用当前仓库 |

构建时会根据这些值生成 `module.prop`、`update.json`、APK BuildConfig、WebUI 控制器路径和
独立数据目录。不要只修改根目录里的示例 `module.prop`;发布产物以
`template.properties` 为准。

## 示例应用

模板内的 runner 只是最小示例:

- 使用 `telegram_bot_oxidebot` 接收 Telegram 事件;
- 从 `TELEGRAM_BOT_TOKEN` 环境变量读取 Token;
- `/start` 返回模板说明;
- `/echo <text>` 回复输入内容。

入口在 [`runner/src/main.rs`](runner/src/main.rs),示例 Handler 在
[`runner/src/example_handler.rs`](runner/src/example_handler.rs)。

典型的应用接线方式是:

```rust
oxidebot::OxideBotManager::new()
.bot(my_bot_adapter)
.await
.filter(MyFilter)
.handler(MyHandler::new(...).await?)
.run_block()
.await
```

数据与模块本体分离:
你可以:

```text
/data/adb/modules/oxidebot_root/ 模块、控制器和当前 ABI 二进制
/data/adb/oxidebot/env.conf 环境变量(0600)
/data/adb/oxidebot/data/ OxideBot 工作目录与数据库
/data/adb/oxidebot/logs/oxidebot.log 当前日志
/data/adb/oxidebot/run/ PID 和运行状态
```
- 换成 `onebot_v11_oxidebot` 或其他 Bot 适配器;
- 引入自己发布的 Handler crate;
- 直接在 `runner/src/` 编写业务模块;
- 注册多个 Bot、Filter、Event Handler 和 Active Handler;
- 从 `env.conf` 读取数据库地址、Token、API Key 或其他运行配置。

卸载模块默认保留 `/data/adb/oxidebot`,便于重装。若确实需要随卸载一并清除,在卸载前把
`REMOVE_DATA_ON_UNINSTALL=1` 写入 `env.conf`。该操作不可恢复。
请不要把真实 Token、Cookie 或 API Key 写进 Rust 源码、`template.properties` 或 GitHub
仓库。运行密钥应在安装后的 WebUI/App 中配置。

## 控制器
## Android 上的环境变量

所有 UI 都通过同一个控制器工作,也可以直接在终端中使用:
安装后,在 Root 管理器 WebUI 或配套 App 中编辑:

```sh
su -c /data/adb/modules/oxidebot_root/scripts/oxidebotctl status
su -c /data/adb/modules/oxidebot_root/scripts/oxidebotctl start
su -c /data/adb/modules/oxidebot_root/scripts/oxidebotctl stop
su -c /data/adb/modules/oxidebot_root/scripts/oxidebotctl restart
su -c /data/adb/modules/oxidebot_root/scripts/oxidebotctl logs 200
```properties
TELEGRAM_BOT_TOKEN=123456:your-token
RUST_LOG=info
MY_API_URL=https://example.com/api
MY_API_KEY=secret
```

模块管理器里的动作按钮会在“启用并启动”和“停止并关闭自动启动”之间切换。
所有 `KEY=value` 会原样作为环境变量传给 runner。配置文件不是 Shell 脚本,不会执行
`$()` 或反引号。

每个模板项目使用独立目录:

```text
/data/adb/modules/<moduleId>/ 模块、WebUI、控制器和 Android ELF
/data/adb/<moduleId>/env.conf 环境变量(0600)
/data/adb/<moduleId>/data/ 应用工作目录和数据库
/data/adb/<moduleId>/logs/ 日志和轮换日志
/data/adb/<moduleId>/run/ PID、锁和运行状态
```

## 本地构建

仓库内的 `runner` 是可公开构建的 OxideBot 运行程序入口。先构建它的四种 Android 目标:
需要 Rust 1.97、Android SDK、Android NDK 29 和 Java 17。

```sh
bash runner/scripts/build-android.sh
bash build.sh
```

默认从 `runner/target` 打包,也可以用 `BINARY_DIR=/path/to/target bash build.sh` 指定其他
二进制目录。模块产物位于
`build/oxidebot-root-v*.zip`。

构建原生管理 App:

```sh
cd manager-app
./gradlew assembleDebug
```

WebUI 会在 Android 构建前自动同步到 App assets,因此两种入口不会产生两套交互逻辑。
也可以指定已有的 Android ELF 目录:

## 验证
```sh
BINARY_DIR=/path/to/target bash build.sh
```

控制器测试不需要 Android 或 Root:
`build.sh` 会生成:

```sh
bash tests/controller_test.sh
```text
build/<moduleId>-v<versionName>.zip
build/update.json
```

项目的发布工作流会构建四种 ABI、运行控制器测试、生成模块 ZIP 和可侧载的管理 APK。
## CI

每次 `main` push、Pull Request 或手动运行都会执行:

1. 控制器、配置安全和模板渲染测试;
2. 四种 Android ABI 并行编译;
3. Android Debug 管理 App 构建;
4. 模块 ZIP 打包和完整性检查;
5. 生成包含模块、`update.json` 和 Debug APK 的 `oxidebot-root` artifact。

普通 `main`/PR 构建使用 Android Debug 签名,仅作为 Actions artifact 提供测试。创建 `v*`
tag 前,需要在 GitHub Actions 配置以下仓库 Secrets,CD 才会构建可长期升级的 Release APK:
四种目标是:

- `ANDROID_SIGNING_KEY_BASE64`:JKS/PKCS12 文件的 Base64 内容
- `aarch64-linux-android`
- `armv7-linux-androideabi`
- `x86_64-linux-android`
- `i686-linux-android`

普通 CI 不会创建 GitHub Release。

## 配置正式发布

正式 APK 必须使用你自己长期保存的签名证书。在仓库的
**Settings → Secrets and variables → Actions** 中配置:

- `ANDROID_SIGNING_KEY_BASE64`
- `ANDROID_KEYSTORE_PASSWORD`
- `ANDROID_KEY_ALIAS`
- `ANDROID_KEY_PASSWORD`

任一签名 Secret 缺失时,tag 构建会明确失败,不会把 Debug APK 发布为正式版本。
例如:

```sh
base64 < my-release.jks | gh secret set ANDROID_SIGNING_KEY_BASE64
gh secret set ANDROID_KEYSTORE_PASSWORD
gh secret set ANDROID_KEY_ALIAS
gh secret set ANDROID_KEY_PASSWORD
```

然后确保 `template.properties` 中的 `versionName`、`versionCode` 已更新并提交,再发布:

```sh
git tag -a v0.1.0 -m "v0.1.0"
git push origin v0.1.0
```

tag 必须严格等于 `v<versionName>`。CD 会发布:

- `<moduleId>-v<versionName>.zip`
- `<moduleId>-manager-v<versionName>.apk`
- `update.json`

缺少签名 Secret 或 tag/版本不一致时,发布会安全失败,不会上传 Debug APK。

## 运行架构

```text
你的 Rust 代码 + OxideBot 框架 + Bot/Handler crates
│
▼
Android ELF runner
│
oxidebotctl / supervisor
┌───────┴────────┐
▼ ▼
Root 管理器模块 WebUI Android 管理 App
```

WebUI 是 KernelSU、SukiSU Ultra、APatch 的标准模块入口;Android App 为 Magisk 等场景提供
图形入口。两者复用同一套离线页面,但最终都只控制你的 runner,不包含远程 Web 服务。

## 安全说明
## Root 兼容性

- 不要把 Telegram Token 写入源码、Issue 或公开日志。
- 原生 App 的 JavaScript Root 桥只接受 `oxidebotctl` 的固定命令集合。
- 原生 App 不申请网络权限,也禁止 WebView 离开内置页面。
- WebUI 不依赖远程 CDN,不会把配置发送到网络。
- Root 环境本身拥有完整设备权限,请只安装来自可信 Release、且校验过的构建产物。
- Magisk
- KernelSU
- SukiSU Ultra
- APatch
- Android API 24+
- `arm64-v8a`、`armeabi-v7a`、`x86_64`、`x86`

## 开源许可证
## 许可证

本仓库使用 `GPL-3.0-only`。OxideBot 核心及适配器各自的许可证与来源见其上游仓库。
模板本身使用 `GPL-3.0-only`。你加入的 OxideBot 适配器、Handler 和业务依赖可能有不同的
许可证;发布应用前请检查并遵守所有依赖的许可证要求。
Loading
Loading