From 3c24514c87d52bcf9f34d066ad33bbcda5c6ff5a Mon Sep 17 00:00:00 2001 From: skyflag2022 <107539971+skyflag2022@users.noreply.github.com> Date: Fri, 17 Oct 2025 23:38:33 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=9C=A3=E9=81=97=E7=89=A9?= =?UTF-8?q?=E8=B4=AD=E4=B9=B0=E6=96=B9=E5=BC=8F=20(#2163)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 参考”OCR购买食材“脚本,采用模板匹配的方式跳过对话和点击对话按钮,增加检查F图标功能 --- repo/js/PurchaseArtifacts/README.md | 4 +- .../{ => Pathing}/挪德卡莱购买狗粮.json | 0 .../assets/{ => Pathing}/枫丹购买狗粮.json | 0 .../assets/{ => Pathing}/璃月购买狗粮1.json | 0 .../assets/{ => Pathing}/璃月购买狗粮2.json | 0 .../assets/{ => Pathing}/稻妻购买狗粮.json | 0 .../assets/{ => Pathing}/纳塔购买狗粮.json | 0 .../assets/{ => Pathing}/蒙德购买狗粮.json | 0 .../assets/{ => Pathing}/须弥购买狗粮.json | 0 .../assets/Picture/Confirm.png | Bin 0 -> 1261 bytes .../assets/Picture/F_Dialogue.png | Bin 0 -> 515 bytes .../assets/Picture/Shopping.png | Bin 0 -> 2425 bytes .../assets/Picture/Shopping2.png | Bin 0 -> 3981 bytes repo/js/PurchaseArtifacts/main.js | 539 +++++++++--------- repo/js/PurchaseArtifacts/manifest.json | 4 +- 15 files changed, 269 insertions(+), 278 deletions(-) rename repo/js/PurchaseArtifacts/assets/{ => Pathing}/挪德卡莱购买狗粮.json (100%) rename repo/js/PurchaseArtifacts/assets/{ => Pathing}/枫丹购买狗粮.json (100%) rename repo/js/PurchaseArtifacts/assets/{ => Pathing}/璃月购买狗粮1.json (100%) rename repo/js/PurchaseArtifacts/assets/{ => Pathing}/璃月购买狗粮2.json (100%) rename repo/js/PurchaseArtifacts/assets/{ => Pathing}/稻妻购买狗粮.json (100%) rename repo/js/PurchaseArtifacts/assets/{ => Pathing}/纳塔购买狗粮.json (100%) rename repo/js/PurchaseArtifacts/assets/{ => Pathing}/蒙德购买狗粮.json (100%) rename repo/js/PurchaseArtifacts/assets/{ => Pathing}/须弥购买狗粮.json (100%) create mode 100644 repo/js/PurchaseArtifacts/assets/Picture/Confirm.png create mode 100644 repo/js/PurchaseArtifacts/assets/Picture/F_Dialogue.png create mode 100644 repo/js/PurchaseArtifacts/assets/Picture/Shopping.png create mode 100644 repo/js/PurchaseArtifacts/assets/Picture/Shopping2.png diff --git a/repo/js/PurchaseArtifacts/README.md b/repo/js/PurchaseArtifacts/README.md index 712786641..bca87b3d1 100644 --- a/repo/js/PurchaseArtifacts/README.md +++ b/repo/js/PurchaseArtifacts/README.md @@ -6,4 +6,6 @@ 此外脚本完整运行后会记录本次的时间,没有刷新时运行脚本会自动跳过。 -账户名只允许使用数字,中英文,同时长度在20个字符以内。 \ No newline at end of file +账户名只允许使用数字,中英文,同时长度在20个字符以内。 + +如果你想要在一周中重复运行,可以删除文件夹里的"账户名.txt"文件。 \ No newline at end of file diff --git a/repo/js/PurchaseArtifacts/assets/挪德卡莱购买狗粮.json b/repo/js/PurchaseArtifacts/assets/Pathing/挪德卡莱购买狗粮.json similarity index 100% rename from repo/js/PurchaseArtifacts/assets/挪德卡莱购买狗粮.json rename to repo/js/PurchaseArtifacts/assets/Pathing/挪德卡莱购买狗粮.json diff --git a/repo/js/PurchaseArtifacts/assets/枫丹购买狗粮.json b/repo/js/PurchaseArtifacts/assets/Pathing/枫丹购买狗粮.json similarity index 100% rename from repo/js/PurchaseArtifacts/assets/枫丹购买狗粮.json rename to repo/js/PurchaseArtifacts/assets/Pathing/枫丹购买狗粮.json diff --git a/repo/js/PurchaseArtifacts/assets/璃月购买狗粮1.json b/repo/js/PurchaseArtifacts/assets/Pathing/璃月购买狗粮1.json similarity index 100% rename from repo/js/PurchaseArtifacts/assets/璃月购买狗粮1.json rename to repo/js/PurchaseArtifacts/assets/Pathing/璃月购买狗粮1.json diff --git a/repo/js/PurchaseArtifacts/assets/璃月购买狗粮2.json b/repo/js/PurchaseArtifacts/assets/Pathing/璃月购买狗粮2.json similarity index 100% rename from repo/js/PurchaseArtifacts/assets/璃月购买狗粮2.json rename to repo/js/PurchaseArtifacts/assets/Pathing/璃月购买狗粮2.json diff --git a/repo/js/PurchaseArtifacts/assets/稻妻购买狗粮.json b/repo/js/PurchaseArtifacts/assets/Pathing/稻妻购买狗粮.json similarity index 100% rename from repo/js/PurchaseArtifacts/assets/稻妻购买狗粮.json rename to repo/js/PurchaseArtifacts/assets/Pathing/稻妻购买狗粮.json diff --git a/repo/js/PurchaseArtifacts/assets/纳塔购买狗粮.json b/repo/js/PurchaseArtifacts/assets/Pathing/纳塔购买狗粮.json similarity index 100% rename from repo/js/PurchaseArtifacts/assets/纳塔购买狗粮.json rename to repo/js/PurchaseArtifacts/assets/Pathing/纳塔购买狗粮.json diff --git a/repo/js/PurchaseArtifacts/assets/蒙德购买狗粮.json b/repo/js/PurchaseArtifacts/assets/Pathing/蒙德购买狗粮.json similarity index 100% rename from repo/js/PurchaseArtifacts/assets/蒙德购买狗粮.json rename to repo/js/PurchaseArtifacts/assets/Pathing/蒙德购买狗粮.json diff --git a/repo/js/PurchaseArtifacts/assets/须弥购买狗粮.json b/repo/js/PurchaseArtifacts/assets/Pathing/须弥购买狗粮.json similarity index 100% rename from repo/js/PurchaseArtifacts/assets/须弥购买狗粮.json rename to repo/js/PurchaseArtifacts/assets/Pathing/须弥购买狗粮.json diff --git a/repo/js/PurchaseArtifacts/assets/Picture/Confirm.png b/repo/js/PurchaseArtifacts/assets/Picture/Confirm.png new file mode 100644 index 0000000000000000000000000000000000000000..201445d06f23e0044a5d944714f767c31d982b3a GIT binary patch literal 1261 zcmV3^RTPH5wa+>C_V%`gLJQPttC3JhTd;yrARt6R zUPD8}Tel7jhS1s!@4aHEr~wM_$#&TM6>L8Y zxj_g7vMI0$T)HOg?1a-7pf(M&=L(rLw9FC?o>Y2nK;Vr*YAp;z@b1gP>=uC#zTB;B z+5){dpf(GEFGw*%je%5Ps7k|y9yo9k=FNbnW?_02Xac*AK*}2~Cj+ih7-I+%VewpH z=>tGPIelJv|63TyDcQ85s#t4>?b=$4s#0B{T)nPr{1gUy6g=h81<>9kL{>1yphb}z z0MGMKRdOLb^)QeE64-tSx-LU?raT!&Lrn%c&pG+vL46G@Zi9T}9P>PHxTgSN0v&Sz z3tV3sLVgmY3WPB%o$qWU1vvkwlMDz{Y6#OPR9uh7F-K_e!1}4I-mf#e)wXK^LS*@FRQ)j0Je4t%UYo6Zl|@yEzWRnze}uq zG?ZYO3Ya+!UUp)mhm5Dm>Kgj8K4Mr(tg=oat5y z5!7U1cBAn4LZP`Cr_ET|_7klC(5b;Q<@qpr6IaL;pkX?!e@0l+2D9!0yrSWxw7NJZ zKm=#c!QNkCNqy{xTdp3qKrz z?++5*O~;YG}I`nr6b3tdjB}A3|SF=(+@*T`t)&fnvs~V&jsQypF9) zp2!YeMN3!Dl;^H4{ur0BTQQ+>F5<#9R>&p;qjr+T^*_SKAx0IfO~#-7KOjj$Oe)Ra X+5Fmk<6x2400000NkvXXu0mjfM`bz| literal 0 HcmV?d00001 diff --git a/repo/js/PurchaseArtifacts/assets/Picture/F_Dialogue.png b/repo/js/PurchaseArtifacts/assets/Picture/F_Dialogue.png new file mode 100644 index 0000000000000000000000000000000000000000..314a85f134cbc0dd620dea029b010905c6415165 GIT binary patch literal 515 zcmV+e0{s1nP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0hmcdK~z{r?UucY z!ax*8_nG_y!6GkUsR)W-uOLPcyMQlXXKN>^f>w5dT8JnqM6eOGuuw!yAt-M0$%KpS zZXh$p6<5{+A0gb_$sxHU^MNN~TAz5T0OKw2_XSMTgkcz1E|*v=7TmDww%aXr^Wh2{ z4hM8P9Tba2WV2ara=9F;)hafd4Xxk~SKxFyVKSMZR4T#e^9d!HOhVUnTEQKm88{w~ zXti4K`~CI}*fAcDLsivpX*3$B)oQ3zDrmRc)a{P&5O%v=1cSk=Kt7+hpU&4X(cNx` z*=&aSd`_M22n+OjJ%mD`t3aVppo$aAvh3j%;UNOI@VWx2RLUN-pXvAeSg+UA#mAEX zOC%COEEaQw4d-Ampe{b11tdvAI-Pc;TrOiY8c`P?p$zVJlJ2IV4vET2hi_hy0 z;r|v01Okv{nJV|;Ngx~!Ls1l}+=nNDXfz5<)2MPE!UF6I$38xZL<04CU3kO6Ls($7 zTA|r&VmKV$wB_OxB$fb_r!DV!r%Y^002ovPDHLk FV1jS-*o^=H literal 0 HcmV?d00001 diff --git a/repo/js/PurchaseArtifacts/assets/Picture/Shopping.png b/repo/js/PurchaseArtifacts/assets/Picture/Shopping.png new file mode 100644 index 0000000000000000000000000000000000000000..2b3153866406f98f101eb4e0d3c506f370c06c3a GIT binary patch literal 2425 zcmV-<35NEGP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D2@Xj_K~z{rwODCT z+-Dho_P;DwxbGvRBoH86MROQ(G^RAlL|Sdfl(AN;&5Sb{^@GRwMV;Y;e$Wq&ol)!P zc%>ehn4~pHZ5kVmOoBPYHVq{tG$9u^Ecda?!utC?|NVz$vkQg751#$s@B6&Z{k*mV z-~7HeEj3xZGhVrIt4&5n$HcJNWYb5=WOa6?G+byDFaFX}Q{>u>_ochLS7v5ra0l?} zuVVIWiI`^qd&TDMb+Iwg(myaLJ-vN0Iq8x~mrDkRMkFCVPSVp-q@$x-JRT32H^ezO zDDJ5#nVy~jvtB=%!M$lcE=c?~kZ^xGC{2sKY~$9tRnbv0G&C$uCm8Td$&}k9GMto{ zAhEGA5Smwy6B83Upu-VnE)(}TkjXU3pYafcZ-No$2u8MjU;3)|k=0q^92k z)Uz*obJwg^RW)C4m9f!rtO_=V36c^MB{?ZU_UzsvPgXx62?=qknkh(|^Sj(`85tRs zv9Spm9vPADo<8Y!4oDy9dh1PTYQCY8Cq4|j_MEjvbrInXiI0oL1Wrsi?o%D?3!G4b zdq1&TQd5%fx>us2A|)y^QX(TGBxY5#nnQY8Dx54s^4H}`abdnxl$A*7hC&$wgV$Sc znKJ=Pm8>xi_4f2RRefnGDPl8hdL9;Lmw2c*Gd)c*z=YjySBcSqh>p%~85kVWa|8o@ zPR8S~ST3lnq)-m*e_kHnwN2moFtBGnQcy>gI2;aynPk10m6;)rmTrJ_vZQeRS}Dk1 zC$TZBWC~v0)zd3y&s~r|{P~E~H(b^Tkd=|9HtY{x^P4hgf(vT9bI;aZnp#A;W|hDrZpVBxI1FCtq!Df$a|J zHEoQs^-5DSoXHc^=InMuD$0xHh37siIY%1Bpxwcv1s%c|&T%~-VMV4$N_J+@7reY!?7*J2s9=j0XF6|T>NT8ktOj>53= z&edjVK?vdX&dSYdcLXQnz21H&Vxe0j!j7$*<*B`UU>@;0c_;?xR5S?>OzZaDc7&!$ z-;;%5uiUY_uA;oe%qqCSpxpTORiwpXDJ?FL#~}eSN6;KH;Ozx)rW`ocmW_`}O?8#5 z$;noeSV%&&@l0rfvGw-d`*1|hybH5n6d|rrQdAXR4G#~O=%^_DFfKM$W1&B&>LN(~ zsl87~%_pnWL@b+K2nkRqnNSJXin`EEX;mRQ=~*pS90CDbXkwLjk(x;bE1M7>+Jpep~twa@1}? z3#n!)V4&YwxkXcRFxdB0*VNI={3S$n8-^LMd;0oymFWn=23Bq@U^zi2WKnYGUc2;S zzQCkluyzavGQt2%<}WwCqj{Re@JfI}VbxUoOpUDb)d~Kv@2;w@W03Wiq$wyD6GBu^+!{OHT3MD=tItg44cO12rf{a^JB z4_e#BfOA?zuoHa`&E4<+^jG=Ik-zE27#=FA!>7d%WP9;z-|?2PdGr=~qJFfi!r z!KZvIh-}}wNxuE{uV@#^2`q4@uA{3<4jnlmCr_P`K``qN%gcko_QHX0c{!Nf9;Sr@ z8DT!B3fVonCfyny$kg-{?&;noQX&SWMg!Ah1OoovJs+3-U#LZoo~rj4OaFJJNsgU3 zrJ0J`i-8Enqb&QqVndPp68%Iiz*DgrNV%CC+U!#Gk3ab18QF559y|YW1 zPfbbIeWT-l|A!ntc2cgt-=+dE7*PUfΝN`^I;F;B`TzWXe>nk1$o=S@g^;_1VF1O2+OlYmn!R%{rsPFyoCtj7DZ?9WbOLbe!LW*YF3&vP6`Iscl r2R?>B&Vt|Ypy&J{=8h5knaKYE!8r>CrsK2j00000NkvXXu0mjfr^Jhm literal 0 HcmV?d00001 diff --git a/repo/js/PurchaseArtifacts/assets/Picture/Shopping2.png b/repo/js/PurchaseArtifacts/assets/Picture/Shopping2.png new file mode 100644 index 0000000000000000000000000000000000000000..8bc22cc8fef32a855501192749c28790c5daf5e9 GIT binary patch literal 3981 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 是否找到并点击了文字 - */ -async function clickTextInRegion(targetText, x, y, width, height, options = {}) { - const { - trimText = true, - clickCenter = true, - retryCount = 1, - retryInterval = 500 - } = options; + /** + * 判断任务是否已刷新 + * @param {string} filePath - 存储最后完成时间的文件路径 + * @param {object} options - 配置选项 + * @param {string} [options.refreshType] - 刷新类型: 'hourly'|'daily'|'weekly'|'monthly'|'custom' + * @param {number} [options.customHours] - 自定义小时数(用于'custom'类型) + * @param {number} [options.dailyHour=4] - 每日刷新的小时(0-23) + * @param {number} [options.weeklyDay=1] - 每周刷新的星期(0-6, 0是周日) + * @param {number} [options.weeklyHour=4] - 每周刷新的小时(0-23) + * @param {number} [options.monthlyDay=1] - 每月刷新的日期(1-31) + * @param {number} [options.monthlyHour=4] - 每月刷新的小时(0-23) + * @returns {Promise} - 是否已刷新 + */ + async function isTaskRefreshed(filePath, options = {}) { + const { + refreshType = 'hourly', // 默认每小时刷新 + customHours = 24, // 自定义刷新小时数默认24 + dailyHour = 4, // 每日刷新默认凌晨4点 + weeklyDay = 1, // 每周刷新默认周一(0是周日) + weeklyHour = 4, // 每周刷新默认凌晨4点 + monthlyDay = 1, // 每月刷新默认第1天 + monthlyHour = 4 // 每月刷新默认凌晨4点 + } = options; - for (let attempt = 0; attempt <= retryCount; attempt++) { try { - // 获取游戏区域截图 - const captureRegion = captureGameRegion(); + // 读取文件内容 + let content = await file.readText(filePath); + const lastTime = new Date(content); + const nowTime = new Date(); - // 创建OCR识别对象,限定识别区域 - const ocrRo = RecognitionObject.ocr(x, y, width, height); - - // 在限定区域内进行OCR识别 - const results = captureRegion.findMulti(ocrRo); - // 遍历OCR结果 - for (let i = 0; i < results.count; i++) { - const res = results[i]; - let detectedText = res.text; - - // 可选:去除前后空白字符 - if (trimText) { - detectedText = detectedText.trim(); - } + let shouldRefresh = false; - // 检查是否匹配目标文字 - if (detectedText === targetText) { - log.info(`找到目标文字: "${targetText}",位置: (${res.x}, ${res.y}, ${res.width}, ${res.height})`); - - if (clickCenter) { - // 点击文字区域中心 - await sleep(200); - keyDown("VK_LMENU"); - await sleep(500); - res.click(); - await sleep(100); - keyUp("VK_LMENU"); - log.info(`已点击文字中心: "${targetText}"`); + switch (refreshType) { + case 'hourly': // 每小时刷新 + shouldRefresh = (nowTime - lastTime) >= 3600 * 1000; + break; + + case 'daily': // 每天固定时间刷新 + // 检查是否已经过了当天的刷新时间 + const todayRefresh = new Date(nowTime); + todayRefresh.setHours(dailyHour, 0, 0, 0); + + // 如果当前时间已经过了今天的刷新时间,检查上次完成时间是否在今天刷新之前 + if (nowTime >= todayRefresh) { + shouldRefresh = lastTime < todayRefresh; } else { - // 点击文字区域的左上角 - res.clickTo(0, 0); - log.info(`已点击文字偏移位置: "${targetText}"`); + // 否则检查上次完成时间是否在昨天刷新之前 + const yesterdayRefresh = new Date(todayRefresh); + yesterdayRefresh.setDate(yesterdayRefresh.getDate() - 1); + shouldRefresh = lastTime < yesterdayRefresh; } - - - return true; - } + break; + + case 'weekly': // 每周固定时间刷新 + // 获取本周的刷新时间 + const thisWeekRefresh = new Date(nowTime); + // 计算与本周指定星期几的差值 + const dayDiff = (thisWeekRefresh.getDay() - weeklyDay + 7) % 7; + thisWeekRefresh.setDate(thisWeekRefresh.getDate() - dayDiff); + thisWeekRefresh.setHours(weeklyHour, 0, 0, 0); + + // 如果当前时间已经过了本周的刷新时间 + if (nowTime >= thisWeekRefresh) { + shouldRefresh = lastTime < thisWeekRefresh; + } else { + // 否则检查上次完成时间是否在上周刷新之前 + const lastWeekRefresh = new Date(thisWeekRefresh); + lastWeekRefresh.setDate(lastWeekRefresh.getDate() - 7); + shouldRefresh = lastTime < lastWeekRefresh; + } + break; + + case 'monthly': // 每月固定时间刷新 + // 获取本月的刷新时间 + const thisMonthRefresh = new Date(nowTime); + // 设置为本月指定日期的凌晨 + thisMonthRefresh.setDate(monthlyDay); + thisMonthRefresh.setHours(monthlyHour, 0, 0, 0); + + // 如果当前时间已经过了本月的刷新时间 + if (nowTime >= thisMonthRefresh) { + shouldRefresh = lastTime < thisMonthRefresh; + } else { + // 否则检查上次完成时间是否在上月刷新之前 + const lastMonthRefresh = new Date(thisMonthRefresh); + lastMonthRefresh.setMonth(lastMonthRefresh.getMonth() - 1); + shouldRefresh = lastTime < lastMonthRefresh; + } + break; + + case 'custom': // 自定义小时数刷新 + shouldRefresh = (nowTime - lastTime) >= customHours * 3600 * 1000; + break; + + default: + throw new Error(`未知的刷新类型: ${refreshType}`); } - // 如果当前尝试未找到,且还有重试机会,则等待后重试 - if (attempt < retryCount) { - log.info(`第${attempt + 1}次尝试未找到文字"${targetText}",${retryInterval}ms后重试...`); - await sleep(retryInterval); + // 如果文件内容无效或不存在,视为需要刷新 + if (!content || isNaN(lastTime.getTime())) { + await file.writeText(filePath, ''); + shouldRefresh = true; } + + if (shouldRefresh) { + notification.send(`购买狗粮已经刷新,执行脚本`); + + + return true; + } else { + log.info(`购买狗粮未刷新`); + return false; + } + } catch (error) { - log.error(`点击文字"${targetText}"时发生错误: ${error.message}`); - if (attempt < retryCount) { - await sleep(retryInterval); + // 如果文件不存在,创建新文件并返回true(视为需要刷新) + const createResult = await file.writeText(filePath, ''); + if (createResult) { + log.info("创建新时间记录文件成功,执行脚本"); + return true; } + else throw new Error(`创建新文件失败`); } } - log.info(`未找到文字: "${targetText}",已尝试${retryCount + 1}次`); - return false; -} + // 购买圣遗物 + async function purChase(locationName) { + // 寻路 + log.info(`加载路径文件: ${locationName}`); + let filePath = `assets/Pathing/${locationName}.json`; + await pathingScript.runFile(filePath); + await sleep(1000); + if (locationName=='璃月购买狗粮2'){ + await sleep(1000); + keyDown("w"); + await sleep(600); + keyUp("w"); + await sleep(1000); + } + if (locationName=='纳塔购买狗粮'){ + await sleep(1000); + keyDown("a"); + await sleep(500); + keyUp("a"); + } + // 定义模板 + let fDialogueRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/Picture/F_Dialogue.png"), 1050, 400, 100, 400); + let shopDialogueRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/Picture/Shopping.png"), 1259, 540, 100, 400); + let shopDialogueRo2 = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/Picture/Shopping2.png"), 0, 0, 150, 100); + let conFirmRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/Picture/Confirm.png"), 1585, 1005, 31, 31); + // 定义一个函数识别并交互 NPC + async function checkFAlignment(fDialogueRo) { + let ra = captureGameRegion(); + let fRes = ra.find(fDialogueRo); + if (!fRes.isExist()) { + let f_attempts = null; // 初始化尝试次数 + while (f_attempts < 5) { // 最多尝试 4 次 + f_attempts++; + log.info(`当前尝试次数:${f_attempts}`); + if (f_attempts <= 3) { + // 第 1-3 次尝试 + await simulateKeyOperations("S", 200); // 后退 200 毫秒 + await sleep(200); + await simulateKeyOperations("W", 400); // 前进 400 毫秒 + await sleep(500); + } else if (f_attempts === 4) { + // 第 4 次尝试 + log.info("重新加载路径文件"); + await pathingScript.runFile(filePath); + await sleep(500); + } else { + // 第 5 次尝试,尝试次数已达上限 + log.warn("尝试次数已达上限"); + break; // 找到后退出循环 + } - -/** - * 判断任务是否已刷新 - * @param {string} filePath - 存储最后完成时间的文件路径 - * @param {object} options - 配置选项 - * @param {string} [options.refreshType] - 刷新类型: 'hourly'|'daily'|'weekly'|'monthly'|'custom' - * @param {number} [options.customHours] - 自定义小时数(用于'custom'类型) - * @param {number} [options.dailyHour=4] - 每日刷新的小时(0-23) - * @param {number} [options.weeklyDay=1] - 每周刷新的星期(0-6, 0是周日) - * @param {number} [options.weeklyHour=4] - 每周刷新的小时(0-23) - * @param {number} [options.monthlyDay=1] - 每月刷新的日期(1-31) - * @param {number} [options.monthlyHour=4] - 每月刷新的小时(0-23) - * @returns {Promise} - 是否已刷新 - */ -async function isTaskRefreshed(filePath, options = {}) { - const { - refreshType = 'hourly', // 默认每小时刷新 - customHours = 24, // 自定义刷新小时数默认24 - dailyHour = 4, // 每日刷新默认凌晨4点 - weeklyDay = 1, // 每周刷新默认周一(0是周日) - weeklyHour = 4, // 每周刷新默认凌晨4点 - monthlyDay = 1, // 每月刷新默认第1天 - monthlyHour = 4 // 每月刷新默认凌晨4点 - } = options; - - try { - // 读取文件内容 - let content = await file.readText(filePath); - const lastTime = new Date(content); - const nowTime = new Date(); - - - let shouldRefresh = false; - - - switch (refreshType) { - case 'hourly': // 每小时刷新 - shouldRefresh = (nowTime - lastTime) >= 3600 * 1000; - break; - - case 'daily': // 每天固定时间刷新 - // 检查是否已经过了当天的刷新时间 - const todayRefresh = new Date(nowTime); - todayRefresh.setHours(dailyHour, 0, 0, 0); - - // 如果当前时间已经过了今天的刷新时间,检查上次完成时间是否在今天刷新之前 - if (nowTime >= todayRefresh) { - shouldRefresh = lastTime < todayRefresh; - } else { - // 否则检查上次完成时间是否在昨天刷新之前 - const yesterdayRefresh = new Date(todayRefresh); - yesterdayRefresh.setDate(yesterdayRefresh.getDate() - 1); - shouldRefresh = lastTime < yesterdayRefresh; + // 检查是否找到 F 图标 + ra = captureGameRegion(); + fRes = ra.find(fDialogueRo); // 重新查找 F 图标 + if (fRes.isExist()) { + log.info("找到 F 图标"); + break; // 找到后退出循环 + } + log.warn(`尝试 ${f_attempts}:寻找 F 图标`); } - break; - - case 'weekly': // 每周固定时间刷新 - // 获取本周的刷新时间 - const thisWeekRefresh = new Date(nowTime); - // 计算与本周指定星期几的差值 - const dayDiff = (thisWeekRefresh.getDay() - weeklyDay + 7) % 7; - thisWeekRefresh.setDate(thisWeekRefresh.getDate() - dayDiff); - thisWeekRefresh.setHours(weeklyHour, 0, 0, 0); - - // 如果当前时间已经过了本周的刷新时间 - if (nowTime >= thisWeekRefresh) { - shouldRefresh = lastTime < thisWeekRefresh; - } else { - // 否则检查上次完成时间是否在上周刷新之前 - const lastWeekRefresh = new Date(thisWeekRefresh); - lastWeekRefresh.setDate(lastWeekRefresh.getDate() - 7); - shouldRefresh = lastTime < lastWeekRefresh; + + // 如果尝试次数用完仍未找到 F 图标,返回 false + if (!fRes.isExist()) { + log.warn("经过多次尝试后仍未找到 F 图标"); + return false; } - break; - - case 'monthly': // 每月固定时间刷新 - // 获取本月的刷新时间 - const thisMonthRefresh = new Date(nowTime); - // 设置为本月指定日期的凌晨 - thisMonthRefresh.setDate(monthlyDay); - thisMonthRefresh.setHours(monthlyHour, 0, 0, 0); - - // 如果当前时间已经过了本月的刷新时间 - if (nowTime >= thisMonthRefresh) { - shouldRefresh = lastTime < thisMonthRefresh; + } + return true + } + let isAligned = await checkFAlignment(fDialogueRo); + if(isAligned){ + // 进入对话选项 + for (let i = 0; i < 5; i++) { + // 最多 F 5次 + let captureRegion = captureGameRegion(); // 获取一张截图 + let res = captureRegion.Find(shopDialogueRo); + if (res.isEmpty()) { + keyPress("F"); + await sleep(1000); } else { - // 否则检查上次完成时间是否在上月刷新之前 - const lastMonthRefresh = new Date(thisMonthRefresh); - lastMonthRefresh.setMonth(lastMonthRefresh.getMonth() - 1); - shouldRefresh = lastTime < lastMonthRefresh; + res.click(); + log.info("已到达对话选项界面,点击商店图标({x},{y},{h},{w})", res.x, res.y, res.width, res.Height); + break; } - break; - - case 'custom': // 自定义小时数刷新 - shouldRefresh = (nowTime - lastTime) >= customHours * 3600 * 1000; - break; - - default: - throw new Error(`未知的刷新类型: ${refreshType}`); + await sleep(500); + } + // 进入商店界面 + for (let i = 0; i < 5; i++) { + // 最多 F 5次 + captureRegion = captureGameRegion(); // 获取一张截图 + res = captureRegion.Find(shopDialogueRo2); + if (res.isEmpty()) { + keyPress("F"); + await sleep(1000); + } else { + log.info("已到达商店界面"); + break; + } + await sleep(500); + } + if (locationName=='稻妻购买狗粮'){ + click(200, 400); await sleep(500); // 选择狗粮 + } + // 购买狗粮 + for (let i = 0; i < 5; i++) { + // 最多购买5次 + captureRegion = captureGameRegion(); // 获取一张截图 + res = captureRegion.Find(conFirmRo); + if (res.isEmpty()) { + log.info('圣遗物已售罄'); + break; + }else{ + // 识别到购买标识,模拟购买操作的后续点击 + await click(1600, 1020); + await sleep(1000); // 购买 + await click(1320, 780); + await sleep(1000); // 最终确认 + await click(1320, 780); + await sleep(1000); // 点击空白 + } + await sleep(500); + } + await genshin.returnMainUi(); } - - // 如果文件内容无效或不存在,视为需要刷新 - if (!content || isNaN(lastTime.getTime())) { - await file.writeText(filePath, ''); - shouldRefresh = true; - } - - if (shouldRefresh) { - notification.send(`购买狗粮已经刷新,执行脚本`); - - - return true; - } else { - log.info(`购买狗粮未刷新`); - return false; - } - - } catch (error) { - // 如果文件不存在,创建新文件并返回true(视为需要刷新) - const createResult = await file.writeText(filePath, ''); - if (createResult) { - log.info("创建新时间记录文件成功,执行脚本"); - return true; - } - else throw new Error(`创建新文件失败`); - } -} - - -//基本购买流程 - async function Shopping() { - await sleep(1500); - for (let j = 0; j < 4; j++) { - keyPress("F"); await sleep(1800);//对话 - } - for (let i = 0; i < 5; i++) { - click(1690, 1020); await sleep(500); // 购买 - click(1170, 780); await sleep(400); // 确定 - click(1690, 1020); await sleep(200); // 点击空白处 - } - keyPress("ESCAPE"); await sleep(2000); } - async function main() { + async function main() { + await genshin.returnMainUi(); if(settings.select1){ - await Purchase('蒙德购买狗粮'); - await Shopping(); + await purChase('蒙德购买狗粮'); } if(settings.select2){ - await Purchase('璃月购买狗粮1'); - await Shopping(); + await purChase('璃月购买狗粮1'); } if(settings.select3){ - await Purchase('璃月购买狗粮2'); - await sleep(1000); - keyDown("w"); - await sleep(600); - keyUp("w"); - await sleep(1000); - keyPress("F"); await sleep(1200); - keyPress("F"); await sleep(1800); - await clickTextInRegion("我想买些古董。", 1264, 532, 370, 160); - await sleep(500); - keyPress("F"); await sleep(1200); - keyPress("F"); await sleep(1800); - for (let i = 0; i < 5; i++) { - click(1690, 1020); await sleep(500); // 购买 - click(1170, 780); await sleep(400); // 确定 - click(1690, 1020); await sleep(200); // 点击空白处 - } - keyPress("ESCAPE"); await sleep(2000); + await purChase('璃月购买狗粮2'); } if(settings.select4){ - await Purchase('稻妻购买狗粮'); - await sleep(1500); - for (let j = 0; j < 5; j++) { - keyPress("F"); await sleep(1800);//对话 - } - click(200, 400); await sleep(500); // 选择狗粮 - for (let i = 0; i < 5; i++) { - click(1690, 1020); await sleep(500); // 购买 - click(1170, 780); await sleep(400); // 确定 - click(1690, 1020); await sleep(200); // 点击空白处 - } - keyPress("ESCAPE"); await sleep(2000); + await purChase('稻妻购买狗粮'); } if(settings.select5){ - await Purchase('须弥购买狗粮'); - await Shopping(); + await purChase('须弥购买狗粮'); } if(settings.select6){ - await Purchase('枫丹购买狗粮'); - await Shopping(); + await purChase('枫丹购买狗粮'); } if(settings.select7){ - await Purchase('纳塔购买狗粮'); - await sleep(1000); - keyDown("a"); - await sleep(500); - keyUp("a"); - await Shopping(); + await purChase('纳塔购买狗粮'); } if(settings.select8){ - await Purchase('挪德卡莱购买狗粮'); - await Shopping(); + await purChase('挪德卡莱购买狗粮'); } await file.writeText(recordPath, new Date().toISOString()); } -userName = getUserName(); -const recordPath = `assets/${userName}.txt`; -//每周四4点刷新 -if( await isTaskRefreshed(recordPath, { - refreshType: 'weekly', - weeklyDay: 4, // 周四 - weeklyHour: 4 // 凌晨4点 -})){ -await main(); -} - + userName = await getUserName(); + const recordPath = `assets/${userName}.txt`; + //每周四4点刷新 + if( await isTaskRefreshed(recordPath, { + refreshType: 'weekly', + weeklyDay: 4, // 周四 + weeklyHour: 4 // 凌晨4点 + })){ + await main(); + } })(); diff --git a/repo/js/PurchaseArtifacts/manifest.json b/repo/js/PurchaseArtifacts/manifest.json index f38199e6c..38d149047 100644 --- a/repo/js/PurchaseArtifacts/manifest.json +++ b/repo/js/PurchaseArtifacts/manifest.json @@ -1,8 +1,8 @@ { "manifest_version": 1, "name": "自动购买狗粮(8点位)", - "version": "2.1", - "bgi_version": "0.50", + "version": "2.2", + "bgi_version": "0.51", "description": "自动购买狗粮", "authors": [ {