Compare commits

...

22 Commits

Author SHA1 Message Date
手瓜一十雪
cdcb51ebe4 build: v2.0.24 2024-08-15 20:11:45 +08:00
手瓜一十雪
0b11786d7d fix 2024-08-15 20:10:35 +08:00
手瓜一十雪
1742247a9a build: fix 2024-08-15 19:40:33 +08:00
手瓜一十雪
42bad123b2 chore: 优化一处逻辑 2024-08-15 19:37:06 +08:00
手瓜一十雪
2d1e87defc chore: 代码质量提高 2024-08-15 19:34:05 +08:00
手瓜一十雪
1c6f783a07 chore: 移除错误推断 2024-08-15 19:27:28 +08:00
手瓜一十雪
6aafc097d5 chore: 废弃无用代码 2024-08-15 19:26:32 +08:00
手瓜一十雪
4010f233dd chore: 移除废弃函数 2024-08-15 19:04:14 +08:00
手瓜一十雪
75f67caa1b release: v2.0.23 2024-08-15 18:46:26 +08:00
手瓜一十雪
d760ce54b7 chore: 重构文件处理 2024-08-15 18:44:29 +08:00
手瓜一十雪
956976ebd5 fix 2024-08-15 17:10:18 +08:00
手瓜一十雪
f9c2d4ca6c fix 2024-08-15 17:07:26 +08:00
手瓜一十雪
dd5cc3c38c fix 2024-08-15 17:04:34 +08:00
手瓜一十雪
daed4cc13e fix 2024-08-15 17:03:55 +08:00
手瓜一十雪
6ff614dd18 fix 2024-08-15 16:56:03 +08:00
手瓜一十雪
eb70ac4266 release 2024-08-15 16:51:31 +08:00
手瓜一十雪
a3a431adb7 fix 2024-08-15 16:45:24 +08:00
手瓜一十雪
e12c72ab98 action fix 2024-08-15 16:41:47 +08:00
手瓜一十雪
9f8549b831 build: 2.0.22 2024-08-15 16:34:50 +08:00
手瓜一十雪
b2de256f87 release: 2.0.22 2024-08-15 16:15:33 +08:00
手瓜一十雪
7f32a5cf9e build: test 2024-08-15 12:28:51 +08:00
手瓜一十雪
56f8314d29 chore: 进一步清理无用代码 2024-08-15 11:10:02 +08:00
15 changed files with 151 additions and 226 deletions

View File

@@ -98,11 +98,16 @@ jobs:
- name: Compress subdirectories
run: |
for dir in */; do
base=$(basename "$dir")
zip -r "${base}.zip" "$dir"
done
cd ./NapCat.Shell/
zip -q -r NapCat.Shell.zip *
cd ..
cd ./NapCat.Framework/
zip -q -r NapCat.Framework.zip *
cd ..
rm ./NapCat.Shell.zip -rf
rm ./NapCat.Framework.zip -rf
mv ./NapCat.Shell/NapCat.Shell.zip ./
mv ./NapCat.Framework/NapCat.Framework.zip ./
- name: Extract version from tag
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV
@@ -118,6 +123,4 @@ jobs:
files: |
NapCat.Framework.zip
NapCat.Shell.zip
# NapCat.darwin.x64.zip
# NapCat.darwin.arm64.zip
draft: true

View File

@@ -4,7 +4,7 @@
"name": "NapCatQQ",
"slug": "NapCat.Framework",
"description": "高性能的 OneBot 11 协议实现",
"version": "2.0.21",
"version": "2.0.24",
"icon": "./logo.png",
"authors": [
{

View File

@@ -2,7 +2,7 @@
"name": "napcat",
"private": true,
"type": "module",
"version": "2.0.21",
"version": "2.0.24",
"scripts": {
"build:framework": "vite build --mode framework",
"build:shell": "vite build --mode shell",

View File

@@ -2,7 +2,7 @@ import path, { dirname } from 'path';
import { fileURLToPath } from 'url';
import fs from 'fs';
export const napcat_version = '2.0.21';
export const napcat_version = '2.0.24';
export class NapCatPathWrapper {
binaryPath: string;

View File

@@ -1,10 +1,9 @@
import fs from 'fs';
import fsPromise, { stat } from 'fs/promises';
import { stat } from 'fs/promises';
import crypto, { randomUUID } from 'crypto';
import util from 'util';
import path from 'node:path';
import * as fileType from 'file-type';
import { LogWrapper } from './log';
export function isGIF(path: string) {
const buffer = Buffer.alloc(4);
@@ -13,7 +12,6 @@ export function isGIF(path: string) {
fs.closeSync(fd);
return buffer.toString() === 'GIF8';
}
// 定义一个异步函数来检查文件是否存在
export function checkFileReceived(path: string, timeout: number = 3000): Promise<void> {
return new Promise((resolve, reject) => {
@@ -94,7 +92,6 @@ export async function file2base64(path: string) {
return result;
}
export function calculateFileMD5(filePath: string): Promise<string> {
return new Promise((resolve, reject) => {
// 创建一个流式读取器
@@ -166,136 +163,98 @@ type Uri2LocalRes = {
isLocal: boolean
}
export async function uri2local(TempDir: string, UriOrPath: string, fileName: string | null = null): Promise<Uri2LocalRes> {
const res = {
success: false,
errMsg: '',
fileName: '',
ext: '',
path: '',
isLocal: false,
};
if (!fileName) fileName = randomUUID();
let filePath = path.join(TempDir, fileName);//临时目录
let url = null;
//区分path和uri
export async function checkFileV2(filePath: string) {
try {
if (fs.existsSync(UriOrPath)) url = new URL('file://' + UriOrPath);
} catch (error: any) {
const ext: string | undefined = (await fileType.fileTypeFromFile(filePath))?.ext;
if (ext) {
fs.renameSync(filePath, filePath + `.${ext}`);
filePath += `.${ext}`;
return { success: true, ext: ext, path: filePath };
}
} catch (e) {
// log("获取文件类型失败", filePath,e.stack)
}
return { success: false, ext: '', path: filePath };
}
export enum FileUriType {
Unknown = 0,
Local = 1,
Remote = 2,
Base64 = 3
}
export async function checkUriType(Uri: string) {
//先判断是否是本地文件
try {
if (fs.existsSync(Uri)) return { Uri: Uri, Type: FileUriType.Local };
} catch (error) {
}
try {
url = new URL(UriOrPath);
} catch (error: any) {
}
//验证url
if (!url) {
res.errMsg = `UriOrPath ${UriOrPath} 解析失败,可能${UriOrPath}不存在`;
return res;
}
if (url.protocol == 'base64:') {
// base64转成文件
const base64Data = UriOrPath.split('base64://')[1];
try {
const buffer = Buffer.from(base64Data, 'base64');
fs.writeFileSync(filePath, buffer);
} catch (e: any) {
res.errMsg = 'base64文件下载失败,' + e.toString();
return res;
//再判断是否是Http
if (Uri.startsWith('http://') || Uri.startsWith('https://')) {
return { Uri: Uri, Type: FileUriType.Remote };
}
} else if (url.protocol == 'http:' || url.protocol == 'https:') {
// 下载文件
let buffer: Buffer | null = null;
try {
buffer = await httpDownload(UriOrPath);
} catch (e: any) {
res.errMsg = `${url}下载失败,` + e.toString();
return res;
//再判断是否是Base64
if (Uri.startsWith('base64://')) {
return { Uri: Uri, Type: FileUriType.Base64 };
}
try {
const pathInfo = path.parse(decodeURIComponent(url.pathname));
if (pathInfo.name) {
fileName = pathInfo.name;
if (pathInfo.ext) {
fileName += pathInfo.ext;
// res.ext = pathInfo.ext
}
}
fileName = fileName.replace(/[/\\:*?"<>|]/g, '_');
res.fileName = fileName;
filePath = path.join(TempDir, randomUUID() + fileName);
fs.writeFileSync(filePath, buffer);
} catch (e: any) {
res.errMsg = `${url}下载失败,` + e.toString();
return res;
}
} else {
let pathname: string;
if (url.protocol === 'file:') {
if (Uri.startsWith('file://')) {
let pathname: string;
let filePath: string;
// await fs.copyFile(url.pathname, filePath);
pathname = decodeURIComponent(url.pathname);
pathname = decodeURIComponent(new URL(Uri).pathname);
if (process.platform === 'win32') {
filePath = pathname.slice(1);
} else {
filePath = pathname;
}
} else {
// 26702执行forword file文件操作 不应该在这里乱来
// const cache = await dbUtil.getFileCacheByName(uri);
// if (cache) {
// filePath = cache.path;
// } else {
// filePath = uri;
// }
}
res.isLocal = true;
}
// else{
// res.errMsg = `不支持的file协议,` + url.protocol
// return res
// }
// if (isGIF(filePath) && !res.isLocal) {
// await fs.rename(filePath, filePath + ".gif");
// filePath += ".gif";
// }
if (!res.isLocal && !res.ext) {
try {
const ext: string | undefined = (await fileType.fileTypeFromFile(filePath))?.ext;
if (ext) {
fs.renameSync(filePath, filePath + `.${ext}`);
filePath += `.${ext}`;
res.fileName += `.${ext}`;
res.ext = ext;
}
} catch (e) {
// log("获取文件类型失败", filePath,e.stack)
}
}
res.success = true;
res.path = filePath;
return res;
}
export async function copyFolder(sourcePath: string, destPath: string, logger: LogWrapper) {
try {
const entries = await fsPromise.readdir(sourcePath, { withFileTypes: true });
await fsPromise.mkdir(destPath, { recursive: true });
for (const entry of entries) {
const srcPath = path.join(sourcePath, entry.name);
const dstPath = path.join(destPath, entry.name);
if (entry.isDirectory()) {
await copyFolder(srcPath, dstPath, logger);
} else {
try {
await fsPromise.copyFile(srcPath, dstPath);
} catch (error) {
logger.logError(`无法复制文件 '${srcPath}' 到 '${dstPath}': ${error}`);
// 这里可以决定是否要继续复制其他文件
}
}
return { Uri: filePath, Type: FileUriType.Local };
}
} catch (error) {
logger.logError('复制文件夹时出错:', error);
}
return { Uri: Uri, Type: FileUriType.Unknown };
}
export async function uri2local(dir: string, uri: string, filename: string | undefined = undefined): Promise<Uri2LocalRes> {
const { Uri: HandledUri, Type: UriType } = await checkUriType(uri);
//解析失败
if (UriType == FileUriType.Unknown) {
return { success: false, errMsg: '未知文件类型', fileName: '', ext: '', path: '', isLocal: false };
}
//解析File协议和本地文件
if (UriType == FileUriType.Local) {
const fileExt = path.extname(HandledUri);
const filename = path.basename(HandledUri, fileExt);
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: HandledUri, isLocal: true };
}
//接下来都要有文件名
if (!filename) filename = randomUUID();
//解析Http和Https协议
if (UriType == FileUriType.Remote) {
const fileExt = path.extname(HandledUri);
const fileName = filename + fileExt;
const filePath = path.join(dir, fileName);
const buffer = await httpDownload(HandledUri);
fs.writeFileSync(filePath, buffer);
return { success: true, errMsg: '', fileName: fileName, ext: fileExt, path: filePath, isLocal: true };
}
//解析Base64
if (UriType == FileUriType.Base64) {
const base64 = HandledUri.replace(/^base64:\/\//, '');
const buffer = Buffer.from(base64, 'base64');
let filePath = path.join(dir, filename);
let fileExt = '';
fs.writeFileSync(filePath, buffer);
const { success, ext, path: fileTypePath } = await checkFileV2(filePath);
if (success) {
filePath = fileTypePath;
fileExt = ext;
filename = path.basename(filePath, fileExt);
}
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath, isLocal: true };
}
return { success: false, errMsg: '未知文件类型', fileName: '', ext: '', path: '', isLocal: false };
}

View File

@@ -53,12 +53,6 @@ export async function runAllWithTimeout<T>(tasks: Promise<T>[], timeout: number)
.map((result) => (result as { status: 'fulfilled'; value: T }).value);
}
export function getMd5(s: string) {
const h = crypto.createHash('md5');
h.update(s);
return h.digest('hex');
}
export function isNull(value: any) {
return value === undefined || value === null;
}
@@ -137,28 +131,6 @@ export function getQQVersionConfigPath(exePath: string = ''): string | undefined
return configVersionInfoPath;
}
export async function deleteOldFiles(directoryPath: string, daysThreshold: number) {
try {
const files = await fsPromise.readdir(directoryPath);
for (const file of files) {
const filePath = path.join(directoryPath, file);
const stats = await fsPromise.stat(filePath);
const lastModifiedTime = stats.mtimeMs;
const currentTime = Date.now();
const timeDifference = currentTime - lastModifiedTime;
const daysDifference = timeDifference / (1000 * 60 * 60 * 24);
if (daysDifference > daysThreshold) {
await fsPromise.unlink(filePath); // Delete the file
//console.log(`Deleted: ${filePath}`);
}
}
} catch (error) {
//console.error('Error deleting files:', error);
}
}
export function calcQQLevel(level: QQLevel) {
const { crownNum, sunNum, moonNum, starNum } = level;
return crownNum * 64 + sunNum * 16 + moonNum * 4 + starNum;

View File

@@ -1,4 +1,4 @@
import { ChatType, GetFileListParam, Peer, RawMessage, SendMessageElement } from '@/core/entities';
import { ChatType, GetFileListParam, Peer, RawMessage, SendMessageElement, SendStatusType } from '@/core/entities';
import { InstanceContext, NapCatCore } from '@/core';
import { onGroupFileInfoUpdateParamType } from '@/core/listeners';
import { GeneralCallResult } from '@/core/services/common';
@@ -171,7 +171,7 @@ export class NTQQMsgApi {
timeout,
(msgRecords: RawMessage[]) => {
for (const msgRecord of msgRecords) {
if (msgRecord.guildId === msgId && msgRecord.sendStatus === 2) {
if (msgRecord.guildId === msgId && msgRecord.sendStatus === SendStatusType.KSEND_STATUS_SUCCESS) {
return true;
}
}

View File

@@ -127,25 +127,7 @@ export class NTQQUserApi {
}
async getUserDetailInfo(uid: string) {
if (this.context.basicInfoWrapper.requireMinNTQQBuild('26702')) {
return this.fetchUserDetailInfo(uid);
}
return this.getUserDetailInfoOld(uid);
}
async getUserDetailInfoOld(uid: string) {
type EventService = NodeIKernelProfileService['getUserDetailInfoWithBizInfo'];
type EventListener = NodeIKernelProfileListener['onProfileDetailInfoChanged'];
const [_retData, profile] = await this.core.eventWrapper.CallNormalEvent<EventService, EventListener>(
'NodeIKernelProfileService/getUserDetailInfoWithBizInfo',
'NodeIKernelProfileListener/onProfileDetailInfoChanged',
2,
5000,
(profile) => profile.uid === uid,
uid,
[0],
);
return profile;
return this.fetchUserDetailInfo(uid);
}
async modifySelfProfile(param: ModifyProfileParams) {

View File

@@ -614,13 +614,28 @@ export interface PicElement {
originImageUrl?: string; // http url, 没有hosthost是https://gchat.qpic.cn/, 带download参数的是https://multimedia.nt.qq.com.cn
}
export enum GrayTipElementSubType {
INVITE_NEW_MEMBER = 12,
MEMBER_NEW_TITLE = 17
export enum NTGrayTipElementSubTypeV2 {
GRAYTIP_ELEMENT_SUBTYPE_AIOOP = 15,
GRAYTIP_ELEMENT_SUBTYPE_BLOCK = 14,
GRAYTIP_ELEMENT_SUBTYPE_BUDDY = 5,
GRAYTIP_ELEMENT_SUBTYPE_BUDDYNOTIFY = 9,
GRAYTIP_ELEMENT_SUBTYPE_EMOJIREPLY = 3,
GRAYTIP_ELEMENT_SUBTYPE_ESSENCE = 7,
GRAYTIP_ELEMENT_SUBTYPE_FEED = 6,
GRAYTIP_ELEMENT_SUBTYPE_FEEDCHANNELMSG = 11,
GRAYTIP_ELEMENT_SUBTYPE_FILE = 10,
GRAYTIP_ELEMENT_SUBTYPE_GROUP = 4,
GRAYTIP_ELEMENT_SUBTYPE_GROUPNOTIFY = 8,
GRAYTIP_ELEMENT_SUBTYPE_JSON = 17,
GRAYTIP_ELEMENT_SUBTYPE_LOCALMSG = 13,
GRAYTIP_ELEMENT_SUBTYPE_PROCLAMATION = 2,
GRAYTIP_ELEMENT_SUBTYPE_REVOKE = 1,
GRAYTIP_ELEMENT_SUBTYPE_UNKNOWN = 0,
GRAYTIP_ELEMENT_SUBTYPE_WALLET = 16,
GRAYTIP_ELEMENT_SUBTYPE_XMLMSG = 12,
}
export interface GrayTipElement {
subElementType: GrayTipElementSubType;
subElementType: NTGrayTipElementSubTypeV2;
revokeElement: {
operatorRole: string;
operatorUid: string;
@@ -876,6 +891,12 @@ export enum NTSubMsgType {
KMSGSUBTYPEMIXTEXT = 0,
KMSGSUBTYPETENCENTDOC = 6
}
export enum SendStatusType {
KSEND_STATUS_FAILED = 0,
KSEND_STATUS_SENDING = 1,
KSEND_STATUS_SUCCESS = 2,
KSEND_STATUS_SUCCESS_NOSEQ = 3
}
export interface RawMessage {
parentMsgPeer: Peer;
@@ -935,7 +956,7 @@ export interface RawMessage {
/**
* 消息状态,别人发的 2 是已撤回,自己发的 2 是已发送
*/
sendStatus?: number;
sendStatus?: SendStatusType;
/**
* 撤回时间,"0" 是没有撤回

View File

@@ -56,7 +56,7 @@ const _handlers: {
if (atQQ === 'all') return SendMsgElementConstructor.at(coreContext, atQQ, atQQ, AtType.atAll, '全体成员');
// then the qq is a group member
// Mlikiowa V2.0.21 Refactor Todo
// Mlikiowa V2.0.24 Refactor Todo
const uid = await coreContext.apis.UserApi.getUidByUinV2(`${atQQ}`);
if (!uid) throw new Error('Get Uid Error');
return SendMsgElementConstructor.at(coreContext, atQQ, uid, AtType.atUser, '');
@@ -161,7 +161,7 @@ const _handlers: {
} else {
postData = data;
}
// Mlikiowa V2.0.21 Refactor Todo
// Mlikiowa V2.0.24 Refactor Todo
const signUrl = obContext.configLoader.configData.musicSignUrl;
if (!signUrl) {
if (data.type === 'qq') {

View File

@@ -15,9 +15,9 @@ import {
FaceIndex,
Friend,
FriendV2,
GrayTipElementSubType,
Group,
GroupMember,
NTGrayTipElementSubTypeV2,
Peer,
RawMessage,
SelfInfo,
@@ -161,7 +161,7 @@ export class OB11Constructor {
peerUid: msg.peerUid,
guildId: '',
chatType: msg.chatType,
}, element.replyElement.replayMsgSeq, 1, true, true)).msgList[0];
}, element.replyElement.replayMsgSeq, 1, true, true)).msgList.find(msg => msg.msgRandom === records.msgRandom);
if (!replyMsg || records.msgRandom !== replyMsg.msgRandom) {
replyMsg = (await NTQQMsgApi.getSingleMsg(peer, element.replyElement.replayMsgSeq)).msgList[0];
}
@@ -286,13 +286,13 @@ export class OB11Constructor {
chatType: msg.chatType,
guildId: '',
},
msg.msgId,
msg.msgSeq,
msg.senderUid,
element.elementId,
element.elementType.toString(),
element.pttElement.fileSize || '0',
element.pttElement.fileUuid || '',
msg.msgId,
msg.msgSeq,
msg.senderUid,
element.elementId,
element.elementType.toString(),
element.pttElement.fileSize || '0',
element.pttElement.fileUuid || '',
);
//以uuid作为文件名
} else if (element.arkElement) {
@@ -377,7 +377,7 @@ export class OB11Constructor {
}
for (const element of msg.elements) {
if (element.grayTipElement) {
if (element.grayTipElement.subElementType == GrayTipElementSubType.MEMBER_NEW_TITLE) {
if (element.grayTipElement.subElementType == NTGrayTipElementSubTypeV2.GRAYTIP_ELEMENT_SUBTYPE_JSON) {
const json = JSON.parse(element.grayTipElement.jsonGrayTipElement.jsonStr);
if (element.grayTipElement.jsonGrayTipElement.busiId == 1061) {
@@ -398,7 +398,7 @@ export class OB11Constructor {
}
//下面得改 上面也是错的grayTipElement.subElementType == GrayTipElementSubType.MEMBER_NEW_TITLE
}
if (element.grayTipElement.subElementType == GrayTipElementSubType.INVITE_NEW_MEMBER) {
if (element.grayTipElement.subElementType == NTGrayTipElementSubTypeV2.GRAYTIP_ELEMENT_SUBTYPE_XMLMSG) {
//好友添加成功事件
if (element.grayTipElement.xmlElement.templId === '10229' && msg.peerUin !== '') {
return new OB11FriendAddNoticeEvent(core, parseInt(msg.peerUin));
@@ -417,7 +417,7 @@ export class OB11Constructor {
return;
}
//log("group msg", msg);
// Mlikiowa V2.0.21 Refactor Todo
// Mlikiowa V2.0.24 Refactor Todo
// if (msg.senderUin && msg.senderUin !== '0') {
// const member = await getGroupMember(msg.peerUid, msg.senderUin);
// if (member && member.cardName !== msg.sendMemberName) {
@@ -536,12 +536,13 @@ export class OB11Constructor {
guildId: '',
peerUid: msg.peerUid,
}, msgSeq, 1, true, true)).msgList;
console.log("表情回应消息长度检测", replyMsgList.length)
if (replyMsgList.length < 1) {
return;
}
const replyMsg = replyMsgList[0];
console.log('表情回应消息', msgSeq, ' 结算ID', replyMsg.msgId);
const replyMsg = replyMsgList.reverse()[0];//获取最顶层消息
//console.log('表情回应消息', msgSeq, ' 结算ID', replyMsg.msgId);
return new OB11GroupMsgEmojiLikeEvent(
core,
parseInt(msg.peerUid),
@@ -556,7 +557,7 @@ export class OB11Constructor {
logger.logError('解析表情回应消息失败', e.stack);
}
}
if (grayTipElement.subElementType == GrayTipElementSubType.INVITE_NEW_MEMBER) {
if (grayTipElement.subElementType == NTGrayTipElementSubTypeV2.GRAYTIP_ELEMENT_SUBTYPE_XMLMSG) {
logger.logDebug('收到新人被邀请进群消息', grayTipElement);
const xmlElement = grayTipElement.xmlElement;
if (xmlElement?.content) {
@@ -582,7 +583,7 @@ export class OB11Constructor {
}
}
//代码歧义 GrayTipElementSubType.MEMBER_NEW_TITLE
else if (grayTipElement.subElementType == GrayTipElementSubType.MEMBER_NEW_TITLE) {
else if (grayTipElement.subElementType == NTGrayTipElementSubTypeV2.GRAYTIP_ELEMENT_SUBTYPE_JSON) {
const json = JSON.parse(grayTipElement.jsonGrayTipElement.jsonStr);
if (grayTipElement.jsonGrayTipElement.busiId == 1061) {
//判断业务类型

View File

@@ -8,6 +8,7 @@ import {
MsgListener,
NapCatCore,
RawMessage,
SendStatusType,
} from '@/core';
import { OB11Config, OB11ConfigLoader } from '@/onebot/helper/config';
import { OneBotApiContextType } from '@/onebot/types';
@@ -250,7 +251,7 @@ export class NapCatOneBot11Adapter {
.catch(e => this.context.logger.logError('处理消息失败', e));
for (const msg of msgList.filter(e => e.senderUin == this.core.selfInfo.uin)) {
if (msg.sendStatus == 2 && !msgIdSend.get(msg.msgId)) {
if (msg.sendStatus == SendStatusType.KSEND_STATUS_SUCCESS && !msgIdSend.get(msg.msgId)) {
msgIdSend.put(msg.msgId, true);
// 完成后再post
OB11Constructor.message(this.core, this, msg)
@@ -325,11 +326,6 @@ export class NapCatOneBot11Adapter {
const flag = notify.group.groupCode + '|' + notify.seq + '|' + notify.type;
this.context.logger.logDebug('收到群通知', notify);
// let member2: GroupMember;
// if (notify.user2.uid) {
// member2 = await getGroupMember(notify.group.groupCode, null, notify.user2.uid);
// }
if ([
GroupNotifyTypes.ADMIN_SET,
GroupNotifyTypes.ADMIN_UNSET,
@@ -405,7 +401,7 @@ export class NapCatOneBot11Adapter {
const groupInviteEvent = new OB11GroupRequestEvent(
this.core,
parseInt(notify.group.groupCode),
parseInt(notify.user1.uid),
parseInt(await this.core.apis.UserApi.getUinByUidV2(notify.user1.uid)),
'invite',
notify.postscript,
flag,

View File

@@ -4,6 +4,7 @@ import http from 'http';
import { NapCatCore } from '@/core';
import { OB11Response } from '../action/OB11Response';
import { ActionMap } from '@/onebot/action';
import cors from 'cors';
export class OB11PassiveHttpAdapter implements IOB11NetworkAdapter {
private app: Express | undefined;
@@ -43,21 +44,11 @@ export class OB11PassiveHttpAdapter implements IOB11NetworkAdapter {
this.server?.close();
this.app = undefined;
}
cors(): any {
return (req: Request, res: Response, next: any) => {
if (req.method === 'OPTIONS') {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
}
next();
};
}
private initializeServer() {
this.app = express();
this.server = http.createServer(this.app);
this.app.use(this.cors());
this.app.use(cors());
this.app.use(express.urlencoded({ extended: true, limit: '5000mb' }));
this.app.use((req, res, next) => {
// 兼容处理没有带content-type的请求
@@ -70,7 +61,7 @@ export class OB11PassiveHttpAdapter implements IOB11NetworkAdapter {
next();
});
});
this.app.use((req, res, next) => this.authorize(this.token, req, res, next));
this.app.use((req, res) => this.handleRequest(req, res));

View File

@@ -30,7 +30,7 @@ async function onSettingWindowCreated(view: Element) {
SettingItem(
'<span id="napcat-update-title">Napcat</span>',
undefined,
SettingButton('V2.0.21', 'napcat-update-button', 'secondary'),
SettingButton('V2.0.24', 'napcat-update-button', 'secondary'),
),
]),
SettingList([

View File

@@ -164,7 +164,7 @@ async function onSettingWindowCreated(view) {
SettingItem(
'<span id="napcat-update-title">Napcat</span>',
void 0,
SettingButton("V2.0.21", "napcat-update-button", "secondary")
SettingButton("V2.0.24", "napcat-update-button", "secondary")
)
]),
SettingList([