From 64275de0e8635e6815f052f5e31aa8cfc1601e24 Mon Sep 17 00:00:00 2001 From: bietiaop <1527109126@qq.com> Date: Thu, 1 Aug 2024 19:08:43 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=87=AA=E5=AE=9A=E4=B9=89=E8=A7=92?= =?UTF-8?q?=E8=89=B2=E5=9B=BE=E4=B8=8A=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/guide.js | 68 ++++------ apps/help.js | 16 ++- apps/manage.js | 301 +++--------------------------------------- apps/manage/alias.js | 44 ++++++ apps/manage/assets.js | 130 ++++++++++++++++++ apps/manage/config.js | 63 +++++++++ apps/manage/guides.js | 50 +++++++ apps/manage/index.js | 17 +++ apps/manage/panel.js | 97 ++++++++++++++ apps/panel.js | 13 +- lib/guides.js | 25 ++++ 11 files changed, 498 insertions(+), 326 deletions(-) create mode 100644 apps/manage/alias.js create mode 100644 apps/manage/assets.js create mode 100644 apps/manage/config.js create mode 100644 apps/manage/guides.js create mode 100644 apps/manage/index.js create mode 100644 apps/manage/panel.js create mode 100644 lib/guides.js diff --git a/apps/guide.js b/apps/guide.js index 1713966..d9892e8 100644 --- a/apps/guide.js +++ b/apps/guide.js @@ -10,6 +10,7 @@ import _ from 'lodash'; import settings from '../lib/settings.js'; import { downloadFile } from '../lib/download.js'; import { char } from '../lib/convert.js'; +import guides from '../lib/guides.js'; const ZZZ_GUIDES_PATH = path.join(imageResourcesPath, 'guides'); @@ -34,39 +35,13 @@ export class Guide extends ZZZPlugin { this.url = 'https://bbs-api.mihoyo.com/post/wapi/getPostFullInCollection?&gids=8&collection_id='; - this.collection_id = [ - [], - // 来源:新艾利都快讯 - [2712859], - [2727116], - [2721968], - [2724610], - [2722266], - [2723586], - [2716049], - ]; - this.source = [ - '新艾利都快讯', - '清茶沐沐Kiyotya', - '小橙子阿', - '猫冬', - '月光中心', - '苦雪的清心花凉糕Suki', - 'HoYo青枫', - ]; - // 最大攻略数量 - this.maxNum = this.source.length; - - // 最大显示攻略数量 - this.maxForwardGuides = _.get( - settings.getConfig('guide'), - 'max_forward_guides', - 4 - ); } getGuideFolder(groupIndex) { - let guideFolder = path.join(ZZZ_GUIDES_PATH, this.source[groupIndex - 1]); + let guideFolder = path.join( + ZZZ_GUIDES_PATH, + guides.guideSources[groupIndex - 1] + ); return guideFolder; } @@ -93,10 +68,14 @@ export class Guide extends ZZZPlugin { group = '0'; } group = Number(group); - if (group > this.maxNum) { - await this.reply(`超过攻略数量(${this.maxNum})`); + if (group > guides.guideMaxNum) { + await this.reply(`超过攻略数量(${guides.guideMaxNum})`); return false; } + if (alias === '设置默认' || alias === '设置所有') { + return false; + } + const name = char.aliasToName(alias); if (!name) { @@ -106,13 +85,18 @@ export class Guide extends ZZZPlugin { if (group === 0) { const msg = []; - for (let i = 1; i <= this.maxNum; i++) { + for ( + let i = 1; + i <= + Number(_.get(settings.getConfig('guide'), 'max_forward_guides', 4)); + i++ + ) { const guidePath = await this.getGuidePath(i, name, !!isUpdate); // msg.push(segment.image(`file://${guidePath}`)); if (guidePath) { msg.push(segment.image(guidePath)); } else { - msg.push(`暂无${name}攻略 (${this.source[i - 1]})`); + msg.push(`暂无${name}攻略 (${guides.guideSources[i - 1]})`); } } if (msg.length) { @@ -124,7 +108,9 @@ export class Guide extends ZZZPlugin { const guidePath = await this.getGuidePath(group, name, !!isUpdate); if (!guidePath) { this.e.reply( - `暂无${name}攻略 (${this.source[group - 1]})\n请尝试其他的攻略来源查询` + `暂无${name}攻略 (${ + guides.guideSources[group - 1] + })\n请尝试其他的攻略来源查询` ); return false; } @@ -135,7 +121,7 @@ export class Guide extends ZZZPlugin { /** 下载攻略图 */ async getImg(name, group) { let mysRes = []; - this.collection_id[group].forEach(id => + guides.collection_id[group].forEach(id => mysRes.push(this.getData(this.url + id)) ); @@ -150,7 +136,7 @@ export class Guide extends ZZZPlugin { // 搜索时过滤特殊符号,譬如「11号」 const filtered_name = name.replace(/[^a-zA-Z0-9\u4e00-\u9fa5]/g, ''); let posts = lodash.flatten(lodash.map(mysRes, item => item.data.posts)); - let url, created_at, updated_at; + let url; for (const val of posts) { if ( val.post.subject @@ -176,7 +162,7 @@ export class Guide extends ZZZPlugin { return false; } logger.debug( - `${this.e.logFnc} 下载${name}攻略图 - ${this.source[group - 1]}` + `${this.e.logFnc} 下载${name}攻略图 - ${guides.guideSources[group - 1]}` ); const filename = `role_guide_${name}.png`; @@ -184,7 +170,7 @@ export class Guide extends ZZZPlugin { const download = await downloadFile(url, guidePath); logger.debug( - `${this.e.logFnc} 下载${name}攻略成功 - ${this.source[group - 1]}` + `${this.e.logFnc} 下载${name}攻略成功 - ${guides.guideSources[group - 1]}` ); return download; @@ -210,7 +196,9 @@ export class Guide extends ZZZPlugin { '示例: %艾莲攻略2', '', '攻略来源:', - ].concat(this.source.map((element, index) => `${index + 1}: ${element}`)); + ].concat( + guides.guideSources.map((element, index) => `${index + 1}: ${element}`) + ); await this.e.reply(reply_msg.join('\n')); } } diff --git a/apps/help.js b/apps/help.js index c97cb26..29f1828 100644 --- a/apps/help.js +++ b/apps/help.js @@ -189,8 +189,8 @@ export class Help extends ZZZPlugin { commands: ['下载全部/所有资源'], }, { - title: '删除资源', - desc: '删除已经下载的资源,查询时需要再次下载(用于删除错误下载缓存)', + title: '删除资源(需注意)', + desc: '请注意,此命令会删除自定义面板图,请确认做好备份后再执行!!!删除已经下载的资源,查询时需要再次下载(用于删除错误下载缓存)。', needCK: false, needSK: false, commands: ['删除全部/所有资源'], @@ -244,6 +244,18 @@ export class Help extends ZZZPlugin { needSK: false, commands: ['删除别名+角色别名'], }, + { + title: '上传角色面板图', + desc: '上传自定义角色面板图,可以随消息附带图片,可以通过引用消息中的图片上传', + needCK: false, + needSK: false, + commands: [ + '上传+角色名+面板图', + '上传+角色名+角色图', + '添加+角色名+面板图', + '添加+角色名+角色图', + ], + }, ], }, ]; diff --git a/apps/manage.js b/apps/manage.js index fcf9bd1..26db293 100644 --- a/apps/manage.js +++ b/apps/manage.js @@ -1,19 +1,8 @@ import { ZZZPlugin } from '../lib/plugin.js'; import { rulePrefix } from '../lib/common.js'; -import { getAllEquipID } from '../lib/convert/equip.js'; -import { getAllWeaponID } from '../lib/convert/weapon.js'; -import { imageResourcesPath } from '../lib/path.js'; import settings from '../lib/settings.js'; -import fs from 'fs'; -import { - getRoleImage, - getSmallSquareAvatar, - getSquareAvatar, - getSuitImage, - getWeaponImage, -} from '../lib/download.js'; import _ from 'lodash'; -import { char } from '../lib/convert.js'; +import manage from './manage/index.js'; export class Panel extends ZZZPlugin { constructor() { @@ -32,295 +21,49 @@ export class Panel extends ZZZPlugin { fnc: 'deleteAll', }, { - reg: `^${rulePrefix}设置默认攻略(\\d+|all)$`, + reg: `${rulePrefix}设置默认攻略(\\d+|all)$`, fnc: 'setDefaultGuide', }, { - reg: `^${rulePrefix}设置所有攻略显示个数(\\d+)$`, + reg: `${rulePrefix}设置所有攻略显示个数(\\d+)$`, fnc: 'setMaxForwardGuide', }, { - reg: `^${rulePrefix}设置渲染精度(\\d+)$`, + reg: `${rulePrefix}设置渲染精度(\\d+)$`, fnc: 'setRenderPrecision', }, { - reg: `^${rulePrefix}刷新抽卡间隔(\\d+)$`, + reg: `${rulePrefix}刷新抽卡间隔(\\d+)$`, fnc: 'setRefreshGachaInterval', }, { - reg: `^${rulePrefix}刷新面板间隔(\\d+)$`, + reg: `${rulePrefix}刷新面板间隔(\\d+)$`, fnc: 'setRefreshPanelInterval', }, { - reg: `^${rulePrefix}添加(\\S+)别名(\\S+)$`, + reg: `${rulePrefix}添加(\\S+)别名(\\S+)$`, fnc: 'addAlias', }, { - reg: `^${rulePrefix}删除别名(\\S+)$`, + reg: `${rulePrefix}删除别名(\\S+)$`, fnc: 'deleteAlias', }, + { + reg: `${rulePrefix}(上传|添加)(\\S+)(角色|面板)图$`, + fnc: 'uploadCharacterImg', + }, ], }); - } - async downloadAll() { - if (!this.e.isMaster) return false; - const charIDs = char.getAllCharactersID(); - const equipSprites = getAllEquipID(); - const weaponSprites = getAllWeaponID(); - const result = { - char: { - success: 0, - failed: 0, - total: charIDs.length, - }, - charSmallSquare: { - success: 0, - failed: 0, - total: charIDs.length, - }, - charSquare: { - success: 0, - failed: 0, - total: charIDs.length, - }, - equip: { - success: 0, - failed: 0, - total: equipSprites.length, - }, - weapon: { - success: 0, - failed: 0, - total: weaponSprites.length, - }, - }; - await this.reply( - '开始下载资源,注意,仅支持下载面板的角色图、武器图、套装图,以及角色卡片的角色头像图。暂不支持下载邦布头像。' - ); - for (const id of charIDs) { - try { - await getSquareAvatar(id); - result.charSquare.success++; - } catch (error) { - logger.error('getSquareAvatar', id, error); - result.charSquare.failed++; - } - try { - await getSmallSquareAvatar(id); - result.charSmallSquare.success++; - } catch (error) { - logger.error('getSmallSquareAvatar', id, error); - result.charSmallSquare.failed++; - } - try { - await getRoleImage(id); - result.char.success++; - } catch (error) { - logger.error('getRoleImage', id, error); - result.char.failed++; - } - } - for (const sprite of equipSprites) { - try { - await getSuitImage(sprite); - result.equip.success++; - } catch (error) { - logger.error('getSuitImage', sprite, error); - result.equip.failed++; - } - } - for (const sprite of weaponSprites) { - try { - await getWeaponImage(sprite); - result.weapon.success++; - } catch (error) { - logger.error('getWeaponImage', sprite, error); - result.weapon.failed++; - } - } - const messages = [ - '资源下载完成(成功的包含先前下载的图片)', - '角色图需下载' + - charIDs.length + - '张,成功' + - result.char.success + - '张,失败' + - result.char.failed + - '张', - '角色头像图需下载' + - charIDs.length + - '张,成功' + - result.charSquare.success + - '张,失败' + - result.charSquare.failed + - '张', - '套装图需下载' + - equipSprites.length + - '张,成功' + - result.equip.success + - '张,失败' + - result.equip.failed + - '张', - '武器图需下载' + - weaponSprites.length + - '张,成功' + - result.weapon.success + - '张,失败' + - result.weapon.failed + - '张', - ]; - await this.reply(messages.join('\n')); - } - async deleteAll() { - if (!this.e.isMaster) return false; - await this.reply('【注意】正在删除所有资源图片,后续使用需要重新下载!'); - if (fs.existsSync(imageResourcesPath)) { - fs.rmSync(imageResourcesPath, { recursive: true }); - } - await this.reply('资源图片已删除!'); - } - /** 设置默认攻略 */ - async setDefaultGuide() { - if (!this.e.isMaster) { - this.reply('仅限主人设置'); - return false; - } - const match = /设置默认攻略(\d+|all)$/g.exec(this.e.msg); - let guide_id = match[1]; - if (guide_id == 'all') { - guide_id = 0; - } - guide_id = Number(guide_id); - if (guide_id > this.maxNum) { - const reply_msg = [ - '绝区零默认攻略设置方式为:', - '%设置默认攻略[0123...]', - `请增加数字0-${this.maxNum}其中一个,或者增加 all 以显示所有攻略`, - '攻略来源请输入 %攻略帮助 查看', - ]; - await this.e.reply(reply_msg.join('\n')); - return; - } - settings.setSingleConfig('guide', 'default_guide', guide_id); - - const source_name = guide_id == 0 ? 'all' : this.source[guide_id - 1]; - await this.e.reply(`绝区零默认攻略已设置为: ${guide_id} (${source_name})`); - } - - /** 设置所有攻略显示个数 */ - async setMaxForwardGuide() { - if (!this.e.isMaster) { - this.reply('仅限主人设置'); - return false; - } - const match = /设置所有攻略显示个数(\d+)$/g.exec(this.e.msg); - const max_forward_guide = Number(match[1]); - settings.setSingleConfig('guide', 'max_forward_guides', max_forward_guide); - await this.e.reply(`绝区零所有攻略显示个数已设置为: ${max_forward_guide}`); - } - - /** 设置渲染精度 */ - async setRenderPrecision() { - if (!this.e.isMaster) { - this.reply('仅限主人设置'); - return false; - } - const match = /渲染精度(\d+)$/g.exec(this.e.msg); - const render_precision = Number(match[1]); - if (render_precision < 50) { - await this.e.reply('渲染精度不能小于50'); - return false; - } - if (render_precision > 200) { - await this.e.reply('渲染精度不能大于200'); - return false; - } - settings.setSingleConfig('config', 'render', { - scale: render_precision, - }); - await this.e.reply(`绝区零渲染精度已设置为: ${render_precision}`); - } - - /** 设置刷新抽卡间隔 */ - async setRefreshGachaInterval() { - if (!this.e.isMaster) { - this.reply('仅限主人设置'); - return false; - } - const match = /刷新抽卡间隔(\d+)$/g.exec(this.e.msg); - const refresh_gacha_interval = Number(match[1]); - if (refresh_gacha_interval < 0) { - await this.e.reply('刷新抽卡间隔不能小于0秒'); - return false; - } - if (refresh_gacha_interval > 1000) { - await this.e.reply('刷新抽卡间隔不能大于1000秒'); - return false; - } - settings.setSingleConfig('gacha', 'interval', refresh_gacha_interval); - await this.e.reply(`绝区零刷新抽卡间隔已设置为: ${refresh_gacha_interval}`); - } - - /** 设置刷新面板间隔 */ - async setRefreshPanelInterval() { - if (!this.e.isMaster) { - this.reply('仅限主人设置'); - return false; - } - const match = /刷新面板间隔(\d+)$/g.exec(this.e.msg); - const refresh_panel_interval = Number(match[1]); - if (refresh_panel_interval < 0) { - await this.e.reply('刷新面板间隔不能小于0秒'); - return false; - } - if (refresh_panel_interval > 1000) { - await this.e.reply('刷新面板间隔不能大于1000秒'); - return false; - } - settings.setSingleConfig('panel', 'interval', refresh_panel_interval); - await this.e.reply(`绝区零刷新面板间隔已设置为: ${refresh_panel_interval}`); - } - - async addAlias() { - if (!this.e.isMaster) { - this.reply('仅限主人设置'); - return false; - } - const match = /添加(\S+)别名(\S+)$/g.exec(this.e.msg); - const key = match[1]; - const value = match[2]; - const oriName = char.aliasToName(key); - const isExist = char.aliasToName(value); - if (!oriName) { - await this.e.reply(`未找到 ${value} 的对应角色`); - return; - } - if (isExist) { - await this.e.reply(`别名 ${value} 已存在`); - return; - } - settings.addArrayleConfig('alias', oriName, value); - await this.e.reply(`角色 ${key} 别名 ${value} 成功`); - } - - async deleteAlias() { - if (!this.e.isMaster) { - this.reply('仅限主人设置'); - return false; - } - const match = /删除别名(\S+)$/g.exec(this.e.msg); - const key = match[1]; - const oriName = char.aliasToName(key); - if (!oriName) { - await this.e.reply(`未找到 ${key} 的对应角色`); - return; - } - if (key === oriName) { - await this.e.reply(`别名 ${key} 为角色本名,无法删除`); - return; - } - settings.removeArrayleConfig('alias', oriName, key); - await this.e.reply(`角色 ${key} 别名删除成功`); + this.downloadAll = manage.assets.downloadAll; + this.deleteAll = manage.assets.deleteAll; + this.setDefaultGuide = manage.guides.setDefaultGuide; + this.setMaxForwardGuide = manage.guides.setMaxForwardGuide; + this.setRenderPrecision = manage.config.setRenderPrecision; + this.setRefreshGachaInterval = manage.config.setRefreshGachaInterval; + this.setRefreshPanelInterval = manage.config.setRefreshPanelInterval; + this.addAlias = manage.alias.addAlias; + this.deleteAlias = manage.alias.deleteAlias; + this.uploadCharacterImg = manage.panel.uploadCharacterImg; } } diff --git a/apps/manage/alias.js b/apps/manage/alias.js new file mode 100644 index 0000000..34a7389 --- /dev/null +++ b/apps/manage/alias.js @@ -0,0 +1,44 @@ +import { char } from '../../lib/convert.js'; +import settings from '../../lib/settings.js'; + +export async function addAlias() { + if (!this.e.isMaster) { + this.reply('仅限主人设置'); + return false; + } + const match = /添加(\S+)别名(\S+)$/g.exec(this.e.msg); + const key = match[1]; + const value = match[2]; + const oriName = char.aliasToName(key); + const isExist = char.aliasToName(value); + if (!oriName) { + await this.e.reply(`未找到 ${value} 的对应角色`); + return; + } + if (isExist) { + await this.e.reply(`别名 ${value} 已存在`); + return; + } + settings.addArrayleConfig('alias', oriName, value); + await this.e.reply(`角色 ${key} 别名 ${value} 成功`); +} + +export async function deleteAlias() { + if (!this.e.isMaster) { + this.reply('仅限主人设置'); + return false; + } + const match = /删除别名(\S+)$/g.exec(this.e.msg); + const key = match[1]; + const oriName = char.aliasToName(key); + if (!oriName) { + await this.e.reply(`未找到 ${key} 的对应角色`); + return; + } + if (key === oriName) { + await this.e.reply(`别名 ${key} 为角色本名,无法删除`); + return; + } + settings.removeArrayleConfig('alias', oriName, key); + await this.e.reply(`角色 ${key} 别名删除成功`); +} diff --git a/apps/manage/assets.js b/apps/manage/assets.js new file mode 100644 index 0000000..c7ecbe6 --- /dev/null +++ b/apps/manage/assets.js @@ -0,0 +1,130 @@ +import fs from 'fs'; +import { + getRoleImage, + getSmallSquareAvatar, + getSquareAvatar, + getSuitImage, + getWeaponImage, +} from '../../lib/download.js'; +import { char } from '../../lib/convert.js'; +import { getAllEquipID } from '../../lib/convert/equip.js'; +import { getAllWeaponID } from '../../lib/convert/weapon.js'; +import { imageResourcesPath } from '../../lib/path.js'; + +export async function downloadAll() { + if (!this.e.isMaster) return false; + const charIDs = char.getAllCharactersID(); + const equipSprites = getAllEquipID(); + const weaponSprites = getAllWeaponID(); + const result = { + char: { + success: 0, + failed: 0, + total: charIDs.length, + }, + charSmallSquare: { + success: 0, + failed: 0, + total: charIDs.length, + }, + charSquare: { + success: 0, + failed: 0, + total: charIDs.length, + }, + equip: { + success: 0, + failed: 0, + total: equipSprites.length, + }, + weapon: { + success: 0, + failed: 0, + total: weaponSprites.length, + }, + }; + await this.reply( + '开始下载资源,注意,仅支持下载面板的角色图、武器图、套装图,以及角色卡片的角色头像图。暂不支持下载邦布头像。' + ); + for (const id of charIDs) { + try { + await getSquareAvatar(id); + result.charSquare.success++; + } catch (error) { + logger.error('getSquareAvatar', id, error); + result.charSquare.failed++; + } + try { + await getSmallSquareAvatar(id); + result.charSmallSquare.success++; + } catch (error) { + logger.error('getSmallSquareAvatar', id, error); + result.charSmallSquare.failed++; + } + try { + await getRoleImage(id); + result.char.success++; + } catch (error) { + logger.error('getRoleImage', id, error); + result.char.failed++; + } + } + for (const sprite of equipSprites) { + try { + await getSuitImage(sprite); + result.equip.success++; + } catch (error) { + logger.error('getSuitImage', sprite, error); + result.equip.failed++; + } + } + for (const sprite of weaponSprites) { + try { + await getWeaponImage(sprite); + result.weapon.success++; + } catch (error) { + logger.error('getWeaponImage', sprite, error); + result.weapon.failed++; + } + } + const messages = [ + '资源下载完成(成功的包含先前下载的图片)', + '角色图需下载' + + charIDs.length + + '张,成功' + + result.char.success + + '张,失败' + + result.char.failed + + '张', + '角色头像图需下载' + + charIDs.length + + '张,成功' + + result.charSquare.success + + '张,失败' + + result.charSquare.failed + + '张', + '套装图需下载' + + equipSprites.length + + '张,成功' + + result.equip.success + + '张,失败' + + result.equip.failed + + '张', + '武器图需下载' + + weaponSprites.length + + '张,成功' + + result.weapon.success + + '张,失败' + + result.weapon.failed + + '张', + ]; + await this.reply(messages.join('\n')); +} +export async function deleteAll() { + if (!this.e.isMaster) return false; + await this.reply('【注意】正在删除所有资源图片,后续使用需要重新下载!'); + if (fs.existsSync(imageResourcesPath)) { + fs.rmSync(imageResourcesPath, { recursive: true }); + } + await this.reply('资源图片已删除!'); +} diff --git a/apps/manage/config.js b/apps/manage/config.js new file mode 100644 index 0000000..68aa53e --- /dev/null +++ b/apps/manage/config.js @@ -0,0 +1,63 @@ +import settings from '../../lib/settings.js'; + +/** 设置渲染精度 */ +export async function setRenderPrecision() { + if (!this.e.isMaster) { + this.reply('仅限主人设置'); + return false; + } + const match = /渲染精度(\d+)$/g.exec(this.e.msg); + const render_precision = Number(match[1]); + if (render_precision < 50) { + await this.e.reply('渲染精度不能小于50'); + return false; + } + if (render_precision > 200) { + await this.e.reply('渲染精度不能大于200'); + return false; + } + settings.setSingleConfig('config', 'render', { + scale: render_precision, + }); + await this.e.reply(`绝区零渲染精度已设置为: ${render_precision}`); +} + +/** 设置刷新抽卡间隔 */ +export async function setRefreshGachaInterval() { + if (!this.e.isMaster) { + this.reply('仅限主人设置'); + return false; + } + const match = /刷新抽卡间隔(\d+)$/g.exec(this.e.msg); + const refresh_gacha_interval = Number(match[1]); + if (refresh_gacha_interval < 0) { + await this.e.reply('刷新抽卡间隔不能小于0秒'); + return false; + } + if (refresh_gacha_interval > 1000) { + await this.e.reply('刷新抽卡间隔不能大于1000秒'); + return false; + } + settings.setSingleConfig('gacha', 'interval', refresh_gacha_interval); + await this.e.reply(`绝区零刷新抽卡间隔已设置为: ${refresh_gacha_interval}`); +} + +/** 设置刷新面板间隔 */ +export async function setRefreshPanelInterval() { + if (!this.e.isMaster) { + this.reply('仅限主人设置'); + return false; + } + const match = /刷新面板间隔(\d+)$/g.exec(this.e.msg); + const refresh_panel_interval = Number(match[1]); + if (refresh_panel_interval < 0) { + await this.e.reply('刷新面板间隔不能小于0秒'); + return false; + } + if (refresh_panel_interval > 1000) { + await this.e.reply('刷新面板间隔不能大于1000秒'); + return false; + } + settings.setSingleConfig('panel', 'interval', refresh_panel_interval); + await this.e.reply(`绝区零刷新面板间隔已设置为: ${refresh_panel_interval}`); +} diff --git a/apps/manage/guides.js b/apps/manage/guides.js new file mode 100644 index 0000000..ab92eab --- /dev/null +++ b/apps/manage/guides.js @@ -0,0 +1,50 @@ +import guides from '../../lib/guides.js'; +import settings from '../../lib/settings.js'; + +/** 设置默认攻略 */ +export async function setDefaultGuide() { + if (!this.e.isMaster) { + this.reply('仅限主人设置'); + return false; + } + const match = /设置默认攻略(\d+|all)$/g.exec(this.e.msg); + let guide_id = match[1]; + if (guide_id == 'all') { + guide_id = 0; + } + guide_id = Number(guide_id); + if (guide_id > guides.guideMaxNum) { + const reply_msg = [ + '绝区零默认攻略设置方式为:', + '%设置默认攻略[0123...]', + `请增加数字0-${guides.guideMaxNum}其中一个,或者增加 all 以显示所有攻略`, + '攻略来源请输入 %攻略帮助 查看', + ]; + await this.e.reply(reply_msg.join('\n')); + return; + } + settings.setSingleConfig('guide', 'default_guide', guide_id); + + const source_name = guide_id == 0 ? 'all' : this.source[guide_id - 1]; + await this.e.reply(`绝区零默认攻略已设置为: ${guide_id} (${source_name})`); +} + +/** 设置所有攻略显示个数 */ +export async function setMaxForwardGuide() { + if (!this.e.isMaster) { + this.reply('仅限主人设置'); + return false; + } + const match = /设置所有攻略显示个数(\d+)$/g.exec(this.e.msg); + const max_forward_guide = Number(match[1]); + if (max_forward_guide < 1) { + await this.e.reply('所有攻略显示个数不能小于1'); + return false; + } + if (max_forward_guide > guides.guideMaxNum) { + await this.e.reply(`所有攻略显示个数不能大于${guides.guideMaxNum}`); + return false; + } + settings.setSingleConfig('guide', 'max_forward_guides', max_forward_guide); + await this.e.reply(`绝区零所有攻略显示个数已设置为: ${max_forward_guide}`); +} diff --git a/apps/manage/index.js b/apps/manage/index.js new file mode 100644 index 0000000..4ce3760 --- /dev/null +++ b/apps/manage/index.js @@ -0,0 +1,17 @@ +import * as assets from './assets.js'; + +import * as guides from './guides.js'; + +import * as config from './config.js'; + +import * as alias from './alias.js'; + +import * as panel from './panel.js'; + +export default { + assets, + guides, + config, + alias, + panel, +}; diff --git a/apps/manage/panel.js b/apps/manage/panel.js new file mode 100644 index 0000000..d9aa764 --- /dev/null +++ b/apps/manage/panel.js @@ -0,0 +1,97 @@ +import { char } from '../../lib/convert.js'; +import { downloadFile } from '../../lib/download.js'; +import { imageResourcesPath } from '../../lib/path.js'; +import path from 'path'; +export async function uploadCharacterImg() { + if (!this.e.isMaster) { + this.reply('只有主人才能添加...'); + return false; + } + const reg = /(上传|添加)(.+)(角色|面板)图$/; + const match = this.e.msg.match(reg); + if (!match) { + return false; + } + const charName = match[2].trim(); + const name = char.aliasToName(charName); + const images = []; + // 下面方法来源于miao-plugin/apps/character/ImgUpload.js + for (const val of this.e.message) { + if (val.type === 'image') { + images.push(val); + } + } + if (images.length === 0) { + let source; + if (this.e.getReply) { + source = await this.e.getReply(); + } else if (this.e.source) { + if (this.e.group?.getChatHistory) { + // 支持at图片添加,以及支持后发送 + source = ( + await this.e.group.getChatHistory(this.e.source?.seq, 1) + ).pop(); + } else if (this.e.friend?.getChatHistory) { + source = ( + await this.e.friend.getChatHistory(this.e.source?.time + 1, 1) + ).pop(); + } + } + if (source) { + for (const val of source.message) { + if (val.type === 'image') { + images.push(val); + } else if (val.type === 'xml' || val.type === 'forward') { + let resid; + try { + resid = val.data + .match(/m_resid="(\d|\w|\/|\+)*"/)[0] + .replace(/m_resid=|"/g, ''); + } catch (err) { + resid = val.id; + } + if (!resid) break; + let message = await this.e.bot.getForwardMsg(resid); + for (const item of message) { + for (const i of item.message) { + if (i.type === 'image') { + images.push(i); + } + } + } + } + } + } + } + logger.debug('images', images); + if (images.length <= 0) { + this.reply( + '消息中未找到图片,请将要发送的图片与消息一同发送或引用要添加的图像。' + ); + return false; + } + const resourcesImagesPath = imageResourcesPath; + const panelImagesPath = path.join(resourcesImagesPath, `panel/${name}`); + let success = 0; + let failed = 0; + for (const image of images) { + let fileName = new Date().getTime().toString(); + let fileType = 'png'; + if (val.file) { + fileName = val.file.substring(0, val.file.lastIndexOf('.')); + fileType = val.file.substring(val.file.lastIndexOf('.') + 1); + } + if (response.headers.get('content-type') === 'image/gif') { + fileType = 'gif'; + } + const filePath = path.join(panelImagesPath, `${fileName}.${fileType}`); + const result = await downloadFile(image.url, filePath); + if (result) { + success++; + } else { + failed++; + } + } + this.reply(`成功上传${success}张图片,失败${failed}张图片。`); + return false; +} diff --git a/apps/panel.js b/apps/panel.js index 10a52d0..1727f0b 100644 --- a/apps/panel.js +++ b/apps/panel.js @@ -30,9 +30,11 @@ export class Panel extends ZZZPlugin { const pre = this.e.msg.match(reg)[4].trim(); const suf = this.e.msg.match(reg)[5].trim(); if (['刷新', '更新'].includes(pre) || ['刷新', '更新'].includes(suf)) - return this.refreshPanel(); - if (!pre || suf === '列表') return this.getCharPanelList(); - return this.getCharPanel(); + return await this.refreshPanel(); + if (!pre || suf === '列表') return await this.getCharPanelList(); + const queryPanelReg = new RegExp(`${rulePrefix}(.*)面板$`); + if (queryPanelReg.test(this.e.msg)) return await this.getCharPanel(); + return false; } async refreshPanel() { @@ -90,8 +92,9 @@ export class Panel extends ZZZPlugin { const uid = await this.getUID(); if (!uid) return false; const reg = new RegExp(`${rulePrefix}(.+)面板$`); - const name = this.e.msg.match(reg)[4]; - if (['刷新', '更新'].includes(name)) return this.getCharPanelList(); + const match = this.e.msg.match(reg); + if (!match) return false; + const name = match[4]; const data = getPanel(uid, name); if (!data) { await this.reply(`未找到角色${name}的面板信息,请先刷新面板`); diff --git a/lib/guides.js b/lib/guides.js new file mode 100644 index 0000000..a57c174 --- /dev/null +++ b/lib/guides.js @@ -0,0 +1,25 @@ +export default { + guideSources: [ + '新艾利都快讯', + '清茶沐沐Kiyotya', + '小橙子阿', + '猫冬', + '月光中心', + '苦雪的清心花凉糕Suki', + 'HoYo青枫', + ], + collection_id: [ + [], + // 来源:新艾利都快讯 + [2712859], + [2727116], + [2721968], + [2724610], + [2722266], + [2723586], + [2716049], + ], + get guideMaxNum() { + return this.guideSources.length; + }, +};