mirror of
https://github.com/babalae/bettergi-scripts-list.git
synced 2026-03-15 03:23:22 +08:00
活动期限/周本通知器 0.0.7 (#2736)
* feat(campaignArea): 添加每日委托OCR识别和提醒功能 - 新增每日委托识别区域坐标配置 - 实现ocrDailyCommission函数进行OCR识别处理 - 添加dailyCommissionMain主函数控制委托提醒流程 - 修改campaignAreaMain函数支持开关热键功能 - 更新main函数调用顺序和参数传递 - 增加版本号至0.0.7并更新README文档 * docs(ActivitySwitchNotice): 更新文档添加核心思维导图 - 添加整体架构流程图展示程序入口和初始化流程 - 添加活动扫描核心流程的详细状态转换图 - 添加征讨领域提醒流程的状态转换图 - 添加通知发送机制的流程图 - 添加配置解析流程的状态转换图 - 添加核心组件依赖关系的架构图 - 将原有的逻辑流程部分后移并保留基础描述
This commit is contained in:
@@ -20,7 +20,136 @@
|
||||
- ✅ 自动提醒征讨领域减半剩余次数(默认`周日`提醒可配置)
|
||||
- ✅ 支持独立通知功能(`0.0.4`版本新增 因BGI不支持WebSocket,需搭配bettergi-scripts-tools+开启JS HTTP
|
||||
权限使用)[前往bettergi-scripts-tools部署](https://github.com/Kirito520Asuna/bettergi-scripts-tools)
|
||||
## 逻辑流程
|
||||
## 核心思维导图
|
||||
### 整体架构流程图
|
||||
```mermaid
|
||||
graph TD
|
||||
A[主程序入口 main.js] --> B[初始化 init]
|
||||
B --> C[加载工具模块]
|
||||
C --> D[uid.js, ws.js, notice.js, campaignArea.js, activity.js]
|
||||
D --> E[读取 manifest.json]
|
||||
E --> F[检查是否返回主界面]
|
||||
F --> G[toMainUi]
|
||||
G --> H[执行主功能 main]
|
||||
H --> I[每日委托检查]
|
||||
I --> J[征讨领域检查]
|
||||
J --> K[活动页面扫描]
|
||||
K --> L[返回主界面]
|
||||
L --> M[程序结束]
|
||||
|
||||
```
|
||||
### 活动扫描核心流程
|
||||
```mermaid
|
||||
graph TD
|
||||
A[activityMain函数] --> B[初始化配置]
|
||||
B --> C[打开活动页面 F5]
|
||||
C --> D[滚动到页面顶部]
|
||||
D --> E[开始逐页扫描]
|
||||
E --> F[OCR识别活动列表]
|
||||
F --> G{是否有活动?}
|
||||
G -->|否| H[结束扫描]
|
||||
G -->|是| I[遍历当前页活动]
|
||||
I --> J[白名单过滤]
|
||||
J --> K{是否在白名单?}
|
||||
K -->|是| L[继续处理]
|
||||
K -->|否| M[根据关系模式判断]
|
||||
M --> N{relationship=true?}
|
||||
N -->|是| O[跳过]
|
||||
N -->|否| L[继续处理]
|
||||
L --> P[黑名单过滤]
|
||||
P --> Q{是否在黑名单?}
|
||||
Q -->|是| R[条件检测]
|
||||
Q -->|否| S[点击活动]
|
||||
R --> T{条件满足?}
|
||||
T -->|是| U[跳过]
|
||||
T -->|否| S[点击活动]
|
||||
S --> V[OCR识别剩余时间]
|
||||
V --> W[解析时间转小时]
|
||||
W --> X[应用阈值过滤]
|
||||
X --> Y[存储活动信息]
|
||||
Y --> Z[向下滚动一页]
|
||||
Z --> E
|
||||
H --> AA[过滤符合条件活动]
|
||||
AA --> BB[按剩余时间排序]
|
||||
BB --> CC[发送通知]
|
||||
CC --> DD[流程结束]
|
||||
```
|
||||
### 征讨领域提醒流程
|
||||
```mermaid
|
||||
graph TD
|
||||
A[campaignAreaMain函数] --> B[获取当前星期]
|
||||
B --> C{是否为提醒日?}
|
||||
C -->|否| D[结束函数]
|
||||
C -->|是| E[打开冒险之书 F1]
|
||||
E --> F[点击秘境坐标]
|
||||
F --> G[点击征讨领域坐标]
|
||||
G --> H[OCR识别周次数]
|
||||
H --> I{剩余次数>0?}
|
||||
I -->|否| J[结束函数]
|
||||
I -->|是| K[发送通知]
|
||||
K --> L[流程结束]
|
||||
|
||||
```
|
||||
### 通知发送机制
|
||||
```mermaid
|
||||
graph TD
|
||||
A[sendNotice函数] --> B[检查通知类型配置]
|
||||
B --> C[获取通知模式]
|
||||
C --> D{BGI通知?}
|
||||
D -->|是| E[notification.send]
|
||||
C --> F{独立通知?}
|
||||
F -->|是| G[wsUtil.sendText]
|
||||
C --> H{两者都发送?}
|
||||
H -->|是| E
|
||||
H -->|是| G
|
||||
E --> I[发送完成]
|
||||
G --> I
|
||||
I --> J[流程结束]
|
||||
```
|
||||
### 配置解析流程
|
||||
```mermaid
|
||||
graph TD
|
||||
A[配置初始化] --> B[parseWhiteActivity]
|
||||
A --> C[parseBlackActivity]
|
||||
B --> D[白名单列表解析]
|
||||
C --> E[黑名单条件解析]
|
||||
D --> F[建立whiteActivityNameList]
|
||||
E --> G[建立blackActivityMap]
|
||||
F --> H[设置relationship逻辑]
|
||||
G --> H
|
||||
H --> I[配置完成]
|
||||
```
|
||||
### 核心组件依赖关系
|
||||
```mermaid
|
||||
graph LR
|
||||
subgraph "工具模块"
|
||||
A[activity.js - 活动处理]
|
||||
B[notice.js - 通知发送]
|
||||
C[campaignArea.js - 征讨领域]
|
||||
D[ws.js - WebSocket通信]
|
||||
E[uid.js - UID识别]
|
||||
end
|
||||
|
||||
subgraph "主控模块"
|
||||
F[main.js - 主入口]
|
||||
G[settings.json - 配置]
|
||||
end
|
||||
|
||||
F --> A
|
||||
F --> B
|
||||
F --> C
|
||||
A --> B
|
||||
A --> D
|
||||
A --> E
|
||||
C --> B
|
||||
C --> E
|
||||
G -.-> A
|
||||
G -.-> B
|
||||
G -.-> C
|
||||
G -.-> D
|
||||
|
||||
```
|
||||
### 逻辑流程
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
@@ -382,6 +511,8 @@ ActivitySwitchNotice/
|
||||
|
||||
## 版本历史
|
||||
|
||||
### 0.0.7 (2026-01-19)
|
||||
- 新增每日委托提醒
|
||||
### 0.0.6 (2026-01-06)
|
||||
- **功能优化**:新增识别uid通知提醒
|
||||
实例:
|
||||
|
||||
@@ -56,7 +56,11 @@ async function toMainUi() {
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function main() {
|
||||
await campaignAreaUtil.campaignAreaMain()
|
||||
let ms = 600
|
||||
await campaignAreaUtil.dailyCommissionMain()
|
||||
await sleep(ms*2);
|
||||
await campaignAreaUtil.campaignAreaMain(false)
|
||||
await sleep(ms*2);
|
||||
await toMainUi()
|
||||
await activityUtil.activityMain()
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "活动期限/周本通知器",
|
||||
"version": "0.0.6",
|
||||
"version": "0.0.7",
|
||||
"description": "",
|
||||
"settings_ui": "settings.json",
|
||||
"main": "main.js",
|
||||
|
||||
@@ -17,10 +17,50 @@ const config = {
|
||||
}
|
||||
const ocrRegionConfig = {
|
||||
weeklyCount: {x: 809, y: 258, width: 277, height: 37},//征讨领域减半次数识别区域坐标和尺寸
|
||||
dailyCommission: {x: 630, y: 312, width: 105, height: 118},//每日委托识别区域坐标和尺寸
|
||||
}
|
||||
const xyConfig = {
|
||||
campaignArea: {x: 493, y: 537},//征讨领域坐标
|
||||
secretRealm: {x: 304, y: 448},//秘境坐标
|
||||
dailyCommission: {x: 266, y: 318},//委托坐标 x=266, y=318, width=69, height=44
|
||||
}
|
||||
|
||||
/**
|
||||
* 每日委托OCR识别函数
|
||||
* @param {Object} ocrRegion - OCR识别区域配置,默认为ocrRegionConfig.dailyCommission
|
||||
* @returns {Object} 返回包含每日委托和体力使用情况的对象
|
||||
*/
|
||||
async function ocrDailyCommission(ocrRegion = ocrRegionConfig.dailyCommission) {
|
||||
let captureRegion = captureGameRegion(); // 获取游戏区域截图
|
||||
try {
|
||||
const ocrObject = RecognitionObject.Ocr(ocrRegion.x, ocrRegion.y, ocrRegion.width, ocrRegion.height); // 创建OCR识别对象
|
||||
// ocrObject.threshold = 1.0;
|
||||
let resList = captureRegion.findMulti(ocrObject); // 在指定区域进行OCR识别
|
||||
let dailyCommission = resList[0].text?.trim();
|
||||
const lastName = dailyCommission.at(dailyCommission.length - 1);
|
||||
|
||||
if (dailyCommission.lastIndexOf('1') === 1) {
|
||||
// 0/4 被识别成==>014
|
||||
dailyCommission = dailyCommission.replace('1' + lastName, '/' + lastName)
|
||||
}
|
||||
const dailyCommissionSplit = dailyCommission.split('/');
|
||||
|
||||
// physical
|
||||
let physical = resList[1].text?.trim();
|
||||
const physicalSplit = physical.split('/');
|
||||
return {
|
||||
daily: {
|
||||
total: parseInt(dailyCommissionSplit[1]),
|
||||
use: parseInt(dailyCommissionSplit[0]),
|
||||
},
|
||||
physical: {
|
||||
total: parseInt(physicalSplit[1]),
|
||||
use: parseInt(physicalSplit[0]),
|
||||
},
|
||||
}
|
||||
} finally {
|
||||
captureRegion.dispose(); // 释放截图资源
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -31,29 +71,32 @@ const xyConfig = {
|
||||
*/
|
||||
async function ocrWeeklyCount(ocrRegion = ocrRegionConfig.weeklyCount) {
|
||||
let captureRegion = captureGameRegion(); // 获取游戏区域截图
|
||||
const ocrObject = RecognitionObject.Ocr(ocrRegion.x, ocrRegion.y, ocrRegion.width, ocrRegion.height); // 创建OCR识别对象
|
||||
// ocrObject.threshold = 1.0;
|
||||
let res = captureRegion.find(ocrObject); // 在指定区域进行OCR识别
|
||||
captureRegion.dispose(); // 释放截图资源
|
||||
if (!res.isExist()) {
|
||||
log.error(`ocrWeeklyCount not found`) // 记录错误日志
|
||||
throw new Error(`ocrWeeklyCount not found`) // 抛出错误异常
|
||||
}
|
||||
let weekJson = { // 初始化周计数JSON对象
|
||||
text: res.text,
|
||||
total: 3,
|
||||
count: 3,
|
||||
}
|
||||
let weekCountText = res.text // 获取OCR识别的文本结果
|
||||
let result = weekCountText.match(/[0-9/]+/g)?.join('') || ''; // 使用正则表达式提取数字和斜杠
|
||||
try {
|
||||
const ocrObject = RecognitionObject.Ocr(ocrRegion.x, ocrRegion.y, ocrRegion.width, ocrRegion.height); // 创建OCR识别对象
|
||||
// ocrObject.threshold = 1.0;
|
||||
let res = captureRegion.find(ocrObject); // 在指定区域进行OCR识别
|
||||
if (!res.isExist()) {
|
||||
log.error(`ocrWeeklyCount not found`) // 记录错误日志
|
||||
throw new Error(`ocrWeeklyCount not found`) // 抛出错误异常
|
||||
}
|
||||
let weekJson = { // 初始化周计数JSON对象
|
||||
text: res.text,
|
||||
total: 3,
|
||||
count: 3,
|
||||
}
|
||||
let weekCountText = res.text // 获取OCR识别的文本结果
|
||||
let result = weekCountText.match(/[0-9/]+/g)?.join('') || ''; // 使用正则表达式提取数字和斜杠
|
||||
|
||||
log.debug(`识别结果:{weekCountText}`, weekCountText) // 记录原始识别结果
|
||||
log.debug(`处理结果:{result}`, result) // 记录处理后的结果
|
||||
const numbers = result.split('/').map((item) => parseInt(item)); // 分割字符串并转换为数字数组
|
||||
weekJson.total = numbers[1] // 设置总数
|
||||
weekJson.count = numbers[0] // 设置当前计数
|
||||
log.debug(`Json:{weekJson}`, weekJson) // 记录最终JSON结果
|
||||
return weekJson // 返回处理后的周计数JSON对象
|
||||
log.debug(`识别结果:{weekCountText}`, weekCountText) // 记录原始识别结果
|
||||
log.debug(`处理结果:{result}`, result) // 记录处理后的结果
|
||||
const numbers = result.split('/').map((item) => parseInt(item)); // 分割字符串并转换为数字数组
|
||||
weekJson.total = numbers[1] // 设置总数
|
||||
weekJson.count = numbers[0] // 设置当前计数
|
||||
log.debug(`Json:{weekJson}`, weekJson) // 记录最终JSON结果
|
||||
return weekJson // 返回处理后的周计数JSON对象
|
||||
} finally {
|
||||
captureRegion.dispose(); // 释放截图资源
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,7 +125,7 @@ async function getDayOfWeek() {
|
||||
* 执行秘境征讨剩余次数提醒的主函数
|
||||
* 该函数会在每周日执行,检查秘境征讨的剩余次数并发送提醒
|
||||
*/
|
||||
async function campaignAreaMain() {
|
||||
async function campaignAreaMain(openKey = true) {
|
||||
// 获取当前星期信息
|
||||
let dayOfWeek = await getDayOfWeek();
|
||||
// 如果不是周日(0代表周日),则直接返回
|
||||
@@ -94,10 +137,12 @@ async function campaignAreaMain() {
|
||||
}
|
||||
// 设置操作间隔时间(毫秒)
|
||||
let ms = 600
|
||||
// 等待一段时间
|
||||
await sleep(ms)
|
||||
// 按下配置的热键
|
||||
await keyPress(config.campaignAreaKey)
|
||||
if (openKey) {
|
||||
// 等待一段时间
|
||||
await sleep(ms)
|
||||
// 按下配置的热键
|
||||
await keyPress(config.campaignAreaKey)
|
||||
}
|
||||
await sleep(ms * 2)
|
||||
// 点击秘境入口坐标
|
||||
await click(xyConfig.secretRealm.x, xyConfig.secretRealm.y)
|
||||
@@ -117,6 +162,41 @@ async function campaignAreaMain() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 每日委托主函数
|
||||
* @param {boolean} openKey - 是否开启热键功能,默认为true
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function dailyCommissionMain(openKey = true) {
|
||||
// 获取当前星期信息
|
||||
let dayOfWeek = await getDayOfWeek();
|
||||
// 如果不是周日(0代表周日),
|
||||
const bool = dayOfWeek.day != config.campaignAreaReminderDay;
|
||||
|
||||
// 设置操作间隔时间(毫秒)
|
||||
let ms = 600
|
||||
// 等待一段时间
|
||||
await sleep(ms)
|
||||
if (openKey || bool) {
|
||||
// 按下配置的热键
|
||||
await keyPress(config.campaignAreaKey)
|
||||
}
|
||||
await sleep(ms * 2)
|
||||
// 点击秘境入口坐标
|
||||
await click(xyConfig.dailyCommission.x, xyConfig.dailyCommission.y)
|
||||
await sleep(ms * 2)
|
||||
const re = await ocrDailyCommission();
|
||||
log.debug(`dailyCommission:{re}`, re)
|
||||
// 如果有每日未完成/领取,则记录日志并发送通知
|
||||
if (re.daily.total > re.daily.use
|
||||
|| re.physical.total > re.physical.use
|
||||
) {
|
||||
let uid = await uidUtil.ocrUID()
|
||||
await noticeUtil.sendText(`>|每日委托奖励:${re.daily.use}/${re.daily.total}\n>|原粹树脂消耗:${re.physical.use}/${re.physical.total}`, `UID:${uid}\n每日委托`)
|
||||
}
|
||||
}
|
||||
|
||||
this.campaignAreaUtil = {
|
||||
campaignAreaMain,
|
||||
dailyCommissionMain,
|
||||
}
|
||||
Reference in New Issue
Block a user