/// <reference types="lru-cache" />
/// <reference types="node" />
/// <reference types="koa__router" />
/// <reference types="ws" />
import * as utils from 'koishi-utils';
import { MaybeArray, Get, Extract, Observed, Logger, Promisify, Awaitable } 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;
type Primitive = string | number;
type Comparable = Primitive | Date;
type Keys<O, T = any> = string & {
    [K in keyof O]: O[K] extends T ? K : never;
}[keyof O];
export interface Tables {
    user: User;
    channel: Channel;
}
export namespace Tables {
    interface Field<T = any> {
        type: Field.Type<T>;
        length?: number;
        nullable?: boolean;
        initial?: T;
        precision?: number;
        scale?: number;
    }
    namespace Field {
        export const number: Type[];
        export const string: Type[];
        export const date: Type[];
        export const object: Type[];
        export type Type<T = any> = T extends number ? 'integer' | 'unsigned' | 'float' | 'double' | 'decimal' : T extends string ? 'char' | 'string' | 'text' : T extends Date ? 'timestamp' | 'date' | 'time' : T extends any[] ? 'list' | 'json' : T extends object ? 'json' : never;
        type WithParam<S extends string> = S | `${S}(${any})`;
        export type Extension<O = any> = {
            [K in keyof O]?: Field<O[K]> | WithParam<Type<O[K]>>;
        };
        export type Config<O = any> = {
            [K in keyof O]?: Field<O[K]>;
        };
        export function parse(source: string | Field): Field;
        export {};
    }
    interface Extension<O = any> {
        type?: 'random' | 'incremental';
        primary?: Keys<O>;
        unique?: MaybeArray<Keys<O>>[];
        foreign?: {
            [K in keyof O]?: [TableType, string];
        };
        fields?: Field.Extension<O>;
    }
    interface Config<O = any> extends Extension<O> {
        fields?: Field.Config<O>;
    }
    const config: Record<string, Config>;
    function extend<T extends TableType>(name: T, meta?: Extension<Tables[T]>): void;
    function create<T extends TableType>(name: T): Tables[T];
}
export type Query<T extends TableType> = Query.Expr<Tables[T]> | Query.Shorthand<Primitive>;
export namespace Query {
    export type Field<T extends TableType> = string & keyof Tables[T];
    export type Index<T extends TableType> = Keys<Tables[T], Primitive>;
    export interface FieldExpr<T = any> {
        $in?: Extract<T, Primitive, T[]>;
        $nin?: Extract<T, Primitive, T[]>;
        $eq?: Extract<T, Comparable>;
        $ne?: Extract<T, Comparable>;
        $gt?: Extract<T, Comparable>;
        $gte?: Extract<T, Comparable>;
        $lt?: Extract<T, Comparable>;
        $lte?: Extract<T, Comparable>;
        $el?: T extends (infer U)[] ? FieldQuery<U> : never;
        $size?: Extract<T, any[], number>;
        $regex?: Extract<T, string, RegExp>;
        $regexFor?: Extract<T, string>;
        $bitsAllClear?: Extract<T, number>;
        $bitsAllSet?: Extract<T, number>;
        $bitsAnyClear?: Extract<T, number>;
        $bitsAnySet?: Extract<T, number>;
    }
    export interface LogicalExpr<T = any> {
        $or?: Expr<T>[];
        $and?: Expr<T>[];
        $not?: Expr<T>;
        $expr?: Eval.Boolean<T>;
    }
    export type Shorthand<T = any> = Extract<T, Comparable> | Extract<T, Primitive, T[]> | Extract<T, string, RegExp>;
    export type FieldQuery<T = any> = FieldExpr<T> | Shorthand<T>;
    export type Expr<T = any> = LogicalExpr<T> & {
        [K in keyof T]?: FieldQuery<T[K]>;
    };
    export function resolve<T extends TableType>(name: T, query?: Query<T>): Expr<Tables[T]>;
    export interface ModifierExpr<K extends string> {
        limit?: number;
        offset?: number;
        fields?: K[];
    }
    export type Modifier<T extends string> = T[] | ModifierExpr<T>;
    export function resolveModifier<K extends string>(modifier: Modifier<K>): ModifierExpr<K>;
    type Projection<T extends TableType> = Record<string, Eval.Aggregation<Tables[T]>>;
    type MapEval<T, P> = {
        [K in keyof P]: Eval<T, P[K]>;
    };
    export interface Database {
        drop(table?: TableType): Promise<void>;
        get<T extends TableType, K extends Field<T>>(table: T, query: Query<T>, modifier?: Modifier<K>): Promise<Pick<Tables[T], K>[]>;
        remove<T extends TableType>(table: T, query: 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?: Index<T>): Promise<void>;
        aggregate<T extends TableType, P extends Projection<T>>(table: T, fields: P, query?: Query<T>): Promise<MapEval<T, P>>;
    }
    export {};
}
export type Eval<T, U> = U extends number ? number : U extends boolean ? boolean : U extends string ? Get<T, U> : U extends Eval.NumericExpr ? number : U extends Eval.BooleanExpr ? boolean : U extends Eval.AggregationExpr ? number : never;
export namespace Eval {
    type Any<T = any, A = never> = A | number | boolean | Keys<T> | NumericExpr<T, A> | BooleanExpr<T, A>;
    type GeneralExpr = NumericExpr & BooleanExpr & AggregationExpr;
    type Numeric<T = any, A = never> = A | number | Keys<T, number> | NumericExpr<T, A>;
    type Boolean<T = any, A = never> = boolean | Keys<T, boolean> | BooleanExpr<T, A>;
    type Aggregation<T = any> = Any<{}, AggregationExpr<T>>;
    interface NumericExpr<T = any, A = never> {
        $add?: Numeric<T, A>[];
        $multiply?: Numeric<T, A>[];
        $subtract?: [Numeric<T, A>, Numeric<T, A>];
        $divide?: [Numeric<T, A>, Numeric<T, A>];
    }
    interface BooleanExpr<T = any, A = never> {
        $eq?: [Numeric<T, A>, Numeric<T, A>];
        $ne?: [Numeric<T, A>, Numeric<T, A>];
        $gt?: [Numeric<T, A>, Numeric<T, A>];
        $gte?: [Numeric<T, A>, Numeric<T, A>];
        $lt?: [Numeric<T, A>, Numeric<T, A>];
        $lte?: [Numeric<T, A>, Numeric<T, A>];
    }
    interface AggregationExpr<T = any> {
        $sum?: Any<T>;
        $avg?: Any<T>;
        $max?: Any<T>;
        $min?: Any<T>;
        $count?: Any<T>;
    }
}
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>;
    /**
     * @deprecated use `Tables.extend('user', { fields })` instead
     */
    export function extend(getter: Getter): void;
    export function create<T extends Index>(type: T, id: string): User;
    export interface Database {
        getUser<K extends Field, T extends Index>(type: T, id: string, modifier?: Query.Modifier<K>): Promise<Pick<User, K | T>>;
        getUser<K extends Field, T extends Index>(type: T, ids: string[], modifier?: Query.Modifier<K>): Promise<Pick<User, K>[]>;
        getUser<K extends Field, T extends Index>(type: T, id: MaybeArray<string>, modifier?: Query.Modifier<K>): Promise<any>;
        setUser<T extends Index>(type: T, id: string, data: Partial<User>): Promise<void>;
        createUser<T extends Index>(type: T, id: string, data: Partial<User>): Promise<void>;
    }
    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>;
    /**
     * @deprecated use `Tables.extend('user', { fields })` instead
     */
    export function extend(getter: Getter): void;
    export function create(type: Platform, id: string): Channel;
    export interface Database {
        getChannel<K extends Field>(type: Platform, id: string, modifier?: Query.Modifier<K>): Promise<Pick<Channel, K | 'id'>>;
        getChannel<K extends Field>(type: Platform, ids: readonly string[], modifier?: Query.Modifier<K>): Promise<Pick<Channel, K>[]>;
        getChannel<K extends Field>(type: Platform, id: MaybeArray<string>, modifier?: Query.Modifier<K>): Promise<any>;
        getAssignedChannels<K extends Field>(fields?: 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>;
    }
    export {};
}
export interface Database extends Query.Database, User.Database, Channel.Database {
}
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' | 'file';
    interface Stats {
        assetCount?: number;
        assetSize?: number;
    }
}
export interface HelpConfig extends Command.Config {
    shortcut?: boolean;
    options?: boolean;
}
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;
    host?: string;
    bots?: BotOptions[];
    prefix?: string | string[] | ((session: Session.Message) => void | string | string[]);
    nickname?: string | string[];
    maxListeners?: number;
    prettyErrors?: boolean;
    processMessage?: (message: string) => string;
    delay?: DelayOptions;
    help?: boolean | HelpConfig;
    autoAssign?: boolean | ((session: Session) => boolean);
    autoAuthorize?: number | ((session: Session) => number);
    userCacheAge?: number;
    userCacheLength?: number;
    channelCacheLength?: number;
    channelCacheAge?: number;
    minSimilarity?: number;
    selfUrl?: string;
    axiosConfig?: AxiosRequestConfig;
}
interface CommandMap extends Map<string, Command> {
    resolve(key: string): Command;
}
export class App extends Context {
    app: this;
    options: AppOptions;
    status: App.Status;
    adapters: Adapter.Instances;
    registry: Plugin.Registry;
    _bots: Bot<never>[] & Record<string, Bot<never>>;
    _commandList: Command[];
    _commands: CommandMap;
    _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;
    static defaultConfig: AppOptions;
    constructor(options?: AppOptions);
    createServer(): void;
    prepare(): void;
    start(): Promise<void>;
    private _listen;
    stop(): Promise<void>;
    private _close;
    private _resolvePrefixes;
    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 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<T = any> extends Meta {
        id?: string;
        parent?: State;
        context?: Context;
        config?: T;
        plugin?: Plugin;
        children: Plugin[];
        disposables: Disposable[];
    }
    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 class Registry extends Map<Plugin, State> {
        resolve(plugin: Plugin): Function<any>;
        get(plugin: Plugin): State<any>;
        set(plugin: Plugin, state: State): this;
        has(plugin: Plugin): boolean;
        delete(plugin: Plugin): boolean;
    }
    export {};
}
type Filter = (session: Session) => boolean;
type PartialSeletor<T> = (...values: T[]) => Context;
interface Selector<T> extends PartialSeletor<T> {
    except?: PartialSeletor<T>;
}
export interface Context extends Context.Delegates {
}
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>;
    protected constructor(filter: Filter, app?: App, _plugin?: Plugin);
    private static inspect;
    [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;
    except(arg: Filter | Context): Context;
    match(session?: Session): boolean;
    get state(): Plugin.State<any>;
    addSideEffect(state?: Plugin.State<any>): void;
    private teleport;
    with<D extends readonly (keyof Plugin.Packages)[]>(deps: D, callback: Plugin.Teleporter<D>): this;
    plugin<T extends Plugin>(plugin: T, options?: boolean | Plugin.Config<T>): this;
    dispose(plugin?: Plugin<any>): Promise<void>;
    parallel<K extends EventName>(name: K, ...args: Parameters<EventMap[K]>): Promise<void>;
    parallel<K extends EventName>(session: Session, name: K, ...args: Parameters<EventMap[K]>): Promise<void>;
    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, Argv.ArgumentType<D>>;
    command<D extends string>(def: D, desc: string, config?: Command.Config): Command<never, never, Argv.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;
}
export namespace Context {
    interface Delegates {
        database: Database;
        assets: Assets;
        router: Router;
    }
}
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 DelegateEventMap = {
    [K in keyof Context.Delegates as `delegate/${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-'>;
export type BeforeEventMap = {
    [E in EventName & string as OmitSubstring<E, 'before-'>]: EventMap[E];
};
export interface EventMap extends SessionEventMap, DelegateEventMap {
    [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>;
    'command-added'(command: Command): void;
    'command-removed'(command: Command): 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 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 {
    export interface Interpolation {
        terminator?: string;
        parse?(source: string): Argv;
    }
    export function interpolate(initiator: string, terminator: string, parse?: (source: string) => Argv): void;
    export 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;
    }
    export function parse(source: string, terminator?: string): Argv<never, never, any[], {}>;
    export function stringify(argv: Argv): string;
    export function revert(token: Token): void;
    export function parsePid(target: string): [Platform, string];
    export interface Domain {
        string: string;
        number: number;
        boolean: boolean;
        text: string;
        rawtext: string;
        user: string;
        channel: string;
        integer: number;
        posint: number;
        natural: number;
        date: Date;
    }
    type DomainType = keyof Domain;
    type ParamType<S extends string, F> = S extends `${any}:${infer T}` ? T extends DomainType ? 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> = ExtractFirst<Replace<S, '>', ']'>, any>;
    export type Type = DomainType | RegExp | string[] | 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 interface DomainConfig<T> {
        transform?: Transform<T>;
        greedy?: boolean;
    }
    export function createDomain<K extends keyof Domain>(name: K, transform: Transform<Domain[K]>, options?: DomainConfig<Domain[K]>): void;
    export function parseValue(source: string, quoted: boolean, kind: string, argv: Argv, decl?: Declaration): any;
    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 TypedOptionConfig<T extends Type> extends OptionConfig<T> {
        type: T;
    }
    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 _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;
        parse(argv: Argv): Argv;
        parse(source: string, terminator?: string, args?: any[], options?: Record<string, any>): Argv;
        private stringifyArg;
        stringify(args: readonly string[], options: any): string;
    }
    export {};
}
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[];
        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) => Awaitable<void | string>;
    type Usage<U extends User.Field = never, G extends Channel.Field = never> = string | ((session: Session<U, G>) => Awaitable<string>);
}
export class Command<U extends User.Field = never, G extends Channel.Field = never, A extends any[] = any[], O extends {} = {}> extends Argv.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: Argv.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, Argv.ArgumentType<D>>;
    subcommand<D extends string>(def: D, desc: string, config?: Command.Config): Command<never, never, Argv.ArgumentType<D>>;
    usage(text: Command.Usage<U, G>): this;
    example(example: string): this;
    option<K extends string>(name: K, desc: string, config: Argv.TypedOptionConfig<RegExp>): Command<U, G, A, Extend<O, K, string>>;
    option<K extends string, R>(name: K, desc: string, config: Argv.TypedOptionConfig<(source: string) => R>): Command<U, G, A, Extend<O, K, R>>;
    option<K extends string, R extends string>(name: K, desc: string, config: Argv.TypedOptionConfig<R[]>): Command<U, G, A, Extend<O, K, R>>;
    option<K extends string, D extends string>(name: K, desc: D, config?: Argv.OptionConfig): Command<U, G, A, Extend<O, K, Argv.OptionType<D>>>;
    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': {};
            'nickname': {};
        };
        'notice': {
            'poke': {};
            'lucky-king': {};
            'honor': {
                'talkative': {};
                'performer': {};
                'emotion': {};
            };
        };
        'reaction-added': {};
        'reaction-deleted': {
            'one': {};
            'all': {};
            'emoji': {};
        };
    }
    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?: 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?: 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, groupId?: 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[]>;
    deleteFriend(userId: string): Promise<void>;
    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", "group" | "private">;
    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 RoleInfo {
    id: 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;
declare module 'koa' {
    interface Request {
        body?: any;
        rawBody: string;
    }
}export default function apply(ctx: Context): void;
