JS脚本:等待到具体时间waitUntilSpecifiedTime v1.3 (#2150)

增加对当天日期的判断,防止之前的配置组超时导致之后的配置组执行拖延至第二天
This commit is contained in:
火山
2025-10-15 23:40:10 +08:00
committed by GitHub
parent 443f161e06
commit 9f1d436bc1
4 changed files with 154 additions and 173 deletions

View File

@@ -25,10 +25,11 @@
### 示例说明
| 当前时间 | 设置目标时间 | 等待结果 |
|----------|--------------|----------|
| 3:00 | 4:00 | 等待1小时 |
| 4:30 | 4:00 | 等待23.5小时次日4:00|
| 当前时间 | 目标时间 | allowNextDay | 结果 |
|----------|----------|--------------|------|
| 03:00 | 04:00 | false | 等待 1 小时,当天 04:00 完成 |
| 04:30 | 04:00 | false | 目标已过立即结束skipped |
| 04:30 | 04:00 | true | 等待至次日 04:00约 23.5 小时) |
---
@@ -40,4 +41,11 @@
- 目标时间3:55
- 等待23小时55分钟次日3:55
**请务必设置目标时间点,否则脚本不会执行!**
**请务必设置目标时间点,否则脚本不会执行!**
### 更新日志
### 1.6.32025.10.15
添加 allowNextDay 配置settings 中为复选框 allowNextDay用于控制当目标时间“今天已过”时是否等待到“明天”的同一时间。
- 若希望在目标时间今天已过时也继续等待到明天,请在设置中勾选“如果目标时间今天已过,是否等待到明天同一时间”。
- 不勾选则脚本会立即跳过,这是为防止意外长时间占用任务造成的问题。
- 若当天已过,可选择等待到次日同一时间(可选)或立即结束(默认)

View File

@@ -1,79 +1,118 @@
(async function () {
/**
* 计算从「现在」到下一次指定时分的毫秒差
*
* @param {number} validatedHours 小时023
* @param {number} validatedMinutes 分钟059
* @returns {number} 下一次指定时分与目前时间的毫秒差
*/
function getTimeUntilNextTime(validatedHours, validatedMinutes) {
const now = new Date();
const nextTime = new Date(
now.getFullYear(),
now.getMonth(),
now.getDate(),
validatedHours, validatedMinutes, 0, 0
);
// 如果当前时间已经到达或超过今天指定的时刻,就把 nextTime 设为明天的同一时间
if (now >= nextTime) {
nextTime.setDate(nextTime.getDate() + 1);
// 默认值
const DEFAULT_HOURS = 4;
const DEFAULT_MINUTES = 0;
const BUFFER_MS = 10 * 1000; // 10秒缓冲
// 解析布尔(支持 true / 'true' / false / 'false'
function parseBoolean(val) {
return val === true || val === 'true' || val === '1' || val === 1;
}
// 解析数字并做范围限制,若输入为空或无法解析则返回 defaultValue
function parseAndClampNumber(val, defaultValue, min, max) {
const n = Number(val);
if (val === '' || !Number.isFinite(n)) {
return { value: defaultValue, warned: true, reason: 'empty_or_invalid' };
}
const rounded = Math.floor(n);
if (rounded < min || rounded > max) {
return { value: Math.min(max, Math.max(min, rounded)), warned: true, reason: 'out_of_range' };
}
return { value: rounded, warned: false, reason: '' };
}
// 计算下一个目标时间(返回 Date 或 null当 allowNextDay=false 且今天已过时)
function computeNextTargetDate(hours, minutes, allowNextDay) {
const now = new Date();
let target = new Date(now.getFullYear(), now.getMonth(), now.getDate(), hours, minutes, 0, 0);
if (target.getTime() > now.getTime()) {
return { target, isTomorrow: false };
} else {
if (allowNextDay) {
const tomorrow = new Date(target.getTime() + 24 * 60 * 60 * 1000);
return { target: tomorrow, isTomorrow: true };
} else {
return { target: null, isTomorrow: false };
}
}
}
// 主等待函数(封装校验、计算、等待)
async function waitUntilSpecifiedTime(rawHours, rawMinutes, rawAllowNextDay) {
// 解析与校验
const ph = parseAndClampNumber(rawHours, DEFAULT_HOURS, 0, 23);
const pm = parseAndClampNumber(rawMinutes, DEFAULT_MINUTES, 0, 59);
const allowNextDay = parseBoolean(rawAllowNextDay);
if (ph.warned) {
if (ph.reason === 'out_of_range') {
log.warn(`设置指定小时错误(${rawHours}),已修正为 ${ph.value}(范围 0~23`);
} else {
log.warn(`未设置有效的指定小时,将使用默认:${ph.value}`);
}
}
if (pm.warned) {
if (pm.reason === 'out_of_range') {
log.warn(`设置指定分钟错误(${rawMinutes}),已修正为 ${pm.value}(范围 0~59`);
} else {
log.warn(`未设置有效的指定分钟,将使用默认:${pm.value}`);
}
}
return nextTime - now;
const validatedHours = ph.value;
const validatedMinutes = pm.value;
log.info(`--------------- 将等待至 ${validatedHours}${validatedMinutes} ---------------`);
// 计算下一次目标时间
const { target, isTomorrow } = computeNextTargetDate(validatedHours, validatedMinutes, allowNextDay);
if (!target) {
// 今天已过且不允许等到明天
log.info(`[等待到指定时间] 目标时间 ${validatedHours}:${validatedMinutes} 已经过了今天(当前时间 ${new Date().toLocaleString()}allowNextDay 未开启,脚本将直接结束当前等待分组。`);
return { status: 'skipped', reason: 'target time already passed today', when: null };
}
const now = Date.now();
let msToWait = target.getTime() - now;
if (msToWait < 0) {
// 非常规保护:若计算误差导致负值(极短时间差),设为 0
msToWait = 0;
}
// 日志 → 用更友好的时间描述
const minutesRemaining = Math.floor(msToWait / 60000);
const hoursRemaining = Math.floor(minutesRemaining / 60);
const minutesPart = minutesRemaining % 60;
log.info(`现在时间 ${new Date().toLocaleString()},将等待约 ${hoursRemaining} 小时 ${minutesPart} 分钟(${Math.floor(msToWait / 1000)} 秒),直到 ${target.toLocaleString()}isTomorrow=${isTomorrow}`);
// 真正等待(加缓冲)
await sleep(msToWait + BUFFER_MS);
log.info(`时间到了!现在是 ${new Date().toLocaleString()},目标 ${validatedHours}:${validatedMinutes}isTomorrow=${isTomorrow}`);
return { status: 'done', when: target.toISOString(), isTomorrow };
}
// --- 入口逻辑 ---
// setGameMetrics / dispatcher / log / settings / sleep 为宿主提供的全局 API
setGameMetrics(1920, 1080, 2);
// 启用自动拾取的实时任务
dispatcher.addTimer(new RealtimeTimer("AutoPick"));
// 启用自动剧情的实时任务
dispatcher.addTimer(new RealtimeTimer("AutoSkip"));
// 读取参数
let specifyHours = Number(settings.specifyHours);
let specifyMinutes = Number(settings.specifyMinutes);
if (isNaN(specifyHours) || isNaN(specifyMinutes)) {
log.warn(`⚠️请先设置目标时间点⚠️\n
⚠️⚠️请先设置目标时间点⚠️⚠️\n
⚠️⚠️⚠️请先设置目标时间点⚠️⚠️⚠️\n`);
} else {
// 读取参数(可能为字符串)
const rawHours = settings && settings.specifyHours !== undefined ? settings.specifyHours : '';
const rawMinutes = settings && settings.specifyMinutes !== undefined ? settings.specifyMinutes : '';
// settings.allowNextDay 由 settings.json 中的 switch 提供,可能为 boolean 或字符串 'true'
const rawAllowNextDay = settings && settings.allowNextDay !== undefined ? settings.allowNextDay : false;
log.info(`--------------- 将等待至 ${specifyHours}${specifyMinutes} ---------------`)
// 调用统一等待函数
const result = await waitUntilSpecifiedTime(rawHours, rawMinutes, rawAllowNextDay);
// 计算相差时间(毫秒)
const timeUntilNextTime = getTimeUntilNextTime(specifyHours, specifyMinutes);
const hours = Math.floor(timeUntilNextTime / 3600000);
const minutes = Math.floor((timeUntilNextTime % 3600000) / 60000);
log.info(`距离目标时间 ${specifyHours}:${specifyMinutes},还有 ${hours} 小时 ${minutes} 分钟`);
// 返回结果,方便宿主或调用者判断
return result;
// 每5分钟报告一次剩余时间
const reportInterval = 5 * 60 * 1000; // 5分钟毫秒
let remainingTime = timeUntilNextTime;
while (remainingTime > reportInterval) {
// 等待5分钟或剩余时间取较小值
const waitTime = Math.min(reportInterval, remainingTime);
await sleep(waitTime);
// 更新剩余时间
remainingTime -= waitTime;
// 计算剩余小时和分钟
const remainHours = Math.floor(remainingTime / 3600000);
const remainMinutes = Math.floor((remainingTime % 3600000) / 60000);
// 报告剩余时间
log.info(`距离目标时间 ${specifyHours}:${specifyMinutes},还有 ${remainHours} 小时 ${remainMinutes} 分钟`);
}
// 等待最后剩余的时间不足5分钟
if (remainingTime > 0) {
await sleep(remainingTime);
}
// 多等待5秒
// await sleep(5000);
log.info(`时间已到!当前时间为 ${specifyHours}${specifyMinutes}`);
}
})();

View File

@@ -1,13 +1,17 @@
{
"manifest_version": 1,
"name": "等待到指定时间",
"version": "1.2",
"bgi_version": "0.42.0",
"description": "等待到指定时间:\n脚本将暂停所有操作直至到达您设置的特定时间24小时制后結束等待让后面的任务在您设置的特定时间后才开始运行。\n例如设置04:00会让脚本等到凌晨4点再继续执行\n使用时务必先设置目标时间否则脚本不会正常运行\n详见README.md",
"name": "等待到指定时间",
"version": "1.3",
"bgi_version": "0.51.0",
"description": "等待到指定时间(默认凌晨4点),适用于等到第二天4点执行其他任务。",
"authors": [
{
"name": "蜜柑魚",
"links": "https://github.com/this-Fish"
"link": "https://github.com/this-Fish"
},
{
"name": "火山",
"link": "https://github.com/RRRR623"
}
],
"settings_ui": "settings.json",

View File

@@ -1,100 +1,30 @@
[
{
"name": "specifyHours",
"type": "select",
"label": "设置目标时间点(24小时制)\n请设置脚本继续执行的具体时间\n示例\n小时4\n分钟30\n脚本会等待至凌晨4点30分\n\n小时",
"options": [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"13",
"14",
"15",
"16",
"17",
"18",
"19",
"20",
"21",
"22",
"23"
]
},
{
"name": "specifyMinutes",
"type": "select",
"label": "分钟",
"options": [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"13",
"14",
"15",
"16",
"17",
"18",
"19",
"20",
"21",
"22",
"23",
"24",
"25",
"26",
"27",
"28",
"29",
"30",
"31",
"32",
"33",
"34",
"35",
"36",
"37",
"38",
"39",
"40",
"41",
"42",
"43",
"44",
"45",
"46",
"47",
"48",
"49",
"50",
"51",
"52",
"53",
"54",
"55",
"56",
"57",
"58",
"59"
]
}
{
"name": "specifyHours",
"type": "select",
"label": "指定等待直到下一个 HHMM 的时0~23默认4",
"default": "4",
"options": [
"0","1","2","3","4","5","6","7","8","9","10","11","12",
"13","14","15","16","17","18","19","20","21","22","23"
]
},
{
"name": "specifyMinutes",
"type": "select",
"label": "指定等待直到下一个 HHMM 的分钟0~59默认0",
"default": "0",
"options": [
"0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19",
"20","21","22","23","24","25","26","27","28","29","30","31","32","33","34","35","36","37",
"38","39","40","41","42","43","44","45","46","47","48","49","50","51","52","53","54","55",
"56","57","58","59"
]
},
{
"name": "allowNextDay",
"type": "checkbox",
"label": "如果目标时间今天已过,是否等待到明天同一时间(默认:否)",
"default": false
}
]