finish pipe
This commit is contained in:
parent
a13a6ba34f
commit
c27bb27ec3
@ -14,7 +14,7 @@ import * as Lagrange from '../type';
|
||||
* @param message 要发送的内容
|
||||
* @param auto_escape 消息内容是否作为纯文本发送(即不解析 CQ 码),只在 message 字段是字符串时有效
|
||||
*/
|
||||
export function sendPrivateMsg(user_id: number, message: Lagrange.Message, auto_escape: boolean = false) {
|
||||
export function sendPrivateMsg(user_id: number, message: string | Lagrange.Send.Default[], auto_escape: boolean = false) {
|
||||
return {
|
||||
action: 'send_private_msg',
|
||||
params: { user_id, message, auto_escape }
|
||||
@ -27,7 +27,7 @@ export function sendPrivateMsg(user_id: number, message: Lagrange.Message, auto_
|
||||
* @param message 要发送的内容
|
||||
* @param auto_escape 消息内容是否作为纯文本发送(即不解析 CQ 码),只在 message 字段是字符串时有效
|
||||
*/
|
||||
export function sendGroupMsg(group_id: number, message: Lagrange.Message, auto_escape: boolean = false) {
|
||||
export function sendGroupMsg(group_id: number, message: string | Lagrange.Send.Default[], auto_escape: boolean = false) {
|
||||
return {
|
||||
action: 'send_group_msg',
|
||||
params: { group_id, message, auto_escape }
|
||||
@ -42,7 +42,7 @@ export function sendGroupMsg(group_id: number, message: Lagrange.Message, auto_e
|
||||
* @param message 要发送的内容
|
||||
* @param auto_escape 消息内容是否作为纯文本发送(即不解析 CQ 码),只在 message 字段是字符串时有效
|
||||
*/
|
||||
export function sendMsg(message_type: string, user_id: number, group_id: number, message: Lagrange.Message, auto_escape: boolean = false) {
|
||||
export function sendMsg(message_type: string, user_id: number, group_id: number, message: string | Lagrange.Send.Default[], auto_escape: boolean = false) {
|
||||
return {
|
||||
action: 'send_msg',
|
||||
params: { message_type, user_id, group_id, message, auto_escape }
|
||||
|
55
bot/event.ts
55
bot/event.ts
@ -1,46 +1,59 @@
|
||||
import type * as Lagrange from './type';
|
||||
|
||||
import lagrangeMapper from './lagrange-mapping';
|
||||
|
||||
function runPipe(message: Lagrange.Message) {
|
||||
import type * as Lagrange from './type';
|
||||
import type { LagrangeContext } from './context';
|
||||
|
||||
class Pipe {
|
||||
context: LagrangeContext | undefined;
|
||||
send: Lagrange.SendApi | undefined;
|
||||
public injectContext(context: LagrangeContext) {
|
||||
this.context = context;
|
||||
this.send = context.send.bind(context);
|
||||
}
|
||||
|
||||
public run(message: Lagrange.Message) {
|
||||
switch (message.post_type) {
|
||||
case 'message': messagePipe(message); break;
|
||||
case 'notice': noticePipe(message); break;
|
||||
case 'request': requestPipe(message); break;
|
||||
case 'message': this.messagePipe(message); break;
|
||||
case 'notice': this.noticePipe(message); break;
|
||||
case 'request':this.requestPipe(message); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 处理 message 类型的 post_type 的
|
||||
function messagePipe(message: Lagrange.MessagePostType) {
|
||||
// 处理 message 类型的 post_type 消息
|
||||
public messagePipe(message: Lagrange.MessagePostType) {
|
||||
switch (message.message_type) {
|
||||
case 'private':
|
||||
|
||||
lagrangeMapper.resolvePrivateUser(message, this.send);
|
||||
break;
|
||||
case 'group':
|
||||
|
||||
lagrangeMapper.resolveGroup(message, this.send);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 处理 notice 类型的 post_type 消息
|
||||
public noticePipe(message: Lagrange.NoticePostType) {
|
||||
|
||||
}
|
||||
|
||||
// 处理 request 类型的 post_type 消息
|
||||
public requestPipe(message: Lagrange.RequestPostType) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 处理 notice 类型的 post_type 消息
|
||||
function noticePipe(message: Lagrange.NoticePostType) {
|
||||
|
||||
}
|
||||
|
||||
// 处理 request 类型的 post_type 消息
|
||||
function requestPipe(message: Lagrange.RequestPostType) {
|
||||
|
||||
}
|
||||
export const pipe = new Pipe();
|
||||
|
||||
export function onMessage(event: Buffer) {
|
||||
const messageBuffer = event.toString('utf-8');
|
||||
const messageJson = JSON.parse(messageBuffer) as Lagrange.Message;
|
||||
// 忽略系统 message
|
||||
if (messageJson.post_type !== 'meta_event') {
|
||||
runPipe(messageJson);
|
||||
console.log('进入 runPipe');
|
||||
pipe.run(messageJson);
|
||||
}
|
||||
}
|
||||
|
||||
|
10
bot/impl.ts
10
bot/impl.ts
@ -1,13 +1,15 @@
|
||||
import lagrangeMapper from './lagrange-mapping';
|
||||
import { apiQueryVecdb } from './api/vecdb';
|
||||
|
||||
import type * as Lagrange from './type';
|
||||
|
||||
|
||||
class Impl {
|
||||
export class Impl {
|
||||
|
||||
@lagrangeMapper.onPrivateUser({ user_id: 1193466151 })
|
||||
async handleJinhui(message: Lagrange.PrivateMessage) {
|
||||
@lagrangeMapper.onPrivateUser(1193466151)
|
||||
async handleJinhui(c: Lagrange.PrivateUserInvokeContext) {
|
||||
console.log('raw message:' + c.message.raw_message);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,8 +1,9 @@
|
||||
import assert from 'assert';
|
||||
|
||||
import type * as Lagrange from './type';
|
||||
|
||||
type PrivateUserInvoker = (message: Lagrange.PrivateMessage) => void;
|
||||
type GroupUserInvoker = (message: Lagrange.GroupMessage) => void;
|
||||
type PrivateUserInvoker = (context: Lagrange.PrivateUserInvokeContext) => Lagrange.Thenable<undefined | void | string | Lagrange.Send.Default>;
|
||||
type GroupUserInvoker = (context: Lagrange.GroupUserInvokeContext) => Lagrange.Thenable<undefined | void | string | Lagrange.Send.Default>;
|
||||
|
||||
type MessageInvoker = PrivateUserInvoker | GroupUserInvoker;
|
||||
|
||||
@ -17,7 +18,7 @@ interface CustomDescriptor<T extends MessageInvoker> {
|
||||
|
||||
interface MessageInvokerStorage<T extends MessageInvoker> {
|
||||
invoker: T;
|
||||
config: Partial<Lagrange.CommonMessage>
|
||||
config?: Partial<Lagrange.CommonMessage>
|
||||
}
|
||||
|
||||
class LagrangeMapper {
|
||||
@ -37,24 +38,33 @@ class LagrangeMapper {
|
||||
return this._groupStorage;
|
||||
}
|
||||
|
||||
public matchPrivateUser(message: Lagrange.PrivateMessage) {
|
||||
public resolvePrivateUser(message: Lagrange.PrivateMessage, send: Lagrange.SendApi) {
|
||||
const user_id = message.user_id;
|
||||
const userStorage = this._privateUserStorage.get(user_id);
|
||||
console.log(user_id);
|
||||
console.log(userStorage);
|
||||
|
||||
if (userStorage) {
|
||||
userStorage.invoker(message);
|
||||
userStorage.invoker({ message, send });
|
||||
}
|
||||
}
|
||||
|
||||
public onPrivateUser(config: Partial<Lagrange.CommonMessage>) {
|
||||
assert(config.user_id, 'onPrivateUser 中 user_id 不能为空');
|
||||
public resolveGroup(message: Lagrange.GroupMessage, send: Lagrange.SendApi) {
|
||||
const group_id = message.group_id;
|
||||
const groupStorage = this._groupStorage.get(group_id);
|
||||
if (groupStorage) {
|
||||
groupStorage.invoker({ message, send });
|
||||
}
|
||||
}
|
||||
|
||||
public onPrivateUser(user_id: number) {
|
||||
const _this = this;
|
||||
return function(target: any, propertyKey: string, descriptor: CustomDescriptor<PrivateUserInvoker>) {
|
||||
const user_id = config.user_id;
|
||||
if (_this.privateUserStorage.has(user_id)) {
|
||||
if (_this._privateUserStorage.has(user_id)) {
|
||||
console.warn(`${propertyKey} -> 用户 ${user_id} 已经被注册过了,该操作将覆盖原本的!`);
|
||||
}
|
||||
const invoker = descriptor.value;
|
||||
_this.privateUserStorage.set(user_id, { invoker, config });
|
||||
_this._privateUserStorage.set(user_id, { invoker });
|
||||
}
|
||||
}
|
||||
|
||||
|
33
bot/main.ts
33
bot/main.ts
@ -1,35 +1,14 @@
|
||||
import * as fs from 'fs';
|
||||
|
||||
import WebSocket from 'ws';
|
||||
import lagServer from './context';
|
||||
import './impl';
|
||||
|
||||
import { onMessage, onClose } from './event';
|
||||
import { apiQueryVecdb } from './api/vecdb';
|
||||
const buffer = fs.readFileSync('./app/publish/appsettings.json', 'utf-8');
|
||||
const config = JSON.parse(buffer);
|
||||
const impl = config.Implementations[0];
|
||||
|
||||
const lagrangeBuffer = fs.readFileSync('./app/publish/appsettings.json', 'utf-8');
|
||||
const lagrangeConfig = JSON.parse(lagrangeBuffer);
|
||||
const impl = lagrangeConfig.Implementations[0];
|
||||
const connectionParam = {
|
||||
lagServer.run({
|
||||
host: impl.Host,
|
||||
port: impl.Port,
|
||||
path: impl.Suffix
|
||||
};
|
||||
|
||||
const socket = new WebSocket.Server(connectionParam);
|
||||
|
||||
socket.on('connection', (ws: WebSocket) => {
|
||||
console.log('完成 ws 连接,启动参数如下');
|
||||
console.table(connectionParam);
|
||||
|
||||
ws.on('message', onMessage);
|
||||
ws.on('close', onClose);
|
||||
|
||||
const testMsg = {
|
||||
action: 'send_private_msg',
|
||||
params: {
|
||||
user_id: 1193466151,
|
||||
message: '你好'
|
||||
}
|
||||
}
|
||||
|
||||
ws.send(JSON.stringify(testMsg));
|
||||
});
|
@ -1,4 +1,5 @@
|
||||
import type * as Lagrange from './type';
|
||||
import * as Lagrange from './type';
|
||||
|
||||
|
||||
class Plugins {
|
||||
registeredPlugins: Map<string, Function>;
|
||||
|
363
bot/type.ts
363
bot/type.ts
@ -38,14 +38,23 @@ export interface Sender {
|
||||
title?: string
|
||||
}
|
||||
|
||||
export interface MsgText {
|
||||
// 参考文档: https://github.com/botuniverse/onebot-11/blob/master/message/segment.md
|
||||
export namespace Receive {
|
||||
export interface Text {
|
||||
type: 'text',
|
||||
data: {
|
||||
text: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface MsgImage {
|
||||
export interface Face {
|
||||
type: 'face',
|
||||
data: {
|
||||
id: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface Image {
|
||||
type: 'image',
|
||||
data: {
|
||||
file: string,
|
||||
@ -53,22 +62,334 @@ export interface MsgImage {
|
||||
// 在简略窗口可以看到的信息,对于图片来说,这就是 [图片]
|
||||
summary: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface MsgFace {
|
||||
type: 'face',
|
||||
data: {
|
||||
id: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface MsgAt {
|
||||
export interface Audio {
|
||||
type: 'record',
|
||||
data: {
|
||||
file: string,
|
||||
magic: 0 | 1,
|
||||
url: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface Video {
|
||||
type: 'video',
|
||||
data: {
|
||||
file: string,
|
||||
url: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface At {
|
||||
type: 'at',
|
||||
data: {
|
||||
qq: string
|
||||
}
|
||||
}
|
||||
|
||||
// 猜拳魔法表情
|
||||
export interface FingerGuess {
|
||||
type: 'rps',
|
||||
data: {}
|
||||
}
|
||||
|
||||
// 掷骰子魔法表情
|
||||
export interface Dice {
|
||||
type: 'dice',
|
||||
data: {}
|
||||
}
|
||||
|
||||
// 窗口抖动(戳一戳)
|
||||
export interface WindowJitter {
|
||||
type: 'shake',
|
||||
data: {}
|
||||
}
|
||||
|
||||
// 戳一戳
|
||||
export interface Poke {
|
||||
type: 'poke',
|
||||
data: {
|
||||
type: string,
|
||||
id: string,
|
||||
name: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface Link {
|
||||
type: 'share',
|
||||
data: {
|
||||
// URL
|
||||
url: string,
|
||||
// 标题
|
||||
title: string,
|
||||
// 发送时可选,内容描述
|
||||
content?: string,
|
||||
// 发送时可选,图片 URL
|
||||
image?: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface RecommendFriend {
|
||||
type: 'contact',
|
||||
data: {
|
||||
type: 'qq',
|
||||
// 被推荐人的 QQ 号
|
||||
id: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface RecommendGroup {
|
||||
type: 'contact',
|
||||
data: {
|
||||
type: 'group',
|
||||
// 被推荐群的群号
|
||||
id: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface Location {
|
||||
type: 'location',
|
||||
data: {
|
||||
// 纬度
|
||||
lat: string,
|
||||
// 经度
|
||||
lon: string,
|
||||
// 发送时可选,标题
|
||||
title?: string,
|
||||
// 发送时可选,内容描述
|
||||
content?: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface Reply {
|
||||
type: 'reply',
|
||||
data: {
|
||||
id: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface Forward {
|
||||
type: 'forward',
|
||||
data: {
|
||||
id: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface XML {
|
||||
type: 'xml',
|
||||
data: {
|
||||
// XML 内容
|
||||
data: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface JSON {
|
||||
type: 'json',
|
||||
data: {
|
||||
data: string
|
||||
}
|
||||
}
|
||||
|
||||
export type Default = Text | Face | Image | Audio | Video | At | FingerGuess | Dice | WindowJitter | Poke | Link | RecommendFriend | RecommendGroup | Location | Reply | Forward | XML | JSON;
|
||||
}
|
||||
|
||||
export namespace Send {
|
||||
export interface Text {
|
||||
type: 'text',
|
||||
data: {
|
||||
text: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface Face {
|
||||
type: 'face',
|
||||
data: {
|
||||
id: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface Image {
|
||||
type: 'image',
|
||||
data: {
|
||||
/**
|
||||
* 发送时 file 可行的三种取值
|
||||
* 1. 绝对路径,例如 file:///C:\\Users\Richard\Pictures\1.png
|
||||
* 2. 网络 URL,例如 http://i1.piimg.com/567571/fdd6e7b6d93f1ef0.jpg
|
||||
* Base64 编码,例如 base64://iVBORw0KGgoAAAANSUhEUgAAABQAAAAVCAIAAADJt1n/AAAAKElEQVQ4EWPk5+RmIBcwkasRpG9UM4mhNxpgowFGMARGEwnBIEJVAAAdBgBNAZf+QAAAAABJRU5ErkJggg==
|
||||
*/
|
||||
file: string,
|
||||
|
||||
// 只在通过网络 URL 发送时有效,表示是否使用已缓存的文件,默认 1
|
||||
cache: 0 | 1,
|
||||
|
||||
// 只在通过网络 URL 发送时有效,表示是否通过代理下载文件(需通过环境变量或配置文件配置代理),默认 1
|
||||
proxy: 0 | 1,
|
||||
|
||||
// 只在通过网络 URL 发送时有效,单位秒,表示下载网络文件的超时时间,默认不超时
|
||||
timeout: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface Audio {
|
||||
type: 'record',
|
||||
data: {
|
||||
file: string,
|
||||
magic: 0 | 1,
|
||||
cache: 0 | 1,
|
||||
proxy: 0 | 1,
|
||||
timeout: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface Video {
|
||||
type: 'video',
|
||||
data: {
|
||||
file: string,
|
||||
cache: 0 | 1,
|
||||
proxy: 0 | 1,
|
||||
timeout: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface At {
|
||||
type: 'at',
|
||||
data: {
|
||||
qq: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface FingerGuess {
|
||||
type: 'rps',
|
||||
data: {}
|
||||
}
|
||||
|
||||
export interface Dice {
|
||||
type: 'dice',
|
||||
data: {}
|
||||
}
|
||||
|
||||
export interface WindowJitter {
|
||||
type: 'shake',
|
||||
data: {}
|
||||
}
|
||||
|
||||
// 戳一戳
|
||||
export interface Poke {
|
||||
type: 'poke',
|
||||
data: {
|
||||
type: string,
|
||||
id: string,
|
||||
}
|
||||
}
|
||||
|
||||
export interface Anonymous {
|
||||
type: 'anonymous',
|
||||
data: {}
|
||||
}
|
||||
|
||||
export interface Link {
|
||||
type: 'share',
|
||||
data: {
|
||||
// URL
|
||||
url: string,
|
||||
// 标题
|
||||
title: string,
|
||||
// 发送时可选,内容描述
|
||||
content?: string,
|
||||
// 发送时可选,图片 URL
|
||||
image?: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface RecommendFriend {
|
||||
type: 'contact',
|
||||
data: {
|
||||
type: 'qq',
|
||||
// 被推荐人的 QQ 号
|
||||
id: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface RecommendGroup {
|
||||
type: 'contact',
|
||||
data: {
|
||||
type: 'group',
|
||||
// 被推荐群的群号
|
||||
id: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface Location {
|
||||
type: 'location',
|
||||
data: {
|
||||
// 纬度
|
||||
lat: string,
|
||||
// 经度
|
||||
lon: string,
|
||||
// 发送时可选,标题
|
||||
title?: string,
|
||||
// 发送时可选,内容描述
|
||||
content?: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface MusicShare {
|
||||
type: 'music',
|
||||
data: {
|
||||
// 分别表示使用 QQ 音乐、网易云音乐、虾米音乐
|
||||
type: 'qq' | '163' | 'xm',
|
||||
// 歌曲 ID
|
||||
id: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface CustomMusicShare {
|
||||
type: 'music',
|
||||
data: {
|
||||
type: 'custom',
|
||||
url: string,
|
||||
audio: string,
|
||||
title: string,
|
||||
content: string,
|
||||
image: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface Reply {
|
||||
type: 'reply',
|
||||
data: {
|
||||
id: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface ForwardNode {
|
||||
type: 'node',
|
||||
data: {
|
||||
id: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface XML {
|
||||
type: 'xml',
|
||||
data: {
|
||||
// XML 内容
|
||||
data: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface JSON {
|
||||
type: 'json',
|
||||
data: {
|
||||
data: string
|
||||
}
|
||||
}
|
||||
|
||||
export type Default = Text | Face | Image | Audio | Video | At | FingerGuess | Dice | WindowJitter | Poke | Anonymous | Link | RecommendFriend | RecommendGroup | Location | MusicShare | CustomMusicShare | Reply | ForwardNode | XML | JSON;
|
||||
}
|
||||
|
||||
|
||||
|
||||
export interface MsgFile {
|
||||
// 一般是 ''
|
||||
id: string,
|
||||
@ -103,7 +424,7 @@ export interface CommonMessage {
|
||||
// 是否为匿名发言,一般都是 null
|
||||
anonymous?: null | boolean,
|
||||
// 消息内容(结构化)
|
||||
message?: MsgText | MsgImage | MsgFace | MsgAt,
|
||||
message?: Receive.Default,
|
||||
// 消息内容(纯文本)
|
||||
raw_message?: string,
|
||||
// 发送的时间戳
|
||||
@ -125,7 +446,7 @@ export interface PrivateMessage {
|
||||
// 发消息的人的 QQ 号
|
||||
user_id: number,
|
||||
// 消息内容(结构化)
|
||||
message: MsgText | MsgImage | MsgFace | MsgAt,
|
||||
message: Receive.Default,
|
||||
// 消息内容(纯文本)
|
||||
raw_message: string,
|
||||
// 发送的时间戳
|
||||
@ -136,6 +457,7 @@ export interface PrivateMessage {
|
||||
font?: number
|
||||
}
|
||||
|
||||
|
||||
export interface GroupMessage {
|
||||
// 事件类型
|
||||
post_type: 'message',
|
||||
@ -152,7 +474,7 @@ export interface GroupMessage {
|
||||
// 是否为匿名发言,一般都是 null
|
||||
anonymous: null | boolean,
|
||||
// 消息内容(结构化)
|
||||
message: MsgText | MsgImage | MsgFace | MsgAt,
|
||||
message: Receive.Default,
|
||||
// 消息内容(纯文本)
|
||||
raw_message: string,
|
||||
// 发送的时间戳
|
||||
@ -205,3 +527,16 @@ export type Message = MetaMessage | PrivateMessage | GroupMessage | FileMessage
|
||||
export type MessagePostType = PrivateMessage | GroupMessage;
|
||||
export type NoticePostType = FileMessage | ApproveMessage;
|
||||
export type RequestPostType = AddMessage;
|
||||
|
||||
|
||||
export type Thenable<T> = T | Promise<T>;
|
||||
|
||||
export type SendApi = (msg: string | Send.Default[]) => Thenable<void | Error>;
|
||||
|
||||
export interface InvokerContext<M = Message> {
|
||||
message: M,
|
||||
send: SendApi
|
||||
}
|
||||
|
||||
export type PrivateUserInvokeContext = InvokerContext<PrivateMessage>;
|
||||
export type GroupUserInvokeContext = InvokerContext<GroupMessage>;
|
||||
|
@ -96,11 +96,11 @@ for el in soup.find_all('h2'):
|
||||
}
|
||||
|
||||
if param['type'] == 'message':
|
||||
param['type'] = 'Lagrange.Message'
|
||||
param['type'] = 'string | Lagrange.Send.Default[]'
|
||||
|
||||
params.append(param)
|
||||
|
||||
t1 = function_desc
|
||||
t1 = function_desc.strip()
|
||||
t2 = '\n'
|
||||
for param in params:
|
||||
t2 += ' * @param {} {}\n'.format(param['name'], param['desc'])
|
||||
|
Loading…
x
Reference in New Issue
Block a user