From a94550b01d811acf3e05de4dff75e175e1eb6359 Mon Sep 17 00:00:00 2001 From: Zichao Lin Date: Sat, 4 Jan 2025 18:45:16 +0800 Subject: [PATCH] Support Zenless Zone Zero --- .gitignore | 3 +- README.md | 12 ++-- src/config.js | 132 +++++++++++++++++++++++++++++++-------- src/index.js | 168 +++++++++++++++++++++++++++++++++++--------------- src/util.js | 2 +- 5 files changed, 236 insertions(+), 81 deletions(-) diff --git a/.gitignore b/.gitignore index 93fb242..de6a908 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ configs/ node_modules/ pnpm-lock.yaml -yarn.lock \ No newline at end of file +yarn.lock +.vscode/ \ No newline at end of file diff --git a/README.md b/README.md index 2f10044..3d8083f 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,18 @@ -# Genshin Cloud Game Helper +# Hoyo Cloud Game Helper -![Genshin Cloud Game Helper](https://socialify.git.ci/earthjasonlin/GenshinCloudGameHelper/image?forks=1&language=1&name=1&owner=1&stargazers=1&theme=Light) +![Genshin Cloud Game Helper](https://socialify.git.ci/earthjasonlin/HoyoCloudGameHelper/image?forks=1&language=1&name=1&owner=1&stargazers=1&theme=Light) -[《云·原神》](https://mhyy.mihoyo.com/)自动签到脚本 +[米哈云游](https://mhyy.mihoyo.com/)自动签到脚本 **⚠️ 请不要进行宣传,谢谢!一旦发现宣传就跑路!** -这是一个可以帮助你每天自动进行云原神签到的脚本,自动获取每日的 15 分钟(600 分钟后无法获取) +这是一个可以帮助你每天自动进行云原神、云绝区零签到的脚本,自动获取每日的 15 分钟(600 分钟后无法获取) ## 赞助 点击下面的 Badge 其中一个就可以跳转到相应页面,感谢老板的支持! -前往爱发电赞助 使用微信赞助 +前往爱发电赞助 ## 免责声明 @@ -28,4 +28,4 @@ ## Stargazers over time -[![Stargazers over time](https://starchart.cc/earthjasonlin/GenshinCloudGameHelper.svg)](https://starchart.cc/earthjasonlin/GenshinCloudGameHelper) +[![Stargazers over time](https://starchart.cc/earthjasonlin/HoyoCloudGameHelper.svg)](https://starchart.cc/earthjasonlin/HoyoCloudGameHelper) diff --git a/src/config.js b/src/config.js index d80cde2..13197c4 100644 --- a/src/config.js +++ b/src/config.js @@ -3,36 +3,66 @@ const fs = require("fs"); const { default: axios } = require("axios"); const { log } = require("./util"); -exports.ListNotificationURL = +exports.hk4e_ListNotificationURL = "https://api-cloudgame.mihoyo.com/hk4e_cg_cn/gamer/api/listNotifications?status=NotificationStatusUnread&type=NotificationTypePopup&is_sort=true"; -exports.AckNotificationURL = +exports.hk4e_AckNotificationURL = "https://api-cloudgame.mihoyo.com/hk4e_cg_cn/gamer/api/ackNotification"; -exports.WalletURL = +exports.hk4e_WalletURL = "https://api-cloudgame.mihoyo.com/hk4e_cg_cn/wallet/wallet/get?cost_method=0"; -exports.AnnouncementURL = - "https://api-cloudgame.mihoyo.com/hk4e_cg_cn/gamer/api/getAnnouncementInfo"; -// Here must be an earlier version so that the response won't be null -exports.AppVersionURL = +exports.hk4e_AppVersionURL = "https://api-takumi.mihoyo.com/ptolemaios/api/getLatestRelease?app_id=1953443910&app_version=3.8.0&channel=mihoyo"; -exports.ListNotification = async function (header) { +exports.nap_ListNotificationURL = + "https://cg-nap-api.mihoyo.com/nap_cn/cg/gamer/api/listNotifications?status=NotificationStatusUnread&type=NotificationTypePopup&is_sort=true"; +exports.nap_AckNotificationURL = + "https://cg-nap-api.mihoyo.com/nap_cn/cg/gamer/api/ackNotification"; +exports.nap_WalletURL = + "https://cg-nap-api.mihoyo.com/nap_cn/cg/wallet/wallet/get?cost_method=0"; +exports.nap_AppVersionURL = + "https://api-takumi.mihoyo.com/ptolemaios_api/api/getLatestRelease?app_id=1953458691&app_version=1.4.0&channel=appstore"; + +exports.hk4e_ListNotification = async function (header) { let tmp = ( - await axios(exports.ListNotificationURL, { + await axios(exports.hk4e_ListNotificationURL, { headers: header, }) ).data; tmp.StringVersion = JSON.stringify(tmp); return tmp; }; -exports.AckNotification = async function (header, id) { +exports.nap_ListNotification = async function (header) { + let tmp = ( + await axios(exports.nap_ListNotificationURL, { + headers: header, + }) + ).data; + tmp.StringVersion = JSON.stringify(tmp); + return tmp; +}; +exports.hk4e_AckNotification = async function (header, id) { let data = `{"id":"${id}"}`; - await axios.post(exports.AckNotificationURL, data, { + await axios.post(exports.hk4e_AckNotificationURL, data, { headers: header, }); }; -exports.Wallet = async function (header) { +exports.nap_AckNotification = async function (header, id) { + let data = `{"id":"${id}"}`; + await axios.post(exports.nap_AckNotificationURL, data, { + headers: header, + }); +}; +exports.hk4e_Wallet = async function (header) { let tmp = ( - await axios(exports.WalletURL, { + await axios(exports.hk4e_WalletURL, { + headers: header, + }) + ).data; + tmp.StringVersion = JSON.stringify(tmp); + return tmp; +}; +exports.nap_Wallet = async function (header) { + let tmp = ( + await axios(exports.nap_WalletURL, { headers: header, }) ).data; @@ -40,11 +70,17 @@ exports.Wallet = async function (header) { return tmp; }; -exports.AppVersion = async function () { - let tmp = (await axios(exports.AppVersionURL)).data; +exports.hk4e_AppVersion = async function () { + let tmp = (await axios(exports.hk4e_AppVersionURL)).data; tmp.StringVersion = JSON.stringify(tmp); return tmp; }; +exports.nap_AppVersion = async function () { + let tmp = (await axios(exports.nap_AppVersionURL)).data; + tmp.StringVersion = JSON.stringify(tmp); + return tmp; +}; + var configKeys = [ "token", "client_type", @@ -68,30 +104,55 @@ exports.getGlobalConfig = function () { return JSON.parse(globalConfig); }; -exports.getConfigs = function () { +exports.hk4e_getConfigs = function () { try { - var configsList = fs.readdirSync("configs"); + var configsList = fs.readdirSync("configs/hk4e"); configsList = configsList.filter((file) => file.endsWith(".json")); } catch (e) { if ( e == "Error: ENOENT: no such file or directory, scandir 'configs'" ) { - log.error(`读取配置失败!找不到configs文件夹`); + log.error(`读取配置失败!找不到configs/hk4e文件夹`); } else { log.error(`读取配置失败!错误信息:${e}`); } exit(); } - log.info(`检测到${configsList.length}个配置文件:`); + log.info(`检测到${configsList.length}个原神配置文件:`); configsList.forEach((file) => { log.info(`${file}`); }); var configs = {}; configsList.forEach((file) => { - configs[file] = JSON.parse(fs.readFileSync(`configs/${file}`)); + configs[file] = JSON.parse(fs.readFileSync(`configs/hk4e/${file}`)); }); return configs; }; +exports.nap_getConfigs = function () { + try { + var configsList = fs.readdirSync("configs/nap"); + configsList = configsList.filter((file) => file.endsWith(".json")); + } catch (e) { + if ( + e == "Error: ENOENT: no such file or directory, scandir 'configs'" + ) { + log.error(`读取配置失败!找不到configs/nap文件夹`); + } else { + log.error(`读取配置失败!错误信息:${e}`); + } + exit(); + } + log.info(`检测到${configsList.length}个绝区零配置文件:`); + configsList.forEach((file) => { + log.info(`${file}`); + }); + var configs = {}; + configsList.forEach((file) => { + configs[file] = JSON.parse(fs.readFileSync(`configs/nap/${file}`)); + }); + return configs; +}; + exports.checkConfigs = function (configs) { for (file in configs) { var configThis = configs[file]; @@ -109,7 +170,7 @@ exports.checkConfigs = function (configs) { } }; -exports.makeHeader = function (data, appversion) { +exports.hk4e_makeHeader = function (data, appversion) { return { "x-rpc-combo_token": data.token, "x-rpc-client_type": data.client_type, @@ -131,6 +192,29 @@ exports.makeHeader = function (data, appversion) { "User-Agent": "okhttp/4.10.0" }; }; +// iOS +exports.nap_makeHeader = function (data, appversion) { + return { + "x-rpc-combo_token": data.token, + "x-rpc-client_type": data.client_type, + "x-rpc-app_version": appversion, + "x-rpc-sys_version": data.sys_version, + "x-rpc-channel": data.channel, + "x-rpc-device_id": data.device_id, + "x-rpc-device_name": data.device_name, + "x-rpc-device_model": data.device_model, + "x-rpc-cg_game_id": 9000357, + "x-rpc-cg_game_biz": "nap_cn", + "x-rpc-op_biz": "clgm_nap-cn", + "x-rpc-language": "zh-cn", + "x-rpc-vendor_id": 2, + "x-rpc-cps": "appstore", + Host: "cg-nap-api.mihoyo.com", + Connection: "Keep-Alive", + "Accept-Encoding": "gzip, deflate, br", + "User-Agent": "CloudGame/2 CFNetwork/1410.1 Darwin/22.6.0" + }; +}; exports.SendLog = function ( transporter, @@ -142,7 +226,7 @@ exports.SendLog = function ( ) { transporter.sendMail( { - from: `"Genshin Cloud Game Helper" <${mailfrom}>`, //邮件来源 + from: `"Hoyo Cloud Game Helper" <${mailfrom}>`, //邮件来源 to: mailto, //邮件发送到哪里,多个邮箱使用逗号隔开 subject: `今日已签到${successNum}/${totalNum}名用户`, // 邮件主题 text: "", // 存文本类型的邮件正文 @@ -160,9 +244,9 @@ exports.SendLog = function ( exports.SendResult = function (transporter, mailfrom, mailto, content, key) { transporter.sendMail( { - from: `"Genshin Cloud Game Helper" <${mailfrom}>`, //邮件来源 + from: `"Hoyo Cloud Game Helper" <${mailfrom}>`, //邮件来源 to: mailto, //邮件发送到哪里,多个邮箱使用逗号隔开 - subject: `Genshin Cloud Game Helper`, // 邮件主题 + subject: `Hoyo Cloud Game Helper`, // 邮件主题 text: `${content}`, // 存文本类型的邮件正文 }, (error) => { diff --git a/src/index.js b/src/index.js index 21339a4..cfe2c4b 100644 --- a/src/index.js +++ b/src/index.js @@ -1,12 +1,18 @@ const { - getConfigs, checkConfigs, - makeHeader, - ListNotification, - AckNotification, - Wallet, + hk4e_getConfigs, + hk4e_makeHeader, + hk4e_ListNotification, + hk4e_AckNotification, + hk4e_Wallet, + hk4e_AppVersion, + nap_getConfigs, + nap_makeHeader, + nap_ListNotification, + nap_AckNotification, + nap_Wallet, + nap_AppVersion, SendLog, - AppVersion, getGlobalConfig, SendResult, } = require("./config"); @@ -19,31 +25,34 @@ const nodemailer = require("nodemailer"); log.info("开始获取全局配置"); var globalConfig = getGlobalConfig(); log.info("获取成功"); - if (globalConfig.sendMail == true) { - log.info("组装邮件发射器"); - var transporter = nodemailer.createTransport({ - host: globalConfig.mailConfig.smtpServer, - port: globalConfig.mailConfig.smtpPort, - secure: globalConfig.mailConfig.smtpSecure, - auth: { - user: globalConfig.mailConfig.user, - pass: globalConfig.mailConfig.pass, - }, - }); - } + log.info("组装邮件发射器"); + var transporter = nodemailer.createTransport({ + host: globalConfig.mailConfig.smtpServer, + port: globalConfig.mailConfig.smtpPort, + secure: globalConfig.mailConfig.smtpSecure, + auth: { + user: globalConfig.mailConfig.user, + pass: globalConfig.mailConfig.pass, + }, + }); var minDelay = globalConfig.minDelay; var maxDelay = globalConfig.maxDelay; - var configs = getConfigs(); - log.info(`正在检测配置有效性`); - checkConfigs(configs); + var hk4e_configs = hk4e_getConfigs(); + var nap_configs = nap_getConfigs(); + log.info(`正在检测原神配置有效性`); + checkConfigs(hk4e_configs); + log.info("检测完毕!"); + log.info(`正在检测绝区零配置有效性`); + checkConfigs(nap_configs); log.info("检测完毕!"); log.info("正在获取版本号"); - var appversion = await AppVersion(); - appversion = appversion.data.package_version; - log.info(`获取成功!当前版本号:${appversion}`); - var successNum = 0, - totalNum = 0; - for (key in configs) { + var hk4e_appversion = await hk4e_AppVersion(); + var nap_appversion = await nap_AppVersion(); + hk4e_appversion = hk4e_appversion.data.package_version; + nap_appversion = nap_appversion.data.package_version; + log.info(`获取成功!当前版本号:原神${hk4e_appversion},绝区零${nap_appversion}`); + var successNum = 0, totalNum = 0; + for (key in hk4e_configs) { var delay = Math.round( Math.random() * (maxDelay - minDelay) + minDelay ); @@ -51,53 +60,114 @@ const nodemailer = require("nodemailer"); await sleep(delay); totalNum++; log.info(`${key} - 正在执行配置 ${key}`); - log.info(`${key} - 尝试签到……`); - var header = makeHeader(configs[key], appversion); - var WalletRespond = await Wallet(header); + log.info(`${key} - 尝试签到原神……`); + var hk4e_header = hk4e_makeHeader(hk4e_configs[key], hk4e_appversion); + var hk4e_WalletRespond = await hk4e_Wallet(hk4e_header); addLogContent( - `${key} Wallet返回体
${JSON.stringify( - WalletRespond + `${key} hk4e_Wallet返回体
${JSON.stringify( + hk4e_WalletRespond )}
` ); - if (WalletRespond.data != null) { - var NotificationRespond = await ListNotification(header); + if (hk4e_WalletRespond.data != null) { + var hk4e_NotificationRespond = await hk4e_ListNotification(hk4e_header); addLogContent( - `${key} Notification返回体
${JSON.stringify( - NotificationRespond + `${key} hk4e_Notification返回体
${JSON.stringify( + hk4e_NotificationRespond )}
` ); successNum++; log.info( - `${key} - 签到完毕! 获得时长:${WalletRespond.data.free_time.send_freetime}分钟,总时长:${WalletRespond.data.free_time.free_time}分钟` + `${key} - 签到完毕! 原神获得时长:${hk4e_WalletRespond.data.free_time.send_freetime}分钟,总时长:${hk4e_WalletRespond.data.free_time.free_time}分钟` ); - if (configs[key].email != null) { + if (hk4e_configs[key].email != null) { SendResult( transporter, globalConfig.mailConfig.user, - configs[key].email, - `签到完毕! 获得时长:${WalletRespond.data.free_time.send_freetime}分钟,总时长:${WalletRespond.data.free_time.free_time}分钟`, + hk4e_configs[key].email, + `签到完毕! 获得时长:${hk4e_WalletRespond.data.free_time.send_freetime}分钟,总时长:${hk4e_WalletRespond.data.free_time.free_time}分钟`, key ); } - let NotificationLength = NotificationRespond.data.list.length; - let postHeader = header; - Object.assign(postHeader, { + let hk4e_NotificationLength = hk4e_NotificationRespond.data.list.length; + let hk4e_postHeader = hk4e_header; + Object.assign(hk4e_postHeader, { "Content-Length": 28, "Content-Type": "application/json; charset=UTF-8", }); - for (var i = 0; i < NotificationLength; i++) { - AckNotification( - postHeader, - NotificationRespond.data.list[i].id + for (var i = 0; i < hk4e_NotificationLength; i++) { + hk4e_AckNotification( + hk4e_postHeader, + hk4e_NotificationRespond.data.list[i].id ); } } else { log.error(`${key} - 签到失败`); - if (configs[key].email != null) { + if (hk4e_configs[key].email != null) { SendResult( transporter, globalConfig.mailConfig.user, - configs[key].email, + hk4e_configs[key].email, + "签到失败", + key + ); + } + } + } + for (key in nap_configs) { + var delay = Math.round( + Math.random() * (maxDelay - minDelay) + minDelay + ); + log.info(`暂停:${delay}毫秒`); + await sleep(delay); + totalNum++; + log.info(`${key} - 正在执行配置 ${key}`); + log.info(`${key} - 尝试签到绝区零……`); + var nap_header = nap_makeHeader(nap_configs[key], nap_appversion); + var nap_WalletRespond = await nap_Wallet(nap_header); + addLogContent( + `${key} nap_Wallet返回体
${JSON.stringify( + nap_WalletRespond + )}
` + ); + if (nap_WalletRespond.data != null) { + var nap_NotificationRespond = await nap_ListNotification(nap_header); + addLogContent( + `${key} nap_Notification返回体
${JSON.stringify( + nap_NotificationRespond + )}
` + ); + successNum++; + log.info( + `${key} - 签到完毕! 绝区零获得时长:${nap_WalletRespond.data.free_time.send_freetime}分钟,总时长:${nap_WalletRespond.data.free_time.free_time}分钟` + ); + if (nap_configs[key].email != null) { + SendRnapt( + transporter, + globalConfig.mailConfig.user, + nap_configs[key].email, + `签到完毕! 获得时长:${nap_WalletRespond.data.free_time.send_freetime}分钟,总时长:${nap_WalletRespond.data.free_time.free_time}分钟`, + key + ); + } + let nap_NotificationLength = nap_NotificationRespond.data.list.length; + let nap_postHeader = nap_header; + Object.assign(nap_postHeader, { + "Content-Length": 28, + "Content-Type": "application/json; charset=UTF-8", + }); + for (var i = 0; i < nap_NotificationLength; i++) { + nap_AckNotification( + nap_postHeader, + nap_NotificationRespond.data.list[i].id + ); + } + } else { + log.error(`${key} - 签到失败`); + if (nap_configs[key].email != null) { + SendResult( + transporter, + globalConfig.mailConfig.user, + nap_configs[key].email, "签到失败", key ); diff --git a/src/util.js b/src/util.js index 87c721f..4adf3b9 100644 --- a/src/util.js +++ b/src/util.js @@ -1,5 +1,5 @@ const reggol = require("reggol"); -const baseLogger = new reggol("GenshinCloudGameHelper"); +const baseLogger = new reggol("HoyoCloudGameHelper"); let logContent = ``; exports.addLogContent = function (content) { logContent += content;