活动期限/周本通知器 0.1.1 (#3002)

* refactor(utils): 重构工具模块导入导出结构并优化功能实现

- 将各个工具模块改为ES6模块化导入导出方式
- 新增通用文本识别点击工具函数findTextAndClick
- 优化campaignArea模块中的征讨领域识别逻辑
- 统一uid识别和通知发送的调用方式
- 移除eval动态加载改用静态导入
- 更新版本号至0.1.1

* config(ActivitySwitchNotice): 更新默认显示天数设置

- 移除周一到周五的默认显示配置
- 保留周日和周六作为默认显示选项

* feat(ActivitySwitchNotice): 更新版本历史记录

- 周本提醒日升为多选功能实现
- 适配新秘境征讨UI界面调整
This commit is contained in:
云端客
2026-03-16 14:20:53 +08:00
committed by GitHub
parent 6af7f188b3
commit a754bd8d7f
11 changed files with 217 additions and 76 deletions

View File

@@ -511,6 +511,9 @@ ActivitySwitchNotice/
## 版本历史
### 0.1.1 (2026-03-16)
- 周本提醒日 升为多选
- 适配新秘境征讨UI
### 0.1.0 (2026-02-01)
- 新增 新活动通知(存储活动名称列表-历史对比)
### 0.0.8 (2026-01-22)

View File

@@ -1,7 +1,9 @@
let manifest = {};
let manifest_json = "manifest.json";
let configSettings = undefined
import {mapMission} from "./utils/mapMission"
import {dailyCommissionMain,campaignAreaMain} from "./utils/campaignArea"
import {activityMain} from "./utils/activity"
/**
* 初始化设置函数
* 从配置文件中读取设置信息并返回
@@ -87,17 +89,17 @@ async function getValueByMultiCheckboxName(name) {
return values
}
async function init() {
let utils = [
"uid",
"ws",
"notice",
"campaignArea",
"activity",
"mapMission",
]
for (let util of utils) {
eval(file.readTextSync(`utils/${util}.js`));
}
// let utils = [
// "uid",
// "ws",
// "notice",
// "campaignArea",
// "activity",
// "mapMission",
// ]
// for (let util of utils) {
// eval(file.readTextSync(`utils/${util}.js`));
// }
// manifest = JSON.parse(file.readTextSync("manifest.json"));
await initSettings();
log.debug("main 初始化完成");
@@ -151,7 +153,7 @@ async function main() {
if (mapList.length > 0) {
try {
log.info(`开始识别地图任务`)
await mapUtil.mapMission(mapList)
await mapMission(mapList)
} finally {
await toMainUi()
}
@@ -160,15 +162,15 @@ async function main() {
let openKey = true
try {
await campaignAreaUtil.dailyCommissionMain(openKey)
await dailyCommissionMain(openKey)
await sleep(ms * 2);
openKey = false
} catch (e) {
await toMainUi()
throw e
}
await campaignAreaUtil.campaignAreaMain(openKey)
await campaignAreaMain(openKey)
await sleep(ms * 2);
await toMainUi()
await activityUtil.activityMain(settings.newActivityNotice)
await activityMain(settings.newActivityNotice)
}

View File

@@ -1,6 +1,6 @@
{
"name": "活动期限/周本通知器",
"version": "0.1.0",
"version": "0.1.1",
"description": "",
"settings_ui": "settings.json",
"main": "main.js",

View File

@@ -75,19 +75,22 @@
"type": "separator"
},
{
"name": "campaignAreaReminderDay",
"type": "select",
"label": "周本提醒日(0-6,0=周日,1=周一,2=周二,3=周三,4=周四,5=周五,6=周六)",
"label": "周本提醒日",
"name": "campaignAreaReminderDays",
"type": "multi-checkbox",
"options": [
"0",
"1",
"2",
"3",
"4",
"5",
"6"
"周一",
"周二",
"周三",
"周四",
"周五",
"周六",
"周日"
],
"default": "0"
"default": [
"周六",
"周日"]
},
{
"name": "campaignAreaKey",

View File

@@ -1,3 +1,5 @@
import {sendNotice,sendText} from "./notice";
import {ocrUID} from "./uid";
const config_name = "config"
const json_path = {
activity: `${config_name}/activity.json`
@@ -445,11 +447,11 @@ async function init() {
/**
* 活动主函数:扫描所有活动页面,识别剩余时间,最后统一发送通知
*/
async function activityMain(newActivityNotice = true) {
async function activityMain(newActivityNotice = true) {
await init();
const ms = 1000;
await sleep(ms);
let uid = await uidUtil.ocrUID()
let uid = await ocrUID()
let activityData=[]
let activitySetLast = new Set()
try {
@@ -724,7 +726,7 @@ async function activityMain(newActivityNotice = true) {
blackText += `==>{已开启黑名单: ${blackAllText.join("|")}}<==`
}
await noticeUtil.sendNotice(activityMapFilter, `UID:${uid}\n原神活动剩余时间提醒(仅显示 ${titleKey} 的活动)${blackText}`);
await sendNotice(activityMapFilter, `UID:${uid}\n原神活动剩余时间提醒(仅显示 ${titleKey} 的活动)${blackText}`);
} else {
log.warn("不存在符合条件的活动,未发送通知");
}
@@ -737,7 +739,7 @@ async function activityMain(newActivityNotice = true) {
try {
if(activitySetLast.size > 0){
log.info("新增活动: {newActivities}", newActivities);
await noticeUtil.sendText(newActivities.join("\n"), `UID:${uid}\n新增活动`);
await sendText(newActivities.join("\n"), `UID:${uid}\n新增活动`);
}
activityData=activityData.filter(item => item.uid !== uid)
activityData.push(currentActivityJson)
@@ -762,8 +764,9 @@ async function activityMain(newActivityNotice = true) {
}
}
this.activityUtil = {
// config,
activityMain,
// OcrRemainingTime,
}
// this.activityUtil = {
// // config,
// activityMain,
// // OcrRemainingTime,
// }
export {activityMain}

View File

@@ -1,3 +1,6 @@
import {findTextAndClick,getDayOfWeek} from "./tool";
import {sendText} from "./notice";
import {ocrUID} from "./uid";
function settingsParseInt(str, defaultValue) {
try {
return str ? parseInt('' + str) : defaultValue;
@@ -13,10 +16,12 @@ function settingsParseStr(str, defaultValue) {
const config = {
campaignAreaKey: settingsParseStr(settings.campaignAreaKey, 'F1'),
campaignAreaReminderDay: settingsParseInt(settings.campaignAreaReminderDay, 0),//征讨领域提醒日
// campaignAreaReminderDay: settingsParseInt(settings.campaignAreaReminderDay, 0),//征讨领域提醒日
campaignAreaReminderDays: Array.from(settings.campaignAreaReminderDays)
}
const ocrRegionConfig = {
weeklyCount: {x: 809, y: 258, width: 277, height: 37},//征讨领域减半次数识别区域坐标和尺寸
campaignArea:{x:433, y:215, width:306, height:697},//征讨领域识别区域
dailyCommission: {x: 630, y: 312, width: 105, height: 118},//每日委托识别区域坐标和尺寸
}
const xyConfig = {
@@ -99,27 +104,31 @@ async function ocrWeeklyCount(ocrRegion = ocrRegionConfig.weeklyCount) {
}
}
/**
* 获取当前日期的星期信息
* @returns {Object} 返回包含星期数字和星期名称的对象
*/
async function getDayOfWeek() {
// 获取当前日期对象
const today = new Date();
// 获取当前日期是星期几0代表星期日1代表星期一以此类推
const day = today.getDay();
// 创建包含星期名称的数组
const weekDays = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
let weekDay = `${weekDays[day]}`;
log.debug(`今天是[{day}]`, day)
log.debug(`今天是[{weekDays}]`, weekDay)
// 返回包含星期数字和对应星期名称的对象
return {
day: day,
dayOfWeek: weekDay
}
}
// /**
// * 获取当前日期的星期信息
// * @param {boolean} [calibrationGameRefreshTime=true] 是否进行游戏刷新时间校准
// * @returns {Object} 返回包含星期数字和星期名称的对象
// */
// async function getDayOfWeek(calibrationGameRefreshTime = true) {
// // 获取当前日期对象
// let today = new Date();//4点刷新 所以要减去4小时
// if (calibrationGameRefreshTime) {
// today.setHours(today.getHours() - 4); // 减去 4 小
// }
// // 获取当前日期是星期几0代表星期日1代表星期一以此类推
// const day = today.getDay();
// // 创建包含星期名称的数组
// const weekDays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
// let weekDay = `${weekDays[day]}`;
//
// log.debug(`今天是[{day}]`, day)
// log.debug(`今天是[{weekDays}]`, weekDay)
// // 返回包含星期数字和对应星期名称的对象
// return {
// day: day,
// dayOfWeek: weekDay
// }
// }
/**
* 执行秘境征讨剩余次数提醒的主函数
@@ -129,7 +138,10 @@ async function campaignAreaMain(openKey = true) {
// 获取当前星期信息
let dayOfWeek = await getDayOfWeek();
// 如果不是周日(0代表周日),则直接返回
const bool = dayOfWeek.day != config.campaignAreaReminderDay;
// const bool = dayOfWeek.day != config.campaignAreaReminderDay;
log.info(`秘境征讨提醒日:{0}`,JSON.stringify(config.campaignAreaReminderDays))
const bool =!config.campaignAreaReminderDays.includes(dayOfWeek.dayOfWeek)
// log.info(`bool={0}`,bool)
// 记录开始执行秘境征讨提醒的日志
log.info(`[{dayOfWeek.dayOfWeek}]${bool ? "跳过" : "开始"}执行秘境征讨剩余次数提醒`, dayOfWeek.dayOfWeek)
if (bool) {
@@ -148,16 +160,21 @@ async function campaignAreaMain(openKey = true) {
await click(xyConfig.secretRealm.x, xyConfig.secretRealm.y)
await sleep(ms * 2)
// 点击秘境征讨坐标
await click(xyConfig.campaignArea.x, xyConfig.campaignArea.y)
// await click(xyConfig.campaignArea.x, xyConfig.campaignArea.y)
const find = await findTextAndClick("征讨领域");
if (find===null){
log.warn("未找到征讨领域")
return
}
await sleep(ms * 2)
// 使用OCR识别本周秘境征讨剩余次数
let weekJson = await ocrWeeklyCount();
// 如果有剩余次数,则记录日志并发送通知
if (weekJson.count > 0) {
let uid = await uidUtil.ocrUID()
let uid = await ocrUID()
log.info(`本周剩余消耗减半次数:${weekJson.count}`)
await noticeUtil.sendText(`>|本周剩余消耗减半次数:${weekJson.count}`, `UID:${uid}\n秘境征讨`)
await sendText(`>|本周剩余消耗减半次数:${weekJson.count}`, `UID:${uid}\n秘境征讨`)
}
}
@@ -171,8 +188,8 @@ async function dailyCommissionMain(openKey = true) {
// 获取当前星期信息
let dayOfWeek = await getDayOfWeek();
// 如果不是周日(0代表周日)
const bool = dayOfWeek.day != config.campaignAreaReminderDay;
// const bool = dayOfWeek.day != config.campaignAreaReminderDay;
const bool =config.campaignAreaReminderDays.includes(dayOfWeek.dayOfWeek)
// 设置操作间隔时间(毫秒)
let ms = 600
// 等待一段时间
@@ -191,12 +208,17 @@ async function dailyCommissionMain(openKey = true) {
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每日委托`)
let uid = await ocrUID()
await sendText(`>|每日委托奖励:${re.daily.use}/${re.daily.total}\n>|原粹树脂消耗:${re.physical.use}/${re.physical.total}`, `UID:${uid}\n每日委托`)
}
}
this.campaignAreaUtil = {
// this.campaignAreaUtil = {
// campaignAreaMain,
// dailyCommissionMain,
// }
export {
campaignAreaMain,
dailyCommissionMain,
}

View File

@@ -1,3 +1,5 @@
import {sendText} from "./notice";
import {ocrUID} from "./uid";
const ocrRegionConfig = {
mapMission: {x: 6, y: 8, width: 395, height: 977},//地图任务识别区域坐标和尺寸
}
@@ -87,13 +89,19 @@ async function mapMission(list = [], toOpenMap = true) {
log.warn(`未识别到地图任务`)
return
}
const uid = await uidUtil.ocrUID()
const uid = await ocrUID()
let text = ""
keyJsonList.forEach(item => text += "|< " + item.text + " >\n")
await noticeUtil.sendText(text, `UID:${uid}\n地图任务`)
await sendText(text, `UID:${uid}\n地图任务`)
}
this.mapUtil = {
// this.mapUtil = {
// mapMission,
// ocrMapMission,
// openMap,
// }
export {
mapMission,
ocrMapMission,
openMap,

View File

@@ -1,3 +1,4 @@
import {sendText as wsSendText} from "./ws"
const NoticeType = Object.freeze({
bgi: 'bgi',//BGI通知
independence: 'independence',//独立通知
@@ -44,7 +45,7 @@ async function sendNotice(map = new Map(), title, noNotice = false) {
for (let noticeElement of configNotice.noticeList) {
switch (noticeElement.type) {
case NoticeType.independence:
await wsUtil.sendText(noticeText)
await wsSendText(noticeText)
break
case NoticeType.bgi:
notification.send(noticeText)
@@ -74,7 +75,7 @@ async function sendText(noticeText, title, noNotice = false) {
for (let noticeElement of configNotice.noticeList) {
switch (noticeElement.type) {
case NoticeType.independence:
await wsUtil.sendText(text)
await wsSendText(text)
break
case NoticeType.bgi:
notification.send(text)
@@ -84,7 +85,12 @@ async function sendText(noticeText, title, noNotice = false) {
return
}
this.noticeUtil = {
// this.noticeUtil = {
// sendNotice,
// sendText,
// }
export {
sendNotice,
sendText,
}

View File

@@ -0,0 +1,82 @@
/**
* 通用找文本并点击OCR
* @param {string} text 目标文本(单个文本)
* @param {number} [x=0] OCR 区域左上角 X
* @param {number} [y=0] OCR 区域左上角 Y
* @param {number} [w=1920] OCR 区域宽度
* @param {number} [h=1080] OCR 区域高度
* @param {number} [attempts=5] OCR 尝试次数
* @param {number} [interval=50] 每次 OCR 之间的等待间隔(毫秒)
* @param {number} [preClickDelay=50] 点击前等待时间(毫秒)
* @param {number} [postClickDelay=50] 点击后等待时间(毫秒)
*
* @returns
* - RecognitionResult | null
*/
async function findTextAndClick(
text,
x = 0,
y = 0,
w = 1920,
h = 1080,
attempts = 5,
interval = 50,
preClickDelay = 50,
postClickDelay = 50
) {
const keyword = text.toLowerCase();
for (let i = 0; i < attempts; i++) {
const gameRegion = captureGameRegion();
try {
const ro = RecognitionObject.Ocr(x, y, w, h);
const results = gameRegion.findMulti(ro);
for (let j = 0; j < results.count; j++) {
const res = results[j];
if (
res.isExist() &&
res.text &&
res.text.toLowerCase().includes(keyword)
) {
await sleep(preClickDelay);
res.click();
await sleep(postClickDelay);
return res;
}
}
} finally {
gameRegion.dispose();
}
await sleep(interval);
}
return null;
}
/**
* 获取当前日期的星期信息
* @param {boolean} [calibrationGameRefreshTime=true] 是否进行游戏刷新时间校准
* @returns {Object} 返回包含星期数字和星期名称的对象
*/
async function getDayOfWeek(calibrationGameRefreshTime = true) {
// 获取当前日期对象
let today = new Date();//4点刷新 所以要减去4小时
if (calibrationGameRefreshTime) {
today.setHours(today.getHours() - 4); // 减去 4 小
}
// 获取当前日期是星期几0代表星期日1代表星期一以此类推
const day = today.getDay();
// 创建包含星期名称的数组
const weekDays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
let weekDay = `${weekDays[day]}`;
log.debug(`今天是[{day}]`, day)
log.debug(`今天是[{weekDays}]`, weekDay)
// 返回包含星期数字和对应星期名称的对象
return {
day: day,
dayOfWeek: weekDay
}
}
export { findTextAndClick,getDayOfWeek}

View File

@@ -135,7 +135,15 @@ async function check() {
return check
}
this.uidUtil = {
// this.uidUtil = {
// toMainUi,
// isInMainUI,
// checkUid,
// ocrUID,
// check,
// compareUid,
// }
export {
toMainUi,
isInMainUI,
checkUid,

View File

@@ -159,7 +159,11 @@ async function sendText(text) {
await send(wsProxyUrl, wsUrl, ws_token, action, group_id, user_id, textList, atList)
}
this.wsUtil = {
// this.wsUtil = {
// send,
// sendText
// }
export {
send,
sendText
}