diff --git a/.gitignore b/.gitignore index 04d30eb..9906885 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ node_modules/ data/ *_test.js test.* -*.log \ No newline at end of file +*.log +.vscode/ \ No newline at end of file diff --git a/README.md b/README.md index 6904b18..c489896 100644 --- a/README.md +++ b/README.md @@ -207,6 +207,7 @@ A:请参考[此教程](https://docs.qq.com/doc/p/108e5d788607d988ac62e1512552c - [Yunzai-Bot](https://gitee.com/Le-niao/Yunzai-Bot) - [cq-picsearcher-bot](https://github.com/Tsuk1ko/cq-picsearcher-bot) - [nonebot-plugin-picstatus](https://github.com/lgc2333/nonebot-plugin-picstatus) +- [HibiAPI](https://github.com/mixmoe/HibiAPI) - [SauceNAO](https://saucenao.com/) - [Ascii2D](https://ascii2d.net/) - [trace.moe](https://trace.moe) ([GitHub](https://github.com/soruly/trace.moe)) diff --git a/apps/groupAdmin.js b/apps/groupAdmin.js index 2840bd0..d8e6ce8 100644 --- a/apps/groupAdmin.js +++ b/apps/groupAdmin.js @@ -332,12 +332,12 @@ export class GroupAdmin extends plugin { '啾咪٩(๑•̀ω•́๑)۶', '弃旧恋新了么笨蛋( 。ớ ₃ờ)ھ' ] - // if (!e.group.is_owner) return false + if (!e.group.is_owner) return false let Title = e.msg.replace(/#|申请头衔/g, '') // 屏蔽词处理 - let { Match_pattern, Shielding_words } = Config.NoTitle - console.log(Shielding_words) + let { Match_pattern, Shielding_words } = Config.groupTitle + Shielding_words = _.compact(Shielding_words) if (!e.isMaster && !_.isEmpty(Shielding_words)) { if (Match_pattern) { diff --git a/apps/groupVerify.js b/apps/groupVerify.js index b9548f3..0a97c8c 100644 --- a/apps/groupVerify.js +++ b/apps/groupVerify.js @@ -36,7 +36,7 @@ export class NewGroupVerify extends plugin { } ] }) - this.verifycfg = Config.verifycfg + this.verifycfg = Config.groupverify } // 重新验证 @@ -133,7 +133,7 @@ export class NewGroupVerify extends plugin { // 进群监听 Bot.on('notice.group.increase', async (e) => { logger.mark(`[椰奶][进群验证]收到${e.user_id}的进群事件`) - let { openGroup, DelayTime } = Config.verifycfg + let { openGroup, DelayTime } = Config.groupverify if (!openGroup.includes(e.group_id)) return if (!e.group.is_admin && !e.group.is_owner) return @@ -146,7 +146,7 @@ Bot.on('notice.group.increase', async (e) => { // 答案监听 Bot.on('message.group', async (e) => { - let { openGroup, mode, SuccessMsgs } = Config.verifycfg + let { openGroup, mode, SuccessMsgs } = Config.groupverify if (!openGroup.includes(e.group_id)) return @@ -210,7 +210,7 @@ async function verify (user_id, group_id, e) { group_id = Number(group_id) logger.mark(`[椰奶][进群验证]进行${user_id}的验证`) - const { times, range, time, remindAtLastMinute } = Config.verifycfg + const { times, range, time, remindAtLastMinute } = Config.groupverify const operator = ops[_.random(0, 1)] let [m, n] = [_.random(range.min, range.max), _.random(range.min, range.max)] diff --git a/apps/picSearch.js b/apps/picSearch.js index d5dca80..404dbc8 100644 --- a/apps/picSearch.js +++ b/apps/picSearch.js @@ -1,7 +1,7 @@ import { PicSearch, common } from '../model/index.js' import { Config } from '../components/index.js' import _ from 'lodash' -export class newPicSearch extends plugin { +export class NewPicSearch extends plugin { constructor () { super({ name: '椰奶图片搜索', @@ -10,7 +10,11 @@ export class newPicSearch extends plugin { rule: [ { reg: '^#?(椰奶)?(以图)?搜图.*$', - fnc: 'search' + fnc: 'SauceNAO' + }, + { + reg: /^#?(SauceNAO|sn)搜图.*$/i, + fnc: 'SauceNAO' }, { reg: '^#?(椰奶)?(以图)?搜番.*$', @@ -23,18 +27,74 @@ export class newPicSearch extends plugin { { reg: /^#?(Ascii2D|ac)搜图.*$/i, fnc: 'Ascii2D' - }, - { - reg: /^#?(SauceNAO|sn)搜图.*$/i, - fnc: 'SauceNAO' } ] }) } - async search (e) { + async SauceNAO (e) { + if (!await this.Authentication(e)) return if (!await this.handelImg(e, 'SauceNAO')) return - await this.SauceNAO(e) + await PicSearch.SauceNAO(e.img[0]) + .then(async res => { + res.maxSimilarity > 80 + ? common.recallsendMsg(e, res.message, true) + : common.getRecallsendMsg(e, res.message) + if (res.maxSimilarity < Config.picSearch.SauceNAOMinSim) { + e.reply(`SauceNAO 相似度 ${res.maxSimilarity}% 过低,使用Ascii2D进行搜索`) + await this.Ascii2D(e) + } + }) + .catch(async err => { + await e.reply(err.message) + await e.reply('SauceNAO搜图出错,自动使用Ascii2D进行搜索') + await this.Ascii2D(e) + }) + } + + async Ascii2D (e) { + if (!await this.Authentication(e)) return + if (!await this.handelImg(e, 'Ascii2D')) return + await PicSearch.Ascii2D(e.img[0]) + .then(res => { + common.getRecallsendMsg(e, res.color, { isxmlMsg: false }) + common.getRecallsendMsg(e, res.bovw, { isxmlMsg: false }) + }) + .catch(err => e.reply(err.message)) + } + + async WhatAnime (e) { + if (!await this.Authentication(e)) return + if (!await this.handelImg(e, 'WhatAnime')) return + await PicSearch.WhatAnime(e.img[0]) + .then(async res => { + for (let i of res) { + await e.reply(i) + } + }) + .catch(err => e.reply(err.message)) + } + + async UploadSauceNAOKey (e) { + if (!e.isMaster) return false + if (e.isGroup) return e.reply('请私聊进行添加') + let apiKey = e.msg.replace(/#?SauceNAOapiKey/i, '').trim() + if (!apiKey) return e.reply('❎ 请发送正确的apikey') + Config.modify('picSearch', 'SauceNAOApiKey', apiKey) + e.reply('OK') + } + + async Authentication (e) { + if (e.isMaster) return true + if (!Config.picSearch.allowPM && !e.isGroup) { + e.reply('主人已禁用私聊该功能') + return false + } + if (!await common.limit(e.user_id, 'PicSearch', Config.picSearch.limit)) { + e.reply('[PicSearch]您已达今日次数上限', true, { at: true }) + return false + } + return true } async handelImg (e, funName) { @@ -62,53 +122,4 @@ export class newPicSearch extends plugin { } this.finish('MonitorImg') } - - async SauceNAO (e) { - if (!await this.handelImg(e, 'SauceNAO')) return - await PicSearch.SauceNAO(e.img[0]) - .then(async res => { - res.maxSimilarity > 80 - ? common.recallsendMsg(e, res.message, true) - : common.getRecallsendMsg(e, res.message) - if (res.maxSimilarity < Config.picSearch.SauceNAOMinSim) { - e.reply(`SauceNAO 相似度 ${res.maxSimilarity}% 过低,使用Ascii2D进行搜索`) - await this.Ascii2D(e) - } - }) - .catch(async err => { - await e.reply(err.message) - await e.reply('SauceNAO搜图出错,自动使用Ascii2D进行搜索') - await this.Ascii2D(e) - }) - } - - async Ascii2D (e) { - if (!await this.handelImg(e, 'Ascii2D')) return - await PicSearch.Ascii2D(e.img[0]) - .then(res => { - common.getRecallsendMsg(e, res.color, { isxmlMsg: false }) - common.getRecallsendMsg(e, res.bovw, { isxmlMsg: false }) - }) - .catch(err => e.reply(err.message)) - } - - async WhatAnime (e) { - if (!await this.handelImg(e, 'WhatAnime')) return - await PicSearch.WhatAnime(e.img[0]) - .then(async res => { - for (let i of res) { - await e.reply(i) - } - }) - .catch(err => e.reply(err.message)) - } - - async UploadSauceNAOKey (e) { - if (!e.isMaster) return false - if (e.isGroup) return e.reply('请私聊进行添加') - let apiKey = e.msg.replace(/#?SauceNAOapiKey/i, '').trim() - if (!apiKey) return e.reply('❎ 请发送正确的apikey') - Config.modify('picSearch', 'SauceNAOApiKey', apiKey) - e.reply('OK') - } } diff --git a/apps/pixiv.js b/apps/pixiv.js index d1ad4b6..6661d7d 100644 --- a/apps/pixiv.js +++ b/apps/pixiv.js @@ -74,83 +74,72 @@ export class NewPixiv extends plugin { // pid搜图 async searchPid (e) { - let { sese, sesepro } = Config.getGroup(e.group_id) - if (!sese && !sesepro && !e.isMaster) return e.reply(SWITCH_ERROR) + if (!await this.Authentication(e, 'sese')) return e.reply(Pixiv.startMsg) let regRet = pidReg.exec(e.msg) - let res = await Pixiv.illust(regRet[1], !e.isMaster && !setu.getR18(e.group_id)).catch(err => { e.reply(err.message) }) - if (!res) return - let { msg, img } = res - await e.reply(msg) - img.length == 1 ? common.recallsendMsg(e, img) : common.getRecallsendMsg(e, img, false) + await Pixiv.illust(regRet[1], !e.isMaster && !setu.getR18(e.group_id)) + .then(async res => { + await e.reply(res.msg) + res.img.length == 1 ? common.recallsendMsg(e, res.img) : common.getRecallsendMsg(e, res.img, false) + }) + .catch(err => e.reply(err.message)) } // p站排行榜 async pixivRanking (e) { + if (!await this.Authentication(e, 'sese')) return let regRet = rankingrReg.exec(e.msg) - let { sese, sesepro } = Config.getGroup(e.group_id) - if (((!sese && !sesepro) || (regRet[4] && !setu.getR18(e.group_id))) && !e.isMaster) { - return e.reply(SWITCH_ERROR) - } + if ((regRet[4] && !setu.getR18(e.group_id)) && !e.isMaster) return e.reply(SWITCH_ERROR) + e.reply(Pixiv.startMsg) let page = common.translateChinaNum(regRet[6]) - let res = await Pixiv.Rank(page, regRet[2], regRet[3], regRet[4]).catch(err => { e.reply(err.message) }) - if (!res) return - - common.getRecallsendMsg(e, res) + await Pixiv.Rank(page, regRet[2], regRet[3], regRet[4]) + .then(res => common.getRecallsendMsg(e, res)) + .catch(err => e.reply(err.message)) } /** 关键词搜图 */ async searchTags (e) { let regRet = tagReg.exec(e.msg) - - let { sese, sesepro } = Config.getGroup(e.group_id) - if (((!sese && !sesepro) || (!sesepro && regRet[1])) && !e.isMaster) return e.reply(SWITCH_ERROR) + if (!await this.Authentication(e, 'sese')) return + if (!await this.Authentication(e, 'sesepro') && regRet[1]) return e.reply(Pixiv.startMsg) let page = common.translateChinaNum(regRet[4]) - let res = await Pixiv[`searchTags${regRet[1] ? 'pro' : ''}`](regRet[2], page, !setu.getR18(e.group_id)) - .catch(err => { e.reply(err.message) }) - if (!res) return - common.getRecallsendMsg(e, res) + await Pixiv[`searchTags${regRet[1] ? 'pro' : ''}`](regRet[2], page, !setu.getR18(e.group_id)) + .then(res => common.getRecallsendMsg(e, res)) + .catch(err => e.reply(err.message)) } /** 获取热门tag */ async PopularTags (e) { - let { sese, sesepro } = Config.getGroup(e.group_id) - if (!sese && !sesepro && !e.isMaster) return e.reply(SWITCH_ERROR) - + if (!await this.Authentication(e, 'sese')) return e.reply(Pixiv.startMsg) - - let res = await Pixiv.PopularTags().catch(err => { e.reply(err.message) }) - if (!res) return - common.getRecallsendMsg(e, res) + await Pixiv.PopularTags() + .then(res => common.getRecallsendMsg(e, res)) + .catch(err => e.reply(err.message)) } /** 以uid搜图**/ async searchUid (e) { - let { sese, sesepro } = Config.getGroup(e.group_id) - if (!sese && !sesepro && !e.isMaster) return e.reply(SWITCH_ERROR) + if (!await this.Authentication(e, 'sese')) return e.reply(Pixiv.startMsg) let regRet = uidReg.exec(e.msg) let page = common.translateChinaNum(regRet[3]) - let res = await Pixiv.userIllust(regRet[1], page, !setu.getR18(e.group_id)).catch(err => { e.reply(err.message) }) - if (!res) return - common.getRecallsendMsg(e, res) + await Pixiv.userIllust(regRet[1], page, !setu.getR18(e.group_id)) + .then(res => common.getRecallsendMsg(e, res)) + .catch(err => e.reply(err.message)) } // 随机原创插画 async randomImg (e) { - let { sese, sesepro } = Config.getGroup(e.group_id) - if (!sese && !sesepro && !e.isMaster) return e.reply(SWITCH_ERROR) - + if (!await this.Authentication(e, 'sese')) return e.reply(Pixiv.startMsg) - let regRet = randomImgReg.exec(e.msg) let num = regRet[1] || 1 @@ -159,48 +148,44 @@ export class NewPixiv extends plugin { num = 1 } num = common.translateChinaNum(num) - let res = await Pixiv.randomImg(num).catch(err => { e.reply(err.message) }) - if (!res) return - common.getRecallsendMsg(e, res) + await Pixiv.randomImg(num) + .then(res => common.getRecallsendMsg(e, res)) + .catch(err => e.reply(err.message)) } // 相关作品 async related (e) { - let { sese, sesepro } = Config.getGroup(e.group_id) - if (!sese && !sesepro && !e.isMaster) return e.reply(SWITCH_ERROR) + if (!await this.Authentication(e, 'sese')) return e.reply(Pixiv.startMsg) let regRet = e.msg.match(/\d+/) - let res = await Pixiv.related(regRet[0], !setu.getR18(e.group_id)).catch(err => { e.reply(err.message) }) - if (!res) return - common.getRecallsendMsg(e, res) + await Pixiv.related(regRet[0], !setu.getR18(e.group_id)) + .then(res => common.getRecallsendMsg(e, res)) + .catch(err => e.reply(err.message)) } // p站单图 async pximg (e) { let ispro = /pro/.test(e.msg) + if (!await this.Authentication(e, 'sese')) return + if (!await this.Authentication(e, 'sesepro') && ispro) return - let { sese, sesepro } = Config.getGroup(e.group_id) - if (((!sese && !sesepro) || (!sesepro && ispro)) && !e.isMaster) return e.reply(SWITCH_ERROR) - - let res = await Pixiv.pximg(ispro).catch(err => { e.reply(err.message) }) - if (!res) return - ispro ? common.getRecallsendMsg(e, [res]) : common.recallsendMsg(e, res) + await Pixiv.pximg(ispro) + .then(res => ispro ? common.getRecallsendMsg(e, [res]) : common.recallsendMsg(e, res)) + .catch(err => e.reply(err.message)) } /** 搜索用户 */ async searchUser (e) { - let { sese, sesepro } = Config.getGroup(e.group_id) - if (!sese && !sesepro && !e.isMaster) return e.reply(SWITCH_ERROR) + if (!await this.Authentication(e, 'sese')) return e.reply(Pixiv.startMsg) let regRet = e.msg.match(searchUser) let page = common.translateChinaNum(regRet[3]) - let res = await Pixiv.searchUser(regRet[1], page, !setu.getR18(e.group_id)).catch(err => { e.reply(err.message) }) - if (!res) return - - common.getRecallsendMsg(e, res) + await Pixiv.searchUser(regRet[1], page, !setu.getR18(e.group_id)) + .then(res => common.getRecallsendMsg(e, res)) + .catch(err => e.reply(err.message)) } // 更换代理 @@ -226,4 +211,22 @@ export class NewPixiv extends plugin { Config.modify('pixiv', 'pixivDirectConnection', /开启/.test(e.msg)) e.reply(`✅ 已${/开启/.test(e.msg) ? '开启' : '关闭'}Pixiv直连`) } + + async Authentication (e, type) { + if (e.isMaster) return true + if (!Config.pixiv.allowPM && !e.isGroup) { + e.reply('主人已禁用私聊该功能') + return false + } + const { sese, sesepro } = Config.getGroup(e.group_id) + if ((type == 'sese' && !sese && !sesepro) || (type == 'sesepro' && !sesepro)) { + e.reply(SWITCH_ERROR) + return false + } + if (!await common.limit(e.user_id, 'pixiv', Config.pixiv.limit)) { + e.reply('[Pixiv]您已达今日次数上限', true, { at: true }) + return false + } + return true + } } diff --git a/apps/set.js b/apps/setting.js similarity index 94% rename from apps/set.js rename to apps/setting.js index 14c8b50..3fbb2fe 100644 --- a/apps/set.js +++ b/apps/setting.js @@ -34,7 +34,7 @@ const configs = { } let managereg = new RegExp(`^#椰奶设置(${Object.keys(configs).join('|')})(开启|关闭)$`) -export class NewConfig extends plugin { +export class Setting extends plugin { constructor () { super({ name: '椰奶配置', @@ -203,11 +203,11 @@ export class NewConfig extends plugin { // 查看涩涩设置 async View_Settings (e) { let set = setu.getSeSeConfig(e) - let data = Config.Notice + let { sese, sesepro } = Config.Notice e.reply([ e.group_id ? `群${e.group_id}涩涩设置:\n` : '私聊涩涩设置:\n', - `sese:${data.sese ? '✅' : '❎'}\n`, - `sesepro:${data.sesepro ? '✅' : '❎'}\n`, + `sese:${sese ? '✅' : '❎'}\n`, + `sesepro:${sesepro ? '✅' : '❎'}\n`, `R17.9 + 0.1:${set.r18 ? '✅' : '❎'}\n`, `CD:${set.cd}s`, set.recall ? `\n撤回:${set.recall}s` : '' @@ -222,7 +222,7 @@ export class NewConfig extends plugin { // 增删查头衔屏蔽词 async NoTitle (e) { - let data = Config.NoTitle.Shielding_words + let data = Config.groupTitle.Shielding_words if (/查看/.test(e.msg)) { return e.reply(`现有的头衔屏蔽词如下:${data.join('\n')}`) } @@ -241,7 +241,7 @@ export class NewConfig extends plugin { if (type) { if (!_.isEmpty(yes)) { for (let i of yes) { - Config.modifyarr('Shielding_words', 'Shielding_words', i, 'add') + Config.modifyarr('groupTitle', 'Shielding_words', i, 'add') } e.reply(`✅ 成功添加:${yes.join(',')}`) } @@ -251,7 +251,7 @@ export class NewConfig extends plugin { } else { if (!_.isEmpty(no)) { for (let i of no) { - Config.modifyarr('Shielding_words', 'Shielding_words', i, 'del') + Config.modifyarr('groupTitle', 'Shielding_words', i, 'del') } e.reply(`✅ 成功删除:${no.join(',')}`) } @@ -263,8 +263,8 @@ export class NewConfig extends plugin { // 修改头衔匹配模式 async NoTitlepattern (e) { - let data = Config.NoTitle.Match_pattern ? 0 : 1 - Config.modify('Shielding_words', 'Match_pattern', data) + let data = Config.groupTitle.Match_pattern ? 0 : 1 + Config.modify('groupTitle', 'Match_pattern', data) e.reply(`✅ 已修改匹配模式为${data ? '精确' : '模糊'}匹配`) } } diff --git a/apps/setu.js b/apps/setu.js index 4154cfe..76f1c54 100644 --- a/apps/setu.js +++ b/apps/setu.js @@ -1,7 +1,7 @@ import plugin from '../../../lib/plugins/plugin.js' import { Config } from '../components/index.js' import { setu, common } from '../model/index.js' -import { NewConfig } from './set.js' +import { Setting } from './setting.js' const SWITCH_ERROR = '主人没有开放这个功能哦(*/ω\*)' let NumReg = '[一壹二两三四五六七八九十百千万亿\\d]+' @@ -49,9 +49,9 @@ export class SeSe extends plugin { } async seturd (e) { - if (!Config.getGroup(e.group_id).sesepro && !e.isMaster) return e.reply(SWITCH_ERROR) + if (!await this.Authentication(e)) return - let iscd = setu.getremainingCd(e) + let iscd = setu.getRemainingCd(e.user_id, e.group_id) if (iscd) return e.reply(` ${setu.CDMsg}你的CD还有${iscd}`, false, { at: true }) @@ -74,16 +74,13 @@ export class SeSe extends plugin { // tag搜图 async setutag (e) { - if (!Config.getGroup(e.group_id).sesepro && !e.isMaster) return e.reply(SWITCH_ERROR) - - let iscd = setu.getremainingCd(e) + if (!await this.Authentication(e)) return + let iscd = setu.getRemainingCd(e.user_id, e.group_id) if (iscd) return e.reply(` ${setu.CDMsg}你的CD还有${iscd}`, false, { at: true }) let tag = e.msg.replace(/#|椰奶tag/g, '').trim() - let num = e.msg.match(new RegExp(`(${NumReg})张`)) - if (!num) { num = 1 } else { @@ -100,9 +97,7 @@ export class SeSe extends plugin { } if (!tag) return e.reply('tag为空!!!', false, { at: true }) - tag = tag.split(' ')?.map(item => item.split('|')) - if (tag.length > 3) return e.reply('tag最多只能指定三个哦~', false, { at: true }) await setu.setuApi(setu.getR18(e.group_id), num, tag) @@ -110,20 +105,37 @@ export class SeSe extends plugin { .catch(err => e.reply(err.message)) } + async Authentication (e) { + if (e.isMaster) return true + if (!Config.setu.allowPM && !e.isGroup) { + e.reply('主人已禁用私聊该功能') + return false + } + if (!Config.getGroup(e.group_id).sesepro) { + e.reply(SWITCH_ERROR) + return false + } + if (!await common.limit(e.user_id, 'setu', Config.setu.limit)) { + e.reply('[setu]您已达今日次数上限', true, { at: true }) + return false + } + return true + } + // 设置群撤回间隔和cd async setGroupRecallAndCD (e) { let num = e.msg.match(new RegExp(NumReg)) num = common.translateChinaNum(num[0]) let type = /撤回间隔/.test(e.msg) setu.setGroupRecallTimeAndCd(e.group_id, num, type) - new NewConfig().View_Settings(e) + new Setting().View_Settings(e) } // 开启r18 async setsese (e) { let isopen = !!/开启/.test(e.msg) setu.setR18(e.group_id, isopen) - new NewConfig().View_Settings(e) + new Setting().View_Settings(e) } // 艾特设置cd diff --git a/components/Config.js b/components/Config.js index 6202c94..e7211dc 100644 --- a/components/Config.js +++ b/components/Config.js @@ -57,13 +57,13 @@ class Config { } /** 进群验证配置 */ - get verifycfg () { + get groupverify () { return this.getDefOrConfig('groupverify') } /** 头衔屏蔽词 */ - get NoTitle () { - return this.getDefOrConfig('Shielding_words') + get groupTitle () { + return this.getDefOrConfig('groupTitle') } /** 加群通知 */ @@ -86,11 +86,16 @@ class Config { return this.getDefOrConfig('bika') } - /** 搜图配置 */ + /** 搜图 */ get picSearch () { return this.getDefOrConfig('picSearch') } + /** setu */ + get setu () { + return this.getDefOrConfig('setu') + } + /** 默认配置和用户配置 */ getDefOrConfig (name) { let def = this.getdefSet(name) diff --git a/config/default_config/Shielding_words.yaml b/config/default_config/groupTitle.yaml similarity index 100% rename from config/default_config/Shielding_words.yaml rename to config/default_config/groupTitle.yaml diff --git a/config/default_config/picSearch.yaml b/config/default_config/picSearch.yaml index ad07189..9be0f51 100644 --- a/config/default_config/picSearch.yaml +++ b/config/default_config/picSearch.yaml @@ -1,3 +1,7 @@ +#是否允许私聊使用 +allowPM: true +#每名用户每日搜索次数限制 +limit: 30 #SauceNAO搜图apikey 请在 https://saucenao.com/user.php?page=search-api 进行获取 SauceNAOApiKey: #SauceNAO搜图相似度低于这个百分比将被认定为相似度过低 @@ -16,4 +20,4 @@ hideImg: false #whatanime 得到 R18 结果时隐藏结果缩略图 hideImgWhenWhatanimeR18: false #whatanime 发送预览视频,R18 结果不会发送 -whatanimeSendVideo: false \ No newline at end of file +whatanimeSendVideo: false diff --git a/config/default_config/pixiv.yaml b/config/default_config/pixiv.yaml index ad4f471..7d7e000 100644 --- a/config/default_config/pixiv.yaml +++ b/config/default_config/pixiv.yaml @@ -1,7 +1,8 @@ +#是否允许私聊使用 +allowPM: true #pixiv图片直连,国内需配合代理使用 pixivDirectConnection: false #pixiv图片反代,开启直连后反代服务则无效 pixivImageProxy: i.pixiv.re -#loliApi(无内鬼和椰奶tag) 是否排除 AI 作品 -loliExcludeAI: false - +#每名用户每日次数限制(0 则无限制) +limit: 30 diff --git a/config/default_config/setu.yaml b/config/default_config/setu.yaml new file mode 100644 index 0000000..c82f47d --- /dev/null +++ b/config/default_config/setu.yaml @@ -0,0 +1,16 @@ +#是否允许私聊使用 +allowPM: true +#是否排除 AI 作品 +excludeAI: false +#获取张数大于前面的数时则使用对应的图片大小 可选值: ['mini', 'thumb', 'small', 'regular', 'original'] +imgSize: + 6: 'regular' + # 9: 'small' + # 15: 'thumb' +#每名用户每日次数限制(0 则无限制) +limit: 30 +#每个群和私聊的默认设置,单独设置后则失效,时间单位: 秒(s) +defSet: + r18: 0 #1开启0关闭 + recall: 120 + cd: 300 diff --git a/model/common.js b/lib/common/common.js similarity index 92% rename from model/common.js rename to lib/common/common.js index 4358245..5a58303 100644 --- a/model/common.js +++ b/lib/common/common.js @@ -1,7 +1,8 @@ import child_process from 'child_process' -import common from '../../../lib/common/common.js' -import Config from '../components/Config.js' -import setu from './setu.js' +import common from '../../../../lib/common/common.js' +import Config from '../../components/Config.js' +import setu from '../../model/setu.js' +import moment from 'moment' import _ from 'lodash' export default new class newCommon { /** @@ -148,6 +149,25 @@ export default new class newCommon { }) } + /** + * @description: 设置每日次数限制 + * @param {Number} userId QQ + * @param {String} key + * @param {Number} maxlimit 最大限制 + * @return {Boolean} + */ + async limit (userId, key, maxlimit) { + let redisKey = `yenai:${key}:limit:${userId}` + let nowNum = await redis.get(redisKey) + if (nowNum > maxlimit) return false + if (!nowNum) { + await redis.set(redisKey, 1, { EX: moment().add(1, 'days').startOf('day').diff(undefined, 'second') }) + } else { + await redis.incr(redisKey) + } + return true + } + /** * @description: 取cookie * @param {String} data 如:qun.qq.com diff --git a/model/index.js b/model/index.js index 17d3f4f..bfbf9e8 100644 --- a/model/index.js +++ b/model/index.js @@ -1,7 +1,7 @@ import puppeteer from '../lib/puppeteer/puppeteer.js' import uploadRecord from '../lib/uploadRecord/uploadRecord.js' import Bika from './Bika.js' -import common from './common.js' +import common from '../lib/common/common.js' import CPU from './CPU.js' import CronValidate from './CronValidate.js' import GroupAdmin from './GroupAdmin.js' diff --git a/model/setu.js b/model/setu.js index 141b730..7a99488 100644 --- a/model/setu.js +++ b/model/setu.js @@ -7,11 +7,7 @@ export default new class setu { constructor () { this.root = `${Plugin_Path}/config/setu` // 默认配置 - this.def = { - r18: 0, - recall: 120, - cd: 300 - } + this.def = Config.setu.defSet // 存cd的变量 this.temp = {} // 初始化 @@ -44,31 +40,30 @@ export default new class setu { * @param {String} tag 关键词 * @return {Object} */ - async setuApi (r18, num = 1, tag = '') { + async setuApi (r18, num = 1, tag = []) { let api = 'https://api.lolicon.app/setu/v2' - - let apicfg = Data.readJSON('api.json', this.root) - if (apicfg.api) api = apicfg.api - + const { imgSize, excludeAI } = Config.setu + const size = imgSize[_.max(Object.keys(imgSize).filter(item => num > item))] || 'original' let parans = { r18, num, tag, proxy: Pixiv.proxy, - size: num > 6 ? 'regular' : 'original', - excludeAI: Config.pixiv.loliExcludeAI + size, + excludeAI } let result = await request.post(api, { data: parans }).then(res => res.json()) if (_.isEmpty(result.data)) throw Error('没有找到相关的tag') // 消息 return await Promise.all(result.data.map(async item => { - let { pid, title, tags, author, r18, urls } = item + let { pid, title, tags, author, r18, urls, aiType } = item return [ `${this.sendMsgs}\n`, `标题:${title}\n`, `画师:${author}\n`, - `pid:${pid}\n`, - `r18:${r18}\n`, + `Pid:${pid}\n`, + `R18:${r18}\n`, + `AI:${aiType ? aiType == 1 ? '是' : '否' : '未知'}\n`, `tag:${_.truncate(tags.join(','))}\n`, await Pixiv.requestPixivImg(urls?.original || urls?.regular || urls?.small) ] @@ -98,7 +93,8 @@ export default new class setu { */ setCdTime (userId, groupId, cd = this.getCfgCd(userId, groupId)) { let present = parseInt(Date.now() / 1000) - + userId = userId - 0 + groupId = groupId - 0 if (!cd) return false if (groupId) { this.temp[userId + groupId] = present + cd @@ -114,17 +110,24 @@ export default new class setu { return true } - // 获取剩余CD时间 - getremainingCd (e) { + /** + * @description: 获取剩余CD时间 + * @param {Number} userId QQ号 + * @param {Number} groupId 群号不传则为私聊CD + * @return {String} 格式化后的时间 + */ + getRemainingCd (userId, groupId) { + userId = userId - 0 + groupId = groupId - 0 // 获取现在的时间并转换为秒 let present = parseInt(new Date().getTime() / 1000) let over = 0 - if (e.isGroup) { - if (!this.temp[e.user_id + e.group_id]) return false - over = (this.temp[e.user_id + e.group_id] - present) + if (groupId) { + if (!this.temp[userId + groupId]) return false + over = (this.temp[userId + groupId] - present) } else { - if (!this.temp[e.user_id]) return false - over = (this.temp[e.user_id] - present) + if (!this.temp[userId]) return false + over = (this.temp[userId] - present) } if (over <= 0) return false return this.Secondformat(over)