mirror of
https://github.com/ctrlcvs/xiaoyao-cvs-plugin.git
synced 2024-12-22 19:10:53 +08:00
新增指令#崩坏3签到
This commit is contained in:
parent
02a86ca345
commit
c6324d6323
@ -1,3 +1,12 @@
|
||||
# 1.1.2
|
||||
* 初步实现米游社签到米游币以及社区签到
|
||||
* 需要引入包文件`cnpm i promise-retry `跟`cnpm i superagent`
|
||||
* V3版本引入文件`pnpm i promise-retry `跟`pnpm i superagent`
|
||||
* 如果出现了安装其中一个包导致另外的包出问题的请群里询问
|
||||
* 具体获取cookie教程后续会完善 敬情期待~
|
||||
* 需要完整的cookie内容要包含`login_ticket`跟`login_uid`不然是无法实现米游社签到的
|
||||
* 自动签到逻辑目前还在梳理中.....
|
||||
|
||||
# 1.1.1
|
||||
* 初步兼容V3版本
|
||||
* 版本兼容问题V2报错的话请导入`yaml`包 指令 `cnpm i yaml`
|
||||
|
19
README.md
19
README.md
@ -1,12 +1,12 @@
|
||||
#### 介绍
|
||||
# xiaoyao-cvs-plugin
|
||||
|
||||
yunzai-bot扩展图鉴以及体力优化
|
||||
yunzai-bot扩展图鉴以及体力优化;
|
||||
|
||||
项目仅供学习交流使用,严禁用于任何商业用途和非法行为
|
||||
|
||||
#### 介绍
|
||||
|
||||
# xiaoyao-cvs-plugin
|
||||
|
||||
介绍
|
||||
|
||||
原神图鉴插件。
|
||||
@ -31,13 +31,24 @@ git clone https://github.com/Ctrlcvs/xiaoyao-cvs-plugin.git ./plugins/xiaoyao-cv
|
||||
1. 配合云崽使用, https://gitee.com/Le-niao/Yunzai-Bot
|
||||
2. V3版本安装报错的话请用指令引入包
|
||||
```
|
||||
pnpm i date-format
|
||||
pnpm i superagent
|
||||
```
|
||||
|
||||
```
|
||||
pnpm i promise-retry
|
||||
```
|
||||
3. V2版本安装报错指令引入包
|
||||
```
|
||||
cnpm i yaml
|
||||
```
|
||||
|
||||
```
|
||||
cnpm i superagent
|
||||
```
|
||||
|
||||
```
|
||||
cnpm i promise-retry
|
||||
```
|
||||
#### 命令说明
|
||||
1. 发送 #图鉴更新 获取最新的图鉴记录。(必须)
|
||||
2. 发送 #**图鉴 进行触发,例如发送 #刻晴图鉴,即可返回对应的图片信息。
|
||||
|
@ -26,7 +26,6 @@ let path_img = ["background_image", "/icon/bg"];
|
||||
let tempDataUrl = `${_path}/plugins/xiaoyao-cvs-plugin/data/NoteTemp`
|
||||
let tempData = {};
|
||||
init()
|
||||
|
||||
function init() {
|
||||
Data.createDir("", tempDataUrl, false);
|
||||
tempData = Data.readJSON(tempDataUrl, "tempData")
|
||||
|
@ -19,15 +19,19 @@ import {
|
||||
import {
|
||||
currentVersion
|
||||
} from "../components/Changelog.js";
|
||||
import {
|
||||
rule as signRule,
|
||||
sign,mysSign
|
||||
} from "./sign.js"
|
||||
export {
|
||||
updateRes,
|
||||
updateMiaoPlugin,
|
||||
updateMiaoPlugin,sign,
|
||||
versionInfo,
|
||||
Note_appoint,pokeNote,
|
||||
sysCfg,
|
||||
help,DailyNoteTask,
|
||||
AtlasAlias,
|
||||
Note
|
||||
Note,mysSign
|
||||
};
|
||||
|
||||
let rule = {
|
||||
@ -55,7 +59,7 @@ let rule = {
|
||||
reg: "#poke#",
|
||||
describe: "体力",
|
||||
},
|
||||
|
||||
...signRule,
|
||||
...adminRule
|
||||
};
|
||||
|
||||
|
181
apps/sign.js
Normal file
181
apps/sign.js
Normal file
@ -0,0 +1,181 @@
|
||||
import MihoYoApi from "../model/mys/mihoyo-api.js"
|
||||
import utils from '../model/mys/utils.js';
|
||||
import promiseRetry from 'promise-retry';
|
||||
import {
|
||||
Cfg,
|
||||
Data
|
||||
} from "../components/index.js";
|
||||
import moment from 'moment';
|
||||
import MysInfo from '../model/mys/mysInfo.js'
|
||||
import {
|
||||
isV3
|
||||
} from '../components/Changelog.js';
|
||||
import gsCfg from '../model/gsCfg.js'
|
||||
import { fileFrom } from "node-fetch";
|
||||
export const rule = {
|
||||
mysSign: {
|
||||
reg: "^#*(米游社|mys|社区)(原神|崩坏3|崩坏2|未定事件簿|大别野|崩坏星穹铁道|绝区零|全部)签到$",
|
||||
describe: "米游社米游币签到(理论上会签到全部所以区分开了)"
|
||||
},
|
||||
sign: {
|
||||
reg: "^#*(原神|崩坏3|崩坏2|未定事件簿|大别野|崩坏星穹铁道|绝区零)签到$",
|
||||
describe: "米社规则签到"
|
||||
}
|
||||
};
|
||||
|
||||
const _path = process.cwd();
|
||||
let START = moment().unix();
|
||||
const TODAY_DATE = moment().format('YYYY-MM-DD');
|
||||
const RETRY_OPTIONS = {
|
||||
retries: 3,
|
||||
minTimeout: 5000,
|
||||
maxTimeout: 10000
|
||||
};
|
||||
export async function sign(e) {
|
||||
if (!(await cookie(e))) {
|
||||
return true;
|
||||
}
|
||||
START = moment().unix();
|
||||
let miHoYoApi = new MihoYoApi(e);
|
||||
let resultMessage="";
|
||||
let msg = e.msg.replace(/#|签到|井|米游社|mys|社区/g, "");
|
||||
let ForumData = await getDataList(msg);
|
||||
for (let forum of ForumData) {
|
||||
resultMessage += `**${forum.name}**\n`
|
||||
try {
|
||||
// 1 BBS Sign
|
||||
let resObj = await promiseRetry((retry, number) => {
|
||||
Bot.logger.info(`开始签到: [${forum.name}] 尝试次数: ${number}`);
|
||||
return miHoYoApi.forumSign(forum.forumId).catch((e) => {
|
||||
Bot.logger.error(`${forum.name} 签到失败: [${e.message}] 尝试次数: ${number}`);
|
||||
return retry(e);
|
||||
});
|
||||
}, RETRY_OPTIONS);
|
||||
Bot.logger.info(`${forum.name} 签到结果: [${resObj.message}]`);
|
||||
resultMessage += `签到: [${resObj.message}]\n`;
|
||||
} catch (e) {
|
||||
Bot.logger.error(`${forum.name} 签到失败 [${e.message}]`);
|
||||
resultMessage += `签到失败: [${e.message}]\n`;
|
||||
}
|
||||
|
||||
await utils.randomSleepAsync();
|
||||
}
|
||||
await replyMsg(e,resultMessage);
|
||||
return true
|
||||
}
|
||||
export async function mysSign(e) {
|
||||
if (!(await cookie(e))) {
|
||||
return true;
|
||||
}
|
||||
START = moment().unix();
|
||||
let miHoYoApi = new MihoYoApi(e);
|
||||
let resultMessage="";
|
||||
// Execute task
|
||||
let msg = e.msg.replace(/#|签到|井|米游社|mys|社区/g, "");
|
||||
let ForumData = await getDataList(msg);
|
||||
for (let forum of ForumData) {
|
||||
resultMessage += `\n**${forum.name}**\n`
|
||||
try {
|
||||
// 2 BBS list post
|
||||
let resObj = await promiseRetry((retry, number) => {
|
||||
Bot.logger.info(`读取帖子列表: [${forum.name}] 尝试次数: ${number}`);
|
||||
return miHoYoApi.forumPostList(forum.forumId).catch((e) => {
|
||||
Bot.logger.error(`${forum.name} 读取帖子列表失败: [${e.message}] 尝试次数: ${number}`);
|
||||
return retry(e);
|
||||
});
|
||||
}, RETRY_OPTIONS);
|
||||
Bot.logger.info(`${forum.name} 读取列表成功 [${resObj.message}],读取到 [${resObj.data.list.length}] 条记录`);
|
||||
|
||||
let postList = resObj.data.list;
|
||||
for (let post of postList) {
|
||||
post = post.post;
|
||||
// 2.1 BBS read post
|
||||
let resObj = await promiseRetry((retry, number) => {
|
||||
Bot.logger.info(`读取帖子: [${post.subject}] 尝试次数: ${number}`);
|
||||
return miHoYoApi.forumPostDetail(post['post_id']).catch((e) => {
|
||||
Bot.logger.error(`${forum.name} 读取帖子失败: [${e.message}] 尝试次数: ${number}`);
|
||||
return retry(e);
|
||||
});
|
||||
}, RETRY_OPTIONS);
|
||||
Bot.logger.info(`${forum.name} [${post.subject}] 读取成功 [${resObj.message}]`);
|
||||
await utils.randomSleepAsync();
|
||||
// 2.2 BBS vote post
|
||||
resObj = await promiseRetry((retry, number) => {
|
||||
Bot.logger.info(`点赞帖子: [${post.subject}] 尝试次数: ${number}`);
|
||||
return miHoYoApi.forumPostVote(post['post_id']).catch((e) => {
|
||||
Bot.logger.error(`${forum.name} 点赞帖子失败: [${e.message}] 尝试次数: ${number}`);
|
||||
return retry(e);
|
||||
});
|
||||
}, RETRY_OPTIONS);
|
||||
|
||||
Bot.logger.info(`${forum.name} [${post.subject}] 点赞成功 [${resObj.message}]`);
|
||||
await utils.randomSleepAsync();
|
||||
}
|
||||
|
||||
// 2.3 BBS share post
|
||||
let sharePost = postList[0].post;
|
||||
resObj = await promiseRetry((retry, number) => {
|
||||
Bot.logger.info(`分享帖子: [${sharePost.subject}] 尝试次数: ${number}`);
|
||||
return miHoYoApi.forumPostShare(sharePost['post_id']).catch((e) => {
|
||||
Bot.logger.error(`${forum.name} 分享帖子失败: [${e.message}] 尝试次数: ${number}`);
|
||||
return retry(e);
|
||||
});
|
||||
}, RETRY_OPTIONS);
|
||||
} catch (e) {
|
||||
Bot.logger.error(`${forum.name} 读帖点赞分享失败 [${e.message}]`);
|
||||
resultMessage += `读帖点赞分享: 失败 [${e.message}]\n`;
|
||||
}
|
||||
resultMessage += `读帖点赞分享: 成功\n`;
|
||||
await utils.randomSleepAsync();
|
||||
}
|
||||
await replyMsg(e,resultMessage);
|
||||
return true
|
||||
}
|
||||
|
||||
async function replyMsg(e,resultMessage){
|
||||
const END = moment().unix();
|
||||
Bot.logger.info(`运行结束, 用时 ${END - START} 秒`);
|
||||
resultMessage += `\n用时 ${END - START} 秒`;
|
||||
e.reply(resultMessage);
|
||||
}
|
||||
|
||||
async function getDataList(name){
|
||||
let ForumData = Data.readJSON(`${_path}/plugins/xiaoyao-cvs-plugin/defSet/json`, "mys")
|
||||
|
||||
for(let item of ForumData){
|
||||
if(item.name=name){ //循环结束未找到的时候返回原数组签到全部
|
||||
return [item]
|
||||
}
|
||||
}
|
||||
return ForumData;
|
||||
}
|
||||
|
||||
async function cookie(e) {
|
||||
let cookie, uid;
|
||||
let miHoYoApi = new MihoYoApi(e);
|
||||
if (isV3) {
|
||||
// console.log(e)
|
||||
let skuid = await gsCfg.getBingCookie(e.user_id);
|
||||
cookie = skuid.ck;
|
||||
uid = skuid.item;
|
||||
} else {
|
||||
if (NoteCookie[e.user_id]) {
|
||||
cookie = NoteCookie[e.user_id].cookie;
|
||||
uid = NoteCookie[e.user_id].uid;
|
||||
} else if (BotConfig.dailyNote && BotConfig.dailyNote[e.user_id]) {
|
||||
cookie = BotConfig.dailyNote[e.user_id].cookie;
|
||||
uid = BotConfig.dailyNote[e.user_id].uid;
|
||||
}
|
||||
}
|
||||
e.uid = uid;
|
||||
if (!cookie.includes("login_ticket")) {
|
||||
e.reply("米游社登录cookie不完整,请前往米游社通行证处重新获取cookie~\ncookies必须包含login_ticket")
|
||||
return false;
|
||||
}
|
||||
let flot = (await miHoYoApi.stoken(cookie, e));
|
||||
if (!flot) {
|
||||
e.reply("登录失效请重新登录获取cookie发送机器人~")
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
44
defSet/json/mys.json
Normal file
44
defSet/json/mys.json
Normal file
@ -0,0 +1,44 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"forumId": "1",
|
||||
"name": "崩坏3",
|
||||
"url": "https://bbs.mihoyo.com/bh3/"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"forumId": "26",
|
||||
"name": "原神",
|
||||
"url": "https://bbs.mihoyo.com/ys/"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"forumId": "30",
|
||||
"name": "崩坏2",
|
||||
"url": "https://bbs.mihoyo.com/bh2/"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"forumId": "37",
|
||||
"name": "未定事件簿",
|
||||
"url": "https://bbs.mihoyo.com/wd/"
|
||||
},
|
||||
{
|
||||
"id": "5",
|
||||
"forumId": "34",
|
||||
"name": "大别野",
|
||||
"url": "https://bbs.mihoyo.com/dby/"
|
||||
},
|
||||
{
|
||||
"id": "6",
|
||||
"forumId": "52",
|
||||
"name": "崩坏星穹铁道",
|
||||
"url": "https://bbs.mihoyo.com/sr/"
|
||||
},
|
||||
{
|
||||
"id": "7",
|
||||
"forumId": "57",
|
||||
"name": "绝区零",
|
||||
"url": "https://bbs.mihoyo.com/zzz/"
|
||||
}
|
||||
]
|
405
model/gsCfg.js
405
model/gsCfg.js
@ -1,233 +1,262 @@
|
||||
import YAML from 'yaml'
|
||||
import chokidar from 'chokidar'
|
||||
import fs from 'node:fs'
|
||||
import { promisify } from 'node:util'
|
||||
import {
|
||||
promisify
|
||||
} from 'node:util'
|
||||
import lodash from 'lodash'
|
||||
|
||||
const plugin="xiaoyao-cvs-plugin"
|
||||
const plugin = "xiaoyao-cvs-plugin"
|
||||
/** 配置文件 */
|
||||
class GsCfg {
|
||||
constructor () {
|
||||
/** 默认设置 */
|
||||
this.defSetPath = `./plugins/${plugin}/defSet/`
|
||||
this.defSet = {}
|
||||
constructor() {
|
||||
/** 默认设置 */
|
||||
this.defSetPath = `./plugins/${plugin}/defSet/`
|
||||
this.defSet = {}
|
||||
|
||||
/** 用户设置 */
|
||||
this.configPath = `./plugins/${plugin}/config/`
|
||||
this.config = {}
|
||||
/** 用户设置 */
|
||||
this.configPath = `./plugins/${plugin}/config/`
|
||||
this.config = {}
|
||||
|
||||
/** 监听文件 */
|
||||
this.watcher = { config: {}, defSet: {} }
|
||||
}
|
||||
/** 监听文件 */
|
||||
this.watcher = {
|
||||
config: {},
|
||||
defSet: {}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param app 功能
|
||||
* @param name 配置文件名称
|
||||
*/
|
||||
getdefSet (app, name) {
|
||||
return this.getYaml(app, name, 'defSet')
|
||||
}
|
||||
/**
|
||||
* @param app 功能
|
||||
* @param name 配置文件名称
|
||||
*/
|
||||
getdefSet(app, name) {
|
||||
return this.getYaml(app, name, 'defSet')
|
||||
}
|
||||
|
||||
/** 用户配置 */
|
||||
getConfig (app, name) {
|
||||
let ignore = ['mys.pubCk', 'gacha.set']
|
||||
/** 用户配置 */
|
||||
getConfig(app, name) {
|
||||
let ignore = ['mys.pubCk', 'gacha.set']
|
||||
|
||||
if (ignore.includes(`${app}.${name}`)) {
|
||||
return this.getYaml(app, name, 'config')
|
||||
}
|
||||
if (ignore.includes(`${app}.${name}`)) {
|
||||
return this.getYaml(app, name, 'config')
|
||||
}
|
||||
|
||||
return { ...this.getdefSet(app, name), ...this.getYaml(app, name, 'config') }
|
||||
}
|
||||
return {
|
||||
...this.getdefSet(app, name),
|
||||
...this.getYaml(app, name, 'config')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配置yaml
|
||||
* @param app 功能
|
||||
* @param name 名称
|
||||
* @param type 默认跑配置-defSet,用户配置-config
|
||||
*/
|
||||
getYaml (app, name, type) {
|
||||
let file = this.getFilePath(app, name, type)
|
||||
let key = `${app}.${name}`
|
||||
/**
|
||||
* 获取配置yaml
|
||||
* @param app 功能
|
||||
* @param name 名称
|
||||
* @param type 默认跑配置-defSet,用户配置-config
|
||||
*/
|
||||
getYaml(app, name, type) {
|
||||
let file = this.getFilePath(app, name, type)
|
||||
let key = `${app}.${name}`
|
||||
|
||||
if (this[type][key]) return this[type][key]
|
||||
if (this[type][key]) return this[type][key]
|
||||
|
||||
this[type][key] = YAML.parse(
|
||||
fs.readFileSync(file, 'utf8')
|
||||
)
|
||||
this[type][key] = YAML.parse(
|
||||
fs.readFileSync(file, 'utf8')
|
||||
)
|
||||
|
||||
this.watch(file, app, name, type)
|
||||
this.watch(file, app, name, type)
|
||||
|
||||
return this[type][key]
|
||||
}
|
||||
return this[type][key]
|
||||
}
|
||||
|
||||
getFilePath (app, name, type) {
|
||||
if (type == 'defSet') return `${this.defSetPath}${app}/${name}.yaml`
|
||||
else return `${this.configPath}${app}.${name}.yaml`
|
||||
}
|
||||
getFilePath(app, name, type) {
|
||||
if (type == 'defSet') return `${this.defSetPath}${app}/${name}.yaml`
|
||||
else return `${this.configPath}${app}.${name}.yaml`
|
||||
}
|
||||
|
||||
/** 监听配置文件 */
|
||||
watch (file, app, name, type = 'defSet') {
|
||||
let key = `${app}.${name}`
|
||||
/** 监听配置文件 */
|
||||
watch(file, app, name, type = 'defSet') {
|
||||
let key = `${app}.${name}`
|
||||
|
||||
if (this.watcher[type][key]) return
|
||||
if (this.watcher[type][key]) return
|
||||
|
||||
const watcher = chokidar.watch(file)
|
||||
watcher.on('change', path => {
|
||||
delete this[type][key]
|
||||
logger.mark(`[修改配置文件][${type}][${app}][${name}]`)
|
||||
if (this[`change_${app}${name}`]) {
|
||||
this[`change_${app}${name}`]()
|
||||
}
|
||||
})
|
||||
const watcher = chokidar.watch(file)
|
||||
watcher.on('change', path => {
|
||||
delete this[type][key]
|
||||
logger.mark(`[修改配置文件][${type}][${app}][${name}]`)
|
||||
if (this[`change_${app}${name}`]) {
|
||||
this[`change_${app}${name}`]()
|
||||
}
|
||||
})
|
||||
|
||||
this.watcher[type][key] = watcher
|
||||
}
|
||||
this.watcher[type][key] = watcher
|
||||
}
|
||||
|
||||
get element () {
|
||||
return { ...this.getdefSet('element', 'role'), ...this.getdefSet('element', 'weapon') }
|
||||
}
|
||||
get element() {
|
||||
return {
|
||||
...this.getdefSet('element', 'role'),
|
||||
...this.getdefSet('element', 'weapon')
|
||||
}
|
||||
}
|
||||
|
||||
/** 读取用户绑定的ck */
|
||||
async getBingCk () {
|
||||
let ck = {}
|
||||
let ckQQ = {}
|
||||
let dir = './data/MysCookie/'
|
||||
let files = fs.readdirSync(dir).filter(file => file.endsWith('.yaml'))
|
||||
/** 读取用户绑定的ck */
|
||||
async getBingCk() {
|
||||
let ck = {}
|
||||
let ckQQ = {}
|
||||
let dir = './data/MysCookie/'
|
||||
let files = fs.readdirSync(dir).filter(file => file.endsWith('.yaml'))
|
||||
|
||||
const readFile = promisify(fs.readFile)
|
||||
const readFile = promisify(fs.readFile)
|
||||
|
||||
let promises = []
|
||||
let promises = []
|
||||
|
||||
files.forEach((v) => promises.push(readFile(`${dir}${v}`, 'utf8')))
|
||||
files.forEach((v) => promises.push(readFile(`${dir}${v}`, 'utf8')))
|
||||
|
||||
const res = await Promise.all(promises)
|
||||
const res = await Promise.all(promises)
|
||||
|
||||
res.forEach((v) => {
|
||||
let tmp = YAML.parse(v)
|
||||
lodash.forEach(tmp, (v, i) => {
|
||||
ck[String(i)] = v
|
||||
if (v.isMain && !ckQQ[String(v.qq)]) {
|
||||
ckQQ[String(v.qq)] = v
|
||||
}
|
||||
})
|
||||
})
|
||||
res.forEach((v) => {
|
||||
let tmp = YAML.parse(v)
|
||||
lodash.forEach(tmp, (v, i) => {
|
||||
ck[String(i)] = v
|
||||
if (v.isMain && !ckQQ[String(v.qq)]) {
|
||||
ckQQ[String(v.qq)] = v
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
return { ck, ckQQ }
|
||||
}
|
||||
return {
|
||||
ck,
|
||||
ckQQ
|
||||
}
|
||||
}
|
||||
|
||||
getBingCkSingle (userId) {
|
||||
let file = `./data/MysCookie/${userId}.yaml`
|
||||
try {
|
||||
let ck = fs.readFileSync(file, 'utf-8')
|
||||
ck = YAML.parse(ck)
|
||||
return ck
|
||||
} catch (error) {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
getBingCkSingle(userId) {
|
||||
let file = `./data/MysCookie/${userId}.yaml`
|
||||
try {
|
||||
let ck = fs.readFileSync(file, 'utf-8')
|
||||
ck = YAML.parse(ck)
|
||||
return ck
|
||||
} catch (error) {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
getBingCookie(userId) {
|
||||
let file = `./data/MysCookie/${userId}.yaml`
|
||||
try {
|
||||
let ck = fs.readFileSync(file, 'utf-8')
|
||||
ck = YAML.parse(ck)
|
||||
for(let item in ck){
|
||||
ck=ck[item].ck
|
||||
return {ck,item};
|
||||
}
|
||||
} catch (error) {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
saveBingCk(userId, data) {
|
||||
let file = `./data/MysCookie/${userId}.yaml`
|
||||
if (lodash.isEmpty(data)) {
|
||||
fs.existsSync(file) && fs.unlinkSync(file)
|
||||
} else {
|
||||
let yaml = YAML.stringify(data)
|
||||
fs.writeFileSync(file, yaml, 'utf8')
|
||||
}
|
||||
}
|
||||
|
||||
saveBingCk (userId, data) {
|
||||
let file = `./data/MysCookie/${userId}.yaml`
|
||||
if (lodash.isEmpty(data)) {
|
||||
fs.existsSync(file) && fs.unlinkSync(file)
|
||||
} else {
|
||||
let yaml = YAML.stringify(data)
|
||||
fs.writeFileSync(file, yaml, 'utf8')
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 原神角色id转换角色名字
|
||||
*/
|
||||
roleIdToName(id) {
|
||||
let name = this.getdefSet('role', 'name')
|
||||
if (name[id]) {
|
||||
return name[id][0]
|
||||
}
|
||||
|
||||
/**
|
||||
* 原神角色id转换角色名字
|
||||
*/
|
||||
roleIdToName (id) {
|
||||
let name = this.getdefSet('role', 'name')
|
||||
if (name[id]) {
|
||||
return name[id][0]
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
return ''
|
||||
}
|
||||
/** 原神角色别名转id */
|
||||
roleNameToID(keyword) {
|
||||
if (!this.nameID) {
|
||||
this.nameID = new Map()
|
||||
let nameArr = this.getdefSet('role', 'name')
|
||||
for (let i in nameArr) {
|
||||
for (let val of nameArr[i]) {
|
||||
this.nameID.set(val, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isNaN(keyword)) keyword = Number(keyword)
|
||||
let roelId = this.nameID.get(keyword)
|
||||
return roelId || false
|
||||
}
|
||||
|
||||
/** 原神角色别名转id */
|
||||
roleNameToID (keyword) {
|
||||
if (!this.nameID) {
|
||||
this.nameID = new Map()
|
||||
let nameArr = this.getdefSet('role', 'name')
|
||||
for (let i in nameArr) {
|
||||
for (let val of nameArr[i]) {
|
||||
this.nameID.set(val, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isNaN(keyword)) keyword = Number(keyword)
|
||||
let roelId = this.nameID.get(keyword)
|
||||
return roelId || false
|
||||
}
|
||||
/**
|
||||
* 原神角色武器长名称缩写
|
||||
* @param name 名称
|
||||
* @param isWeapon 是否武器
|
||||
*/
|
||||
shortName(name, isWeapon = false) {
|
||||
let other = {}
|
||||
if (isWeapon) {
|
||||
other = this.getdefSet('weapon', 'other')
|
||||
} else {
|
||||
other = this.getdefSet('role', 'other')
|
||||
}
|
||||
return other.sortName[name] ?? name
|
||||
}
|
||||
|
||||
/**
|
||||
* 原神角色武器长名称缩写
|
||||
* @param name 名称
|
||||
* @param isWeapon 是否武器
|
||||
*/
|
||||
shortName (name, isWeapon = false) {
|
||||
let other = {}
|
||||
if (isWeapon) {
|
||||
other = this.getdefSet('weapon', 'other')
|
||||
} else {
|
||||
other = this.getdefSet('role', 'other')
|
||||
}
|
||||
return other.sortName[name] ?? name
|
||||
}
|
||||
/** 公共配置ck文件修改hook */
|
||||
async change_myspubCk() {
|
||||
let MysInfo = await import('./mys/mysInfo.js').default
|
||||
await new MysInfo().addPubCk()
|
||||
}
|
||||
|
||||
/** 公共配置ck文件修改hook */
|
||||
async change_myspubCk () {
|
||||
let MysInfo = await import('./mys/mysInfo.js').default
|
||||
await new MysInfo().addPubCk()
|
||||
}
|
||||
getGachaSet(groupId = '') {
|
||||
let config = this.getYaml('gacha', 'set', 'config')
|
||||
let def = config.default
|
||||
if (config[groupId]) {
|
||||
return {
|
||||
...def,
|
||||
...config[groupId]
|
||||
}
|
||||
}
|
||||
return def
|
||||
}
|
||||
|
||||
getGachaSet (groupId = '') {
|
||||
let config = this.getYaml('gacha', 'set', 'config')
|
||||
let def = config.default
|
||||
if (config[groupId]) {
|
||||
return { ...def, ...config[groupId] }
|
||||
}
|
||||
return def
|
||||
}
|
||||
getMsgUid(msg) {
|
||||
let ret = /[1|2|5][0-9]{8}/g.exec(msg)
|
||||
if (!ret) return false
|
||||
return ret[0]
|
||||
}
|
||||
|
||||
getMsgUid (msg) {
|
||||
let ret = /[1|2|5][0-9]{8}/g.exec(msg)
|
||||
if (!ret) return false
|
||||
return ret[0]
|
||||
}
|
||||
/**
|
||||
* 获取消息内原神角色名称,uid
|
||||
* @param msg 判断消息
|
||||
* @param filterMsg 过滤消息
|
||||
* @return roleId 角色id
|
||||
* @return name 角色名称
|
||||
* @return alias 当前别名
|
||||
* @return uid 游戏uid
|
||||
*/
|
||||
getRole(msg, filterMsg = '') {
|
||||
let alias = msg.replace(/#|老婆|老公|[1|2|5][0-9]{8}/g, '').trim()
|
||||
if (filterMsg) {
|
||||
alias = alias.replace(new RegExp(filterMsg, 'g'), '').trim()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取消息内原神角色名称,uid
|
||||
* @param msg 判断消息
|
||||
* @param filterMsg 过滤消息
|
||||
* @return roleId 角色id
|
||||
* @return name 角色名称
|
||||
* @return alias 当前别名
|
||||
* @return uid 游戏uid
|
||||
*/
|
||||
getRole (msg, filterMsg = '') {
|
||||
let alias = msg.replace(/#|老婆|老公|[1|2|5][0-9]{8}/g, '').trim()
|
||||
if (filterMsg) {
|
||||
alias = alias.replace(new RegExp(filterMsg, 'g'), '').trim()
|
||||
}
|
||||
/** 判断是否命中别名 */
|
||||
let roleId = this.roleNameToID(alias)
|
||||
if (!roleId) return false
|
||||
/** 获取uid */
|
||||
let uid = this.getMsgUid(msg) || ''
|
||||
|
||||
/** 判断是否命中别名 */
|
||||
let roleId = this.roleNameToID(alias)
|
||||
if (!roleId) return false
|
||||
/** 获取uid */
|
||||
let uid = this.getMsgUid(msg) || ''
|
||||
|
||||
return {
|
||||
roleId,
|
||||
uid,
|
||||
alias,
|
||||
name: this.roleIdToName(roleId)
|
||||
}
|
||||
}
|
||||
return {
|
||||
roleId,
|
||||
uid,
|
||||
alias,
|
||||
name: this.roleIdToName(roleId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new GsCfg()
|
||||
|
158
model/mys/mihoyo-api.js
Normal file
158
model/mys/mihoyo-api.js
Normal file
@ -0,0 +1,158 @@
|
||||
import utils from './utils.js';
|
||||
import md5 from 'md5';
|
||||
import _ from 'lodash';
|
||||
import superagent from 'superagent';
|
||||
import fs from "fs";
|
||||
import YAML from 'yaml'
|
||||
import {Data} from "../../components/index.js";
|
||||
import fetch from "node-fetch"
|
||||
const APP_VERSION = "2.2.0";
|
||||
const DEVICE_ID = utils.randomString(32).toUpperCase();
|
||||
const DEVICE_NAME = utils.randomString(_.random(1, 10));
|
||||
const _path = process.cwd();
|
||||
let YamlDataUrl = `${_path}/plugins/xiaoyao-cvs-plugin/data/yaml`
|
||||
export default class MihoYoApi {
|
||||
constructor(e) {
|
||||
if (e) {
|
||||
this.e = e
|
||||
this.userId = String(e.user_id)
|
||||
}
|
||||
Data.createDir("", YamlDataUrl, false);
|
||||
}
|
||||
|
||||
async forumSign(forumId) {
|
||||
const url = `https://api-takumi.mihoyo.com/apihub/sapi/signIn?gids=${forumId}`;
|
||||
let res = await superagent.post(url).set(this._getHeader()).timeout(10000);
|
||||
let resObj = JSON.parse(res.text);
|
||||
// Bot.logger.mark(`ForumSign: ${res.text}`);
|
||||
return resObj;
|
||||
}
|
||||
|
||||
async forumPostList(forumId) {
|
||||
const url =
|
||||
`https://api-takumi.mihoyo.com/post/api/getForumPostList?forum_id=${forumId}&is_good=false&is_hot=false&page_size=20&sort_type=1`;
|
||||
|
||||
let res = await superagent.get(url).set(this._getHeader()).timeout(10000);
|
||||
let resObj = JSON.parse(res.text);
|
||||
// logger.mark(`ForumList: ${res.text}`)
|
||||
return resObj;
|
||||
}
|
||||
|
||||
async forumPostDetail(postId) {
|
||||
const url = `https://api-takumi.mihoyo.com/post/api/getPostFull?post_id=${postId}`;
|
||||
|
||||
let res = await superagent.get(url).set(this._getHeader()).timeout(10000);
|
||||
let resObj = JSON.parse(res.text);
|
||||
// logger.mark(`ForumDetail: ${res.text}`)
|
||||
return resObj;
|
||||
}
|
||||
|
||||
async forumPostShare(postId) {
|
||||
const url = `https://api-takumi.mihoyo.com/apihub/api/getShareConf?entity_id=${postId}&entity_type=1`;
|
||||
let res = await superagent.get(url).set(this._getHeader()).timeout(10000);
|
||||
let resObj = JSON.parse(res.text);
|
||||
// Bot.logger.mark(`ForumShare: ${res.text}`)
|
||||
return resObj;
|
||||
}
|
||||
|
||||
async forumPostVote(postId) {
|
||||
const url = `https://api-takumi.mihoyo.com/apihub/sapi/upvotePost`;
|
||||
const upvotePostData = {
|
||||
"post_id": postId,
|
||||
"is_cancel": false
|
||||
}
|
||||
let res = await superagent.post(url).set(this._getHeader()).send(JSON.stringify(upvotePostData));
|
||||
let resObj = JSON.parse(res.text);
|
||||
// Bot.logger.mark(`ForumVote: ${res.text}`)
|
||||
return resObj;
|
||||
}
|
||||
async stoken(cookie, e) {
|
||||
this.e=e;
|
||||
if(this.getStoken(e.user_id)){
|
||||
return true;
|
||||
}
|
||||
const map = this.getCookieMap(cookie);
|
||||
const loginTicket = map.get("login_ticket");
|
||||
const loginUid = map.get("login_uid");
|
||||
const url = "https://api-takumi.mihoyo.com/auth/api/getMultiTokenByLoginTicket?login_ticket=" +
|
||||
loginTicket + "&token_types=3&uid=" + loginUid;
|
||||
fetch(url, {
|
||||
"headers": {
|
||||
"x-rpc-device_id": "zxcvbnmasadfghjk123456",
|
||||
"Content-Type": "application/json;charset=UTF-8",
|
||||
"x-rpc-client_type": "",
|
||||
"x-rpc-app_version": "",
|
||||
"DS": "",
|
||||
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_0_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/%s",
|
||||
"Referer": "cors",
|
||||
"Accept-Encoding": "gzip, deflate, br",
|
||||
"x-rpc-channel": "appstore",
|
||||
},
|
||||
"method": "GET"
|
||||
}).then(
|
||||
function(response) {
|
||||
if (response.status !== 200) {
|
||||
return false;
|
||||
}
|
||||
response.json().then(function(data) {
|
||||
// console.log(data);
|
||||
let datalist = {
|
||||
stuid: map.get("account_id"),
|
||||
stoken: data.data.list[0].token,
|
||||
ltoken: data.data.list[1].token,
|
||||
uid: e.uid
|
||||
}
|
||||
let yamlStr = YAML.stringify(datalist);
|
||||
fs.writeFileSync(`${YamlDataUrl}/${e.user_id}.yaml`, yamlStr, 'utf8');
|
||||
return true;
|
||||
});
|
||||
}
|
||||
).catch(function(err) {
|
||||
return false;
|
||||
});
|
||||
return true;
|
||||
}
|
||||
_getHeader() {
|
||||
const randomStr = utils.randomString(6);
|
||||
const timestamp = Math.floor(Date.now() / 1000)
|
||||
let data=this.getStoken(this.e.user_id);
|
||||
// console.log(data)
|
||||
// iOS sign
|
||||
let sign = md5(`salt=b253c83ab2609b1b600eddfe974df47b&t=${timestamp}&r=${randomStr}`);
|
||||
let cookie =`stuid=${data.stuid};stoken=${data.stoken};ltoken=${data.ltoken};`;
|
||||
return {
|
||||
'Cookie': cookie,
|
||||
'Content-Type': 'application/json',
|
||||
'User-Agent': 'Hyperion/67 CFNetwork/1128.0.1 Darwin/19.6.0',
|
||||
'Referer': 'https://app.mihoyo.com',
|
||||
'x-rpc-channel': 'appstore',
|
||||
'x-rpc-device_id': DEVICE_ID,
|
||||
'x-rpc-app_version': APP_VERSION,
|
||||
'x-rpc-device_model': 'iPhone11,8',
|
||||
'x-rpc-device_name': DEVICE_NAME,
|
||||
'x-rpc-client_type': '1', // 1 - iOS, 2 - Android, 4 - Web
|
||||
'DS': `${timestamp},${randomStr},${sign}`
|
||||
// 'DS': `1602569298,k0xfEh,07f4545f5d88eac59cb1257aef74a570`
|
||||
}
|
||||
}
|
||||
getCookieMap(cookie) {
|
||||
let cookiePattern = /^(\S+)=(\S+)$/;
|
||||
let cookieArray = cookie.split("; ");
|
||||
let cookieMap = new Map();
|
||||
for (let item of cookieArray) {
|
||||
let entry = cookiePattern.exec(item);
|
||||
cookieMap.set(entry[1], entry[2]);
|
||||
}
|
||||
return cookieMap;
|
||||
}
|
||||
getStoken(userId) {
|
||||
let file = `${YamlDataUrl}/${userId}.yaml`
|
||||
try {
|
||||
let ck = fs.readFileSync(file, 'utf-8')
|
||||
ck = YAML.parse(ck)
|
||||
return ck
|
||||
} catch (error) {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
}
|
29
model/mys/utils.js
Normal file
29
model/mys/utils.js
Normal file
@ -0,0 +1,29 @@
|
||||
import _ from 'lodash';
|
||||
|
||||
export async function sleepAsync(sleepms) {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, sleepms)
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
export async function randomSleepAsync(){
|
||||
let sleep = 2 * 1000 + _.random(3 * 1000);
|
||||
await sleepAsync(sleep);
|
||||
}
|
||||
|
||||
export function randomString(length){
|
||||
let randomStr = '';
|
||||
for (let i = 0; i < length; i++) {
|
||||
randomStr += _.sample('abcdefghijklmnopqrstuvwxyz0123456789');
|
||||
}
|
||||
return randomStr;
|
||||
}
|
||||
|
||||
export default {
|
||||
sleepAsync,
|
||||
randomSleepAsync,
|
||||
randomString
|
||||
}
|
Loading…
Reference in New Issue
Block a user