From ba387b40ca49c60ab46f409082570cd4dfb83443 Mon Sep 17 00:00:00 2001
From: linyuchen <lin.yu.chen@hotmail.com>
Date: Sat, 17 Feb 2024 01:42:14 +0800
Subject: [PATCH] =?UTF-8?q?=E6=9A=82=E5=AD=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 manifest.json                      | 52 ++++++++++++-----------
 src/common/data.ts                 |  2 +-
 src/ntqqapi/hook.ts                |  2 +-
 src/onebot11/actions/GetStatus.ts  |  2 +
 src/onebot11/actions/index.ts      |  4 +-
 src/onebot11/constructor.ts        | 29 ++-----------
 src/onebot11/events/constructor.ts | 58 ++++++++++++++++++++++++++
 src/onebot11/events/types.ts       | 67 ++++++++++++++++++++++++++++++
 src/onebot11/server.ts             | 14 +++----
 src/onebot11/types.ts              | 20 +--------
 10 files changed, 168 insertions(+), 82 deletions(-)
 create mode 100644 src/onebot11/events/constructor.ts
 create mode 100644 src/onebot11/events/types.ts

diff --git a/manifest.json b/manifest.json
index bd5ee7f..521ef5a 100644
--- a/manifest.json
+++ b/manifest.json
@@ -1,31 +1,33 @@
 {
-    "manifest_version": 4,
-    "type": "extension",
-    "name": "LLOneBot",
-    "slug": "LLOneBot",
-    "description": "LiteLoaderQQNT的OneBotApi",
-    "version": "3.2.1",
-    "thumbnail": "./icon.png",
-    "authors": [{
-        "name": "linyuchen",
-        "link": "https://github.com/linyuchen"
-    }],
-    "repository": {
+  "manifest_version": 4,
+  "type": "extension",
+  "name": "LLOneBot",
+  "slug": "LLOneBot",
+  "description": "LiteLoaderQQNT的OneBotApi",
+  "version": "3.3.0",
+  "thumbnail": "./icon.png",
+  "authors": [
+    {
+      "name": "linyuchen",
+      "link": "https://github.com/linyuchen"
+    }
+  ],
+  "repository": {
     "repo": "linyuchen/LiteLoaderQQNT-OneBotApi",
     "branch": "main",
     "release": {
-        "tag": "latest",
-        "name": "LLOneBot.zip"
-    }
-},
-    "platform": [
-        "win32",
-        "linux",
-        "darwin"
-    ],
-    "injects": {
-        "renderer": "./renderer.js",
-        "main": "./main.js",
-        "preload": "./preload.js"
+      "tag": "latest",
+      "name": "LLOneBot.zip"
     }
+  },
+  "platform": [
+    "win32",
+    "linux",
+    "darwin"
+  ],
+  "injects": {
+    "renderer": "./renderer.js",
+    "main": "./main.js",
+    "preload": "./preload.js"
+  }
 }
diff --git a/src/common/data.ts b/src/common/data.ts
index 91163d6..0027f11 100644
--- a/src/common/data.ts
+++ b/src/common/data.ts
@@ -88,5 +88,5 @@ export function getStrangerByUin(uin: string) {
     }
 }
 
-export const version = "v3.2.1"
+export const version = "v3.3.0"
 export const heartInterval = 15000 // 毫秒
\ No newline at end of file
diff --git a/src/ntqqapi/hook.ts b/src/ntqqapi/hook.ts
index 3b281b3..d937a16 100644
--- a/src/ntqqapi/hook.ts
+++ b/src/ntqqapi/hook.ts
@@ -41,7 +41,7 @@ let receiveHooks: Array<{
 export function hookNTQQApiReceive(window: BrowserWindow) {
     const originalSend = window.webContents.send;
     const patchSend = (channel: string, ...args: NTQQApiReturnData) => {
-        // log(`received ntqq api message: ${channel}`, JSON.stringify(args))
+        log(`received ntqq api message: ${channel}`, JSON.stringify(args))
         if (args?.[1] instanceof Array) {
             for (let receiveData of args?.[1]) {
                 const ntQQApiMethodName = receiveData.cmdName;
diff --git a/src/onebot11/actions/GetStatus.ts b/src/onebot11/actions/GetStatus.ts
index 1e388af..2df98db 100644
--- a/src/onebot11/actions/GetStatus.ts
+++ b/src/onebot11/actions/GetStatus.ts
@@ -1,8 +1,10 @@
 import BaseAction from "./BaseAction";
 import {OB11Status} from "../types";
+import { ActionName } from "./types";
 
 
 export default class GetStatus extends BaseAction<any, OB11Status> {
+    actionName = ActionName.GetStatus
     protected async _handle(payload: any): Promise<OB11Status> {
         return {
             online: null,
diff --git a/src/onebot11/actions/index.ts b/src/onebot11/actions/index.ts
index ae75b78..7ebaa6d 100644
--- a/src/onebot11/actions/index.ts
+++ b/src/onebot11/actions/index.ts
@@ -12,6 +12,7 @@ import DeleteMsg from "./DeleteMsg";
 import GetVersionInfo from "./GetVersionInfo";
 import CanSendRecord from "./CanSendRecord";
 import CanSendImage from "./CanSendImage";
+import GetStatus from "./GetStatus";
 
 export const actionHandlers = [
     new GetMsg(),
@@ -22,5 +23,6 @@ export const actionHandlers = [
     new DeleteMsg(),
     new GetVersionInfo(),
     new CanSendRecord(),
-    new CanSendImage()
+    new CanSendImage(),
+    new GetStatus()
 ]
\ No newline at end of file
diff --git a/src/onebot11/constructor.ts b/src/onebot11/constructor.ts
index d8afb2e..fd1511c 100644
--- a/src/onebot11/constructor.ts
+++ b/src/onebot11/constructor.ts
@@ -4,15 +4,16 @@ import {
     OB11Message,
     OB11Group,
     OB11GroupMember,
-    OB11User, OB11LifeCycleEvent, OB11HeartEvent
+    OB11User
 } from "./types";
 import { AtType, ChatType, Group, GroupMember, IMAGE_HTTP_HOST, RawMessage, SelfInfo, User } from '../ntqqapi/types';
 import { getFriend, getGroupMember, getHistoryMsgBySeq, heartInterval, msgHistory, selfInfo } from '../common/data';
 import { file2base64, getConfigUtil, log } from "../common/utils";
 import { NTQQApi } from "../ntqqapi/ntcall";
+import {OB11EventConstructor} from "./events/constructor";
 
 
-export class OB11Constructor {
+export class OB11Constructor extends OB11EventConstructor{
     static async message(msg: RawMessage): Promise<OB11Message> {
 
         const {enableBase64} = getConfigUtil().getConfig()
@@ -186,28 +187,4 @@ export class OB11Constructor {
     static groups(groups: Group[]): OB11Group[] {
         return groups.map(OB11Constructor.group)
     }
-
-    static lifeCycleEvent(): OB11LifeCycleEvent {
-        return {
-            time: Math.floor(Date.now() / 1000),
-            self_id: parseInt(selfInfo.uin),
-            post_type: "meta_event",
-            meta_event_type: "lifecycle",
-            sub_type: "connect"
-        }
-    }
-
-    static heartEvent(): OB11HeartEvent {
-        return {
-            time: Math.floor(Date.now() / 1000),
-            self_id: parseInt(selfInfo.uin),
-            post_type: "meta_event",
-            meta_event_type: "heartbeat",
-            status: {
-                online: true,
-                good: true
-            },
-            interval: heartInterval
-        }
-    }
 }
\ No newline at end of file
diff --git a/src/onebot11/events/constructor.ts b/src/onebot11/events/constructor.ts
new file mode 100644
index 0000000..3ce9221
--- /dev/null
+++ b/src/onebot11/events/constructor.ts
@@ -0,0 +1,58 @@
+import {
+    OB11EventBase,
+    OB11EventPostType, OB11FriendRecallNoticeEvent,
+    OB11GroupRecallNoticeEvent,
+    OB11HeartEvent,
+    OB11LifeCycleEvent, OB11MetaEvent, OB11NoticeBase
+} from "./types";
+import { heartInterval, selfInfo } from "../../common/data";
+
+function eventBase(post_type: OB11EventPostType): OB11EventBase {
+    return {
+        time: Math.floor(Date.now() / 1000),
+        self_id: parseInt(selfInfo.uin),
+        post_type
+    }
+}
+
+export class OB11EventConstructor {
+    static lifeCycle(): OB11LifeCycleEvent {
+        return {
+            ...eventBase(OB11EventPostType.META) as OB11MetaEvent,
+            meta_event_type: "lifecycle",
+            sub_type: "connect"
+        }
+    }
+
+    static heart(): OB11HeartEvent {
+        return {
+            ...eventBase(OB11EventPostType.META) as OB11MetaEvent,
+            meta_event_type: "heartbeat",
+            status: {
+                online: true,
+                good: true
+            },
+            interval: heartInterval
+        }
+    }
+
+    static groupRecall(group_id: string, user_id: string, operator_id: string, message_id: number): OB11GroupRecallNoticeEvent {
+        return {
+            ...eventBase(OB11EventPostType.NOTICE) as OB11NoticeBase,
+            notice_type: "group_recall",
+            group_id: parseInt(group_id),
+            user_id: parseInt(user_id),
+            operator_id: parseInt(operator_id),
+            message_id
+        }
+    }
+
+    static friendRecall(user_id: string, operator_id: string, message_id: number): OB11FriendRecallNoticeEvent {
+        return {
+            ...eventBase(OB11EventPostType.NOTICE) as OB11NoticeBase,
+            notice_type: "friend_recall",
+            user_id: parseInt(user_id),
+            message_id
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/onebot11/events/types.ts b/src/onebot11/events/types.ts
new file mode 100644
index 0000000..e1d9224
--- /dev/null
+++ b/src/onebot11/events/types.ts
@@ -0,0 +1,67 @@
+import { OB11Status } from "../types";
+
+export enum OB11EventPostType{
+    META = "meta_event",
+    NOTICE = "notice"
+}
+
+export interface OB11EventBase {
+    time: number
+    self_id: number
+    post_type: OB11EventPostType
+}
+
+export interface OB11MetaEvent extends OB11EventBase{
+    post_type: OB11EventPostType.META
+    meta_event_type: "lifecycle" | "heartbeat"
+}
+
+export interface OB11NoticeBase extends OB11EventBase{
+    post_type: OB11EventPostType.NOTICE
+    notice_type: "group_admin" | "group_decrease" | "group_increase" | "group_ban" | "friend_add" | "group_recall" | "friend_recall"
+}
+
+interface OB11GroupNoticeBase extends OB11NoticeBase{
+    group_id: number
+    user_id: number
+}
+
+export interface OB11GroupAdminNoticeEvent extends OB11GroupNoticeBase{
+    notice_type: "group_admin"
+    sub_type: "set" | "unset"
+}
+
+export interface OB11GroupMemberDecNoticeEvent extends OB11GroupNoticeBase{
+    notice_type: "group_decrease"
+    sub_type: "leave" | "kick" | "kick_me"
+    operator_id: number
+}
+
+export interface OB11GroupMemberIncNoticeEvent extends OB11GroupNoticeBase{
+    notice_type: "group_increase"
+    sub_type: "approve" | "invite"
+    operator_id: number
+}
+
+export interface OB11GroupRecallNoticeEvent extends OB11GroupNoticeBase{
+    notice_type: "group_recall"
+    operator_id: number
+    message_id: number
+}
+
+export interface OB11FriendRecallNoticeEvent extends OB11NoticeBase{
+    notice_type: "friend_recall"
+    user_id: number
+    message_id: number
+}
+
+export interface OB11LifeCycleEvent extends OB11MetaEvent {
+    meta_event_type: "lifecycle"
+    sub_type: "enable" | "disable" | "connect"
+}
+
+export interface OB11HeartEvent extends OB11MetaEvent {
+    meta_event_type: "heartbeat"
+    status: OB11Status
+    interval: number
+}
\ No newline at end of file
diff --git a/src/onebot11/server.ts b/src/onebot11/server.ts
index c479501..ec43b40 100644
--- a/src/onebot11/server.ts
+++ b/src/onebot11/server.ts
@@ -6,12 +6,13 @@ import { Request } from 'express';
 import { Response } from 'express';
 import { getConfigUtil, log } from "../common/utils";
 import { heartInterval, selfInfo } from "../common/data";
-import { OB11Message, OB11Return, OB11MessageData, OB11LifeCycleEvent, OB11MetaEvent } from './types';
+import { OB11Message, OB11Return, OB11MessageData } from './types';
 import { actionHandlers } from "./actions";
 import { OB11Response } from "./actions/utils";
 import { ActionName } from "./actions/types";
 import BaseAction from "./actions/BaseAction";
 import { OB11Constructor } from "./constructor";
+import { OB11LifeCycleEvent, OB11MetaEvent } from "./events/types";
 
 let wsServer: websocket.Server = null;
 let accessToken = ""
@@ -104,7 +105,7 @@ export function startWSServer(port: number) {
     wsServer = new websocket.Server({port})
     wsServer.on("connection", (ws, req) => {
         const url = req.url.split("?").shift();
-        log("received ws connect", url)
+        log("receive ws connect", url)
         let token: string = ""
         const authHeader = req.headers['authorization'];
         if (authHeader) {
@@ -129,11 +130,6 @@ export function startWSServer(port: number) {
                 return ws.close()
             }
         }
-        // const queryParams = querystring.parse(parsedUrl.query);
-        // let token = req
-        // ws.send('Welcome to the LLOneBot WebSocket server! url:' + url);
-
-
         if (url == "/api" || url == "/api/" || url == "/") {
             ws.on("message", async (msg) => {
 
@@ -167,14 +163,14 @@ export function startWSServer(port: number) {
             log("event上报ws客户端已连接")
             wsEventClients.push(ws)
             try {
-                wsReply(ws, OB11Constructor.lifeCycleEvent())
+                wsReply(ws, OB11Constructor.lifeCycle())
             }catch (e){
                 log("发送生命周期失败", e)
             }
             // 心跳
             let wsHeart = setInterval(()=>{
                 if (wsEventClients.find(c => c == ws)){
-                    wsReply(ws, OB11Constructor.heartEvent())
+                    wsReply(ws, OB11Constructor.heart())
                 }
             }, heartInterval)
             ws.on("close", () => {
diff --git a/src/onebot11/types.ts b/src/onebot11/types.ts
index 611ad3f..32e5248 100644
--- a/src/onebot11/types.ts
+++ b/src/onebot11/types.ts
@@ -1,5 +1,4 @@
-import { AtType } from "../ntqqapi/types";
-import { RawMessage } from "../ntqqapi/types";
+import { AtType, RawMessage } from "../ntqqapi/types";
 
 export interface OB11User{
     user_id: number;
@@ -149,25 +148,8 @@ export interface OB11Version {
 }
 
 
-export interface OB11MetaEvent {
-    time: number
-    self_id: number
-    post_type: "meta_event"
-    meta_event_type: "lifecycle" | "heartbeat"
-}
-
-export interface OB11LifeCycleEvent extends OB11MetaEvent{
-    meta_event_type: "lifecycle"
-    sub_type: "enable" | "disable" | "connect"
-}
-
 export interface OB11Status {
     online: boolean | null,
     good: boolean
 }
 
-export interface OB11HeartEvent extends OB11MetaEvent{
-    meta_event_type: "heartbeat"
-    status: OB11Status
-    interval: number
-}
\ No newline at end of file