ZZZ-Plugin/apps/guide.js
2024-07-25 16:30:00 +08:00

266 lines
7.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import path from 'path';
import fs from 'fs';
import fetch from 'node-fetch';
import lodash from 'lodash';
import common from '../../../lib/common/common.js';
import { ZZZPlugin } from '../lib/plugin.js';
import { rulePrefix } from '../lib/common.js';
import { atlasToName } from '../lib/convert/char.js';
import { imageResourcesPath, configPath } from '../lib/path.js';
import _ from 'lodash';
import settings from '../lib/settings.js';
const ZZZ_GUIDES_PATH = path.join(imageResourcesPath, 'guides');
const ZZZ_GUIDES_CONFIG_PATH = path.join(configPath, 'guide.yaml');
export class Guide extends ZZZPlugin {
constructor() {
super({
name: '[ZZZ-Plugin]Guide',
dsc: '#zzz角色攻略',
event: 'message',
priority: _.get(settings.getConfig('priority'), 'guide', 70),
rule: [
{
reg: `^${rulePrefix}攻略(说明|帮助)$`,
fnc: 'GuideHelp'
},
{
reg: `^${rulePrefix}设置默认攻略(\\d+|all)$`,
fnc: 'SetDefaultGuide'
},
{
reg: `^${rulePrefix}设置所有攻略显示个数(\\d+)$`,
fnc: 'SetMaxForwardGuide'
},
{
reg: `${rulePrefix}(更新)?\\S+攻略(\\d+|all)?$`,
fnc: 'Guide',
}
],
});
this.url =
'https://bbs-api.mihoyo.com/post/wapi/getPostFullInCollection?&gids=8&collection_id=';
this.collection_id = [
[],
// 来源:新艾利都快讯
[2712859],
[2727116],
[2721968],
[2724610],
[2722266],
];
this.source = [
'新艾利都快讯',
'清茶沐沐Kiyotya',
'小橙子阿',
'猫冬',
'月光中心',
];
// 最大攻略数量
this.maxNum = this.source.length;
// 最大显示攻略数量
this.maxForwardGuides = _.get(settings.getConfig('guide'), 'max_forward_guides', 4);
}
async init() {
for (let group = 1; group <= this.maxNum; group++) {
let guideFolder = this.getGuideFolder(group);
if (!fs.existsSync(guideFolder)) {
fs.mkdirSync(guideFolder, { recursive: true });
}
}
}
getGuideFolder(groupIndex) {
let guideFolder = path.join(ZZZ_GUIDES_PATH, this.source[groupIndex - 1]);
return guideFolder;
}
getGuidePath(groupIndex, characterName) {
let filename = `role_guide_${characterName}.png`;
let guidePath = path.join(this.getGuideFolder(groupIndex), filename);
return guidePath;
}
canGetImageFromFile(guidePath, isUpdate) {
return fs.existsSync(guidePath) && !isUpdate;
}
async Guide() {
let reg = new RegExp(`${rulePrefix}(更新)?(\\S+)攻略(\\d+|all)?$`);
let [
,
,
,
,
isUpdate,
atlas,
group = _.get(settings.getConfig('guide'), 'default_guide', 1).toString(),
] = this.e.msg.match(reg);
// all -> 0
if (group == 'all') {
group = '0';
}
group = Number(group);
if (group > this.maxNum) {
await this.reply(`超过攻略数量(${this.maxNum}`);
return;
}
let name = atlasToName(atlas);
if (!name) {
await this.reply('该角色不存在');
return;
}
if (group === 0) {
// eslint-disable-next-line no-unused-vars
let msg = [];
// eslint-disable-next-line no-unused-vars
for (let i = 1; i <= this.maxNum; i++) {
let guidePath = this.getGuidePath(i, name);
if (this.canGetImageFromFile(guidePath, isUpdate)) {
msg.push(segment.image(`file://${guidePath}`));
continue;
}
if (i <= this.maxForwardGuides && (await this.getImg(name, i))) {
msg.push(segment.image(`file://${guidePath}`));
}
}
if (msg.length) {
await this.reply(await common.makeForwardMsg(this.e, [msg]));
}
return false;
}
let guidePath = this.getGuidePath(group, name);
if (this.canGetImageFromFile(guidePath, isUpdate)) {
await this.e.reply(segment.image(`file://${guidePath}`));
return;
}
if (await this.getImg(name, group)) {
await this.e.reply(segment.image(`file://${guidePath}`));
}
}
/** 下载攻略图 */
async getImg(name, group) {
let mysRes = [];
this.collection_id[group].forEach(id =>
mysRes.push(this.getData(this.url + id))
);
try {
mysRes = await Promise.all(mysRes);
} catch (error) {
this.e.reply('暂无攻略数据,请稍后再试');
console.log(`米游社接口报错:${error}}`);
return false;
}
// 搜索时过滤特殊符号譬如「11号」
const filtered_name = name.replace(/[^\w\s]|_/g, '')
let posts = lodash.flatten(lodash.map(mysRes, item => item.data.posts));
let url, created_at, updated_at;
for (let val of posts) {
if (val.post.subject.replace(/【[^】]*本[^】]*】/g, '').includes(filtered_name)) {
let max = 0;
val.image_list.forEach((v, i) => {
if (
Number(v.size) >= Number(val.image_list[max].size) &&
v.format != 'gif' // 动图天生 size 会撑得很大
) {
max = i;
}
});
url = val.image_list[max].url;
created_at = val.post.created_at;
updated_at = val.post.updated_at;
break;
}
}
if (!url) {
this.e.reply(
`暂无${name}攻略 (${this.source[group - 1]})\n请尝试其他的攻略来源查询`
);
return false;
}
console.log(`${this.e.logFnc} 下载${name}攻略图 - ${this.source[group - 1]}`);
const download = await fetch(url);
const arrayBuffer = await download.arrayBuffer();
const buffer = Buffer.from(arrayBuffer);
let guidePath = this.getGuidePath(group, name);
fs.writeFileSync(guidePath, buffer);
console.log(`${this.e.logFnc} 下载${name}攻略成功 - ${this.source[group - 1]}`);
return true;
}
/** 获取数据 */
async getData(url) {
let response = await fetch(url, { method: 'get' });
if (!response.ok) {
return false;
}
return await response.json();
}
/** %攻略帮助 */
async GuideHelp () {
let reply_msg = [
'绝区零角色攻略帮助:',
'%艾莲攻略+攻略id',
'%更新艾莲攻略+攻略id',
'%设置默认攻略+攻略id',
'%设置所有攻略显示个数+攻略id',
'示例: %艾莲攻略2',
'',
'攻略来源:'
].concat(this.source.map((element, index) => `${index + 1}: ${element}`))
await this.e.reply(reply_msg.join('\n'))
}
setConfig(key, value) {
let config = fs.readFileSync(ZZZ_GUIDES_CONFIG_PATH, 'utf8')
let newREG = new RegExp(`^${key}: (.*)`, 'gm')
config = config.replace(newREG, `${key}: ${value}`)
fs.writeFileSync(ZZZ_GUIDES_CONFIG_PATH, config, 'utf8')
}
/** %设置默认攻略1 */
async SetDefaultGuide () {
let match = /设置默认攻略(\d+|all)$/g.exec(this.e.msg)
let guide_id = match[1]
if (guide_id == 'all') {
guide_id = 0
}
if (guide_id > this.maxNum) {
let reply_msg = [
'绝区零默认攻略设置方式为:',
'%设置默认攻略[0123...]',
`请增加数字0-${this.maxNum}其中一个,或者增加 all 以显示所有攻略`,
'攻略来源请输入 %攻略帮助 查看'
]
await this.e.reply(reply_msg.join('\n'))
return
}
this.setConfig('default_guide', guide_id)
let source_name = guide_id == 0 ? 'all' : this.source[guide_id - 1]
await this.e.reply(`绝区零默认攻略已设置为: ${guide_id} (${source_name})`)
}
/** %设置所有攻略显示个数3 */
async SetMaxForwardGuide () {
let match = /设置所有攻略显示个数(\d+)$/g.exec(this.e.msg)
let max_forward_guide = Number(match[1])
this.setConfig('max_forward_guides', max_forward_guide)
await this.e.reply(`绝区零所有攻略显示个数已设置为: ${max_forward_guide}`)
}
}