koishi-core
Advanced tools
Comparing version 1.0.0-alpha.7 to 1.0.0-alpha.8
@@ -43,2 +43,3 @@ import { Server, ServerType } from './server'; | ||
_middlewares: [Context, Middleware][]; | ||
private _isReady; | ||
private _middlewareCounter; | ||
@@ -57,3 +58,2 @@ private _middlewareSet; | ||
stop(): Promise<void>; | ||
dispatchMeta(meta: Meta, emitEvents?: boolean): Promise<void>; | ||
emitEvent<K extends Events>(meta: Meta, event: K, ...payload: Parameters<EventMap[K]>): void; | ||
@@ -60,0 +60,0 @@ private _preprocess; |
157
dist/app.js
@@ -80,2 +80,3 @@ "use strict"; | ||
this._middlewares = []; | ||
this._isReady = false; | ||
this._middlewareCounter = 0; | ||
@@ -142,5 +143,2 @@ this._middlewareSet = new Set(); | ||
} | ||
else if (meta.messageType === 'group' && !fields.includes('talkativeness')) { | ||
fields.push('talkativeness'); | ||
} | ||
if (this.database) { | ||
@@ -157,4 +155,2 @@ // attach user data | ||
const isAssignee = meta.$group.assignee === this.selfId; | ||
if (isAssignee && !parsedArgv) | ||
utils_1.updateActivity(user.talkativeness, meta.groupId); | ||
const noCommand = meta.$group.flag & database_1.GroupFlag.noCommand; | ||
@@ -212,17 +208,15 @@ const noResponse = meta.$group.flag & database_1.GroupFlag.noResponse || !isAssignee; | ||
const next = async (fallback) => { | ||
var _a, _b; | ||
if (!this._middlewareSet.has(counter)) { | ||
return this.emitEvent(meta, 'error', new Error(errors.ISOLATED_NEXT)); | ||
return this.receiver.emit('error', new Error(errors.ISOLATED_NEXT)); | ||
} | ||
if (fallback) | ||
middlewares.push((_, next) => fallback(next)); | ||
const middleware = middlewares[index++]; | ||
if (middleware) { | ||
try { | ||
return middleware(meta, next); | ||
} | ||
catch (error) { | ||
this.emitEvent(meta, 'error/middleware', error); | ||
this.emitEvent(meta, 'error', error); | ||
} | ||
try { | ||
return (_b = (_a = middlewares)[index++]) === null || _b === void 0 ? void 0 : _b.call(_a, meta, next); | ||
} | ||
catch (error) { | ||
this.receiver.emit('error/middleware', error); | ||
this.receiver.emit('error', error); | ||
} | ||
}; | ||
@@ -266,4 +260,10 @@ await next(); | ||
_registerSelfId(selfId) { | ||
if (selfId) | ||
var _a; | ||
if (selfId) { | ||
this.options.selfId = selfId; | ||
if (!this._isReady && ((_a = this.server) === null || _a === void 0 ? void 0 : _a.isListening)) { | ||
this.receiver.emit('ready'); | ||
this._isReady = true; | ||
} | ||
} | ||
exports.appMap[this.selfId] = this; | ||
@@ -309,2 +309,3 @@ selfIds.push(this.selfId); | ||
var _a, _b, _c; | ||
this.receiver.emit('before-connect'); | ||
const tasks = []; | ||
@@ -321,5 +322,11 @@ if (this.database) { | ||
showLog('started'); | ||
if (this.selfId && !this._isReady) { | ||
this.receiver.emit('ready'); | ||
this._isReady = true; | ||
} | ||
this.receiver.emit('connect'); | ||
} | ||
async stop() { | ||
var _a, _b, _c; | ||
this.receiver.emit('before-disconnect'); | ||
const tasks = []; | ||
@@ -336,120 +343,6 @@ if (this.database) { | ||
showLog('stopped'); | ||
this.receiver.emit('disconnect'); | ||
} | ||
async dispatchMeta(meta, emitEvents = true) { | ||
// prepare prefix | ||
let ctxType, ctxId; | ||
if (meta.groupId) { | ||
ctxType = 'group'; | ||
ctxId = meta.groupId; | ||
} | ||
else if (meta.discussId) { | ||
ctxType = 'discuss'; | ||
ctxId = meta.discussId; | ||
} | ||
else if (meta.userId) { | ||
ctxType = 'user'; | ||
ctxId = meta.userId; | ||
} | ||
// polyfill CQHTTP 3.x events | ||
// https://cqhttp.cc/docs/4.12/#/UpgradeGuide | ||
/* eslint-disable dot-notation */ | ||
if (typeof meta.anonymous === 'string') { | ||
meta.anonymous = { | ||
name: meta.anonymous, | ||
flag: meta['anonymousFlag'], | ||
}; | ||
delete meta['anonymousFlag']; | ||
// @ts-ignore | ||
} | ||
else if (meta.postType === 'event') { | ||
meta.postType = 'notice'; | ||
meta.noticeType = meta['event']; | ||
delete meta['event']; | ||
} | ||
else if (meta.postType === 'request') { | ||
meta.comment = meta.message; | ||
delete meta.message; | ||
} | ||
/* eslint-enable dot-notation */ | ||
// prepare events | ||
const events = []; | ||
if (meta.postType === 'message' || meta.postType === 'send') { | ||
events.push(meta.postType); | ||
} | ||
else if (meta.postType === 'request') { | ||
events.push('request/' + meta.requestType); | ||
} | ||
else if (meta.postType === 'notice') { | ||
events.push(meta.noticeType); | ||
} | ||
else { | ||
events.push(meta.metaEventType); | ||
} | ||
if (meta.subType) | ||
events.unshift(events[0] + '/' + meta.subType); | ||
// 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 }); | ||
showReceiverLog('path %s', path); | ||
// add context properties | ||
if (meta.postType === 'message') { | ||
if (meta.messageType === 'group') { | ||
if (this.database) { | ||
Object.defineProperty(meta, '$group', { | ||
value: await this.database.getGroup(meta.groupId), | ||
writable: true, | ||
}); | ||
} | ||
meta.$delete = async () => { | ||
if (meta.$response) | ||
return meta.$response({ delete: true }); | ||
return this.sender.deleteMsgAsync(meta.messageId); | ||
}; | ||
meta.$ban = async (duration = 30 * 60) => { | ||
if (meta.$response) | ||
return meta.$response({ ban: true, banDuration: duration }); | ||
return meta.anonymous | ||
? this.sender.setGroupAnonymousBanAsync(meta.groupId, meta.anonymous.flag, duration) | ||
: this.sender.setGroupBanAsync(meta.groupId, meta.userId, duration); | ||
}; | ||
meta.$kick = async () => { | ||
if (meta.$response) | ||
return meta.$response({ kick: true }); | ||
if (meta.anonymous) | ||
return; | ||
return this.sender.setGroupKickAsync(meta.groupId, meta.userId); | ||
}; | ||
} | ||
meta.$send = async (message, autoEscape = false) => { | ||
if (meta.$response) | ||
return meta.$response({ reply: message, autoEscape, atSender: false }); | ||
return this.sender[`send${koishi_utils_1.capitalize(meta.messageType)}MsgAsync`](ctxId, message, autoEscape); | ||
}; | ||
} | ||
else if (meta.postType === 'request') { | ||
meta.$approve = async (remark = '') => { | ||
if (meta.$response) | ||
return meta.$response({ approve: true, remark }); | ||
return meta.requestType === 'friend' | ||
? this.sender.setFriendAddRequestAsync(meta.flag, true, remark) | ||
: this.sender.setGroupAddRequestAsync(meta.flag, meta.subType, true); | ||
}; | ||
meta.$reject = async (reason = '') => { | ||
if (meta.$response) | ||
return meta.$response({ approve: false, reason }); | ||
return meta.requestType === 'friend' | ||
? this.sender.setFriendAddRequestAsync(meta.flag, false) | ||
: this.sender.setGroupAddRequestAsync(meta.flag, meta.subType, false, reason); | ||
}; | ||
} | ||
// emit events | ||
if (!emitEvents) | ||
return; | ||
for (const event of events) { | ||
this.emitEvent(meta, event, meta); | ||
} | ||
} | ||
emitEvent(meta, event, ...payload) { | ||
showReceiverLog('path %s', meta.$path); | ||
for (const path in this._contexts) { | ||
@@ -456,0 +349,0 @@ const context = this._contexts[path]; |
@@ -54,3 +54,3 @@ import { Context, NextFunction } from './context'; | ||
_shortcuts: Record<string, ShortcutConfig>; | ||
_userFields: Set<"id" | "name" | "flag" | "ignoreEnd" | "authority" | "usage" | "talkativeness">; | ||
_userFields: Set<"id" | "name" | "flag" | "ignoreEnd" | "authority" | "usage">; | ||
private _argsDef; | ||
@@ -60,2 +60,3 @@ private _optsDef; | ||
constructor(name: string, declaration: string, context: Context, config?: CommandConfig); | ||
get app(): import("./app").App; | ||
private _registerAlias; | ||
@@ -80,3 +81,3 @@ userFields(fields: Iterable<UserField>): this; | ||
parse(source: string): ParsedLine; | ||
execute(config: ParsedCommandLine, next?: NextFunction): any; | ||
execute(argv: ParsedCommandLine, next?: NextFunction): any; | ||
/** check authority and usage */ | ||
@@ -83,0 +84,0 @@ private _checkUser; |
@@ -48,8 +48,11 @@ "use strict"; | ||
} | ||
get app() { | ||
return this.context.app; | ||
} | ||
_registerAlias(name) { | ||
name = name.toLowerCase(); | ||
this._aliases.push(name); | ||
const previous = this.context.app._commandMap[name]; | ||
const previous = this.app._commandMap[name]; | ||
if (!previous) { | ||
this.context.app._commandMap[name] = this; | ||
this.app._commandMap[name] = this; | ||
} | ||
@@ -83,4 +86,4 @@ else if (previous !== this) { | ||
}; | ||
this.context.app._shortcutMap[name] = this; | ||
this.context.app._shortcuts.push(config); | ||
this.app._shortcutMap[name] = this; | ||
this.app._shortcuts.push(config); | ||
return this; | ||
@@ -137,7 +140,8 @@ } | ||
} | ||
async execute(config, next = koishi_utils_1.noop) { | ||
async execute(argv, next = koishi_utils_1.noop) { | ||
var _a; | ||
const { meta, options, args, unknown } = config; | ||
if (!config.next) | ||
config.next = next; | ||
const { meta, options, args, unknown } = argv; | ||
if (!argv.next) | ||
argv.next = next; | ||
this.app.emitEvent(meta, 'before-command', argv); | ||
// show help when use `-h, --help` or when there is no action | ||
@@ -175,8 +179,10 @@ if (!this._action || options.help && !this.config.noHelpOption) { | ||
showCommandLog('execute %s', this.name); | ||
this.app.emitEvent(meta, 'command', argv); | ||
try { | ||
return this._action(config, ...args); | ||
await this._action(argv, ...args); | ||
this.app.emitEvent(meta, 'after-command', argv); | ||
} | ||
catch (error) { | ||
this.context.app.emitEvent(meta, 'error/command', error); | ||
this.context.app.emitEvent(meta, 'error', error); | ||
this.app.receiver.emit('error/command', error); | ||
this.app.receiver.emit('error', error); | ||
} | ||
@@ -183,0 +189,0 @@ } |
/// <reference types="node" /> | ||
import { MessageMeta, Meta } from './meta'; | ||
import { Command, CommandConfig } from './command'; | ||
import { Command, CommandConfig, ParsedCommandLine } from './command'; | ||
import { EventEmitter } from 'events'; | ||
@@ -57,17 +57,17 @@ import { Sender } from './sender'; | ||
'message/other'(meta: Meta<'message'>): any; | ||
'friend_add'(meta: Meta<'notice'>): any; | ||
'group_increase'(meta: Meta<'notice'>): any; | ||
'group_increase/invite'(meta: Meta<'notice'>): any; | ||
'group_increase/approve'(meta: Meta<'notice'>): any; | ||
'group_decrease'(meta: Meta<'notice'>): any; | ||
'group_decrease/leave'(meta: Meta<'notice'>): any; | ||
'group_decrease/kick'(meta: Meta<'notice'>): any; | ||
'group_decrease/kick_me'(meta: Meta<'notice'>): any; | ||
'group_upload'(meta: Meta<'notice'>): any; | ||
'group_admin'(meta: Meta<'notice'>): any; | ||
'group_admin/set'(meta: Meta<'notice'>): any; | ||
'group_admin/unset'(meta: Meta<'notice'>): any; | ||
'group_ban'(meta: Meta<'notice'>): any; | ||
'group_ban/ban'(meta: Meta<'notice'>): any; | ||
'group_ban/lift_ban'(meta: Meta<'notice'>): any; | ||
'friend-add'(meta: Meta<'notice'>): any; | ||
'group-increase'(meta: Meta<'notice'>): any; | ||
'group-increase/invite'(meta: Meta<'notice'>): any; | ||
'group-increase/approve'(meta: Meta<'notice'>): any; | ||
'group-decrease'(meta: Meta<'notice'>): any; | ||
'group-decrease/leave'(meta: Meta<'notice'>): any; | ||
'group-decrease/kick'(meta: Meta<'notice'>): any; | ||
'group-decrease/kick-me'(meta: Meta<'notice'>): any; | ||
'group-upload'(meta: Meta<'notice'>): any; | ||
'group-admin'(meta: Meta<'notice'>): any; | ||
'group-admin/set'(meta: Meta<'notice'>): any; | ||
'group-admin/unset'(meta: Meta<'notice'>): any; | ||
'group-ban'(meta: Meta<'notice'>): any; | ||
'group-ban/ban'(meta: Meta<'notice'>): any; | ||
'group-ban/lift-ban'(meta: Meta<'notice'>): any; | ||
'request/friend'(meta: Meta<'request'>): any; | ||
@@ -81,7 +81,14 @@ 'request/group/add'(meta: Meta<'request'>): any; | ||
'send'(meta: Meta<'send'>): any; | ||
'before-send'(meta: Meta<'send'>): any; | ||
'before-command'(argv: ParsedCommandLine): any; | ||
'command'(argv: ParsedCommandLine): any; | ||
'after-command'(argv: ParsedCommandLine): any; | ||
'error'(error: Error): any; | ||
'error/command'(error: Error): any; | ||
'error/middleware'(error: Error): any; | ||
'ready'(): any; | ||
'before-connect'(): any; | ||
'connect'(): any; | ||
'connected'(): any; | ||
'before-disconnect'(): any; | ||
'disconnect'(): any; | ||
} | ||
@@ -92,4 +99,7 @@ export declare type Events = keyof EventMap; | ||
once<K extends Events>(event: K, listener: EventMap[K]): this; | ||
off<K extends Events>(event: K, listener: EventMap[K]): this; | ||
addListener<K extends Events>(event: K, listener: EventMap[K]): this; | ||
removeListener<K extends Events>(event: K, listener: EventMap[K]): this; | ||
emit<K extends Events>(event: K, ...args: Parameters<EventMap[K]>): boolean; | ||
} | ||
export {}; |
@@ -43,5 +43,2 @@ "use strict"; | ||
const noopIdentifier = ContextScope.stringify(noopScope); | ||
// @ts-ignore TODO: pending for typings | ||
// https://nodejs.org/api/events.html#events_capture_rejections_of_promises | ||
events_1.EventEmitter.captureRejections = true; | ||
class Context { | ||
@@ -48,0 +45,0 @@ constructor(identifier, _scope) { |
import { Observed } from 'koishi-utils'; | ||
import { Activity } from './utils'; | ||
export interface Usage { | ||
@@ -19,3 +18,2 @@ last?: number; | ||
usage: Record<string, Usage>; | ||
talkativeness: Activity; | ||
} | ||
@@ -22,0 +20,0 @@ export declare type User<K extends UserField = UserField> = Observed<Pick<UserData, K | 'id'>>; |
@@ -22,3 +22,2 @@ "use strict"; | ||
usage: {}, | ||
talkativeness: {}, | ||
})); | ||
@@ -25,0 +24,0 @@ function createUser(id, authority) { |
import { App } from './app'; | ||
import { GroupMemberInfo, StatusInfo, VersionInfo, FriendInfo, GroupInfo, Credentials, AccountInfo, StrangerInfo, ListedGroupInfo, VipInfo, GroupNoticeInfo } from './meta'; | ||
import { GroupMemberInfo, StatusInfo, VersionInfo, Meta, FriendInfo, GroupInfo, Credentials, AccountInfo, StrangerInfo, ListedGroupInfo, VipInfo, GroupNoticeInfo, ContextType } from './meta'; | ||
export declare class SenderError extends Error { | ||
@@ -24,6 +24,6 @@ readonly args: Record<string, any>; | ||
private getAsync; | ||
private _dispatchSendMeta; | ||
private _assertInteger; | ||
private _assertElement; | ||
private _assertVersion; | ||
_createSendMeta($ctxType: ContextType, $ctxId: number, message: string): Meta<"send">; | ||
sendGroupMsg(groupId: number, message: string, autoEscape?: boolean): Promise<number>; | ||
@@ -49,18 +49,22 @@ sendGroupMsgAsync(groupId: number, message: string, autoEscape?: boolean): Promise<void>; | ||
setGroupWholeBanAsync(groupId: number, enable?: boolean): Promise<void>; | ||
setGroupAdmin(groupId: number, userId: number, enable: boolean): Promise<void>; | ||
setGroupAdminAsync(groupId: number, userId: number, enable: boolean): Promise<void>; | ||
setGroupAnonymous(groupId: number, enable: boolean): Promise<void>; | ||
setGroupAnonymousAsync(groupId: number, enable: boolean): Promise<void>; | ||
setGroupAdmin(groupId: number, userId: number, enable?: boolean): Promise<void>; | ||
setGroupAdminAsync(groupId: number, userId: number, enable?: boolean): Promise<void>; | ||
setGroupAnonymous(groupId: number, enable?: boolean): Promise<void>; | ||
setGroupAnonymousAsync(groupId: number, enable?: boolean): Promise<void>; | ||
setGroupCard(groupId: number, userId: number, card?: string): Promise<void>; | ||
setGroupCardAsync(groupId: number, userId: number, card?: string): Promise<void>; | ||
setGroupSpecialTitle(groupId: number, userId: number, specialTitle?: string, duration?: number): Promise<void>; | ||
setGroupSpecialTitleAsync(groupId: number, userId: number, specialTitle?: string, duration?: number): Promise<void>; | ||
setGroupLeave(groupId: number, isDismiss?: boolean): Promise<void>; | ||
setGroupLeaveAsync(groupId: number, isDismiss?: boolean): Promise<void>; | ||
setGroupSpecialTitle(groupId: number, userId: number, specialTitle?: string, duration?: number): Promise<void>; | ||
setGroupSpecialTitleAsync(groupId: number, userId: number, specialTitle?: string, duration?: number): Promise<void>; | ||
setDiscussLeave(discussId: number): Promise<void>; | ||
setDiscussLeaveAsync(discussId: number): Promise<void>; | ||
setFriendAddRequest(flag: string, approve?: boolean, remark?: string): Promise<void>; | ||
setFriendAddRequestAsync(flag: string, approve?: boolean, remark?: string): Promise<void>; | ||
setGroupAddRequest(flag: string, subType: 'add' | 'invite', approve?: boolean, reason?: string): Promise<void>; | ||
setGroupAddRequestAsync(flag: string, subType: 'add' | 'invite', approve?: boolean, reason?: string): Promise<void>; | ||
setFriendAddRequest(flag: string, approve?: boolean): Promise<void>; | ||
setFriendAddRequest(flag: string, remark?: string): Promise<void>; | ||
setFriendAddRequestAsync(flag: string, approve?: boolean): Promise<void>; | ||
setFriendAddRequestAsync(flag: string, remark?: string): Promise<void>; | ||
setGroupAddRequest(flag: string, subType: 'add' | 'invite', approve?: boolean): Promise<void>; | ||
setGroupAddRequest(flag: string, subType: 'add' | 'invite', reason?: string): Promise<void>; | ||
setGroupAddRequestAsync(flag: string, subType: 'add' | 'invite', approve?: boolean): Promise<void>; | ||
setGroupAddRequestAsync(flag: string, subType: 'add' | 'invite', reason?: string): Promise<void>; | ||
getLoginInfo(): Promise<AccountInfo>; | ||
@@ -70,4 +74,4 @@ getVipInfo(): Promise<VipInfo>; | ||
getFriendList(): Promise<FriendInfo[]>; | ||
getGroupInfo(groupId: number, noCache?: boolean): Promise<GroupInfo>; | ||
getGroupList(): Promise<ListedGroupInfo[]>; | ||
getGroupInfo(groupId: string, noCache?: boolean): Promise<GroupInfo>; | ||
getGroupMemberInfo(groupId: number, userId: number, noCache?: boolean): Promise<GroupMemberInfo>; | ||
@@ -83,4 +87,4 @@ getGroupMemberList(groupId: number): Promise<GroupMemberInfo[]>; | ||
getImage(file: string): Promise<string>; | ||
canSendRecord(): Promise<boolean>; | ||
canSendImage(): Promise<boolean>; | ||
canSendRecord(): Promise<boolean>; | ||
getStatus(): Promise<StatusInfo>; | ||
@@ -87,0 +91,0 @@ getVersionInfo(): Promise<VersionInfo>; |
@@ -55,24 +55,21 @@ "use strict"; | ||
} | ||
getAsync(action, params) { | ||
return this.app.server.versionLessThan(4) | ||
? this.get(action, params, true) | ||
: this.get(action + '_async', params); | ||
async getAsync(action, params) { | ||
if (this.app.server.versionLessThan(4)) { | ||
await this.get(action, params, true); | ||
} | ||
else { | ||
await this.get(action + '_async', params); | ||
} | ||
} | ||
async _dispatchSendMeta(type, subId, message, messageId) { | ||
const meta = { | ||
postType: 'send', | ||
sendType: type === 'user' ? 'private' : type, | ||
messageId, | ||
message, | ||
}; | ||
meta[type + 'Id'] = subId; | ||
await this.app.dispatchMeta(meta); | ||
} | ||
_assertInteger(name, value) { | ||
if (value === undefined) | ||
throw new Error('missing argument: ' + name); | ||
if (!koishi_utils_1.isInteger(value)) | ||
throw new Error('missing or invalid argument: ' + name); | ||
throw new Error('invalid argument: ' + name); | ||
} | ||
_assertElement(name, value, array) { | ||
if (value === undefined) | ||
throw new Error('missing argument: ' + name); | ||
if (!array.includes(value)) | ||
throw new Error('missing or invalid argument: ' + name); | ||
throw new Error('invalid argument: ' + name); | ||
} | ||
@@ -84,2 +81,15 @@ _assertVersion(label, major, minor = 0, patch = 0) { | ||
} | ||
_createSendMeta($ctxType, $ctxId, message) { | ||
const sendType = $ctxType === 'user' ? 'private' : $ctxType; | ||
const $path = `/${$ctxType}/${$ctxId}/send/`; | ||
return { | ||
$path, | ||
$ctxId, | ||
$ctxType, | ||
message, | ||
sendType, | ||
postType: 'send', | ||
[$ctxType + 'Id']: $ctxId, | ||
}; | ||
} | ||
async sendGroupMsg(groupId, message, autoEscape) { | ||
@@ -89,4 +99,7 @@ this._assertInteger('groupId', groupId); | ||
return; | ||
const meta = this._createSendMeta('group', groupId, message); | ||
this.app.emitEvent(meta, 'before-send', meta); | ||
const { messageId } = await this.get('send_group_msg', { groupId, message, autoEscape }); | ||
await this._dispatchSendMeta('group', groupId, message, messageId); | ||
meta.messageId = messageId; | ||
this.app.emitEvent(meta, 'send', meta); | ||
return messageId; | ||
@@ -99,3 +112,2 @@ } | ||
await this.get('send_group_msg_async', { groupId, message, autoEscape }); | ||
return this._dispatchSendMeta('group', groupId, message); | ||
} | ||
@@ -106,4 +118,7 @@ async sendDiscussMsg(discussId, message, autoEscape) { | ||
return; | ||
const meta = this._createSendMeta('discuss', discussId, message); | ||
this.app.emitEvent(meta, 'before-send', meta); | ||
const { messageId } = await this.get('send_discuss_msg', { discussId, message, autoEscape }); | ||
await this._dispatchSendMeta('discuss', discussId, message, messageId); | ||
meta.messageId = messageId; | ||
this.app.emitEvent(meta, 'send', meta); | ||
return messageId; | ||
@@ -116,3 +131,2 @@ } | ||
await this.get('send_discuss_msg_async', { discussId, message, autoEscape }); | ||
return this._dispatchSendMeta('discuss', discussId, message); | ||
} | ||
@@ -123,4 +137,7 @@ async sendPrivateMsg(userId, message, autoEscape) { | ||
return; | ||
const meta = this._createSendMeta('user', userId, message); | ||
this.app.emitEvent(meta, 'before-send', meta); | ||
const { messageId } = await this.get('send_private_msg', { userId, message, autoEscape }); | ||
await this._dispatchSendMeta('user', userId, message, messageId); | ||
meta.messageId = messageId; | ||
this.app.emitEvent(meta, 'send', meta); | ||
return messageId; | ||
@@ -133,3 +150,2 @@ } | ||
await this.get('send_private_msg_async', { userId, message, autoEscape }); | ||
return this._dispatchSendMeta('user', userId, message); | ||
} | ||
@@ -139,3 +155,3 @@ async deleteMsg(messageId) { | ||
this._assertVersion('sender.deleteMsg()', 3, 3); | ||
return this.get('delete_msg', { messageId }); | ||
await this.get('delete_msg', { messageId }); | ||
} | ||
@@ -157,3 +173,3 @@ async deleteMsgAsync(messageId) { | ||
} | ||
async setGroupKick(groupId, userId, rejectAddRequest = false) { | ||
async setGroupKick(groupId, userId, rejectAddRequest) { | ||
this._assertInteger('groupId', groupId); | ||
@@ -163,3 +179,3 @@ this._assertInteger('userId', userId); | ||
} | ||
async setGroupKickAsync(groupId, userId, rejectAddRequest = false) { | ||
async setGroupKickAsync(groupId, userId, rejectAddRequest) { | ||
this._assertInteger('groupId', groupId); | ||
@@ -169,3 +185,3 @@ this._assertInteger('userId', userId); | ||
} | ||
async setGroupBan(groupId, userId, duration = 30 * 60) { | ||
async setGroupBan(groupId, userId, duration) { | ||
this._assertInteger('groupId', groupId); | ||
@@ -175,3 +191,3 @@ this._assertInteger('userId', userId); | ||
} | ||
async setGroupBanAsync(groupId, userId, duration = 30 * 60) { | ||
async setGroupBanAsync(groupId, userId, duration) { | ||
this._assertInteger('groupId', groupId); | ||
@@ -181,3 +197,3 @@ this._assertInteger('userId', userId); | ||
} | ||
async setGroupAnonymousBan(groupId, meta, duration = 30 * 60) { | ||
async setGroupAnonymousBan(groupId, meta, duration) { | ||
this._assertInteger('groupId', groupId); | ||
@@ -187,6 +203,6 @@ if (!meta) | ||
const args = { groupId, duration }; | ||
args[typeof meta === 'string' ? 'flag' : 'anomymous'] = meta; | ||
args[typeof meta === 'string' ? 'flag' : 'anonymous'] = meta; | ||
await this.get('set_group_anonymous_ban', args); | ||
} | ||
async setGroupAnonymousBanAsync(groupId, meta, duration = 30 * 60) { | ||
async setGroupAnonymousBanAsync(groupId, meta, duration) { | ||
this._assertInteger('groupId', groupId); | ||
@@ -196,3 +212,3 @@ if (!meta) | ||
const args = { groupId, duration }; | ||
args[typeof meta === 'string' ? 'flag' : 'anomymous'] = meta; | ||
args[typeof meta === 'string' ? 'flag' : 'anonymous'] = meta; | ||
return this.getAsync('set_group_anonymous_ban', args); | ||
@@ -208,3 +224,3 @@ } | ||
} | ||
async setGroupAdmin(groupId, userId, enable) { | ||
async setGroupAdmin(groupId, userId, enable = true) { | ||
this._assertInteger('groupId', groupId); | ||
@@ -214,3 +230,3 @@ this._assertInteger('userId', userId); | ||
} | ||
async setGroupAdminAsync(groupId, userId, enable) { | ||
async setGroupAdminAsync(groupId, userId, enable = true) { | ||
this._assertInteger('groupId', groupId); | ||
@@ -220,7 +236,7 @@ this._assertInteger('userId', userId); | ||
} | ||
async setGroupAnonymous(groupId, enable) { | ||
async setGroupAnonymous(groupId, enable = true) { | ||
this._assertInteger('groupId', groupId); | ||
await this.get('set_group_anonymous', { groupId, enable }); | ||
} | ||
async setGroupAnonymousAsync(groupId, enable) { | ||
async setGroupAnonymousAsync(groupId, enable = true) { | ||
this._assertInteger('groupId', groupId); | ||
@@ -232,3 +248,3 @@ return this.getAsync('set_group_anonymous', { groupId, enable }); | ||
this._assertInteger('userId', userId); | ||
await this.get('set_group_admin', { groupId, userId, card }); | ||
await this.get('set_group_card', { groupId, userId, card }); | ||
} | ||
@@ -238,12 +254,4 @@ async setGroupCardAsync(groupId, userId, card = '') { | ||
this._assertInteger('userId', userId); | ||
return this.getAsync('set_group_admin', { groupId, userId, card }); | ||
return this.getAsync('set_group_card', { groupId, userId, card }); | ||
} | ||
async setGroupLeave(groupId, isDismiss = false) { | ||
this._assertInteger('groupId', groupId); | ||
await this.get('set_group_leave', { groupId, isDismiss }); | ||
} | ||
async setGroupLeaveAsync(groupId, isDismiss = false) { | ||
this._assertInteger('groupId', groupId); | ||
return this.getAsync('set_group_leave', { groupId, isDismiss }); | ||
} | ||
async setGroupSpecialTitle(groupId, userId, specialTitle = '', duration = -1) { | ||
@@ -259,2 +267,10 @@ this._assertInteger('groupId', groupId); | ||
} | ||
async setGroupLeave(groupId, isDismiss) { | ||
this._assertInteger('groupId', groupId); | ||
await this.get('set_group_leave', { groupId, isDismiss }); | ||
} | ||
async setGroupLeaveAsync(groupId, isDismiss) { | ||
this._assertInteger('groupId', groupId); | ||
return this.getAsync('set_group_leave', { groupId, isDismiss }); | ||
} | ||
async setDiscussLeave(discussId) { | ||
@@ -268,43 +284,60 @@ this._assertInteger('discussId', discussId); | ||
} | ||
async setFriendAddRequest(flag, approve = true, remark = '') { | ||
async setFriendAddRequest(flag, info = true) { | ||
if (!flag) | ||
throw new Error('missing argument: flag'); | ||
await this.get('set_friend_add_request', { flag, approve, remark }); | ||
if (typeof info === 'string') { | ||
await this.get('set_friend_add_request', { flag, approve: true, remark: info }); | ||
} | ||
else { | ||
await this.get('set_friend_add_request', { flag, approve: info }); | ||
} | ||
} | ||
async setFriendAddRequestAsync(flag, approve = true, remark = '') { | ||
async setFriendAddRequestAsync(flag, info = true) { | ||
if (!flag) | ||
throw new Error('missing argument: flag'); | ||
return this.getAsync('set_friend_add_request', { flag, approve, remark }); | ||
if (typeof info === 'string') { | ||
return this.getAsync('set_friend_add_request', { flag, approve: true, remark: info }); | ||
} | ||
else { | ||
return this.getAsync('set_friend_add_request', { flag, approve: info }); | ||
} | ||
} | ||
async setGroupAddRequest(flag, subType, approve = true, reason = '') { | ||
async setGroupAddRequest(flag, subType, info = true) { | ||
if (!flag) | ||
throw new Error('missing argument: flag'); | ||
this._assertElement('subType', subType, ['add', 'invite']); | ||
await this.get('set_group_add_request', { flag, subType, approve, reason }); | ||
if (typeof info === 'string') { | ||
await this.get('set_group_add_request', { flag, subType, approve: false, reason: info }); | ||
} | ||
else { | ||
await this.get('set_group_add_request', { flag, subType, approve: info }); | ||
} | ||
} | ||
async setGroupAddRequestAsync(flag, subType, approve = true, reason = '') { | ||
async setGroupAddRequestAsync(flag, subType, info = true) { | ||
if (!flag) | ||
throw new Error('missing argument: flag'); | ||
this._assertElement('subType', subType, ['add', 'invite']); | ||
return this.getAsync('set_group_add_request', { flag, subType, approve, reason }); | ||
if (typeof info === 'string') { | ||
return this.getAsync('set_group_add_request', { flag, subType, approve: false, reason: info }); | ||
} | ||
else { | ||
return this.getAsync('set_group_add_request', { flag, subType, approve: info }); | ||
} | ||
} | ||
getLoginInfo() { | ||
async getLoginInfo() { | ||
return this.get('get_login_info'); | ||
} | ||
getVipInfo() { | ||
async getVipInfo() { | ||
this._assertVersion('sender.getVipInfo()', 4, 3, 1); | ||
return this.get('_get_vip_info'); | ||
} | ||
getStrangerInfo(userId, noCache = false) { | ||
async getStrangerInfo(userId, noCache) { | ||
this._assertInteger('userId', userId); | ||
return this.get('get_stranger_info', { userId, noCache }); | ||
} | ||
getFriendList() { | ||
async getFriendList() { | ||
this._assertVersion('sender.getFriendList()', 4, 12); | ||
return this.get('get_friend_list'); | ||
} | ||
getGroupList() { | ||
return this.get('get_group_list'); | ||
} | ||
getGroupInfo(groupId, noCache = false) { | ||
async getGroupInfo(groupId, noCache) { | ||
this._assertInteger('groupId', groupId); | ||
@@ -316,3 +349,6 @@ this._assertVersion('sender.getGroupInfo()', 4, 0, 1); | ||
} | ||
getGroupMemberInfo(groupId, userId, noCache = false) { | ||
async getGroupList() { | ||
return this.get('get_group_list'); | ||
} | ||
async getGroupMemberInfo(groupId, userId, noCache) { | ||
this._assertInteger('groupId', groupId); | ||
@@ -322,7 +358,7 @@ this._assertInteger('userId', userId); | ||
} | ||
getGroupMemberList(groupId) { | ||
async getGroupMemberList(groupId) { | ||
this._assertInteger('groupId', groupId); | ||
return this.get('get_group_member_list', { groupId }); | ||
} | ||
getGroupNotice(groupId) { | ||
async getGroupNotice(groupId) { | ||
this._assertInteger('groupId', groupId); | ||
@@ -334,2 +370,6 @@ this._assertVersion('sender.getGroupNotice()', 4, 9); | ||
this._assertInteger('groupId', groupId); | ||
if (!title) | ||
throw new Error('missing argument: title'); | ||
if (!content) | ||
throw new Error('missing argument: content'); | ||
this._assertVersion('sender.sendGroupNotice()', 4, 9); | ||
@@ -340,2 +380,6 @@ await this.get('_send_group_notice', { groupId, title, content }); | ||
this._assertInteger('groupId', groupId); | ||
if (!title) | ||
throw new Error('missing argument: title'); | ||
if (!content) | ||
throw new Error('missing argument: content'); | ||
this._assertVersion('sender.sendGroupNotice()', 4, 9); | ||
@@ -352,6 +396,9 @@ return this.getAsync('_send_group_notice', { groupId, title, content }); | ||
} | ||
getCredentials() { | ||
async getCredentials() { | ||
return this.get('get_credentials'); | ||
} | ||
async getRecord(file, outFormat, fullPath = false) { | ||
async getRecord(file, outFormat, fullPath) { | ||
if (!file) | ||
throw new Error('missing argument: file'); | ||
this._assertElement('outFormat', outFormat, ['mp3', 'amr', 'wma', 'm4a', 'spx', 'ogg', 'wav', 'flac']); | ||
this._assertVersion('sender.getRecord()', 3, 3); | ||
@@ -362,2 +409,4 @@ const response = await this.get('get_record', { file, outFormat, fullPath }); | ||
async getImage(file) { | ||
if (!file) | ||
throw new Error('missing argument: file'); | ||
this._assertVersion('sender.getImage()', 4, 8); | ||
@@ -367,2 +416,7 @@ const response = await this.get('get_image', { file }); | ||
} | ||
async canSendRecord() { | ||
this._assertVersion('sender.canSendRecord()', 4, 8); | ||
const { yes } = await this.get('can_send_record'); | ||
return yes; | ||
} | ||
async canSendImage() { | ||
@@ -373,7 +427,2 @@ this._assertVersion('sender.canSendImage()', 4, 8); | ||
} | ||
async canSendRecord() { | ||
this._assertVersion('sender.canSendRecord()', 4, 8); | ||
const { yes } = await this.get('can_send_record'); | ||
return yes; | ||
} | ||
getStatus() { | ||
@@ -380,0 +429,0 @@ return this.get('get_status'); |
@@ -11,7 +11,8 @@ /// <reference types="node" /> | ||
appMap: Record<number, App>; | ||
private _isListening; | ||
isListening: boolean; | ||
protected abstract _listen(): Promise<void>; | ||
abstract close(): void; | ||
constructor(app: App); | ||
protected _handleMeta(data: any): Meta<import("./meta").PostType>; | ||
protected prepareMeta(data: any): Meta<import("./meta").PostType>; | ||
dispatchMeta(meta: Meta): Promise<void>; | ||
bind(app: App): this; | ||
@@ -18,0 +19,0 @@ versionLessThan(major: number, minor?: number, patch?: number): boolean; |
@@ -26,6 +26,6 @@ "use strict"; | ||
this.appMap = {}; | ||
this._isListening = false; | ||
this.isListening = false; | ||
this.bind(app); | ||
} | ||
_handleMeta(data) { | ||
prepareMeta(data) { | ||
const meta = koishi_utils_1.camelCase(data); | ||
@@ -44,2 +44,120 @@ if (!meta.selfId) { | ||
} | ||
async dispatchMeta(meta) { | ||
// prepare prefix | ||
let ctxType, ctxId; | ||
if (meta.groupId) { | ||
ctxType = 'group'; | ||
ctxId = meta.groupId; | ||
} | ||
else if (meta.discussId) { | ||
ctxType = 'discuss'; | ||
ctxId = meta.discussId; | ||
} | ||
else if (meta.userId) { | ||
ctxType = 'user'; | ||
ctxId = meta.userId; | ||
} | ||
// polyfill CQHTTP 3.x events | ||
// https://cqhttp.cc/docs/4.12/#/UpgradeGuide | ||
/* eslint-disable dot-notation */ | ||
if (typeof meta.anonymous === 'string') { | ||
meta.anonymous = { | ||
name: meta.anonymous, | ||
flag: meta['anonymousFlag'], | ||
}; | ||
delete meta['anonymousFlag']; | ||
// @ts-ignore | ||
} | ||
else if (meta.postType === 'event') { | ||
meta.postType = 'notice'; | ||
meta.noticeType = meta['event']; | ||
delete meta['event']; | ||
} | ||
else if (meta.postType === 'request') { | ||
meta.comment = meta.message; | ||
delete meta.message; | ||
} | ||
/* eslint-enable dot-notation */ | ||
// prepare events | ||
const events = []; | ||
if (meta.postType === 'message' || meta.postType === 'send') { | ||
events.push(meta.postType); | ||
} | ||
else if (meta.postType === 'request') { | ||
events.push('request/' + meta.requestType); | ||
} | ||
else if (meta.postType === 'notice') { | ||
events.push(meta.noticeType); | ||
} | ||
else { | ||
events.push(meta.metaEventType); | ||
} | ||
if (meta.subType) | ||
events.unshift(events[0] + '/' + meta.subType); | ||
// 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; | ||
// add context properties | ||
if (meta.postType === 'message') { | ||
if (meta.messageType === 'group') { | ||
if (app.database) { | ||
Object.defineProperty(meta, '$group', { | ||
value: await app.database.getGroup(meta.groupId), | ||
writable: true, | ||
}); | ||
} | ||
meta.$delete = async () => { | ||
if (meta.$response) | ||
return meta.$response({ delete: true }); | ||
return app.sender.deleteMsgAsync(meta.messageId); | ||
}; | ||
meta.$ban = async (duration = 30 * 60) => { | ||
if (meta.$response) | ||
return meta.$response({ ban: true, banDuration: duration }); | ||
return meta.anonymous | ||
? app.sender.setGroupAnonymousBanAsync(meta.groupId, meta.anonymous.flag, duration) | ||
: app.sender.setGroupBanAsync(meta.groupId, meta.userId, duration); | ||
}; | ||
meta.$kick = async () => { | ||
if (meta.$response) | ||
return meta.$response({ kick: true }); | ||
if (meta.anonymous) | ||
return; | ||
return app.sender.setGroupKickAsync(meta.groupId, meta.userId); | ||
}; | ||
} | ||
meta.$send = async (message, autoEscape = false) => { | ||
if (meta.$response) { | ||
app.emitEvent(meta, 'before-send', app.sender._createSendMeta(ctxType, ctxId, message)); | ||
return meta.$response({ reply: message, autoEscape, atSender: false }); | ||
} | ||
return app.sender[`send${koishi_utils_1.capitalize(meta.messageType)}MsgAsync`](ctxId, message, autoEscape); | ||
}; | ||
} | ||
else if (meta.postType === 'request') { | ||
meta.$approve = async (remark = '') => { | ||
if (meta.$response) | ||
return meta.$response({ approve: true, remark }); | ||
return meta.requestType === 'friend' | ||
? app.sender.setFriendAddRequestAsync(meta.flag, remark) | ||
: app.sender.setGroupAddRequestAsync(meta.flag, meta.subType, true); | ||
}; | ||
meta.$reject = async (reason = '') => { | ||
if (meta.$response) | ||
return meta.$response({ approve: false, reason }); | ||
return meta.requestType === 'friend' | ||
? app.sender.setFriendAddRequestAsync(meta.flag, false) | ||
: app.sender.setGroupAddRequestAsync(meta.flag, meta.subType, reason); | ||
}; | ||
} | ||
// emit events | ||
for (const event of events) { | ||
app.emitEvent(meta, koishi_utils_1.paramCase(event), meta); | ||
} | ||
} | ||
bind(app) { | ||
@@ -58,5 +176,5 @@ this.appList.push(app); | ||
async listen() { | ||
if (this._isListening) | ||
if (this.isListening) | ||
return; | ||
this._isListening = true; | ||
this.isListening = true; | ||
await this._listen(); | ||
@@ -67,12 +185,8 @@ if (this.versionLessThan(3)) { | ||
else if (this.versionLessThan(3, 4)) { | ||
const anonymous = this.appList.filter(app => app.options.type && !app.selfId); | ||
if (anonymous.length > 1) | ||
const apps = this.appList.filter(app => app.options.type && !app.selfId); | ||
if (apps.length > 1) | ||
throw new Error(errors.MULTIPLE_ANONYMOUS_BOTS); | ||
const info = await anonymous[0].sender.getLoginInfo(); | ||
anonymous[0]._registerSelfId(info.userId); | ||
const info = await apps[0].sender.getLoginInfo(); | ||
apps[0]._registerSelfId(info.userId); | ||
} | ||
for (const app of this.appList) { | ||
app.receiver.emit('connect'); | ||
app.receiver.emit('connected'); | ||
} | ||
} | ||
@@ -106,3 +220,3 @@ } | ||
showServerLog('receive %o', data); | ||
const meta = this._handleMeta(data); | ||
const meta = this.prepareMeta(data); | ||
if (!meta) { | ||
@@ -112,7 +226,6 @@ res.statusCode = 403; | ||
} | ||
// ok, dispatch events | ||
// handle quick operations | ||
res.statusCode = 200; | ||
const app = this.appMap[meta.selfId]; | ||
if (app.options.quickOperationTimeout > 0) { | ||
// handle quick operations | ||
meta.$response = (data) => { | ||
@@ -134,3 +247,4 @@ clearTimeout(timer); | ||
} | ||
app.dispatchMeta(meta); | ||
// dispatch events | ||
this.dispatchMeta(meta); | ||
}); | ||
@@ -209,5 +323,5 @@ }); | ||
if ('post_type' in parsed) { | ||
const meta = this._handleMeta(parsed); | ||
const meta = this.prepareMeta(parsed); | ||
if (meta) | ||
this.appMap[meta.selfId].dispatchMeta(meta); | ||
this.dispatchMeta(meta); | ||
} | ||
@@ -214,0 +328,0 @@ else { |
import { NextFunction } from './context'; | ||
import { Command } from './command'; | ||
import { MessageMeta } from './meta'; | ||
export declare type Activity = Record<number, Record<number, number>>; | ||
export declare function updateActivity(activity: Activity, groupId: number): void; | ||
export declare function getAverageActivity(activity: Activity, date: number): number; | ||
export declare function getSenderName(meta: MessageMeta): string; | ||
@@ -8,0 +5,0 @@ export declare function getTargetId(target: string): number; |
@@ -8,31 +8,6 @@ "use strict"; | ||
const leven_1 = __importDefault(require("leven")); | ||
const PRESERVE_ACTIVITY = 7; | ||
function updateActivity(activity, groupId) { | ||
const date = koishi_utils_1.getDateNumber(); | ||
if (!activity[date]) { | ||
activity[date] = {}; | ||
const dates = Object.keys(activity); | ||
dates.slice(0, -PRESERVE_ACTIVITY).forEach(date => delete activity[date]); | ||
} | ||
if (!activity[date][groupId]) { | ||
activity[date][groupId] = 1; | ||
} | ||
else { | ||
activity[date][groupId] += 1; | ||
} | ||
} | ||
exports.updateActivity = updateActivity; | ||
function getMaxActivity(activity = {}) { | ||
return Math.max(0, ...Object.keys(activity).map(k => activity[k])); | ||
} | ||
function getAverageActivity(activity, date) { | ||
return getMaxActivity(activity[date - 1]) / 2 | ||
+ getMaxActivity(activity[date - 2]) / 3 | ||
+ getMaxActivity(activity[date - 3]) / 6; | ||
} | ||
exports.getAverageActivity = getAverageActivity; | ||
function getSenderName(meta) { | ||
if (!meta.sender || meta.$user && meta.$user.name !== String(meta.userId)) | ||
return meta.$user.name; | ||
return meta.sender.card || meta.sender.nickname; | ||
const userId = '' + meta.userId; | ||
return meta.$user && meta.$user.name !== userId ? meta.$user.name | ||
: meta.sender ? meta.sender.card || meta.sender.nickname : userId; | ||
} | ||
@@ -79,2 +54,3 @@ exports.getSenderName = getSenderName; | ||
const middleware = async (meta, next) => { | ||
var _a; | ||
if (meta.userId + meta.$ctxType + meta.$ctxId !== identifier) | ||
@@ -84,3 +60,3 @@ return next(); | ||
if (!meta.message.trim()) { | ||
meta.$user = await command.context.database.observeUser(meta.userId, 0, fields); | ||
meta.$user = await ((_a = command.context.database) === null || _a === void 0 ? void 0 : _a.observeUser(meta.userId, 0, fields)); | ||
return execute(suggestions[0], meta, next); | ||
@@ -87,0 +63,0 @@ } |
{ | ||
"name": "koishi-core", | ||
"description": "Core features for Koishi", | ||
"version": "1.0.0-alpha.7", | ||
"version": "1.0.0-alpha.8", | ||
"main": "dist/index.js", | ||
@@ -37,3 +37,3 @@ "typings": "dist/index.d.ts", | ||
"@types/ws": "^6.0.4", | ||
"koishi-test-utils": "^1.0.0-alpha.6" | ||
"koishi-test-utils": "^1.0.0-alpha.7" | ||
}, | ||
@@ -40,0 +40,0 @@ "dependencies": { |
110312
2751