koishi-core
Advanced tools
Comparing version 1.1.1 to 1.2.0
@@ -67,3 +67,2 @@ "use strict"; | ||
maxMiddlewares: 64, | ||
similarityCoefficient: 0.4, | ||
}; | ||
@@ -170,4 +169,4 @@ class App extends context_1.Context { | ||
next, | ||
prefix: '没有此命令。', | ||
suffix: '发送空行以调用推测的指令。', | ||
prefix: messages_1.messages.COMMAND_SUGGESTION_PREFIX, | ||
suffix: messages_1.messages.COMMAND_SUGGESTION_SUFFIX, | ||
items: Object.keys(this._commandMap), | ||
@@ -215,3 +214,2 @@ coefficient: this.options.similarityCoefficient, | ||
}; | ||
exports.appList.push(this); | ||
// resolve options | ||
@@ -229,2 +227,4 @@ this.options = { ...defaultOptions, ...options }; | ||
} | ||
// register application | ||
exports.appList.push(this); | ||
if (this.selfId) | ||
@@ -318,3 +318,3 @@ this.prepare(); | ||
} | ||
if (this.options.type) { | ||
if (this.server) { | ||
tasks.push(this.server.listen()); | ||
@@ -340,3 +340,3 @@ } | ||
await Promise.all(tasks); | ||
if (this.options.type) { | ||
if (this.server) { | ||
this.server.close(); | ||
@@ -348,3 +348,2 @@ } | ||
emitEvent(meta, event, ...payload) { | ||
showReceiverLog('path %s', meta.$path); | ||
for (const path in this._contexts) { | ||
@@ -368,3 +367,3 @@ const context = this._contexts[path]; | ||
executeCommandLine(message, meta, next = koishi_utils_1.noop) { | ||
if (!meta.$path) | ||
if (!('$ctxType' in meta)) | ||
this.server.parseMeta(meta); | ||
@@ -371,0 +370,0 @@ const argv = this.parseCommandLine(message, meta); |
@@ -40,3 +40,3 @@ "use strict"; | ||
} | ||
static attachUserFields(userFields, { command, options }) { | ||
static attachUserFields(userFields, { command, options = {} }) { | ||
if (!command) | ||
@@ -177,3 +177,3 @@ return; | ||
var _a; | ||
const { meta, options, args, unknown } = argv; | ||
const { meta, options = {}, args = [], unknown = [] } = argv; | ||
this.app.emitEvent(meta, 'before-command', argv); | ||
@@ -180,0 +180,0 @@ // show help when use `-h, --help` or when there is no action |
@@ -56,8 +56,11 @@ "use strict"; | ||
exports.createGroup = createGroup; | ||
const unknownMethods = {}; | ||
const unknownOptions = {}; | ||
const subdatabases = {}; | ||
const existingDatabases = {}; | ||
function registerDatabase(name, subdatabase) { | ||
var _a, _b; | ||
subdatabases[name] = subdatabase; | ||
subdatabase._methods = {}; | ||
subdatabase._options = {}; | ||
subdatabase._methods = (_a = unknownMethods[name], (_a !== null && _a !== void 0 ? _a : {})); | ||
subdatabase._options = (_b = unknownOptions[name], (_b !== null && _b !== void 0 ? _b : {})); | ||
} | ||
@@ -67,23 +70,22 @@ exports.registerDatabase = registerDatabase; | ||
const Subdatabase = subdatabases[name]; | ||
if (!Subdatabase) | ||
return; | ||
if (Subdatabase._manager) { | ||
const config = Subdatabase._manager.config[name]; | ||
if (!config) | ||
return; | ||
if (!Subdatabase._manager.database[name]) { | ||
Subdatabase._manager.createSubdatabase(name, config); | ||
} | ||
Subdatabase._manager.injectMethods(name, table, methods); | ||
let methodMap; | ||
let optionMap; | ||
// inject before subdatabase was registered | ||
if (!Subdatabase) { | ||
methodMap = unknownMethods[name] || (unknownMethods[name] = {}); | ||
optionMap = unknownOptions[name] || (unknownOptions[name] = {}); | ||
} | ||
else { | ||
Subdatabase._methods[table] = { | ||
...Subdatabase._methods[table], | ||
...methods, | ||
}; | ||
optionMap = Subdatabase._options; | ||
if (Subdatabase._manager) { | ||
// inject after application was created | ||
Subdatabase._manager.injectMethods(name, table, methods); | ||
methodMap = {}; | ||
} | ||
else { | ||
methodMap = Subdatabase._methods; | ||
} | ||
} | ||
Subdatabase._options[table] = { | ||
...Subdatabase._options[table], | ||
...options, | ||
}; | ||
methodMap[table] = { ...methodMap[table], ...methods }; | ||
optionMap[table] = { ...optionMap[table], ...options }; | ||
} | ||
@@ -90,0 +92,0 @@ exports.injectMethods = injectMethods; |
@@ -24,5 +24,16 @@ import { User, Group } from './database'; | ||
export declare type ContextType = keyof typeof contextTypes; | ||
export interface ResponsePayload { | ||
delete?: boolean; | ||
ban?: boolean; | ||
banDuration?: number; | ||
kick?: boolean; | ||
reply?: string; | ||
autoEscape?: boolean; | ||
atSender?: boolean; | ||
approve?: boolean; | ||
remark?: string; | ||
reason?: string; | ||
} | ||
/** CQHTTP Meta Information */ | ||
export interface Meta<T extends PostType = PostType> { | ||
$path?: string; | ||
$user?: User; | ||
@@ -32,3 +43,3 @@ $group?: Group; | ||
$ctxType?: ContextType; | ||
$response?: (data: any) => void; | ||
$response?: (payload: ResponsePayload) => void; | ||
$delete?: () => Promise<void>; | ||
@@ -35,0 +46,0 @@ $kick?: () => Promise<void>; |
@@ -20,6 +20,6 @@ import { App } from './app'; | ||
app: App; | ||
private _get; | ||
protected _get: (action: string, params: Record<string, any>) => Promise<CQResponse>; | ||
constructor(app: App); | ||
get<T = any>(action: string, params?: object, silent?: boolean): Promise<T>; | ||
private getAsync; | ||
get<T = any>(action: string, params?: Record<string, any>, silent?: boolean): Promise<T>; | ||
getAsync(action: string, params?: Record<string, any>): Promise<void>; | ||
private _assertInteger; | ||
@@ -26,0 +26,0 @@ private _assertElement; |
@@ -25,7 +25,7 @@ "use strict"; | ||
if (type === 'http') { | ||
const headers = {}; | ||
if (app.options.token) { | ||
headers.Authorization = `Token ${app.options.token}`; | ||
} | ||
this._get = async (action, params = {}) => { | ||
this._get = async (action, params) => { | ||
const headers = {}; | ||
if (app.options.token) { | ||
headers.Authorization = `Token ${app.options.token}`; | ||
} | ||
const uri = new URL(action, this.app.options.server).href; | ||
@@ -37,7 +37,9 @@ const { data } = await axios_1.default.get(uri, { params, headers }); | ||
else if (type === 'ws') { | ||
const server = app.server; | ||
this._get = (action, params = {}) => server.send({ action, params }); | ||
this._get = (action, params) => { | ||
const server = app.server; | ||
return server.send({ action, params }); | ||
}; | ||
} | ||
} | ||
async get(action, params, silent = false) { | ||
async get(action, params = {}, silent = false) { | ||
showSenderLog('request %s %o', action, params); | ||
@@ -57,3 +59,3 @@ const response = await this._get(action, koishi_utils_1.snakeCase(params)); | ||
} | ||
async getAsync(action, params) { | ||
async getAsync(action, params = {}) { | ||
if (this.app.server.versionLessThan(4)) { | ||
@@ -78,5 +80,5 @@ await this.get(action, params, true); | ||
} | ||
_assertVersion(label, major, minor = 0, patch = 0) { | ||
_assertVersion(label, major, minor, patch = 0) { | ||
if (this.app.server.versionLessThan(major, minor, patch)) { | ||
throw new Error(`${label} requires CQHTTP version >= ${major}.${minor}`); | ||
throw new Error(`${label} requires CQHTTP version >= ${major}.${minor}.${patch}`); | ||
} | ||
@@ -86,5 +88,3 @@ } | ||
const sendType = $ctxType === 'user' ? 'private' : $ctxType; | ||
const $path = `/${$ctxType}/${$ctxId}/send/`; | ||
return { | ||
$path, | ||
$ctxId, | ||
@@ -91,0 +91,0 @@ $ctxType, |
@@ -32,3 +32,2 @@ /// <reference types="node" /> | ||
private _listeners; | ||
constructor(app: App); | ||
send(data: any): Promise<CQResponse>; | ||
@@ -39,2 +38,3 @@ _listen(): Promise<void>; | ||
export declare type ServerType = 'http' | 'ws'; | ||
export declare const serverMap: Record<ServerType, Record<keyof any, Server>>; | ||
export declare function createServer(app: App): Server; |
@@ -102,9 +102,5 @@ "use strict"; | ||
// generate path | ||
const path = (ctxType ? `/${ctxType}/${ctxId}/` : '/') + events[0]; | ||
Object.defineProperty(meta, '$path', { value: path }); | ||
Object.defineProperty(meta, '$ctxId', { value: ctxId }); | ||
Object.defineProperty(meta, '$ctxType', { value: ctxType }); | ||
const app = this.appMap[meta.selfId]; | ||
if (!app) | ||
return events; | ||
// add context properties | ||
@@ -182,12 +178,18 @@ if (meta.postType === 'message') { | ||
this.isListening = true; | ||
await this._listen(); | ||
if (this.versionLessThan(3)) { | ||
throw new Error(messages_1.errors.UNSUPPORTED_CQHTTP_VERSION); | ||
try { | ||
await this._listen(); | ||
if (this.versionLessThan(3)) { | ||
throw new Error(messages_1.errors.UNSUPPORTED_CQHTTP_VERSION); | ||
} | ||
else if (this.versionLessThan(3, 4)) { | ||
const apps = this.appList.filter(app => app.options.type && !app.selfId); | ||
if (apps.length > 1) | ||
throw new Error(messages_1.errors.MULTIPLE_ANONYMOUS_BOTS); | ||
const info = await apps[0].sender.getLoginInfo(); | ||
apps[0].prepare(info.userId); | ||
} | ||
} | ||
else if (this.versionLessThan(3, 4)) { | ||
const apps = this.appList.filter(app => app.options.type && !app.selfId); | ||
if (apps.length > 1) | ||
throw new Error(messages_1.errors.MULTIPLE_ANONYMOUS_BOTS); | ||
const info = await apps[0].sender.getLoginInfo(); | ||
apps[0].prepare(info.userId); | ||
catch (error) { | ||
this.close(); | ||
throw error; | ||
} | ||
@@ -256,2 +258,3 @@ } | ||
async _listen() { | ||
showServerLog('http server opening'); | ||
const { port } = this.appList[0].options; | ||
@@ -265,3 +268,3 @@ this.server.listen(port); | ||
} | ||
showServerLog('listen to port', port); | ||
showServerLog('http server listen to', port); | ||
} | ||
@@ -276,10 +279,5 @@ _close() { | ||
class WsClient extends Server { | ||
constructor(app) { | ||
super(app); | ||
constructor() { | ||
super(...arguments); | ||
this._listeners = {}; | ||
this.socket = new ws_1.default(app.options.server, { | ||
headers: { | ||
Authorization: `Bearer ${app.options.token}`, | ||
}, | ||
}); | ||
} | ||
@@ -298,2 +296,8 @@ send(data) { | ||
return new Promise((resolve, reject) => { | ||
showServerLog('websocket client opening'); | ||
const headers = {}; | ||
const { token, server } = this.appList[0].options; | ||
if (token) | ||
headers.Authorization = `Bearer ${token}`; | ||
this.socket = new ws_1.default(server, { headers }); | ||
this.socket.once('error', reject); | ||
@@ -312,2 +316,3 @@ this.socket.once('open', () => { | ||
data = data.toString(); | ||
showServerLog('receive', data); | ||
let parsed; | ||
@@ -318,3 +323,3 @@ try { | ||
catch (error) { | ||
return reject(data); | ||
return reject(new Error(data)); | ||
} | ||
@@ -344,10 +349,7 @@ if (!resolved) { | ||
this.socket.close(); | ||
showServerLog('ws client closed'); | ||
showServerLog('websocket client closed'); | ||
} | ||
} | ||
exports.WsClient = WsClient; | ||
const serverTypes = { | ||
http: ['port', {}, HttpServer], | ||
ws: ['server', {}, WsClient], | ||
}; | ||
exports.serverMap = { http: {}, ws: {} }; | ||
function createServer(app) { | ||
@@ -358,6 +360,15 @@ if (typeof app.options.type !== 'string') { | ||
app.options.type = app.options.type.toLowerCase(); | ||
if (!serverTypes[app.options.type]) { | ||
let key, Server; | ||
if (app.options.type === 'http') { | ||
key = 'port'; | ||
Server = HttpServer; | ||
} | ||
else if (app.options.type === 'ws') { | ||
key = 'server'; | ||
Server = WsClient; | ||
} | ||
else { | ||
throw new Error(messages_1.errors.UNSUPPORTED_SERVER_TYPE); | ||
} | ||
const [key, serverMap, Server] = serverTypes[app.options.type]; | ||
const servers = exports.serverMap[app.options.type]; | ||
const value = app.options[key]; | ||
@@ -367,7 +378,7 @@ if (!value) { | ||
} | ||
if (value in serverMap) { | ||
return serverMap[value].bind(app); | ||
if (value in servers) { | ||
return servers[value].bind(app); | ||
} | ||
return serverMap[value] = new Server(app); | ||
return servers[value] = new Server(app); | ||
} | ||
exports.createServer = createServer; |
@@ -13,3 +13,3 @@ import { NextFunction } from './context'; | ||
suffix: string; | ||
coefficient: number; | ||
coefficient?: number; | ||
command: Command | ((suggestion: string) => Command); | ||
@@ -16,0 +16,0 @@ execute: (suggestion: string, meta: MessageMeta, next: NextFunction) => any; |
@@ -7,2 +7,3 @@ "use strict"; | ||
const koishi_utils_1 = require("koishi-utils"); | ||
const command_1 = require("./command"); | ||
const messages_1 = require("./messages"); | ||
@@ -35,3 +36,3 @@ const util_1 = require("util"); | ||
function showSuggestions(options) { | ||
const { target, items, meta, next, prefix, suffix, execute, coefficient } = options; | ||
const { target, items, meta, next, prefix, suffix, execute, coefficient = 0.4 } = options; | ||
const suggestions = items.filter(findSimilar(target, coefficient)); | ||
@@ -46,11 +47,8 @@ if (!suggestions.length) | ||
const identifier = meta.userId + meta.$ctxType + meta.$ctxId; | ||
const fields = Array.from(command._userFields); | ||
if (!fields.includes('name')) | ||
fields.push('name'); | ||
if (!fields.includes('usage')) | ||
fields.push('usage'); | ||
if (!fields.includes('authority')) | ||
fields.push('authority'); | ||
const userFields = new Set(['name']); | ||
const groupFields = new Set(); | ||
command_1.Command.attachUserFields(userFields, { command, meta }); | ||
command_1.Command.attachGroupFields(groupFields, { command, meta }); | ||
const middleware = async (meta, next) => { | ||
var _a; | ||
var _a, _b; | ||
if (meta.userId + meta.$ctxType + meta.$ctxId !== identifier) | ||
@@ -60,3 +58,6 @@ return next(); | ||
if (!meta.message.trim()) { | ||
meta.$user = await ((_a = command.context.database) === null || _a === void 0 ? void 0 : _a.observeUser(meta.userId, 0, fields)); | ||
meta.$user = await ((_a = command.context.database) === null || _a === void 0 ? void 0 : _a.observeUser(meta.userId, Array.from(userFields))); | ||
if (meta.messageType === 'group') { | ||
meta.$group = await ((_b = command.context.database) === null || _b === void 0 ? void 0 : _b.observeGroup(meta.groupId, Array.from(groupFields))); | ||
} | ||
return execute(suggestions[0], meta, next); | ||
@@ -63,0 +64,0 @@ } |
{ | ||
"name": "koishi-core", | ||
"description": "Core features for Koishi", | ||
"version": "1.1.1", | ||
"version": "1.2.0", | ||
"main": "dist/index.js", | ||
@@ -37,7 +37,7 @@ "typings": "dist/index.d.ts", | ||
"@types/ws": "^6.0.4", | ||
"koishi-database-level": "^1.0.3", | ||
"get-port": "^5.1.0", | ||
"koishi-test-utils": "^1.0.3" | ||
}, | ||
"dependencies": { | ||
"axios": "^0.19.0", | ||
"axios": "^0.19.1", | ||
"debug": "^4.1.1", | ||
@@ -44,0 +44,0 @@ "escape-string-regexp": "^2.0.0", |
116663
2882
Updatedaxios@^0.19.1