koishi-core
Advanced tools
Comparing version 0.2.6 to 0.2.7
/// <reference types="node" /> | ||
import { Server, ServerType } from './server'; | ||
import { Context, UserContext, GroupContext, DiscussContext, Middleware, Plugin, NoticeEvent, RequestEvent, MetaEventEvent, MessageEvent } from './context'; | ||
import { Command, ShortcutConfig, ParsedCommandLine } from './command'; | ||
@@ -8,2 +7,3 @@ import { Database, DatabaseConfig } from './database'; | ||
import { Meta, MessageMeta } from './meta'; | ||
import { Context, UserContext, GroupContext, DiscussContext, Middleware, Plugin, NoticeEvent, RequestEvent, MetaEventEvent, MessageEvent, ContextScope } from './context'; | ||
export interface AppOptions { | ||
@@ -27,2 +27,5 @@ port?: number; | ||
export declare function getSelfIds(): Promise<number[]>; | ||
export declare type MajorContext<T extends Context> = T & { | ||
except(...ids: number[]): T; | ||
}; | ||
export declare class App extends Context { | ||
@@ -36,2 +39,5 @@ options: AppOptions; | ||
userPrefixRE: RegExp; | ||
users: MajorContext<UserContext>; | ||
groups: MajorContext<GroupContext>; | ||
discusses: MajorContext<DiscussContext>; | ||
_commands: Command[]; | ||
@@ -41,17 +47,14 @@ _commandMap: Record<string, Command>; | ||
_shortcutMap: Record<string, Command>; | ||
_middlewares: [string, Middleware][]; | ||
_middlewares: [Context, Middleware][]; | ||
private _middlewareCounter; | ||
private _middlewareSet; | ||
private _contexts; | ||
users: UserContext; | ||
groups: GroupContext; | ||
discusses: DiscussContext; | ||
constructor(options?: AppOptions); | ||
get selfId(): number; | ||
set selfId(value: number); | ||
get version(): import("./meta").VersionInfo; | ||
_registerSelfId(): void; | ||
_createContext<T extends Context>(path: string, id?: number): T; | ||
discuss(id: number): DiscussContext; | ||
group(id: number): GroupContext; | ||
user(id: number): UserContext; | ||
_createContext<T extends Context>(scope: string | ContextScope): T; | ||
discuss(...ids: number[]): DiscussContext; | ||
group(...ids: number[]): GroupContext; | ||
user(...ids: number[]): UserContext; | ||
start(): Promise<void>; | ||
@@ -58,0 +61,0 @@ stop(): void; |
118
dist/app.js
@@ -15,5 +15,4 @@ "use strict"; | ||
const escape_string_regexp_1 = __importDefault(require("escape-string-regexp")); | ||
const sender_1 = require("./sender"); | ||
const server_1 = require("./server"); | ||
const sender_1 = require("./sender"); | ||
const context_1 = require("./context"); | ||
const database_1 = require("./database"); | ||
@@ -23,2 +22,3 @@ const utils_1 = require("./utils"); | ||
const errors = __importStar(require("./errors")); | ||
const context_1 = require("./context"); | ||
const showLog = debug_1.default('koishi'); | ||
@@ -60,3 +60,3 @@ const showReceiverLog = debug_1.default('koishi:receiver'); | ||
const info = await app.sender.getLoginInfo(); | ||
app.selfId = info.userId; | ||
app.options.selfId = info.userId; | ||
app._registerSelfId(); | ||
@@ -69,5 +69,7 @@ })); | ||
exports.getSelfIds = getSelfIds; | ||
const appScope = [[null, []], [null, []], [null, []]]; | ||
const appIdentifier = context_1.ContextScope.stringify(appScope); | ||
class App extends context_1.Context { | ||
constructor(options = {}) { | ||
super('/'); | ||
super(appIdentifier, appScope); | ||
this.options = options; | ||
@@ -82,10 +84,5 @@ this.app = this; | ||
this._middlewareSet = new Set(); | ||
this._contexts = { '/': this }; | ||
this.users = this._createContext('/user/'); | ||
this.groups = this._createContext('/group/'); | ||
this.discusses = this._createContext('/discuss/'); | ||
this._contexts = { [appIdentifier]: this }; | ||
this._preprocess = async (meta, next) => { | ||
// strip prefix | ||
if (!meta.message) | ||
console.log(meta); | ||
let message = meta.message.trim(); | ||
@@ -194,3 +191,3 @@ let prefix = ''; | ||
prefix: '没有此命令。', | ||
postfix: '发送空行以调用推测的指令。', | ||
suffix: '发送空行以调用推测的指令。', | ||
items: Object.keys(this._commandMap), | ||
@@ -210,7 +207,6 @@ command: suggestion => this._commandMap[suggestion], | ||
const middlewares = this._middlewares | ||
.filter(([path]) => context_1.isAncestor(path, meta.$path)) | ||
.filter(([context]) => context.match(meta)) | ||
.map(([_, middleware]) => middleware); | ||
// execute middlewares | ||
let index = 0; | ||
const initial = middlewares.indexOf(this._preprocess); | ||
const next = async (fallback) => { | ||
@@ -229,5 +225,2 @@ if (!this._middlewareSet.has(counter)) { | ||
this._middlewareSet.delete(counter); | ||
if (index <= initial) { | ||
return this.emitWarning(errors.PREMIDDLEWARE_INTERCEPTION); | ||
} | ||
// flush user data | ||
@@ -238,4 +231,5 @@ if (meta.$user) | ||
exports.appList.push(this); | ||
if (options.database) | ||
if (options.database && Object.keys(options.database).length) { | ||
this.database = database_1.createDatabase(options.database); | ||
} | ||
if (options.selfId) | ||
@@ -249,2 +243,8 @@ this._registerSelfId(); | ||
this.middleware(this._preprocess); | ||
this.users = this._createContext([[null, []], [[], null], [[], null]]); | ||
this.groups = this._createContext([[[], null], [null, []], [[], null]]); | ||
this.discusses = this._createContext([[[], null], [[], null], [null, []]]); | ||
this.users.except = (...ids) => this._createContext([[null, ids], [[], null], [[], null]]); | ||
this.groups.except = (...ids) => this._createContext([[[], null], [null, ids], [[], null]]); | ||
this.discusses.except = (...ids) => this._createContext([[[], null], [[], null], [null, ids]]); | ||
} | ||
@@ -254,4 +254,4 @@ get selfId() { | ||
} | ||
set selfId(value) { | ||
this.options.selfId = value; | ||
get version() { | ||
return this.server && this.server.version; | ||
} | ||
@@ -272,20 +272,25 @@ _registerSelfId() { | ||
} | ||
_createContext(path, id) { | ||
if (!this._contexts[path]) { | ||
const ctx = this._contexts[path] = new context_1.Context(path, this); | ||
_createContext(scope) { | ||
if (typeof scope === 'string') | ||
scope = context_1.ContextScope.parse(scope); | ||
scope = scope.map(([include, exclude]) => { | ||
return include ? [include.sort(), exclude] : [include, exclude.sort()]; | ||
}); | ||
const identifier = context_1.ContextScope.stringify(scope); | ||
if (!this._contexts[identifier]) { | ||
const ctx = this._contexts[identifier] = new context_1.Context(identifier, scope); | ||
ctx.database = this.database; | ||
ctx.sender = this.sender; | ||
ctx.app = this; | ||
ctx.id = id; | ||
} | ||
return this._contexts[path]; | ||
return this._contexts[identifier]; | ||
} | ||
discuss(id) { | ||
return this._createContext(`/discuss/${id}/`, id); | ||
discuss(...ids) { | ||
return this._createContext([[[], null], [[], null], [ids, null]]); | ||
} | ||
group(id) { | ||
return this._createContext(`/group/${id}/`, id); | ||
group(...ids) { | ||
return this._createContext([[[], null], [ids, null], [[], null]]); | ||
} | ||
user(id) { | ||
return this._createContext(`/user/${id}/`, id); | ||
user(...ids) { | ||
return this._createContext([[ids, null], [[], null], [[], null]]); | ||
} | ||
@@ -306,25 +311,41 @@ async start() { | ||
async dispatchMeta(meta, emitEvents = true) { | ||
Object.defineProperty(meta, '$path', { | ||
value: '/', | ||
writable: true, | ||
}); | ||
// prepare prefix | ||
let type, subId; | ||
if (meta.groupId) { | ||
type = 'group'; | ||
subId = meta.groupId; | ||
} | ||
else if (meta.discussId) { | ||
type = 'discuss'; | ||
subId = meta.discussId; | ||
} | ||
else if (meta.userId) { | ||
type = 'user'; | ||
subId = meta.userId; | ||
} | ||
// prepare events | ||
const events = []; | ||
if (meta.postType === 'message' || meta.postType === 'send') { | ||
const type = meta[meta.postType + 'Type']; | ||
meta.$path += `${type === 'private' ? 'user' : type}/${meta.groupId || meta.discussId || meta.userId}/${meta.postType}`; | ||
events.push(meta.postType); | ||
} | ||
else if (meta.postType === 'request') { | ||
meta.$path += `${meta.requestType === 'friend' ? 'user' : 'group'}/${meta.groupId || meta.userId}/request`; | ||
events.push('request'); | ||
} | ||
else if (meta.groupId) { | ||
meta.$path += `group/${meta.groupId}/${meta.noticeType}`; | ||
events.push(meta.noticeType); | ||
} | ||
else if (meta.userId) { | ||
meta.$path += `user/${meta.userId}/${meta.noticeType}`; | ||
events.push(meta.noticeType); | ||
} | ||
else { | ||
meta.$path += `meta_event/${meta.metaEventType}`; | ||
events.push('meta_event/' + meta.metaEventType, 'meta_event'); | ||
} | ||
if (meta.subType) | ||
meta.$path += '/' + meta.subType; | ||
showReceiverLog('path %s', meta.$path); | ||
events.unshift(events[0] + '/' + meta.subType); | ||
// generate path | ||
const path = (type ? `/${type}/${subId}/` : '/') + events[0]; | ||
Object.defineProperty(meta, '$path', { value: path }); | ||
Object.defineProperty(meta, '$type', { value: type }); | ||
Object.defineProperty(meta, '$subId', { value: subId }); | ||
showReceiverLog('path %s', path); | ||
// add context properties | ||
@@ -348,2 +369,3 @@ if (meta.postType === 'message') { | ||
} | ||
// emit events | ||
if (!emitEvents) | ||
@@ -353,6 +375,8 @@ return; | ||
const context = this._contexts[path]; | ||
const types = context._getEventTypes(meta.$path); | ||
if (types.length) | ||
showReceiverLog(path, 'emits', types.join(', ')); | ||
types.forEach(type => context.receiver.emit(type, meta)); | ||
if (!context.match(meta)) | ||
continue; | ||
showReceiverLog(path, 'emits', events); | ||
events.forEach((event) => { | ||
context.receiver.emit(event, meta); | ||
}); | ||
} | ||
@@ -363,3 +387,3 @@ } | ||
const command = this._commandMap[name]; | ||
if (command && context_1.isAncestor(command.context.path, meta.$path)) { | ||
if (command && command.context.match(meta)) { | ||
const result = command.parse(message.slice(name.length).trimStart()); | ||
@@ -366,0 +390,0 @@ return { meta, command, ...result }; |
@@ -43,5 +43,4 @@ import { Context, NextFunction } from './context'; | ||
export declare class Command { | ||
rawName: string; | ||
name: string; | ||
context: Context; | ||
name: string; | ||
config: CommandConfig; | ||
@@ -55,11 +54,12 @@ children: Command[]; | ||
_shortcuts: Record<string, ShortcutConfig>; | ||
_userFields: Set<"name" | "id" | "flag" | "ignoreEnd" | "authority" | "usage" | "talkativeness">; | ||
_userFields: Set<"id" | "name" | "flag" | "ignoreEnd" | "authority" | "usage" | "talkativeness">; | ||
private _argsDef; | ||
private _optsDef; | ||
private _action?; | ||
constructor(rawName: string, context: Context, config?: CommandConfig); | ||
constructor(name: string, declaration: string, context: Context, config?: CommandConfig); | ||
private _registerAlias; | ||
userFields(fields: Iterable<UserField>): this; | ||
alias(...names: string[]): this; | ||
subcommand(name: string, description?: string, config?: CommandConfig): Command; | ||
subcommand(rawName: string, config?: CommandConfig): Command; | ||
subcommand(rawName: string, description: string, config?: CommandConfig): Command; | ||
shortcut(name: string, config?: ShortcutConfig): this; | ||
@@ -66,0 +66,0 @@ usage(text: string): this; |
@@ -26,4 +26,4 @@ "use strict"; | ||
class Command { | ||
constructor(rawName, context, config = {}) { | ||
this.rawName = rawName; | ||
constructor(name, declaration, context, config = {}) { | ||
this.name = name; | ||
this.context = context; | ||
@@ -38,10 +38,5 @@ this.children = []; | ||
this._optsDef = {}; | ||
this.name = parser_1.removeBrackets(rawName); | ||
if (!this.name) { | ||
if (!name) | ||
throw new Error(errors.EXPECT_COMMAND_NAME); | ||
} | ||
else if (!/^[\w.-]+$/.exec(this.name)) { | ||
throw new Error(errors.INVALID_CHARACTER); | ||
} | ||
this._argsDef = parser_1.parseArguments(rawName); | ||
this._argsDef = parser_1.parseArguments(declaration); | ||
this.config = { ...defaultConfig, ...config }; | ||
@@ -77,14 +72,5 @@ this._registerAlias(this.name); | ||
} | ||
subcommand(name, description = '', config = {}) { | ||
const dotPrefixed = name.startsWith('.'); | ||
if (dotPrefixed) | ||
name = this.name + name; | ||
const [firstName] = name.split(/(?=[\s/])/, 1); | ||
if (this.context.app._commandMap[firstName.toLowerCase()]) { | ||
throw new Error(errors.EXISTING_SUBCOMMAND); | ||
} | ||
if (!dotPrefixed) | ||
name = this.name + '/' + name; | ||
const command = this.context.command(name, description, config); | ||
return command; | ||
subcommand(rawName, ...args) { | ||
rawName = this.name + (rawName.charCodeAt(0) === 46 ? '' : '/') + rawName; | ||
return this.context.command(rawName, ...args); | ||
} | ||
@@ -91,0 +77,0 @@ shortcut(name, config = {}) { |
/// <reference types="node" /> | ||
import { MessageMeta, Meta } from './meta'; | ||
import { Command, CommandConfig } from './command'; | ||
import { EventEmitter } from 'events'; | ||
import { MessageMeta, Meta } from './meta'; | ||
import { Sender } from './sender'; | ||
@@ -16,11 +16,22 @@ import { App } from './app'; | ||
export declare type Plugin<T extends Context = Context, U = any> = PluginFunction<T, U> | PluginObject<T, U>; | ||
export declare function isAncestor(ancestor: string, path: string): boolean; | ||
declare type Subscope = [number[], number[]]; | ||
export declare type ContextScope = Subscope[]; | ||
export declare namespace ContextScope { | ||
function stringify(scope: ContextScope): string; | ||
function parse(identifier: string): Subscope[]; | ||
} | ||
export declare class Context { | ||
path: string; | ||
app?: App; | ||
id?: number; | ||
readonly identifier: string; | ||
private readonly _scope; | ||
app: App; | ||
sender: Sender; | ||
database: Database; | ||
receiver: EventEmitter; | ||
constructor(path: string, app?: App); | ||
constructor(identifier: string, _scope: ContextScope); | ||
inverse(): Context; | ||
plus(ctx: Context): Context; | ||
minus(ctx: Context): Context; | ||
intersect(ctx: Context): Context; | ||
match(meta: Meta): boolean; | ||
contain(ctx: Context): boolean; | ||
plugin<U>(plugin: PluginFunction<this, U>, options?: U): this; | ||
@@ -31,10 +42,8 @@ plugin<U>(plugin: PluginObject<this, U>, options?: U): this; | ||
removeMiddleware(middleware: Middleware): boolean; | ||
private _getCommandByParent; | ||
command(rawName: string, config?: CommandConfig): Command; | ||
command(rawName: string, description: string, config?: CommandConfig): Command; | ||
private _getCommandByRawName; | ||
getCommand(name: string, meta?: MessageMeta): Command; | ||
getCommand(name: string, meta: MessageMeta): Command; | ||
runCommand(name: string, meta: MessageMeta, args?: string[], options?: Record<string, any>, rest?: string): any; | ||
end(): App; | ||
_getEventTypes(path: string): string[]; | ||
} | ||
@@ -41,0 +50,0 @@ declare type UserMessageEvent = 'message' | 'message/friend' | 'message/group' | 'message/discuss' | 'message/other'; |
@@ -10,2 +10,4 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const koishi_utils_1 = require("koishi-utils"); | ||
const meta_1 = require("./meta"); | ||
const command_1 = require("./command"); | ||
@@ -15,13 +17,76 @@ const events_1 = require("events"); | ||
const errors = __importStar(require("./errors")); | ||
function isAncestor(ancestor, path) { | ||
return path.startsWith(ancestor) || path.replace(/\d+/, '*').startsWith(ancestor); | ||
} | ||
exports.isAncestor = isAncestor; | ||
const prefixTypes = ['user', 'discuss', 'group']; | ||
var ContextScope; | ||
(function (ContextScope) { | ||
function stringify(scope) { | ||
return scope.map(([include, exclude], index) => { | ||
const type = meta_1.contextTypes[index]; | ||
const sign = include ? '+' : '-'; | ||
const idList = include || exclude; | ||
return `${sign}${type}:${idList.join(',')}`; | ||
}).filter(a => a).join(';'); | ||
} | ||
ContextScope.stringify = stringify; | ||
function parse(identifier) { | ||
const scope = noopScope.slice(); | ||
identifier.split(';').forEach((segment) => { | ||
const capture = /^([+-])(user|group|discuss):(.+)$/.exec(segment); | ||
if (!capture) | ||
throw new Error(errors.INVALID_IDENTIFIER); | ||
const [_, sign, type, list] = capture; | ||
const idList = list.split(',').map(n => +n); | ||
scope[meta_1.contextTypes[type]] = sign === '+' ? [idList, null] : [null, idList]; | ||
}); | ||
return scope; | ||
} | ||
ContextScope.parse = parse; | ||
})(ContextScope = exports.ContextScope || (exports.ContextScope = {})); | ||
const noopScope = [[[], null], [[], null], [[], null]]; | ||
const noopIdentifier = ContextScope.stringify(noopScope); | ||
class Context { | ||
constructor(path, app) { | ||
this.path = path; | ||
this.app = app; | ||
constructor(identifier, _scope) { | ||
this.identifier = identifier; | ||
this._scope = _scope; | ||
this.receiver = new events_1.EventEmitter(); | ||
} | ||
inverse() { | ||
return this.app._createContext(this._scope.map(([include, exclude]) => { | ||
return include ? [null, include.slice()] : [exclude.slice(), []]; | ||
})); | ||
} | ||
plus(ctx) { | ||
return this.app._createContext(this._scope.map(([include1, exclude1], index) => { | ||
const [include2, exclude2] = ctx._scope[index]; | ||
return include1 | ||
? include2 ? [koishi_utils_1.union(include1, include2), null] : [null, koishi_utils_1.difference(exclude2, include1)] | ||
: [null, include2 ? koishi_utils_1.difference(exclude1, include2) : koishi_utils_1.intersection(exclude1, exclude2)]; | ||
})); | ||
} | ||
minus(ctx) { | ||
return this.app._createContext(this._scope.map(([include1, exclude1], index) => { | ||
const [include2, exclude2] = ctx._scope[index]; | ||
return include1 | ||
? [include2 ? koishi_utils_1.difference(include1, include2) : koishi_utils_1.intersection(include1, exclude2), null] | ||
: include2 ? [null, koishi_utils_1.union(include2, exclude1)] : [koishi_utils_1.difference(exclude2, exclude1), null]; | ||
})); | ||
} | ||
intersect(ctx) { | ||
return this.app._createContext(this._scope.map(([include1, exclude1], index) => { | ||
const [include2, exclude2] = ctx._scope[index]; | ||
return include1 | ||
? [include2 ? koishi_utils_1.intersection(include1, include2) : koishi_utils_1.difference(include1, exclude2), null] | ||
: include2 ? [koishi_utils_1.difference(include2, exclude1), null] : [null, koishi_utils_1.union(exclude1, exclude2)]; | ||
})); | ||
} | ||
match(meta) { | ||
const [include, exclude] = this._scope[+meta_1.contextTypes[meta.$type]]; | ||
return include ? include.includes(meta.$subId) : !exclude.includes(meta.$subId); | ||
} | ||
contain(ctx) { | ||
return this._scope.every(([include1, exclude1], index) => { | ||
const [include2, exclude2] = ctx._scope[index]; | ||
return include1 | ||
? include2 && koishi_utils_1.isSubset(include2, include1) | ||
: include2 ? !koishi_utils_1.intersection(include2, exclude1).length : koishi_utils_1.isSubset(exclude1, exclude2); | ||
}); | ||
} | ||
plugin(plugin, options) { | ||
@@ -43,11 +108,11 @@ if (options === false) | ||
middleware(middleware) { | ||
this.app._middlewares.push([this.path, middleware]); | ||
this.app._middlewares.push([this, middleware]); | ||
return this; | ||
} | ||
premiddleware(middleware) { | ||
this.app._middlewares.unshift([this.path, middleware]); | ||
this.app._middlewares.unshift([this, middleware]); | ||
return this; | ||
} | ||
removeMiddleware(middleware) { | ||
const index = this.app._middlewares.findIndex(([p, m]) => p === this.path && m === middleware); | ||
const index = this.app._middlewares.findIndex(([c, m]) => c === this && m === middleware); | ||
if (index >= 0) { | ||
@@ -58,44 +123,45 @@ this.app._middlewares.splice(index, 1); | ||
} | ||
_getCommandByParent(name, parent) { | ||
let command = this.app._commandMap[name.toLowerCase()]; | ||
if (command) { | ||
if (parent && command.parent !== parent) { | ||
throw new Error(errors.WRONG_SUBCOMMAND); | ||
} | ||
if (!isAncestor(command.context.path, this.path)) { | ||
throw new Error(errors.WRONG_CONTEXT); | ||
} | ||
return command; | ||
} | ||
if (parent && !isAncestor(parent.context.path, this.path)) { | ||
throw new Error(errors.WRONG_CONTEXT); | ||
} | ||
command = new command_1.Command(name, this); | ||
if (parent) { | ||
command.parent = parent; | ||
parent.children.push(command); | ||
} | ||
return command; | ||
} | ||
command(rawName, ...args) { | ||
const description = typeof args[0] === 'string' ? args.shift() : undefined; | ||
const config = { description, ...args[0] }; | ||
const [name] = rawName.split(/\s/, 1); | ||
const declaration = rawName.slice(name.length); | ||
const segments = name.split(/(?=[\\./])/); | ||
let command; | ||
segments.forEach((name, index) => { | ||
if (index === segments.length - 1) | ||
name += declaration; | ||
if (!index) | ||
return command = this._getCommandByParent(name); | ||
if (name.charCodeAt(0) === 46) { | ||
command = this._getCommandByParent(command.name + name, command); | ||
const [path] = rawName.split(' ', 1); | ||
const declaration = rawName.slice(path.length); | ||
let parent = null; | ||
path.toLowerCase().split(/(?=[\\./])/).forEach((segment) => { | ||
const code = segment.charCodeAt(0); | ||
const name = code === 46 ? parent.name + segment : code === 47 ? segment.slice(1) : segment; | ||
let command = this.app._commandMap[name]; | ||
if (command) { | ||
if (parent) { | ||
if (command === parent) { | ||
throw new Error(errors.INVALID_SUBCOMMAND); | ||
} | ||
if (command.parent) { | ||
if (command.parent !== parent) { | ||
throw new Error(errors.INVALID_SUBCOMMAND); | ||
} | ||
} | ||
else if (parent.context.contain(command.context)) { | ||
command.parent = parent; | ||
parent.children.push(command); | ||
} | ||
else { | ||
throw new Error(errors.INVALID_CONTEXT); | ||
} | ||
} | ||
return parent = command; | ||
} | ||
else { | ||
command = this._getCommandByParent(name.slice(1), command); | ||
const context = parent ? this.intersect(parent.context) : this; | ||
if (context.identifier === noopIdentifier) { | ||
throw new Error(errors.INVALID_CONTEXT); | ||
} | ||
command = new command_1.Command(name, declaration, context); | ||
if (parent) { | ||
command.parent = parent; | ||
parent.children.push(command); | ||
} | ||
parent = command; | ||
}); | ||
Object.assign(command.config, config); | ||
return command; | ||
Object.assign(parent.config, config); | ||
return parent; | ||
} | ||
@@ -108,9 +174,8 @@ _getCommandByRawName(name) { | ||
getCommand(name, meta) { | ||
const path = meta ? meta.$path : this.path; | ||
const command = this._getCommandByRawName(name); | ||
return command && isAncestor(command.context.path, path) && command; | ||
return command && command.context.match(meta) && command; | ||
} | ||
runCommand(name, meta, args = [], options = {}, rest = '') { | ||
const command = this._getCommandByRawName(name); | ||
if (!command || !isAncestor(command.context.path, meta.$path)) { | ||
if (!command || !command.context.match(meta)) { | ||
return meta.$send(messages.COMMAND_NOT_FOUND); | ||
@@ -123,19 +188,3 @@ } | ||
} | ||
_getEventTypes(path) { | ||
if (path.startsWith(this.path)) { | ||
let lastEvent = ''; | ||
const events = []; | ||
for (let segment of path.slice(this.path.length).split('/')) { | ||
if (!isNaN(segment) || prefixTypes.includes(segment)) | ||
segment = lastEvent ? '*' : ''; | ||
if (segment) | ||
events.push(lastEvent = lastEvent ? `${lastEvent}/${segment}` : segment); | ||
} | ||
return events; | ||
} | ||
else { | ||
return []; | ||
} | ||
} | ||
} | ||
exports.Context = Context; |
export declare const DUPLICATE_COMMAND = "duplicate command names"; | ||
export declare const DUPLICATE_OPTION = "duplicate option names"; | ||
export declare const EXISTING_SUBCOMMAND = "cannot set existing command as subcommand"; | ||
export declare const EXPECT_COMMAND_NAME = "expect a command name"; | ||
export declare const INVALID_CHARACTER = "invalid characters"; | ||
export declare const INVALID_CONTEXT = "invalid context path"; | ||
export declare const INVALID_IDENTIFIER = "invalid context identifier"; | ||
export declare const INVALID_SUBCOMMAND = "invalid subcommand"; | ||
export declare const ISOLATED_NEXT = "isolated next function"; | ||
export declare const NO_CORRESPONDING_APP = "no corresponding app"; | ||
export declare const PREMIDDLEWARE_INTERCEPTION = "premiddlewares interception"; | ||
export declare const WRONG_CONTEXT = "invalid context path"; | ||
export declare const WRONG_SUBCOMMAND = "invalid subcommand"; |
@@ -5,9 +5,6 @@ "use strict"; | ||
exports.DUPLICATE_OPTION = 'duplicate option names'; | ||
exports.EXISTING_SUBCOMMAND = 'cannot set existing command as subcommand'; | ||
exports.EXPECT_COMMAND_NAME = 'expect a command name'; | ||
exports.INVALID_CHARACTER = 'invalid characters'; | ||
exports.INVALID_CONTEXT = 'invalid context path'; | ||
exports.INVALID_IDENTIFIER = 'invalid context identifier'; | ||
exports.INVALID_SUBCOMMAND = 'invalid subcommand'; | ||
exports.ISOLATED_NEXT = 'isolated next function'; | ||
exports.NO_CORRESPONDING_APP = 'no corresponding app'; | ||
exports.PREMIDDLEWARE_INTERCEPTION = 'premiddlewares interception'; | ||
exports.WRONG_CONTEXT = 'invalid context path'; | ||
exports.WRONG_SUBCOMMAND = 'invalid subcommand'; |
@@ -10,2 +10,3 @@ "use strict"; | ||
__export(require("./database")); | ||
__export(require("./meta")); | ||
__export(require("./parser")); | ||
@@ -12,0 +13,0 @@ __export(require("./sender")); |
@@ -17,3 +17,9 @@ import { GroupData, User } from './database'; | ||
} | ||
export declare enum contextTypes { | ||
user = 0, | ||
group = 1, | ||
discuss = 2 | ||
} | ||
export declare type MessageMeta = Meta<'message'>; | ||
export declare type ContextType = keyof typeof contextTypes; | ||
/** CQHTTP Meta Information */ | ||
@@ -24,2 +30,4 @@ export interface Meta<T extends PostType = PostType> { | ||
$group?: GroupData; | ||
$type?: ContextType; | ||
$subId?: number; | ||
$send?: (message: string) => Promise<number>; | ||
@@ -26,0 +34,0 @@ postType?: T; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var contextTypes; | ||
(function (contextTypes) { | ||
contextTypes[contextTypes["user"] = 0] = "user"; | ||
contextTypes[contextTypes["group"] = 1] = "group"; | ||
contextTypes[contextTypes["discuss"] = 2] = "discuss"; | ||
})(contextTypes = exports.contextTypes || (exports.contextTypes = {})); |
@@ -1,2 +0,2 @@ | ||
import { NextFunction, Context } from './context'; | ||
import { NextFunction } from './context'; | ||
import { UserData } from './database'; | ||
@@ -12,3 +12,2 @@ import { Command } from './command'; | ||
export declare function getTargetId(target: string): number; | ||
export declare function assertContextType(ctx: Context, type: 'user' | 'group' | 'discuss'): void; | ||
interface SuggestOptions { | ||
@@ -20,3 +19,3 @@ target: string; | ||
prefix: string; | ||
postfix: string; | ||
suffix: string; | ||
command: Command | ((suggestion: string) => Command); | ||
@@ -23,0 +22,0 @@ execute: (suggestion: string, meta: MessageMeta, next: NextFunction) => any; |
@@ -70,8 +70,2 @@ "use strict"; | ||
exports.getTargetId = getTargetId; | ||
function assertContextType(ctx, type) { | ||
if (!ctx.id || !ctx.path.slice(1).startsWith(type)) { | ||
throw new Error(`expect a ${type} context, received path: ${ctx.path}`); | ||
} | ||
} | ||
exports.assertContextType = assertContextType; | ||
exports.SIMILARITY_COEFFICIENT = 0.4; | ||
@@ -82,3 +76,3 @@ function findSimilar(target) { | ||
function showSuggestions(options) { | ||
const { target, items, meta, next, prefix, postfix, execute } = options; | ||
const { target, items, meta, next, prefix, suffix, execute } = options; | ||
const suggestions = items.filter(findSimilar(target)); | ||
@@ -116,3 +110,3 @@ if (!suggestions.length) | ||
command.context.premiddleware(middleware); | ||
message += postfix; | ||
message += suffix; | ||
} | ||
@@ -119,0 +113,0 @@ await meta.$send(message); |
{ | ||
"name": "koishi-core", | ||
"version": "0.2.6", | ||
"version": "0.2.7", | ||
"main": "dist/index.js", | ||
"typings": "dist/index.d.ts", | ||
"files": [ | ||
"dist", | ||
"!tsconfig.tsbuildinfo" | ||
"dist" | ||
], | ||
@@ -52,3 +51,3 @@ "author": "Shigma <1700011071@pku.edu.cn>", | ||
"fs-extra": "^8.1.0", | ||
"koishi-utils": "^0.1.7", | ||
"koishi-utils": "^0.1.8", | ||
"leven": "^3.1.0", | ||
@@ -55,0 +54,0 @@ "ws": "^7.2.0" |
Sorry, the diff of this file is not supported yet
237851
28
2268
Updatedkoishi-utils@^0.1.8