UNPKG

koishi-core

Version:
780 lines (779 loc) 33.8 kB
/// <reference types="lru-cache" /> /// <reference types="node" /> /// <reference types="koa__router" /> /// <reference types="ws" /> import * as utils from 'koishi-utils'; import { Observed, Logger } from 'koishi-utils'; import LruCache from 'lru-cache'; import { AxiosRequestConfig } from 'axios'; import { Server } from 'http'; import { inspect } from 'util'; import Router from '@koa/router'; import WebSocket from 'ws'; export type TableType = keyof Tables; export interface Tables { user: User; channel: Channel; } export namespace Tables { type IndexType = string | number; type IndexKeys<O, T = any> = string & { [K in keyof O]: O[K] extends T ? K : never; }[keyof O]; type QueryMap<O> = { [K in keyof O]?: O[K][]; }; export type Index<T extends TableType> = IndexKeys<Tables[T], IndexType>; export type Query<T extends TableType> = IndexType[] | QueryMap<Tables[T]>; export type Field<T extends TableType> = string & keyof Tables[T]; interface Meta<O> { primary?: keyof O; unique?: (keyof O)[]; type?: 'incremental'; } export const config: { [T in TableType]?: Meta<Tables[T]>; }; export function extend<T extends TableType>(name: T, meta?: Meta<Tables[T]>): void; export function resolveQuery<T extends TableType>(name: T, query: Query<T>): Record<string, any[]>; export {}; } export interface User extends Record<Platform, string> { id: string; flag: number; authority: number; name: string; usage: Record<string, number>; timers: Record<string, number>; } export namespace User { export enum Flag { ignore = 1 } export type Field = keyof User; export const fields: Field[]; export type Index = Platform | 'name' | 'id'; export type Observed<K extends Field = Field> = utils.Observed<Pick<User, K>, Promise<void>>; type Getter = <T extends Index>(type: T, id: string) => Partial<User>; export function extend(getter: Getter): void; export function create<T extends Index>(type: T, id: string): User; export {}; } export interface Channel { id: string; flag: number; assignee: string; disable: string[]; } export namespace Channel { export enum Flag { ignore = 1, silent = 4 } export type Field = keyof Channel; export const fields: Field[]; export type Observed<K extends Field = Field> = utils.Observed<Pick<Channel, K>, Promise<void>>; type Getter = (type: Platform, id: string) => Partial<Channel>; export function extend(getter: Getter): void; export function create(type: Platform, id: string): Channel; export {}; } type MaybeArray<T> = T | T[]; export interface Database { get<T extends TableType, F extends Tables.Field<T>>(table: T, query: Tables.Query<T>, fields?: readonly F[]): Promise<Pick<Tables[T], F>[]>; remove<T extends TableType>(table: T, query: Tables.Query<T>): Promise<void>; create<T extends TableType>(table: T, data: Partial<Tables[T]>): Promise<Tables[T]>; update<T extends TableType>(table: T, data: Partial<Tables[T]>[], key?: Tables.Index<T>): Promise<void>; getUser<K extends User.Field, T extends User.Index>(type: T, id: string, fields?: readonly K[]): Promise<Pick<User, K | T>>; getUser<K extends User.Field, T extends User.Index>(type: T, ids: readonly string[], fields?: readonly K[]): Promise<Pick<User, K | T>[]>; setUser<T extends User.Index>(type: T, id: string, data: Partial<User>): Promise<void>; createUser<T extends User.Index>(type: T, id: string, data: Partial<User>): Promise<void>; removeUser<T extends User.Index>(type: T, id: string): Promise<void>; getChannel<K extends Channel.Field>(type: Platform, id: string, fields?: readonly K[]): Promise<Pick<Channel, K | 'id'>>; getChannel<K extends Channel.Field>(type: Platform, ids: readonly string[], fields?: readonly K[]): Promise<Pick<Channel, K | 'id'>[]>; getChannel<K extends Channel.Field>(type: Platform, id: MaybeArray<string>, fields?: readonly K[]): Promise<any>; getAssignedChannels<K extends Channel.Field>(fields?: readonly K[], assignMap?: Record<string, readonly string[]>): Promise<Pick<Channel, K>[]>; setChannel(type: Platform, id: string, data: Partial<Channel>): Promise<void>; createChannel(type: Platform, id: string, data: Partial<Channel>): Promise<void>; removeChannel(type: Platform, id: string): Promise<void>; } type Methods<S, T> = { [K in keyof S]?: S[K] extends (...args: infer R) => infer U ? (this: T, ...args: R) => U : S[K]; }; export namespace Database { export interface Statics { } type Constructor<T> = new (...args: any[]) => T; type ExtensionMethods<T> = Methods<Database, T extends Constructor<infer I> ? I : never>; type Extension<T> = ((Database: T) => void) | ExtensionMethods<T>; export function extend<K extends keyof Statics>(module: K, extension: Extension<Statics[K]>): void; export function extend<T extends Constructor<unknown>>(module: T, extension: Extension<T>): void; export {}; } export interface Assets { types: readonly Assets.Type[]; upload(url: string, file: string): Promise<string>; stats(): Promise<Assets.Stats>; } export namespace Assets { type Type = 'image' | 'audio' | 'video'; interface Stats { assetCount?: number; assetSize?: number; } } export function getCommandNames(session: Session): string[]; export interface DelayOptions { character?: number; message?: number; cancel?: number; broadcast?: number; prompt?: number; } export interface AppOptions extends BotOptions { port?: number; bots?: BotOptions[]; prefix?: string | string[]; nickname?: string | string[]; maxListeners?: number; prettyErrors?: boolean; processMessage?: (message: string) => string; delay?: DelayOptions; autoAssign?: boolean | ((session: Session) => boolean); autoAuthorize?: number | ((session: Session) => number); userCacheAge?: number; userCacheLength?: number; channelCacheLength?: number; channelCacheAge?: number; minSimilarity?: number; selfUrl?: string; axiosConfig?: AxiosRequestConfig; } export class App extends Context { app: this; options: AppOptions; status: App.Status; adapters: Adapter.Instances; registry: Map<Plugin<any>, Plugin.State>; _bots: Bot<never>[] & Record<string, Bot<never>>; _commands: Command[]; _commandMap: Record<string, Command>; _shortcuts: Command.Shortcut[]; _hooks: Record<keyof any, [Context, (...args: any[]) => any][]>; _userCache: Record<string, LruCache<string, Observed<Partial<User>, Promise<void>>>>; _channelCache: LruCache<string, Observed<Partial<Channel>, Promise<void>>>; _httpServer?: Server; _sessions: Record<string, Session>; private _nameRE; private _prefixRE; static defaultConfig: AppOptions; constructor(options?: AppOptions); createServer(): void; prepare(): void; start(): Promise<void>; private _listen; stop(): Promise<void>; private _close; private _process; private _suggest; private _handleMessage; private _handleArgv; private _handleShortcut; } export namespace App { enum Status { closed = 0, opening = 1, open = 2, closing = 3 } } export type NextFunction = (next?: NextFunction) => Promise<void>; export type Middleware = (session: Session, next: NextFunction) => any; export type Promisify<T> = T extends Promise<unknown> ? T : Promise<T>; export type Awaitable<T> = T extends Promise<unknown> ? T : T | Promise<T>; export type Await<T> = T extends Promise<infer U> ? U : T; export type Disposable = () => void; export type Plugin<T = any> = Plugin.Function<T> | Plugin.Object<T>; export namespace Plugin { export type Function<T = any> = (ctx: Context, options: T) => void; export interface Meta { name?: string; sideEffect?: boolean; } export interface Object<T = any> extends Meta { apply: Function<T>; } export type Config<T extends Plugin> = T extends Function<infer U> ? U : T extends Object<infer U> ? U : never; export interface State extends Meta { parent: State; children: Plugin[]; disposables: Disposable[]; dependencies: Set<State>; } export interface Packages { } export type Teleporter<D extends readonly (keyof Packages)[]> = (ctx: Context, ...modules: From<D>) => void; type From<D extends readonly unknown[]> = D extends readonly [infer L, ...infer R] ? [L extends keyof Packages ? Packages[L] : unknown, ...From<R>] : []; export {}; } type Filter = (session: Session) => boolean; type PartialSeletor<T> = (...values: T[]) => Context; interface Selector<T> extends PartialSeletor<T> { except?: PartialSeletor<T>; } export class Context { filter: Filter; app?: App; private _plugin; static readonly middleware: unique symbol; static readonly current: unique symbol; protected _bots: Bot[] & Record<string, Bot>; database: Database; assets: Assets; router: Router; protected constructor(filter: Filter, app?: App, _plugin?: Plugin); [inspect.custom](): string; private createSelector; get user(): Selector<string>; get self(): Selector<string>; get group(): Selector<string>; get channel(): Selector<string>; get platform(): Selector<never>; get private(): Selector<string>; get bots(): Bot<never>[] & Record<string, Bot<never>>; logger(name: string): Logger; select<K extends keyof Session>(key: K, ...values: Session[K][]): Context; unselect<K extends keyof Session>(key: K, ...values: Session[K][]): Context; all(): Context; union(arg: Filter | Context): Context; intersect(arg: Filter | Context): Context; match(session?: Session): boolean; get state(): Plugin.State; addSideEffect(state?: Plugin.State): void; private teleport; with<D extends readonly (keyof Plugin.Packages)[]>(deps: D, callback: Plugin.Teleporter<D>): this; plugin<T extends Plugin>(plugin: T, options?: Plugin.Config<T>): this; dispose(plugin?: Plugin<any>): Promise<void>; parallel<K extends EventName>(name: K, ...args: Parameters<EventMap[K]>): Promise<Await<ReturnType<EventMap[K]>>[]>; parallel<K extends EventName>(session: Session, name: K, ...args: Parameters<EventMap[K]>): Promise<Await<ReturnType<EventMap[K]>>[]>; emit<K extends EventName>(name: K, ...args: Parameters<EventMap[K]>): void; emit<K extends EventName>(session: Session, name: K, ...args: Parameters<EventMap[K]>): void; waterfall<K extends EventName>(name: K, ...args: Parameters<EventMap[K]>): Promisify<ReturnType<EventMap[K]>>; waterfall<K extends EventName>(session: Session, name: K, ...args: Parameters<EventMap[K]>): Promisify<ReturnType<EventMap[K]>>; chain<K extends EventName>(name: K, ...args: Parameters<EventMap[K]>): ReturnType<EventMap[K]>; chain<K extends EventName>(session: Session, name: K, ...args: Parameters<EventMap[K]>): ReturnType<EventMap[K]>; serial<K extends EventName>(name: K, ...args: Parameters<EventMap[K]>): Promisify<ReturnType<EventMap[K]>>; serial<K extends EventName>(session: Session, name: K, ...args: Parameters<EventMap[K]>): Promisify<ReturnType<EventMap[K]>>; bail<K extends EventName>(name: K, ...args: Parameters<EventMap[K]>): ReturnType<EventMap[K]>; bail<K extends EventName>(session: Session, name: K, ...args: Parameters<EventMap[K]>): ReturnType<EventMap[K]>; on<K extends EventName>(name: K, listener: EventMap[K], prepend?: boolean): () => boolean; before<K extends BeforeEventName>(name: K, listener: BeforeEventMap[K], append?: boolean): () => boolean; once<K extends EventName>(name: K, listener: EventMap[K], prepend?: boolean): () => boolean; off<K extends EventName>(name: K, listener: EventMap[K]): boolean; middleware(middleware: Middleware, prepend?: boolean): () => boolean; private createTimerDispose; setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): () => boolean; setInterval(callback: (...args: any[]) => void, ms: number, ...args: any[]): () => boolean; command<D extends string>(def: D, config?: Command.Config): Command<never, never, Domain.ArgumentType<D>>; command<D extends string>(def: D, desc: string, config?: Command.Config): Command<never, never, Domain.ArgumentType<D>>; transformAssets(content: string, assets?: Assets): Promise<string>; getBot(platform: Platform, selfId?: string): Bot<never>; getSelfIds(type?: Platform, assignees?: readonly string[]): Record<string, readonly string[]>; broadcast(content: string, forced?: boolean): Promise<string[]>; broadcast(channels: readonly string[], content: string, forced?: boolean): Promise<string[]>; static delegate(key: string & keyof Context): void; } type FlattenEvents<T> = { [K in keyof T & string]: K | `${K}/${FlattenEvents<T[K]>}`; }[keyof T & string]; type SessionEventMap = { [K in FlattenEvents<Session.Events>]: K extends `${infer X}/${infer R}` ? R extends `${infer Y}/${any}` ? (session: Session.Payload<X, Y>) => void : (session: Session.Payload<X, R>) => void : (session: Session.Payload<K>) => void; }; type EventName = keyof EventMap; type OmitSubstring<S extends string, T extends string> = S extends `${infer L}${T}${infer R}` ? `${L}${R}` : never; type BeforeEventName = OmitSubstring<EventName & string, 'before-'>; type BeforeEventMap = { [E in EventName & string as OmitSubstring<E, 'before-'>]: EventMap[E]; }; export interface EventMap extends SessionEventMap { [Context.middleware]: Middleware; 'appellation'(name: string, session: Session): string; 'before-parse'(content: string, session: Session): Argv; 'parse'(argv: Argv, session: Session): string; 'before-attach-channel'(session: Session, fields: Set<Channel.Field>): void; 'attach-channel'(session: Session): Awaitable<void | boolean>; 'before-attach-user'(session: Session, fields: Set<User.Field>): void; 'attach-user'(session: Session): Awaitable<void | boolean>; 'before-attach'(session: Session): void; 'attach'(session: Session): void; 'before-send'(session: Session<never, never, Platform, 'send'>): Awaitable<void | boolean>; 'before-command'(argv: Argv): Awaitable<void | string>; 'command'(argv: Argv): Awaitable<void>; 'middleware'(session: Session): void; 'plugin-added'(plugin: Plugin, registry: Map<Plugin, Plugin.State>): void; 'plugin-removed'(plugin: Plugin, registry: Map<Plugin, Plugin.State>): void; 'before-connect'(): Awaitable<void>; 'connect'(): void; 'before-disconnect'(): Awaitable<void>; 'disconnect'(): void; } export interface Domain { string: string; number: number; boolean: boolean; text: string; user: string; channel: string; integer: number; posint: number; date: Date; } export namespace Domain { type Builtin = keyof Domain; type ParamType<S extends string, F> = S extends `${any}:${infer T}` ? T extends Builtin ? Domain[T] : F : F; type Replace<S extends string, X extends string, Y extends string> = S extends `${infer L}${X}${infer R}` ? `${L}${Y}${Replace<R, X, Y>}` : S; type ExtractAll<S extends string, F> = S extends `${infer L}]${infer R}` ? [ParamType<L, F>, ...ExtractAll<R, F>] : []; type ExtractFirst<S extends string, F> = S extends `${infer L}]${any}` ? ParamType<L, F> : boolean; type ExtractSpread<S extends string> = S extends `${infer L}...${infer R}` ? [...ExtractAll<L, string>, ...ExtractFirst<R, string>[]] : [...ExtractAll<S, string>, ...string[]]; export type ArgumentType<S extends string> = ExtractSpread<Replace<S, '>', ']'>>; export type OptionType<S extends string, T extends Type> = [T] extends [Builtin] ? Domain[T] : [T] extends [RegExp] ? string : T extends (source: string) => infer R ? R : ExtractFirst<Replace<S, '>', ']'>, any>; export type Type = Builtin | RegExp | Transform<any>; export interface Declaration { name?: string; type?: Type; fallback?: any; variadic?: boolean; required?: boolean; } export type Transform<T> = (source: string, session: Session) => T; export function create<K extends keyof Domain>(name: K, callback: Transform<Domain[K]>): void; export interface OptionConfig<T extends Type = Type> { value?: any; fallback?: any; type?: T; /** hide the option by default */ hidden?: boolean | ((session: Session) => boolean); authority?: number; notUsage?: boolean; } export interface OptionDeclaration extends Declaration, OptionConfig { description?: string; values?: Record<string, any>; } type OptionDeclarationMap = Record<string, OptionDeclaration>; export class CommandBase { name: string; description: string; declaration: string; _arguments: Declaration[]; _options: OptionDeclarationMap; private _error; private _namedOptions; private _symbolicOptions; constructor(name: string, declaration: string, description: string); _createOption(name: string, def: string, config?: OptionConfig): void; private _assignOption; removeOption<K extends string>(name: K): boolean; private _parseValue; parse(argv: Argv): Argv; parse(source: string, terminator?: string): Argv; private stringifyArg; stringify(args: readonly string[], options: any): string; } export {}; } export interface Token { rest?: string; content: string; quoted: boolean; terminator: string; inters: Argv[]; } export interface Argv<U extends User.Field = never, G extends Channel.Field = never, A extends any[] = any[], O = {}> { args?: A; options?: O; error?: string; source?: string; initiator?: string; terminator?: string; session?: Session<U, G>; command?: Command<U, G, A, O>; rest?: string; pos?: number; root?: boolean; tokens?: Token[]; name?: string; next?: NextFunction; } export namespace Argv { interface Interpolation { terminator?: string; parse?(source: string): Argv; } function interpolate(initiator: string, terminator: string, parse?: (source: string) => Argv): void; class Tokenizer { private bracs; constructor(); interpolate(initiator: string, terminator: string, parse?: (source: string) => Argv): void; parseToken(source: string, stopReg?: string): Token; parse(source: string, terminator?: string): Argv; stringify(argv: Argv): string; } function parse(source: string, terminator?: string): Argv<never, never, any[], {}>; function stringify(argv: Argv): string; function revert(token: Token): void; const createDomain: typeof Domain.create; function parsePid(target: string): [Platform, string]; } export type UserType<T, U extends User.Field = User.Field> = T | ((user: Pick<User, U>) => T); export type Extend<O extends {}, K extends string, T> = { [P in K | keyof O]?: (P extends keyof O ? O[P] : unknown) & (P extends K ? T : unknown); }; export namespace Command { interface Config { /** hide all options by default */ hideOptions?: boolean; /** hide command */ hidden?: boolean; /** min authority */ authority?: number; /** disallow unknown options */ checkUnknown?: boolean; /** check argument count */ checkArgCount?: boolean; /** show command warnings */ showWarning?: boolean; /** usage identifier */ usageName?: string; /** max usage per day */ maxUsage?: UserType<number>; /** min interval */ minInterval?: UserType<number>; /** depend on existing commands */ patch?: boolean; } interface Shortcut { name?: string | RegExp; command?: Command; authority?: number; prefix?: boolean; fuzzy?: boolean; args?: string[]; greedy?: boolean; options?: Record<string, any>; } type Action<U extends User.Field = never, G extends Channel.Field = never, A extends any[] = any[], O extends {} = {}> = (argv: Argv<U, G, A, O>, ...args: A) => void | string | Promise<void | string>; type Usage<U extends User.Field = never, G extends Channel.Field = never> = string | ((session: Session<U, G>) => string | Promise<string>); } export class Command<U extends User.Field = never, G extends Channel.Field = never, A extends any[] = any[], O extends {} = {}> extends Domain.CommandBase { context: Context; config: Command.Config; children: Command[]; parent: Command; _aliases: string[]; _examples: string[]; _usage?: Command.Usage; _disposed?: boolean; _disposables?: Disposable[]; private _userFields; private _channelFields; private _actions; private _checkers; static defaultConfig: Command.Config; static defaultOptionConfig: Domain.OptionConfig; private static _userFields; private static _channelFields; static userFields(fields: FieldCollector<'user'>): typeof Command; static channelFields(fields: FieldCollector<'channel'>): typeof Command; constructor(name: string, decl: string, desc: string, context: Context); get app(): App; private _registerAlias; [inspect.custom](): string; userFields<T extends User.Field = never>(fields: FieldCollector<'user', T, A, O>): Command<U | T, G, A, O>; channelFields<T extends Channel.Field = never>(fields: FieldCollector<'channel', T, A, O>): Command<U, G | T, A, O>; alias(...names: string[]): this; shortcut(name: string | RegExp, config?: Command.Shortcut): this; subcommand<D extends string>(def: D, config?: Command.Config): Command<never, never, Domain.ArgumentType<D>>; subcommand<D extends string>(def: D, desc: string, config?: Command.Config): Command<never, never, Domain.ArgumentType<D>>; usage(text: Command.Usage<U, G>): this; example(example: string): this; option<K extends string, D extends string, T extends Domain.Type>(name: K, desc: D, config?: Domain.OptionConfig<T>): Command<U, G, A, Extend<O, K, Domain.OptionType<D, T>>>; match(session: Session): boolean; getConfig<K extends keyof Command.Config>(key: K, session: Session): Exclude<Command.Config[K], (user: User) => any>; check(callback: Command.Action<U, G, A, O>, prepend?: boolean): this; action(callback: Command.Action<U, G, A, O>, append?: boolean): this; execute(argv0: Argv<U, G, A, O>, next?: NextFunction): Promise<string>; dispose(): void; } export function getUsageName(command: Command): string; export type ValidationField = 'authority' | 'usage' | 'timers'; export function getUsage(name: string, user: Pick<User, 'usage'>): number; export function checkUsage(name: string, user: Pick<User, 'usage'>, maxUsage?: number): boolean; export function checkTimer(name: string, { timers }: Pick<User, 'timers'>, offset?: number): boolean; type UnionToIntersection<U> = (U extends any ? (key: U) => void : never) extends (key: infer I) => void ? I : never; type Flatten<T, K extends keyof T = keyof T> = UnionToIntersection<T[K]>; type InnerKeys<T, K extends keyof T = keyof T> = keyof Flatten<T> & keyof Flatten<T, K>; export interface Session<U, G, P, X, Y> extends MessageBase, Partial<ChannelInfo>, Partial<GroupInfo> { } export namespace Session { type Genres = 'friend' | 'channel' | 'group' | 'group-member' | 'group-role' | 'group-file' | 'group-emoji'; type Actions = 'added' | 'deleted' | 'updated'; export interface Events extends Record<`${Genres}-${Actions}`, {}> { } export type MessageAction = 'message' | 'message-deleted' | 'message-updated' | 'send'; export type Message = Session<never, never, Platform, MessageAction>; export interface Events extends Record<MessageAction, MessageType> { } export type RequestAction = 'friend-request' | 'group-request' | 'group-member-request'; export type Request = Session<never, never, Platform, RequestAction>; export interface Events extends Record<RequestAction, {}> { } export interface Events { 'friend-request': {}; 'group-request': {}; 'group-member-request': {}; 'group-added': GroupMemberChangeType; 'group-member-added': GroupMemberChangeType; 'group-deleted': GroupMemberChangeType; 'group-member-deleted': GroupMemberChangeType; 'group-member': { 'role': {}; 'ban': {}; }; 'notice': { 'poke': {}; 'lucky-king': {}; 'honor': { 'talkative': {}; 'performer': {}; 'emotion': {}; }; }; } export interface GroupMemberChangeType { 'active': {}; 'passive': {}; } export interface MessageType { 'private': {}; 'group': {}; } type ParamX<X> = Extract<keyof Events, X>; type ParamY<X, Y> = Extract<InnerKeys<Events, ParamX<X>>, Y>; export type Payload<X, Y = any> = Session<never, never, Platform, ParamX<X>, ParamY<X, Y>>; export {}; } export interface Parsed { content: string; prefix: string; appel: boolean; } export class Session<U extends User.Field = never, G extends Channel.Field = never, P extends Platform = Platform, X extends keyof Session.Events = keyof Session.Events, Y extends InnerKeys<Session.Events, X> = InnerKeys<Session.Events, X>> { type?: X; subtype?: Y; subsubtype?: InnerKeys<UnionToIntersection<Session.Events[X]>, Y>; platform?: P; selfId?: string; operatorId?: string; targetId?: string; duration?: number; file?: FileInfo; readonly app: App; readonly bot: Bot.Instance<P>; readonly sid: string; uid: string; cid: string; gid: string; id?: string; argv?: Argv<U, G>; user?: User.Observed<U>; channel?: Channel.Observed<G>; parsed?: Parsed; private _delay?; private _queued; private _hooks; private _promise; static readonly send: unique symbol; constructor(app: App, session: Partial<Session>); toJSON(): Partial<Session>; private _preprocess; preprocess(): Promise<string>; get username(): string; get database(): Database; send(message: string): Promise<void>; cancelQueued(delay?: number): void; sendQueued(content: string, delay?: number): Promise<void>; resolveValue<T>(source: T | ((session: Session) => T)): T; getChannel<K extends Channel.Field = never>(id?: string, assignee?: string, fields?: readonly K[]): Promise<Pick<Channel, "id" | K>>; /** 在当前会话上绑定一个可观测频道实例 */ observeChannel<T extends Channel.Field = never>(fields?: Iterable<T>): Promise<Channel.Observed<T | G>>; getUser<K extends User.Field = never>(id?: string, authority?: number, fields?: readonly K[]): Promise<Pick<User, P | K>>; /** 在当前会话上绑定一个可观测用户实例 */ observeUser<T extends User.Field = never>(fields?: Iterable<T>): Promise<User.Observed<T | U>>; collect<T extends TableType>(key: T, argv: Argv, fields?: Set<keyof Tables[T]>): Set<keyof Tables[T]>; resolve(argv: Argv): Command<never, never, any[], {}>; execute(content: string, next?: true | NextFunction): Promise<string>; execute(argv: Argv, next?: true | NextFunction): Promise<string>; middleware(middleware: Middleware): () => boolean; prompt(timeout?: number): Promise<string>; suggest(options: SuggestOptions): Promise<void>; } export interface SuggestOptions { target: string; items: string[]; next?: NextFunction; prefix?: string; suffix: string; minSimilarity?: number; apply: (this: Session, suggestion: string, next: NextFunction) => void; } export function getSessionId(session: Session): string; export type FieldCollector<T extends TableType, K = keyof Tables[T], A extends any[] = any[], O = {}> = Iterable<K> | ((argv: Argv<never, never, A, O>, fields: Set<keyof Tables[T]>) => void); export interface FileInfo { id: string; name: string; size: number; busid: number; } export interface BotOptions { type?: string; token?: string; selfId?: string; } type BotList<T extends Bot> = Array<T> & Record<string, T>; export function createBots<T extends Bot>(key: 'selfId' | 'sid'): BotList<T>; export abstract class Adapter<P extends Platform = Platform> { app: App; private Bot?; bots: BotList<Bot.Instance<P>>; abstract start(): Promise<void>; abstract stop?(): void; constructor(app: App, Bot?: Bot.Constructor<P>); create(options: BotOptions, constructor?: Bot.Constructor<P>): Bot.Instance<P>; dispatch(session: Session): void; } export namespace Adapter { type Constructor<T extends Platform = Platform> = new (app: App, bot: BotOptions) => Adapter<T>; type Instances = { [K in string]: K extends `${infer T}:${any}` ? Adapter<T & Platform> : Adapter<K & Platform>; }; const types: Record<string, Constructor>; function from(app: App, bot: BotOptions): Adapter<never>; function redirect(target: string | ((bot: BotOptions) => string)): Constructor<never>; interface WsClientOptions { retryLazy?: number; retryTimes?: number; retryInterval?: number; } abstract class WsClient<P extends Platform = Platform> extends Adapter<P> { abstract prepare(bot: Bot.Instance<P>): WebSocket | Promise<WebSocket>; abstract connect(bot: Bot.Instance<P>): Promise<void>; private _listening; options: WsClientOptions; static options: WsClientOptions; constructor(app: App, Bot: Bot.Constructor<P>, options?: WsClientOptions); private _listen; start(): Promise<void>; stop(): void; } } export interface Bot<P = Platform> extends BotOptions, UserBase { [Session.send](session: Session, message: string): Promise<void>; status: Bot.Status; socket?: WebSocket; version?: string; getStatus(): Promise<Bot.Status>; sendMessage(channelId: string, content: string): Promise<string>; sendPrivateMessage(userId: string, content: string): Promise<string>; getMessage(channelId: string, messageId: string): Promise<MessageInfo>; editMessage(channelId: string, messageId: string, content: string): Promise<void>; deleteMessage(channelId: string, messageId: string): Promise<void>; getSelf(): Promise<UserInfo>; getUser(userId: string): Promise<UserInfo>; getFriendList(): Promise<UserInfo[]>; getGroup(groupId: string): Promise<GroupInfo>; getGroupList(): Promise<GroupInfo[]>; getGroupMember(groupId: string, userId: string): Promise<GroupMemberInfo>; getGroupMemberList(groupId: string): Promise<GroupMemberInfo[]>; getChannel(channelId: string): Promise<ChannelInfo>; getChannelList(groupId: string): Promise<ChannelInfo[]>; handleFriendRequest(messageId: string, approve: boolean, comment?: string): Promise<void>; handleGroupRequest(messageId: string, approve: boolean, comment?: string): Promise<void>; handleGroupMemberRequest(messageId: string, approve: boolean, comment?: string): Promise<void>; } export class Bot<P extends Platform> { adapter: Adapter<P>; readonly app: App; readonly logger: Logger; readonly platform: P; constructor(adapter: Adapter<P>, options: BotOptions); get sid(): string; createSession(session: Partial<Session<never, never, P, 'send'>>): Session<never, never, P, "send", "private" | "group">; getGroupMemberMap(groupId: string): Promise<{ [k: string]: string; }>; broadcast(channels: string[], content: string, delay?: number): Promise<string[]>; } export namespace Bot { interface Platforms { } type Instance<T extends Platform> = [T] extends [never] ? Bot<T> : Platforms[T]; type Constructor<T extends Platform> = new (adapter: Adapter, options: BotOptions) => Instance<T>; enum Status { /** 正常运行 */ GOOD = 0, /** 机器人处于闲置状态 */ BOT_IDLE = 1, /** 机器人离线 */ BOT_OFFLINE = 2, /** 无法获得状态 */ NET_ERROR = 3, /** 服务器状态异常 */ SERVER_ERROR = 4, /** 机器人被封禁 */ BANNED = 5, /** 正在尝试连接 */ CONNECTING = 6 } } export type Platform = keyof Bot.Platforms; export interface ChannelInfo { channelId: string; channelName: string; } export interface GroupInfo { groupId: string; groupName: string; } export interface UserBase { username: string; nickname?: string; avatar?: string; discriminator?: string; isBot?: boolean; } export interface UserInfo extends UserBase { userId: string; } export interface GroupMemberInfo extends UserInfo { roles?: string[]; } export interface AuthorInfo extends GroupMemberInfo { anonymous?: string; } export interface MessageBase { messageId?: string; channelId?: string; groupId?: string; userId?: string; content?: string; timestamp?: number; author?: AuthorInfo; quote?: MessageInfo; } export interface MessageInfo extends MessageBase { subtype?: keyof Session.Events['message']; } export * from 'koishi-utils'; export const version: string;export default function apply(ctx: Context): void;