mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-07-19 12:03:37 +00:00
Compare commits
62 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
da90245f7b | ||
![]() |
410d6a85d7 | ||
![]() |
b693342e4f | ||
![]() |
acca361f2e | ||
![]() |
b663f47713 | ||
![]() |
d332b199b5 | ||
![]() |
78bac1dbd1 | ||
![]() |
724ff215f9 | ||
![]() |
68ea146469 | ||
![]() |
82583e616f | ||
![]() |
bfc339c58d | ||
![]() |
fe4427c076 | ||
![]() |
5745f388a9 | ||
![]() |
377e3c253f | ||
![]() |
3007a0c00e | ||
![]() |
f51ffc091d | ||
![]() |
c37c364a08 | ||
![]() |
331a106e9a | ||
![]() |
cd74687b7b | ||
![]() |
b3e145c1e6 | ||
![]() |
d8e1547736 | ||
![]() |
8617f01924 | ||
![]() |
55f9e75e6a | ||
![]() |
b93e7b7ed1 | ||
![]() |
89cc79ad60 | ||
![]() |
8dd0e60eea | ||
![]() |
df6113fdf6 | ||
![]() |
3a3095d15a | ||
![]() |
fb4d07391e | ||
![]() |
9bef9c85cf | ||
![]() |
b77b3f227f | ||
![]() |
6a065f0a34 | ||
![]() |
4e1e190797 | ||
![]() |
1ce8cd2100 | ||
![]() |
c03af6b9ad | ||
![]() |
adca850075 | ||
![]() |
e3616b484e | ||
![]() |
cfd7808169 | ||
![]() |
addcedc588 | ||
![]() |
bfea786088 | ||
![]() |
50e84c3c9e | ||
![]() |
dc92ace85e | ||
![]() |
1a543928b1 | ||
![]() |
652fe8d21e | ||
![]() |
199690f45f | ||
![]() |
37a4dd4b00 | ||
![]() |
34d4358bfc | ||
![]() |
90906b9019 | ||
![]() |
1c212ff2b4 | ||
![]() |
7d709f44a8 | ||
![]() |
ea9e88a18a | ||
![]() |
0be8a9c805 | ||
![]() |
fcf8139afe | ||
![]() |
62f969b50b | ||
![]() |
6726062500 | ||
![]() |
cf1f4bdcaf | ||
![]() |
b09a14ad4e | ||
![]() |
1dc62c9ca3 | ||
![]() |
beaa89a2dc | ||
![]() |
f39a000b49 | ||
![]() |
013a74fb14 | ||
![]() |
7c4964753b |
28
.github/workflows/release.yml
vendored
28
.github/workflows/release.yml
vendored
@@ -93,15 +93,18 @@ jobs:
|
|||||||
needs: [Build-LiteLoader,Build-Shell]
|
needs: [Build-LiteLoader,Build-Shell]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
|
- name: Clone Main Repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: 'NapNeko/NapCatQQ'
|
||||||
|
submodules: true
|
||||||
|
ref: main
|
||||||
|
token: ${{ secrets.NAPCAT_BUILD }}
|
||||||
|
|
||||||
- name: Download All Artifact
|
- name: Download All Artifact
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
# - name: Compress subdirectories
|
|
||||||
# run: |
|
|
||||||
# cd ./NapCat.Shell/
|
|
||||||
# zip -q -r NapCat.Shell.zip *
|
|
||||||
# cd ..
|
|
||||||
# rm ./NapCat.Shell.zip -rf
|
|
||||||
# mv ./NapCat.Shell/NapCat.Shell.zip ./
|
|
||||||
- name: Compress subdirectories
|
- name: Compress subdirectories
|
||||||
run: |
|
run: |
|
||||||
cd ./NapCat.Shell/
|
cd ./NapCat.Shell/
|
||||||
@@ -114,6 +117,16 @@ jobs:
|
|||||||
rm ./NapCat.Framework.zip -rf
|
rm ./NapCat.Framework.zip -rf
|
||||||
mv ./NapCat.Shell/NapCat.Shell.zip ./
|
mv ./NapCat.Shell/NapCat.Shell.zip ./
|
||||||
mv ./NapCat.Framework/NapCat.Framework.zip ./
|
mv ./NapCat.Framework/NapCat.Framework.zip ./
|
||||||
|
|
||||||
|
mkdir ./NapCat.Framework.Windows.Once
|
||||||
|
unzip -q ./external/LiteLoaderWrapper.zip -d ./NapCat.Framework.Windows.Once
|
||||||
|
cd ./NapCat.Framework.Windows.Once
|
||||||
|
ls
|
||||||
|
mkdir -p ./LL/plugins/NapCatQQ
|
||||||
|
unzip -q ../NapCat.Framework.zip -d ./LL/plugins/NapCatQQ
|
||||||
|
zip -q -r NapCat.Framework.Windows.Once.zip *
|
||||||
|
cd ..
|
||||||
|
mv ./NapCat.Framework.Windows.Once/NapCat.Framework.Windows.Once.zip ./
|
||||||
- name: Extract version from tag
|
- name: Extract version from tag
|
||||||
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV
|
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV
|
||||||
|
|
||||||
@@ -129,4 +142,5 @@ jobs:
|
|||||||
files: |
|
files: |
|
||||||
NapCat.Framework.zip
|
NapCat.Framework.zip
|
||||||
NapCat.Shell.zip
|
NapCat.Shell.zip
|
||||||
|
NapCat.Framework.Windows.Once.zip
|
||||||
draft: true
|
draft: true
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
## 欢迎回来
|
## 欢迎回来
|
||||||
NapCatQQ (aka 猫猫框架) 是现代化的基于 NTQQ 的 Bot 协议端实现。
|
NapCatQQ (aka 猫猫框架) 是现代化的基于 NTQQ 的 Bot 协议端实现
|
||||||
|
|
||||||
## 猫猫技能
|
## 猫猫技能
|
||||||
- [x] **高性能**:1K+ 群聊数目、20 线程并行发送消息毫无压力
|
- [x] **高性能**:1K+ 群聊数目、20 线程并行发送消息毫无压力
|
||||||
@@ -20,7 +20,7 @@ NapCatQQ (aka 猫猫框架) 是现代化的基于 NTQQ 的 Bot 协议端实现
|
|||||||
|
|
||||||
可前往 [Release](https://github.com/NapNeko/NapCatQQ/releases/) 页面下载最新版本
|
可前往 [Release](https://github.com/NapNeko/NapCatQQ/releases/) 页面下载最新版本
|
||||||
|
|
||||||
**首次使用**请务必前往[官方文档](https://napneko.github.io/)查看使用教程。
|
**首次使用**请务必前往[官方文档](https://napneko.github.io/)查看使用教程
|
||||||
|
|
||||||
## 回家旅途
|
## 回家旅途
|
||||||
[QQ Group](https://qm.qq.com/q/VfjAq5HIMS)
|
[QQ Group](https://qm.qq.com/q/VfjAq5HIMS)
|
||||||
@@ -40,4 +40,4 @@ NapCatQQ (aka 猫猫框架) 是现代化的基于 NTQQ 的 Bot 协议端实现
|
|||||||
> [!CAUTION]\
|
> [!CAUTION]\
|
||||||
> **请不要在 QQ 官方群聊和任何影响力较大的简中互联网平台(包括但不限于: 哔哩哔哩,微博,知乎,抖音等)发布和讨论*任何*与本项目存在相关性的信息**
|
> **请不要在 QQ 官方群聊和任何影响力较大的简中互联网平台(包括但不限于: 哔哩哔哩,微博,知乎,抖音等)发布和讨论*任何*与本项目存在相关性的信息**
|
||||||
|
|
||||||
任何使用本仓库代码的地方,都应当严格遵守[本仓库开源许可](./LICENSE)。**此外,禁止任何项目未经授权二次分发或基于 NapCat 代码开发。**
|
任何使用本仓库代码的地方,都应当严格遵守[本仓库开源许可](./LICENSE)。**此外,禁止任何项目未经授权二次分发或基于 NapCat 代码开发。**
|
||||||
|
BIN
external/LiteLoaderWrapper.zip
vendored
Normal file
BIN
external/LiteLoaderWrapper.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,6 +1,9 @@
|
|||||||
{
|
{
|
||||||
"name": "qq-chat",
|
"name": "qq-chat",
|
||||||
"version": "9.9.15-28131",
|
"version": "9.9.15-28418",
|
||||||
|
"verHash": "206bfa62",
|
||||||
|
"linuxVersion": "3.2.12-28327",
|
||||||
|
"linuxVerHash": "f60e8252",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "QQ",
|
"description": "QQ",
|
||||||
@@ -15,7 +18,7 @@
|
|||||||
"qd": "externals/devtools/cli/index.js"
|
"qd": "externals/devtools/cli/index.js"
|
||||||
},
|
},
|
||||||
"main": "./loadNapCat.js",
|
"main": "./loadNapCat.js",
|
||||||
"buildVersion": "28131",
|
"buildVersion": "28418",
|
||||||
"isPureShell": true,
|
"isPureShell": true,
|
||||||
"isByteCodeShell": true,
|
"isByteCodeShell": true,
|
||||||
"platform": "win32",
|
"platform": "win32",
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
"name": "NapCatQQ",
|
"name": "NapCatQQ",
|
||||||
"slug": "NapCat.Framework",
|
"slug": "NapCat.Framework",
|
||||||
"description": "高性能的 OneBot 11 协议实现",
|
"description": "高性能的 OneBot 11 协议实现",
|
||||||
"version": "2.6.13",
|
"version": "2.6.20",
|
||||||
"icon": "./logo.png",
|
"icon": "./logo.png",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
"name": "napcat",
|
"name": "napcat",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "2.6.13",
|
"version": "2.6.20",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build:framework": "vite build --mode framework",
|
"build:framework": "vite build --mode framework",
|
||||||
"build:shell": "vite build --mode shell",
|
"build:shell": "vite build --mode shell",
|
||||||
@@ -13,11 +13,10 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/preset-typescript": "^7.24.7",
|
"@babel/preset-typescript": "^7.24.7",
|
||||||
"@log4js-node/log4js-api": "^1.0.2",
|
"@log4js-node/log4js-api": "^1.0.2",
|
||||||
"@protobuf-ts/plugin": "^2.9.4",
|
|
||||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||||
"@rollup/plugin-typescript": "^11.1.6",
|
"@rollup/plugin-typescript": "^11.1.6",
|
||||||
"@types/cors": "^2.8.17",
|
"@types/cors": "^2.8.17",
|
||||||
"@types/express": "^4.17.21",
|
"@types/express": "^5.0.0",
|
||||||
"@types/fluent-ffmpeg": "^2.1.24",
|
"@types/fluent-ffmpeg": "^2.1.24",
|
||||||
"@types/node": "^22.0.1",
|
"@types/node": "^22.0.1",
|
||||||
"@types/qrcode-terminal": "^0.12.2",
|
"@types/qrcode-terminal": "^0.12.2",
|
||||||
@@ -30,11 +29,11 @@
|
|||||||
"typescript": "^5.3.3",
|
"typescript": "^5.3.3",
|
||||||
"vite": "^5.2.6",
|
"vite": "^5.2.6",
|
||||||
"vite-plugin-cp": "^4.0.8",
|
"vite-plugin-cp": "^4.0.8",
|
||||||
"vite-plugin-dts": "^3.8.2",
|
|
||||||
"vite-tsconfig-paths": "^4.3.2"
|
"vite-tsconfig-paths": "^4.3.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ajv": "^8.13.0",
|
"ajv": "^8.13.0",
|
||||||
|
"@protobuf-ts/plugin": "^2.9.4",
|
||||||
"async-mutex": "^0.5.0",
|
"async-mutex": "^0.5.0",
|
||||||
"chalk": "^5.3.0",
|
"chalk": "^5.3.0",
|
||||||
"commander": "^12.1.0",
|
"commander": "^12.1.0",
|
||||||
@@ -46,10 +45,8 @@
|
|||||||
"image-size": "^1.1.1",
|
"image-size": "^1.1.1",
|
||||||
"json-schema-to-ts": "^3.1.0",
|
"json-schema-to-ts": "^3.1.0",
|
||||||
"log4js": "^6.9.1",
|
"log4js": "^6.9.1",
|
||||||
"protobufjs": "~7.4.0",
|
|
||||||
"qrcode-terminal": "^0.12.0",
|
"qrcode-terminal": "^0.12.0",
|
||||||
"silk-wasm": "^3.6.1",
|
"silk-wasm": "^3.6.1",
|
||||||
"strtok3": "8.0.1",
|
|
||||||
"ws": "^8.18.0"
|
"ws": "^8.18.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -139,8 +139,7 @@ export class LogWrapper {
|
|||||||
|
|
||||||
logMessage(msg: RawMessage, selfInfo: SelfInfo) {
|
logMessage(msg: RawMessage, selfInfo: SelfInfo) {
|
||||||
const isSelfSent = msg.senderUin === selfInfo.uin;
|
const isSelfSent = msg.senderUin === selfInfo.uin;
|
||||||
this.log(`${
|
this.log(`${isSelfSent ? '发送 ->' : '接收 <-'
|
||||||
isSelfSent ? '发送 ->' : '接收 <-'
|
|
||||||
} ${rawMessageToText(msg)}`);
|
} ${rawMessageToText(msg)}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -180,12 +179,11 @@ export function rawMessageToText(msg: RawMessage, recursiveLevel = 0): string {
|
|||||||
const recordMsgOrNull = msg.records.find(
|
const recordMsgOrNull = msg.records.find(
|
||||||
record => element.replyElement!.sourceMsgIdInRecords === record.msgId,
|
record => element.replyElement!.sourceMsgIdInRecords === record.msgId,
|
||||||
);
|
);
|
||||||
return `[回复消息 ${
|
return `[回复消息 ${recordMsgOrNull &&
|
||||||
recordMsgOrNull &&
|
recordMsgOrNull.peerUin != '284840486' && recordMsgOrNull.peerUin != '1094950020'// 非转发消息; 否则定位不到
|
||||||
recordMsgOrNull.peerUin != '284840486' // 非转发消息; 否则定位不到
|
?
|
||||||
?
|
rawMessageToText(recordMsgOrNull, recursiveLevel + 1) :
|
||||||
rawMessageToText(recordMsgOrNull, recursiveLevel + 1) :
|
`未找到消息记录 (MsgId = ${element.replyElement.sourceMsgIdInRecords})`
|
||||||
`未找到消息记录 (MsgId = ${element.replyElement.sourceMsgIdInRecords})`
|
|
||||||
}]`;
|
}]`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1 +1 @@
|
|||||||
export const napCatVersion = '2.6.13';
|
export const napCatVersion = '2.6.20';
|
||||||
|
@@ -120,12 +120,20 @@ export class NTQQUserApi {
|
|||||||
return this.context.session.getProfileService().modifyDesktopMiniProfile(param);
|
return this.context.session.getProfileService().modifyDesktopMiniProfile(param);
|
||||||
}
|
}
|
||||||
|
|
||||||
//需要异常处理
|
|
||||||
async getCookies(domain: string) {
|
async getCookies(domain: string) {
|
||||||
const ClientKeyData = await this.forceFetchClientKey();
|
const ClientKeyData = await this.forceFetchClientKey();
|
||||||
const requestUrl = 'https://ssl.ptlogin2.qq.com/jump?ptlang=1033&clientuin=' + this.core.selfInfo.uin +
|
const requestUrl = 'https://ssl.ptlogin2.qq.com/jump?ptlang=1033&clientuin=' + this.core.selfInfo.uin +
|
||||||
'&clientkey=' + ClientKeyData.clientKey + '&u1=https%3A%2F%2F' + domain + '%2F' + this.core.selfInfo.uin + '%2Finfocenter&keyindex=19%27';
|
'&clientkey=' + ClientKeyData.clientKey + '&u1=https%3A%2F%2F' + domain + '%2F' + this.core.selfInfo.uin + '%2Finfocenter&keyindex=19%27';
|
||||||
return await RequestUtil.HttpsGetCookies(requestUrl);
|
let data = await RequestUtil.HttpsGetCookies(requestUrl);
|
||||||
|
if (!data.p_skey || data.p_skey.length == 0) {
|
||||||
|
try {
|
||||||
|
let pskey = (await this.getPSkey([domain])).domainPskeyMap.get(domain);
|
||||||
|
if (pskey) data.p_skey = pskey;
|
||||||
|
} catch {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPSkey(domainList: string[]) {
|
async getPSkey(domainList: string[]) {
|
||||||
|
@@ -659,7 +659,8 @@ export interface GrayTipElement {
|
|||||||
export enum FaceType {
|
export enum FaceType {
|
||||||
normal = 1, // 小黄脸
|
normal = 1, // 小黄脸
|
||||||
normal2 = 2, // 新小黄脸, 从faceIndex 222开始?
|
normal2 = 2, // 新小黄脸, 从faceIndex 222开始?
|
||||||
dice = 3 // 骰子
|
dice = 3, // 骰子
|
||||||
|
poke = 5 // 拍一拍
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum FaceIndex {
|
export enum FaceIndex {
|
||||||
|
16
src/core/external/appid.json
vendored
16
src/core/external/appid.json
vendored
@@ -14,5 +14,21 @@
|
|||||||
"3.2.12-28131": {
|
"3.2.12-28131": {
|
||||||
"appid": 537246140,
|
"appid": 537246140,
|
||||||
"qua": "V1_LNX_NQ_3.2.12_28131_GW_B"
|
"qua": "V1_LNX_NQ_3.2.12_28131_GW_B"
|
||||||
|
},
|
||||||
|
"9.9.15-28327":{
|
||||||
|
"appid": 537249321,
|
||||||
|
"qua": "V1_WIN_NQ_9.9.15_28327_GW_B"
|
||||||
|
},
|
||||||
|
"3.2.12-28327":{
|
||||||
|
"appid": 537249393,
|
||||||
|
"qua": "V1_LNX_NQ_3.2.12_28327_GW_B"
|
||||||
|
},
|
||||||
|
"9.9.15-28418":{
|
||||||
|
"appid": 537249321,
|
||||||
|
"qua": "V1_WIN_NQ_9.9.15_28418_GW_B"
|
||||||
|
},
|
||||||
|
"3.2.12-28418":{
|
||||||
|
"appid": 537249393,
|
||||||
|
"qua": "V1_LNX_NQ_3.2.12_28418_GW_B"
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -20,16 +20,15 @@ import { LogLevel, LogWrapper } from '@/common/log';
|
|||||||
import { NodeIKernelLoginService } from '@/core/services';
|
import { NodeIKernelLoginService } from '@/core/services';
|
||||||
import { QQBasicInfoWrapper } from '@/common/qq-basic-info';
|
import { QQBasicInfoWrapper } from '@/common/qq-basic-info';
|
||||||
import { NapCatPathWrapper } from '@/common/path';
|
import { NapCatPathWrapper } from '@/common/path';
|
||||||
import path from 'node:path';
|
import path, { resolve } from 'node:path';
|
||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
import { hostname, systemName, systemVersion } from '@/common/system';
|
import { hostname, systemName, systemVersion } from '@/common/system';
|
||||||
import { NTEventWrapper } from '@/common/event';
|
import { NTEventWrapper } from '@/common/event';
|
||||||
import { DataSource, GroupMember, KickedOffLineInfo, SelfInfo, SelfStatusInfo } from '@/core/entities';
|
import { ChatType, DataSource, GroupMember, KickedOffLineInfo, Peer, SelfInfo, SelfStatusInfo } from '@/core/entities';
|
||||||
import { NapCatConfigLoader } from '@/core/helper/config';
|
import { NapCatConfigLoader } from '@/core/helper/config';
|
||||||
import os from 'node:os';
|
import os from 'node:os';
|
||||||
import { NodeIKernelGroupListener, NodeIKernelMsgListener, NodeIKernelProfileListener } from '@/core/listeners';
|
import { NodeIKernelGroupListener, NodeIKernelMsgListener, NodeIKernelProfileListener } from '@/core/listeners';
|
||||||
import { proxiedListenerOf } from '@/common/proxy-handler';
|
import { proxiedListenerOf } from '@/common/proxy-handler';
|
||||||
|
|
||||||
export * from './wrapper';
|
export * from './wrapper';
|
||||||
export * from './entities';
|
export * from './entities';
|
||||||
export * from './services';
|
export * from './services';
|
||||||
@@ -99,6 +98,7 @@ export class NapCatCore {
|
|||||||
if (!fs.existsSync(this.NapCatTempPath)) {
|
if (!fs.existsSync(this.NapCatTempPath)) {
|
||||||
fs.mkdirSync(this.NapCatTempPath, { recursive: true });
|
fs.mkdirSync(this.NapCatTempPath, { recursive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
this.initNapCatCoreListeners().then().catch(this.context.logger.logError.bind(this.context.logger));
|
this.initNapCatCoreListeners().then().catch(this.context.logger.logError.bind(this.context.logger));
|
||||||
|
|
||||||
this.context.logger.setFileLogEnabled(
|
this.context.logger.setFileLogEnabled(
|
||||||
@@ -248,7 +248,7 @@ export class NapCatCore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function genSessionConfig(
|
export async function genSessionConfig(
|
||||||
guid:string,
|
guid: string,
|
||||||
QQVersionAppid: string,
|
QQVersionAppid: string,
|
||||||
QQVersion: string,
|
QQVersion: string,
|
||||||
selfUin: string,
|
selfUin: string,
|
||||||
|
48
src/core/proto/Message.ts
Normal file
48
src/core/proto/Message.ts
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import { MessageType, BinaryReader, ScalarType } from '@protobuf-ts/runtime';
|
||||||
|
|
||||||
|
export const BodyInner = new MessageType("BodyInner", [
|
||||||
|
{ no: 1, name: "msgType", kind: "scalar", T: ScalarType.UINT32 /* uint32 */, opt: true },
|
||||||
|
{ no: 2, name: "subType", kind: "scalar", T: ScalarType.UINT32 /* uint32 */, opt: true }
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const NoifyData = new MessageType("NoifyData", [
|
||||||
|
{ no: 1, name: "skip", kind: "scalar", T: ScalarType.BYTES /* bytes */, opt: true },
|
||||||
|
{ no: 2, name: "innerData", kind: "scalar", T: ScalarType.BYTES /* bytes */, opt: true }
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const MsgHead = new MessageType("MsgHead", [
|
||||||
|
{ no: 2, name: "bodyInner", kind: "message", T: () => BodyInner, opt: true },
|
||||||
|
{ no: 3, name: "noifyData", kind: "message", T: () => NoifyData, opt: true }
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const Message = new MessageType("Message", [
|
||||||
|
{ no: 1, name: "msgHead", kind: "message", T: () => MsgHead }
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const SubDetail = new MessageType("SubDetail", [
|
||||||
|
{ no: 1, name: "msgSeq", kind: "scalar", T: ScalarType.UINT32 /* uint32 */ },
|
||||||
|
{ no: 2, name: "msgTime", kind: "scalar", T: ScalarType.UINT32 /* uint32 */ },
|
||||||
|
{ no: 6, name: "senderUid", kind: "scalar", T: ScalarType.STRING /* string */ }
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const RecallDetails = new MessageType("RecallDetails", [
|
||||||
|
{ no: 1, name: "operatorUid", kind: "scalar", T: ScalarType.STRING /* string */ },
|
||||||
|
{ no: 3, name: "subDetail", kind: "message", T: () => SubDetail }
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const RecallGroup = new MessageType("RecallGroup", [
|
||||||
|
{ no: 1, name: "type", kind: "scalar", T: ScalarType.INT32 /* int32 */ },
|
||||||
|
{ no: 4, name: "peerUid", kind: "scalar", T: ScalarType.UINT32 /* uint32 */ },
|
||||||
|
{ no: 11, name: "recallDetails", kind: "message", T: () => RecallDetails },
|
||||||
|
{ no: 37, name: "grayTipsSeq", kind: "scalar", T: ScalarType.UINT32 /* uint32 */ }
|
||||||
|
]);
|
||||||
|
|
||||||
|
export function decodeMessage(buffer: Uint8Array): any {
|
||||||
|
const reader = new BinaryReader(buffer);
|
||||||
|
return Message.internalBinaryRead(reader, reader.len, { readUnknownField: true, readerFactory: () => new BinaryReader(buffer) });
|
||||||
|
}
|
||||||
|
|
||||||
|
export function decodeRecallGroup(buffer: Uint8Array): any {
|
||||||
|
const reader = new BinaryReader(buffer);
|
||||||
|
return RecallGroup.internalBinaryRead(reader, reader.len, { readUnknownField: true, readerFactory: () => new BinaryReader(buffer) });
|
||||||
|
}
|
@@ -1,95 +1,58 @@
|
|||||||
import * as pb from 'protobufjs';
|
import { MessageType, BinaryReader, ScalarType, RepeatType } from '@protobuf-ts/runtime';
|
||||||
|
|
||||||
// Proto: from src/core/proto/ProfileLike.proto
|
export const LikeDetail = new MessageType("likeDetail", [
|
||||||
// Author: Mlikiowa
|
{ no: 1, name: "txt", kind: "scalar", T: ScalarType.STRING /* string */ },
|
||||||
|
{ no: 3, name: "uin", kind: "scalar", T: ScalarType.INT64 /* int64 */ },
|
||||||
|
{ no: 5, name: "nickname", kind: "scalar", T: ScalarType.STRING /* string */ }
|
||||||
|
]);
|
||||||
|
|
||||||
export interface LikeDetailType {
|
export const LikeMsg = new MessageType("likeMsg", [
|
||||||
txt: string;
|
{ no: 1, name: "times", kind: "scalar", T: ScalarType.INT32 /* int32 */ },
|
||||||
uin: pb.Long;
|
{ no: 2, name: "time", kind: "scalar", T: ScalarType.INT32 /* int32 */ },
|
||||||
nickname: string;
|
{ no: 3, name: "detail", kind: "message", T: () => LikeDetail }
|
||||||
}
|
]);
|
||||||
export interface LikeMsgType {
|
|
||||||
times: number;
|
export const ProfileLikeSubTip = new MessageType("profileLikeSubTip", [
|
||||||
time: number;
|
{ no: 14, name: "msg", kind: "message", T: () => LikeMsg }
|
||||||
detail: LikeDetailType;
|
]);
|
||||||
|
export const ProfileLikeTip = new MessageType("profileLikeTip", [
|
||||||
|
{ no: 1, name: "msgType", kind: "scalar", T: ScalarType.INT32 /* int32 */ },
|
||||||
|
{ no: 2, name: "subType", kind: "scalar", T: ScalarType.INT32 /* int32 */ },
|
||||||
|
{ no: 203, name: "content", kind: "message", T: () => ProfileLikeSubTip }
|
||||||
|
]);
|
||||||
|
export const SysMessageHeader = new MessageType("SysMessageHeader", [
|
||||||
|
{ no: 1, name: "PeerNumber", kind: "scalar", T: ScalarType.UINT32 /* uint32 */ },
|
||||||
|
{ no: 2, name: "PeerString", kind: "scalar", T: ScalarType.STRING /* string */ },
|
||||||
|
{ no: 5, name: "Uin", kind: "scalar", T: ScalarType.UINT32 /* uint32 */ },
|
||||||
|
{ no: 6, name: "Uid", kind: "scalar", T: ScalarType.STRING /* string */, opt: true }
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const SysMessageMsgSpec = new MessageType("SysMessageMsgSpec", [
|
||||||
|
{ no: 1, name: "msgType", kind: "scalar", T: ScalarType.UINT32 /* uint32 */ },
|
||||||
|
{ no: 2, name: "subType", kind: "scalar", T: ScalarType.UINT32 /* uint32 */ },
|
||||||
|
{ no: 3, name: "subSubType", kind: "scalar", T: ScalarType.UINT32 /* uint32 */ },
|
||||||
|
{ no: 5, name: "msgSeq", kind: "scalar", T: ScalarType.UINT32 /* uint32 */ },
|
||||||
|
{ no: 6, name: "time", kind: "scalar", T: ScalarType.UINT32 /* uint32 */ },
|
||||||
|
{ no: 12, name: "msgId", kind: "scalar", T: ScalarType.UINT64 /* uint64 */ },
|
||||||
|
{ no: 13, name: "other", kind: "scalar", T: ScalarType.UINT32 /* uint32 */ }
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const SysMessageBodyWrapper = new MessageType("SysMessageBodyWrapper", [
|
||||||
|
{ no: 2, name: "wrappedBody", kind: "scalar", T: ScalarType.BYTES /* bytes */ }
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const SysMessage = new MessageType("SysMessage", [
|
||||||
|
{ no: 1, name: "header", kind: "message", T: () => SysMessageHeader, repeat: RepeatType.UNPACKED },
|
||||||
|
{ no: 2, name: "msgSpec", kind: "message", T: () => SysMessageMsgSpec, repeat: RepeatType.UNPACKED },
|
||||||
|
{ no: 3, name: "bodyWrapper", kind: "message", T: () => SysMessageBodyWrapper }
|
||||||
|
]);
|
||||||
|
|
||||||
|
export function decodeProfileLikeTip(buffer: Uint8Array): any {
|
||||||
|
const reader = new BinaryReader(buffer);
|
||||||
|
return ProfileLikeTip.internalBinaryRead(reader, reader.len, { readUnknownField: true, readerFactory: () => new BinaryReader(buffer) });
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface profileLikeSubTipType {
|
export function decodeSysMessage(buffer: Uint8Array): any {
|
||||||
msg: LikeMsgType;
|
const reader = new BinaryReader(buffer);
|
||||||
}
|
return SysMessage.internalBinaryRead(reader, reader.len, { readUnknownField: true, readerFactory: () => new BinaryReader(buffer) });
|
||||||
|
}
|
||||||
export interface ProfileLikeTipType {
|
|
||||||
msgType: number;
|
|
||||||
subType: number;
|
|
||||||
content: profileLikeSubTipType;
|
|
||||||
}
|
|
||||||
export interface SysMessageHeaderType {
|
|
||||||
id: string;
|
|
||||||
timestamp: number;
|
|
||||||
sender: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SysMessageMsgSpecType {
|
|
||||||
msgType: number;
|
|
||||||
subType: number;
|
|
||||||
subSubType: number;
|
|
||||||
msgSeq: number;
|
|
||||||
time: number;
|
|
||||||
msgId: pb.Long;
|
|
||||||
other: number;
|
|
||||||
}
|
|
||||||
export interface SysMessageBodyWrapperType {
|
|
||||||
wrappedBody: Uint8Array;
|
|
||||||
}
|
|
||||||
export interface SysMessageType {
|
|
||||||
header: SysMessageHeaderType[];
|
|
||||||
msgSpec: SysMessageMsgSpecType[];
|
|
||||||
bodyWrapper: SysMessageBodyWrapperType;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const SysMessageHeader = new pb.Type("SysMessageHeader")
|
|
||||||
.add(new pb.Field("PeerNumber", 1, "uint32"))
|
|
||||||
.add(new pb.Field("PeerString", 2, "string"))
|
|
||||||
.add(new pb.Field("Uin", 5, "uint32"))
|
|
||||||
.add(new pb.Field("Uid", 6, "string", "optional"));
|
|
||||||
|
|
||||||
export const SysMessageMsgSpec = new pb.Type("SysMessageMsgSpec")
|
|
||||||
.add(new pb.Field("msgType", 1, "uint32"))
|
|
||||||
.add(new pb.Field("subType", 2, "uint32"))
|
|
||||||
.add(new pb.Field("subSubType", 3, "uint32"))
|
|
||||||
.add(new pb.Field("msgSeq", 5, "uint32"))
|
|
||||||
.add(new pb.Field("time", 6, "uint32"))
|
|
||||||
.add(new pb.Field("msgId", 12, "uint64"))
|
|
||||||
.add(new pb.Field("other", 13, "uint32"));
|
|
||||||
|
|
||||||
export const SysMessageBodyWrapper = new pb.Type("SysMessageBodyWrapper")
|
|
||||||
.add(new pb.Field("wrappedBody", 2, "bytes"));
|
|
||||||
|
|
||||||
export const SysMessage = new pb.Type("SysMessage")
|
|
||||||
.add(SysMessageHeader)
|
|
||||||
.add(SysMessageMsgSpec)
|
|
||||||
.add(SysMessageBodyWrapper)
|
|
||||||
.add(new pb.Field("header", 1, "SysMessageHeader", "repeated"))
|
|
||||||
.add(new pb.Field("msgSpec", 2, "SysMessageMsgSpec", "repeated"))
|
|
||||||
.add(new pb.Field("bodyWrapper", 3, "SysMessageBodyWrapper"));
|
|
||||||
|
|
||||||
export const likeDetail = new pb.Type("likeDetail")
|
|
||||||
.add(new pb.Field("txt", 1, "string"))
|
|
||||||
.add(new pb.Field("uin", 3, "int64"))
|
|
||||||
.add(new pb.Field("nickname", 5, "string"));
|
|
||||||
|
|
||||||
export const likeMsg = new pb.Type("likeMsg")
|
|
||||||
.add(likeDetail)
|
|
||||||
.add(new pb.Field("times", 1, "int32"))
|
|
||||||
.add(new pb.Field("time", 2, "int32"))
|
|
||||||
.add(new pb.Field("detail", 3, "likeDetail"));
|
|
||||||
|
|
||||||
export const profileLikeSubTip = new pb.Type("profileLikeSubTip")
|
|
||||||
.add(likeMsg)
|
|
||||||
.add(new pb.Field("msg", 14, "likeMsg"))
|
|
||||||
|
|
||||||
export const profileLikeTip = new pb.Type("profileLikeTip")
|
|
||||||
.add(profileLikeSubTip)
|
|
||||||
.add(new pb.Field("msgType", 1, "int32"))
|
|
||||||
.add(new pb.Field("subType", 2, "int32"))
|
|
||||||
.add(new pb.Field("content", 203, "profileLikeSubTip"));
|
|
@@ -240,7 +240,12 @@ export interface NodeIKernelGroupService {
|
|||||||
|
|
||||||
getGroupRecommendContactArkJson(groupCode: string): unknown;
|
getGroupRecommendContactArkJson(groupCode: string): unknown;
|
||||||
|
|
||||||
getJoinGroupLink(groupCode: string): unknown;
|
getJoinGroupLink(param: {
|
||||||
|
groupCode: string,
|
||||||
|
srcId: number,//73
|
||||||
|
needShortUrl: boolean,//true
|
||||||
|
additionalParam: string//''
|
||||||
|
}): Promise<GeneralCallResult & { url?: string }>;
|
||||||
|
|
||||||
modifyGroupExtInfo(groupCode: string, arg: unknown): void;
|
modifyGroupExtInfo(groupCode: string, arg: unknown): void;
|
||||||
|
|
||||||
|
BIN
src/native/external/MoeHoo.win32.node
vendored
Normal file
BIN
src/native/external/MoeHoo.win32.node
vendored
Normal file
Binary file not shown.
40
src/native/index.ts
Normal file
40
src/native/index.ts
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import { constants } from "node:os";
|
||||||
|
import path from "path";
|
||||||
|
import { dlopen } from "process";
|
||||||
|
import fs from "fs";
|
||||||
|
export class Native {
|
||||||
|
platform: string;
|
||||||
|
supportedPlatforms = ['win32'];
|
||||||
|
MoeHooExport: any = { exports: {} };
|
||||||
|
recallHookEnabled: boolean = false;
|
||||||
|
inited = true;
|
||||||
|
constructor(nodePath: string, platform: string = process.platform) {
|
||||||
|
this.platform = platform;
|
||||||
|
try {
|
||||||
|
if (!this.supportedPlatforms.includes(this.platform)) {
|
||||||
|
throw new Error(`Platform ${this.platform} is not supported`);
|
||||||
|
}
|
||||||
|
let nativeNode = path.join(nodePath, './native/MoeHoo.win32.node');
|
||||||
|
if (fs.existsSync(nativeNode)) {
|
||||||
|
dlopen(this.MoeHooExport, nativeNode, constants.dlopen.RTLD_LAZY);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.inited = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
isSetReCallEnabled(): boolean {
|
||||||
|
return this.recallHookEnabled && this.inited;
|
||||||
|
}
|
||||||
|
registerRecallCallback(callback: (hex: string) => any): void {
|
||||||
|
try {
|
||||||
|
if (!this.inited) throw new Error('Native Not Init');
|
||||||
|
if (this.MoeHooExport.exports?.registMsgPush) {
|
||||||
|
this.MoeHooExport.exports.registMsgPush(callback);
|
||||||
|
this.recallHookEnabled = true;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.recallHookEnabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,9 +1,16 @@
|
|||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import { OB11ForwardMessage } from '@/onebot';
|
import { OB11Message, OB11MessageData, OB11MessageDataType, OB11MessageForward, OB11MessageNode as OriginalOB11MessageNode } from '@/onebot';
|
||||||
import { ActionName } from '../types';
|
import { ActionName } from '../types';
|
||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
import { MessageUnique } from '@/common/message-unique';
|
import { MessageUnique } from '@/common/message-unique';
|
||||||
|
|
||||||
|
type OB11MessageNode = OriginalOB11MessageNode & {
|
||||||
|
data: {
|
||||||
|
content?: Array<OB11MessageData>;
|
||||||
|
message: Array<OB11MessageData>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const SchemaData = {
|
const SchemaData = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
@@ -18,36 +25,69 @@ export class GoCQHTTPGetForwardMsgAction extends BaseAction<Payload, any> {
|
|||||||
actionName = ActionName.GoCQHTTP_GetForwardMsg;
|
actionName = ActionName.GoCQHTTP_GetForwardMsg;
|
||||||
payloadSchema = SchemaData;
|
payloadSchema = SchemaData;
|
||||||
|
|
||||||
|
private createTemplateNode(message: OB11Message): OB11MessageNode {
|
||||||
|
return {
|
||||||
|
type: OB11MessageDataType.node,
|
||||||
|
data: {
|
||||||
|
user_id: message.user_id,
|
||||||
|
nickname: message.sender.nickname,
|
||||||
|
message: [],
|
||||||
|
content: []
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async parseForward(messages: OB11Message[]): Promise<OB11MessageNode[]> {
|
||||||
|
const retMsg: OB11MessageNode[] = [];
|
||||||
|
|
||||||
|
for (const message of messages) {
|
||||||
|
const templateNode = this.createTemplateNode(message);
|
||||||
|
|
||||||
|
for (const msgdata of message.message) {
|
||||||
|
if ((msgdata as OB11MessageData).type === OB11MessageDataType.forward) {
|
||||||
|
const newNode = this.createTemplateNode(message);
|
||||||
|
newNode.data.message = await this.parseForward((msgdata as OB11MessageForward).data.content);
|
||||||
|
|
||||||
|
templateNode.data.message.push(newNode);
|
||||||
|
} else {
|
||||||
|
templateNode.data.message.push(msgdata as OB11MessageData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
retMsg.push(templateNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retMsg;
|
||||||
|
}
|
||||||
|
|
||||||
async _handle(payload: Payload): Promise<any> {
|
async _handle(payload: Payload): Promise<any> {
|
||||||
const msgId = payload.message_id || payload.id;
|
const msgId = payload.message_id || payload.id;
|
||||||
if (!msgId) {
|
if (!msgId) {
|
||||||
throw Error('message_id is required');
|
throw new Error('message_id is required');
|
||||||
}
|
}
|
||||||
|
|
||||||
const rootMsgId = MessageUnique.getShortIdByMsgId(msgId);
|
const rootMsgId = MessageUnique.getShortIdByMsgId(msgId);
|
||||||
const rootMsg = MessageUnique.getMsgIdAndPeerByShortId(rootMsgId || parseInt(msgId));
|
const rootMsg = MessageUnique.getMsgIdAndPeerByShortId(rootMsgId || parseInt(msgId));
|
||||||
if (!rootMsg) {
|
if (!rootMsg) {
|
||||||
throw Error('msg not found');
|
throw new Error('msg not found');
|
||||||
}
|
}
|
||||||
const data = await this.core.apis.MsgApi.getMultiMsg(rootMsg.Peer, rootMsg.MsgId, rootMsg.MsgId);
|
const data = await this.core.apis.MsgApi.getMsgsByMsgId(rootMsg.Peer, [rootMsg.MsgId]);
|
||||||
|
|
||||||
if (!data || data.result !== 0) {
|
if (!data || data.result !== 0) {
|
||||||
throw Error('找不到相关的聊天记录' + data?.errMsg);
|
throw new Error('找不到相关的聊天记录' + data?.errMsg);
|
||||||
}
|
}
|
||||||
const msgList = data.msgList;
|
|
||||||
const messages = (await Promise.all(msgList.map(async msg => {
|
const singleMsg = data.msgList[0];
|
||||||
const resMsg = await this.obContext.apis.MsgApi
|
const resMsg = await this.obContext.apis.MsgApi.parseMessage(singleMsg, 'array');//强制array 以便处理
|
||||||
.parseMessage(msg);
|
if (!resMsg) {
|
||||||
if (!resMsg) return;
|
throw new Error('找不到相关的聊天记录');
|
||||||
resMsg.message_id = MessageUnique.createUniqueMsgId({
|
}
|
||||||
guildId: '',
|
//if (this.obContext.configLoader.configData.messagePostFormat === 'array') {
|
||||||
chatType: msg.chatType,
|
//提取
|
||||||
peerUid: msg.peerUid,
|
let realmsg = ((await this.parseForward([resMsg]))[0].data.message as OB11MessageNode[])[0].data.message;
|
||||||
}, msg.msgId)!;
|
//里面都是offline消息 id都是0 没得说话
|
||||||
return resMsg;
|
return { message: realmsg };
|
||||||
}))).filter(msg => !!msg);
|
//}
|
||||||
messages.map(msg => {
|
|
||||||
(<OB11ForwardMessage>msg).content = msg.message;
|
// return { message: resMsg };
|
||||||
delete (<any>msg).message;
|
|
||||||
});
|
|
||||||
return { messages };
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -3,6 +3,7 @@ import BaseAction from '../BaseAction';
|
|||||||
import { ActionName } from '../types';
|
import { ActionName } from '../types';
|
||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
import { MessageUnique } from '@/common/message-unique';
|
import { MessageUnique } from '@/common/message-unique';
|
||||||
|
import { RawMessage } from '@/core';
|
||||||
|
|
||||||
|
|
||||||
export type ReturnDataType = OB11Message
|
export type ReturnDataType = OB11Message
|
||||||
@@ -32,13 +33,17 @@ class GetMsg extends BaseAction<Payload, OB11Message> {
|
|||||||
throw new Error('消息不存在');
|
throw new Error('消息不存在');
|
||||||
}
|
}
|
||||||
const peer = { guildId: '', peerUid: msgIdWithPeer?.Peer.peerUid, chatType: msgIdWithPeer.Peer.chatType };
|
const peer = { guildId: '', peerUid: msgIdWithPeer?.Peer.peerUid, chatType: msgIdWithPeer.Peer.chatType };
|
||||||
const msg = await this.core.apis.MsgApi.getMsgsByMsgId(
|
let orimsg = this.obContext.recallMsgCache.get(msgIdWithPeer.MsgId);
|
||||||
peer,
|
let msg: RawMessage;
|
||||||
[msgIdWithPeer?.MsgId || payload.message_id.toString()]);
|
if (orimsg) {
|
||||||
const retMsg = await this.obContext.apis.MsgApi.parseMessage(msg.msgList[0]);
|
msg = orimsg;
|
||||||
|
} else {
|
||||||
|
msg = (await this.core.apis.MsgApi.getMsgsByMsgId(peer, [msgIdWithPeer?.MsgId || payload.message_id.toString()])).msgList[0];
|
||||||
|
}
|
||||||
|
const retMsg = await this.obContext.apis.MsgApi.parseMessage(msg);
|
||||||
if (!retMsg) throw Error('消息为空');
|
if (!retMsg) throw Error('消息为空');
|
||||||
try {
|
try {
|
||||||
retMsg.message_id = MessageUnique.createUniqueMsgId(peer, msg.msgList[0].msgId)!;
|
retMsg.message_id = MessageUnique.createUniqueMsgId(peer, msg.msgId)!;
|
||||||
retMsg.message_seq = retMsg.message_id;
|
retMsg.message_seq = retMsg.message_id;
|
||||||
retMsg.real_id = retMsg.message_id;
|
retMsg.real_id = retMsg.message_id;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@@ -15,14 +15,14 @@ export class OneBotFriendApi {
|
|||||||
//使用前预先判断 busiId 1061
|
//使用前预先判断 busiId 1061
|
||||||
async parsePrivatePokeEvent(grayTipElement: GrayTipElement) {
|
async parsePrivatePokeEvent(grayTipElement: GrayTipElement) {
|
||||||
const json = JSON.parse(grayTipElement.jsonGrayTipElement.jsonStr);
|
const json = JSON.parse(grayTipElement.jsonGrayTipElement.jsonStr);
|
||||||
let pokedetail: any[] = json.items;
|
let pokedetail: Array<{ uid: string }> = json.items;
|
||||||
//筛选item带有uid的元素
|
//筛选item带有uid的元素
|
||||||
pokedetail = pokedetail.filter(item => item.uid);
|
pokedetail = pokedetail.filter(item => item.uid);
|
||||||
if (pokedetail.length == 2) {
|
if (pokedetail.length == 2) {
|
||||||
return new OB11FriendPokeEvent(
|
return new OB11FriendPokeEvent(
|
||||||
this.core,
|
this.core,
|
||||||
parseInt((await this.core.apis.UserApi.getUinByUidV2(pokedetail[0].uid))!),
|
parseInt((await this.core.apis.UserApi.getUinByUidV2(pokedetail[0].uid))),
|
||||||
parseInt((await this.core.apis.UserApi.getUinByUidV2(pokedetail[1].uid))!),
|
parseInt((await this.core.apis.UserApi.getUinByUidV2(pokedetail[1].uid))),
|
||||||
pokedetail,
|
pokedetail,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -96,7 +96,6 @@ export class OneBotGroupApi {
|
|||||||
if (GroupIncreaseEvent) return GroupIncreaseEvent;
|
if (GroupIncreaseEvent) return GroupIncreaseEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
//代码歧义 GrayTipElementSubType.MEMBER_NEW_TITLE
|
|
||||||
else if (element.grayTipElement.subElementType == NTGrayTipElementSubTypeV2.GRAYTIP_ELEMENT_SUBTYPE_JSON) {
|
else if (element.grayTipElement.subElementType == NTGrayTipElementSubTypeV2.GRAYTIP_ELEMENT_SUBTYPE_JSON) {
|
||||||
const json = JSON.parse(element.grayTipElement.jsonGrayTipElement.jsonStr);
|
const json = JSON.parse(element.grayTipElement.jsonGrayTipElement.jsonStr);
|
||||||
if (element.grayTipElement.jsonGrayTipElement.busiId == 1061) {
|
if (element.grayTipElement.jsonGrayTipElement.busiId == 1061) {
|
||||||
@@ -139,7 +138,6 @@ export class OneBotGroupApi {
|
|||||||
// 获取MsgSeq+Peer可获取具体消息
|
// 获取MsgSeq+Peer可获取具体消息
|
||||||
}
|
}
|
||||||
if (element.grayTipElement.jsonGrayTipElement.busiId == 2407) {
|
if (element.grayTipElement.jsonGrayTipElement.busiId == 2407) {
|
||||||
//下面得改 上面也是错的grayTipElement.subElementType == GrayTipElementSubType.MEMBER_NEW_TITLE
|
|
||||||
const type = json.items[json.items.length - 1]?.txt;
|
const type = json.items[json.items.length - 1]?.txt;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "头衔": {
|
case "头衔": {
|
||||||
@@ -207,7 +205,6 @@ export class OneBotGroupApi {
|
|||||||
while ((match = regex.exec(xmlElement.content)) !== null) {
|
while ((match = regex.exec(xmlElement.content)) !== null) {
|
||||||
matches.push(match[1]);
|
matches.push(match[1]);
|
||||||
}
|
}
|
||||||
// log("新人进群匹配到的QQ号", matches)
|
|
||||||
if (matches.length === 2) {
|
if (matches.length === 2) {
|
||||||
const [inviter, invitee] = matches;
|
const [inviter, invitee] = matches;
|
||||||
return new OB11GroupIncreaseEvent(
|
return new OB11GroupIncreaseEvent(
|
||||||
|
@@ -34,7 +34,7 @@ import { RequestUtil } from '@/common/request';
|
|||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
import fsPromise from 'node:fs/promises';
|
import fsPromise from 'node:fs/promises';
|
||||||
import { OB11FriendAddNoticeEvent } from '@/onebot/event/notice/OB11FriendAddNoticeEvent';
|
import { OB11FriendAddNoticeEvent } from '@/onebot/event/notice/OB11FriendAddNoticeEvent';
|
||||||
import { SysMessage, SysMessageType } from '@/core/proto/ProfileLike';
|
import { decodeSysMessage } from '@/core/proto/ProfileLike';
|
||||||
|
|
||||||
type RawToOb11Converters = {
|
type RawToOb11Converters = {
|
||||||
[Key in keyof MessageElement as Key extends `${string}Element` ? Key : never]: (
|
[Key in keyof MessageElement as Key extends `${string}Element` ? Key : never]: (
|
||||||
@@ -212,7 +212,7 @@ export class OneBotMsgApi {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (records.peerUin === '284840486') {
|
if (records.peerUin === '284840486' || records.peerUin === '1094950020') {
|
||||||
return createReplyData(records.msgId);
|
return createReplyData(records.msgId);
|
||||||
}
|
}
|
||||||
const replyMsg = (await this.core.apis.MsgApi.queryMsgsWithFilterExWithSeqV2(peer, element.replayMsgSeq, element.replyMsgTime, [element.senderUidStr]))
|
const replyMsg = (await this.core.apis.MsgApi.queryMsgsWithFilterExWithSeqV2(peer, element.replayMsgSeq, element.replyMsgTime, [element.senderUidStr]))
|
||||||
@@ -234,19 +234,29 @@ export class OneBotMsgApi {
|
|||||||
//读取视频链接并兜底
|
//读取视频链接并兜底
|
||||||
let videoUrlWrappers: Awaited<ReturnType<typeof this.core.apis.FileApi.getVideoUrl>> | undefined;
|
let videoUrlWrappers: Awaited<ReturnType<typeof this.core.apis.FileApi.getVideoUrl>> | undefined;
|
||||||
|
|
||||||
if (msg.peerUin === '284840486') {
|
if (msg.peerUin === '284840486' || msg.peerUin === '1094950020') {
|
||||||
//TODO: 合并消息内部 应该进行特殊处理 可能需要重写peer 待测试与研究 Mlikiowa Tagged
|
try {
|
||||||
}
|
videoUrlWrappers = await this.core.apis.FileApi.getVideoUrl({
|
||||||
try {
|
chatType: msg.chatType,
|
||||||
videoUrlWrappers = await this.core.apis.FileApi.getVideoUrl({
|
peerUid: msg.peerUid,
|
||||||
chatType: msg.chatType,
|
guildId: '0',
|
||||||
peerUid: msg.peerUid,
|
}, msg.parentMsgIdList[0] ?? msg.msgId, elementWrapper.elementId);
|
||||||
guildId: '0',
|
} catch (error) {
|
||||||
}, msg.msgId, elementWrapper.elementId);
|
this.core.context.logger.logWarn('合并获取视频 URL 失败');
|
||||||
} catch (error) {
|
}
|
||||||
this.core.context.logger.logWarn('获取视频 URL 失败');
|
} else {
|
||||||
|
try {
|
||||||
|
videoUrlWrappers = await this.core.apis.FileApi.getVideoUrl({
|
||||||
|
chatType: msg.chatType,
|
||||||
|
peerUid: msg.peerUid,
|
||||||
|
guildId: '0',
|
||||||
|
}, msg.msgId, elementWrapper.elementId);
|
||||||
|
} catch (error) {
|
||||||
|
this.core.context.logger.logWarn('获取视频 URL 失败');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//读取在线URL
|
//读取在线URL
|
||||||
let videoDownUrl: string | undefined;
|
let videoDownUrl: string | undefined;
|
||||||
|
|
||||||
@@ -447,7 +457,6 @@ export class OneBotMsgApi {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
[OB11MessageDataType.mface]: async ({
|
[OB11MessageDataType.mface]: async ({
|
||||||
data: {
|
data: {
|
||||||
emoji_package_id, emoji_id, key, summary,
|
emoji_package_id, emoji_id, key, summary,
|
||||||
@@ -510,13 +519,12 @@ export class OneBotMsgApi {
|
|||||||
faceElement: {
|
faceElement: {
|
||||||
faceIndex: FaceIndex.dice,
|
faceIndex: FaceIndex.dice,
|
||||||
faceType: FaceType.dice,
|
faceType: FaceType.dice,
|
||||||
'faceText': '[骰子]',
|
faceText: '[骰子]',
|
||||||
'packId': '1',
|
packId: '1',
|
||||||
'stickerId': '33',
|
stickerId: '33',
|
||||||
'sourceType': 1,
|
sourceType: 1,
|
||||||
'stickerType': 2,
|
stickerType: 2,
|
||||||
// resultId: resultId.toString(),
|
surpriseId: '',
|
||||||
'surpriseId': '',
|
|
||||||
// "randomType": 1,
|
// "randomType": 1,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -525,15 +533,14 @@ export class OneBotMsgApi {
|
|||||||
elementType: ElementType.FACE,
|
elementType: ElementType.FACE,
|
||||||
elementId: '',
|
elementId: '',
|
||||||
faceElement: {
|
faceElement: {
|
||||||
'faceIndex': FaceIndex.RPS,
|
faceIndex: FaceIndex.RPS,
|
||||||
'faceText': '[包剪锤]',
|
faceText: '[包剪锤]',
|
||||||
'faceType': 3,
|
faceType: 3,
|
||||||
'packId': '1',
|
packId: '1',
|
||||||
'stickerId': '34',
|
stickerId: '34',
|
||||||
'sourceType': 1,
|
sourceType: 1,
|
||||||
'stickerType': 2,
|
stickerType: 2,
|
||||||
// 'resultId': resultId.toString(),
|
surpriseId: '',
|
||||||
'surpriseId': '',
|
|
||||||
// "randomType": 1,
|
// "randomType": 1,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -834,7 +841,7 @@ export class OneBotMsgApi {
|
|||||||
return { path, fileName: inputdata.name ?? fileName };
|
return { path, fileName: inputdata.name ?? fileName };
|
||||||
}
|
}
|
||||||
async parseSysMessage(msg: number[]) {
|
async parseSysMessage(msg: number[]) {
|
||||||
const sysMsg = SysMessage.decode(Uint8Array.from(msg)) as unknown as SysMessageType;
|
const sysMsg = decodeSysMessage(Uint8Array.from(msg));
|
||||||
if (sysMsg.msgSpec.length === 0) {
|
if (sysMsg.msgSpec.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { NapCatCore } from '@/core';
|
import { NapCatCore } from '@/core';
|
||||||
import { profileLikeTip, ProfileLikeTipType } from '@/core/proto/ProfileLike';
|
import { decodeProfileLikeTip } from '@/core/proto/ProfileLike';
|
||||||
|
|
||||||
import { NapCatOneBot11Adapter } from '@/onebot';
|
import { NapCatOneBot11Adapter } from '@/onebot';
|
||||||
import { OB11ProfileLikeEvent } from '../event/notice/OB11ProfileLikeEvent';
|
import { OB11ProfileLikeEvent } from '../event/notice/OB11ProfileLikeEvent';
|
||||||
@@ -13,7 +13,7 @@ export class OneBotUserApi {
|
|||||||
this.core = core;
|
this.core = core;
|
||||||
}
|
}
|
||||||
async parseLikeEvent(wrappedBody: Uint8Array): Promise<OB11ProfileLikeEvent | undefined> {
|
async parseLikeEvent(wrappedBody: Uint8Array): Promise<OB11ProfileLikeEvent | undefined> {
|
||||||
const likeTip = profileLikeTip.decode(Uint8Array.from(wrappedBody)) as unknown as ProfileLikeTipType;
|
const likeTip = decodeProfileLikeTip(Uint8Array.from(wrappedBody));
|
||||||
if (likeTip?.msgType !== 0 || likeTip?.subType !== 203) return;
|
if (likeTip?.msgType !== 0 || likeTip?.subType !== 203) return;
|
||||||
this.core.context.logger.logDebug("收到点赞通知消息");
|
this.core.context.logger.logDebug("收到点赞通知消息");
|
||||||
const likeMsg = likeTip.content.msg;
|
const likeMsg = likeTip.content.msg;
|
||||||
|
@@ -10,6 +10,7 @@ import {
|
|||||||
NodeIKernelBuddyListener,
|
NodeIKernelBuddyListener,
|
||||||
NodeIKernelGroupListener,
|
NodeIKernelGroupListener,
|
||||||
NodeIKernelMsgListener,
|
NodeIKernelMsgListener,
|
||||||
|
Peer,
|
||||||
RawMessage,
|
RawMessage,
|
||||||
SendStatusType,
|
SendStatusType,
|
||||||
} from '@/core';
|
} from '@/core';
|
||||||
@@ -43,8 +44,9 @@ import { OB11FriendRecallNoticeEvent } from '@/onebot/event/notice/OB11FriendRec
|
|||||||
import { OB11GroupRecallNoticeEvent } from '@/onebot/event/notice/OB11GroupRecallNoticeEvent';
|
import { OB11GroupRecallNoticeEvent } from '@/onebot/event/notice/OB11GroupRecallNoticeEvent';
|
||||||
import { LRUCache } from '@/common/lru-cache';
|
import { LRUCache } from '@/common/lru-cache';
|
||||||
import { NodeIKernelRecentContactListener } from '@/core/listeners/NodeIKernelRecentContactListener';
|
import { NodeIKernelRecentContactListener } from '@/core/listeners/NodeIKernelRecentContactListener';
|
||||||
import { OB11ProfileLikeEvent } from './event/notice/OB11ProfileLikeEvent';
|
import { Native } from '@/native';
|
||||||
import { profileLikeTip, ProfileLikeTipType, SysMessage, SysMessageType } from '@/core/proto/ProfileLike';
|
import { decodeMessage, decodeRecallGroup, Message, RecallGroup } from '@/core/proto/Message';
|
||||||
|
|
||||||
//OneBot实现类
|
//OneBot实现类
|
||||||
export class NapCatOneBot11Adapter {
|
export class NapCatOneBot11Adapter {
|
||||||
readonly core: NapCatCore;
|
readonly core: NapCatCore;
|
||||||
@@ -54,8 +56,9 @@ export class NapCatOneBot11Adapter {
|
|||||||
apis: StableOneBotApiWrapper;
|
apis: StableOneBotApiWrapper;
|
||||||
networkManager: OB11NetworkManager;
|
networkManager: OB11NetworkManager;
|
||||||
actions: ActionMap;
|
actions: ActionMap;
|
||||||
|
nativeCore: Native | undefined;
|
||||||
private bootTime = Date.now() / 1000;
|
private bootTime = Date.now() / 1000;
|
||||||
|
recallMsgCache = new LRUCache<string, RawMessage>(100);
|
||||||
|
|
||||||
constructor(core: NapCatCore, context: InstanceContext, pathWrapper: NapCatPathWrapper) {
|
constructor(core: NapCatCore, context: InstanceContext, pathWrapper: NapCatPathWrapper) {
|
||||||
this.core = core;
|
this.core = core;
|
||||||
@@ -70,10 +73,41 @@ export class NapCatOneBot11Adapter {
|
|||||||
};
|
};
|
||||||
this.actions = createActionMap(this, core);
|
this.actions = createActionMap(this, core);
|
||||||
this.networkManager = new OB11NetworkManager();
|
this.networkManager = new OB11NetworkManager();
|
||||||
|
this.registerNative(core, context).then().catch();
|
||||||
this.InitOneBot()
|
this.InitOneBot()
|
||||||
.catch(e => this.context.logger.logError.bind(this.context.logger)('初始化OneBot失败', e));
|
.catch(e => this.context.logger.logError.bind(this.context.logger)('初始化OneBot失败', e));
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
|
async registerNative(core: NapCatCore, context: InstanceContext) {
|
||||||
|
try {
|
||||||
|
this.nativeCore = new Native(context.pathWrapper.binaryPath);
|
||||||
|
if (!this.nativeCore.inited) throw new Error('Native Not Init');
|
||||||
|
this.nativeCore.registerRecallCallback(async (hex: string) => {
|
||||||
|
try {
|
||||||
|
let data = decodeMessage(Buffer.from(hex, 'hex')) as any;
|
||||||
|
//data.MsgHead.BodyInner.MsgType SubType
|
||||||
|
let bodyInner = data.msgHead?.bodyInner;
|
||||||
|
//context.logger.log("[appNative] Parse MsgType:" + bodyInner.msgType + " / SubType:" + bodyInner.subType);
|
||||||
|
if (bodyInner && bodyInner.msgType == 732 && bodyInner.subType == 17) {
|
||||||
|
let RecallData = Buffer.from(data.msgHead.noifyData.innerData);
|
||||||
|
//跳过 4字节 群号 + 不知道的1字节 +2字节 长度
|
||||||
|
let uid = RecallData.readUint32BE();
|
||||||
|
const buffer = Buffer.from(RecallData.toString('hex').slice(14), 'hex');
|
||||||
|
let seq: number = decodeRecallGroup(buffer).recallDetails.subDetail.msgSeq;
|
||||||
|
let peer: Peer = { chatType: ChatType.KCHATTYPEGROUP, peerUid: uid.toString() };
|
||||||
|
context.logger.log("[Native] 群消息撤回 Peer: " + uid.toString() + " / MsgSeq:" + seq);
|
||||||
|
let msgs = await core.apis.MsgApi.queryMsgsWithFilterExWithSeq(peer, seq.toString());
|
||||||
|
this.recallMsgCache.put(msgs.msgList[0].msgId, msgs.msgList[0]);
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
context.logger.logWarn("[Native] Error:", (error as Error).message, ' HEX:', hex);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
context.logger.logWarn("[Native] Error:", (error as Error).message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
async InitOneBot() {
|
async InitOneBot() {
|
||||||
const selfInfo = this.core.selfInfo;
|
const selfInfo = this.core.selfInfo;
|
||||||
const ob11Config = this.configLoader.configData;
|
const ob11Config = this.configLoader.configData;
|
||||||
@@ -523,7 +557,6 @@ export class NapCatOneBot11Adapter {
|
|||||||
}
|
}
|
||||||
}).catch(e => this.context.logger.logError.bind(this.context.logger)('constructPrivateEvent error: ', e));
|
}).catch(e => this.context.logger.logError.bind(this.context.logger)('constructPrivateEvent error: ', e));
|
||||||
}
|
}
|
||||||
|
|
||||||
private async emitRecallMsg(msgList: RawMessage[], cache: LRUCache<string, boolean>) {
|
private async emitRecallMsg(msgList: RawMessage[], cache: LRUCache<string, boolean>) {
|
||||||
for (const message of msgList) {
|
for (const message of msgList) {
|
||||||
// log("message update", message.sendStatus, message.msgId, message.msgSeq)
|
// log("message update", message.sendStatus, message.msgId, message.msgSeq)
|
||||||
@@ -555,7 +588,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
parseInt(message.peerUin),
|
parseInt(message.peerUin),
|
||||||
parseInt(message.senderUin),
|
parseInt(message.senderUin),
|
||||||
parseInt(operatorId),
|
parseInt(operatorId),
|
||||||
oriMessageId,
|
oriMessageId
|
||||||
);
|
);
|
||||||
this.networkManager.emitEvent(groupRecallEvent)
|
this.networkManager.emitEvent(groupRecallEvent)
|
||||||
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理群消息撤回失败', e));
|
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理群消息撤回失败', e));
|
||||||
|
@@ -54,7 +54,6 @@ export async function NCoreInitShell() {
|
|||||||
const loginService = wrapper.NodeIKernelLoginService.get();
|
const loginService = wrapper.NodeIKernelLoginService.get();
|
||||||
|
|
||||||
const session = wrapper.NodeIQQNTWrapperSession.create();
|
const session = wrapper.NodeIQQNTWrapperSession.create();
|
||||||
|
|
||||||
// from get dataPath
|
// from get dataPath
|
||||||
const [dataPath, dataPathGlobal] = (() => {
|
const [dataPath, dataPathGlobal] = (() => {
|
||||||
if (os.platform() === 'darwin') {
|
if (os.platform() === 'darwin') {
|
||||||
@@ -72,15 +71,15 @@ export async function NCoreInitShell() {
|
|||||||
})();
|
})();
|
||||||
let systemPlatform = PlatformType.KWINDOWS;
|
let systemPlatform = PlatformType.KWINDOWS;
|
||||||
switch (os.platform()) {
|
switch (os.platform()) {
|
||||||
case 'win32':
|
case 'win32':
|
||||||
systemPlatform = PlatformType.KWINDOWS;
|
systemPlatform = PlatformType.KWINDOWS;
|
||||||
break;
|
break;
|
||||||
case 'darwin':
|
case 'darwin':
|
||||||
systemPlatform = PlatformType.KMAC;
|
systemPlatform = PlatformType.KMAC;
|
||||||
break;
|
break;
|
||||||
case 'linux':
|
case 'linux':
|
||||||
systemPlatform = PlatformType.KLINUX;
|
systemPlatform = PlatformType.KLINUX;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!basicInfoWrapper.QQVersionAppid || !basicInfoWrapper.QQVersionQua) throw new Error('QQVersionAppid or QQVersionQua is not defined');
|
if (!basicInfoWrapper.QQVersionAppid || !basicInfoWrapper.QQVersionQua) throw new Error('QQVersionAppid or QQVersionQua is not defined');
|
||||||
// from initConfig
|
// from initConfig
|
||||||
@@ -119,7 +118,7 @@ export async function NCoreInitShell() {
|
|||||||
quickLoginUin = '';
|
quickLoginUin = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let dataTimestape = new Date().getTime().toString();
|
const dataTimestape = new Date().getTime().toString();
|
||||||
o3Service.reportAmgomWeather('login', 'a1', [dataTimestape, '0', '0']);
|
o3Service.reportAmgomWeather('login', 'a1', [dataTimestape, '0', '0']);
|
||||||
const selfInfo = await new Promise<SelfInfo>((resolve) => {
|
const selfInfo = await new Promise<SelfInfo>((resolve) => {
|
||||||
const loginListener = new NodeIKernelLoginListener();
|
const loginListener = new NodeIKernelLoginListener();
|
||||||
@@ -234,13 +233,13 @@ export async function NCoreInitShell() {
|
|||||||
logger.log(`可用于快速登录的 QQ:\n${historyLoginList
|
logger.log(`可用于快速登录的 QQ:\n${historyLoginList
|
||||||
.map((u, index) => `${index + 1}. ${u.uin} ${u.nickName}`)
|
.map((u, index) => `${index + 1}. ${u.uin} ${u.nickName}`)
|
||||||
.join('\n')
|
.join('\n')
|
||||||
}`);
|
}`);
|
||||||
}
|
}
|
||||||
loginService.getQRCodePicture();
|
loginService.getQRCodePicture();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// BEFORE LOGGING IN
|
// BEFORE LOGGING IN
|
||||||
let amgomDataPiece = 'eb1fd6ac257461580dc7438eb099f23aae04ca679f4d88f53072dc56e3bb1129';
|
const amgomDataPiece = 'eb1fd6ac257461580dc7438eb099f23aae04ca679f4d88f53072dc56e3bb1129';
|
||||||
o3Service.setAmgomDataPiece(basicInfoWrapper.QQVersionAppid, new Uint8Array(Buffer.from(amgomDataPiece, 'hex')));
|
o3Service.setAmgomDataPiece(basicInfoWrapper.QQVersionAppid, new Uint8Array(Buffer.from(amgomDataPiece, 'hex')));
|
||||||
// AFTER LOGGING IN
|
// AFTER LOGGING IN
|
||||||
//99b15bdb4c984fc69d5aa1feb9aa16xx --> 99b15bdb-4c98-4fc6-9d5a-a1feb9aa16xx
|
//99b15bdb4c984fc69d5aa1feb9aa16xx --> 99b15bdb-4c98-4fc6-9d5a-a1feb9aa16xx
|
||||||
|
@@ -30,7 +30,7 @@ async function onSettingWindowCreated(view: Element) {
|
|||||||
SettingItem(
|
SettingItem(
|
||||||
'<span id="napcat-update-title">Napcat</span>',
|
'<span id="napcat-update-title">Napcat</span>',
|
||||||
undefined,
|
undefined,
|
||||||
SettingButton('V2.6.13', 'napcat-update-button', 'secondary'),
|
SettingButton('V2.6.20', 'napcat-update-button', 'secondary'),
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
SettingList([
|
SettingList([
|
||||||
|
@@ -164,7 +164,7 @@ async function onSettingWindowCreated(view) {
|
|||||||
SettingItem(
|
SettingItem(
|
||||||
'<span id="napcat-update-title">Napcat</span>',
|
'<span id="napcat-update-title">Napcat</span>',
|
||||||
void 0,
|
void 0,
|
||||||
SettingButton("V2.6.13", "napcat-update-button", "secondary")
|
SettingButton("V2.6.20", "napcat-update-button", "secondary")
|
||||||
)
|
)
|
||||||
]),
|
]),
|
||||||
SettingList([
|
SettingList([
|
||||||
|
@@ -41,6 +41,7 @@ const FrameworkBaseConfigPlugin: PluginOption[] = [
|
|||||||
const ShellBaseConfigPlugin: PluginOption[] = [
|
const ShellBaseConfigPlugin: PluginOption[] = [
|
||||||
cp({
|
cp({
|
||||||
targets: [
|
targets: [
|
||||||
|
{ src: './src/native/external', dest: 'dist/native', flatten: false },
|
||||||
{ src: './static/', dest: 'dist/static/', flatten: false },
|
{ src: './static/', dest: 'dist/static/', flatten: false },
|
||||||
{ src: './src/core/external/napcat.json', dest: 'dist/config/' },
|
{ src: './src/core/external/napcat.json', dest: 'dist/config/' },
|
||||||
{ src: './src/onebot/config/onebot11.json', dest: 'dist/config/' },
|
{ src: './src/onebot/config/onebot11.json', dest: 'dist/config/' },
|
||||||
|
Reference in New Issue
Block a user