mirror of
https://github.com/ctrlcvs/xiaoyao-cvs-plugin.git
synced 2024-12-22 19:10:53 +08:00
初步兼容yunzaiV3版本
This commit is contained in:
parent
cb9b06c6ef
commit
a7294079e4
@ -1,3 +1,6 @@
|
|||||||
|
# 1.1.1
|
||||||
|
* 初步兼容V3版本
|
||||||
|
|
||||||
# 1.1.0
|
# 1.1.0
|
||||||
* 增加`#图鉴帮助`用于查看帮助命令
|
* 增加`#图鉴帮助`用于查看帮助命令
|
||||||
* 增加`#图鉴设置`用于设置图鉴相关功能
|
* 增加`#图鉴设置`用于设置图鉴相关功能
|
||||||
|
44
adapter/index.js
Normal file
44
adapter/index.js
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import plugin from '../../../lib/plugins/plugin.js'
|
||||||
|
import * as Atlas from '../apps/index.js'
|
||||||
|
import { render } from './render.js'
|
||||||
|
import { checkAuth, getMysApi } from './mys.js'
|
||||||
|
|
||||||
|
export class atlas extends plugin {
|
||||||
|
constructor () {
|
||||||
|
super({
|
||||||
|
name: 'xiaoyao-cvs-plugin',
|
||||||
|
desc: '图鉴插件',
|
||||||
|
event: 'message',
|
||||||
|
priority: 50,
|
||||||
|
rule: [{
|
||||||
|
reg: '.+',
|
||||||
|
fnc: 'dispatch'
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async dispatch (e) {
|
||||||
|
let msg = e.raw_message
|
||||||
|
e.checkAuth = async function (cfg) {
|
||||||
|
return await checkAuth(e, cfg)
|
||||||
|
}
|
||||||
|
e.getMysApi = async function (cfg) {
|
||||||
|
return await getMysApi(e, cfg)
|
||||||
|
}
|
||||||
|
msg = '#' + msg.replace('#', '')
|
||||||
|
for (let fn in Atlas.rule) {
|
||||||
|
let cfg = Atlas.rule[fn]
|
||||||
|
if (Atlas[fn] && new RegExp(cfg.reg).test(msg)) {
|
||||||
|
let ret = await Atlas[fn](e, {
|
||||||
|
render
|
||||||
|
})
|
||||||
|
if (ret === true) {
|
||||||
|
console.log('ret true')
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
114
adapter/mys.js
Normal file
114
adapter/mys.js
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
import MysInfo from '../../genshin/model/mys/mysInfo.js'
|
||||||
|
import lodash from 'lodash'
|
||||||
|
|
||||||
|
class User {
|
||||||
|
constructor (cfg) {
|
||||||
|
this.id = cfg.id
|
||||||
|
this.uid = cfg.uid
|
||||||
|
this.cookie = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存用户配置
|
||||||
|
async setCfg (path, value) {
|
||||||
|
console.log(this.id)
|
||||||
|
let userCfg = await redis.get(`genshin:user-cfg:${this.id}`)
|
||||||
|
userCfg = userCfg ? JSON.parse(userCfg) : {}
|
||||||
|
lodash.set(userCfg, path, value)
|
||||||
|
await redis.set(`genshin:user-cfg:${this.id}`, JSON.stringify(userCfg))
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 获取用户配置 */
|
||||||
|
async getCfg (path, defaultValue) {
|
||||||
|
let userCfg = await redis.get(`genshin:user-cfg:${this.id}`)
|
||||||
|
userCfg = userCfg ? JSON.parse(userCfg) : {}
|
||||||
|
return lodash.get(userCfg, path, defaultValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
async getMysUser () {
|
||||||
|
return {
|
||||||
|
uid: this.uid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Mys {
|
||||||
|
constructor (e, uid, MysApi) {
|
||||||
|
this.selfUser = new User({ id: e.user_id, uid })
|
||||||
|
this.targetUser = {
|
||||||
|
uid
|
||||||
|
}
|
||||||
|
this.e = e
|
||||||
|
this.MysApi = MysApi
|
||||||
|
e.targetUser = this.targetUser
|
||||||
|
e.selfUser = this.selfUser
|
||||||
|
}
|
||||||
|
|
||||||
|
async getData (api, data) {
|
||||||
|
if (!this.MysApi) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
let ret = await MysInfo.get(this.e, api, data)
|
||||||
|
if (!ret) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return ret.data || ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取角色信息
|
||||||
|
async getCharacter () {
|
||||||
|
return await this.getData('character')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取角色详情
|
||||||
|
async getAvatar (id) {
|
||||||
|
return await this.getData('detail', { avatar_id: id })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 首页宝箱信息
|
||||||
|
async getIndex () {
|
||||||
|
return await this.getData('index')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取深渊信息
|
||||||
|
async getSpiralAbyss (type = 1) {
|
||||||
|
return await this.getData('spiralAbyss', { schedule_type: type })
|
||||||
|
}
|
||||||
|
|
||||||
|
async getDetail (id) {
|
||||||
|
return await this.getData('detail', { avatar_id: id })
|
||||||
|
}
|
||||||
|
|
||||||
|
async getCompute (data) {
|
||||||
|
return await this.getData('compute', data)
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAvatarSkill (id) {
|
||||||
|
return await this.getData('avatarSkill', { avatar_id: id })
|
||||||
|
}
|
||||||
|
|
||||||
|
get isSelfCookie () {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getMysApi (e, cfg) {
|
||||||
|
let { auth = 'all' } = cfg
|
||||||
|
let uid = await MysInfo.getUid(e)
|
||||||
|
if (!uid) return false
|
||||||
|
|
||||||
|
/* 检查user ck */
|
||||||
|
let isCookieUser = await MysInfo.checkUidBing(uid)
|
||||||
|
if (auth === 'cookie' && !isCookieUser) {
|
||||||
|
e.reply('尚未绑定Cookie...')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
let MysApi = await MysInfo.init(e, 'roleIndex')
|
||||||
|
if (!MysApi) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return new Mys(e, uid, MysApi)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function checkAuth (e, cfg) {
|
||||||
|
return new User({ id: e.user_id })
|
||||||
|
}
|
21
adapter/render.js
Normal file
21
adapter/render.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import lodash from 'lodash'
|
||||||
|
import Data from '../components/Data.js'
|
||||||
|
import puppeteer from '../../../lib/puppeteer/puppeteer.js'
|
||||||
|
|
||||||
|
const plugin = 'xiaoyao-cvs-plugin'
|
||||||
|
|
||||||
|
const _path = process.cwd()
|
||||||
|
|
||||||
|
export async function render (app = '', tpl = '', data = {}, imgType = 'jpeg') {
|
||||||
|
// 在data中保存plugin信息
|
||||||
|
data._plugin = plugin
|
||||||
|
|
||||||
|
if (lodash.isUndefined(data._res_path)) {
|
||||||
|
data._res_path = `../../../../../plugins/${plugin}/resources/`
|
||||||
|
}
|
||||||
|
Data.createDir(_path + '/data/', `html/${plugin}/${app}/${tpl}`)
|
||||||
|
data.saveId = data.saveId || data.save_id || tpl
|
||||||
|
data.tplFile = `./plugins/${plugin}/resources/${app}/${tpl}.html`
|
||||||
|
data.pluResPath = data._res_path
|
||||||
|
return await puppeteer.screenshot(`${plugin}/${app}/${tpl}`, data)
|
||||||
|
}
|
49
apps/Note.js
49
apps/Note.js
@ -5,24 +5,20 @@ import fetch from "node-fetch";
|
|||||||
import Common from "../components/Common.js";
|
import Common from "../components/Common.js";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import format from "date-format";
|
import format from "date-format";
|
||||||
import puppeteer from "puppeteer";
|
import { isV3 } from '../components/Changelog.js'
|
||||||
|
import MysInfo from '../model/mys/mysInfo.js'
|
||||||
import { MysUser, User } from "../../../lib/components/Models.js";
|
// import { MysUser } from "../../../lib/components/Models.js";
|
||||||
import common from "../../../lib/common.js";
|
// import common from "../../../lib/common.js";
|
||||||
import lodash from "lodash";
|
import lodash from "lodash";
|
||||||
import { getPluginRender } from "../../../lib/render.js"
|
import { getPluginRender } from "./render.js";
|
||||||
|
|
||||||
|
import gsCfg from '../model/gsCfg.js'
|
||||||
import {
|
import {
|
||||||
Cfg,
|
Cfg,
|
||||||
Data
|
Data
|
||||||
} from "../components/index.js";
|
} from "../components/index.js";
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
// import MysApi from "../components/MysApi.js"
|
import MysApi from "../model/mys/mysApi.js";
|
||||||
|
|
||||||
import {
|
|
||||||
getUrl,
|
|
||||||
getHeaders
|
|
||||||
} from "../../../lib/app/mysApi.js";
|
|
||||||
|
|
||||||
const _path = process.cwd();
|
const _path = process.cwd();
|
||||||
let role_user = Data.readJSON(`${_path}/plugins/xiaoyao-cvs-plugin/resources/dailyNote/json/`, "dispatch_time");
|
let role_user = Data.readJSON(`${_path}/plugins/xiaoyao-cvs-plugin/resources/dailyNote/json/`, "dispatch_time");
|
||||||
|
|
||||||
@ -44,7 +40,11 @@ export async function Note(e, {
|
|||||||
if (!Cfg.get("sys.Note")&&!poke) {
|
if (!Cfg.get("sys.Note")&&!poke) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let cookie, uid;
|
let cookie, uid,res;
|
||||||
|
if(isV3){
|
||||||
|
res = await MysInfo.get(e, 'dailyNote')
|
||||||
|
if (!res || res.retcode !== 0) return false
|
||||||
|
}else{
|
||||||
if (NoteCookie[e.user_id]) {
|
if (NoteCookie[e.user_id]) {
|
||||||
cookie = NoteCookie[e.user_id].cookie;
|
cookie = NoteCookie[e.user_id].cookie;
|
||||||
uid = NoteCookie[e.user_id].uid;
|
uid = NoteCookie[e.user_id].uid;
|
||||||
@ -55,14 +55,12 @@ export async function Note(e, {
|
|||||||
e.reply(`尚未配置,无法查询体力\n配置教程:${BotConfig.cookieDoc}`);
|
e.reply(`尚未配置,无法查询体力\n配置教程:${BotConfig.cookieDoc}`);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await getDailyNote(uid, cookie);
|
const response = await getDailyNote(uid, cookie);
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
e.reply("米游社接口错误");
|
e.reply("米游社接口错误");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const res = await response.json();
|
res = await response.json();
|
||||||
|
|
||||||
if (res.retcode == 10102) {
|
if (res.retcode == 10102) {
|
||||||
if (!e.openDailyNote) {
|
if (!e.openDailyNote) {
|
||||||
e.openDailyNote = true;
|
e.openDailyNote = true;
|
||||||
@ -73,14 +71,12 @@ export async function Note(e, {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res.retcode != 0) {
|
if (res.retcode != 0) {
|
||||||
if (res.message == "Please login") {
|
if (res.message == "Please login") {
|
||||||
Bot.logger.mark(`体力cookie已失效`);
|
Bot.logger.mark(`体力cookie已失效`);
|
||||||
e.reply(`体力cookie已失效,请重新配置\n注意:退出米游社登录cookie将会失效!`);
|
e.reply(`体力cookie已失效,请重新配置\n注意:退出米游社登录cookie将会失效!`);
|
||||||
|
|
||||||
if (NoteCookie[e.user_id]) {
|
if (NoteCookie[e.user_id]) {
|
||||||
await MysUser.delNote(NoteCookie[e.user_id]);
|
// await MysUser.delNote(NoteCookie[e.user_id]);
|
||||||
delete NoteCookie[e.user_id];
|
delete NoteCookie[e.user_id];
|
||||||
saveJson();
|
saveJson();
|
||||||
}
|
}
|
||||||
@ -102,6 +98,7 @@ export async function Note(e, {
|
|||||||
NoteCookie[e.user_id].maxTime = new Date().getTime() + res.data.resin_recovery_time * 1000;
|
NoteCookie[e.user_id].maxTime = new Date().getTime() + res.data.resin_recovery_time * 1000;
|
||||||
saveJson();
|
saveJson();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let data = res.data;
|
let data = res.data;
|
||||||
//推送任务
|
//推送任务
|
||||||
@ -143,9 +140,9 @@ export async function Note(e, {
|
|||||||
val.remained_time = new Date().getTime() + val.remained_time * 1000;
|
val.remained_time = new Date().getTime() + val.remained_time * 1000;
|
||||||
// console.log(val.remained_time)
|
// console.log(val.remained_time)
|
||||||
var urls_avatar_side = val.avatar_side_icon.split("_");
|
var urls_avatar_side = val.avatar_side_icon.split("_");
|
||||||
let id = YunzaiApps.mysInfo.roleIdToName(urls_avatar_side[urls_avatar_side.length - 1].replace(
|
let id = gsCfg.roleIdToName(urls_avatar_side[urls_avatar_side.length - 1].replace(
|
||||||
/(.png|.jpg)/g, ""));
|
/(.png|.jpg)/g, ""));
|
||||||
let name = YunzaiApps.mysInfo.roleIdToName(id, true);
|
let name = gsCfg.roleIdToName(id, true);
|
||||||
var time_cha = 20;
|
var time_cha = 20;
|
||||||
if (role_user["12"].includes(name)) {
|
if (role_user["12"].includes(name)) {
|
||||||
time_cha = 15;
|
time_cha = 15;
|
||||||
@ -287,14 +284,14 @@ async function dateTime_(time) {
|
|||||||
time) < 19.5 ? "傍晚" : format("hh",
|
time) < 19.5 ? "傍晚" : format("hh",
|
||||||
time) < 22 ? "晚上" : "深夜";
|
time) < 22 ? "晚上" : "深夜";
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getDailyNote(uid, cookie) {
|
async function getDailyNote(uid, cookie) {
|
||||||
|
let mysApi = new MysApi(uid, cookie)
|
||||||
let {
|
let {
|
||||||
url,
|
url,
|
||||||
headers,
|
headers,
|
||||||
query,
|
query,
|
||||||
body
|
body
|
||||||
} = getUrl("dailyNote", uid);
|
} = mysApi.getUrl("dailyNote", uid);
|
||||||
headers.Cookie = cookie;
|
headers.Cookie = cookie;
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
method: "get",
|
method: "get",
|
||||||
@ -302,7 +299,6 @@ async function getDailyNote(uid, cookie) {
|
|||||||
});
|
});
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function saveJson() {
|
export async function saveJson() {
|
||||||
let path = "data/NoteCookie/NoteCookie.json";
|
let path = "data/NoteCookie/NoteCookie.json";
|
||||||
fs.writeFileSync(path, JSON.stringify(NoteCookie, "", "\t"));
|
fs.writeFileSync(path, JSON.stringify(NoteCookie, "", "\t"));
|
||||||
@ -337,7 +333,10 @@ export async function DailyNoteTask() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
e.reply = (msg) => {
|
e.reply = (msg) => {
|
||||||
common.relpyPrivate(user_id, msg);
|
Bot.pickUser(user_id*1).sendMsg(msg).catch((err) => {
|
||||||
|
logger.mark(err)
|
||||||
|
})
|
||||||
|
// common.relpyPrivate(user_id, msg);
|
||||||
};
|
};
|
||||||
//判断今天是否推送
|
//判断今天是否推送
|
||||||
if (cookie.maxTime && cookie.maxTime > 0 && new Date().getTime() > cookie.maxTime - (160 - sendResin) * 8 *
|
if (cookie.maxTime && cookie.maxTime > 0 && new Date().getTime() > cookie.maxTime - (160 - sendResin) * 8 *
|
||||||
|
@ -13,9 +13,7 @@ import {
|
|||||||
Cfg
|
Cfg
|
||||||
} from "../components/index.js";
|
} from "../components/index.js";
|
||||||
import Common from "../components/Common.js";
|
import Common from "../components/Common.js";
|
||||||
import {
|
|
||||||
init
|
|
||||||
} from "../apps/xiaoyao_image.js"
|
|
||||||
|
|
||||||
const require = createRequire(
|
const require = createRequire(
|
||||||
import.meta.url);
|
import.meta.url);
|
||||||
@ -156,14 +154,12 @@ export async function updateRes(e) {
|
|||||||
}
|
}
|
||||||
let numRet = /(\d*) files changed,/.exec(stdout);
|
let numRet = /(\d*) files changed,/.exec(stdout);
|
||||||
if (numRet && numRet[1]) {
|
if (numRet && numRet[1]) {
|
||||||
init()
|
|
||||||
e.reply(`报告主人,更新成功,此次更新了${numRet[1]}个图片~`);
|
e.reply(`报告主人,更新成功,此次更新了${numRet[1]}个图片~`);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (error) {
|
if (error) {
|
||||||
e.reply("更新失败!\nError code: " + error.code + "\n" + error.stack + "\n 请稍后重试。");
|
e.reply("更新失败!\nError code: " + error.code + "\n" + error.stack + "\n 请稍后重试。");
|
||||||
} else {
|
} else {
|
||||||
init()
|
|
||||||
e.reply("图片加量包更新成功~");
|
e.reply("图片加量包更新成功~");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -176,7 +172,6 @@ export async function updateRes(e) {
|
|||||||
if (error) {
|
if (error) {
|
||||||
e.reply("角色图片加量包安装失败!\nError code: " + error.code + "\n" + error.stack + "\n 请稍后重试。");
|
e.reply("角色图片加量包安装失败!\nError code: " + error.code + "\n" + error.stack + "\n 请稍后重试。");
|
||||||
} else {
|
} else {
|
||||||
init()
|
|
||||||
e.reply("角色图片加量包安装成功!您后续也可以通过 #图鉴更新 命令来更新图像");
|
e.reply("角色图片加量包安装成功!您后续也可以通过 #图鉴更新 命令来更新图像");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
70
apps/index.js
Normal file
70
apps/index.js
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
import lodash from "lodash";
|
||||||
|
import {
|
||||||
|
AtlasAlias
|
||||||
|
} from "./xiaoyao_image.js";
|
||||||
|
import {
|
||||||
|
versionInfo,
|
||||||
|
help
|
||||||
|
} from "./help.js";
|
||||||
|
import {
|
||||||
|
Note,DailyNoteTask,
|
||||||
|
Note_appoint,pokeNote
|
||||||
|
} from "./Note.js";
|
||||||
|
import {
|
||||||
|
rule as adminRule,
|
||||||
|
updateRes,
|
||||||
|
sysCfg,
|
||||||
|
updateMiaoPlugin
|
||||||
|
} from "./admin.js";
|
||||||
|
import {
|
||||||
|
currentVersion
|
||||||
|
} from "../components/Changelog.js";
|
||||||
|
export {
|
||||||
|
updateRes,
|
||||||
|
updateMiaoPlugin,
|
||||||
|
versionInfo,
|
||||||
|
Note_appoint,pokeNote,
|
||||||
|
sysCfg,
|
||||||
|
help,DailyNoteTask,
|
||||||
|
AtlasAlias,
|
||||||
|
Note
|
||||||
|
};
|
||||||
|
|
||||||
|
let rule = {
|
||||||
|
versionInfo: {
|
||||||
|
reg: "^#图鉴版本$",
|
||||||
|
describe: "【#帮助】 图鉴版本介绍",
|
||||||
|
},
|
||||||
|
help: {
|
||||||
|
reg: "^#?(图鉴)?(命令|帮助|菜单|help|说明|功能|指令|使用说明)$",
|
||||||
|
describe: "查看插件的功能",
|
||||||
|
},
|
||||||
|
AtlasAlias: {
|
||||||
|
reg: "^(#(.*)|.*图鉴)$",
|
||||||
|
describe: "角色、食物、怪物、武器信息图鉴",
|
||||||
|
},
|
||||||
|
Note: {
|
||||||
|
reg: "^#*(体力|树脂|查询体力|便笺|便签)$",
|
||||||
|
describe: "体力",
|
||||||
|
},
|
||||||
|
Note_appoint: {
|
||||||
|
reg: "^#体力模板(设置(.*)|列表)$",
|
||||||
|
describe: "体力模板设置",
|
||||||
|
},
|
||||||
|
pokeNote: {
|
||||||
|
reg: "#poke#",
|
||||||
|
describe: "体力",
|
||||||
|
},
|
||||||
|
|
||||||
|
...adminRule
|
||||||
|
};
|
||||||
|
|
||||||
|
lodash.forEach(rule, (r) => {
|
||||||
|
r.priority = r.priority || 50;
|
||||||
|
r.prehash = true;
|
||||||
|
r.hashMark = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
export {
|
||||||
|
rule
|
||||||
|
};
|
@ -3,7 +3,7 @@ import fs from "fs";
|
|||||||
import puppeteer from "puppeteer";
|
import puppeteer from "puppeteer";
|
||||||
import lodash from "lodash";
|
import lodash from "lodash";
|
||||||
|
|
||||||
import { Data } from "../../../lib/components/index.js";
|
import { Data } from "../components/index.js";
|
||||||
|
|
||||||
const _path = process.cwd();
|
const _path = process.cwd();
|
||||||
//html模板
|
//html模板
|
||||||
@ -33,6 +33,7 @@ let shoting = [];
|
|||||||
* @param data 前端参数,必传 data.save_id 用来区分模板
|
* @param data 前端参数,必传 data.save_id 用来区分模板
|
||||||
* @param imgType 图片类型 jpeg,png(清晰一点,大小更大)
|
* @param imgType 图片类型 jpeg,png(清晰一点,大小更大)
|
||||||
*/
|
*/
|
||||||
|
const plugin="xiaoyao-cvs-plugin"
|
||||||
async function render1(app = "", type = "", data = {}, imgType = "jpeg") {
|
async function render1(app = "", type = "", data = {}, imgType = "jpeg") {
|
||||||
if (lodash.isUndefined(data._res_path)) {
|
if (lodash.isUndefined(data._res_path)) {
|
||||||
data._res_path = `../../../../../plugins/xiaoyao-cvs-plugin/resources/`;
|
data._res_path = `../../../../../plugins/xiaoyao-cvs-plugin/resources/`;
|
||||||
@ -197,4 +198,29 @@ async function browserInit() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { render1, browserInit, renderNum };
|
function getPluginRender(plugin) {
|
||||||
|
return async function (app = "", type = "", data = {}, imgType = "jpeg") {
|
||||||
|
// 在data中保存plugin信息
|
||||||
|
data._plugin = plugin;
|
||||||
|
|
||||||
|
if (lodash.isUndefined(data._res_path)) {
|
||||||
|
data._res_path = `../../../../../plugins/${plugin}/resources/`;
|
||||||
|
}
|
||||||
|
if (lodash.isUndefined(data._sys_res_path)) {
|
||||||
|
data._sys_res_path = `../../../../../resources/`;
|
||||||
|
}
|
||||||
|
let tplKey = `${plugin}.${app}.${type}`;
|
||||||
|
let saveId = data.save_id;
|
||||||
|
let tplFile = _path + `/plugins/${plugin}/resources/${app}/${type}.html`;
|
||||||
|
Data.createDir(_path + `/data/`, `html/plugin_${plugin}/${app}/${type}`);
|
||||||
|
let savePath = _path + `/data/html/plugin_${plugin}/${app}/${type}/${saveId}.html`;
|
||||||
|
return await doRender(app, type, data, imgType, {
|
||||||
|
tplKey,
|
||||||
|
tplFile,
|
||||||
|
savePath,
|
||||||
|
saveId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { render1, browserInit, renderNum,getPluginRender };
|
||||||
|
@ -8,10 +8,11 @@ import {
|
|||||||
import Data from "../components/Data.js"
|
import Data from "../components/Data.js"
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import fetch from "node-fetch";
|
import fetch from "node-fetch";
|
||||||
|
import gsCfg from '../model/gsCfg.js'
|
||||||
const _path = process.cwd();
|
const _path = process.cwd();
|
||||||
const __dirname = path.resolve();
|
const __dirname = path.resolve();
|
||||||
|
|
||||||
const list = ["shiwu_tujian", "yuanmo_tujian", "mijin_tujian", "shengyiwu_tujian"]
|
const list = ["wuqi_tujian","shiwu_tujian", "yuanmo_tujian", "mijin_tujian", "shengyiwu_tujian"]
|
||||||
export async function AtlasAlias(e) {
|
export async function AtlasAlias(e) {
|
||||||
if (!Cfg.get("Atlas.all")) {
|
if (!Cfg.get("Atlas.all")) {
|
||||||
return false;
|
return false;
|
||||||
@ -25,7 +26,7 @@ export async function AtlasAlias(e) {
|
|||||||
}
|
}
|
||||||
if (await Atlas_list(e)) return true;
|
if (await Atlas_list(e)) return true;
|
||||||
if (await roleInfo(e)) return true;
|
if (await roleInfo(e)) return true;
|
||||||
if (await weaponInfo(e)) return true;
|
// if (await weaponInfo(e)) return true;
|
||||||
// if (await foodInfo(e)) return true;
|
// if (await foodInfo(e)) return true;
|
||||||
// if (await RelicsInfo(e)) return true;
|
// if (await RelicsInfo(e)) return true;
|
||||||
// if (await monsterInfo(e)) return true;
|
// if (await monsterInfo(e)) return true;
|
||||||
@ -37,7 +38,7 @@ export async function AtlasAlias(e) {
|
|||||||
export async function roleInfo(e) {
|
export async function roleInfo(e) {
|
||||||
// let msg=e.msg.replace(/#|图鉴/g,"");
|
// let msg=e.msg.replace(/#|图鉴/g,"");
|
||||||
let msg = e.msg.replace(/#|#|信息|图鉴|命座|天赋|突破/g, "");
|
let msg = e.msg.replace(/#|#|信息|图鉴|命座|天赋|突破/g, "");
|
||||||
let id = YunzaiApps.mysInfo.roleIdToName(msg);
|
let id = gsCfg.roleNameToID(msg)
|
||||||
let name;
|
let name;
|
||||||
if (["10000005", "10000007", "20000000"].includes(id)) {
|
if (["10000005", "10000007", "20000000"].includes(id)) {
|
||||||
if (!["风主", "岩主", "雷主"].includes(msg)) {
|
if (!["风主", "岩主", "雷主"].includes(msg)) {
|
||||||
@ -46,7 +47,7 @@ export async function roleInfo(e) {
|
|||||||
}
|
}
|
||||||
name = msg;
|
name = msg;
|
||||||
} else {
|
} else {
|
||||||
name = YunzaiApps.mysInfo.roleIdToName(id, true);
|
name = gsCfg.roleIdToName(id, true);
|
||||||
if (!name) return false;
|
if (!name) return false;
|
||||||
}
|
}
|
||||||
send_Msg(e, "juese_tujian", name)
|
send_Msg(e, "juese_tujian", name)
|
||||||
@ -77,43 +78,43 @@ const send_Msg = function(e, type, name) {
|
|||||||
e.reply(segment.image(`file:///${path}`));
|
e.reply(segment.image(`file:///${path}`));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
let weapon = new Map();
|
// let weapon = new Map();
|
||||||
let weaponFile = [];
|
// let weaponFile = [];
|
||||||
await init();
|
// await init();
|
||||||
export async function init(isUpdate = false) {
|
// export async function init(isUpdate = false) {
|
||||||
let weaponJson = JSON.parse(fs.readFileSync("./config/genshin/weapon.json", "utf8"));
|
// let weaponJson = JSON.parse(fs.readFileSync("./config/genshin/weapon.json", "utf8"));
|
||||||
for (let i in weaponJson) {
|
// for (let i in weaponJson) {
|
||||||
for (let val of weaponJson[i]) {
|
// for (let val of weaponJson[i]) {
|
||||||
weapon.set(val, i);
|
// weapon.set(val, i);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
let paths = "./plugins/xiaoyao-cvs-plugin/resources/xiaoyao-plus/wuqi_tujian";
|
// let paths = "./plugins/xiaoyao-cvs-plugin/resources/xiaoyao-plus/wuqi_tujian";
|
||||||
if (!fs.existsSync(paths)) {
|
// if (!fs.existsSync(paths)) {
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
weaponFile = fs.readdirSync(paths);
|
// weaponFile = fs.readdirSync(paths);
|
||||||
for (let val of weaponFile) {
|
// for (let val of weaponFile) {
|
||||||
let name = val.replace(".png", "");
|
// let name = val.replace(".png", "");
|
||||||
weapon.set(name, name);
|
// weapon.set(name, name);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
export async function weaponInfo(e) {
|
// export async function weaponInfo(e) {
|
||||||
let msg = e.msg || '';
|
// let msg = e.msg || '';
|
||||||
if (e.atBot) {
|
// if (e.atBot) {
|
||||||
msg = "#" + msg.replace("#", "");
|
// msg = "#" + msg.replace("#", "");
|
||||||
}
|
// }
|
||||||
if (!/(#*(.*)(信息|图鉴|突破|武器|材料)|#(.*))$/.test(msg)) return;
|
// if (!/(#*(.*)(信息|图鉴|突破|武器|材料)|#(.*))$/.test(msg)) return;
|
||||||
|
|
||||||
let name = weapon.get(msg.replace(/#|#|信息|图鉴|突破|武器|材料/g, ""));
|
// let name = weapon.get(msg.replace(/#|#|信息|图鉴|突破|武器|材料/g, ""));
|
||||||
|
|
||||||
if (name) {
|
// if (name) {
|
||||||
send_Msg(e, "wuqi_tujian", name)
|
// send_Msg(e, "wuqi_tujian", name)
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
export async function Atlas_list(e) {
|
export async function Atlas_list(e) {
|
||||||
let list = Data.readJSON(`${_path}/plugins/xiaoyao-cvs-plugin/resources/Atlas_alias/`, "Atlas_list");
|
let list = Data.readJSON(`${_path}/plugins/xiaoyao-cvs-plugin/resources/Atlas_alias/`, "Atlas_list");
|
||||||
let name = e.msg.replace(/#|井/g, "")
|
let name = e.msg.replace(/#|井/g, "")
|
||||||
|
@ -1,46 +1,48 @@
|
|||||||
import fs from "fs";
|
import fs from 'fs'
|
||||||
import lodash from "lodash";
|
import lodash from 'lodash'
|
||||||
|
|
||||||
const _path = process.cwd();
|
const _path = process.cwd()
|
||||||
const _logPath = `${_path}/plugins/xiaoyao-cvs-plugin/CHANGELOG.md`;
|
const _logPath = `${_path}/plugins/xiaoyao-cvs-plugin/CHANGELOG.md`
|
||||||
|
|
||||||
let logs = {};
|
let logs = {}
|
||||||
let changelogs = [];
|
let changelogs = []
|
||||||
let currentVersion;
|
let currentVersion
|
||||||
let versionCount = 4;
|
let versionCount = 4
|
||||||
|
|
||||||
let packageJson = JSON.parse(fs.readFileSync("package.json", "utf8"));
|
let packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'))
|
||||||
|
|
||||||
const getLine = function (line) {
|
const getLine = function (line) {
|
||||||
line = line.replace(/(^\s*\*|\r)/g, '');
|
line = line.replace(/(^\s*\*|\r)/g, '')
|
||||||
line = line.replace(/\s*`([^`]+`)/g, '<span class="cmd">$1');
|
line = line.replace(/\s*`([^`]+`)/g, '<span class="cmd">$1')
|
||||||
line = line.replace(/`\s*/g, '</span>');
|
line = line.replace(/`\s*/g, '</span>')
|
||||||
line = line.replace(/\s*\*\*([^\*]+\*\*)/g, '<span class="strong">$1')
|
line = line.replace(/\s*\*\*([^\*]+\*\*)/g, '<span class="strong">$1')
|
||||||
line = line.replace(/\*\*\s*/g, '</span>');
|
line = line.replace(/\*\*\s*/g, '</span>')
|
||||||
line = line.replace(/ⁿᵉʷ/g, '<span class="new"></span>');
|
line = line.replace(/ⁿᵉʷ/g, '<span class="new"></span>')
|
||||||
return line;
|
return line
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (fs.existsSync(_logPath)) {
|
if (fs.existsSync(_logPath)) {
|
||||||
logs = fs.readFileSync(_logPath, "utf8") || "";
|
logs = fs.readFileSync(_logPath, 'utf8') || ''
|
||||||
logs = logs.split("\n");
|
logs = logs.split('\n')
|
||||||
let temp = {}, lastLine = {};
|
|
||||||
|
let temp = {};
|
||||||
|
let lastLine = {}
|
||||||
lodash.forEach(logs, (line) => {
|
lodash.forEach(logs, (line) => {
|
||||||
if (versionCount <= -1) {
|
if (versionCount <= -1) {
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
let versionRet = /^#\s*([0-9\\.~\s]+?)\s*$/.exec(line);
|
let versionRet = /^#\s*([0-9\\.~\s]+?)\s*$/.exec(line)
|
||||||
if (versionRet && versionRet[1]) {
|
if (versionRet && versionRet[1]) {
|
||||||
let v = versionRet[1].trim();
|
let v = versionRet[1].trim()
|
||||||
if (!currentVersion) {
|
if (!currentVersion) {
|
||||||
currentVersion = v;
|
currentVersion = v
|
||||||
} else {
|
} else {
|
||||||
changelogs.push(temp);
|
changelogs.push(temp)
|
||||||
if (/0\s*$/.test(v) && versionCount > 0) {
|
if (/0\s*$/.test(v) && versionCount > 0) {
|
||||||
versionCount = 0;
|
versionCount = 0
|
||||||
} else {
|
} else {
|
||||||
versionCount--;
|
versionCount--
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,26 +52,25 @@ try {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!line.trim()) {
|
if (!line.trim()) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
if (/^\*/.test(line)) {
|
if (/^\*/.test(line)) {
|
||||||
lastLine = {
|
lastLine = {
|
||||||
title: getLine(line),
|
title: getLine(line),
|
||||||
logs: []
|
logs: []
|
||||||
}
|
}
|
||||||
temp.logs.push(lastLine);
|
temp.logs.push(lastLine)
|
||||||
} else if (/^\s{3,}\*/.test(line)) {
|
} else if (/^\s{2,}\*/.test(line)) {
|
||||||
lastLine.logs.push(getLine(line));
|
lastLine.logs.push(getLine(line))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// do nth
|
// do nth
|
||||||
}
|
}
|
||||||
|
|
||||||
const yunzaiVersion = packageJson.version;
|
const yunzaiVersion = packageJson.version
|
||||||
|
const isV3 = yunzaiVersion[0] === '3'
|
||||||
|
|
||||||
export { currentVersion, yunzaiVersion, changelogs };
|
export { currentVersion, yunzaiVersion, isV3, changelogs }
|
||||||
|
@ -29,7 +29,7 @@ export const render_path = async function (path, params, cfg,path_) {
|
|||||||
let paths = path.split("/");
|
let paths = path.split("/");
|
||||||
let { render, e } = cfg;
|
let { render, e } = cfg;
|
||||||
let _layout_path = process.cwd() + path_;
|
let _layout_path = process.cwd() + path_;
|
||||||
let base64 = await render(paths[0], paths[1], {
|
let base64 = await render1(paths[0], paths[1], {
|
||||||
...params,
|
...params,
|
||||||
_layout_path,
|
_layout_path,
|
||||||
defaultLayout: _layout_path + "default.html",
|
defaultLayout: _layout_path + "default.html",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import lodash from "lodash";
|
import lodash from "lodash";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import request from "request";
|
const _path = process.cwd()
|
||||||
|
|
||||||
let Data = {
|
let Data = {
|
||||||
|
|
||||||
@ -51,7 +51,18 @@ let Data = {
|
|||||||
Data.createDir(path, true);
|
Data.createDir(path, true);
|
||||||
return fs.writeFileSync(`${path}/${file}`, JSON.stringify(data, null, space));
|
return fs.writeFileSync(`${path}/${file}`, JSON.stringify(data, null, space));
|
||||||
},
|
},
|
||||||
|
async importModule (path, file, rootPath = _path) {
|
||||||
|
if (!/\.js$/.test(file)) {
|
||||||
|
file = file + '.js'
|
||||||
|
}
|
||||||
|
// 检查并创建目录
|
||||||
|
Data.createDir(_path, path, true)
|
||||||
|
if (fs.existsSync(`${_path}/${path}/${file}`)) {
|
||||||
|
let data = await import(`file://${_path}/${path}/${file}`)
|
||||||
|
return data || {}
|
||||||
|
}
|
||||||
|
return {}
|
||||||
|
},
|
||||||
/*
|
/*
|
||||||
* 返回一个从 target 中选中的属性的对象
|
* 返回一个从 target 中选中的属性的对象
|
||||||
*
|
*
|
||||||
@ -146,29 +157,6 @@ let Data = {
|
|||||||
return Promise.all(ret);
|
return Promise.all(ret);
|
||||||
},
|
},
|
||||||
|
|
||||||
async cacheFile(fileList, cacheRoot) {
|
|
||||||
|
|
||||||
let ret = {};
|
|
||||||
let cacheFn = async function (url) {
|
|
||||||
let path = Data.getUrlPath(url);
|
|
||||||
if (fs.existsSync(`${cacheRoot}/${path.path}/${path.filename}`)) {
|
|
||||||
console.log("已存在,跳过 " + path.path + "/" + path.filename);
|
|
||||||
ret[url] = `${path.path}/${path.filename}`;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Data.pathExists(cacheRoot, path.path);
|
|
||||||
await request(url).pipe(fs.createWriteStream(`${cacheRoot}/${path.path}/` + path.filename));
|
|
||||||
console.log("下载成功: " + path.path + "/" + path.filname);
|
|
||||||
ret[url] = `${path.path}/${path.filename}`;
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
await Data.asyncPool(10, fileList, cacheFn);
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
sleep(ms) {
|
sleep(ms) {
|
||||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
}
|
}
|
||||||
|
2
config/.gitignore
vendored
Normal file
2
config/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
*
|
||||||
|
!.gitignore
|
3
defSet/mys/pubCk.yaml
Normal file
3
defSet/mys/pubCk.yaml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# 米游社公共查询ck,支持多个一行一个,横杆空格开头
|
||||||
|
- ltoken=xxx; ltuid=xxx; cookie_token=xxx; account_id=xxx;
|
||||||
|
- ltoken=xxx; ltuid=xxx; cookie_token=xxx; account_id=xxx;
|
6
defSet/mys/set.yaml
Normal file
6
defSet/mys/set.yaml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# 公共查询是否使用用户ck 0-不使用 1-使用
|
||||||
|
allowUseCookie: 0
|
||||||
|
# 默认cookie帮助文档链接地址
|
||||||
|
cookieDoc: docs.qq.com/doc/DUWNVQVFTU3liTVlO
|
||||||
|
# 米游社原神签到定时任务,Cron表达式,默认00:02开始执行,每10s签到一个
|
||||||
|
signTime: 0 2 0 * * ?
|
601
defSet/role/name.yaml
Normal file
601
defSet/role/name.yaml
Normal file
@ -0,0 +1,601 @@
|
|||||||
|
20000000:
|
||||||
|
- 主角
|
||||||
|
- 旅行者
|
||||||
|
- 卑鄙的外乡人
|
||||||
|
- 荣誉骑士
|
||||||
|
- 爷
|
||||||
|
- 风主
|
||||||
|
- 岩主
|
||||||
|
- 雷主
|
||||||
|
- 草主
|
||||||
|
- 履刑者
|
||||||
|
- 抽卡不歪真君
|
||||||
|
10000002:
|
||||||
|
- 神里绫华
|
||||||
|
- Kamisato Ayaka
|
||||||
|
- Ayaka
|
||||||
|
- ayaka
|
||||||
|
- 神里
|
||||||
|
- 绫华
|
||||||
|
- 神里凌华
|
||||||
|
- 凌华
|
||||||
|
- 白鹭公主
|
||||||
|
- 神里大小姐
|
||||||
|
10000003:
|
||||||
|
- 琴
|
||||||
|
- Jean
|
||||||
|
- jean
|
||||||
|
- 团长
|
||||||
|
- 代理团长
|
||||||
|
- 琴团长
|
||||||
|
- 蒲公英骑士
|
||||||
|
10000005:
|
||||||
|
- 空
|
||||||
|
- 男主
|
||||||
|
- 男主角
|
||||||
|
- 龙哥
|
||||||
|
- 空哥
|
||||||
|
10000006:
|
||||||
|
- 丽莎
|
||||||
|
- Lisa
|
||||||
|
- lisa
|
||||||
|
- 图书管理员
|
||||||
|
- 图书馆管理员
|
||||||
|
- 蔷薇魔女
|
||||||
|
10000007:
|
||||||
|
- 荧
|
||||||
|
- 女主
|
||||||
|
- 女主角
|
||||||
|
- 莹
|
||||||
|
- 萤
|
||||||
|
- 黄毛阿姨
|
||||||
|
- 荧妹
|
||||||
|
10000014:
|
||||||
|
- 芭芭拉
|
||||||
|
- Barbara
|
||||||
|
- barbara
|
||||||
|
- 巴巴拉
|
||||||
|
- 拉粑粑
|
||||||
|
- 拉巴巴
|
||||||
|
- 内鬼
|
||||||
|
- 加湿器
|
||||||
|
- 闪耀偶像
|
||||||
|
- 偶像
|
||||||
|
10000015:
|
||||||
|
- 凯亚
|
||||||
|
- Kaeya
|
||||||
|
- kaeya
|
||||||
|
- 盖亚
|
||||||
|
- 凯子哥
|
||||||
|
- 凯鸭
|
||||||
|
- 矿工
|
||||||
|
- 矿工头子
|
||||||
|
- 骑兵队长
|
||||||
|
- 凯子
|
||||||
|
- 凝冰渡海真君
|
||||||
|
10000016:
|
||||||
|
- 迪卢克
|
||||||
|
- diluc
|
||||||
|
- Diluc
|
||||||
|
- 卢姥爷
|
||||||
|
- 姥爷
|
||||||
|
- 卢老爷
|
||||||
|
- 卢锅巴
|
||||||
|
- 正义人
|
||||||
|
- 正e人
|
||||||
|
- 正E人
|
||||||
|
- 卢本伟
|
||||||
|
- 暗夜英雄
|
||||||
|
- 卢卢伯爵
|
||||||
|
- 落魄了
|
||||||
|
- 落魄了家人们
|
||||||
|
10000020:
|
||||||
|
- 雷泽
|
||||||
|
- razor
|
||||||
|
- Razor
|
||||||
|
- 狼少年
|
||||||
|
- 狼崽子
|
||||||
|
- 狼崽
|
||||||
|
- 卢皮卡
|
||||||
|
- 小狼
|
||||||
|
- 小狼狗
|
||||||
|
10000021:
|
||||||
|
- 安柏
|
||||||
|
- Amber
|
||||||
|
- amber
|
||||||
|
- 安伯
|
||||||
|
- 兔兔伯爵
|
||||||
|
- 飞行冠军
|
||||||
|
- 侦查骑士
|
||||||
|
- 点火姬
|
||||||
|
- 点火机
|
||||||
|
- 打火机
|
||||||
|
- 打火姬
|
||||||
|
10000022:
|
||||||
|
- 温迪
|
||||||
|
- Venti
|
||||||
|
- venti
|
||||||
|
- 温蒂
|
||||||
|
- 风神
|
||||||
|
- 卖唱的
|
||||||
|
- 巴巴托斯
|
||||||
|
- 巴巴脱丝
|
||||||
|
- 芭芭托斯
|
||||||
|
- 芭芭脱丝
|
||||||
|
- 干点正事
|
||||||
|
- 不干正事
|
||||||
|
- 吟游诗人
|
||||||
|
- 诶嘿
|
||||||
|
- 唉嘿
|
||||||
|
- 摸鱼
|
||||||
|
10000023:
|
||||||
|
- 香菱
|
||||||
|
- Xiangling
|
||||||
|
- xiangling
|
||||||
|
- 香玲
|
||||||
|
- 锅巴
|
||||||
|
- 厨师
|
||||||
|
- 万民堂厨师
|
||||||
|
- 香师傅
|
||||||
|
10000024:
|
||||||
|
- 北斗
|
||||||
|
- Beidou
|
||||||
|
- beidou
|
||||||
|
- 大姐头
|
||||||
|
- 大姐
|
||||||
|
- 无冕的龙王
|
||||||
|
- 龙王
|
||||||
|
10000025:
|
||||||
|
- 行秋
|
||||||
|
- Xingqiu
|
||||||
|
- xingqiu
|
||||||
|
- 秋秋人
|
||||||
|
- 秋妹妹
|
||||||
|
- 书呆子
|
||||||
|
- 水神
|
||||||
|
- 飞云商会二少爷
|
||||||
|
10000026:
|
||||||
|
- 魈
|
||||||
|
- Xiao
|
||||||
|
- xiao
|
||||||
|
- 杏仁豆腐
|
||||||
|
- 打桩机
|
||||||
|
- 插秧
|
||||||
|
- 三眼五显仙人
|
||||||
|
- 三眼五显真人
|
||||||
|
- 降魔大圣
|
||||||
|
- 护法夜叉
|
||||||
|
- 快乐风男
|
||||||
|
- 无聊
|
||||||
|
- 靖妖傩舞
|
||||||
|
- 矮子仙人
|
||||||
|
- 三点五尺仙人
|
||||||
|
- 跳跳虎
|
||||||
|
10000027:
|
||||||
|
- 凝光
|
||||||
|
- Ningguang
|
||||||
|
- ningguang
|
||||||
|
- 富婆
|
||||||
|
- 天权星
|
||||||
|
10000029:
|
||||||
|
- 可莉
|
||||||
|
- Klee
|
||||||
|
- klee
|
||||||
|
- 嘟嘟可
|
||||||
|
- 火花骑士
|
||||||
|
- 蹦蹦炸弹
|
||||||
|
- 炸鱼
|
||||||
|
- 放火烧山
|
||||||
|
- 放火烧山真君
|
||||||
|
- 蒙德最强战力
|
||||||
|
- 逃跑的太阳
|
||||||
|
- 啦啦啦
|
||||||
|
- 哒哒哒
|
||||||
|
- 炸弹人
|
||||||
|
- 禁闭室
|
||||||
|
10000030:
|
||||||
|
- 钟离
|
||||||
|
- Zhongli
|
||||||
|
- zhongli
|
||||||
|
- 摩拉克斯
|
||||||
|
- 岩王爷
|
||||||
|
- 岩神
|
||||||
|
- 钟师傅
|
||||||
|
- 天动万象
|
||||||
|
- 岩王帝君
|
||||||
|
- 未来可期
|
||||||
|
- 帝君
|
||||||
|
- 拒收病婿
|
||||||
|
10000031:
|
||||||
|
- 菲谢尔
|
||||||
|
- Fischl
|
||||||
|
- fischl
|
||||||
|
- 皇女
|
||||||
|
- 小艾米
|
||||||
|
- 小艾咪
|
||||||
|
- 奥兹
|
||||||
|
- 断罪皇女
|
||||||
|
- 中二病
|
||||||
|
- 中二少女
|
||||||
|
- 中二皇女
|
||||||
|
- 奥兹发射器
|
||||||
|
10000032:
|
||||||
|
- 班尼特
|
||||||
|
- Bennett
|
||||||
|
- bennett
|
||||||
|
- 点赞哥
|
||||||
|
- 点赞
|
||||||
|
- 倒霉少年
|
||||||
|
- 倒霉蛋
|
||||||
|
- 霹雳闪雷真君
|
||||||
|
- 班神
|
||||||
|
- 班爷
|
||||||
|
- 倒霉
|
||||||
|
- 火神
|
||||||
|
- 六星真神
|
||||||
|
10000033:
|
||||||
|
- 达达利亚
|
||||||
|
- Tartaglia
|
||||||
|
- tartaglia
|
||||||
|
- Childe
|
||||||
|
- childe
|
||||||
|
- Ajax
|
||||||
|
- ajax
|
||||||
|
- 达达鸭
|
||||||
|
- 达达利鸭
|
||||||
|
- 公子
|
||||||
|
- 玩具销售员
|
||||||
|
- 玩具推销员
|
||||||
|
- 钱包
|
||||||
|
- 鸭鸭
|
||||||
|
- 愚人众末席
|
||||||
|
10000034:
|
||||||
|
- 诺艾尔
|
||||||
|
- Noelle
|
||||||
|
- noelle
|
||||||
|
- 女仆
|
||||||
|
- 高达
|
||||||
|
- 岩王帝姬
|
||||||
|
10000035:
|
||||||
|
- 七七
|
||||||
|
- Qiqi
|
||||||
|
- qiqi
|
||||||
|
- 僵尸
|
||||||
|
- 肚饿真君
|
||||||
|
- 度厄真君
|
||||||
|
- 77
|
||||||
|
10000036:
|
||||||
|
- 重云
|
||||||
|
- Chongyun
|
||||||
|
- chongyun
|
||||||
|
- 纯阳之体
|
||||||
|
- 冰棍
|
||||||
|
10000037:
|
||||||
|
- 甘雨
|
||||||
|
- Ganyu
|
||||||
|
- ganyu
|
||||||
|
- 椰羊
|
||||||
|
- 椰奶
|
||||||
|
- 王小美
|
||||||
|
10000038:
|
||||||
|
- 阿贝多
|
||||||
|
- Albedo
|
||||||
|
- albedo
|
||||||
|
- 可莉哥哥
|
||||||
|
- 升降机
|
||||||
|
- 升降台
|
||||||
|
- 电梯
|
||||||
|
- 白垩之子
|
||||||
|
- 贝爷
|
||||||
|
- 白垩
|
||||||
|
- 阿贝少
|
||||||
|
- 花呗多
|
||||||
|
- 阿贝夕
|
||||||
|
- abd
|
||||||
|
- 阿师傅
|
||||||
|
10000039:
|
||||||
|
- 迪奥娜
|
||||||
|
- Diona
|
||||||
|
- diona
|
||||||
|
- 迪欧娜
|
||||||
|
- dio
|
||||||
|
- dio娜
|
||||||
|
- 冰猫
|
||||||
|
- 猫猫
|
||||||
|
- 猫娘
|
||||||
|
- 喵喵
|
||||||
|
- 调酒师
|
||||||
|
10000041:
|
||||||
|
- 莫娜
|
||||||
|
- Mona
|
||||||
|
- mona
|
||||||
|
- 穷鬼
|
||||||
|
- 穷光蛋
|
||||||
|
- 穷
|
||||||
|
- 莫纳
|
||||||
|
- 占星术士
|
||||||
|
- 占星师
|
||||||
|
- 讨龙真君
|
||||||
|
- 半部讨龙真君
|
||||||
|
- 阿斯托洛吉斯·莫娜·梅姬斯图斯
|
||||||
|
10000042:
|
||||||
|
- 刻晴
|
||||||
|
- Keqing
|
||||||
|
- keqing
|
||||||
|
- 刻情
|
||||||
|
- 氪晴
|
||||||
|
- 刻师傅
|
||||||
|
- 刻师父
|
||||||
|
- 牛杂
|
||||||
|
- 牛杂师傅
|
||||||
|
- 斩尽牛杂
|
||||||
|
- 免疫
|
||||||
|
- 免疫免疫
|
||||||
|
- 屁斜剑法
|
||||||
|
- 玉衡星
|
||||||
|
- 阿晴
|
||||||
|
- 啊晴
|
||||||
|
10000043:
|
||||||
|
- 砂糖
|
||||||
|
- Sucrose
|
||||||
|
- sucrose
|
||||||
|
- 雷莹术士
|
||||||
|
- 雷萤术士
|
||||||
|
- 雷荧术士
|
||||||
|
10000044:
|
||||||
|
- 辛焱
|
||||||
|
- Xinyan
|
||||||
|
- xinyan
|
||||||
|
- 辛炎
|
||||||
|
- 黑妹
|
||||||
|
- 摇滚
|
||||||
|
10000045:
|
||||||
|
- 罗莎莉亚
|
||||||
|
- Rosaria
|
||||||
|
- rosaria
|
||||||
|
- 罗莎莉娅
|
||||||
|
- 白色史莱姆
|
||||||
|
- 白史莱姆
|
||||||
|
- 修女
|
||||||
|
- 罗莎利亚
|
||||||
|
- 罗莎利娅
|
||||||
|
- 罗沙莉亚
|
||||||
|
- 罗沙莉娅
|
||||||
|
- 罗沙利亚
|
||||||
|
- 罗沙利娅
|
||||||
|
- 萝莎莉亚
|
||||||
|
- 萝莎莉娅
|
||||||
|
- 萝莎利亚
|
||||||
|
- 萝莎利娅
|
||||||
|
- 萝沙莉亚
|
||||||
|
- 萝沙莉娅
|
||||||
|
- 萝沙利亚
|
||||||
|
- 萝沙利娅
|
||||||
|
10000046:
|
||||||
|
- 胡桃
|
||||||
|
- Hu Tao
|
||||||
|
- hu tao
|
||||||
|
- HuTao
|
||||||
|
- hutao
|
||||||
|
- Hutao
|
||||||
|
- 胡淘
|
||||||
|
- 往生堂堂主
|
||||||
|
- 火化
|
||||||
|
- 抬棺的
|
||||||
|
- 蝴蝶
|
||||||
|
- 核桃
|
||||||
|
- 堂主
|
||||||
|
- 胡堂主
|
||||||
|
- 雪霁梅香
|
||||||
|
10000047:
|
||||||
|
- 枫原万叶
|
||||||
|
- Kaedehara Kazuha
|
||||||
|
- Kazuha
|
||||||
|
- kazuha
|
||||||
|
- 万叶
|
||||||
|
- 叶天帝
|
||||||
|
- 天帝
|
||||||
|
- 叶师傅
|
||||||
|
10000048:
|
||||||
|
- 烟绯
|
||||||
|
- Yanfei
|
||||||
|
- yanfei
|
||||||
|
- 烟老师
|
||||||
|
- 律师
|
||||||
|
- 罗翔
|
||||||
|
10000049:
|
||||||
|
- 宵宫
|
||||||
|
- Yoimiya
|
||||||
|
- yoimiya
|
||||||
|
- 霄宫
|
||||||
|
- 烟花
|
||||||
|
- 肖宫
|
||||||
|
- 肖工
|
||||||
|
- 绷带女孩
|
||||||
|
10000050:
|
||||||
|
- 托马
|
||||||
|
- Thoma
|
||||||
|
- thoma
|
||||||
|
- 家政官
|
||||||
|
- 太郎丸
|
||||||
|
- 地头蛇
|
||||||
|
- 男仆
|
||||||
|
- 拖马
|
||||||
|
10000051:
|
||||||
|
- 优菈
|
||||||
|
- Eula
|
||||||
|
- eula
|
||||||
|
- 优拉
|
||||||
|
- 尤拉
|
||||||
|
- 尤菈
|
||||||
|
- 浪花骑士
|
||||||
|
- 记仇
|
||||||
|
- 劳伦斯
|
||||||
|
10000052:
|
||||||
|
- 雷电将军
|
||||||
|
- Raiden Shogun
|
||||||
|
- Raiden
|
||||||
|
- raiden
|
||||||
|
- 雷神
|
||||||
|
- 将军
|
||||||
|
- 雷军
|
||||||
|
- 巴尔
|
||||||
|
- 阿影
|
||||||
|
- 影
|
||||||
|
- 巴尔泽布
|
||||||
|
- 煮饭婆
|
||||||
|
- 奶香一刀
|
||||||
|
- 无想一刀
|
||||||
|
- 宅女
|
||||||
|
10000053:
|
||||||
|
- 早柚
|
||||||
|
- Sayu
|
||||||
|
- sayu
|
||||||
|
- 小狸猫
|
||||||
|
- 狸猫
|
||||||
|
- 忍者
|
||||||
|
10000054:
|
||||||
|
- 珊瑚宫心海
|
||||||
|
- Sangonomiya Kokomi
|
||||||
|
- Kokomi
|
||||||
|
- kokomi
|
||||||
|
- 心海
|
||||||
|
- 军师
|
||||||
|
- 珊瑚宫
|
||||||
|
- 书记
|
||||||
|
- 观赏鱼
|
||||||
|
- 水母
|
||||||
|
- 鱼
|
||||||
|
- 美人鱼
|
||||||
|
10000055:
|
||||||
|
- 五郎
|
||||||
|
- Gorou
|
||||||
|
- gorou
|
||||||
|
- 柴犬
|
||||||
|
- 土狗
|
||||||
|
- 希娜
|
||||||
|
- 希娜小姐
|
||||||
|
10000056:
|
||||||
|
- 九条裟罗
|
||||||
|
- Kujou Sara
|
||||||
|
- Sara
|
||||||
|
- sara
|
||||||
|
- 九条
|
||||||
|
- 九条沙罗
|
||||||
|
- 裟罗
|
||||||
|
- 沙罗
|
||||||
|
- 天狗
|
||||||
|
10000057:
|
||||||
|
- 荒泷一斗
|
||||||
|
- Arataki Itto
|
||||||
|
- Itto
|
||||||
|
- itto
|
||||||
|
- 荒龙一斗
|
||||||
|
- 荒泷天下第一斗
|
||||||
|
- 一斗
|
||||||
|
- 一抖
|
||||||
|
- 荒泷
|
||||||
|
- 1斗
|
||||||
|
- 牛牛
|
||||||
|
- 斗子哥
|
||||||
|
- 牛子哥
|
||||||
|
- 牛子
|
||||||
|
- 孩子王
|
||||||
|
- 斗虫
|
||||||
|
- 巧乐兹
|
||||||
|
- 放牛的
|
||||||
|
10000058:
|
||||||
|
- 八重神子
|
||||||
|
- Yae Miko
|
||||||
|
- Miko
|
||||||
|
- miko
|
||||||
|
- 八重
|
||||||
|
- 神子
|
||||||
|
- 狐狸
|
||||||
|
- 想得美哦
|
||||||
|
- 巫女
|
||||||
|
- 屑狐狸
|
||||||
|
- 骚狐狸
|
||||||
|
- 八重宫司
|
||||||
|
- 婶子
|
||||||
|
- 小八
|
||||||
|
10000059:
|
||||||
|
- 鹿野院平藏
|
||||||
|
- shikanoin heizou
|
||||||
|
- Heizou
|
||||||
|
- heizou
|
||||||
|
- heizo
|
||||||
|
- 鹿野苑
|
||||||
|
- 鹿野院
|
||||||
|
- 平藏
|
||||||
|
- 鹿野苑平藏
|
||||||
|
- 鹿野
|
||||||
|
- 小鹿
|
||||||
|
10000060:
|
||||||
|
- 夜兰
|
||||||
|
- Yelan
|
||||||
|
- yelan
|
||||||
|
- 夜阑
|
||||||
|
- 叶澜
|
||||||
|
- 腋兰
|
||||||
|
- 夜天后
|
||||||
|
10000062:
|
||||||
|
- 埃洛伊
|
||||||
|
- Aloy
|
||||||
|
- aloy
|
||||||
|
10000063:
|
||||||
|
- 申鹤
|
||||||
|
- Shenhe
|
||||||
|
- shenhe
|
||||||
|
- 神鹤
|
||||||
|
- 小姨
|
||||||
|
- 小姨子
|
||||||
|
- 审鹤
|
||||||
|
10000064:
|
||||||
|
- 云堇
|
||||||
|
- Yun Jin
|
||||||
|
- yunjin
|
||||||
|
- yun jin
|
||||||
|
- 云瑾
|
||||||
|
- 云先生
|
||||||
|
- 云锦
|
||||||
|
- 神女劈观
|
||||||
|
10000065:
|
||||||
|
- 久岐忍
|
||||||
|
- Kuki Shinobu
|
||||||
|
- Kuki
|
||||||
|
- kuki
|
||||||
|
- Shinobu
|
||||||
|
- shinobu
|
||||||
|
- 97忍
|
||||||
|
- 小忍
|
||||||
|
- 久歧忍
|
||||||
|
- 97
|
||||||
|
- 茄忍
|
||||||
|
- 阿忍
|
||||||
|
- 忍姐
|
||||||
|
10000066:
|
||||||
|
- 神里绫人
|
||||||
|
- Kamisato Ayato
|
||||||
|
- Ayato
|
||||||
|
- ayato
|
||||||
|
- 绫人
|
||||||
|
- 神里凌人
|
||||||
|
- 凌人
|
||||||
|
- 0人
|
||||||
|
- 神人
|
||||||
|
- 零人
|
||||||
|
- 大舅哥
|
||||||
|
10000067:
|
||||||
|
- 柯莱
|
||||||
|
- Collei
|
||||||
|
- collei
|
||||||
|
10000068:
|
||||||
|
- 多莉
|
||||||
|
- Dori
|
||||||
|
- dori
|
||||||
|
- 多利
|
||||||
|
10000069:
|
||||||
|
- 提纳里
|
||||||
|
- Tighnari
|
||||||
|
- tighnari
|
19
defSet/role/other.yaml
Normal file
19
defSet/role/other.yaml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# 角色名称缩短
|
||||||
|
sortName:
|
||||||
|
达达利亚: 公子
|
||||||
|
神里绫华: 绫华
|
||||||
|
神里绫人: 绫人
|
||||||
|
枫原万叶: 万叶
|
||||||
|
雷电将军: 雷神
|
||||||
|
珊瑚宫心海: 心海
|
||||||
|
荒泷一斗: 一斗
|
||||||
|
八重神子: 八重
|
||||||
|
九条裟罗: 九条
|
||||||
|
罗莎莉亚: 罗莎
|
||||||
|
鹿野院平藏: 平藏
|
||||||
|
|
||||||
|
costumes:
|
||||||
|
- 海风之梦
|
||||||
|
- 闪耀协奏
|
||||||
|
- 纱中幽兰
|
||||||
|
- 霓裾翩跹
|
102
index.js
102
index.js
@ -1,84 +1,26 @@
|
|||||||
import lodash from "lodash";
|
// 适配V3 Yunzai,将index.js移至app/index.js
|
||||||
import {
|
import { currentVersion, isV3 } from './components/Changelog.js'
|
||||||
AtlasAlias
|
import Data from './components/Data.js'
|
||||||
} from "./apps/xiaoyao_image.js";
|
|
||||||
import {
|
|
||||||
versionInfo,
|
|
||||||
help
|
|
||||||
} from "./apps/help.js";
|
|
||||||
|
|
||||||
import common from "../../lib/common.js";
|
export * from './apps/index.js'
|
||||||
import {
|
let index = { atlas: {} }
|
||||||
Note,DailyNoteTask,
|
if (isV3) {
|
||||||
Note_appoint,pokeNote
|
index = await Data.importModule('/plugins/xiaoyao-cvs-plugin/adapter', 'index.js')
|
||||||
} from "./apps/Note.js";
|
console.log(index)
|
||||||
import {
|
}
|
||||||
rule as adminRule,
|
export const atlas = index.atlas || {}
|
||||||
updateRes,
|
|
||||||
sysCfg,
|
|
||||||
updateMiaoPlugin
|
|
||||||
} from "./apps/admin.js";
|
|
||||||
import {
|
|
||||||
currentVersion
|
|
||||||
} from "./components/Changelog.js";
|
|
||||||
export {
|
|
||||||
updateRes,
|
|
||||||
updateMiaoPlugin,
|
|
||||||
versionInfo,
|
|
||||||
Note_appoint,pokeNote,
|
|
||||||
sysCfg,
|
|
||||||
help,DailyNoteTask,
|
|
||||||
AtlasAlias,
|
|
||||||
Note
|
|
||||||
};
|
|
||||||
|
|
||||||
let rule = {
|
console.log(`图鉴插件${currentVersion}初始化~`)
|
||||||
versionInfo: {
|
|
||||||
reg: "^#图鉴版本$",
|
|
||||||
describe: "【#帮助】 图鉴版本介绍",
|
|
||||||
},
|
|
||||||
help: {
|
|
||||||
reg: "^#?(图鉴)?(命令|帮助|菜单|help|说明|功能|指令|使用说明)$",
|
|
||||||
describe: "查看插件的功能",
|
|
||||||
},
|
|
||||||
AtlasAlias: {
|
|
||||||
reg: "^(#(.*)|.*图鉴)$",
|
|
||||||
describe: "角色、食物、怪物、武器信息图鉴",
|
|
||||||
},
|
|
||||||
Note: {
|
|
||||||
reg: "^#*(体力|树脂|查询体力|便笺|便签)$",
|
|
||||||
describe: "体力",
|
|
||||||
},
|
|
||||||
Note_appoint: {
|
|
||||||
reg: "^#体力模板(设置(.*)|列表)$",
|
|
||||||
describe: "体力模板设置",
|
|
||||||
},
|
|
||||||
pokeNote: {
|
|
||||||
reg: "#poke#",
|
|
||||||
describe: "体力",
|
|
||||||
},
|
|
||||||
|
|
||||||
...adminRule
|
setTimeout(async function () {
|
||||||
};
|
let msgStr = await redis.get('xiaoyao:restart-msg')
|
||||||
|
let relpyPrivate = async function () {
|
||||||
lodash.forEach(rule, (r) => {
|
|
||||||
r.priority = r.priority || 50;
|
|
||||||
r.prehash = true;
|
|
||||||
r.hashMark = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
export {
|
|
||||||
rule
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log(`图鉴插件${currentVersion}初始化~`);
|
|
||||||
setTimeout(async function() {
|
|
||||||
let msgStr = await redis.get("xiaoyao:restart-msg");
|
|
||||||
if (msgStr) {
|
|
||||||
let msg = JSON.parse(msgStr);
|
|
||||||
await common.relpyPrivate(msg.qq, msg.msg);
|
|
||||||
await redis.del("xiaoyao:restart-msg");
|
|
||||||
let msgs = [`当前版本: ${currentVersion}`, `您可使用 #图鉴版本 命令查看更新信息`];
|
|
||||||
await common.relpyPrivate(msg.qq, msgs.join("\n"));
|
|
||||||
}
|
}
|
||||||
}, 1000);
|
if (msgStr) {
|
||||||
|
let msg = JSON.parse(msgStr)
|
||||||
|
await relpyPrivate(msg.qq, msg.msg)
|
||||||
|
await redis.del('xiaoyao:restart-msg')
|
||||||
|
let msgs = [`当前图鉴版本: ${currentVersion}`, '您可使用 #图鉴版本 命令查看更新信息']
|
||||||
|
await relpyPrivate(msg.qq, msgs.join('\n'))
|
||||||
|
}
|
||||||
|
}, 1000)
|
||||||
|
233
model/gsCfg.js
Normal file
233
model/gsCfg.js
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
import YAML from 'yaml'
|
||||||
|
import chokidar from 'chokidar'
|
||||||
|
import fs from 'node:fs'
|
||||||
|
import { promisify } from 'node:util'
|
||||||
|
import lodash from 'lodash'
|
||||||
|
|
||||||
|
const plugin="xiaoyao-cvs-plugin"
|
||||||
|
/** 配置文件 */
|
||||||
|
class GsCfg {
|
||||||
|
constructor () {
|
||||||
|
/** 默认设置 */
|
||||||
|
this.defSetPath = `./plugins/${plugin}/defSet/`
|
||||||
|
this.defSet = {}
|
||||||
|
|
||||||
|
/** 用户设置 */
|
||||||
|
this.configPath = `./plugins/${plugin}/config/`
|
||||||
|
this.config = {}
|
||||||
|
|
||||||
|
/** 监听文件 */
|
||||||
|
this.watcher = { config: {}, defSet: {} }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param app 功能
|
||||||
|
* @param name 配置文件名称
|
||||||
|
*/
|
||||||
|
getdefSet (app, name) {
|
||||||
|
return this.getYaml(app, name, 'defSet')
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 用户配置 */
|
||||||
|
getConfig (app, name) {
|
||||||
|
let ignore = ['mys.pubCk', 'gacha.set']
|
||||||
|
|
||||||
|
if (ignore.includes(`${app}.${name}`)) {
|
||||||
|
return 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}`
|
||||||
|
|
||||||
|
if (this[type][key]) return this[type][key]
|
||||||
|
|
||||||
|
this[type][key] = YAML.parse(
|
||||||
|
fs.readFileSync(file, 'utf8')
|
||||||
|
)
|
||||||
|
|
||||||
|
this.watch(file, app, name, type)
|
||||||
|
|
||||||
|
return this[type][key]
|
||||||
|
}
|
||||||
|
|
||||||
|
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}`
|
||||||
|
|
||||||
|
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}`]()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
this.watcher[type][key] = watcher
|
||||||
|
}
|
||||||
|
|
||||||
|
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'))
|
||||||
|
|
||||||
|
const readFile = promisify(fs.readFile)
|
||||||
|
|
||||||
|
let promises = []
|
||||||
|
|
||||||
|
files.forEach((v) => promises.push(readFile(`${dir}${v}`, 'utf8')))
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
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 {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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]
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 原神角色武器长名称缩写
|
||||||
|
* @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()
|
||||||
|
}
|
||||||
|
|
||||||
|
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]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取消息内原神角色名称,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) || ''
|
||||||
|
|
||||||
|
return {
|
||||||
|
roleId,
|
||||||
|
uid,
|
||||||
|
alias,
|
||||||
|
name: this.roleIdToName(roleId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new GsCfg()
|
219
model/mys/mysApi.js
Normal file
219
model/mys/mysApi.js
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
import md5 from 'md5'
|
||||||
|
import lodash from 'lodash'
|
||||||
|
import fetch from 'node-fetch'
|
||||||
|
|
||||||
|
export default class MysApi {
|
||||||
|
/**
|
||||||
|
* @param uid 游戏uid
|
||||||
|
* @param cookie 米游社cookie
|
||||||
|
* @param option 其他参数
|
||||||
|
* @param option.log 是否显示日志
|
||||||
|
*/
|
||||||
|
constructor (uid, cookie, option = {}) {
|
||||||
|
this.uid = uid
|
||||||
|
this.cookie = cookie
|
||||||
|
this.server = this.getServer()
|
||||||
|
|
||||||
|
let op = {
|
||||||
|
log: true,
|
||||||
|
...option
|
||||||
|
}
|
||||||
|
this.option = op
|
||||||
|
}
|
||||||
|
|
||||||
|
getUrl (type, data = {}) {
|
||||||
|
let host, hostRecord
|
||||||
|
if (['cn_gf01', 'cn_qd01'].includes(this.server)) {
|
||||||
|
host = 'https://api-takumi.mihoyo.com/'
|
||||||
|
hostRecord = 'https://api-takumi-record.mihoyo.com/'
|
||||||
|
}
|
||||||
|
|
||||||
|
let urlMap = {
|
||||||
|
/** 首页宝箱 */
|
||||||
|
index: {
|
||||||
|
url: `${hostRecord}game_record/app/genshin/api/index`,
|
||||||
|
query: `role_id=${this.uid}&server=${this.server}`
|
||||||
|
},
|
||||||
|
/** 深渊 */
|
||||||
|
spiralAbyss: {
|
||||||
|
url: `${hostRecord}game_record/app/genshin/api/spiralAbyss`,
|
||||||
|
query: `role_id=${this.uid}&schedule_type=${data.schedule_type || 1}&server=${this.server}`
|
||||||
|
},
|
||||||
|
/** 角色详情 */
|
||||||
|
character: {
|
||||||
|
url: `${hostRecord}game_record/app/genshin/api/character`,
|
||||||
|
body: { role_id: this.uid, server: this.server }
|
||||||
|
},
|
||||||
|
/** 树脂 */
|
||||||
|
dailyNote: {
|
||||||
|
url: `${hostRecord}game_record/app/genshin/api/dailyNote`,
|
||||||
|
query: `role_id=${this.uid}&server=${this.server}`
|
||||||
|
},
|
||||||
|
/** 签到信息 */
|
||||||
|
bbs_sign_info: {
|
||||||
|
url: `${host}event/bbs_sign_reward/info`,
|
||||||
|
query: `act_id=e202009291139501®ion=${this.server}&uid=${this.uid}`,
|
||||||
|
sign: true
|
||||||
|
},
|
||||||
|
/** 签到奖励 */
|
||||||
|
bbs_sign_home: {
|
||||||
|
url: `${host}event/bbs_sign_reward/home`,
|
||||||
|
query: `act_id=e202009291139501®ion=${this.server}&uid=${this.uid}`,
|
||||||
|
sign: true
|
||||||
|
},
|
||||||
|
/** 签到 */
|
||||||
|
bbs_sign: {
|
||||||
|
url: `${host}event/bbs_sign_reward/sign`,
|
||||||
|
body: { act_id: 'e202009291139501', region: this.server, uid: this.uid },
|
||||||
|
sign: true
|
||||||
|
},
|
||||||
|
/** 详情 */
|
||||||
|
detail: {
|
||||||
|
url: `${host}event/e20200928calculate/v1/sync/avatar/detail`,
|
||||||
|
query: `uid=${this.uid}®ion=${this.server}&avatar_id=${data.avatar_id}`
|
||||||
|
},
|
||||||
|
/** 札记 */
|
||||||
|
ys_ledger: {
|
||||||
|
url: 'https://hk4e-api.mihoyo.com/event/ys_ledger/monthInfo',
|
||||||
|
query: `month=${data.month}&bind_uid=${this.uid}&bind_region=${this.server}`
|
||||||
|
},
|
||||||
|
/** 养成计算器 */
|
||||||
|
compute: {
|
||||||
|
url: `${host}event/e20200928calculate/v2/compute`,
|
||||||
|
body: data
|
||||||
|
},
|
||||||
|
/** 角色技能 */
|
||||||
|
avatarSkill: {
|
||||||
|
url: `${host}event/e20200928calculate/v1/avatarSkill/list`,
|
||||||
|
query: `avatar_id=${data.avatar_id}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!urlMap[type]) return false
|
||||||
|
|
||||||
|
let { url, query = '', body = '', sign = '' } = urlMap[type]
|
||||||
|
|
||||||
|
if (query) url += `?${query}`
|
||||||
|
if (body) body = JSON.stringify(body)
|
||||||
|
|
||||||
|
let headers = this.getHeaders(query, body, sign)
|
||||||
|
|
||||||
|
return { url, headers, body }
|
||||||
|
}
|
||||||
|
|
||||||
|
getServer () {
|
||||||
|
let uid = this.uid
|
||||||
|
switch (String(uid)[0]) {
|
||||||
|
case '1':
|
||||||
|
case '2':
|
||||||
|
return 'cn_gf01' // 官服
|
||||||
|
case '5':
|
||||||
|
return 'cn_qd01' // B服
|
||||||
|
}
|
||||||
|
return 'cn_gf01'
|
||||||
|
}
|
||||||
|
|
||||||
|
async getData (type, data = {}, isForce = true) {
|
||||||
|
let { url, headers, body } = this.getUrl(type, data)
|
||||||
|
|
||||||
|
if (!url) return false
|
||||||
|
|
||||||
|
let cahce = await redis.get(`Yz:genshin:mys:cache:${type}:${this.uid}`)
|
||||||
|
if (cahce && !isForce) return JSON.parse(cahce)
|
||||||
|
|
||||||
|
headers.Cookie = this.cookie
|
||||||
|
let param = {
|
||||||
|
headers,
|
||||||
|
timeout: 10000
|
||||||
|
}
|
||||||
|
|
||||||
|
if (body) {
|
||||||
|
param.method = 'post'
|
||||||
|
param.body = body
|
||||||
|
} else {
|
||||||
|
param.method = 'get'
|
||||||
|
}
|
||||||
|
let response = {}
|
||||||
|
let start = Date.now()
|
||||||
|
try {
|
||||||
|
response = await fetch(url, param)
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(error)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
logger.error(response)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (this.option.log) {
|
||||||
|
logger.mark(`[米游社接口][${type}][${this.uid}] ${Date.now() - start}ms`)
|
||||||
|
}
|
||||||
|
const res = await response.json()
|
||||||
|
|
||||||
|
if (!res) {
|
||||||
|
logger.mark('mys接口没有返回')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res.retcode !== 0) {
|
||||||
|
logger.debug(`[米游社接口][请求参数] ${url} ${JSON.stringify(param)}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
res.api = type
|
||||||
|
|
||||||
|
this.cache(res, type)
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
getHeaders (query = '', body = '', sign = false) {
|
||||||
|
if (sign) {
|
||||||
|
return {
|
||||||
|
'x-rpc-app_version': '2.3.0',
|
||||||
|
'x-rpc-client_type': 5,
|
||||||
|
'x-rpc-device_id': this.getGuid(),
|
||||||
|
'User-Agent': ' miHoYoBBS/2.3.0',
|
||||||
|
DS: this.getDsSign()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
'x-rpc-app_version': '2.31.1',
|
||||||
|
'x-rpc-client_type': 5,
|
||||||
|
DS: this.getDs(query, body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getDs (q = '', b = '') {
|
||||||
|
let n = ''
|
||||||
|
if (['cn_gf01', 'cn_qd01'].includes(this.server)) {
|
||||||
|
n = 'xV8v4Qu54lUKrEYFZkJhB8cuOh9Asafs'
|
||||||
|
}
|
||||||
|
let t = Math.round(new Date().getTime() / 1000)
|
||||||
|
let r = Math.floor(Math.random() * 900000 + 100000)
|
||||||
|
let DS = md5(`salt=${n}&t=${t}&r=${r}&b=${b}&q=${q}`)
|
||||||
|
return `${t},${r},${DS}`
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 签到ds */
|
||||||
|
getDsSign () {
|
||||||
|
const n = 'h8w582wxwgqvahcdkpvdhbh2w9casgfl'
|
||||||
|
const t = Math.round(new Date().getTime() / 1000)
|
||||||
|
const r = lodash.sampleSize('abcdefghijklmnopqrstuvwxyz0123456789', 6).join('')
|
||||||
|
const DS = md5(`salt=${n}&t=${t}&r=${r}`)
|
||||||
|
return `${t},${r},${DS}`
|
||||||
|
}
|
||||||
|
|
||||||
|
getGuid () {
|
||||||
|
function S4 () {
|
||||||
|
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (S4() + S4() + '-' + S4() + '-' + S4() + '-' + S4() + '-' + S4() + S4() + S4())
|
||||||
|
}
|
||||||
|
|
||||||
|
async cache (res, type) {
|
||||||
|
if (!res || res.retcode !== 0) return
|
||||||
|
redis.setEx(`Yz:genshin:mys:cache:${type}:${this.uid}`, 300, JSON.stringify(res))
|
||||||
|
}
|
||||||
|
}
|
650
model/mys/mysInfo.js
Normal file
650
model/mys/mysInfo.js
Normal file
@ -0,0 +1,650 @@
|
|||||||
|
import MysApi from './mysApi.js'
|
||||||
|
import GsCfg from '../gsCfg.js'
|
||||||
|
import lodash from 'lodash'
|
||||||
|
import moment from 'moment'
|
||||||
|
|
||||||
|
/** 公共ck */
|
||||||
|
let pubCk = {}
|
||||||
|
/** 绑定ck */
|
||||||
|
let bingCkUid = {}
|
||||||
|
let bingCkQQ = {}
|
||||||
|
let bingCkLtuid = {}
|
||||||
|
|
||||||
|
export default class MysInfo {
|
||||||
|
/** redis key */
|
||||||
|
static keyPre = 'Yz:genshin:mys:'
|
||||||
|
static key = {
|
||||||
|
/** ck使用次数统计 */
|
||||||
|
count: `${MysInfo.keyPre}ck:count`,
|
||||||
|
/** ck使用详情 */
|
||||||
|
detail: `${MysInfo.keyPre}ck:detail`,
|
||||||
|
/** 单个ck使用次数 */
|
||||||
|
ckNum: `${MysInfo.keyPre}ckNum:`,
|
||||||
|
/** 已失效的ck使用详情 */
|
||||||
|
delDetail: `${MysInfo.keyPre}ck:delDetail`,
|
||||||
|
/** qq-uid */
|
||||||
|
qqUid: `${MysInfo.keyPre}qq-uid:`
|
||||||
|
}
|
||||||
|
|
||||||
|
static tips = '请先#绑定cookie\n发送【体力帮助】查看配置教程'
|
||||||
|
|
||||||
|
constructor (e) {
|
||||||
|
if (e) {
|
||||||
|
this.e = e
|
||||||
|
this.userId = String(e.user_id)
|
||||||
|
}
|
||||||
|
/** 当前查询原神uid */
|
||||||
|
this.uid = ''
|
||||||
|
/** 当前ck信息 */
|
||||||
|
this.ckInfo = {
|
||||||
|
ck: '',
|
||||||
|
uid: '',
|
||||||
|
qq: '',
|
||||||
|
ltuid: '',
|
||||||
|
type: ''
|
||||||
|
}
|
||||||
|
|
||||||
|
this.auth = ['dailyNote', 'bbs_sign_info', 'bbs_sign_home', 'bbs_sign']
|
||||||
|
}
|
||||||
|
|
||||||
|
static async init (e, api) {
|
||||||
|
let mysInfo = new MysInfo(e)
|
||||||
|
|
||||||
|
/** 检查时间 */
|
||||||
|
if (!mysInfo.checkTime()) return false
|
||||||
|
|
||||||
|
/** 初始化绑定ck */
|
||||||
|
await mysInfo.initBingCk()
|
||||||
|
|
||||||
|
/** 初始化公共ck */
|
||||||
|
await mysInfo.initPubCk()
|
||||||
|
|
||||||
|
if (mysInfo.checkAuth(api)) {
|
||||||
|
/** 获取ck绑定uid */
|
||||||
|
mysInfo.uid = (await MysInfo.getSelfUid(e)).uid
|
||||||
|
} else {
|
||||||
|
/** 获取uid */
|
||||||
|
mysInfo.uid = await MysInfo.getUid(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mysInfo.uid) return false
|
||||||
|
|
||||||
|
mysInfo.e.uid = mysInfo.uid
|
||||||
|
|
||||||
|
/** 获取ck */
|
||||||
|
await mysInfo.getCookie()
|
||||||
|
|
||||||
|
/** 判断回复 */
|
||||||
|
await mysInfo.checkReply()
|
||||||
|
|
||||||
|
return mysInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获取uid */
|
||||||
|
static async getUid (e) {
|
||||||
|
if (e.uid) return e.uid
|
||||||
|
|
||||||
|
let { msg = '', at = '' } = e
|
||||||
|
|
||||||
|
if (!msg) return false
|
||||||
|
|
||||||
|
let uid = false
|
||||||
|
/** at用户 */
|
||||||
|
if (at) {
|
||||||
|
uid = await redis.get(`${MysInfo.key.qqUid}${at}`)
|
||||||
|
if (uid) return String(uid)
|
||||||
|
e.reply('尚未绑定uid', false, { at })
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
let matchUid = (msg = '') => {
|
||||||
|
let ret = /[1|2|5][0-9]{8}/g.exec(msg)
|
||||||
|
if (!ret) return false
|
||||||
|
return ret[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 命令消息携带 */
|
||||||
|
uid = matchUid(msg)
|
||||||
|
if (uid) return String(uid)
|
||||||
|
|
||||||
|
/** 绑定的uid */
|
||||||
|
uid = await redis.get(`${MysInfo.key.qqUid}${e.user_id}`)
|
||||||
|
if (uid) return String(uid)
|
||||||
|
|
||||||
|
/** 群名片 */
|
||||||
|
uid = matchUid(e.sender.card)
|
||||||
|
if (uid) return String(uid)
|
||||||
|
|
||||||
|
e.reply('请先#绑定uid', false, { at })
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获取ck绑定uid */
|
||||||
|
static async getSelfUid (e) {
|
||||||
|
if (e.uid) return e.uid
|
||||||
|
|
||||||
|
let { msg = '', at = '' } = e
|
||||||
|
|
||||||
|
if (!msg) return false
|
||||||
|
|
||||||
|
/** at用户 */
|
||||||
|
if (at && (!bingCkQQ[at] || !bingCkQQ[at].uid)) {
|
||||||
|
e.reply('尚未绑定cookie', false, { at })
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!e.user_id || !bingCkQQ[e.user_id] || !bingCkQQ[e.user_id].uid) {
|
||||||
|
e.reply(MysInfo.tips, false, { at })
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return bingCkQQ[e.user_id]
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 判断绑定ck才能查询 */
|
||||||
|
checkAuth (api) {
|
||||||
|
if (lodash.isObject(api)) {
|
||||||
|
for (let i in api) {
|
||||||
|
if (this.auth.includes(i)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (this.auth.includes(api)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param api
|
||||||
|
* * `index` 米游社原神首页宝箱等数据
|
||||||
|
* * `spiralAbyss` 原神深渊
|
||||||
|
* * `character` 原神角色详情
|
||||||
|
* * `dailyNote` 原神树脂
|
||||||
|
* * `bbs_sign` 米游社原神签到
|
||||||
|
* * `detail` 详情
|
||||||
|
* * `ys_ledger` 札记
|
||||||
|
* * `compute` 养成计算器
|
||||||
|
* * `avatarSkill` 角色技能
|
||||||
|
*/
|
||||||
|
static async get (e, api, data = {}) {
|
||||||
|
let mysInfo = await MysInfo.init(e, api)
|
||||||
|
|
||||||
|
if (!mysInfo.uid || !mysInfo.ckInfo.ck) return false
|
||||||
|
e.uid = mysInfo.uid
|
||||||
|
|
||||||
|
let mysApi = new MysApi(mysInfo.uid, mysInfo.ckInfo.ck)
|
||||||
|
|
||||||
|
let res
|
||||||
|
if (lodash.isObject(api)) {
|
||||||
|
let all = []
|
||||||
|
lodash.forEach(api, (v, i) => {
|
||||||
|
all.push(mysApi.getData(i, v))
|
||||||
|
})
|
||||||
|
res = await Promise.all(all)
|
||||||
|
|
||||||
|
for (let i in res) {
|
||||||
|
res[i] = await mysInfo.checkCode(res[i], res[i].api)
|
||||||
|
if (res[i].retcode === 0) continue
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res = await mysApi.getData(api, data)
|
||||||
|
if (!res) return false
|
||||||
|
|
||||||
|
res = await mysInfo.checkCode(res, api)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkReply () {
|
||||||
|
if (!this.uid) {
|
||||||
|
this.e.reply('请先#绑定uid')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.ckInfo.ck) {
|
||||||
|
if (lodash.isEmpty(pubCk)) {
|
||||||
|
this.e.reply('请先配置公共查询ck')
|
||||||
|
} else {
|
||||||
|
this.e.reply('公共ck查询次数已用完,暂无法查询新uid')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getCookie () {
|
||||||
|
if (this.ckInfo.ck) return this.ckInfo.ck
|
||||||
|
// 使用用户uid绑定的ck
|
||||||
|
await this.getBingCK() ||
|
||||||
|
// 使用uid已查询的ck
|
||||||
|
await this.getCheckCK() ||
|
||||||
|
// 使用用户绑定的ck
|
||||||
|
await this.getBingCKqq() ||
|
||||||
|
// 使用公共ck
|
||||||
|
await this.getPublicCK()
|
||||||
|
|
||||||
|
return this.ckInfo.ck
|
||||||
|
}
|
||||||
|
|
||||||
|
async getBingCK () {
|
||||||
|
if (!bingCkUid[this.uid]) return false
|
||||||
|
|
||||||
|
this.isSelf = true
|
||||||
|
|
||||||
|
let ck = bingCkUid[this.uid]
|
||||||
|
|
||||||
|
this.ckInfo = ck
|
||||||
|
this.ckInfo.type = 'self'
|
||||||
|
|
||||||
|
logger.mark(`[米游社查询][uid:${this.uid}]${logger.green(`[使用已绑定ck:${ck.ltuid}]`)}`)
|
||||||
|
|
||||||
|
return ck.ck
|
||||||
|
}
|
||||||
|
|
||||||
|
async getCheckCK () {
|
||||||
|
let ltuid = await redis.zScore(MysInfo.key.detail, this.uid)
|
||||||
|
|
||||||
|
if (!ltuid) return false
|
||||||
|
|
||||||
|
this.ckInfo.ltuid = ltuid
|
||||||
|
this.ckInfo.type = 'public'
|
||||||
|
|
||||||
|
/** 使用用户绑定ck */
|
||||||
|
if (bingCkLtuid[ltuid]) {
|
||||||
|
logger.mark(`[米游社查询][uid:${this.uid}]${logger.blue(`[已查询][使用用户ck:${ltuid}]`)}`)
|
||||||
|
|
||||||
|
this.ckInfo = bingCkLtuid[ltuid]
|
||||||
|
this.ckInfo.type = 'self'
|
||||||
|
|
||||||
|
return this.ckInfo.ck
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 公共ck */
|
||||||
|
if (pubCk[ltuid]) {
|
||||||
|
logger.mark(`[米游社查询][uid:${this.uid}]${logger.cyan(`[已查询][使用公共ck:${ltuid}]`)}`)
|
||||||
|
|
||||||
|
this.ckInfo.ck = pubCk[ltuid]
|
||||||
|
return this.ckInfo.ck
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 使用用户绑定的ck */
|
||||||
|
async getBingCKqq () {
|
||||||
|
/** 用户没有绑定ck */
|
||||||
|
if (!bingCkQQ[this.userId]) return false
|
||||||
|
|
||||||
|
let ck = bingCkQQ[this.userId]
|
||||||
|
|
||||||
|
/** 判断用户ck使用次数 */
|
||||||
|
let num = await redis.get(`${MysInfo.key.ckNum}${ck.ltuid}`)
|
||||||
|
if (num && num >= 27) {
|
||||||
|
logger.mark(`[米游社查询][uid:${this.uid}] 绑定用户ck次数已用完`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!num) num = 0
|
||||||
|
|
||||||
|
this.ckInfo = ck
|
||||||
|
this.ckInfo.type = 'bing'
|
||||||
|
|
||||||
|
/** 插入查询详情 */
|
||||||
|
await redis.zAdd(MysInfo.key.detail, { score: ck.ltuid, value: this.uid })
|
||||||
|
/** 获取ck查询详情 */
|
||||||
|
let count = await redis.zRangeByScore(MysInfo.key.detail, ck.ltuid, ck.ltuid)
|
||||||
|
|
||||||
|
/** 用户ck也配置公共ck */
|
||||||
|
if (pubCk[ck.ltuid]) {
|
||||||
|
/** 统计ck查询次数 */
|
||||||
|
redis.zAdd(MysInfo.key.count, { score: count.length || 1, value: String(ck.ltuid) })
|
||||||
|
}
|
||||||
|
this.expire(MysInfo.key.detail)
|
||||||
|
|
||||||
|
/** 插入单个查询次数 */
|
||||||
|
redis.setEx(`${MysInfo.key.ckNum}${ck.ltuid}`, this.getEnd(), String(count.length))
|
||||||
|
|
||||||
|
logger.mark(`[米游社查询][uid:${this.uid}]${logger.blue(`[使用用户ck:${ck.ltuid}]`)}[次数:${++num}次]`)
|
||||||
|
|
||||||
|
return ck.ck
|
||||||
|
}
|
||||||
|
|
||||||
|
async getPublicCK () {
|
||||||
|
if (lodash.isEmpty(pubCk)) {
|
||||||
|
logger.mark('请先配置公共查询ck')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获取使用次数最少的ck */
|
||||||
|
let list = await redis.zRangeByScore(MysInfo.key.count, 0, 27, true)
|
||||||
|
|
||||||
|
if (lodash.isEmpty(list)) {
|
||||||
|
logger.mark('公共查询ck已用完')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
let ltuid = list[0]
|
||||||
|
|
||||||
|
if (!pubCk[ltuid]) {
|
||||||
|
logger.mark(`公共查询ck错误[ltuid:${ltuid}]`)
|
||||||
|
await redis.zAdd(MysInfo.key.count, { score: 99, value: ltuid })
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ckInfo.ck = pubCk[ltuid]
|
||||||
|
this.ckInfo.ltuid = ltuid
|
||||||
|
this.ckInfo.type = 'public'
|
||||||
|
|
||||||
|
/** 非原子操作,可能存在误差 */
|
||||||
|
|
||||||
|
/** 插入查询详情 */
|
||||||
|
await redis.zAdd(MysInfo.key.detail, { score: ltuid, value: this.uid })
|
||||||
|
/** 获取ck查询详情 */
|
||||||
|
let count = await redis.zRangeByScore(MysInfo.key.detail, ltuid, ltuid)
|
||||||
|
/** 统计ck查询次数 */
|
||||||
|
redis.zAdd(MysInfo.key.count, { score: count.length, value: ltuid })
|
||||||
|
/** 插入单个查询次数 */
|
||||||
|
redis.setEx(`${MysInfo.key.ckNum}${ltuid}`, this.getEnd(), String(count.length))
|
||||||
|
|
||||||
|
this.expire(MysInfo.key.detail)
|
||||||
|
|
||||||
|
logger.mark(`[米游社查询][uid:${this.uid}]${logger.yellow(`[使用公共ck:${ltuid}][次数:${count.length}]`)}`)
|
||||||
|
|
||||||
|
return pubCk[ltuid]
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 初始化公共查询ck */
|
||||||
|
async initPubCk () {
|
||||||
|
/** 没配置每次都会初始化 */
|
||||||
|
if (!lodash.isEmpty(pubCk)) return
|
||||||
|
|
||||||
|
let ckList = await redis.zRangeByScore(MysInfo.key.count, 0, 100)
|
||||||
|
|
||||||
|
await this.addPubCk(ckList)
|
||||||
|
|
||||||
|
/** 使用用户ck当公共查询 */
|
||||||
|
let set = GsCfg.getConfig('mys', 'set')
|
||||||
|
let userNum = 0
|
||||||
|
if (set.allowUseCookie == 1) {
|
||||||
|
lodash.forEach(bingCkUid, async v => {
|
||||||
|
if (pubCk[v.ltuid]) return
|
||||||
|
pubCk[v.ltuid] = v.ck
|
||||||
|
|
||||||
|
userNum++
|
||||||
|
/** 加入redis统计 */
|
||||||
|
if (!ckList.includes(v.ltuid)) {
|
||||||
|
await redis.zAdd(MysInfo.key.count, { score: 0, value: String(v.ltuid) })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.expire(MysInfo.key.count)
|
||||||
|
|
||||||
|
if (userNum > 0) logger.mark(`加载用户ck:${userNum}个`)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 加入公共ck池 */
|
||||||
|
async addPubCk (ckList = '') {
|
||||||
|
let ckArr = GsCfg.getConfig('mys', 'pubCk')
|
||||||
|
|
||||||
|
if (!ckList) {
|
||||||
|
ckList = await redis.zRangeByScore(MysInfo.key.count, 0, 100)
|
||||||
|
}
|
||||||
|
|
||||||
|
let pubNum = 0
|
||||||
|
for (let v of ckArr) {
|
||||||
|
let [ltuid = ''] = v.match(/ltuid=(\w{0,9})/g)
|
||||||
|
if (!ltuid) return
|
||||||
|
|
||||||
|
ltuid = String(lodash.trim(ltuid, 'ltuid='))
|
||||||
|
|
||||||
|
if (isNaN(ltuid)) return
|
||||||
|
|
||||||
|
pubCk[ltuid] = v
|
||||||
|
|
||||||
|
pubNum++
|
||||||
|
|
||||||
|
/** 加入redis统计 */
|
||||||
|
if (!ckList.includes(ltuid)) {
|
||||||
|
await redis.zAdd(MysInfo.key.count, { score: 0, value: ltuid })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pubNum > 0) logger.mark(`加载公共ck:${pubNum}个`)
|
||||||
|
}
|
||||||
|
|
||||||
|
async initBingCk () {
|
||||||
|
if (!lodash.isEmpty(bingCkUid)) return
|
||||||
|
|
||||||
|
let res = await GsCfg.getBingCk()
|
||||||
|
bingCkUid = res.ck
|
||||||
|
bingCkQQ = res.ckQQ
|
||||||
|
bingCkLtuid = lodash.keyBy(bingCkUid, 'ltuid')
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkCode (res, type) {
|
||||||
|
res.retcode = Number(res.retcode)
|
||||||
|
if (type == 'bbs_sign') {
|
||||||
|
if ([-5003].includes(res.retcode)) {
|
||||||
|
res.retcode = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (res.retcode) {
|
||||||
|
case 0:break
|
||||||
|
case -1:
|
||||||
|
case -100:
|
||||||
|
case 1001:
|
||||||
|
case 10001:
|
||||||
|
case 10103:
|
||||||
|
if (/(登录|login)/i.test(res.message)) {
|
||||||
|
if (this.ckInfo.uid) {
|
||||||
|
this.e.reply(`UID:${this.ckInfo.uid},米游社cookie已失效,请重新绑定cookie`)
|
||||||
|
} else {
|
||||||
|
this.e.reply(`ltuid:${this.ckInfo.ltuid},米游社cookie已失效`)
|
||||||
|
}
|
||||||
|
await this.delCk()
|
||||||
|
} else {
|
||||||
|
this.e.reply(`米游社接口报错,暂时无法查询:${res.message}`)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 1008:
|
||||||
|
this.e.reply('\n请先去米游社绑定角色', false, { at: this.userId })
|
||||||
|
break
|
||||||
|
case 10101:
|
||||||
|
this.disableToday()
|
||||||
|
this.e.reply('查询已达今日上限')
|
||||||
|
break
|
||||||
|
case 10102:
|
||||||
|
if (res.message == 'Data is not public for the user') {
|
||||||
|
this.e.reply(`\nUID:${this.ckInfo.uid},米游社数据未公开`, false, { at: this.userId })
|
||||||
|
} else {
|
||||||
|
this.e.reply(`uid:${this.uid},请先去米游社绑定角色`)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
// 伙伴不存在~
|
||||||
|
case -1002:
|
||||||
|
if (res.api == 'detail') res.retcode = 0
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
this.e.reply(`米游社接口报错,暂时无法查询:${res.message || 'error'}`)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res.retcode !== 0) {
|
||||||
|
logger.mark(`mys接口报错:${JSON.stringify(res)},uid:${this.uid}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除失效ck */
|
||||||
|
async delCk () {
|
||||||
|
let ltuid = this.ckInfo.ltuid
|
||||||
|
|
||||||
|
/** 记录公共ck失效 */
|
||||||
|
if (this.ckInfo.type == 'public') {
|
||||||
|
if (bingCkLtuid[ltuid]) {
|
||||||
|
this.ckInfo = bingCkLtuid[ltuid]
|
||||||
|
this.ckInfo.type = 'self'
|
||||||
|
} else {
|
||||||
|
logger.mark(`删除失效ck[ltuid:${ltuid}]`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.ckInfo.type == 'self' || this.ckInfo.type == 'bing') {
|
||||||
|
/** 获取用户绑定ck */
|
||||||
|
let ck = GsCfg.getBingCkSingle(this.userId)
|
||||||
|
let tmp = ck[this.ckInfo.uid]
|
||||||
|
if (tmp) {
|
||||||
|
ltuid = tmp.ltuid
|
||||||
|
|
||||||
|
logger.mark(`删除失效绑定ck[qq:${this.userId}]`)
|
||||||
|
/** 删除文件保存ck */
|
||||||
|
delete ck[this.ckInfo.uid]
|
||||||
|
GsCfg.saveBingCk(this.userId, ck)
|
||||||
|
|
||||||
|
this.redisDel(ltuid)
|
||||||
|
|
||||||
|
delete pubCk[ltuid]
|
||||||
|
delete bingCkUid[tmp.uid]
|
||||||
|
delete bingCkQQ[tmp.qq]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete pubCk[ltuid]
|
||||||
|
|
||||||
|
await this.redisDel(ltuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
async redisDel (ltuid) {
|
||||||
|
/** 统计次数设为超限 */
|
||||||
|
await redis.zRem(MysInfo.key.count, String(ltuid))
|
||||||
|
// await redis.setEx(`${MysInfo.key.ckNum}${ltuid}`, this.getEnd(), '99')
|
||||||
|
|
||||||
|
/** 将当前查询记录移入回收站 */
|
||||||
|
await this.detailDel(ltuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 将当前查询记录移入回收站 */
|
||||||
|
async detailDel (ltuid) {
|
||||||
|
let detail = await redis.zRangeByScore(MysInfo.key.detail, ltuid, ltuid)
|
||||||
|
if (!lodash.isEmpty(detail)) {
|
||||||
|
let delDetail = []
|
||||||
|
detail.forEach((v) => {
|
||||||
|
delDetail.push({ score: ltuid, value: String(v) })
|
||||||
|
})
|
||||||
|
await redis.zAdd(MysInfo.key.delDetail, delDetail)
|
||||||
|
this.expire(MysInfo.key.delDetail)
|
||||||
|
}
|
||||||
|
/** 删除当前ck查询记录 */
|
||||||
|
await redis.zRemRangeByScore(MysInfo.key.detail, ltuid, ltuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
async disableToday () {
|
||||||
|
/** 统计次数设为超限 */
|
||||||
|
await redis.zAdd(MysInfo.key.count, { score: 99, value: String(this.ckInfo.ltuid) })
|
||||||
|
await redis.setEx(`${MysInfo.key.ckNum}${this.ckInfo.ltuid}`, this.getEnd(), '99')
|
||||||
|
}
|
||||||
|
|
||||||
|
async expire (key) {
|
||||||
|
return await redis.expire(key, this.getEnd())
|
||||||
|
}
|
||||||
|
|
||||||
|
getEnd () {
|
||||||
|
let end = moment().endOf('day').format('X')
|
||||||
|
return end - moment().format('X')
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理用户绑定ck */
|
||||||
|
async addBingCk (ck) {
|
||||||
|
/** 加入缓存 */
|
||||||
|
bingCkUid[ck.uid] = ck
|
||||||
|
bingCkQQ[ck.qq] = ck
|
||||||
|
bingCkLtuid[ck.ltuid] = ck
|
||||||
|
|
||||||
|
let set = GsCfg.getConfig('mys', 'set')
|
||||||
|
|
||||||
|
/** qq-uid */
|
||||||
|
await redis.setEx(`${MysInfo.key.qqUid}${ck.qq}`, 3600 * 24 * 30, String(ck.uid))
|
||||||
|
|
||||||
|
/** 恢复回收站查询记录,会覆盖原来记录 */
|
||||||
|
let detail = await redis.zRangeByScore(MysInfo.key.delDetail, ck.ltuid, ck.ltuid)
|
||||||
|
if (!lodash.isEmpty(detail)) {
|
||||||
|
let delDetail = []
|
||||||
|
detail.forEach((v) => {
|
||||||
|
delDetail.push({ score: ck.ltuid, value: String(v) })
|
||||||
|
})
|
||||||
|
await redis.zAdd(MysInfo.key.detail, delDetail)
|
||||||
|
this.expire(MysInfo.key.detail)
|
||||||
|
}
|
||||||
|
/** 删除回收站记录 */
|
||||||
|
await redis.zRemRangeByScore(MysInfo.key.delDetail, ck.ltuid, ck.ltuid)
|
||||||
|
|
||||||
|
/** 获取ck查询详情 */
|
||||||
|
let count = await redis.zRangeByScore(MysInfo.key.detail, ck.ltuid, ck.ltuid)
|
||||||
|
|
||||||
|
/** 开启了用户ck查询 */
|
||||||
|
if (set.allowUseCookie == 1) {
|
||||||
|
pubCk[ck.ltuid] = ck
|
||||||
|
let ckList = await redis.zRangeByScore(MysInfo.key.count, 0, 100)
|
||||||
|
if (!ckList.includes(ck.ltuid)) {
|
||||||
|
await redis.zAdd(MysInfo.key.count, { score: count.length, value: String(ck.ltuid) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async delBingCk (ck) {
|
||||||
|
delete bingCkUid[ck.uid]
|
||||||
|
delete bingCkQQ[ck.qq]
|
||||||
|
delete bingCkLtuid[ck.ltuid]
|
||||||
|
|
||||||
|
this.detailDel(ck.ltuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
async resetCk () {
|
||||||
|
return await redis.del(MysInfo.key.count)
|
||||||
|
}
|
||||||
|
|
||||||
|
static async initCk () {
|
||||||
|
if (lodash.isEmpty(bingCkUid)) {
|
||||||
|
let mysInfo = new MysInfo()
|
||||||
|
await mysInfo.initBingCk()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async getBingCkUid () {
|
||||||
|
await MysInfo.initCk()
|
||||||
|
|
||||||
|
return bingCkUid
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 切换uid */
|
||||||
|
static toggleUid (qq, ck) {
|
||||||
|
bingCkQQ[qq] = ck
|
||||||
|
}
|
||||||
|
|
||||||
|
static async checkUidBing (uid) {
|
||||||
|
await MysInfo.initCk()
|
||||||
|
|
||||||
|
if (bingCkUid[uid]) return true
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 数据更新中,请稍后再试 */
|
||||||
|
checkTime () {
|
||||||
|
let hour = moment().hour()
|
||||||
|
let min = moment().minute()
|
||||||
|
let second = moment().second()
|
||||||
|
|
||||||
|
if (hour == 23 && min == 59 && second >= 58) {
|
||||||
|
this.e.reply('数据更新中,请稍后再试')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (hour == 0 && min == 0 && second <= 3) {
|
||||||
|
this.e.reply('数据更新中,请稍后再试')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
88
resources/Atlas_alias/wuqi_tujian.json
Normal file
88
resources/Atlas_alias/wuqi_tujian.json
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
{
|
||||||
|
"磐岩结绿": ["绿箭", "绿剑"],
|
||||||
|
"斫峰之刃": ["斫峰", "盾剑"],
|
||||||
|
"无工之剑": ["蜈蚣", "蜈蚣大剑", "无工大剑", "盾大剑", "无工"],
|
||||||
|
"贯虹之槊": ["贯虹", "岩枪", "盾枪"],
|
||||||
|
"赤角石溃杵": ["赤角", "石溃杵"],
|
||||||
|
"尘世之锁": ["尘世锁", "尘世", "盾书", "锁"],
|
||||||
|
|
||||||
|
"终末嗟叹之诗": ["终末", "终末弓", "叹气弓", "乐团弓"],
|
||||||
|
"松籁响起之时": ["松籁", "乐团大剑", "松剑"],
|
||||||
|
"苍古自由之誓": ["苍古", "乐团剑"],
|
||||||
|
|
||||||
|
"渔获": ["鱼叉"],
|
||||||
|
"衔珠海皇": ["海皇", "咸鱼剑", "咸鱼大剑"],
|
||||||
|
|
||||||
|
"匣里日月": ["日月"],
|
||||||
|
"匣里灭辰": ["灭辰"],
|
||||||
|
"匣里龙吟": ["龙吟"],
|
||||||
|
|
||||||
|
"天空之翼": ["天空弓"],
|
||||||
|
"天空之刃": ["天空剑"],
|
||||||
|
"天空之卷": ["天空书", "厕纸"],
|
||||||
|
"天空之脊": ["天空枪", "薄荷枪"],
|
||||||
|
"天空之傲": ["天空大剑"],
|
||||||
|
"四风原典": ["四风"],
|
||||||
|
|
||||||
|
"试作斩岩": ["斩岩"],
|
||||||
|
"试作星镰": ["星镰"],
|
||||||
|
"试作金珀": ["金珀"],
|
||||||
|
"试作古华": ["古华"],
|
||||||
|
"试作澹月": ["澹月"],
|
||||||
|
|
||||||
|
"千岩长枪": ["千岩枪"],
|
||||||
|
"千岩古剑": ["千岩剑", "千岩大剑"],
|
||||||
|
|
||||||
|
"暗巷闪光": ["暗巷剑"],
|
||||||
|
"暗巷猎手": ["暗巷弓"],
|
||||||
|
|
||||||
|
"阿莫斯之弓": ["阿莫斯", "ams", "痛苦弓"],
|
||||||
|
"雾切之回光": ["雾切"],
|
||||||
|
"飞雷之弦振": ["飞雷", "飞雷弓"],
|
||||||
|
"薙草之稻光": ["薙草", "稻光", "薙草稻光", "马尾枪", "马尾", "薙刀"],
|
||||||
|
"神乐之真意": ["神乐", "真意"],
|
||||||
|
"狼的末路": ["狼末"],
|
||||||
|
"护摩之杖": ["护摩", "护摩枪","护膜"],
|
||||||
|
"和璞鸢": ["鸟枪", "绿枪"],
|
||||||
|
"风鹰剑": ["风鹰"],
|
||||||
|
"冬极白星": ["冬极"],
|
||||||
|
"不灭月华": ["月华"],
|
||||||
|
"波乱月白经津": ["波乱", "月白", "波乱月白", "经津", "波波津"],
|
||||||
|
"若水": ["麒麟弓","Aqua","aqua"],
|
||||||
|
"笼钓瓶一心":["妖刀", "红刀", "笼钓瓶", "一心传名刀"],
|
||||||
|
"昭心": ["糟心"],
|
||||||
|
"幽夜华尔兹": ["幽夜", "幽夜弓", "华尔兹", "皇女弓"],
|
||||||
|
"雪葬的星银": ["雪葬", "星银", "雪葬星银", "雪山大剑"],
|
||||||
|
"喜多院十文字": ["喜多院", "十文字"],
|
||||||
|
"万国诸海图谱": ["万国", "万国诸海"],
|
||||||
|
"天目影打刀": ["天目刀", "天目"],
|
||||||
|
"破魔之弓": ["破魔弓"],
|
||||||
|
"曚云之月": ["曚云弓"],
|
||||||
|
"流月针": ["针"],
|
||||||
|
"流浪乐章": ["赌狗书", "赌狗乐章", "赌狗"],
|
||||||
|
"桂木斩长正": ["桂木", "斩长正"],
|
||||||
|
"腐殖之剑": ["腐殖", "腐殖剑"],
|
||||||
|
|
||||||
|
"风花之颂": ["风花弓"],
|
||||||
|
"证誓之明瞳": ["证誓", "明瞳", "证誓明瞳"],
|
||||||
|
"嘟嘟可故事集": ["嘟嘟可"],
|
||||||
|
"辰砂之纺锤": ["辰砂", "辰砂纺锤", "纺锤"],
|
||||||
|
"白辰之环": ["白辰", "白辰环"],
|
||||||
|
|
||||||
|
"决斗之枪": ["决斗枪", "决斗", "月卡枪"],
|
||||||
|
"螭骨剑": ["螭骨", "丈育剑", "离骨剑", "月卡大剑"],
|
||||||
|
"黑剑": ["月卡剑"],
|
||||||
|
"苍翠猎弓": ["绿弓", "月卡弓"],
|
||||||
|
|
||||||
|
"讨龙英杰谭": ["讨龙"],
|
||||||
|
"神射手之誓": ["脚气弓", "神射手"],
|
||||||
|
"黑缨枪": ["史莱姆枪"],
|
||||||
|
|
||||||
|
"贯月矢":["贯月矢","月矢"],
|
||||||
|
"竭泽":["竭泽"],
|
||||||
|
"猎人之径":["猎人之径"],
|
||||||
|
"森林王器":["森林王器","王器"],
|
||||||
|
"王下近侍":["王下近侍","近侍"],
|
||||||
|
"盈满之实":["盈满之实","盈满"],
|
||||||
|
"原木刀":["原木刀","木刀"]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user