New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

koishi-core

Package Overview
Dependencies
Maintainers
1
Versions
182
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

koishi-core - npm Package Compare versions

Comparing version 0.2.1 to 0.2.2

18

dist/app.d.ts
/// <reference types="node" />
import { Server } from './server';
import { Server, ServerType } from './server';
import { Context, UserContext, GroupContext, DiscussContext, Middleware, Plugin, NoticeEvent, RequestEvent, MetaEventEvent, MessageEvent } from './context';
import { Command, ShortcutConfig } from './command';
import { Command, ShortcutConfig, ParsedCommandLine } from './command';
import { Database, DatabaseConfig } from './database';
import { EventEmitter } from 'events';
import { Meta } from './meta';
import { Meta, MessageMeta } from './meta';
export interface AppOptions {

@@ -17,2 +17,3 @@ port?: number;

database?: DatabaseConfig;
type?: ServerType;
}

@@ -24,3 +25,3 @@ export declare const selfIds: number[];

export declare function onStart(hook: (...app: App[]) => void): void;
export declare function startAll(): void;
export declare function startAll(): Promise<void>;
export declare function stopAll(): void;

@@ -47,2 +48,4 @@ export declare class App extends Context {

constructor(options?: AppOptions);
get selfId(): number;
set selfId(value: number);
_registerSelfId(): void;

@@ -53,9 +56,8 @@ _createContext<T extends Context>(path: string, id?: number): T;

user(id: number): UserContext;
start(): void;
start(): Promise<void>;
stop(): void;
emitWarning(message: string): void;
handleMeta(meta: Meta): Promise<void>;
emitMeta(meta: Meta): void;
dispatchMeta(meta: Meta, emitEvents?: boolean): Promise<void>;
private _preprocess;
private _parseCommandLine;
parseCommandLine(message: string, meta: MessageMeta): ParsedCommandLine;
private _applyMiddlewares;

@@ -62,0 +64,0 @@ }

@@ -44,8 +44,9 @@ "use strict";

exports.onStart = onStart;
function startAll() {
async function startAll() {
const appList = [];
for (const id in exports.apps) {
exports.apps[id].start();
appList.push(exports.apps[id]);
}
await Promise.all(Object.keys(exports.apps).map(async (id) => {
const app = exports.apps[id];
await app.start();
appList.push(app);
}));
for (const hook of onStartHooks) {

@@ -100,3 +101,3 @@ hook(...appList);

// parse as command
if (canBeCommand && (parsedArgv = this._parseCommandLine(message, meta))) {
if (canBeCommand && (parsedArgv = this.parseCommandLine(message, meta))) {
fields.push(...parsedArgv.command._userFields);

@@ -191,3 +192,3 @@ }

const newMessage = suggestion + message.slice(target.length);
const parsedArgv = this._parseCommandLine(newMessage, meta);
const parsedArgv = this.parseCommandLine(newMessage, meta);
return parsedArgv.command.execute(parsedArgv, next);

@@ -229,10 +230,17 @@ },

this.database = database_1.createDatabase(options.database);
if (options.port)
this.server = server_1.createServer(this);
if (options.selfId)
this._registerSelfId();
this.sender = new sender_1.Sender(this);
if (options.type) {
this.server = server_1.createServer(this);
this.sender = new sender_1.Sender(this);
}
this.receiver.on('message', this._applyMiddlewares);
this.middleware(this._preprocess);
}
get selfId() {
return this.options.selfId;
}
set selfId(value) {
this.options.selfId = value;
}
_registerSelfId() {

@@ -269,9 +277,9 @@ const atMeRE = `\\[CQ:at,qq=${this.options.selfId}\\]`;

}
start() {
async start() {
this.sender.start();
this.server.listen(this.options.port);
await this.server.listen();
showLog('started');
}
stop() {
this.server.stop();
this.server.close();
this.sender.stop();

@@ -283,3 +291,3 @@ showLog('stopped');

}
async handleMeta(meta) {
async dispatchMeta(meta, emitEvents = true) {
Object.defineProperty(meta, '$path', {

@@ -326,4 +334,4 @@ value: '/',

}
}
emitMeta(meta) {
if (!emitEvents)
return;
for (const path in this._contexts) {

@@ -337,3 +345,3 @@ const context = this._contexts[path];

}
_parseCommandLine(message, meta) {
parseCommandLine(message, meta) {
const name = message.split(/\s/, 1)[0].toLowerCase();

@@ -340,0 +348,0 @@ const command = this._commandMap[name];

import { Context, NextFunction } from './context';
import { UserData, UserField } from './database';
import { MessageMeta } from './meta';
import { CommandOption, CommandArgument, OptionConfig, ParsedLine } from './parser';
import { CommandOption, OptionConfig, ParsedLine } from './parser';
export interface ParsedCommandLine extends ParsedLine {

@@ -30,2 +30,3 @@ meta: MessageMeta;

showWarning?: boolean;
noHelpOption?: boolean;
}

@@ -50,10 +51,10 @@ export interface ShortcutConfig {

_aliases: string[];
_action?: (this: Command, config: ParsedCommandLine, ...args: string[]) => any;
_options: CommandOption[];
_argsDef: CommandArgument[];
_usage?: string;
_examples: string[];
_shortcuts: Record<string, ShortcutConfig>;
_optsDef: Record<string, CommandOption>;
_userFields: Set<"id" | "name" | "flag" | "ignoreEnd" | "authority" | "usage" | "talkativeness">;
private _argsDef;
private _optsDef;
private _action?;
constructor(rawName: string, context: Context, config?: CommandConfig);

@@ -60,0 +61,0 @@ private _registerAlias;

@@ -19,3 +19,3 @@ "use strict";

const parser_1 = require("./parser");
const showCommandLog = debug_1.default('app:command');
const showCommandLog = debug_1.default('koishi:command');
const defaultConfig = {

@@ -36,4 +36,4 @@ authority: 1,

this._shortcuts = {};
this._userFields = new Set();
this._optsDef = {};
this._userFields = new Set();
this.name = parser_1.removeBrackets(rawName);

@@ -49,4 +49,6 @@ if (!this.name) {

this._registerAlias(this.name);
this.option('-h, --help', messages.SHOW_THIS_MESSAGE);
context.app._commands.push(this);
if (!config.noHelpOption) {
this.option('-h, --help', messages.SHOW_THIS_MESSAGE);
}
}

@@ -151,5 +153,6 @@ _registerAlias(name) {

const { meta, options, args, unknown } = config;
config.next = next;
if (!config.next)
config.next = next;
// show help when use `-h, --help` or when there is no action
if (!this._action || options.help) {
if (!this._action || options.help && !this.config.noHelpOption) {
return this.context.runCommand('help', meta, [this.name]);

@@ -156,0 +159,0 @@ }

@@ -17,3 +17,2 @@ /// <reference types="node" />

export declare function isAncestor(ancestor: string, path: string): boolean;
export declare const prefixTypes: string[];
export declare class Context {

@@ -20,0 +19,0 @@ path: string;

@@ -18,3 +18,3 @@ "use strict";

exports.isAncestor = isAncestor;
exports.prefixTypes = ['user', 'discuss', 'group'];
const prefixTypes = ['user', 'discuss', 'group'];
class Context {

@@ -124,3 +124,3 @@ constructor(path, app) {

for (let segment of path.slice(this.path.length).split('/')) {
if (!isNaN(segment) || exports.prefixTypes.includes(segment))
if (!isNaN(segment) || prefixTypes.includes(segment))
segment = lastEvent ? '*' : '';

@@ -127,0 +127,0 @@ if (segment)

@@ -65,2 +65,4 @@ "use strict";

function injectMethods(name, methods) {
if (!subdatabases[name])
return;
Object.assign(subdatabases[name]._injections, methods);

@@ -67,0 +69,0 @@ }

@@ -1,2 +0,1 @@

/// <reference types="node" />
import { GroupMemberInfo, StatusInfo, VersionInfo, FriendInfo, GroupInfo, Credentials, AccountInfo, StrangerInfo, ListedGroupInfo } from './meta';

@@ -13,11 +12,17 @@ import { App } from './app';

export declare type DataDirectoryType = 'image' | 'record' | 'show' | 'bface';
export interface CQResponse {
status: string;
retcode: number;
data: any;
echo?: number;
}
export declare class Sender {
app: App;
messages: any[];
timer: NodeJS.Timeout;
headers: Record<string, any>;
private _messages;
private _timer;
private _post;
constructor(app: App);
private post;
start(): void;
stop(): void;
protected _post(api: string, args?: Record<string, any>): Promise<any>;
sendContextMsg(contextId: string, message: string, autoEscape?: boolean): Promise<number>;

@@ -24,0 +29,0 @@ sendGroupMsg(groupId: number, message: string, autoEscape?: boolean): Promise<number>;

@@ -9,3 +9,3 @@ "use strict";

const koishi_utils_1 = require("koishi-utils");
const showSenderLog = debug_1.default('app:sender');
const showSenderLog = debug_1.default('koishi:sender');
class SenderError extends Error {

@@ -24,30 +24,31 @@ constructor(args, url, retcode) {

this.app = app;
this.messages = new Array(61).fill(0);
this.headers = {
Authorization: `Token ${app.options.token}`,
};
this._messages = new Array(61).fill(0);
const { type } = app.options;
if (type === 'http') {
const headers = {};
if (app.options.token) {
headers.Authorization = `Token ${app.options.token}`;
}
this._post = async (action, params = {}) => {
const uri = new URL(action, this.app.options.sendUrl).href;
const { data } = await axios_1.default.get(uri, { params, headers });
return data;
};
}
else if (type === 'ws') {
const server = app.server;
this._post = (action, params = {}) => server.send({ action, params });
}
}
start() {
this.timer = setInterval(() => {
this.messages.unshift(0);
this.messages.splice(-1, 1);
}, 1000);
}
stop() {
clearInterval(this.timer);
}
async _post(api, args = {}) {
const uri = new URL(api, this.app.options.sendUrl).href;
showSenderLog('request %s %o', api, args);
async post(action, params) {
showSenderLog('request %s %o', action, params);
try {
const { data } = await axios_1.default.get(uri, {
params: koishi_utils_1.snakeCase(args),
headers: this.headers,
});
showSenderLog('response %o', data);
if (data.retcode === 0) {
return koishi_utils_1.camelCase(data.data);
const response = await this._post(action, koishi_utils_1.snakeCase(params));
showSenderLog('response %o', response);
const { data, retcode } = response;
if (retcode === 0) {
return koishi_utils_1.camelCase(data);
}
else {
throw new SenderError(args, uri, data.retcode);
throw new SenderError(params, action, retcode);
}

@@ -60,2 +61,11 @@ }

}
start() {
this._timer = setInterval(() => {
this._messages.unshift(0);
this._messages.splice(-1, 1);
}, 1000);
}
stop() {
clearInterval(this._timer);
}
async sendContextMsg(contextId, message, autoEscape) {

@@ -73,3 +83,3 @@ const type = contextId[0];

return;
const response = await this._post('send_group_msg', { groupId, message, autoEscape });
const response = await this.post('send_group_msg', { groupId, message, autoEscape });
const meta = {

@@ -82,4 +92,3 @@ $path: `/group/${groupId}/send`,

};
this.app.handleMeta(meta);
this.app.emitMeta(meta);
await this.app.dispatchMeta(meta);
return response.messageId;

@@ -90,4 +99,4 @@ }

return;
this.messages[0] += 1;
const response = await this._post('send_discuss_msg', { discussId, message, autoEscape });
this._messages[0] += 1;
const response = await this.post('send_discuss_msg', { discussId, message, autoEscape });
const meta = {

@@ -100,4 +109,3 @@ $path: `/discuss/${discussId}/send`,

};
this.app.handleMeta(meta);
this.app.emitMeta(meta);
await this.app.dispatchMeta(meta);
return response.messageId;

@@ -108,4 +116,4 @@ }

return;
this.messages[0] += 1;
const response = await this._post('send_private_msg', { userId, message, autoEscape });
this._messages[0] += 1;
const response = await this.post('send_private_msg', { userId, message, autoEscape });
const meta = {

@@ -118,17 +126,16 @@ $path: `/user/${userId}/send`,

};
this.app.handleMeta(meta);
this.app.emitMeta(meta);
await this.app.dispatchMeta(meta);
return response.messageId;
}
async deleteMsg(messageId) {
await this._post('delete_msg', { messageId });
await this.post('delete_msg', { messageId });
}
async sendLike(userId, times = 1) {
await this._post('send_like', { userId, times });
await this.post('send_like', { userId, times });
}
async setGroupKick(groupId, userId, rejectAddRequest = false) {
await this._post('set_group_kick', { groupId, userId, rejectAddRequest });
await this.post('set_group_kick', { groupId, userId, rejectAddRequest });
}
async setGroupBan(groupId, userId, duration = 36 * 60) {
await this._post('set_group_ban', { groupId, userId, duration });
await this.post('set_group_ban', { groupId, userId, duration });
}

@@ -138,95 +145,95 @@ async setGroupAnonymousBan(groupId, meta, duration = 36 * 60) {

args[typeof meta === 'string' ? 'flag' : 'anomymous'] = meta;
await this._post('set_group_anonymous_ban', args);
await this.post('set_group_anonymous_ban', args);
}
async setGroupWholeBan(groupId, enable = true) {
await this._post('set_group_whole_ban', { groupId, enable });
await this.post('set_group_whole_ban', { groupId, enable });
}
async setGroupAdmin(groupId, userId, enable) {
await this._post('set_group_admin', { groupId, userId, enable });
await this.post('set_group_admin', { groupId, userId, enable });
}
async setGroupAnonymous(groupId, enable) {
await this._post('set_group_anonymous', { groupId, enable });
await this.post('set_group_anonymous', { groupId, enable });
}
async setGroupCard(groupId, userId, card = '') {
await this._post('set_group_admin', { groupId, userId, card });
await this.post('set_group_admin', { groupId, userId, card });
}
async setGroupLeave(groupId, isDismiss = false) {
await this._post('set_group_leave', { groupId, isDismiss });
await this.post('set_group_leave', { groupId, isDismiss });
}
async setGroupSpecialTitle(groupId, userId, specialTitle = '', duration = -1) {
await this._post('set_group_special_title', { groupId, userId, specialTitle, duration });
await this.post('set_group_special_title', { groupId, userId, specialTitle, duration });
}
async setDiscussLeave(discussId) {
await this._post('set_discuss_leave', { discussId });
await this.post('set_discuss_leave', { discussId });
}
async setFriendAddRequest(flag, approve = true, remark = '') {
await this._post('set_friend_add_request', { flag, approve, remark });
await this.post('set_friend_add_request', { flag, approve, remark });
}
async setGroupAddRequest(flag, subType, approve = true, reason = '') {
await this._post('set_group_add_request', { flag, subType, approve, reason });
await this.post('set_group_add_request', { flag, subType, approve, reason });
}
getLoginInfo() {
return this._post('get_login_info');
return this.post('get_login_info');
}
getStrangerInfo(userId, noCache = false) {
return this._post('get_stranger_info', { userId, noCache });
return this.post('get_stranger_info', { userId, noCache });
}
getFriendList() {
return this._post('get_friend_list');
return this.post('get_friend_list');
}
getGroupList() {
return this._post('get_group_list');
return this.post('get_group_list');
}
getGroupInfo(groupId, noCache = false) {
return this._post('get_group_info', { groupId, noCache });
return this.post('get_group_info', { groupId, noCache });
}
getGroupMemberInfo(groupId, userId, noCache = false) {
return this._post('get_group_member_info', { groupId, userId, noCache });
return this.post('get_group_member_info', { groupId, userId, noCache });
}
getGroupMemberList(groupId) {
return this._post('get_group_member_list', { groupId });
return this.post('get_group_member_list', { groupId });
}
async getCookies(domain) {
const { cookies } = await this._post('get_cookies', { domain });
const { cookies } = await this.post('get_cookies', { domain });
return cookies;
}
async getCsrfToken() {
const { token } = await this._post('get_csrf_token');
const { token } = await this.post('get_csrf_token');
return token;
}
getCredentials() {
return this._post('get_credentials');
return this.post('get_credentials');
}
async getRecord(file, outFormat, fullPath = false) {
const response = await this._post('get_record', { file, outFormat, fullPath });
const response = await this.post('get_record', { file, outFormat, fullPath });
return response.file;
}
async getImage(file) {
const response = await this._post('get_image', { file });
const response = await this.post('get_image', { file });
return response.file;
}
async canSendImage() {
const { yes } = await this._post('can_send_image');
const { yes } = await this.post('can_send_image');
return yes;
}
async canSendRecord() {
const { yes } = await this._post('can_send_record');
const { yes } = await this.post('can_send_record');
return yes;
}
getStatus() {
return this._post('get_status');
return this.post('get_status');
}
getVersionInfo() {
return this._post('get_version_info');
return this.post('get_version_info');
}
async setRestartPlugin(delay = 0) {
await this._post('set_restart_plugin', { delay });
await this.post('set_restart_plugin', { delay });
}
async cleanDataDir(dataDir) {
await this._post('clean_data_dir', { dataDir });
await this.post('clean_data_dir', { dataDir });
}
async cleanPluginLog() {
await this._post('clean_plugin_log');
await this.post('clean_plugin_log');
}
}
exports.Sender = Sender;

@@ -0,14 +1,34 @@

/// <reference types="node" />
import WebSocket from 'ws';
import { Response } from 'express';
import * as http from 'http';
import { App } from './app';
export declare function createServer(app: App): Server;
export declare class Server {
private _apps;
import { CQResponse } from './sender';
export declare abstract class Server {
protected _apps: App[];
private _appMap;
private _server;
private _socket;
private _httpServer;
private _isListening;
protected abstract _listen(): Promise<void>;
abstract close(): void;
constructor(app: App);
protected _handleData(data: any, res?: Response): void;
bind(app: App): this;
listen(port: number): void;
stop(): void;
listen(): Promise<void>;
}
export declare class HttpServer extends Server {
express: import("express-serve-static-core").Express;
httpServer: http.Server;
constructor(app: App);
_listen(): Promise<void>;
close(): void;
}
export declare class WsClient extends Server {
socket: WebSocket;
private _listeners;
constructor(app: App);
send(data: any): Promise<CQResponse>;
_listen(): Promise<void>;
close(): void;
}
export declare type ServerType = 'http' | 'ws';
export declare function createServer(app: App): Server;

@@ -15,11 +15,2 @@ "use strict";

showServerLog.inspectOpts.depth = 0;
const serverMap = {};
function createServer(app) {
const { port } = app.options;
if (port in serverMap) {
return serverMap[port].bind(app);
}
return serverMap[port] = new Server(app);
}
exports.createServer = createServer;
class Server {

@@ -29,43 +20,23 @@ constructor(app) {

this._appMap = {};
this._server = express_1.default().use(body_parser_1.json());
this._isListening = false;
if (app.options.wsServer) {
this._socket = new ws_1.default(app.options.wsServer + '/event', {
headers: {
Authorization: `Token ${app.options.token}`,
},
});
this._socket.on('message', (data) => {
console.log(data);
});
this.bind(app);
}
_handleData(data, res) {
const meta = koishi_utils_1.camelCase(data);
if (!this._appMap[meta.selfId]) {
const index = this._apps.findIndex(app => !app.options.selfId);
if (index < 0) {
if (res)
res.sendStatus(403);
return;
}
this._appMap[meta.selfId] = this._apps[index];
this._apps[index].options.selfId = meta.selfId;
this._apps[index]._registerSelfId();
}
if (app.options.secret) {
this._server.use((req, res, next) => {
const signature = req.header('x-signature');
if (!signature)
return res.sendStatus(401);
const body = JSON.stringify(req.body);
const sig = crypto_1.createHmac('sha1', app.options.secret).update(body).digest('hex');
if (signature !== `sha1=${sig}`)
return res.sendStatus(403);
return next();
});
}
this._server.use(async (req, res) => {
const meta = koishi_utils_1.camelCase(req.body);
if (!this._appMap[meta.selfId]) {
const index = this._apps.findIndex(app => !app.options.selfId);
if (index < 0)
return res.sendStatus(403);
this._appMap[meta.selfId] = this._apps[index];
this._apps[index].options.selfId = meta.selfId;
this._apps[index]._registerSelfId();
}
const app = this._appMap[meta.selfId];
const app = this._appMap[meta.selfId];
if (res)
res.sendStatus(200);
showServerLog('receive %o', meta);
await app.handleMeta(meta);
app.emitMeta(meta);
});
this.bind(app);
showServerLog('receive %o', meta);
app.dispatchMeta(meta);
}

@@ -79,8 +50,7 @@ bind(app) {

}
listen(port) {
async listen() {
if (this._isListening)
return;
this._isListening = true;
this._httpServer = this._server.listen(port);
showServerLog('listen to port', port);
await this._listen();
for (const app of this._apps) {

@@ -90,9 +60,107 @@ app.receiver.emit('connected', app);

}
stop() {
if (!this._httpServer)
return;
this._httpServer.close();
showServerLog('closed');
}
exports.Server = Server;
class HttpServer extends Server {
constructor(app) {
super(app);
this.express = express_1.default().use(body_parser_1.json());
if (app.options.secret) {
this.express.use((req, res, next) => {
const signature = req.header('x-signature');
if (!signature)
return res.sendStatus(401);
const body = JSON.stringify(req.body);
const sig = crypto_1.createHmac('sha1', app.options.secret).update(body).digest('hex');
if (signature !== `sha1=${sig}`)
return res.sendStatus(403);
return next();
});
}
this.express.use((req, res) => {
this._handleData(req.body, res);
});
}
async _listen() {
const { port } = this._apps[0].options;
this.httpServer = this.express.listen(port);
showServerLog('listen to port', port);
}
close() {
if (this.httpServer)
this.httpServer.close();
showServerLog('http server closed');
}
}
exports.Server = Server;
exports.HttpServer = HttpServer;
let counter = 0;
class WsClient extends Server {
constructor(app) {
super(app);
this._listeners = {};
this.socket = new ws_1.default(app.options.wsServer, {
headers: {
Authorization: `Bearer ${app.options.token}`,
},
});
this.socket.on('message', (data) => {
data = data.toString();
let parsed;
try {
parsed = JSON.parse(data);
}
catch (error) {
throw new Error(data);
}
if ('post_type' in parsed) {
this._handleData(parsed);
}
else if (parsed.echo in this._listeners) {
this._listeners[parsed.echo](parsed);
}
});
}
send(data) {
data.echo = ++counter;
return new Promise((resolve, reject) => {
this._listeners[counter] = resolve;
this.socket.send(JSON.stringify(data), (error) => {
if (error)
reject(error);
});
});
}
async _listen() {
await new Promise((resolve, reject) => {
this.socket.once('open', resolve);
this.socket.once('error', reject);
});
const { wsServer } = this._apps[0].options;
showServerLog('connect to ws server:', wsServer);
}
close() {
if (this.socket)
this.socket.close();
showServerLog('ws client closed');
}
}
exports.WsClient = WsClient;
const serverTypes = {
http: ['port', {}, HttpServer],
ws: ['wsServer', {}, WsClient],
};
function createServer(app) {
const { type } = app.options;
if (!serverTypes[type]) {
throw new Error(`server type "${type}" is not supported`);
}
const [key, serverMap, Server] = serverTypes[type];
const value = app.options[key];
if (!value) {
throw new Error(`missing configuration "${key}"`);
}
if (value in serverMap) {
return serverMap[value].bind(app);
}
return serverMap[value] = new Server(app);
}
exports.createServer = createServer;

@@ -71,3 +71,3 @@ "use strict";

function assertContextType(ctx, type) {
if (!ctx['id'] || !ctx.path.slice(1).startsWith(type)) {
if (!ctx.id || !ctx.path.slice(1).startsWith(type)) {
throw new Error(`expect a ${type} context, received path: ${ctx.path}`);

@@ -74,0 +74,0 @@ }

{
"name": "koishi-core",
"version": "0.2.1",
"version": "0.2.2",
"main": "dist/index.js",

@@ -5,0 +5,0 @@ "typings": "dist/index.d.ts",

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc