From c94975b85ea72b4c1f204201d2b773dfb9224242 Mon Sep 17 00:00:00 2001 From: Patrick-Ze <19711799+Patrick-Ze@users.noreply.github.com> Date: Sat, 12 Jul 2025 11:31:10 +0800 Subject: [PATCH] =?UTF-8?q?js:=20CD-Aware-AutoGather:=20=E6=89=AB=E6=8F=8F?= =?UTF-8?q?=E5=BE=85=E5=A4=84=E7=90=86=E7=9A=84=E6=9D=90=E6=96=99=E6=97=B6?= =?UTF-8?q?=E8=B7=B3=E8=BF=87=E7=A9=BA=E6=96=87=E4=BB=B6=E5=A4=B9=20(#1336?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- repo/js/CD-Aware-AutoGather/README.md | 2 +- repo/js/CD-Aware-AutoGather/lib/lib.js | 43 +++++++++++++++---- repo/js/CD-Aware-AutoGather/main.js | 13 ++++-- repo/js/CD-Aware-AutoGather/manifest.json | 2 +- repo/js/CD-Aware-AutoGather/settings.json | 20 ++++----- .../settings.template.json | 20 ++++----- .../README.md | 2 + 7 files changed, 67 insertions(+), 35 deletions(-) diff --git a/repo/js/CD-Aware-AutoGather/README.md b/repo/js/CD-Aware-AutoGather/README.md index a5bf6dda..aeca2a6d 100644 --- a/repo/js/CD-Aware-AutoGather/README.md +++ b/repo/js/CD-Aware-AutoGather/README.md @@ -28,11 +28,11 @@ | 选项 | 说明 | | ---- | ---- | +| `地图追踪`中已订阅的任务目录的处理方式 | 有三种处理方式:
- `每次自动扫描,并采集扫描到的所有材料`
- `手动扫描,并采集扫描到的所有材料`
- `手动扫描,只采集已勾选的材料`
`自动扫描`会在每次执行采集前扫描当前已订阅的任务目录,`手动扫描`则是手动将运行模式切换到扫描模式执行脚本进行扫描。
`采集所有`会无视后面的每个材料⬇️是否选中,`采集已勾选`则是根据勾选的列表进行采集 | | 设置首选队伍名称 | 执行采集任务前切换到指定的队伍,未设置则不切换。 | | 设置备选队伍名称 | 首选队伍缺少对应的采集角色时使用。
两支队伍的名称不要存在包含关系,例如不能一支叫`特产`一支叫`特产备选` | | 停止运行时间 | 超过此时间后,停止后续的任务(会等待正在运行的那条json路线结束)。 | | 我肝的账号不止一个 | 如果你有多个账号,可以选中此选项,选中后将分账号维护对应的材料刷新时间。 | -| `地图追踪`中已订阅的任务目录的处理方式 | 有三种处理方式:
- `每次自动扫描,并采集扫描到的所有材料`
- `手动扫描,并采集扫描到的所有材料`
- `手动扫描,只采集已勾选的材料`
`自动扫描`会在每次执行采集前扫描当前已订阅的任务目录,`手动扫描`则是手动将运行模式切换到扫描模式执行脚本进行扫描。
`采集所有`会无视后面的每个材料⬇️是否选中,`采集已勾选`则是根据勾选的列表进行采集 | | 即使同一种材料有多个版本的路线,也全都执行采集 | 如果某种材料选中了多个版本的路线(常见于不同作者),默认只会执行第一个。勾选此选项后会每个版本都执行,可能造成部分点位重复(空跑)。 | | `↓` 地方特产\稻妻\绯樱绣球 | 根据你订阅的路径追踪任务数量,这里将会显示相应个数的选择框。
勾选后将执行你选中的条目的采集任务。
Tip: `↓`符号是在提示你应该勾选文本下面的选择框 | diff --git a/repo/js/CD-Aware-AutoGather/lib/lib.js b/repo/js/CD-Aware-AutoGather/lib/lib.js index a1ccb9bc..97816f7a 100644 --- a/repo/js/CD-Aware-AutoGather/lib/lib.js +++ b/repo/js/CD-Aware-AutoGather/lib/lib.js @@ -7,17 +7,16 @@ let scriptContext = { scriptStartTime: new Date(), - version: "1.0" + version: "1.1", }; /** - * 将 Date 对象格式化为 ISO 8601 字符串,包含本地时区(如:2020-09-28T20:20:20.999+08:00) + * 将 Date 对象格式化为 ISO 8601 字符串,包含本地时区(如:2020-09-28T20:20:20+08:00) * @param {Date} date - 要格式化的日期对象 * @returns {string} 格式化后的字符串 */ function formatDateTime(date) { const pad = (n) => n.toString().padStart(2, "0"); - const padMs = (n) => n.toString().padStart(3, "0"); const year = date.getFullYear(); const month = pad(date.getMonth() + 1); @@ -25,7 +24,6 @@ function formatDateTime(date) { const hour = pad(date.getHours()); const minute = pad(date.getMinutes()); const second = pad(date.getSeconds()); - const ms = padMs(date.getMilliseconds()); // 获取时区偏移(分钟),转换成±HH:MM const offset = -date.getTimezoneOffset(); @@ -33,7 +31,7 @@ function formatDateTime(date) { const offsetHour = pad(Math.floor(Math.abs(offset) / 60)); const offsetMin = pad(Math.abs(offset) % 60); - return `${year}-${month}-${day}T${hour}:${minute}:${second}.${ms}${sign}${offsetHour}:${offsetMin}`; + return `${year}-${month}-${day}T${hour}:${minute}:${second}${sign}${offsetHour}:${offsetMin}`; } /** @@ -329,9 +327,10 @@ async function switchPartySafely(partyName) { * * @async * @param {*} multiAccount 是否使用OCR区分多个账号(可以传入一个设置项) + * @param {boolean} mask 对UID进行掩码,只保留开头和结尾 * @returns {Promise} 当前账号的UID,如果不区分多账号或OCR失败则返回"默认账号"。 */ -async function getGameAccount(multiAccount = false) { +async function getGameAccount(multiAccount = false, mask = true) { let account = "默认账号"; if (!multiAccount) { return account; @@ -352,6 +351,10 @@ async function getGameAccount(multiAccount = false) { const match = text.match(/\d+/); if (match) { account = match[0]; + if (mask) { + // 避免完整UID出现在log中造成意外暴露 + account = account.replace(/\d*(\d{4})\d{4}/, (match, group1) => match.replace(group1, "xxxx")); + } } break; } @@ -397,7 +400,7 @@ function getScriptName() { * @returns {string} - 文件名。 */ function basename(filePath) { - const lastSlashIndex = filePath.lastIndexOf('\\'); // 或者使用 '/' + const lastSlashIndex = filePath.lastIndexOf("\\"); // 或者使用 '/' return filePath.substring(lastSlashIndex + 1); } @@ -504,8 +507,9 @@ function _fakeLogCore(name, isJs = true, dateIn = null) { logTime = dateIn; } - // 时间部分从第11位开始,长度是12("20:20:20.999") - const formattedTime = formatDateTime(logTime).slice(11, 23); + const ms = logTime.getMilliseconds().toString().padStart(3, "0"); + // 时间部分从第11位开始,长度是12("20:20:20") + const formattedTime = formatDateTime(logTime).slice(11, 19) + "." + ms; if (isStart) { logMessage = @@ -594,3 +598,24 @@ function logFakeScriptEnd({ scriptName = null, startTime = new Date() } = {}) { } return _fakeLogCore(scriptName, true, startTime); } + +/** + * 等待传送结束 + * @param {Int} timeout 单位为ms + * @note 参考了七圣召唤七日历练脚本 + */ +async function waitTpFinish(timeout = 30000) { + const region = RecognitionObject.ocr(1690, 230, 75, 350); // 队伍名称区域 + const startTime = Date.now(); + + await sleep(500); //点击传送后等待一段时间避免误判 + while (Date.now() - startTime < timeout) { + let res = captureGameRegion().find(region); + if (!res.isEmpty()) { + await sleep(600); //传送结束后有僵直 + return; + } + await sleep(100); + } + throw new Error("传送时间超时"); +} diff --git a/repo/js/CD-Aware-AutoGather/main.js b/repo/js/CD-Aware-AutoGather/main.js index 8d7422ed..c1442c74 100644 --- a/repo/js/CD-Aware-AutoGather/main.js +++ b/repo/js/CD-Aware-AutoGather/main.js @@ -167,9 +167,8 @@ async function runClearMode() { const resetTimeStr = formatDateTime(getDefaultTime()); let account = await getGameAccount(settings.iHaveMultipleAccounts); for (const pathTask of selectedMaterials) { - const jsonFiles = filterFilesInTaskDir(pathTask.label); const recordFile = getRecordFilePath(account, pathTask); - const lines = jsonFiles.map((filePath) => { + const lines = pathTask.jsonFiles.map((filePath) => { return `${basename(filePath)}\t${resetTimeStr}`; }); const content = lines.join("\n"); @@ -280,7 +279,7 @@ async function runPathScriptFile(jsonPath) { async function runPathTaskIfCooldownExpired(account, pathTask) { const recordFile = getRecordFilePath(account, pathTask); - const jsonFiles = filterFilesInTaskDir(pathTask.label); + const jsonFiles = pathTask.jsonFiles; log.info("{0}共有{1}条路线", pathTask.label, jsonFiles.length); @@ -397,7 +396,13 @@ function getSelectedMaterials() { if (selectAllMaterials || settings[entry.name] === true) { let index = entry.label.indexOf(" "); entry.label = entry.label.slice(index + 1); // 去除⬇️指示 - selectedMaterials.push(entry); + const jsonFiles = filterFilesInTaskDir(entry.label); + if (jsonFiles.length > 0) { + entry.jsonFiles = jsonFiles; + selectedMaterials.push(entry); + } else { + log.debug("跳过空文件夹: {0}", entry.label); + } } } } diff --git a/repo/js/CD-Aware-AutoGather/manifest.json b/repo/js/CD-Aware-AutoGather/manifest.json index 07f3f1e4..f3656624 100644 --- a/repo/js/CD-Aware-AutoGather/manifest.json +++ b/repo/js/CD-Aware-AutoGather/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 1, "name": "带CD管理的自动采集", - "version": "1.4", + "version": "1.5", "bgi_version": "0.45.0", "description": "自动同步你通过BetterGI订阅的地图追踪任务,执行采集任务,并管理材料刷新时间(支持多账号)。\n首次使用前请先简单阅读说明(可在`全自动`——`JS脚本`页面,点击本脚本名称查看)", "authors": [ diff --git a/repo/js/CD-Aware-AutoGather/settings.json b/repo/js/CD-Aware-AutoGather/settings.json index b5c40abc..bb8379c1 100644 --- a/repo/js/CD-Aware-AutoGather/settings.json +++ b/repo/js/CD-Aware-AutoGather/settings.json @@ -9,6 +9,16 @@ "清除运行记录(重置材料刷新时间)" ] }, + { + "name": "subscribeMode", + "type": "select", + "label": "'地图追踪'中已订阅的任务目录的处理方式:", + "options": [ + "每次自动扫描,并采集扫描到的所有材料", + "手动扫描,并采集扫描到的所有材料", + "手动扫描,只采集已勾选的材料" + ] + }, { "name": "partyName", "type": "input-text", @@ -29,16 +39,6 @@ "type": "checkbox", "label": "我肝的账号不止一个(选中后将分账号维护对应的材料刷新时间)" }, - { - "name": "subscribeMode", - "type": "select", - "label": "'地图追踪'中已订阅的任务目录的处理方式:", - "options": [ - "每次自动扫描,并采集扫描到的所有材料", - "手动扫描,并采集扫描到的所有材料", - "手动扫描,只采集已勾选的材料" - ] - }, { "name": "acceptMultiplePathOfSameMaterial", "type": "checkbox", diff --git a/repo/js/CD-Aware-AutoGather/settings.template.json b/repo/js/CD-Aware-AutoGather/settings.template.json index bd94811a..6841d05b 100644 --- a/repo/js/CD-Aware-AutoGather/settings.template.json +++ b/repo/js/CD-Aware-AutoGather/settings.template.json @@ -9,6 +9,16 @@ "清除运行记录(重置材料刷新时间)" ] }, + { + "name": "subscribeMode", + "type": "select", + "label": "'地图追踪'中已订阅的任务目录的处理方式:", + "options": [ + "每次自动扫描,并采集扫描到的所有材料", + "手动扫描,并采集扫描到的所有材料", + "手动扫描,只采集已勾选的材料" + ] + }, { "name": "partyName", "type": "input-text", @@ -29,16 +39,6 @@ "type": "checkbox", "label": "我肝的账号不止一个(选中后将分账号维护对应的材料刷新时间)" }, - { - "name": "subscribeMode", - "type": "select", - "label": "'地图追踪'中已订阅的任务目录的处理方式:", - "options": [ - "每次自动扫描,并采集扫描到的所有材料", - "手动扫描,并采集扫描到的所有材料", - "手动扫描,只采集已勾选的材料" - ] - }, { "name": "acceptMultiplePathOfSameMaterial", "type": "checkbox", diff --git a/repo/js/GeniusInvokationTCGQuickProficiency/README.md b/repo/js/GeniusInvokationTCGQuickProficiency/README.md index f2f3ed8a..eb62fc28 100644 --- a/repo/js/GeniusInvokationTCGQuickProficiency/README.md +++ b/repo/js/GeniusInvokationTCGQuickProficiency/README.md @@ -34,6 +34,8 @@ 这种情况只能手动操作小号投降(见前面的[使用说明](#使用说明))。由于发起邀请的角色(大号)操作会更复杂,建议用脚本来发起邀请。 + 或者你也可以在QQ群或者QQ频道找同样想刷熟练度的玩家,互相挂投降模式协助对方。[右击此链接——在新窗口中打开](https://bettergi.com/community.html)查看QQ群和QQ频道信息。 + - **只有一台电脑,能不能运行一个原神,运行一个云原神?** Better GI在检测到已经有运行中的实例时不会再启动第二份,但并不像原神那样针对同一台物理设备。我也尝试过通过创建多个Windows账号,以双开Better GI,但是后启动的截图器会报错,可能是无法同时运行多个截图器。