Compare commits
19 Commits
4c74a34d9d
...
main
Author | SHA1 | Date | |
---|---|---|---|
c0b46611e4
|
|||
6025465912
|
|||
a94550b01d
|
|||
1c21596315
|
|||
ef7235c006
|
|||
88d4474728
|
|||
1119581d19
|
|||
15ca17e903
|
|||
41280019f6
|
|||
6bcb19e8e1
|
|||
ee3321c7e8
|
|||
2dbcab998f
|
|||
f8e47879f1
|
|||
dd86b82e1c
|
|||
5c8a9eb55e
|
|||
2ed58716bf
|
|||
2f5bac484b
|
|||
616c94ddc9
|
|||
723fba3763
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,3 +2,4 @@ configs/
|
|||||||
node_modules/
|
node_modules/
|
||||||
pnpm-lock.yaml
|
pnpm-lock.yaml
|
||||||
yarn.lock
|
yarn.lock
|
||||||
|
.vscode/
|
2
LICENSE
2
LICENSE
@ -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
113
README.md
@ -1,112 +1,31 @@
|
|||||||
# Genshin Cloud Game Helper
|
# Hoyo Cloud Game Helper
|
||||||
|
|
||||||
每天帮你获取 15 分钟云原神时间~
|

|
||||||
|
|
||||||
## 配置教程
|
[米哈云游](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 是在云原神登录后用于验证的标记
|
[](#)
|
||||||
> 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
|
[](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 电脑运行去抓也行)
|
|
||||||
> > []
|
|
||||||
> > 一定要记得装抓包软件提供的证书,要不然解不了 SSL 连接,一定要先登录并成功进去了再启动抓包软件!!!
|
|
||||||
> > []
|
|
||||||
> > 这里面只要是个 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 文件夹下面的文件
|
|
||||||
|
|
||||||
## 另外
|
|
||||||
|
|
||||||
程序会自动获取最新的云原神版本,确保数据与用户一样
|
|
||||||
|
@ -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": ""
|
||||||
}
|
}
|
14
global.json
14
global.json
@ -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
4
package-lock.json
generated
@ -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": {
|
||||||
|
10
package.json
10
package.json
@ -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",
|
||||||
|
283
src/config.js
283
src/config.js
@ -1,106 +1,176 @@
|
|||||||
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,
|
||||||
@ -112,29 +182,78 @@ exports.makeHeader = function(data,appversion){
|
|||||||
"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": 2,
|
"x-rpc-vendor_id": 1,
|
||||||
Referer: "https://app.mihoyo.com",
|
"x-rpc-cps": "cyydmihoyo",
|
||||||
Host: "api-cloudgame.mihoyo.com",
|
Host: "api-cloudgame.mihoyo.com",
|
||||||
Connection: "Keep-Alive",
|
Connection: "Keep-Alive",
|
||||||
"Accept-Encoding": "gzip, deflate",
|
"Accept-Encoding": "gzip, deflate",
|
||||||
Accept: "*/*",
|
"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,mailfrom,mailto,successNum,totalNum,content) {
|
exports.SendLog = function (
|
||||||
transporter.sendMail({
|
transporter,
|
||||||
from: `"Genshin Cloud Game Helper" <${mailfrom}>`, //邮件来源
|
mailfrom,
|
||||||
|
mailto,
|
||||||
|
successNum,
|
||||||
|
totalNum,
|
||||||
|
content
|
||||||
|
) {
|
||||||
|
transporter.sendMail(
|
||||||
|
{
|
||||||
|
from: `"Hoyo Cloud Game Helper" <${mailfrom}>`, //邮件来源
|
||||||
to: mailto, //邮件发送到哪里,多个邮箱使用逗号隔开
|
to: mailto, //邮件发送到哪里,多个邮箱使用逗号隔开
|
||||||
subject: `今日已签到${successNum}/${totalNum}名用户`, // 邮件主题
|
subject: `今日已签到${successNum}/${totalNum}名用户`, // 邮件主题
|
||||||
text: '', // 存文本类型的邮件正文
|
text: "", // 存文本类型的邮件正文
|
||||||
html: `${content}` // html类型的邮件正文
|
html: `${content}`, // html类型的邮件正文
|
||||||
}, (error) => {
|
},
|
||||||
|
(error) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
return console.log(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}`);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
200
src/index.js
200
src/index.js
@ -1,62 +1,184 @@
|
|||||||
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
|
||||||
|
);
|
||||||
}
|
}
|
||||||
var configs = getConfigs();
|
let hk4e_NotificationLength = hk4e_NotificationRespond.data.list.length;
|
||||||
log.info(`正在检测配置有效性`)
|
let hk4e_postHeader = hk4e_header;
|
||||||
checkConfigs(configs)
|
Object.assign(hk4e_postHeader, {
|
||||||
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-Length": 28,
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json; charset=UTF-8",
|
||||||
});
|
});
|
||||||
for (var i = 0; i < NotificationLength; i++) {
|
for (var i = 0; i < hk4e_NotificationLength; i++) {
|
||||||
AckNotification(postHeader, NotificationRespond.data.list[i].id);
|
hk4e_AckNotification(
|
||||||
|
hk4e_postHeader,
|
||||||
|
hk4e_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,
|
||||||
@ -64,6 +186,6 @@ const nodemailer = require("nodemailer");
|
|||||||
successNum,
|
successNum,
|
||||||
totalNum,
|
totalNum,
|
||||||
getLogs()
|
getLogs()
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
})()
|
})();
|
||||||
|
@ -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
26
src/util.js
Normal 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);
|
||||||
|
});
|
||||||
|
};
|
Reference in New Issue
Block a user