koishi-plugin-teach
Advanced tools
Comparing version 1.0.0-alpha.10 to 1.0.0-alpha.11
@@ -0,1 +1,2 @@ | ||
import { Observed } from 'koishi-utils'; | ||
declare module 'koishi-core/dist/database' { | ||
@@ -9,8 +10,16 @@ interface TableMethods { | ||
} | ||
export declare namespace Dialogue { | ||
interface UpdateContext { | ||
skipped?: number[]; | ||
updated?: number[]; | ||
} | ||
} | ||
export declare type DialogueField = keyof Dialogue; | ||
interface DialogueMethods { | ||
createDialogue(options: Dialogue): Promise<Dialogue>; | ||
getDialogues(test: string[]): Promise<Dialogue[]>; | ||
getDialoguesById<K extends DialogueField>(ids: string[], keys?: readonly K[]): Promise<Pick<Dialogue, K>[]>; | ||
getDialoguesByTest(test: DialogueTest): Promise<Dialogue[]>; | ||
setDialogue(id: number, data: Partial<Dialogue>): Promise<any>; | ||
removeDialogues(ids: number[]): Promise<any>; | ||
setDialogue(id: number, data: Partial<Dialogue>): Promise<void>; | ||
setDialogues(data: Observed<Dialogue>[], ctx: Dialogue.UpdateContext): Promise<void>; | ||
removeDialogues(ids: number[]): Promise<void>; | ||
} | ||
@@ -17,0 +26,0 @@ export interface DialogueCount { |
@@ -24,6 +24,6 @@ "use strict"; | ||
}, | ||
async getDialogues(ids) { | ||
async getDialoguesById(ids, keys) { | ||
if (!ids.length) | ||
return []; | ||
return this.query(`SELECT * FROM \`dialogue\` WHERE \`id\` IN (${ids.join(',')})`); | ||
return this.select('dialogue', keys, `\`id\` IN (${ids.join(',')})`); | ||
}, | ||
@@ -49,11 +49,27 @@ async getDialoguesByTest(test) { | ||
}, | ||
setDialogue(id, data) { | ||
return this.update('dialogue', id, data); | ||
async setDialogue(id, data) { | ||
await this.update('dialogue', id, data); | ||
}, | ||
removeDialogues(ids) { | ||
async setDialogues(dialogues, ctx) { | ||
const data = []; | ||
for (const { id, _diff } of dialogues) { | ||
if (!Object.keys(_diff).length) { | ||
ctx.skipped.push(id); | ||
} | ||
else { | ||
ctx.updated.push(id); | ||
data.push({ id, ..._diff }); | ||
} | ||
} | ||
await this.update('dialogue', data); | ||
for (const dialogue of dialogues) { | ||
dialogue._diff = {}; | ||
} | ||
}, | ||
async removeDialogues(ids) { | ||
if (!ids.length) | ||
return; | ||
return this.query(`DELETE FROM \`dialogue\` WHERE \`id\` IN (${ids.join(',')})`); | ||
await this.query(`DELETE FROM \`dialogue\` WHERE \`id\` IN (${ids.join(',')})`); | ||
}, | ||
}); | ||
//# sourceMappingURL=database.js.map |
@@ -19,3 +19,3 @@ "use strict"; | ||
.option('-C, --no-redirect', '取消使用指令重定向') | ||
.option('=>, --redirect-dialogue', '重定向到其他问答'); | ||
.option('=>, --redirect-dialogue <answer>', '重定向到其他问答'); | ||
ctx.before('dialogue/validate', ({ options, meta, args }) => { | ||
@@ -106,3 +106,3 @@ if (args.length) { | ||
if (probA) { | ||
output.push(`不带称呼/带称呼触发权重:${probS}/${probA}`); | ||
output.push(`触发权重:p=${probS}, P=${probA}`); | ||
} | ||
@@ -109,0 +109,0 @@ else { |
@@ -8,2 +8,3 @@ import { Context } from 'koishi-core'; | ||
reversed?: boolean; | ||
noContextOptions?: boolean; | ||
} | ||
@@ -10,0 +11,0 @@ } |
@@ -9,7 +9,7 @@ "use strict"; | ||
.option('-d, --disable', '在当前环境下禁用问答') | ||
.option('-D, --disable-global', '在所有环境下禁用问答') | ||
.option('-D, --disable-global', '在所有环境下禁用问答', { authority: 3 }) | ||
.option('-e, --enable', '在当前环境下启用问答') | ||
.option('-E, --enable-global', '在所有环境下启用问答') | ||
.option('-g, --groups <gids>', '设置具体的生效环境', { isString: true, validate: utils_1.isIdList }) | ||
.option('-G, --global', '无视上下文搜索'); | ||
.option('-E, --enable-global', '在所有环境下启用问答', { authority: 3 }) | ||
.option('-g, --groups <gids>', '设置具体的生效环境', { authority: 3, isString: true, validate: utils_1.isIdList }) | ||
.option('-G, --global', '无视上下文搜索', { authority: 3 }); | ||
ctx.on('dialogue/filter-stateless', (data, test) => { | ||
@@ -42,3 +42,3 @@ if (!test.groups) | ||
} | ||
let noDisableEnable = false; | ||
argv.noContextOptions = false; | ||
if (options.disable) { | ||
@@ -60,3 +60,3 @@ argv.reversed = true; | ||
else { | ||
noDisableEnable = !options.enable; | ||
argv.noContextOptions = !options.enable; | ||
if (options.target ? options.enable : !options.global) { | ||
@@ -69,3 +69,3 @@ argv.reversed = false; | ||
if ('groups' in options) { | ||
if (noDisableEnable) { | ||
if (argv.noContextOptions) { | ||
return meta.$send('参数 -g, --groups 必须与 -d/-D/-e/-E 之一同时使用。'); | ||
@@ -118,3 +118,6 @@ } | ||
if (!argv.groups && argv.meta.messageType === 'group') { | ||
output.unshift(!(flag & database_1.DialogueFlag.reversed) === groups.includes('' + argv.meta.groupId) ? '√' : '×'); | ||
const isReversed = flag & database_1.DialogueFlag.reversed; | ||
const hasGroup = groups.includes('' + argv.meta.groupId); | ||
// output.unshift(hasGroup ? isReversed ? 'D' : 'e' : isReversed ? 'E' : 'd') | ||
output.unshift(!isReversed === hasGroup ? '√' : '×'); | ||
} | ||
@@ -121,0 +124,0 @@ }); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const koishi_utils_1 = require("koishi-utils"); | ||
const database_1 = require("../database"); | ||
const utils_1 = require("../utils"); | ||
@@ -8,6 +9,6 @@ function apply(ctx, config) { | ||
ctx.command('teach') | ||
.option('<<, --set-pred <ids>', '设置前置问题', { isString: true, validate: utils_1.isIdList }) | ||
.option('<, --add-pred <ids>', '添加前置问题', { isString: true, validate: utils_1.isIdList }) | ||
.option('>>, --set-succ <ids>', '设置后继问题', { isString: true, validate: utils_1.isIdList }) | ||
.option('>, --add-succ <ids>', '添加后继问题', { isString: true, validate: utils_1.isIdList }); | ||
.option('<, --set-pred <ids>', '设置前置问题', { isString: true, validate: utils_1.isIdList }) | ||
.option('<<, --add-pred <ids>', '添加前置问题', { isString: true, validate: utils_1.isIdList }) | ||
.option('>, --set-succ <ids>', '设置后继问题', { isString: true, validate: utils_1.isIdList }) | ||
.option('>>, --add-succ <ids>', '添加后继问题', { isString: true, validate: utils_1.isIdList }); | ||
ctx.on('dialogue/filter', (data, test, state) => { | ||
@@ -57,3 +58,10 @@ if (test.successors) { | ||
}); | ||
ctx.on('dialogue/modify', ({ succOverwrite, successors }, data) => { | ||
ctx.on('dialogue/modify', ({ succOverwrite, successors, predecessors, noContextOptions }, data) => { | ||
// fallback to --disable-global when there are predecessors | ||
if (predecessors && predecessors.length && noContextOptions) { | ||
if (data.groups.length) | ||
data.groups = []; | ||
data.flag |= database_1.DialogueFlag.reversed; | ||
} | ||
// merge successors | ||
if (!data.successors) | ||
@@ -77,7 +85,7 @@ data.successors = []; | ||
} | ||
const { predOverwrite, predecessors, dialogues, skipped, updated, failed } = argv; | ||
const { predOverwrite, predecessors, dialogues } = argv; | ||
if (!predecessors) | ||
return; | ||
const successors = dialogues.map(dialogue => '' + dialogue.id); | ||
const predDialogues = await ctx.database.getDialogues(predecessors); | ||
const predDialogues = await ctx.database.getDialoguesById(predecessors); | ||
const newTargets = predDialogues.map(d => d.id); | ||
@@ -94,25 +102,12 @@ const predecessorIds = predecessors.map(Number); | ||
} | ||
const targets = utils_1.checkAuthority(argv, predDialogues); | ||
const targets = utils_1.prepareTargets(argv, predDialogues); | ||
for (const data of targets) { | ||
if (predecessorIds.includes(data.id)) { | ||
if (koishi_utils_1.contain(data.successors, successors)) { | ||
skipped.push(data.id); | ||
continue; | ||
} | ||
else { | ||
data.successors = koishi_utils_1.union(data.successors, successors); | ||
} | ||
} | ||
else { | ||
if (!predecessorIds.includes(data.id)) { | ||
data.successors = koishi_utils_1.difference(data.successors, successors); | ||
} | ||
try { | ||
const { id, successors } = data; | ||
await ctx.database.setDialogue(id, { successors }); | ||
updated.push(id); | ||
else if (!koishi_utils_1.contain(data.successors, successors)) { | ||
data.successors = koishi_utils_1.union(data.successors, successors); | ||
} | ||
catch (error) { | ||
failed.push(data.id); | ||
} | ||
} | ||
await ctx.database.setDialogues(targets, argv); | ||
}); | ||
@@ -119,0 +114,0 @@ ctx.on('dialogue/detail', (dialogue, output) => { |
@@ -11,5 +11,6 @@ "use strict"; | ||
ctx.command('teach') | ||
.option('-s, --search', '搜索已有问答', { notUsage: true, isString: true }) | ||
.option('--search', '搜索已有问答', { notUsage: true, isString: true }) | ||
.option('--page <page>', '设置搜索结果的页码', { validate: utils_1.isPositiveInteger }) | ||
.option('--auto-merge', '自动合并相同的问题和回答'); | ||
.option('--auto-merge', '自动合并相同的问题和回答') | ||
.option('|, --pipe <op...>', '对每个搜索结果执行操作', { authority: 3 }); | ||
ctx.before('dialogue/execute', (argv) => { | ||
@@ -23,3 +24,3 @@ if (argv.options.search) | ||
const { ctx, meta, options } = argv; | ||
const { keyword, question, answer, page = 1, original } = options; | ||
const { keyword, question, answer, page = 1, original, pipe } = options; | ||
const { itemsPerPage = 20, mergeThreshold = 5 } = argv.config; | ||
@@ -30,2 +31,10 @@ const test = { question, answer, keyword }; | ||
const dialogues = await utils_1.getDialogues(ctx, test); | ||
if (pipe) { | ||
if (!dialogues.length) | ||
return meta.$send('没有搜索到任何问答。'); | ||
const command = ctx.getCommand('teach', meta); | ||
Object.assign(meta.$argv, command.parse(pipe)); | ||
meta.$argv.options.target = dialogues.map(d => d.id).join(','); | ||
return command.execute(meta.$argv); | ||
} | ||
function formatPrefix(dialogue) { | ||
@@ -48,3 +57,3 @@ const output = []; | ||
output.push(suffix); | ||
output.push('可以使用 --page 或 ##page 调整输出的条目页数。'); | ||
output.push('可以使用 --page 或在 ## 之后加上页码以调整输出的条目页数。'); | ||
} | ||
@@ -51,0 +60,0 @@ return meta.$send(output.join('\n')); |
@@ -15,3 +15,2 @@ "use strict"; | ||
argv.skipped = []; | ||
argv.failed = []; | ||
argv.dialogues = await utils_1.getDialogues(ctx, { question, answer }); | ||
@@ -24,3 +23,3 @@ if (argv.dialogues.length) { | ||
if (Object.keys(dialogue._diff).length) { | ||
utils_1.checkAuthority(argv, [data]); | ||
utils_1.prepareTargets(argv, [data]); | ||
if (argv.uneditable[0] === data.id) { | ||
@@ -37,7 +36,13 @@ argv.uneditable.shift(); | ||
} | ||
const dialogue = { flag: 0 }; | ||
ctx.emit('dialogue/modify', argv, dialogue); | ||
argv.dialogues = [await ctx.database.createDialogue(dialogue)]; | ||
await ctx.serialize('dialogue/after-modify', argv); | ||
return utils_1.sendResult(argv, `问答已添加,编号为 ${argv.dialogues[0].id}。`); | ||
try { | ||
const dialogue = { flag: 0 }; | ||
ctx.emit('dialogue/modify', argv, dialogue); | ||
argv.dialogues = [await ctx.database.createDialogue(dialogue)]; | ||
await ctx.serialize('dialogue/after-modify', argv); | ||
return utils_1.sendResult(argv, `问答已添加,编号为 ${argv.dialogues[0].id}。`); | ||
} | ||
catch (err) { | ||
await argv.meta.$send('添加问答时遇到错误。'); | ||
throw err; | ||
} | ||
}); | ||
@@ -44,0 +49,0 @@ } |
@@ -7,3 +7,3 @@ "use strict"; | ||
ctx.command('teach') | ||
.option('-t, --target <ids>', '查看或修改已有问题', { isString: true, validate: val => !/^\d+(,\d+)*$/.test(val) }) | ||
.option('--target <ids>', '查看或修改已有问题', { isString: true, validate: utils_1.isIdList }) | ||
.option('-r, --remove', '彻底删除问答'); | ||
@@ -15,4 +15,9 @@ ctx.before('dialogue/execute', (argv) => { | ||
delete argv.options.target; | ||
delete argv.options.t; | ||
return update(argv); | ||
try { | ||
return update(argv); | ||
} | ||
catch (err) { | ||
ctx.logger('teach').warn(err); | ||
return argv.meta.$send('修改问答时出现问题。'); | ||
} | ||
}); | ||
@@ -23,8 +28,6 @@ } | ||
const { ctx, meta, options, target } = argv; | ||
const logger = ctx.logger('teach'); | ||
argv.uneditable = []; | ||
argv.updated = []; | ||
argv.skipped = []; | ||
argv.failed = []; | ||
argv.dialogues = await ctx.database.getDialogues(target); | ||
argv.dialogues = await ctx.database.getDialoguesById(target); | ||
const actualIds = argv.dialogues.map(d => '' + d.id); | ||
@@ -42,3 +45,3 @@ argv.unknown = koishi_utils_1.difference(target, actualIds); | ||
} | ||
const targets = utils_1.checkAuthority(argv, argv.dialogues); | ||
const targets = utils_1.prepareTargets(argv, argv.dialogues); | ||
if (options.remove) { | ||
@@ -62,20 +65,6 @@ const output = []; | ||
return; | ||
for (const data of targets) { | ||
const { id } = data; | ||
const dialogue = koishi_utils_1.observe(data, `dialogue ${id}`); | ||
for (const dialogue of targets) { | ||
ctx.emit('dialogue/modify', argv, dialogue); | ||
if (Object.keys(dialogue._diff).length) { | ||
try { | ||
await ctx.database.setDialogue(id, dialogue._diff); | ||
argv.updated.push(id); | ||
} | ||
catch (error) { | ||
logger.warn(error); | ||
argv.failed.push(id); | ||
} | ||
} | ||
else { | ||
argv.skipped.push(id); | ||
} | ||
} | ||
await ctx.database.setDialogues(targets, argv); | ||
await ctx.serialize('dialogue/after-modify', argv); | ||
@@ -82,0 +71,0 @@ return utils_1.sendResult(argv); |
@@ -19,3 +19,3 @@ import { Context, Meta, User } from 'koishi-core'; | ||
} | ||
export interface TeachArgv { | ||
export interface TeachArgv extends Dialogue.UpdateContext { | ||
ctx: Context; | ||
@@ -30,5 +30,2 @@ meta: Meta<'message'>; | ||
uneditable?: number[]; | ||
updated?: number[]; | ||
skipped?: number[]; | ||
failed?: number[]; | ||
} | ||
@@ -39,3 +36,3 @@ export declare function sendResult(argv: TeachArgv, message?: string): Promise<void>; | ||
export declare function getDialogues(ctx: Context, test: DialogueTest, state?: SessionState): Promise<Dialogue[]>; | ||
export declare function checkAuthority(argv: TeachArgv, dialogues: Dialogue[]): Dialogue[]; | ||
export declare function prepareTargets(argv: TeachArgv, dialogues: Dialogue[]): import("koishi-utils").Observed<Dialogue, void>[]; | ||
export declare function sendDetail(ctx: Context, dialogue: Dialogue, argv: TeachArgv): Promise<void>; | ||
@@ -42,0 +39,0 @@ export declare function isPositiveInteger(value: any): "" | "应为正整数。"; |
@@ -12,5 +12,2 @@ "use strict"; | ||
} | ||
if (argv.failed.length) { | ||
output.push(`问答 ${argv.failed.join(', ')} 修改时发生错误。`); | ||
} | ||
if (argv.skipped.length) { | ||
@@ -40,3 +37,3 @@ output.push(`问答 ${argv.skipped.join(', ')} 没有发生改动。`); | ||
exports.getDialogues = getDialogues; | ||
function checkAuthority(argv, dialogues) { | ||
function prepareTargets(argv, dialogues) { | ||
const targets = dialogues.filter((dialogue) => { | ||
@@ -46,5 +43,5 @@ return !argv.ctx.bail('dialogue/permit', argv.meta.$user, dialogue); | ||
argv.uneditable.unshift(...koishi_utils_1.difference(dialogues, targets).map(d => d.id)); | ||
return targets; | ||
return targets.map(data => koishi_utils_1.observe(data, `dialogue ${data.id}`)); | ||
} | ||
exports.checkAuthority = checkAuthority; | ||
exports.prepareTargets = prepareTargets; | ||
async function sendDetail(ctx, dialogue, argv) { | ||
@@ -51,0 +48,0 @@ const output = [`编号为 ${dialogue.id} 的问答信息:`]; |
{ | ||
"name": "koishi-plugin-teach", | ||
"description": "Teach plugin for Koishi", | ||
"version": "1.0.0-alpha.10", | ||
"version": "1.0.0-alpha.11", | ||
"main": "dist/index.js", | ||
@@ -38,12 +38,12 @@ "typings": "dist/index.d.ts", | ||
"devDependencies": { | ||
"koishi-database-level": "^2.0.0-alpha.8", | ||
"koishi-database-memory": "^2.0.0-alpha.8", | ||
"koishi-database-mysql": "^2.0.0-alpha.8", | ||
"koishi-test-utils": "^4.0.0-alpha.8" | ||
"koishi-database-level": "^2.0.0-alpha.9", | ||
"koishi-database-memory": "^2.0.0-alpha.9", | ||
"koishi-database-mysql": "^2.0.0-alpha.9", | ||
"koishi-test-utils": "^4.0.0-alpha.9" | ||
}, | ||
"dependencies": { | ||
"escape-string-regexp": "^2.0.0", | ||
"koishi-core": "^2.0.0-alpha.8", | ||
"koishi-core": "^2.0.0-alpha.9", | ||
"koishi-utils": "^1.0.6" | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
125858
1563
Updatedkoishi-core@^2.0.0-alpha.9