Compare commits

..

19 Commits

Author SHA1 Message Date
c0b46611e4 remove new gained time 2025-01-11 16:31:21 +08:00
6025465912 only send email to user when email enabled globally 2025-01-04 18:54:07 +08:00
a94550b01d Support Zenless Zone Zero 2025-01-04 18:45:16 +08:00
1c21596315 wait 10s before sending email to admin (fix #6) 2023-10-28 12:30:46 +08:00
ef7235c006 BREAKING: change API to Android client 2023-10-22 14:47:26 +08:00
88d4474728 move sleep process (fix #5) 2023-10-22 13:36:45 +08:00
1119581d19 update license 2023-10-21 19:56:31 +08:00
15ca17e903 fix package.json 2023-10-21 19:54:22 +08:00
41280019f6 log content contains config name 2023-10-20 23:04:16 +08:00
6bcb19e8e1 log content contains config name 2023-10-20 22:50:59 +08:00
ee3321c7e8 log content 2023-10-20 22:46:48 +08:00
2dbcab998f only read files end with json 2023-10-20 22:42:54 +08:00
f8e47879f1 user notifications 2023-10-20 22:33:34 +08:00
dd86b82e1c format code 2023-10-20 21:57:43 +08:00
5c8a9eb55e add random delay (fix #1) 2023-10-20 21:56:21 +08:00
2ed58716bf fix log content 2023-09-20 17:13:11 +08:00
2f5bac484b update log 2023-09-01 12:45:01 +08:00
616c94ddc9 update readme 2023-08-30 17:30:16 +08:00
723fba3763 update readme 2023-08-30 17:22:43 +08:00
11 changed files with 469 additions and 299 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@ configs/
node_modules/ node_modules/
pnpm-lock.yaml pnpm-lock.yaml
yarn.lock yarn.lock
.vscode/

View File

@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2022 HuanLinMaster Copyright (c) 2022-2023 HuanLinMaster, earthjasonlin
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

113
README.md
View File

@ -1,112 +1,31 @@
# Genshin Cloud Game Helper # Hoyo Cloud Game Helper
每天帮你获取 15 分钟云原神时间~ ![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/)自动签到脚本
### 全局配置 global.json **⚠️ 请不要进行宣传,谢谢!一旦发现宣传就跑路!**
``` 这是一个可以帮助你每天自动进行云原神、云绝区零签到的脚本,自动获取每日的 15 分钟600 分钟后无法获取)
{
"sendMail": true,
"mailConfig": {
"user":"",
"pass":"",
"mailto":"",
"smtpServer":"",
"smtpPort":"",
"smtpSecure":true
}
}
```
> sendMail 一个 bool 代表是否在运行结束后将结果发送至指定邮箱false 时 mailConfig 内的内容可不填 ## 赞助
> mailConfig 具体配置
>
> > user 发送方邮箱
> >
> > pass 有授权码的填授权码,没有的填密码,填了密码报错了找授权码
> >
> > mailto 接收方邮箱
> >
> > smtpServer 发送邮件时使用的 smtp 服务器地址
> >
> > smtpPort smtp 服务器端口
> >
> > smtpSecure 如果 smtp 服务器使用 SSL/TLS那么为 true如果使用 STARTTLS 或不使用加密,那么为 false
对于常用的邮件而言,配置列举如下 点击下面的 Badge 其中一个就可以跳转到相应页面,感谢老板的支持!
| 服务 | server | port | secure | <a href="https://afdian.net/a/earthjasonlin"><img src="https://img.shields.io/badge/%E7%88%B1%E5%8F%91%E7%94%B5-earthjasonlin-%238e8cd8?style=for-the-badge" alt="前往爱发电赞助" width=auto height=auto border="0" /></a>
|:-----:|:------------:|:-------:|:------:|
| QQ 邮箱 | smtp.qq.com | 465/587 | true |
| 网易邮箱 | smtp.163.com | 465 | true |
| ... | ... | ... | ... |
其余邮箱服务的配置可以在对应服务商的帮助文档中找到 ## 免责声明
### 用户配置 一旦你 fork 了本仓库则代表你同意以下内容:
先放一个配置模板 - 所有账号被封禁的情况由使用者自行承担
``` - 一切由使用本脚本造成的后果由使用者自行承担
{
"token":"",
"client_type":"",
"device_name":"",
"device_model":"",
"device_id":"",
"sys_version":"",
"channel":""
}
```
具体数据 请看“抓包”环节 ## Contributions
> token 是在云原神登录后用于验证的标记 [![Contribution](https://repobeats.axiom.co/api/embed/a5d4b41b1ca14049d54b93ad9d00fe478f6154ec.svg "Repobeats analytics image")](#)
> client_type 1 代表 ios 设备 2 代表 android&鸿蒙设备
> device_name 设备名称
> device_model 设备型号
> device_id 在米哈游服务器中注册的 uuid
> sys_version 系统版本 android&鸿蒙中为系统版本 ios 设备中为 ios 版本
> channel 下载渠道 ios 设备填"app store" android&鸿蒙填"mihoyo"(以抓包为准,我也不知道渠道服是不是这个)
### 抓包 ## Stargazers over time
> > # ios [![Stargazers over time](https://starchart.cc/earthjasonlin/HoyoCloudGameHelper.svg)](https://starchart.cc/earthjasonlin/HoyoCloudGameHelper)
> >
> > App Store 中下载应用 Stream用于抓包
> > 然后看视频吧
> > 看不了/不显示的点右边 https://hzsj.coding.net/p/ayakaturtleshop/d/PublicResource/git/raw/master/c9f1a9b91951b0f1c2da8f3817274074.mp4?download=false
> > <video src="https://hzsj.coding.net/p/ayakaturtleshop/d/PublicResource/git/raw/master/c9f1a9b91951b0f1c2da8f3817274074.mp4?download=false"></video>
>
> # android&鸿蒙
>
> > (来自 https://bili33.top/posts/MHYY-AutoCheckin-Manual)
> > 因为云原神是在手机上运行的,所以你需要安装一个手机上的抓包软件(例如 HttpCanary或者如果你能够用 fiddler 电脑运行去抓也行)
> > [![看就完了](https://cdn.bilicdn.tk/gh/Vikutorika/assets@master/img/Github/MHYY-AutoCheckin/HTTPCANARY-Result.jpg?download=false)]
> > 一定要记得装抓包软件提供的证书,要不然解不了 SSL 连接,一定要先登录并成功进去了再启动抓包软件!!!
> > [![看就完了](https://cdn.bilicdn.tk/gh/Vikutorika/assets@master/img/Github/MHYY-AutoCheckin/HTTPS-REQUEST-RESULT.png?download=false)]
> > 这里面只要是个 HTTP 链接,随便一个里面都有我们所需要的东西,这里我就点开了一个链接,在请求里面有所有我们需要的东西,而解释我都写在图片里面了
二者抓到的包差不多,抓到包之后有以下对应关系
```-
{
"token":"x-rpc-combo_token",
"client_type":"x-rpc-client_type",
"device_name":"x-rpc-device_name",
"device_model":"x-rpc-device_model",
"device_id":"x-rpc-device_id",
"sys_version":"x-rpc-sys_version",
"channel":"x-rpc-channel"
}
```
对着填进去就完了
接着在 configs 文件夹里创建任意一个 json 文件,将配置填进去
如果想一次性签到 n 个用户,创建不同的 json 文件即可,程序会自动扫描 configs 文件夹下面的文件
## 另外
程序会自动获取最新的云原神版本,确保数据与用户一样

View File

@ -1,9 +1,10 @@
{ {
"token":"", "token": "",
"client_type":"", "client_type": "",
"device_name":"", "device_name": "",
"device_model":"", "device_model": "",
"device_id":"", "device_id": "",
"sys_version":"", "sys_version": "",
"channel":"" "channel": "",
"email": ""
} }

View File

@ -1,11 +1,13 @@
{ {
"minDelay": 1000,
"maxDelay": 5000,
"sendMail": false, "sendMail": false,
"mailConfig": { "mailConfig": {
"user":"", "user": "",
"pass":"", "pass": "",
"mailto":"", "mailto": "",
"smtpServer":"", "smtpServer": "",
"smtpPort":"", "smtpPort": "",
"smtpSecure":true "smtpSecure": true
} }
} }

4
package-lock.json generated
View File

@ -1,11 +1,11 @@
{ {
"name": "genshincloudgamehelpper", "name": "genshincloudgamehelper",
"version": "1.0.0", "version": "1.0.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "genshincloudgamehelpper", "name": "genshincloudgamehelper",
"version": "1.0.0", "version": "1.0.0",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {

View File

@ -1,22 +1,22 @@
{ {
"name": "genshincloudgamehelpper", "name": "genshincloudgamehelper",
"version": "1.0.0", "version": "1.0.0",
"description": "每天帮你获取15分钟云原神时间~", "description": "每天帮你获取15分钟云原神时间~",
"main": "index.js", "main": "src/index.js",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/HuanLinMaster/GenshinCloudGameHelpper.git" "url": "git+https://git.loliquq.cn/earthjasonlin/GenshinCloudGameHelper.git"
}, },
"keywords": [], "keywords": [],
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"bugs": { "bugs": {
"url": "https://github.com/HuanLinMaster/GenshinCloudGameHelpper/issues" "url": "https://git.loliquq.cn/earthjasonlin/GenshinCloudGameHelper/issues"
}, },
"homepage": "https://github.com/HuanLinMaster/GenshinCloudGameHelpper#readme", "homepage": "https://git.loliquq.cn/earthjasonlin/GenshinCloudGameHelper#readme",
"dependencies": { "dependencies": {
"axios": "^1.5.0", "axios": "^1.5.0",
"nodemailer": "^6.7.6", "nodemailer": "^6.7.6",

View File

@ -1,140 +1,259 @@
const { exit } = require("process") const { exit } = require("process");
const fs = require("fs") const fs = require("fs");
const { default: axios } = require("axios") const { default: axios } = require("axios");
const { log } = require("./logger") const { log } = require("./util");
exports.ListNotificationURL = 'https://api-cloudgame.mihoyo.com/hk4e_cg_cn/gamer/api/listNotifications?is_sort=true&source=NotificationSourceUnknown&status=NotificationStatusUnread&type=NotificationTypePopup' exports.hk4e_ListNotificationURL =
exports.AckNotificationURL = 'https://api-cloudgame.mihoyo.com/hk4e_cg_cn/gamer/api/ackNotification' "https://api-cloudgame.mihoyo.com/hk4e_cg_cn/gamer/api/listNotifications?status=NotificationStatusUnread&type=NotificationTypePopup&is_sort=true";
exports.WalletURL = 'https://api-cloudgame.mihoyo.com/hk4e_cg_cn/wallet/wallet/get?cost_method=COST_METHOD_UNSPECIFIED' exports.hk4e_AckNotificationURL =
exports.AnnouncementURL = 'https://api-cloudgame.mihoyo.com/hk4e_cg_cn/gamer/api/getAnnouncementInfo' "https://api-cloudgame.mihoyo.com/hk4e_cg_cn/gamer/api/ackNotification";
// Here must be an earlier version so that the response won't be null exports.hk4e_WalletURL =
exports.AppVersionURL = 'https://api-takumi.mihoyo.com/ptolemaios/api/getLatestRelease?app_id=1953443910&app_version=3.8.0&channel=mihoyo' "https://api-cloudgame.mihoyo.com/hk4e_cg_cn/wallet/wallet/get?cost_method=0";
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 =
let tmp = (await axios(exports.ListNotificationURL,{ "https://cg-nap-api.mihoyo.com/nap_cn/cg/gamer/api/listNotifications?status=NotificationStatusUnread&type=NotificationTypePopup&is_sort=true";
headers:header exports.nap_AckNotificationURL =
})).data; "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.hk4e_ListNotificationURL, {
headers: header,
})
).data;
tmp.StringVersion = JSON.stringify(tmp); tmp.StringVersion = JSON.stringify(tmp);
return 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}"}`; let data = `{"id":"${id}"}`;
await axios.post(exports.AckNotificationURL, data,{ await axios.post(exports.hk4e_AckNotificationURL, data, {
headers:header headers: header,
}); });
} };
exports.Wallet = async function(header) { exports.nap_AckNotification = async function (header, id) {
let tmp = (await axios(exports.WalletURL,{ let data = `{"id":"${id}"}`;
headers:header await axios.post(exports.nap_AckNotificationURL, data, {
})).data; headers: header,
});
};
exports.hk4e_Wallet = async function (header) {
let tmp = (
await axios(exports.hk4e_WalletURL, {
headers: header,
})
).data;
tmp.StringVersion = JSON.stringify(tmp); tmp.StringVersion = JSON.stringify(tmp);
return tmp; return tmp;
} };
exports.Announcement = async function(header) { exports.nap_Wallet = async function (header) {
let tmp = (await axios(exports.AnnouncementURL,{ let tmp = (
headers:header await axios(exports.nap_WalletURL, {
})).data; headers: header,
})
).data;
tmp.StringVersion = JSON.stringify(tmp); tmp.StringVersion = JSON.stringify(tmp);
return tmp; 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); tmp.StringVersion = JSON.stringify(tmp);
return 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 = [ var configKeys = [
"token", "token",
"client_type", "client_type",
"device_name", "device_name",
"device_model", "device_model",
"sys_version", "sys_version",
"channel" "channel",
] ];
exports.getGlobalConfig = function() { exports.getGlobalConfig = function () {
try { try {
var globalConfig = fs.readFileSync("global.json") var globalConfig = fs.readFileSync("global.json");
} catch(e) { } catch (e) {
if(e.toString().includes("Error: ENOENT: no such file or directory")) { if (e.toString().includes("Error: ENOENT: no such file or directory")) {
log.error(`读取配置失败!找不到全局配置文件`) log.error(`读取配置失败找不到全局配置文件`);
} else { } else {
log.error(`读取配置失败!错误信息:${e}`); log.error(`读取配置失败错误信息:${e}`);
} }
exit() exit();
} }
return JSON.parse(globalConfig); return JSON.parse(globalConfig);
} };
exports.getConfigs = function(){ exports.hk4e_getConfigs = function () {
try { try {
var configsList = fs.readdirSync("configs") var configsList = fs.readdirSync("configs/hk4e");
} catch(e) { configsList = configsList.filter((file) => file.endsWith(".json"));
if(e == "Error: ENOENT: no such file or directory, scandir 'configs'") { } catch (e) {
log.error(`读取配置失败!找不到configs文件夹`) if (
e == "Error: ENOENT: no such file or directory, scandir 'configs'"
) {
log.error(`读取配置失败找不到configs/hk4e文件夹`);
} else { } else {
log.error(`读取配置失败!错误信息:${e}`); log.error(`读取配置失败错误信息:${e}`);
} }
exit() exit();
} }
log.info(`检测到${configsList.length}个配置文件:`) log.info(`检测到${configsList.length}原神配置文件:`);
configsList.forEach(file => { configsList.forEach((file) => {
log.info(`${file}`) log.info(`${file}`);
}) });
var configs = {} var configs = {};
configsList.forEach(file => { configsList.forEach((file) => {
configs[file] = JSON.parse(fs.readFileSync(`configs/${file}`)) configs[file] = JSON.parse(fs.readFileSync(`configs/hk4e/${file}`));
}) });
return configs return configs;
} };
exports.checkConfigs = function(configs){ exports.nap_getConfigs = function () {
for(file in configs) { 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]; var configThis = configs[file];
for(key in configKeys) { for (key in configKeys) {
if(configThis[configKeys[key]] == "" || configThis[configKeys[key]] == undefined || configThis[configKeys[key]] == null || configThis[configKeys[key]] == NaN) { if (
configThis[configKeys[key]] == "" ||
configThis[configKeys[key]] == undefined ||
configThis[configKeys[key]] == null ||
configThis[configKeys[key]] == NaN
) {
log.error(`配置文件 ${file} 异常:`); log.error(`配置文件 ${file} 异常:`);
log.error(` —— ${configKeys[key]}字段缺失`); log.error(` —— ${configKeys[key]}字段缺失`);
} }
} }
} }
} };
exports.makeHeader = function(data,appversion){ exports.hk4e_makeHeader = function (data, appversion) {
return { return {
"x-rpc-combo_token": data.token, "x-rpc-combo_token": data.token,
"x-rpc-client_type": data.client_type, "x-rpc-client_type": data.client_type,
"x-rpc-app_version": appversion, "x-rpc-app_version": appversion,
"x-rpc-sys_version": data.sys_version, "x-rpc-sys_version": data.sys_version,
"x-rpc-channel": data.channel, "x-rpc-channel": data.channel,
"x-rpc-device_id": data.device_id, "x-rpc-device_id": data.device_id,
"x-rpc-device_name": data.device_name, "x-rpc-device_name": data.device_name,
"x-rpc-device_model": data.device_model, "x-rpc-device_model": data.device_model,
"x-rpc-app_id": 1953439974, "x-rpc-app_id": 1953439974,
"x-rpc-cg_game_biz": "hk4e_cn", "x-rpc-cg_game_biz": "hk4e_cn",
"x-rpc-preview": 0, "x-rpc-op_biz": "clgm_cn",
"x-rpc-op_biz": "clgm_cn", "x-rpc-language": "zh-cn",
"x-rpc-language": "zh-cn", "x-rpc-vendor_id": 1,
"x-rpc-vendor_id": 2, "x-rpc-cps": "cyydmihoyo",
Referer: "https://app.mihoyo.com", Host: "api-cloudgame.mihoyo.com",
Host: "api-cloudgame.mihoyo.com", Connection: "Keep-Alive",
Connection: "Keep-Alive", "Accept-Encoding": "gzip, deflate",
"Accept-Encoding": "gzip, deflate", "User-Agent": "okhttp/4.10.0"
Accept: "*/*", };
} };
} // 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,mailfrom,mailto,successNum,totalNum,content) { exports.SendLog = function (
transporter.sendMail({ transporter,
from: `"Genshin Cloud Game Helper" <${mailfrom}>`, //邮件来源 mailfrom,
to: mailto, //邮件发送到哪里,多个邮箱使用逗号隔开 mailto,
subject: `今日已签到${successNum}/${totalNum}名用户`, // 邮件主题 successNum,
text: '', // 存文本类型的邮件正文 totalNum,
html: `${content}` // html类型的邮件正文 content
}, (error) => { ) {
if (error) { transporter.sendMail(
return console.log(error); {
from: `"Hoyo Cloud Game Helper" <${mailfrom}>`, //邮件来源
to: mailto, //邮件发送到哪里,多个邮箱使用逗号隔开
subject: `今日已签到${successNum}/${totalNum}名用户`, // 邮件主题
text: "", // 存文本类型的邮件正文
html: `${content}`, // html类型的邮件正文
},
(error) => {
if (error) {
return console.log(error);
}
log.info("日志已丢出!");
} }
log.info("日志已丢出!") );
}); };
}
exports.SendResult = function (transporter, mailfrom, mailto, content, key) {
transporter.sendMail(
{
from: `"Hoyo Cloud Game Helper" <${mailfrom}>`, //邮件来源
to: mailto, //邮件发送到哪里,多个邮箱使用逗号隔开
subject: `Hoyo Cloud Game Helper`, // 邮件主题
text: `${content}`, // 存文本类型的邮件正文
},
(error) => {
if (error) {
return console.log(error);
}
log.info(`${key} - 已发送通知至${mailto}`);
}
);
};

View File

@ -1,69 +1,191 @@
const { getConfigs, checkConfigs, makeHeader, ListNotification, AckNotification, Wallet, SendLog, AppVersion, getGlobalConfig } = require("./config") const {
checkConfigs,
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,
getGlobalConfig,
SendResult,
} = require("./config");
const { log, addLogContent, getLogs } = require("./logger"); const { log, addLogContent, getLogs, sleep } = require("./util");
const nodemailer = require("nodemailer"); const nodemailer = require("nodemailer");
(async () => { (async () => {
log.info("开始获取全局配置") log.info("开始获取全局配置");
var globalConfig = getGlobalConfig(); var globalConfig = getGlobalConfig();
log.info("获取成功") log.info("获取成功");
if (globalConfig.sendMail == true) { log.info("组装邮件发射器");
log.info("组装邮件发射器") var transporter = nodemailer.createTransport({
var transporter = nodemailer.createTransport({ host: globalConfig.mailConfig.smtpServer,
host: globalConfig.mailConfig.smtpServer, port: globalConfig.mailConfig.smtpPort,
port: globalConfig.mailConfig.smtpPort, secure: globalConfig.mailConfig.smtpSecure,
secure: globalConfig.mailConfig.smtpSecure, auth: {
auth: { user: globalConfig.mailConfig.user,
user: globalConfig.mailConfig.user, pass: globalConfig.mailConfig.pass,
pass: globalConfig.mailConfig.pass },
});
var minDelay = globalConfig.minDelay;
var maxDelay = globalConfig.maxDelay;
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 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
);
log.info(`暂停:${delay}毫秒`);
await sleep(delay);
totalNum++;
log.info(`${key} - 正在执行配置 ${key}`);
log.info(`${key} - 尝试签到原神……`);
var hk4e_header = hk4e_makeHeader(hk4e_configs[key], hk4e_appversion);
var hk4e_WalletRespond = await hk4e_Wallet(hk4e_header);
addLogContent(
`<span style="color: orange; font-weight: bold">${key} hk4e_Wallet返回体</span> <br> <span style="color: orange">${JSON.stringify(
hk4e_WalletRespond
)}</span><br>`
);
if (hk4e_WalletRespond.data != null) {
var hk4e_NotificationRespond = await hk4e_ListNotification(hk4e_header);
addLogContent(
`<span style="color: orange; font-weight: bold">${key} hk4e_Notification返回体</span> <br> <span style="color: orange">${JSON.stringify(
hk4e_NotificationRespond
)}</span><br>`
);
successNum++;
log.info(
`${key} - 签到完毕! 原神总时长:${hk4e_WalletRespond.data.free_time.free_time}分钟`
);
if (hk4e_configs[key].email != null && globalConfig.sendMail == true) {
SendResult(
transporter,
globalConfig.mailConfig.user,
hk4e_configs[key].email,
`签到完毕! 总时长:${hk4e_WalletRespond.data.free_time.free_time}分钟`,
key
);
}
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 < hk4e_NotificationLength; i++) {
hk4e_AckNotification(
hk4e_postHeader,
hk4e_NotificationRespond.data.list[i].id
);
} }
});
}
var configs = getConfigs();
log.info(`正在检测配置有效性`)
checkConfigs(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) {
totalNum ++;
log.info(`正在执行配置 ${key}`)
log.info("尝试签到……")
var header = makeHeader(configs[key], appversion);
var WalletRespond = await Wallet(header);
addLogContent(`<span style="color: orange; font-weight: bold">${key} Wallet返回体</span> <br> <span style="color: orange">${JSON.stringify(WalletRespond)}</span><br>`);
if(WalletRespond.data != null) {
var NotificationRespond = await ListNotification(header);
addLogContent(`<span style="color: orange; font-weight: bold">${key} Notification返回体</span> <br> <span style="color: orange">${JSON.stringify(NotificationRespond)}</span><br>`);
successNum ++;
log.info(`签到完毕! 剩余时长:${WalletRespond.data.free_time.free_time}分钟`)
let NotificationLength = NotificationRespond.data.list.length
let postHeader = header;
Object.assign(postHeader, {
"Content-Length": 28,
"Content-Type": "application/json",
});
for (var i = 0; i < NotificationLength; i++) {
AckNotification(postHeader, NotificationRespond.data.list[i].id);
}
} else { } else {
log.error("签到失败") log.error(`${key} - 签到失败`);
if (hk4e_configs[key].email != null && globalConfig.sendMail == true) {
SendResult(
transporter,
globalConfig.mailConfig.user,
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(
`<span style="color: orange; font-weight: bold">${key} nap_Wallet返回体</span> <br> <span style="color: orange">${JSON.stringify(
nap_WalletRespond
)}</span><br>`
);
if (nap_WalletRespond.data != null) {
var nap_NotificationRespond = await nap_ListNotification(nap_header);
addLogContent(
`<span style="color: orange; font-weight: bold">${key} nap_Notification返回体</span> <br> <span style="color: orange">${JSON.stringify(
nap_NotificationRespond
)}</span><br>`
);
successNum++;
log.info(
`${key} - 签到完毕! 绝区零总时长:${nap_WalletRespond.data.free_time.free_time}分钟`
);
if (nap_configs[key].email != null && globalConfig.sendMail == true) {
SendRnapt(
transporter,
globalConfig.mailConfig.user,
nap_configs[key].email,
`签到完毕! 总时长:${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 && globalConfig.sendMail == true) {
SendResult(
transporter,
globalConfig.mailConfig.user,
nap_configs[key].email,
"签到失败",
key
);
}
} }
} }
if (globalConfig.sendMail == true) { if (globalConfig.sendMail == true) {
log.info(`运行完毕!丢出日志`) log.info(`暂停10秒`);
await sleep(10000);
log.info(`运行完毕!丢出日志`);
SendLog( SendLog(
transporter, transporter,
globalConfig.mailConfig.user, globalConfig.mailConfig.user,
globalConfig.mailConfig.mailto, globalConfig.mailConfig.mailto,
successNum, successNum,
totalNum, totalNum,
getLogs() getLogs()
) );
} }
})() })();

View File

@ -1,20 +0,0 @@
const reggol = require("reggol")
const baseLogger = new reggol("GenshinCloudGameHelper")
let logContent = ``
exports.addLogContent = function(content) {
logContent += content
}
exports.getLogs = function() {
return logContent
}
exports.log = {
info(content) {
logContent += `<strong style="color: green">[info]</strong> ${content}<br>`
baseLogger.info(content)
},
error(content) {
logContent += `<strong style="color: red">[error]</strong> ${content}<br>`
baseLogger.error(content)
}
}

26
src/util.js Normal file
View File

@ -0,0 +1,26 @@
const reggol = require("reggol");
const baseLogger = new reggol("HoyoCloudGameHelper");
let logContent = ``;
exports.addLogContent = function (content) {
logContent += content;
};
exports.getLogs = function () {
return logContent;
};
exports.log = {
info(content) {
logContent += `<strong style="color: green">[info]</strong> ${content}<br>`;
baseLogger.info(content);
},
error(content) {
logContent += `<strong style="color: red">[error]</strong> ${content}<br>`;
baseLogger.error(content);
},
};
exports.sleep = function (delay) {
return new Promise((resolve) => {
setTimeout(resolve, delay);
});
};