koishi-plugin-teach
Advanced tools
Comparing version 0.1.0 to 0.1.1
{ | ||
"name": "koishi-plugin-teach", | ||
"version": "0.1.0", | ||
"version": "0.1.1", | ||
"main": "dist/index.js", | ||
@@ -8,6 +8,23 @@ "typings": "dist/index.d.ts", | ||
"license": "MIT", | ||
"scripts": { | ||
"build": "tsc -b", | ||
"lint": "eslint src --ext .ts" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/koishijs/koishi.git" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/koishijs/koishi/issues" | ||
}, | ||
"homepage": "https://github.com/koishijs/koishi/packages/plugin-teach#readme", | ||
"devDependencies": { | ||
"koishi-database-level": "^1.0.0-alpha.5", | ||
"koishi-database-mysql": "^1.0.0-alpha.5" | ||
}, | ||
"dependencies": { | ||
"koishi-core": "^0.1.0", | ||
"koishi-utils": "^0.1.0" | ||
"fast-deep-equal": "^3.1.1", | ||
"koishi-core": "^1.0.0-alpha.5", | ||
"koishi-utils": "^1.0.0-alpha.1" | ||
} | ||
} |
@@ -1,2 +0,4 @@ | ||
# plugin-teach | ||
# [koishi-plugin-teach](https://koishijs.github.io/plugins/teach.html) | ||
[](https://www.npmjs.com/package/koishi-plugin-teach) | ||
@@ -1,4 +0,4 @@ | ||
import { GroupContext } from 'koishi-core' | ||
import { Context } from 'koishi-core' | ||
import info from './info' | ||
import parseOptions from './utils' | ||
import parseOptions, { TeachConfig } from './utils' | ||
import receiver from './receiver' | ||
@@ -9,38 +9,22 @@ import search from './search' | ||
import './dialogue' | ||
export * from './database' | ||
export { TeachConfig } | ||
export function apply (ctx: GroupContext) { | ||
ctx.plugin(receiver) | ||
export function apply (ctx: Context, config: TeachConfig = {}) { | ||
ctx.plugin(receiver, config) | ||
ctx.command('teach <question> <answer>', '教四季酱说话', { authority: 2 }) | ||
const command = ctx.command('teach <question> <answer>', '教四季酱说话', { authority: 2, checkUnknown: true, ...config }) | ||
.alias('教学') | ||
.shortcut('教学信息', { options: { info: true } }) | ||
.shortcut('全局教学信息', { options: { info: true, allEnv: true } }) | ||
.config({ | ||
maxUsage: ({ authority: auth }) => auth < 3 ? 10 : auth < 4 ? 30 : Infinity | ||
}) | ||
.option('-q, --question <question>', '搜索或修改已有问题', { notUsage: true, type: String }) | ||
.option('-a, --answer <answer>', '搜索或修改已有回答', { notUsage: true, type: String }) | ||
.option('-q, --question <question>', '搜索或修改已有问题', { notUsage: true, isString: true }) | ||
.option('-a, --answer <answer>', '搜索或修改已有回答', { notUsage: true, isString: true }) | ||
.option('--all', '搜索全部问答') | ||
.option('-f, --frozen', '锁定这个问答', { authority: 4 }) | ||
.option('-F, --no-frozen', '解锁这个问答', { authority: 4, noNagated: true }) | ||
.option('-k, --keyword', '使用关键词匹配') | ||
.option('-c, --chance <value>', '设置问题的触发概率') | ||
.option('-u, --update <id>', '查看或修改已有问题', { notUsage: true, type: String }) | ||
.option('-d, --disable', '在当前环境下禁用问题或回答') | ||
.option('-u, --update <id>', '查看或修改已有问题', { notUsage: true, isString: true }) | ||
.option('-D, --delete', '彻底删除问题或回答') | ||
.option('-e, --env <environment>', '设置问题的生效环境', { type: String }) | ||
.option('-E, --all-env', '搜索所有环境中的问答') | ||
.option('-g, --global-env', '设置全局生效环境,相当于 -e=*') | ||
.option('-n, --no-env', '设置无生效环境,相当于 -e=""', { noNagated: true }) | ||
.option('-w, --writer <qq>', '添加或设置问题的作者', { type: Number }) | ||
.option('-W, --anonymous', '添加或设置匿名问题') | ||
.option('-s, --add-successor <id>', '设置后继问题', { type: String }) | ||
.option('-S, --remove-successor <id>', '取消后继问题', { type: String }) | ||
.option('-p, --add-predecessor <id>', '设置前置问题', { type: String }) | ||
.option('-P, --remove-predecessor <id>', '取消前置问题', { type: String }) | ||
.option('-i, --info', '查看教学信息', { notUsage: true }) | ||
.usage('详细的使用方法请参考:https://shiki.shigma.xyz/manual/teach.html') | ||
.action(async (parsedArgv, question: string, answer: string) => { | ||
const parsedOptions = await parseOptions(ctx, parsedArgv) | ||
const parsedOptions = await parseOptions(ctx, config, parsedArgv) | ||
if (!parsedOptions) return | ||
@@ -55,2 +39,23 @@ | ||
}) | ||
if (config.useWriter) { | ||
command | ||
.option('-w, --writer <qq>', '添加或设置问题的作者') | ||
.option('-W, --anonymous', '添加或设置匿名问题') | ||
} | ||
if (config.useFrozen) { | ||
command | ||
.option('-f, --frozen', '锁定这个问答', { authority: 4 }) | ||
.option('-F, --no-frozen', '解锁这个问答', { authority: 4, noNegated: true }) | ||
} | ||
if (config.useEnvironment) { | ||
command | ||
.option('-d, --disable', '在当前环境下禁用问题或回答') | ||
.option('-e, --env <environment>', '设置问题的生效环境', { isString: true }) | ||
.option('-E, --all-env', '搜索所有环境中的问答') | ||
.option('-g, --global-env', '设置全局生效环境,相当于 -e=*') | ||
.option('-n, --no-env', '设置无生效环境,相当于 -e=""', { noNegated: true }) | ||
} | ||
} |
import { TeachOptions } from './utils' | ||
export default async function apply (config: TeachOptions) { | ||
if (config.options.info) { | ||
let { envMode, groups, ctx, meta, options } = config | ||
if (!envMode && !options.allEnv) { | ||
envMode = 1 | ||
groups = [meta.groupId] | ||
} | ||
const test = ctx.database.getDialogueTest({ envMode, groups }) | ||
const { | ||
'COUNT(DISTINCT `question`)': questions, | ||
'COUNT(*)': answers | ||
} = await ctx.database.query('SELECT COUNT(DISTINCT `question`), COUNT(*) FROM `dialogues`' + test) | ||
return meta.$send(`共收录了 ${questions} 个问题和 ${answers} 个回答。`) | ||
export default async function apply ({ envMode, groups, ctx, meta, options, config }: TeachOptions) { | ||
if (config.useEnvironment && !envMode && !options.allEnv) { | ||
envMode = 1 | ||
groups = [meta.groupId] | ||
} | ||
const { questions, answers } = await ctx.database.getDialogueCount({ envMode, groups }) | ||
return meta.$send(`共收录了 ${questions} 个问题和 ${answers} 个回答。`) | ||
} |
@@ -1,14 +0,6 @@ | ||
import { GroupContext, updateActivity } from 'koishi-core' | ||
import { randomPick, cqCode, sleep } from 'koishi-utils' | ||
import { simplifyQuestion, splitIds } from './utils' | ||
import { updateActivity, Context } from 'koishi-core' | ||
import { randomPick, CQCode, sleep } from 'koishi-utils' | ||
import { simplifyQuestion, TeachConfig } from './utils' | ||
import { DialogueTest } from './database' | ||
interface State { | ||
currentUser: number | ||
currentCount: number | ||
predecessors: Record<number, number> | ||
} | ||
const states: Record<number, State> = {} | ||
const MAX_CONSECUTIVE = 5 | ||
function escapeAnswer (message: string) { | ||
@@ -18,23 +10,15 @@ return message.replace(/\$/g, '@@__DOLLARS_PLACEHOLDER__@@') | ||
export default function (ctx: GroupContext) { | ||
ctx.middleware(async (meta, next) => { | ||
export default function (ctx: Context, config: TeachConfig) { | ||
ctx.intersect(ctx.app.groups).middleware(async (meta, next) => { | ||
const { groupId } = meta | ||
if (!states[groupId]) states[groupId] = { currentUser: 0, currentCount: 0, predecessors: {} } | ||
const state = states[groupId] | ||
const question = simplifyQuestion(meta.message) | ||
if (!question) return next() | ||
if (state.currentUser !== meta.userId) { | ||
state.currentUser = meta.userId | ||
state.currentCount = 0 | ||
} else if (state.currentCount >= MAX_CONSECUTIVE) { | ||
return next() | ||
const test: DialogueTest = { question } | ||
if (config.useEnvironment) { | ||
test.envMode = 1 | ||
test.groups = [groupId] | ||
} | ||
const items = await ctx.database.getDialogues({ | ||
question, | ||
envMode: 1, | ||
groups: [groupId], | ||
extraIds: Object.keys(state.predecessors), | ||
}) | ||
const items = await ctx.database.getDialogues(test) | ||
if (!items.length) return next() | ||
@@ -45,6 +29,5 @@ | ||
state.currentCount += 1 | ||
const { interactiveness, name } = meta.$user | ||
updateActivity(interactiveness, groupId) | ||
await meta.$user.update() | ||
await meta.$user._update() | ||
@@ -54,4 +37,4 @@ const answers = dialogue.answer | ||
.replace(/\$a/g, `[CQ:at,qq=${meta.userId}]`) | ||
.replace(/\$A/g, `[CQ:at,qq=all]`) | ||
.replace(/\$m/g, cqCode('at', { qq: meta.selfId })) | ||
.replace(/\$A/g, '[CQ:at,qq=all]') | ||
.replace(/\$m/g, CQCode.stringify('at', { qq: meta.selfId })) | ||
.replace(/\$s/g, escapeAnswer(name === String(meta.userId) ? meta.sender.card || meta.sender.nickname : name)) | ||
@@ -66,17 +49,3 @@ .replace(/\$0/g, escapeAnswer(meta.message)) | ||
} | ||
const successors = await ctx.database.getDialogues(splitIds(dialogue.successors)) | ||
if (!successors.length) return | ||
const time = Date.now() | ||
for (const successor of successors) { | ||
state.predecessors[successor.id] = time | ||
} | ||
setTimeout(() => { | ||
const { predecessors } = states[meta.groupId] | ||
for (const successor of successors) { | ||
if (predecessors[successor.id] === time) { | ||
delete predecessors[successor.id] | ||
} | ||
} | ||
}, 20000) | ||
}) | ||
} |
@@ -10,3 +10,3 @@ import { TeachOptions } from './utils' | ||
export default async function (parsedOptions: TeachOptions) { | ||
const { ctx, meta, options } = parsedOptions | ||
const { ctx, meta, options, config } = parsedOptions | ||
const question = options.all ? undefined : options.question | ||
@@ -16,16 +16,25 @@ const answer = options.all ? undefined : options.answer | ||
const { keyword } = options | ||
if (!envMode && !options.allEnv) { | ||
if (config.useEnvironment && !envMode && !options.allEnv) { | ||
envMode = 1 | ||
groups = [meta.groupId] | ||
} | ||
const dialogues = await ctx.database.getDialogues({ | ||
writer, keyword, question, answer, envMode, groups, | ||
writer, | ||
keyword, | ||
question, | ||
answer, | ||
envMode, | ||
groups, | ||
frozen: options.unFrozen ? false : options.frozen, | ||
}) | ||
if (!options.question && !options.answer) { | ||
if (!dialogues.length) return meta.$send(`没有搜索到任何回答,尝试切换到其他环境。`) | ||
if (!dialogues.length) return meta.$send('没有搜索到任何回答,尝试切换到其他环境。') | ||
const output = dialogues.map(({ id, question, answer }) => `${id}. 问题:“${question}”,回答:“${formatAnswer(answer)}”`) | ||
output.unshift(`全部问答如下:`) | ||
output.unshift('全部问答如下:') | ||
return meta.$send(output.join('\n')) | ||
} | ||
if (!options.keyword) { | ||
@@ -32,0 +41,0 @@ if (!options.question) { |
@@ -1,6 +0,6 @@ | ||
import { DialogueFlag } from './dialogue' | ||
import { simplifyQuestion, simplifyAnswer, processAnswer, TeachOptions } from './utils' | ||
import { DialogueFlag, Dialogue } from './database' | ||
import { simplifyQuestion, simplifyAnswer, TeachOptions } from './utils' | ||
export default async function (parsedOptions: TeachOptions, question: string, answer: string) { | ||
const { argc, meta, ctx, options } = parsedOptions | ||
const { argc, meta, ctx, options, config } = parsedOptions | ||
if (String(question).includes('[CQ:image,')) return meta.$send('问题不能包含图片。') | ||
@@ -13,9 +13,8 @@ question = simplifyQuestion(question) | ||
answer = await processAnswer(answer, ctx.app.options.imageServerKey) | ||
const [dialogue] = await ctx.database.getDialogues({ question, answer }) | ||
if (dialogue) return meta.$send(`问答已存在,编号为 ${dialogue.id},如要修改请尝试使用 -u 指令。`) | ||
const [dialogue] = await ctx.database.getDialogues({ question, answer }) | ||
if (dialogue) { | ||
return meta.$send(`问答已存在,编号为 ${dialogue.id},如要修改请尝试使用 -u 指令。`) | ||
} else { | ||
let { envMode, groups, writer } = parsedOptions | ||
let { envMode, groups, writer } = parsedOptions | ||
if (config.useEnvironment) { | ||
if (!envMode) { | ||
@@ -25,22 +24,22 @@ envMode = 2 | ||
} else if (Math.abs(envMode) === 1) { | ||
return meta.$send(`参数 -e, --env 错误,请检查指令语法。`) | ||
return meta.$send('参数 -e, --env 错误,请检查指令语法。') | ||
} | ||
if (writer === undefined) { | ||
writer = meta.userId | ||
} | ||
const { minAffinity, maxAffinity, chance: probability = 1 } = options | ||
const successors = (parsedOptions.addSuccessor || []).join(',') | ||
const flag = Number(!!options.frozen) * DialogueFlag.frozen | ||
+ Number(!!options.regexp) * DialogueFlag.regexp | ||
const dialogue = await ctx.database.createDialogue({ | ||
groups: (envMode === 2 ? '' : '*') + groups.join(','), | ||
question, | ||
answer, | ||
writer, | ||
flag, | ||
successors, | ||
probability, | ||
}) | ||
return meta.$send(`问答已添加,编号为 ${dialogue.id}。`) | ||
} | ||
if (config.useWriter && writer === undefined) { | ||
writer = meta.userId | ||
} | ||
const { chance: probability = 1 } = options | ||
const flag = Number(!!options.frozen) * DialogueFlag.frozen | ||
+ Number(!!options.regexp) * DialogueFlag.regexp | ||
+ Number(!!options.keyword) * DialogueFlag.keyword | ||
+ Number(!!options.appellation) * DialogueFlag.appellation | ||
const data = { question, answer, writer, flag, probability } as Dialogue | ||
data.groups = config.useEnvironment ? (envMode === 2 ? '' : '*') + groups.join(',') : '*' | ||
const { id } = await ctx.database.createDialogue(data) | ||
return meta.$send(`问答已添加,编号为 ${id}。`) | ||
} |
@@ -1,9 +0,9 @@ | ||
import { getUserName } from 'koishi-core' | ||
import { Dialogue, DialogueFlag } from './dialogue' | ||
import { splitIds, processAnswer, TeachOptions } from './utils' | ||
import { Dialogue, DialogueFlag } from './database' | ||
import { splitIds, TeachOptions } from './utils' | ||
export default async function (parsedOptions: TeachOptions) { | ||
const { ctx, meta, argc, options } = parsedOptions | ||
const { ctx, meta, argc, options, config } = parsedOptions | ||
if (argc) return meta.$send('存在多余的参数,请检查指令语法或将含有空格或换行的问答置于一对引号内。') | ||
if (!/^\d+(,\d+)*$/.exec(options.update)) return meta.$send(`参数 -u, --update 错误,请检查指令语法。`) | ||
if (!/^\d+(,\d+)*$/.exec(options.update)) return meta.$send('参数 -u, --update 错误,请检查指令语法。') | ||
const ids: number[] = splitIds(options.update) | ||
@@ -21,4 +21,4 @@ const dialogues = await ctx.database.getDialogues(ids) | ||
meta.$user.authority > 3 ? () => false : | ||
meta.$user.authority > 2 ? d => !!(d.flag & DialogueFlag.frozen) : | ||
d => !!(d.flag & DialogueFlag.frozen) || d.writer !== meta.userId | ||
meta.$user.authority > 2 ? d => !!(d.flag & DialogueFlag.frozen) : | ||
d => !!(d.flag & DialogueFlag.frozen) || d.writer !== meta.userId | ||
const removable = dialogues.filter(d => !predicate(d)).map(d => d.id) | ||
@@ -38,3 +38,3 @@ const unremovable = dialogues.filter(predicate).map(d => d.id) | ||
let hasUpdates = Object.keys(parsedOptions).length - 5 | ||
const hasUpdates = Object.keys(parsedOptions).length - 6 | ||
|| options.answer | ||
@@ -47,4 +47,4 @@ || options.question | ||
if (hasUpdates) { | ||
let updateSet = new Set<number>() | ||
let skipSet = new Set<number>() | ||
const updateSet = new Set<number>() | ||
const skipSet = new Set<number>() | ||
@@ -60,2 +60,3 @@ for (const dialogue of dialogues) { | ||
function updateValue <K extends keyof Dialogue> (key: K, type: 'string' | 'number', value: Dialogue[K]) { | ||
// eslint-disable-next-line valid-typeof | ||
if (typeof value === type && value !== dialogue[key]) { | ||
@@ -66,2 +67,3 @@ updates[key] = value | ||
updateValue('answer', 'string', options.answer) | ||
updateValue('question', 'string', options.question) | ||
@@ -71,6 +73,2 @@ updateValue('writer', 'number', parsedOptions.writer) | ||
if (typeof options.answer === 'string' && options.answer !== dialogue.answer) { | ||
updates.answer = await processAnswer(options.answer, ctx.app.options.imageServerKey) | ||
} | ||
let newFlag = dialogue.flag | ||
@@ -108,14 +106,2 @@ if (options.frozen) { | ||
if (parsedOptions.addSuccessor || parsedOptions.removeSuccessor) { | ||
const { addSuccessor = [], removeSuccessor = [] } = parsedOptions | ||
const oldSuccessors = splitIds(dialogue.successors) | ||
const newSuccessors = Array | ||
.from(new Set([...oldSuccessors, ...addSuccessor])) | ||
.filter(id => !removeSuccessor.includes(id)) | ||
.sort().join(',') | ||
if (newSuccessors !== dialogue.successors) updates.successors = newSuccessors | ||
} | ||
// TODO: predecessor | ||
if (Object.keys(updates).length) { | ||
@@ -147,19 +133,22 @@ try { | ||
] | ||
if (dialogue.writer) { | ||
if (config.useWriter && dialogue.writer) { | ||
const user = await ctx.database.getUser(dialogue.writer, 0, ['id', 'name']) | ||
output.push(`来源:${getUserName(user)}`) | ||
output.push(`来源:${user.name}`) | ||
} | ||
output.push(`生效环境:${dialogue.groups.startsWith('*') | ||
? groups.includes(meta.groupId) | ||
? groups.length - 1 ? `除本群等 ${groups.length} 个群外的所有群` : '除本群' | ||
: groups.length ? `除 ${groups.length} 个群外的所有群` : '全局' | ||
: groups.includes(meta.groupId) | ||
? groups.length - 1 ? `本群等 ${groups.length} 个群` : '本群' | ||
: groups.length ? `${groups.length} 个群` : '全局禁止'}`) | ||
if (config.useEnvironment) { | ||
output.push(`生效环境:${dialogue.groups.startsWith('*') | ||
? groups.includes(meta.groupId) | ||
? groups.length - 1 ? `除本群等 ${groups.length} 个群外的所有群` : '除本群' | ||
: groups.length ? `除 ${groups.length} 个群外的所有群` : '全局' | ||
: groups.includes(meta.groupId) | ||
? groups.length - 1 ? `本群等 ${groups.length} 个群` : '本群' | ||
: groups.length ? `${groups.length} 个群` : '全局禁止'}`) | ||
} | ||
if (dialogue.probability < 1) output.push(`触发概率:${dialogue.probability}`) | ||
if (dialogue.successors) output.push(`后继问题:${dialogue.successors}`) | ||
if (dialogue.flag & DialogueFlag.frozen) output.push('此问题已锁定') | ||
await meta.$send(output.join('\n')) | ||
} | ||
return | ||
} |
142
src/utils.ts
@@ -1,30 +0,12 @@ | ||
import { Context, ParsedArgv, Meta } from 'koishi-core' | ||
import { simplify, isInteger, randomId } from 'koishi-utils' | ||
import { createHash } from 'crypto' | ||
import axios from 'axios' | ||
import { Context, ParsedCommandLine, Meta, CommandConfig } from 'koishi-core' | ||
import { simplify, isInteger } from 'koishi-utils' | ||
const imageRE = /\[CQ:image,file=([^,]+),url=([^\]]+)\]/ | ||
export const IMAGE_SERVER = 'https://shiki.shigma.xyz/img' | ||
export const UPLOAD_SERVER = 'https://shiki.shigma.xyz/upload' | ||
export async function processAnswer (source: string, key: string) { | ||
let temp = '' | ||
let capture = source.match(imageRE) | ||
while (capture) { | ||
const [text, file, url] = capture | ||
temp += source.slice(0, capture.index) | ||
source = source.slice(capture.index + text.length) | ||
const salt = randomId() | ||
const sign = createHash('md5').update(file + salt + key).digest('hex') | ||
await axios.get(UPLOAD_SERVER, { | ||
params: { salt, sign, url, file }, | ||
}) | ||
temp += `[CQ:image,file=${IMAGE_SERVER}/${file}]` | ||
capture = source.match(imageRE) | ||
} | ||
return temp + source | ||
export interface TeachConfig extends CommandConfig { | ||
useWriter?: boolean | ||
useFrozen?: boolean | ||
useEnvironment?: boolean | ||
} | ||
const prefixPunctuation = /^([()\]]|\[(?!cq:))*/ | ||
const suffixPunctuation = /([\.,?!()\[~]|(?<!\[cq:[^\]]+)\])*$/ | ||
const suffixPunctuation = /([.,?!()[~]|(?<!\[cq:[^\]]+)\])*$/ | ||
@@ -67,19 +49,12 @@ export function stripPunctuation (source: string) { | ||
options: Record<string, any> | ||
config: TeachConfig | ||
writer?: number | ||
groups?: number[] | ||
envMode?: -2 | -1 | 0 | 1 | 2 | ||
addSuccessor?: number[] | ||
addPredecessor?: number[] | ||
removeSuccessor?: number[] | ||
removePredecessor?: number[] | ||
} | ||
export default function parseOptions (ctx: Context, parsedArgv: ParsedArgv) { | ||
const { options, meta, args } = parsedArgv | ||
let argc = args.length | ||
export default async function parseOptions (ctx: Context, config: TeachConfig, argv: ParsedCommandLine) { | ||
const { options, meta, args } = argv | ||
const argc = args.length | ||
if (options.addPredecessor || options.removePredecessor || options.regexp) { | ||
return meta.$send('本功能目前处于维护中,暂时停止访问。') | ||
} | ||
if (typeof options.chance === 'number' && (options.chance <= 0 || options.chance > 1)) { | ||
@@ -89,77 +64,40 @@ return meta.$send('参数 -c, --chance 应为不超过 1 的正数。') | ||
const parsedOptions: TeachOptions = { ctx, meta, argc, args, options } | ||
const parsedOptions: TeachOptions = { ctx, meta, argc, args, options, config } | ||
if (options.noWriter) { | ||
parsedOptions.writer = 0 | ||
} else if (options.writer) { | ||
if (isInteger(options.writer) && options.writer > 0) { | ||
parsedOptions.writer = options.writer | ||
} else { | ||
return meta.$send(`参数 -w, --writer 错误,请检查指令语法。`) | ||
if (config.useWriter) { | ||
if (options.noWriter) { | ||
parsedOptions.writer = 0 | ||
} else if (options.writer) { | ||
if (isInteger(options.writer) && options.writer > 0) { | ||
parsedOptions.writer = options.writer | ||
} else { | ||
return meta.$send('参数 -w, --writer 错误,请检查指令语法。') | ||
} | ||
} | ||
} | ||
if (options.minAffinity !== undefined) { | ||
if (!isInteger(options.minAffinity) || options.minAffinity < 0 || options.minAffinity >= 32768) { | ||
return meta.$send(`参数 -m, --min-affinity 错误,请检查指令语法。`) | ||
if (config.useEnvironment) { | ||
if (options.globalEnv) { | ||
parsedOptions.envMode = -2 | ||
parsedOptions.groups = [] | ||
} else if (options.noEnv) { | ||
parsedOptions.envMode = 2 | ||
parsedOptions.groups = [] | ||
} else if (typeof options.env === 'string') { | ||
if (options.env.match(/^(\*?(\d{9}(,\d{9})*)?|[#~]\d{9}(,\d{9})*)$/)) { | ||
parsedOptions.groups = splitIds(options.env.replace(/^[#~*]/, '')).sort() | ||
parsedOptions.envMode = options.env.startsWith('*') ? -2 | ||
: options.env.startsWith('#') ? 1 | ||
: options.env.startsWith('~') ? -1 | ||
: 2 | ||
} else { | ||
return meta.$send('参数 -e, --env 错误,请检查指令语法。') | ||
} | ||
} | ||
} | ||
if (options.maxAffinity !== undefined) { | ||
if (!isInteger(options.maxAffinity) || options.maxAffinity <= 0 || options.maxAffinity > 32768) { | ||
return meta.$send(`参数 -m, --max-affinity 错误,请检查指令语法。`) | ||
} | ||
if (String(options.question).includes('[CQ:image,')) { | ||
return meta.$send('问题不能包含图片。') | ||
} | ||
if (options.globalEnv) { | ||
parsedOptions.envMode = -2 | ||
parsedOptions.groups = [] | ||
} else if (options.noEnv) { | ||
parsedOptions.envMode = 2 | ||
parsedOptions.groups = [] | ||
} else if (typeof options.env === 'string') { | ||
if (options.env.match(/^(\*?(\d{9}(,\d{9})*)?|[#~]\d{9}(,\d{9})*)$/)) { | ||
parsedOptions.groups = splitIds(options.env.replace(/^[#~*]/, '')).sort() | ||
parsedOptions.envMode = options.env.startsWith('*') ? -2 | ||
: options.env.startsWith('#') ? 1 | ||
: options.env.startsWith('~') ? -1 | ||
: 2 | ||
} else { | ||
return meta.$send(`参数 -e, --env 错误,请检查指令语法。`) | ||
} | ||
} | ||
if (options.addSuccessor) { | ||
if (options.addSuccessor.match(/^\d+(,\d+)*$/)) { | ||
parsedOptions.addSuccessor = splitIds(options.addSuccessor) | ||
} else { | ||
return meta.$send(`参数 -s, --add-successor 错误,请检查指令语法。`) | ||
} | ||
} | ||
if (options.removeSuccessor) { | ||
if (options.removeSuccessor.match(/^\d+(,\d+)*$/)) { | ||
parsedOptions.removeSuccessor = splitIds(options.removeSuccessor) | ||
} else { | ||
return meta.$send(`参数 -S, --remove-successor 错误,请检查指令语法。`) | ||
} | ||
} | ||
if (options.addPredecessor) { | ||
if (options.addPredecessor.match(/^\d+(,\d+)*$/)) { | ||
parsedOptions.addPredecessor = splitIds(options.addPredecessor) | ||
} else { | ||
return meta.$send(`参数 -p, --add-predecessor 错误,请检查指令语法。`) | ||
} | ||
} | ||
if (options.removePredecessor) { | ||
if (options.removePredecessor.match(/^\d+(,\d+)*$/)) { | ||
parsedOptions.removePredecessor = splitIds(options.removePredecessor) | ||
} else { | ||
return meta.$send(`参数 -P, --remove-predecessor 错误,请检查指令语法。`) | ||
} | ||
} | ||
if (String(options.question).includes('[CQ:image,')) return meta.$send('问题不能包含图片。') | ||
options.question = simplifyQuestion(options.question) | ||
@@ -166,0 +104,0 @@ if (!options.question) delete options.question |
{ | ||
"extends": "../tsconfig.base", | ||
"compilerOptions": { | ||
"target": "esnext", | ||
"module": "commonjs", | ||
"incremental": true, | ||
"esModuleInterop": true, | ||
"moduleResolution": "node", | ||
"declaration": true, | ||
"outDir": "dist" | ||
"outDir": "dist", | ||
"rootDir": "src", | ||
}, | ||
"include": [ | ||
"src" | ||
] | ||
"src", | ||
], | ||
} |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
208734
28
1280
0
5
0
3
2
1
+ Addedfast-deep-equal@^3.1.1
+ Addedescape-string-regexp@3.0.0(transitive)
+ Addedfast-deep-equal@3.1.3(transitive)
+ Addedkoishi-core@1.12.0(transitive)
+ Addedkoishi-utils@1.1.2(transitive)
- Removedaccepts@1.3.8(transitive)
- Removedarray-flatten@1.1.1(transitive)
- Removedbody-parser@1.20.3(transitive)
- Removedbytes@3.1.2(transitive)
- Removedcall-bind-apply-helpers@1.0.2(transitive)
- Removedcall-bound@1.0.3(transitive)
- Removedcontent-disposition@0.5.4(transitive)
- Removedcontent-type@1.0.5(transitive)
- Removedcookie@0.7.1(transitive)
- Removedcookie-signature@1.0.6(transitive)
- Removeddebug@2.6.9(transitive)
- Removeddepd@2.0.0(transitive)
- Removeddestroy@1.2.0(transitive)
- Removeddunder-proto@1.0.1(transitive)
- Removedee-first@1.1.1(transitive)
- Removedencodeurl@1.0.22.0.0(transitive)
- Removedes-define-property@1.0.1(transitive)
- Removedes-errors@1.3.0(transitive)
- Removedes-object-atoms@1.1.1(transitive)
- Removedescape-html@1.0.3(transitive)
- Removedescape-string-regexp@2.0.0(transitive)
- Removedetag@1.8.1(transitive)
- Removedexpress@4.21.2(transitive)
- Removedfinalhandler@1.3.1(transitive)
- Removedforwarded@0.2.0(transitive)
- Removedfresh@0.5.2(transitive)
- Removedfs-extra@8.1.0(transitive)
- Removedfunction-bind@1.1.2(transitive)
- Removedget-intrinsic@1.3.0(transitive)
- Removedget-proto@1.0.1(transitive)
- Removedgopd@1.2.0(transitive)
- Removedgraceful-fs@4.2.11(transitive)
- Removedhas-symbols@1.1.0(transitive)
- Removedhasown@2.0.2(transitive)
- Removedhttp-errors@2.0.0(transitive)
- Removediconv-lite@0.4.24(transitive)
- Removedinherits@2.0.4(transitive)
- Removedipaddr.js@1.9.1(transitive)
- Removedjsonfile@4.0.0(transitive)
- Removedkoishi-core@0.1.11(transitive)
- Removedkoishi-utils@0.1.8(transitive)
- Removedmath-intrinsics@1.1.0(transitive)
- Removedmedia-typer@0.3.0(transitive)
- Removedmerge-descriptors@1.0.3(transitive)
- Removedmethods@1.1.2(transitive)
- Removedmime@1.6.0(transitive)
- Removedmime-db@1.52.0(transitive)
- Removedmime-types@2.1.35(transitive)
- Removedms@2.0.0(transitive)
- Removednegotiator@0.6.3(transitive)
- Removedobject-inspect@1.13.4(transitive)
- Removedon-finished@2.4.1(transitive)
- Removedparseurl@1.3.3(transitive)
- Removedpath-to-regexp@0.1.12(transitive)
- Removedproxy-addr@2.0.7(transitive)
- Removedqs@6.13.0(transitive)
- Removedrange-parser@1.2.1(transitive)
- Removedraw-body@2.5.2(transitive)
- Removedsafe-buffer@5.2.1(transitive)
- Removedsafer-buffer@2.1.2(transitive)
- Removedsend@0.19.0(transitive)
- Removedserve-static@1.16.2(transitive)
- Removedsetprototypeof@1.2.0(transitive)
- Removedside-channel@1.1.0(transitive)
- Removedside-channel-list@1.0.0(transitive)
- Removedside-channel-map@1.0.1(transitive)
- Removedside-channel-weakmap@1.0.2(transitive)
- Removedstatuses@2.0.1(transitive)
- Removedtoidentifier@1.0.1(transitive)
- Removedtype-is@1.6.18(transitive)
- Removeduniversalify@0.1.2(transitive)
- Removedunpipe@1.0.0(transitive)
- Removedutils-merge@1.0.1(transitive)
- Removedvary@1.1.2(transitive)
Updatedkoishi-core@^1.0.0-alpha.5
Updatedkoishi-utils@^1.0.0-alpha.1