mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-07-19 12:03:37 +00:00
Compare commits
16 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
81a8115c56 | ||
![]() |
0ddd26bd51 | ||
![]() |
69e2133a27 | ||
![]() |
b04f85949b | ||
![]() |
667dba01ae | ||
![]() |
85a8cef628 | ||
![]() |
3099acfd00 | ||
![]() |
b00fe0b5f8 | ||
![]() |
9a64b8bdb6 | ||
![]() |
c01e493bd2 | ||
![]() |
890236af23 | ||
![]() |
ea678d805d | ||
![]() |
29699418ff | ||
![]() |
87bb36c39f | ||
![]() |
7cb85ed73c | ||
![]() |
c647771a6d |
@@ -1,4 +1,4 @@
|
||||
# v1.8.1
|
||||
# v1.8.3
|
||||
|
||||
QQ Version: Windows 9.9.15-26702 / Linux 3.2.12-26702
|
||||
|
||||
@@ -6,8 +6,8 @@ QQ Version: Windows 9.9.15-26702 / Linux 3.2.12-26702
|
||||
Way03/Way05
|
||||
|
||||
## 新增与调整
|
||||
1. 多层转发消息解析
|
||||
2. 撤回消息附带反馈
|
||||
3. 文件上传兼容性提升
|
||||
1. 输入状态变更事件加入
|
||||
2. Way05 支持Bat启动
|
||||
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
@@ -2,7 +2,7 @@
|
||||
"name": "napcat",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"version": "1.8.1",
|
||||
"version": "1.8.3",
|
||||
"scripts": {
|
||||
"watch:dev": "vite --mode development",
|
||||
"watch:prod": "vite --mode production",
|
||||
|
90
script/BootWay05.bat
Normal file
90
script/BootWay05.bat
Normal file
@@ -0,0 +1,90 @@
|
||||
@echo off
|
||||
REM 检查当前会话是否具有管理员权限
|
||||
openfiles >nul 2>&1
|
||||
if %errorlevel% neq 0 (
|
||||
REM 如果不是管理员,则重新启动脚本以管理员模式运行
|
||||
echo 请求管理员权限...
|
||||
powershell -Command "Start-Process cmd -ArgumentList '/c %~f0 %*' -Verb RunAs"
|
||||
exit /b
|
||||
)
|
||||
|
||||
REM 设置当前工作目录
|
||||
cd /d %~dp0
|
||||
|
||||
REM 获取当前目录路径
|
||||
set currentPath=%cd%
|
||||
set currentPath=%currentPath:\=/%
|
||||
|
||||
REM 生成JavaScript代码
|
||||
set "jsCode=(async () =^>await import('file:///%currentPath%/napcat.mjs'))();"
|
||||
|
||||
REM 将JavaScript代码保存到文件中
|
||||
echo %jsCode% > loadScript.js
|
||||
echo JavaScript code has been generated and saved to loadScript.js
|
||||
|
||||
REM 设置NAPCAT_PATH环境变量为 当前目录的loadScript.js地址
|
||||
set NAPCAT_PATH=%cd%\loadScript.js
|
||||
|
||||
REM 获取QQ路径
|
||||
|
||||
|
||||
:loop_read
|
||||
for /f "tokens=2*" %%a in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ" /v "UninstallString"') do (
|
||||
set RetString=%%b
|
||||
goto :napcat_boot
|
||||
)
|
||||
|
||||
:napcat_boot
|
||||
for %%a in (%RetString%) do (
|
||||
set "pathWithoutUninstall=%%~dpa"
|
||||
)
|
||||
|
||||
SET QQPath=%pathWithoutUninstall%QQ.exe
|
||||
|
||||
REM 拿不到QQ路径则退出
|
||||
if not exist "%QQpath%" (
|
||||
echo provided QQ path is invalid: %QQpath%
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
|
||||
REM 收集dbghelp.dll路径和HASH信息
|
||||
set QQdir=%~dp0
|
||||
set oldDllPath=%QQdir%dbghelp.dll
|
||||
set newDllPath=%currentPath%\dbghelp.dll
|
||||
|
||||
for /f "tokens=*" %%A in ('certutil -hashfile "%oldDllPath%" MD5') do (
|
||||
if not defined oldDllHash set oldDllHash=%%A
|
||||
)
|
||||
for /f "tokens=*" %%A in ('certutil -hashfile "%newDllPath%" MD5') do (
|
||||
if not defined newDllHash set newDllHash=%%A
|
||||
)
|
||||
|
||||
REM 如果文件一致则跳过
|
||||
if "%oldDllHash%" neq "%newDllHash%" (
|
||||
tasklist /fi "imagename eq QQ.exe" 2>nul | find /i "QQ.exe" >nul
|
||||
if %errorlevel% equ 0 (
|
||||
REM 文件占用则退出
|
||||
echo dbghelp.dll is in use, cannot continue.
|
||||
) else (
|
||||
REM 文件未占用则尝试覆盖
|
||||
copy /y "%newDllPath%" "%oldDllPath%"
|
||||
if %errorlevel% neq 0 (
|
||||
echo Failed to copy dbghelp.dll
|
||||
pause
|
||||
exit /b
|
||||
) else (
|
||||
echo dbghelp.dll has been copied to %QQdir%
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
REM 带参数启动QQ
|
||||
REM 判断wt是否存在,存在则通过wt启动,不存在则通过cmd启动
|
||||
REM %QQPath% --enable-logging %*
|
||||
where wt >nul 2>nul
|
||||
if %errorlevel% equ 0 (
|
||||
wt "cmd" /c "%QQPath%" --enable-logging %*
|
||||
) else (
|
||||
%QQPath%" --enable-logging %*
|
||||
)
|
93
script/BootWay05.utf8.bat
Normal file
93
script/BootWay05.utf8.bat
Normal file
@@ -0,0 +1,93 @@
|
||||
@echo off
|
||||
REM 检查当前会话是否具有管理员权限
|
||||
openfiles >nul 2>&1
|
||||
if %errorlevel% neq 0 (
|
||||
REM 如果不是管理员,则重新启动脚本以管理员模式运行
|
||||
echo 请求管理员权限...
|
||||
where wt >nul 2>nul
|
||||
if %errorlevel% equ 0 (
|
||||
powershell -Command "Start-Process cmd -ArgumentList ' /c %~f0 %*' -Verb RunAs"
|
||||
) else (
|
||||
powershell -Command "Start-Process wt -ArgumentList 'cmd /c %~f0 %*' -Verb RunAs"
|
||||
)
|
||||
|
||||
REM wt "cmd" /c "%~f0 %*"
|
||||
exit /b
|
||||
)
|
||||
|
||||
REM 设置当前工作目录
|
||||
cd /d %~dp0
|
||||
|
||||
REM 获取当前目录路径
|
||||
set currentPath=%cd%
|
||||
set currentPath=%currentPath:\=/%
|
||||
|
||||
REM 生成JavaScript代码
|
||||
set "jsCode=(async () =^>await import('file:///%currentPath%/napcat.mjs'))();"
|
||||
|
||||
REM 将JavaScript代码保存到文件中
|
||||
echo %jsCode% > loadScript.js
|
||||
echo JavaScript code has been generated and saved to loadScript.js
|
||||
|
||||
REM 设置NAPCAT_PATH环境变量为 当前目录的loadScript.js地址
|
||||
set NAPCAT_PATH=%cd%\loadScript.js
|
||||
|
||||
REM 获取QQ路径
|
||||
|
||||
|
||||
:loop_read
|
||||
for /f "tokens=2*" %%a in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ" /v "UninstallString"') do (
|
||||
set RetString=%%b
|
||||
goto :napcat_boot
|
||||
)
|
||||
|
||||
:napcat_boot
|
||||
for %%a in (%RetString%) do (
|
||||
set "pathWithoutUninstall=%%~dpa"
|
||||
)
|
||||
|
||||
SET QQPath=%pathWithoutUninstall%QQ.exe
|
||||
|
||||
REM 拿不到QQ路径则退出
|
||||
if not exist "%QQpath%" (
|
||||
echo provided QQ path is invalid: %QQpath%
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
|
||||
REM 收集dbghelp.dll路径和HASH信息
|
||||
set QQdir=%~dp0
|
||||
set oldDllPath=%QQdir%dbghelp.dll
|
||||
set newDllPath=%currentPath%\dbghelp.dll
|
||||
|
||||
for /f "tokens=*" %%A in ('certutil -hashfile "%oldDllPath%" MD5') do (
|
||||
if not defined oldDllHash set oldDllHash=%%A
|
||||
)
|
||||
for /f "tokens=*" %%A in ('certutil -hashfile "%newDllPath%" MD5') do (
|
||||
if not defined newDllHash set newDllHash=%%A
|
||||
)
|
||||
|
||||
REM 如果文件一致则跳过
|
||||
if "%oldDllHash%" neq "%newDllHash%" (
|
||||
tasklist /fi "imagename eq QQ.exe" 2>nul | find /i "QQ.exe" >nul
|
||||
if %errorlevel% equ 0 (
|
||||
REM 文件占用则退出
|
||||
echo dbghelp.dll is in use, cannot continue.
|
||||
) else (
|
||||
REM 文件未占用则尝试覆盖
|
||||
copy /y "%newDllPath%" "%oldDllPath%"
|
||||
if %errorlevel% neq 0 (
|
||||
echo Failed to copy dbghelp.dll
|
||||
pause
|
||||
exit /b
|
||||
) else (
|
||||
echo dbghelp.dll has been copied to %QQdir%
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
REM 带参数启动QQ
|
||||
REM 判断wt是否存在,存在则通过wt启动,不存在则通过cmd启动
|
||||
REM %QQPath% --enable-logging %*
|
||||
chcp 65001
|
||||
"%QQPath%" --enable-logging %*
|
@@ -1,6 +1,6 @@
|
||||
// --------------------
|
||||
// 2024.7.3 9.9.12 BootWay.03 其余方法暂不公开(此方案为临时方案 Win平台已验证)
|
||||
// 缺陷 (已知)
|
||||
|
||||
// 1.与非入侵式不同 现在破坏本体代码
|
||||
// 2.重启代码与正常启动代码失效
|
||||
// 3.Win需要补丁
|
||||
|
@@ -43,6 +43,7 @@ setTimeout(() => {
|
||||
await sleep(100);
|
||||
// NTQQMsgApi.CheckSendMode().then().catch();
|
||||
loadMessageUnique().then().catch();
|
||||
//下面的代码还没摸清 不要使用
|
||||
//let data = await napCatCore.session.getMsgService().sendSsoCmdReqByContend("LightAppSvc.mini_app_growguard.ReportExecute","1124343");
|
||||
//console.log(data);
|
||||
});
|
||||
@@ -72,6 +73,7 @@ export class NTQQMsgApi {
|
||||
}
|
||||
static async getMsgEmojiLikesList(peer: Peer, msgSeq: string, emojiId: string, emojiType: string, count: number = 20) {
|
||||
//console.log(peer, msgSeq, emojiId, emojiType, count);
|
||||
//注意此处emojiType 可选值一般为1-2 2好像是unicode表情dec值 大部分情况 Taged M likiowa
|
||||
return napCatCore.session.getMsgService().getMsgEmojiLikesList(peer, msgSeq, emojiId, emojiType, "", false, 20)
|
||||
}
|
||||
// static napCatCore: NapCatCore | null = null;
|
||||
@@ -94,20 +96,26 @@ export class NTQQMsgApi {
|
||||
} | undefined> {
|
||||
return napCatCore.session.getMsgService().getMultiMsg(peer, rootMsgId, parentMsgId);
|
||||
}
|
||||
static async getLastestMsgByUids(peer: Peer, count: number = 20) {
|
||||
static async ForwardMsg(peer: Peer, msgIds: string[]) {
|
||||
return napCatCore.session.getMsgService().forwardMsg(msgIds, peer, [peer], new Map());
|
||||
}
|
||||
static async getLastestMsgByUids(peer: Peer, count: number = 20, isReverseOrder: boolean = false) {
|
||||
let ret = await napCatCore.session.getMsgService().queryMsgsWithFilterEx('0', '0', '0', {
|
||||
chatInfo: peer,
|
||||
filterMsgType: [],
|
||||
filterSendersUid: [],
|
||||
filterMsgToTime: '0',
|
||||
filterMsgFromTime: '0',
|
||||
isReverseOrder: false,
|
||||
isReverseOrder: isReverseOrder,//此参数有点离谱 注意不是本次查询的排序 而是全部消历史信息的排序 默认false 从新消息拉取到旧消息
|
||||
isIncludeCurrent: true,
|
||||
pageLimit: count,
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
static async getMsgsByMsgId(peer: Peer, msgIds: string[]) {
|
||||
static async getMsgsByMsgId(peer: Peer | undefined, msgIds: string[] | undefined) {
|
||||
if (!peer) throw new Error('peer is not allowed');
|
||||
if (!msgIds) throw new Error('msgIds is not allowed');
|
||||
//Mlikiowa: 参数不合规会导致NC异常崩溃 原因是TX未对进入参数判断 对应Android标记@NotNull AndroidJADX分析可得
|
||||
return await napCatCore.session.getMsgService().getMsgsByMsgId(peer, msgIds);
|
||||
}
|
||||
static async getSingleMsg(peer: Peer, seq: string) {
|
||||
@@ -118,7 +126,7 @@ export class NTQQMsgApi {
|
||||
}
|
||||
static async queryMsgsWithFilterExWithSeq(peer: Peer, msgSeq: string) {
|
||||
let ret = await napCatCore.session.getMsgService().queryMsgsWithFilterEx('0', '0', msgSeq, {
|
||||
chatInfo: peer,
|
||||
chatInfo: peer,//此处为Peer 为关键查询参数 没有啥也没有 by mlik iowa
|
||||
filterMsgType: [],
|
||||
filterSendersUid: [],
|
||||
filterMsgToTime: '0',
|
||||
@@ -145,6 +153,7 @@ export class NTQQMsgApi {
|
||||
1,
|
||||
5000,
|
||||
(groupFileListResult: onGroupFileInfoUpdateParamType) => {
|
||||
//Developer Mlikiowa Todo: 此处有问题 无法判断是否成功
|
||||
return true;
|
||||
},
|
||||
GroupCode,
|
||||
@@ -152,9 +161,9 @@ export class NTQQMsgApi {
|
||||
);
|
||||
return data[1].item;
|
||||
}
|
||||
static async getMsgHistory(peer: Peer, msgId: string, count: number) {
|
||||
static async getMsgHistory(peer: Peer, msgId: string, count: number, isReverseOrder: boolean = false) {
|
||||
// 消息时间从旧到新
|
||||
return napCatCore.session.getMsgService().getMsgsIncludeSelf(peer, msgId, count, true);
|
||||
return napCatCore.session.getMsgService().getMsgsIncludeSelf(peer, msgId, count, isReverseOrder);
|
||||
}
|
||||
static async recallMsg(peer: Peer, msgIds: string[]) {
|
||||
await napCatCore.session.getMsgService().recallMsg({
|
||||
@@ -163,19 +172,26 @@ export class NTQQMsgApi {
|
||||
}, msgIds);
|
||||
}
|
||||
static async sendMsgV2(peer: Peer, msgElements: SendMessageElement[], waitComplete = true, timeout = 10000) {
|
||||
// function generateMsgId() {
|
||||
// const timestamp = Math.floor(Date.now() / 1000);
|
||||
// const random = Math.floor(Math.random() * Math.pow(2, 32));
|
||||
// const buffer = Buffer.alloc(8);
|
||||
// buffer.writeUInt32BE(timestamp, 0);
|
||||
// buffer.writeUInt32BE(random, 4);
|
||||
// const msgId = BigInt("0x" + buffer.toString('hex')).toString();
|
||||
// return msgId;
|
||||
// }
|
||||
function generateMsgId() {
|
||||
const timestamp = Math.floor(Date.now() / 1000);
|
||||
const random = Math.floor(Math.random() * Math.pow(2, 32));
|
||||
const buffer = Buffer.alloc(8);
|
||||
buffer.writeUInt32BE(timestamp, 0);
|
||||
buffer.writeUInt32BE(random, 4);
|
||||
const msgId = BigInt("0x" + buffer.toString('hex')).toString();
|
||||
return msgId;
|
||||
}
|
||||
// 此处有采用Hack方法 利用数据返回正确得到对应消息
|
||||
// 与之前 Peer队列 MsgSeq队列 真正的MsgId并发不同
|
||||
// 谨慎采用 目前测试暂无问题 Developer.Mlikiowa
|
||||
let msgId = await NTQQMsgApi.getMsgUnique(peer.chatType, await NTQQMsgApi.getServerTime());
|
||||
let msgId: string;
|
||||
try {
|
||||
msgId = await NTQQMsgApi.getMsgUnique(peer.chatType, await NTQQMsgApi.getServerTime());
|
||||
} catch (error) {
|
||||
//if (!napCatCore.session.getMsgService()['generateMsgUniqueId'])
|
||||
//兜底识别策略V2
|
||||
msgId = generateMsgId().toString();
|
||||
}
|
||||
let data = await NTEventDispatch.CallNormalEvent<
|
||||
(msgId: string, peer: Peer, msgElements: SendMessageElement[], map: Map<any, any>) => Promise<unknown>,
|
||||
(msgList: RawMessage[]) => void
|
||||
|
@@ -77,7 +77,7 @@ export const sessionConfig: WrapperSessionInitConfig | any = {};
|
||||
export async function genSessionConfig(selfUin: string, selfUid: string, account_path: string): Promise<WrapperSessionInitConfig> {
|
||||
const downloadPath = path.join(account_path, 'NapCat', 'temp');
|
||||
fs.mkdirSync(downloadPath, { recursive: true });
|
||||
let guid: string = await getMachineId();
|
||||
let guid: string = await getMachineId();//26702 支持JS获取guid值 在LoginService中获取 TODO mlikiow a
|
||||
//console.log(guid);
|
||||
// guid = '52afb776-82f6-4e59-9d38-44705b112d0a';
|
||||
//let guid: string = await getMachineId();
|
||||
|
@@ -15,6 +15,7 @@ export class FetchCustomFace extends BaseAction<Payload, string[]> {
|
||||
actionName = ActionName.FetchCustomFace;
|
||||
PayloadSchema = SchemaData;
|
||||
protected async _handle(payload: Payload) {
|
||||
//48 可能正好是QQ需要的一个页面的数量 Tagged Mlikiowa
|
||||
const ret = await NTQQMsgApi.fetchFavEmojiList(payload.count || 48);
|
||||
return ret.emojiInfoList.map(e => e.url);
|
||||
}
|
||||
|
@@ -1,11 +1,7 @@
|
||||
import BaseAction from '../BaseAction';
|
||||
import { ActionName, BaseCheckResult } from '../types';
|
||||
import * as fs from 'node:fs';
|
||||
import { NTQQUserApi } from '@/core/apis/user';
|
||||
import { checkFileReceived, uri2local } from '@/common/utils/file';
|
||||
import { napCatCore, NTQQGroupApi } from '@/core';
|
||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||
// import { log } from "../../../common/utils";
|
||||
|
||||
const SchemaData = {
|
||||
type: 'object',
|
||||
|
@@ -10,9 +10,7 @@ const SchemaData = {
|
||||
properties: {
|
||||
words: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'string',
|
||||
}
|
||||
items: { type: 'string' }
|
||||
}
|
||||
},
|
||||
required: ['words'],
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import BaseAction from '../BaseAction';
|
||||
import { OB11Message, OB11User } from '../../types';
|
||||
import { ActionName } from '../types';
|
||||
import { ChatType } from '@/core/entities';
|
||||
import { ChatType, RawMessage } from '@/core/entities';
|
||||
import { NTQQMsgApi } from '@/core/apis/msg';
|
||||
import { OB11Constructor } from '../../constructor';
|
||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||
@@ -17,9 +17,10 @@ const SchemaData = {
|
||||
properties: {
|
||||
user_id: { type: ['number', 'string'] },
|
||||
message_seq: { type: 'number' },
|
||||
count: { type: 'number' }
|
||||
count: { type: 'number' },
|
||||
reverseOrder: { type: 'boolean' }
|
||||
},
|
||||
required: ['user_id', 'message_seq', 'count']
|
||||
required: ['user_id']
|
||||
} as const satisfies JSONSchema;
|
||||
|
||||
type Payload = FromSchema<typeof SchemaData>;
|
||||
@@ -28,21 +29,28 @@ export default class GetFriendMsgHistory extends BaseAction<Payload, Response> {
|
||||
actionName = ActionName.GetFriendMsgHistory;
|
||||
PayloadSchema = SchemaData;
|
||||
protected async _handle(payload: Payload): Promise<Response> {
|
||||
//处理参数
|
||||
const uid = await NTQQUserApi.getUidByUin(payload.user_id.toString());
|
||||
if (!uid) {
|
||||
throw `记录${payload.user_id}不存在`;
|
||||
}
|
||||
const startMsgId = (await MessageUnique.getMsgIdAndPeerByShortId(payload.message_seq))?.MsgId || '0';
|
||||
const MsgCount = payload.count || 20;
|
||||
const isReverseOrder = payload.reverseOrder || true;
|
||||
if (!uid) throw `记录${payload.user_id}不存在`;
|
||||
const friend = await NTQQFriendApi.isBuddy(uid);
|
||||
const historyResult = (await NTQQMsgApi.getMsgHistory({
|
||||
chatType: friend ? ChatType.friend : ChatType.temp,
|
||||
peerUid: uid
|
||||
}, startMsgId, parseInt(payload.count?.toString()) || 20));
|
||||
//logDebug(historyResult);
|
||||
const msgList = historyResult.msgList;
|
||||
const peer = { chatType: friend ? ChatType.friend : ChatType.temp, peerUid: uid };
|
||||
|
||||
//拉取消息
|
||||
let msgList: RawMessage[];
|
||||
if (!payload.message_seq || payload.message_seq == 0) {
|
||||
msgList = (await NTQQMsgApi.getLastestMsgByUids(peer, MsgCount)).msgList;
|
||||
} else {
|
||||
const startMsgId = MessageUnique.getMsgIdAndPeerByShortId(payload.message_seq)?.MsgId;
|
||||
if (!startMsgId) throw `消息${payload.message_seq}不存在`;
|
||||
msgList = (await NTQQMsgApi.getMsgHistory(peer, startMsgId, MsgCount)).msgList;
|
||||
}
|
||||
if(isReverseOrder) msgList.reverse();
|
||||
await Promise.all(msgList.map(async msg => {
|
||||
msg.id = await MessageUnique.createMsg({ guildId: '', chatType: msg.chatType, peerUid: msg.peerUid }, msg.msgId);
|
||||
msg.id = MessageUnique.createMsg({ guildId: '', chatType: msg.chatType, peerUid: msg.peerUid }, msg.msgId);
|
||||
}));
|
||||
//转换消息
|
||||
const ob11MsgList = await Promise.all(msgList.map(msg => OB11Constructor.message(msg)));
|
||||
return { 'messages': ob11MsgList };
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@ import BaseAction from '../BaseAction';
|
||||
import { OB11Message, OB11User } from '../../types';
|
||||
import { getGroup, groups } from '@/core/data';
|
||||
import { ActionName } from '../types';
|
||||
import { ChatType, RawMessage } from '@/core/entities';
|
||||
import { ChatType, Peer, RawMessage } from '@/core/entities';
|
||||
import { NTQQMsgApi } from '@/core/apis/msg';
|
||||
import { OB11Constructor } from '../../constructor';
|
||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||
@@ -16,7 +16,8 @@ const SchemaData = {
|
||||
properties: {
|
||||
group_id: { type: ['number', 'string'] },
|
||||
message_seq: { type: 'number' },
|
||||
count: { type: 'number' }
|
||||
count: { type: 'number' },
|
||||
reverseOrder: { type: 'boolean' }
|
||||
},
|
||||
required: ['group_id']
|
||||
} as const satisfies JSONSchema;
|
||||
@@ -27,25 +28,28 @@ export default class GoCQHTTPGetGroupMsgHistory extends BaseAction<Payload, Resp
|
||||
actionName = ActionName.GoCQHTTP_GetGroupMsgHistory;
|
||||
PayloadSchema = SchemaData;
|
||||
protected async _handle(payload: Payload): Promise<Response> {
|
||||
//处理参数
|
||||
const group = await getGroup(payload.group_id.toString());
|
||||
if (!group) {
|
||||
throw `群${payload.group_id}不存在`;
|
||||
}
|
||||
let targetMsgShortId, count = parseInt(payload.count?.toString() ?? '20');
|
||||
const peer = {
|
||||
chatType: ChatType.group,
|
||||
peerUid: group.groupCode
|
||||
};
|
||||
const isReverseOrder = payload.reverseOrder || true;
|
||||
const MsgCount = payload.count || 20;
|
||||
const peer: Peer = { chatType: ChatType.group, peerUid: payload.group_id.toString() };
|
||||
if (!group) throw `群${payload.group_id}不存在`;
|
||||
|
||||
//拉取消息
|
||||
let msgList: RawMessage[];
|
||||
if (!payload.message_seq || payload.message_seq === 0) {
|
||||
msgList = (await NTQQMsgApi.getLastestMsgByUids(peer, count)).msgList;
|
||||
if (!payload.message_seq || payload.message_seq == 0) {
|
||||
msgList = (await NTQQMsgApi.getLastestMsgByUids(peer, MsgCount)).msgList;
|
||||
} else {
|
||||
const startMsgId = (await MessageUnique.getMsgIdAndPeerByShortId(targetMsgShortId ?? (payload.message_seq ?? 0)))?.MsgId || '0';
|
||||
msgList = (await NTQQMsgApi.getMsgHistory(peer, startMsgId, count)).msgList;
|
||||
const startMsgId = MessageUnique.getMsgIdAndPeerByShortId(payload.message_seq)?.MsgId;
|
||||
if (!startMsgId) throw `消息${payload.message_seq}不存在`;
|
||||
msgList = (await NTQQMsgApi.getMsgHistory(peer, startMsgId, MsgCount)).msgList;
|
||||
}
|
||||
if(isReverseOrder) msgList.reverse();
|
||||
await Promise.all(msgList.map(async msg => {
|
||||
msg.id = await MessageUnique.createMsg({ guildId: '', chatType: msg.chatType, peerUid: msg.peerUid }, msg.msgId);
|
||||
msg.id = MessageUnique.createMsg({ guildId: '', chatType: msg.chatType, peerUid: msg.peerUid }, msg.msgId);
|
||||
}));
|
||||
|
||||
//转换消息
|
||||
const ob11MsgList = await Promise.all(msgList.map(msg => OB11Constructor.message(msg)));
|
||||
return { 'messages': ob11MsgList };
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@ import {
|
||||
IdMusicSignPostData,
|
||||
NTQQFileApi,
|
||||
NTQQMsgApi,
|
||||
Peer,
|
||||
SendArkElement,
|
||||
SendMessageElement,
|
||||
SendMsgElementConstructor,
|
||||
@@ -17,16 +18,16 @@ import { uri2local } from '@/common/utils/file';
|
||||
import { ob11Config } from '@/onebot11/config';
|
||||
import { RequestUtil } from '@/common/utils/request';
|
||||
import { MessageUnique } from '@/common/utils/MessageUnique';
|
||||
|
||||
console.log(process.pid)
|
||||
export type MessageContext = {
|
||||
group?: Group,
|
||||
deleteAfterSentFiles: string[],
|
||||
peer:Peer
|
||||
}
|
||||
async function handleOb11FileLikeMessage(
|
||||
{ data: inputdata }: OB11MessageFileBase,
|
||||
{ deleteAfterSentFiles }: MessageContext
|
||||
) {
|
||||
//有的奇怪的框架将url作为参数 而不是file 此时优先url
|
||||
//有的奇怪的框架将url作为参数 而不是file 此时优先url 同时注意可能传入的是非file://开头的目录 By Mlikiowa
|
||||
const { path, isLocal, fileName, errMsg,success } = (await uri2local(inputdata?.url || inputdata.file));
|
||||
|
||||
if (!success) {
|
||||
@@ -52,12 +53,12 @@ const _handlers: {
|
||||
[OB11MessageDataType.text]: async ({ data: { text } }) => SendMsgElementConstructor.text(text),
|
||||
|
||||
[OB11MessageDataType.at]: async ({ data: { qq: atQQ } }, context) => {
|
||||
if (!context.group) return undefined;
|
||||
if (!context.peer) return undefined;
|
||||
|
||||
if (atQQ === 'all') return SendMsgElementConstructor.at(atQQ, atQQ, AtType.atAll, '全体成员');
|
||||
|
||||
// then the qq is a group member
|
||||
const atMember = await getGroupMember(context.group.groupCode, atQQ);
|
||||
const atMember = await getGroupMember(context.peer.peerUid, atQQ);
|
||||
return atMember ?
|
||||
SendMsgElementConstructor.at(atQQ, atMember.uid, AtType.atUser, atMember.cardName || atMember.nick) :
|
||||
undefined;
|
||||
@@ -206,7 +207,7 @@ const handlers = <{
|
||||
|
||||
export default async function createSendElements(
|
||||
messageData: OB11MessageData[],
|
||||
group?: Group,
|
||||
peer: Peer,
|
||||
ignoreTypes: OB11MessageDataType[] = []
|
||||
) {
|
||||
const deleteAfterSentFiles: string[] = [];
|
||||
@@ -217,7 +218,7 @@ export default async function createSendElements(
|
||||
}
|
||||
const callResult = handlers[sendMsg.type](
|
||||
sendMsg,
|
||||
{ group, deleteAfterSentFiles }
|
||||
{ peer, deleteAfterSentFiles }
|
||||
)?.catch(undefined);
|
||||
callResultList.push(callResult);
|
||||
}
|
||||
@@ -228,7 +229,7 @@ export default async function createSendElements(
|
||||
|
||||
export async function createSendElementsParallel(
|
||||
messageData: OB11MessageData[],
|
||||
group?: Group,
|
||||
peer: Peer,
|
||||
ignoreTypes: OB11MessageDataType[] = []
|
||||
) {
|
||||
const deleteAfterSentFiles: string[] = [];
|
||||
@@ -236,7 +237,7 @@ export async function createSendElementsParallel(
|
||||
await Promise.all(
|
||||
messageData.map(async sendMsg => ignoreTypes.includes(sendMsg.type) ?
|
||||
undefined :
|
||||
handlers[sendMsg.type](sendMsg, { group, deleteAfterSentFiles }))
|
||||
handlers[sendMsg.type](sendMsg, { peer, deleteAfterSentFiles }))
|
||||
).then(
|
||||
results => results.filter(
|
||||
element => element !== undefined
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { ChatType, ElementType, Group, NTQQMsgApi, Peer, RawMessage, SendMessageElement } from '@/core';
|
||||
import { OB11MessageNode } from '@/onebot11/types';
|
||||
import { OB11MessageDataType, OB11MessageNode } from '@/onebot11/types';
|
||||
import { selfInfo } from '@/core/data';
|
||||
import createSendElements from '@/onebot11/action/msg/SendMsg/create-send-elements';
|
||||
import { logDebug, logError } from '@/common/utils/log';
|
||||
@@ -24,135 +24,92 @@ async function cloneMsg(msg: RawMessage): Promise<RawMessage | undefined> {
|
||||
if (sendElements.length === 0) {
|
||||
logDebug('需要clone的消息无法解析,将会忽略掉', msg);
|
||||
}
|
||||
|
||||
//logDebug('克隆消息', sendElements);
|
||||
|
||||
try {
|
||||
const nodeMsg = await NTQQMsgApi.sendMsg(selfPeer, sendElements, true);
|
||||
await sleep(500); // 防止风控
|
||||
return nodeMsg;
|
||||
} catch (e) {
|
||||
logError(e, '克隆转发消息失败,将忽略本条消息', msg);
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleForwardNode(destPeer: Peer, messageNodes: OB11MessageNode[], group: Group | undefined): Promise<RawMessage | null> {
|
||||
export async function handleForwardNode(destPeer: Peer, messageNodes: OB11MessageNode[]): Promise<RawMessage | null> {
|
||||
const selfPeer = {
|
||||
chatType: ChatType.friend,
|
||||
peerUid: selfInfo.uid
|
||||
};
|
||||
let nodeMsgIds: string[] = [];
|
||||
|
||||
// 先判断一遍是不是id和自定义混用
|
||||
const needClone =
|
||||
messageNodes.filter(node => node.data.id).length &&
|
||||
messageNodes.filter(node => !node.data.id).length;
|
||||
|
||||
for (const messageNode of messageNodes) {
|
||||
// 一个node表示一个人的消息
|
||||
const nodeId = messageNode.data.id;
|
||||
// 有nodeId表示一个子转发消息卡片
|
||||
if (nodeId) {
|
||||
const nodeMsg = MessageUnique.getPeerByMsgId(nodeId);
|
||||
if (!needClone) {
|
||||
nodeMsgIds.push(nodeMsg!.MsgId);
|
||||
} else {
|
||||
if (nodeMsg!.Peer.peerUid !== selfInfo.uid) {
|
||||
// need cloning
|
||||
const rawClone = await NTQQMsgApi.getMsgsByMsgId(nodeMsg?.Peer!, [nodeMsg?.MsgId!]);
|
||||
const clonedMsg = await cloneMsg(rawClone.msgList[0]);
|
||||
if (clonedMsg) {
|
||||
nodeMsgIds.push(clonedMsg.msgId);
|
||||
}
|
||||
}
|
||||
//对Mgsid和OB11ID混用情况兜底
|
||||
const nodeMsg = MessageUnique.getMsgIdAndPeerByShortId(parseInt(nodeId)) || MessageUnique.getPeerByMsgId(nodeId);
|
||||
if (!nodeMsg) {
|
||||
logError('转发消息失败,未找到消息', nodeId);
|
||||
continue;
|
||||
}
|
||||
nodeMsgIds.push(nodeMsg.MsgId);
|
||||
} else {
|
||||
// 自定义的消息
|
||||
// 提取消息段,发给自己生成消息id
|
||||
try {
|
||||
const { sendElements } = await createSendElements(normalize(messageNode.data.content), group);
|
||||
//logDebug('开始生成转发节点', sendElements);
|
||||
const sendElementsSplit: SendMessageElement[][] = [];
|
||||
let splitIndex = 0;
|
||||
for (const sendElement of sendElements) {
|
||||
if (!sendElementsSplit[splitIndex]) {
|
||||
sendElementsSplit[splitIndex] = [];
|
||||
}
|
||||
|
||||
if (sendElement.elementType === ElementType.FILE || sendElement.elementType === ElementType.VIDEO) {
|
||||
if (sendElementsSplit[splitIndex].length > 0) {
|
||||
splitIndex++;
|
||||
}
|
||||
sendElementsSplit[splitIndex] = [sendElement];
|
||||
splitIndex++;
|
||||
} else {
|
||||
sendElementsSplit[splitIndex].push(sendElement);
|
||||
}
|
||||
//logDebug(sendElementsSplit);
|
||||
let OB11Data = normalize(messageNode.data.content);
|
||||
//筛选node消息
|
||||
let isNodeMsg = OB11Data.filter(e => e.type === OB11MessageDataType.node).length;//找到子转发消息
|
||||
if (isNodeMsg !== 0) {
|
||||
if (isNodeMsg !== OB11Data.length) { logError('子消息中包含非node消息 跳过不合法部分'); continue; }
|
||||
const nodeMsg = await handleForwardNode(selfPeer, OB11Data.filter(e => e.type === OB11MessageDataType.node));
|
||||
if (nodeMsg) { nodeMsgIds.push(nodeMsg.msgId); MessageUnique.createMsg(selfPeer, nodeMsg.msgId) };
|
||||
//完成子卡片生成跳过后续
|
||||
continue;
|
||||
}
|
||||
// log("分割后的转发节点", sendElementsSplit)
|
||||
const { sendElements } = await createSendElements(OB11Data, destPeer);
|
||||
//拆分消息
|
||||
let MixElement = sendElements.filter(element => element.elementType !== ElementType.FILE && element.elementType !== ElementType.VIDEO);
|
||||
let SingleElement = sendElements.filter(element => element.elementType === ElementType.FILE || element.elementType === ElementType.VIDEO).map(e => [e]);
|
||||
let AllElement: SendMessageElement[][] = [MixElement, ...SingleElement].filter(e => e !== undefined && e.length !== 0);
|
||||
const MsgNodeList: Promise<RawMessage | undefined>[] = [];
|
||||
for (const sendElementsSplitElement of sendElementsSplit) {
|
||||
MsgNodeList.push(sendMsg(selfPeer, sendElementsSplitElement, [], true));
|
||||
await sleep(Math.trunc(sendElementsSplit.length / 10) * 100);
|
||||
//await sleep(10);
|
||||
for (const sendElementsSplitElement of AllElement) {
|
||||
MsgNodeList.push(sendMsg(selfPeer, sendElementsSplitElement, [], true).catch(e => new Promise((resolve, reject) => { resolve(undefined) })));
|
||||
}
|
||||
for (const msgNode of MsgNodeList) {
|
||||
const result = await msgNode;
|
||||
if (result) {
|
||||
nodeMsgIds.push(result.msgId);
|
||||
(await Promise.allSettled(MsgNodeList)).map((result) => {
|
||||
if (result.status === 'fulfilled' && result.value) {
|
||||
nodeMsgIds.push(result.value.msgId);
|
||||
MessageUnique.createMsg(selfPeer, result.value.msgId);
|
||||
}
|
||||
//logDebug('转发节点生成成功', result.msgId);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
logDebug('生成转发消息节点失败', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 检查srcPeer是否一致,不一致则需要克隆成自己的消息, 让所有srcPeer都变成自己的,使其保持一致才能够转发
|
||||
const nodeMsgArray: Array<RawMessage> = [];
|
||||
|
||||
let srcPeer: Peer | undefined = undefined;
|
||||
let needSendSelf = false;
|
||||
for (const msgId of nodeMsgIds) {
|
||||
const nodeMsgPeer = await MessageUnique.getPeerByMsgId(msgId);
|
||||
const nodeMsg = (await NTQQMsgApi.getMsgsByMsgId(nodeMsgPeer?.Peer!, [msgId])).msgList[0];
|
||||
if (nodeMsg) {
|
||||
nodeMsgArray.push(nodeMsg);
|
||||
if (!srcPeer) {
|
||||
srcPeer = { chatType: nodeMsg.chatType, peerUid: nodeMsg.peerUid };
|
||||
} else if (srcPeer.peerUid !== nodeMsg.peerUid) {
|
||||
needSendSelf = true;
|
||||
srcPeer = selfPeer;
|
||||
}
|
||||
//检测是否处于同一个Peer 不在同一个peer则全部消息由自身发送
|
||||
for (let msgId of nodeMsgIds) {
|
||||
const nodeMsgPeer = MessageUnique.getPeerByMsgId(msgId);
|
||||
if (!nodeMsgPeer) {
|
||||
logError('转发消息失败,未找到消息', msgId);
|
||||
continue;
|
||||
}
|
||||
const nodeMsg = (await NTQQMsgApi.getMsgsByMsgId(nodeMsgPeer.Peer, [msgId])).msgList[0];
|
||||
srcPeer = srcPeer ?? { chatType: nodeMsg.chatType, peerUid: nodeMsg.peerUid };
|
||||
if (srcPeer.peerUid !== nodeMsg.peerUid) {
|
||||
needSendSelf = true;
|
||||
}
|
||||
nodeMsgArray.push(nodeMsg);
|
||||
}
|
||||
// logDebug('nodeMsgArray', nodeMsgArray);
|
||||
nodeMsgIds = nodeMsgArray.map(msg => msg.msgId);
|
||||
let retMsgIds: string[] = [];
|
||||
if (needSendSelf) {
|
||||
//logDebug('需要克隆转发消息');
|
||||
for (const [index, msg] of nodeMsgArray.entries()) {
|
||||
if (msg.peerUid !== selfInfo.uid) {
|
||||
const clonedMsg = await cloneMsg(msg);
|
||||
if (clonedMsg) {
|
||||
nodeMsgIds[index] = clonedMsg.msgId;
|
||||
}
|
||||
}
|
||||
if (msg.peerUid === selfInfo.uid) continue;
|
||||
const ClonedMsg = await cloneMsg(msg);
|
||||
if (ClonedMsg) retMsgIds.push(ClonedMsg.msgId);
|
||||
}
|
||||
} else {
|
||||
retMsgIds = nodeMsgIds;
|
||||
}
|
||||
// elements之间用换行符分隔
|
||||
// let _sendForwardElements: SendMessageElement[] = []
|
||||
// for(let i = 0; i < sendForwardElements.length; i++){
|
||||
// _sendForwardElements.push(sendForwardElements[i])
|
||||
// _sendForwardElements.push(SendMsgElementConstructor.text("\n\n"))
|
||||
// }
|
||||
// const nodeMsg = await NTQQApi.sendMsg(selfPeer, _sendForwardElements, true);
|
||||
// nodeIds.push(nodeMsg.msgId)
|
||||
// await sleep(500);
|
||||
// 开发转发
|
||||
if (nodeMsgIds.length === 0) {
|
||||
throw Error('转发消息失败,生成节点为空');
|
||||
}
|
||||
if (nodeMsgIds.length === 0) throw Error('转发消息失败,生成节点为空');
|
||||
try {
|
||||
logDebug('开发转发', srcPeer, destPeer, nodeMsgIds);
|
||||
return await NTQQMsgApi.multiForwardMsg(srcPeer!, destPeer, nodeMsgIds);
|
||||
|
@@ -76,9 +76,7 @@ export async function sendMsg(peer: Peer, sendElements: SendMessageElement[], de
|
||||
return returnMsg;
|
||||
}
|
||||
|
||||
async function createContext(payload: OB11PostSendMsg, contextMode: ContextMode): Promise<{
|
||||
peer: Peer, group?: Group
|
||||
}> {
|
||||
async function createContext(payload: OB11PostSendMsg, contextMode: ContextMode): Promise<Peer> {
|
||||
// This function determines the type of message by the existence of user_id / group_id,
|
||||
// not message_type.
|
||||
// This redundant design of Ob11 here should be blamed.
|
||||
@@ -86,11 +84,8 @@ async function createContext(payload: OB11PostSendMsg, contextMode: ContextMode)
|
||||
if ((contextMode === ContextMode.Group || contextMode === ContextMode.Normal) && payload.group_id) {
|
||||
const group = (await getGroup(payload.group_id))!; // checked before
|
||||
return {
|
||||
peer: {
|
||||
chatType: ChatType.group,
|
||||
peerUid: group.groupCode
|
||||
},
|
||||
group: group,
|
||||
chatType: ChatType.group,
|
||||
peerUid: group.groupCode
|
||||
};
|
||||
}
|
||||
if ((contextMode === ContextMode.Private || contextMode === ContextMode.Normal) && payload.user_id) {
|
||||
@@ -98,10 +93,8 @@ async function createContext(payload: OB11PostSendMsg, contextMode: ContextMode)
|
||||
const isBuddy = await NTQQFriendApi.isBuddy(Uid!);
|
||||
//console.log("[调试代码] UIN:", payload.user_id, " UID:", Uid, " IsBuddy:", isBuddy);
|
||||
return {
|
||||
peer: {
|
||||
chatType: isBuddy ? ChatType.friend : ChatType.temp,
|
||||
peerUid: Uid!
|
||||
},
|
||||
chatType: isBuddy ? ChatType.friend : ChatType.temp,
|
||||
peerUid: Uid!
|
||||
};
|
||||
}
|
||||
throw '请指定 group_id 或 user_id';
|
||||
@@ -139,7 +132,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
||||
}
|
||||
|
||||
protected async _handle(payload: OB11PostSendMsg): Promise<{ message_id: number }> {
|
||||
const { peer, group } = await createContext(payload, this.contextMode);
|
||||
const peer = await createContext(payload, this.contextMode);
|
||||
|
||||
const messages = normalize(
|
||||
payload.message,
|
||||
@@ -147,9 +140,9 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
||||
);
|
||||
|
||||
if (getSpecialMsgNum(payload, OB11MessageDataType.node)) {
|
||||
const returnMsg = await handleForwardNode(peer, messages as OB11MessageNode[], group);
|
||||
const returnMsg = await handleForwardNode(peer, messages as OB11MessageNode[]);
|
||||
if (returnMsg) {
|
||||
const msgShortId = await MessageUnique.createMsg({ guildId: '', peerUid: peer.peerUid, chatType: peer.chatType }, returnMsg!.msgId);
|
||||
const msgShortId = MessageUnique.createMsg({ guildId: '', peerUid: peer.peerUid, chatType: peer.chatType }, returnMsg!.msgId);
|
||||
return { message_id: msgShortId! };
|
||||
} else {
|
||||
throw Error('发送转发消息失败');
|
||||
@@ -163,7 +156,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
||||
}
|
||||
// log("send msg:", peer, sendElements)
|
||||
|
||||
const { sendElements, deleteAfterSentFiles } = await createSendElements(messages, group);
|
||||
const { sendElements, deleteAfterSentFiles } = await createSendElements(messages, peer);
|
||||
//console.log(peer, JSON.stringify(sendElements,null,2));
|
||||
const returnMsg = await sendMsg(peer, sendElements, deleteAfterSentFiles);
|
||||
return { message_id: returnMsg!.id! };
|
||||
|
@@ -224,9 +224,10 @@ export class OB11Constructor {
|
||||
//读取视频链接并兜底
|
||||
let videoUrl;//Array
|
||||
if (msg.peerUin = '284840486') {
|
||||
//合并消息内部 应该进行特殊处理
|
||||
//合并消息内部 应该进行特殊处理 可能需要重写peer 待测试与研究 Mlikiowa Taged TODO
|
||||
}
|
||||
try {
|
||||
|
||||
videoUrl = await NTQQFileApi.getVideoUrl({
|
||||
chatType: msg.chatType,
|
||||
peerUid: msg.peerUid,
|
||||
|
@@ -2,5 +2,5 @@ import { OB11GroupNoticeEvent } from './OB11GroupNoticeEvent';
|
||||
|
||||
export class OB11GroupAdminNoticeEvent extends OB11GroupNoticeEvent {
|
||||
notice_type = 'group_admin';
|
||||
sub_type: 'set' | 'unset'; // "set" | "unset"
|
||||
sub_type: 'set' | 'unset' = "set"; // "set" | "unset"
|
||||
}
|
16
src/onebot11/event/notice/OB11InputStatusEvent.ts
Normal file
16
src/onebot11/event/notice/OB11InputStatusEvent.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { OB11BaseNoticeEvent } from './OB11BaseNoticeEvent';
|
||||
//输入状态事件 初步完成 Mlikio wa Todo 需要做一些过滤
|
||||
export class OB11InputStatusEvent extends OB11BaseNoticeEvent {
|
||||
notice_type = 'notify';
|
||||
sub_type = 'input_status';
|
||||
status_text = "对方正在输入..."
|
||||
eventType = 1;
|
||||
user_id = 0;
|
||||
constructor(user_id: number, eventType: number, status_text: string) {
|
||||
super();
|
||||
this.user_id = user_id;
|
||||
this.eventType = eventType;
|
||||
this.status_text = status_text;
|
||||
}
|
||||
}
|
||||
|
@@ -8,7 +8,6 @@ export interface MsgEmojiLike {
|
||||
export class OB11GroupMsgEmojiLikeEvent extends OB11GroupNoticeEvent {
|
||||
notice_type = 'group_msg_emoji_like';
|
||||
message_id: number;
|
||||
sub_type: 'ban' | 'lift_ban';
|
||||
likes: MsgEmojiLike[];
|
||||
|
||||
constructor(groupId: number, userId: number, messageId: number, likes: MsgEmojiLike[]) {
|
||||
|
@@ -1,6 +1,4 @@
|
||||
import { OB11BaseNoticeEvent } from './OB11BaseNoticeEvent';
|
||||
import { selfInfo } from '@/core/data';
|
||||
import { OB11BaseEvent } from '../OB11BaseEvent';
|
||||
|
||||
class OB11PokeEvent extends OB11BaseNoticeEvent {
|
||||
notice_type = 'notify';
|
||||
|
@@ -33,6 +33,7 @@ import { logMessage, logNotice, logRequest } from '@/onebot11/log';
|
||||
import { OB11Message } from '@/onebot11/types';
|
||||
import { isEqual } from '@/common/utils/helper';
|
||||
import { MessageUnique } from '@/common/utils/MessageUnique';
|
||||
import { OB11InputStatusEvent } from './event/notice/OB11InputStatusEvent';
|
||||
|
||||
//下面几个其实应该移进Core-Data 缓存实现 但是现在在这里方便
|
||||
//
|
||||
@@ -92,6 +93,21 @@ export class NapCatOnebot11 {
|
||||
}
|
||||
// Create MsgListener
|
||||
const msgListener = new MsgListener();
|
||||
msgListener.onInputStatusPush = async (data: {
|
||||
chatType: number;
|
||||
eventType: number;
|
||||
fromUin: string;
|
||||
interval: string;
|
||||
showTime: string;
|
||||
statusText: string;
|
||||
timestamp: string;
|
||||
toUin: string;
|
||||
}
|
||||
) => {
|
||||
let uin = await NTQQUserApi.getUinByUid(data.fromUin);
|
||||
logNotice(`[输入状态] ${uin} ${data.statusText}`);
|
||||
postOB11Event(new OB11InputStatusEvent(parseInt(uin), data.eventType, data.statusText));
|
||||
}
|
||||
msgListener.onRecvSysMsg = async (protobufData: number[]) => {
|
||||
// function buf2hex(buffer: Buffer) {
|
||||
// return [...new Uint8Array(buffer)]
|
||||
|
@@ -159,7 +159,7 @@ async function handleMsg(msg: OB11Message, quickAction: QuickAction) {
|
||||
}
|
||||
}
|
||||
replyMessage = replyMessage.concat(normalize(reply, quickAction.auto_escape));
|
||||
const { sendElements, deleteAfterSentFiles } = await createSendElements(replyMessage, group);
|
||||
const { sendElements, deleteAfterSentFiles } = await createSendElements(replyMessage, peer);
|
||||
sendMsg(peer, sendElements, deleteAfterSentFiles, false).then().catch(logError);
|
||||
}
|
||||
}
|
||||
|
@@ -1 +1 @@
|
||||
export const version = '1.8.1';
|
||||
export const version = '1.8.3';
|
||||
|
@@ -29,7 +29,7 @@ async function onSettingWindowCreated(view: Element) {
|
||||
SettingItem(
|
||||
'<span id="napcat-update-title">Napcat</span>',
|
||||
undefined,
|
||||
SettingButton('V1.8.1', 'napcat-update-button', 'secondary')
|
||||
SettingButton('V1.8.3', 'napcat-update-button', 'secondary')
|
||||
),
|
||||
]),
|
||||
SettingList([
|
||||
|
@@ -163,7 +163,7 @@ async function onSettingWindowCreated(view) {
|
||||
SettingItem(
|
||||
'<span id="napcat-update-title">Napcat</span>',
|
||||
void 0,
|
||||
SettingButton("V1.8.1", "napcat-update-button", "secondary")
|
||||
SettingButton("V1.8.3", "napcat-update-button", "secondary")
|
||||
)
|
||||
]),
|
||||
SettingList([
|
||||
|
@@ -26,9 +26,9 @@ if (process.env.NAPCAT_BUILDSYS == 'linux') {
|
||||
} else if (process.env.NAPCAT_BUILDSYS == 'win32') {
|
||||
if (process.env.NAPCAT_BUILDARCH == 'x64') {
|
||||
}
|
||||
startScripts = ['./script/dbghelp.dll', './script/BootWay05.ps1', './script/napcat-9912.ps1', './script/napcat-9912-utf8.ps1', './script/napcat-9912.bat', './script/napcat-9912-utf8.bat'];
|
||||
startScripts = ['./script/BootWay05.bat', './script/BootWay05.utf8.bat', './script/dbghelp.dll', './script/BootWay05.ps1', './script/napcat-9912.ps1', './script/napcat-9912-utf8.ps1', './script/napcat-9912.bat', './script/napcat-9912-utf8.bat'];
|
||||
} else {
|
||||
startScripts = ['./script/dbghelp.dll', './script/BootWay05.ps1', './script/napcat.sh', './script/napcat.ps1', './script/napcat.bat', './script/napcat-utf8.bat', './script/napcat-utf8.ps1', './script/napcat-log.ps1', './script/napcat-9912.ps1', './script/napcat-9912-utf8.ps1', './script/napcat-9912.bat', './script/napcat-9912-utf8.bat'];
|
||||
startScripts = ['./script/BootWay05.bat', './script/BootWay05.utf8.bat', './script/dbghelp.dll', './script/BootWay05.ps1', './script/napcat.sh', './script/napcat.ps1', './script/napcat.bat', './script/napcat-utf8.bat', './script/napcat-utf8.ps1', './script/napcat-log.ps1', './script/napcat-9912.ps1', './script/napcat-9912-utf8.ps1', './script/napcat-9912.bat', './script/napcat-9912-utf8.bat'];
|
||||
}
|
||||
|
||||
const baseConfigPlugin: PluginOption[] = [
|
||||
|
Reference in New Issue
Block a user