@@ -1,15 +1,93 @@
// fakeLog 函数,使用方法:将本函数放在主函数前,调用时请务必使用await, 否则可能出现v8白框报错
//在js开头处伪造该js结束运行的日志信息, 如 await fakeLog("js脚本", true, true, 0);
//在js结尾处伪造该js开始运行的日志信息, 如 await fakeLog("js脚本", true, false, 2333);
//duration项目仅在伪造结束信息时有效, 且无实际作用, 可以任意填写, 当你需要在日志中输出特定值时才需要, 单位为毫秒
//在调用地图追踪前伪造该地图追踪开始运行的日志信息,如 await fakeLog(`地图追踪.json`, false, true, 0);
//在调用地图追踪后伪造该地图追踪结束运行的日志信息,如 await fakeLog(`地图追踪.json`, false, false, 0);
//如此便可以在js运行过程中伪造地图追踪的日志信息, 可以在日志分析等中查看
async function fakeLog ( name , isJs , isStart , duration ) {
await sleep ( 10 ) ;
const currentTime = Date . now ( ) ;
// 参数检查
if ( typeof name !== 'string' ) {
log . error ( "参数 'name' 必须是字符串类型!" ) ;
return ;
}
if ( typeof isJs !== 'boolean' ) {
log . error ( "参数 'isJs' 必须是布尔型!" ) ;
return ;
}
if ( typeof isStart !== 'boolean' ) {
log . error ( "参数 'isStart' 必须是布尔型!" ) ;
return ;
}
if ( typeof currentTime !== 'number' || ! Number . isInteger ( currentTime ) ) {
log . error ( "参数 'currentTime' 必须是整数!" ) ;
return ;
}
if ( typeof duration !== 'number' || ! Number . isInteger ( duration ) ) {
log . error ( "参数 'duration' 必须是整数!" ) ;
return ;
}
// 将 currentTime 转换为 Date 对象并格式化为 HH:mm:ss.sss
const date = new Date ( currentTime ) ;
const hours = String ( date . getHours ( ) ) . padStart ( 2 , '0' ) ;
const minutes = String ( date . getMinutes ( ) ) . padStart ( 2 , '0' ) ;
const seconds = String ( date . getSeconds ( ) ) . padStart ( 2 , '0' ) ;
const milliseconds = String ( date . getMilliseconds ( ) ) . padStart ( 3 , '0' ) ;
const formattedTime = ` ${ hours } : ${ minutes } : ${ seconds } . ${ milliseconds } ` ;
// 将 duration 转换为分钟和秒,并保留三位小数
const durationInSeconds = duration / 1000 ; // 转换为秒
const durationMinutes = Math . floor ( durationInSeconds / 60 ) ;
const durationSeconds = ( durationInSeconds % 60 ) . toFixed ( 3 ) ; // 保留三位小数
// 使用四个独立的 if 语句处理四种情况
if ( isJs && isStart ) {
// 处理 isJs = true 且 isStart = true 的情况
const logMessage = ` 正在伪造js开始的日志记录 \n \n ` +
` [ ${ formattedTime } ] [INF] BetterGenshinImpact.Service.ScriptService \n ` +
` ------------------------------ \n \n ` +
` [ ${ formattedTime } ] [INF] BetterGenshinImpact.Service.ScriptService \n ` +
` → 开始执行JS脚本: " ${ name } " ` ;
log . info ( logMessage ) ;
}
if ( isJs && ! isStart ) {
// 处理 isJs = true 且 isStart = false 的情况
const logMessage = ` 正在伪造js结束的日志记录 \n \n ` +
` [ ${ formattedTime } ] [INF] BetterGenshinImpact.Service.ScriptService \n ` +
` → 脚本执行结束: " ${ name } ", 耗时: ${ durationMinutes } 分 ${ durationSeconds } 秒 \n \n ` +
` [ ${ formattedTime } ] [INF] BetterGenshinImpact.Service.ScriptService \n ` +
` ------------------------------ ` ;
log . info ( logMessage ) ;
}
if ( ! isJs && isStart ) {
// 处理 isJs = false 且 isStart = true 的情况
const logMessage = ` 正在伪造地图追踪开始的日志记录 \n \n ` +
` [ ${ formattedTime } ] [INF] BetterGenshinImpact.Service.ScriptService \n ` +
` ------------------------------ \n \n ` +
` [ ${ formattedTime } ] [INF] BetterGenshinImpact.Service.ScriptService \n ` +
` → 开始执行地图追踪任务: " ${ name } " ` ;
log . info ( logMessage ) ;
}
if ( ! isJs && ! isStart ) {
// 处理 isJs = false 且 isStart = false 的情况
const logMessage = ` 正在伪造地图追踪结束的日志记录 \n \n ` +
` [ ${ formattedTime } ] [INF] BetterGenshinImpact.Service.ScriptService \n ` +
` → 脚本执行结束: " ${ name } ", 耗时: ${ durationMinutes } 分 ${ durationSeconds } 秒 \n \n ` +
` [ ${ formattedTime } ] [INF] BetterGenshinImpact.Service.ScriptService \n ` +
` ------------------------------ ` ;
log . info ( logMessage ) ;
}
}
// 定义目标文件夹路径和记录文件路径
const recordFolder = "record" ; // 存储记录文件的文件夹路径
const timestamp = "::2000-01-01T00:00:00.000Z" ; // 固定的时间戳
// 定义六个运行时变量,初始值分别为 2000、1000、0、0、0、0
let runtime1 = 2000 ;
let runtime2 = 1000 ;
let runtime3 = 0 ;
let runtime4 = 0 ;
let runtime5 = 0 ;
let runtime6 = 0 ;
// 从 settings 中读取用户配置,并设置默认值
const userSettings = {
operationMode : settings . operationMode || "执行任务(若不存在索引文件则自动创建)" ,
@@ -146,194 +224,198 @@ function removeJsonSuffix(fileName) {
}
// 新增逻辑:当选择“执行任务(若不存在索引文件则自动创建)”时,执行类似路径执行的逻辑
if ( userSettings . operationMode === "执行任务(若不存在索引文件则自动创建)" ) {
log . info ( "启用自动拾取的实时任务" ) ;
dispatcher . addTimer ( new RealtimeTimer ( "AutoPick" ) ) ;
// 获取子文件夹内的所有文件路径
const recordFiles = file . ReadPathSync ( subFolderPath ) ;
// 直接获取文件数量作为路径组数量
const totalPathGroups = recordFiles . length ;
if ( userSettings . operationMode === "执行任务(若不存在索引文件则自动创建)" ) {
log . info ( "启用自动拾取的实时任务" ) ;
dispatcher . addTimer ( new RealtimeTimer ( "AutoPick" ) ) ;
await fakeLog ( "采集cd管理" , true , false , 1000 ) ;
// 获取子文件夹内的所有文件路径
const recordFiles = file . ReadPathSync ( subFolderPath ) ;
// 直接获取文件数量作为路径组数量
const totalPathGroups = recordFiles . length ;
// 外层循环:依次处理每个路径组
for ( let groupNumber = 1 ; groupNumber <= totalPathGroups ; groupNumber ++ ) {
const pathGroupFilePath = ` ${ subFolderPath } /路径组 ${ groupNumber } .txt ` ; // 动态生成路径组文件路径
// 外层循环:依次处理每个路径组
for ( let groupNumber = 1 ; groupNumber <= totalPathGroups ; groupNumber ++ ) {
const pathGroupFilePath = ` ${ subFolderPath } /路径组 ${ groupNumber } .txt ` ; // 动态生成路径组文件路径
genshin . returnMainUi ( ) ;
genshin . returnMainUi ( ) ;
//切换到指定配队
if ( partyNamesArray [ groupNumber - 1 ] !== "" ) {
await genshin . switchParty ( partyNamesArray [ groupNumber - 1 ] )
}
genshin . returnMainUi ( ) ;
try {
let pathGroupContent = await file . readText ( pathGroupFilePath ) ;
let pathGroupEntries = pathGroupContent . trim ( ) . split ( '\n' ) ;
for ( let i = 0 ; i < pathGroupEntries . length ; i ++ ) {
const entryWithTimestamp = pathGroupEntries [ i ] . trim ( ) ;
const [ entryName , entryTimestamp ] = entryWithTimestamp . split ( '::' ) ;
// 构造路径文件路径
const pathingFilePath = ` pathing/路径组 ${ groupNumber } / ${ entryName } .json ` ;
// 获取开始时间
const startTime = new Date ( ) ;
// 更新 runtime 变量
runtime6 = runtime5 ;
runtime5 = runtime4 ;
runtime4 = runtime3 ;
runtime3 = runtime2 ;
runtime2 = runtime1 ;
runtime1 = startTime . getTime ( ) ;
// 检查时间差条件
if ( ( runtime1 - runtime2 ) < 500 &&
( runtime2 - runtime3 ) < 500 &&
( runtime3 - runtime4 ) < 500 &&
( runtime4 - runtime5 ) < 500 &&
( runtime5 - runtime6 ) < 500 ) {
log . info ( ` 连续五次时间差小于 500 毫秒,循环终止。 ` ) ;
break ; // 如果连续五次时间差小于 500 毫秒,退出循环
}
// 比较当前时间戳与任务的时间戳
const entryDate = new Date ( entryTimestamp ) ;
if ( startTime <= entryDate ) {
log . info ( ` 当前任务 ${ entryName } 未刷新,跳过任务 ${ i + 1 } / ${ pathGroupEntries . length } 个 ` ) ;
await sleep ( 500 ) ;
continue ; // 跳过当前任务
//切换到指定配队
if ( partyNamesArray [ groupNumber - 1 ] !== "" ) {
await genshin . switchParty ( partyNamesArray [ groupNumber - 1 ] )
}
// 新增校验:若当前时间的小时数和 skipTimeRanges 一致,则跳过任务
const currentHour = startTime . getHours ( ) ; // 获取当前时间的小时数
const skipHours = userSettings . skipTimeRanges . split ( ';' ) . map ( Number ) ; // 将 skipTimeRanges 转换为数字数组
if ( skipHours . includes ( currentHour ) ) {
log . info ( ` 当前时间的小时数为 ${ currentHour } ,在跳过时间范围内,跳过任务 ${ entryName } ` ) ;
continue ; // 跳过当前任务
}
genshin . returnMainUi ( ) ;
// 日志输出当前任务信息
log . info ( ` 当前任务 ${ entryName } 为第 ${ i + 1 } / ${ pathGroupEntries . length } 个 ` ) ;
// 执行路径文件
try {
awai t pathingScript . runFile ( pathing FilePath ) ;
log . info ( ` 执行任务: ${ entryName } ` ) ;
le t pathGroupContent = await file . readText ( pathGroup FilePath ) ;
let pathGroupEntries = pathGroupContent . trim ( ) . split ( '\n' ) ;
for ( let i = 0 ; i < pathGroupEntries . length ; i ++ ) {
const entryWithTimestamp = pathGroupEntries [ i ] . trim ( ) ;
const [ entryName , entryTimestamp ] = entryWithTimestamp . split ( '::' ) ;
// 构造路径文件路径
const pathingFilePath = ` pathing/路径组 ${ groupNumber } / ${ entryName } .json ` ;
// 获取开始时间
const startTime = new Date ( ) ;
// 比较当前时间戳与任务的时间戳
const entryDate = new Date ( entryTimestamp ) ;
if ( startTime <= entryDate ) {
log . info ( ` 当前任务 ${ entryName } 未刷新,跳过任务 ${ i + 1 } / ${ pathGroupEntries . length } 个 ` ) ;
await sleep ( 10 ) ;
continue ; // 跳过当前任务
}
// 新增校验:若当前时间的小时数和 skipTimeRanges 一致,则跳过任务
const currentHour = startTime . getHours ( ) ; // 获取当前时间的小时数
const skipHours = userSettings . skipTimeRanges . split ( ';' ) . map ( Number ) ; // 将 skipTimeRanges 转换为数字数组
if ( skipHours . includes ( currentHour ) ) {
log . info ( ` 当前时间的小时数为 ${ currentHour } ,在跳过时间范围内,跳过任务 ${ entryName } ` ) ;
continue ; // 跳过当前任务
}
//伪造地图追踪开始的日志
await fakeLog ( entryName , false , true , 0 ) ;
// 日志输出当前任务信息
log . info ( ` 当前任务 ${ entryName } 为第 ${ i + 1 } / ${ pathGroupEntries . length } 个 ` ) ;
// 执行路径文件
try {
await pathingScript . runFile ( pathingFilePath ) ;
log . info ( ` 执行任务: ${ entryName } ` ) ;
} catch ( error ) {
log . error ( ` 路径文件 ${ pathingFilePath } 不存在或执行失败: ${ error } ` ) ;
continue ; // 跳过当前任务
}
//捕获任务取消的信息并跳出循环
try {
await sleep ( 10 ) ; // 假设 sleep 是一个异步函数,休眠 10 毫秒
} catch ( error ) {
log . error ( ` 发生错误: ${ error } ` ) ;
break ; // 终止循环
}
// 获取结束时间
const endTime = new Date ( ) ;
// 比较开始时间与结束时间
const timeDiff = endTime . getTime ( ) - startTime . getTime ( ) ; // 时间差(毫秒)
//伪造地图追踪结束的日志
await fakeLog ( entryName , false , false , timeDiff ) ;
if ( timeDiff > 3000 ) { // 时间差大于3秒
// 获取当前路径组的 cdtype
const currentCdType = pathGroupCdType [ groupNumber - 1 ] || "未知类型" ;
// 初始化 newTimestamp 和 nextAvailableTime
let newTimestamp ;
let nextAvailableTime ;
// 根据 cdtype 执行不同的操作
switch ( currentCdType ) {
case "1次0点刷新" :
// 将任务文件中对应的时间戳改为下一个0点
const tomorrow = new Date ( startTime . getTime ( ) + 24 * 60 * 60 * 1000 ) ;
tomorrow . setHours ( 0 , 0 , 0 , 0 ) ; // 设置为下一个0点
newTimestamp = tomorrow . toISOString ( ) ;
nextAvailableTime = new Date ( newTimestamp ) . toLocaleString ( ) ; // 转换为本地时间格式
//log.info(`下一次可用时间为 ${nextAvailableTime}`);
break ;
case "2次0点刷新" :
// 将任务文件中对应的时间戳改为下下个0点
const dayAfterTomorrow = new Date ( startTime . getTime ( ) + 48 * 60 * 60 * 1000 ) ;
dayAfterTomorrow . setHours ( 0 , 0 , 0 , 0 ) ; // 设置为下下个0点
newTimestamp = dayAfterTomorrow . toISOString ( ) ;
nextAvailableTime = new Date ( newTimestamp ) . toLocaleString ( ) ; // 转换为本地时间格式
//log.info(`下一次可用时间为 ${nextAvailableTime}`);
break ;
case "3次0点刷新" :
// 将任务文件中对应的时间戳改为下下下个0点
const twoDaysAfterTomorrow = new Date ( startTime . getTime ( ) + 72 * 60 * 60 * 1000 ) ;
twoDaysAfterTomorrow . setHours ( 0 , 0 , 0 , 0 ) ; // 设置为下下下个0点
newTimestamp = twoDaysAfterTomorrow . toISOString ( ) ;
nextAvailableTime = new Date ( newTimestamp ) . toLocaleString ( ) ; // 转换为本地时间格式
//log.info(`下一次可用时间为 ${nextAvailableTime}`);
break ;
case "4点刷新" :
// 将任务文件中对应的时间戳改为下一个4点
const next4AM = new Date ( startTime . getTime ( ) ) ;
next4AM . setHours ( 4 , 0 , 0 , 0 ) ; // 设置为当天的4点
if ( next4AM <= startTime ) {
next4AM . setDate ( next4AM . getDate ( ) + 1 ) ; // 如果当前时间已过4点, 则设置为下一天的4点
}
newTimestamp = next4AM . toISOString ( ) ;
nextAvailableTime = new Date ( newTimestamp ) . toLocaleString ( ) ; // 转换为本地时间格式
//log.info(`下一次可用时间为 ${nextAvailableTime}`);
break ;
case "12小时刷新" :
// 将任务文件中对应的时间戳改为开始时间后12小时0分0秒
newTimestamp = new Date ( startTime . getTime ( ) + 12 * 60 * 60 * 1000 ) . toISOString ( ) ;
nextAvailableTime = new Date ( newTimestamp ) . toLocaleString ( ) ; // 转换为本地时间格式
//log.info(`下一次可用时间为 ${nextAvailableTime}`);
break ;
case "24小时刷新" :
// 将任务文件中对应的时间戳改为开始时间后24小时0分0秒
newTimestamp = new Date ( startTime . getTime ( ) + 24 * 60 * 60 * 1000 ) . toISOString ( ) ;
nextAvailableTime = new Date ( newTimestamp ) . toLocaleString ( ) ; // 转换为本地时间格式
//log.info(`下一次可用时间为 ${nextAvailableTime}`);
break ;
case "46小时刷新" :
// 将任务文件中对应的时间戳改为开始时间后46小时0分0秒
newTimestamp = new Date ( startTime . getTime ( ) + 46 * 60 * 60 * 1000 ) . toISOString ( ) ;
nextAvailableTime = new Date ( newTimestamp ) . toLocaleString ( ) ; // 转换为本地时间格式
//log.info(`下一次可用时间为 ${nextAvailableTime}`);
break ;
default :
log . warn ( ` 路径组 ${ groupNumber } 的 cdtype 是 ${ currentCdType } ,执行默认操作 ` ) ;
// 默认操作:将下一个可用时间设置为开始时间
newTimestamp = startTime . toISOString ( ) ;
nextAvailableTime = startTime . toLocaleString ( ) ; // 转换为本地时间格式
break ;
}
// 更新任务文件中的时间戳
// 首先根据newTimestamp修改pathGroupEntries中对应项
pathGroupEntries = pathGroupEntries . map ( entry => {
const [ name , timestamp ] = entry . split ( '::' ) ;
if ( name === entryName ) {
return ` ${ name } :: ${ newTimestamp } ` ;
}
return entry ;
} ) ;
// 然后根据pathGroupEntries修改pathGroupContent
pathGroupContent = pathGroupEntries . join ( '\n' ) ;
// 最后将pathGroupContent写回原文件
await file . writeText ( pathGroupFilePath , pathGroupContent ) ;
log . info ( ` 本任务执行大于3秒, cd信息已更新, 下一次可用时间为 ${ nextAvailableTime } ` ) ;
}
}
log . info ( ` 路径组 ${ groupNumber } 的所有任务运行完成 ` ) ;
} catch ( error ) {
log . error ( ` 路径文件 ${ pathing FilePath } 不存在或执行失败 : ${ error } ` ) ;
continue ; // 跳过当前任务
}
// 获取结束时间
const endTime = new Date ( ) ;
// 比较开始时间与结束时间
const timeDiff = endTime . getTime ( ) - startTime . getTime ( ) ; // 时间差(毫秒)
if ( timeDiff > 3000 ) { // 时间差大于3秒
// 获取当前路径组的 cdtype
const currentCdType = pathGroupCdType [ groupNumber - 1 ] || "未知类型" ;
// 初始化 newTimestamp 和 nextAvailableTime
let newTimestamp ;
let nextAvailableTime ;
// 根据 cdtype 执行不同的操作
switch ( currentCdType ) {
case "1次0点刷新" :
// 将任务文件中对应的时间戳改为下一个0点
const tomorrow = new Date ( startTime . getTime ( ) + 24 * 60 * 60 * 1000 ) ;
tomorrow . setHours ( 0 , 0 , 0 , 0 ) ; // 设置为下一个0点
newTimestamp = tomorrow . toISOString ( ) ;
nextAvailableTime = new Date ( newTimestamp ) . toLocaleString ( ) ; // 转换为本地时间格式
//log.info(`下一次可用时间为 ${nextAvailableTime}`);
break ;
case "2次0点刷新" :
// 将任务文件中对应的时间戳改为下下个0点
const dayAfterTomorrow = new Date ( startTime . getTime ( ) + 48 * 60 * 60 * 1000 ) ;
dayAfterTomorrow . setHours ( 0 , 0 , 0 , 0 ) ; // 设置为下下个0点
newTimestamp = dayAfterTomorrow . toISOString ( ) ;
nextAvailableTime = new Date ( newTimestamp ) . toLocaleString ( ) ; // 转换为本地时间格式
//log.info(`下一次可用时间为 ${nextAvailableTime}`);
break ;
case "3次0点刷新" :
// 将任务文件中对应的时间戳改为下下下个0点
const twoDaysAfterTomorrow = new Date ( startTime . getTime ( ) + 72 * 60 * 60 * 1000 ) ;
twoDaysAfterTomorrow . setHours ( 0 , 0 , 0 , 0 ) ; // 设置为下下下个0点
newTimestamp = twoDaysAfterTomorrow . toISOString ( ) ;
nextAvailableTime = new Date ( newTimestamp ) . toLocaleString ( ) ; // 转换为本地时间格式
//log.info(`下一次可用时间为 ${nextAvailableTime}`);
break ;
case "4点刷新" :
// 将任务文件中对应的时间戳改为下一个4点
const next4AM = new Date ( startTime . getTime ( ) ) ;
next4AM . setHours ( 4 , 0 , 0 , 0 ) ; // 设置为当天的4点
if ( next4AM <= startTime ) {
next4AM . setDate ( next4AM . getDate ( ) + 1 ) ; // 如果当前时间已过4点, 则设置为下一天的4点
}
newTimestamp = next4AM . toISOString ( ) ;
nextAvailableTime = new Date ( newTimestamp ) . toLocaleString ( ) ; // 转换为本地时间格式
//log.info(`下一次可用时间为 ${nextAvailableTime}`);
break ;
case "12小时刷新" :
// 将任务文件中对应的时间戳改为开始时间后12小时0分0秒
newTimestamp = new Date ( startTime . getTime ( ) + 12 * 60 * 60 * 1000 ) . toISOString ( ) ;
nextAvailableTime = new Date ( newTimestamp ) . toLocaleString ( ) ; // 转换为本地时间格式
//log.info(`下一次可用时间为 ${nextAvailableTime}`);
break ;
case "24小时刷新" :
// 将任务文件中对应的时间戳改为开始时间后24小时0分0秒
newTimestamp = new Date ( startTime . getTime ( ) + 24 * 60 * 60 * 1000 ) . toISOString ( ) ;
nextAvailableTime = new Date ( newTimestamp ) . toLocaleString ( ) ; // 转换为本地时间格式
//log.info(`下一次可用时间为 ${nextAvailableTime}`);
break ;
case "46小时刷新" :
// 将任务文件中对应的时间戳改为开始时间后46小时0分0秒
newTimestamp = new Date ( startTime . getTime ( ) + 46 * 60 * 60 * 1000 ) . toISOString ( ) ;
nextAvailableTime = new Date ( newTimestamp ) . toLocaleString ( ) ; // 转换为本地时间格式
//log.info(`下一次可用时间为 ${nextAvailableTime}`);
break ;
default :
log . warn ( ` 路径组 ${ groupNumber } 的 cdtype 是 ${ currentCdType } ,执行默认操作 ` ) ;
// 默认操作:将下一个可用时间设置为开始时间
newTimestamp = startTime . toISOString ( ) ;
nextAvailableTime = startTime . toLocaleString ( ) ; // 转换为本地时间格式
break ;
}
// 更新任务文件中的时间戳
// 首先根据newTimestamp修改pathGroupEntries中对应项
pathGroupEntries = pathGroupEntries . map ( entry => {
const [ name , timestamp ] = entry . split ( '::' ) ;
if ( name === entryName ) {
return ` ${ name } :: ${ newTimestamp } ` ;
}
return entry ;
} ) ;
// 然后根据pathGroupEntries修改pathGroupContent
pathGroupContent = pathGroupEntries . join ( '\n' ) ;
// 最后将pathGroupContent写回原文件
await file . writeText ( pathGroupFilePath , pathGroupContent ) ;
log . info ( ` 本任务执行大于10秒, cd信息已更新, 下一次可用时间为 ${ nextAvailableTime } ` ) ;
log . error ( ` 读取 路径组 文件 ${ pathGroup FilePath } 时出错 : ${ error } ` ) ;
}
}
log . info ( ` 路径组 ${ groupNumber } 的所有 任务运行完成` ) ;
} catch ( error ) {
log . error ( ` 读取路径组文件 ${ pathGroupFilePath } 时出错: ${ error } ` ) ;
log . info ( '所有路径组的 任务运行完成' ) ;
//伪造js开始的日志
await fakeLog ( "采集cd管理" , true , true , 0 ) ;
}
}
log . info ( '所有路径组的任务运行完成' ) ;
}
} catch ( error ) {
log . error ( ` 操作失败: ${ error } ` ) ;
}