Compare commits

...

36 Commits

Author SHA1 Message Date
手瓜一十雪
daf42c8203 release: 2.4.2 2024-09-09 15:04:19 +08:00
手瓜一十雪
0a18bae3b5 fix: #351 2024-09-09 15:04:00 +08:00
手瓜一十雪
919705966c build: 2.4.1 2024-09-09 09:19:23 +08:00
手瓜一十雪
2c54aee63e build: test 2024-09-08 21:39:53 +08:00
手瓜一十雪
3f80bdf2a3 fix 2024-09-08 18:29:21 +08:00
手瓜一十雪
1c429b8dd3 fix: type 2024-09-08 18:26:07 +08:00
手瓜一十雪
5669e2b0b7 fix: 跟进实际逻辑 2024-09-08 18:21:55 +08:00
手瓜一十雪
1a6a43babf release: 2.4.0 2024-09-08 10:50:30 +08:00
手瓜一十雪
2650db5ddc fix: 字段V2 2024-09-08 10:48:33 +08:00
手瓜一十雪
255491a107 fix: hex计算问题 2024-09-08 10:41:30 +08:00
手瓜一十雪
5c64147dfa fix: encodeFile 2024-09-08 10:34:49 +08:00
手瓜一十雪
39f4118577 fix: #347 2024-09-08 10:30:30 +08:00
手瓜一十雪
f7f6e4736a fix #349 2024-09-08 10:24:36 +08:00
手瓜一十雪
c635da7ebb style: lint 2024-09-08 10:10:47 +08:00
手瓜一十雪
58124b006a Merge pull request #346 from NapNeko/Refactor-2.4.x
refactor: v2.4.0
2024-09-08 10:08:41 +08:00
手瓜一十雪
563aeccd0f refactor: fileNameEncode 2024-09-08 10:07:49 +08:00
手瓜一十雪
bd1a95a7f5 style: apis 2024-09-07 23:48:41 +08:00
手瓜一十雪
cdb25828f2 chore: code 2024-09-07 23:34:52 +08:00
手瓜一十雪
45803b3b23 Merge branch 'main' into Refactor-2.4.x 2024-09-07 23:34:23 +08:00
手瓜一十雪
0e5e3d3383 refactor: Service 2024-09-07 23:33:40 +08:00
Wesley F. Young
4672930037 update: move to recallMsg(V2) 2024-09-07 23:28:35 +08:00
手瓜一十雪
09be7131c3 refactor: 整理Service 2024-09-07 23:07:24 +08:00
手瓜一十雪
a804f90b9c refactor: adapter 2024-09-07 22:58:29 +08:00
手瓜一十雪
264cb6bbd2 release: 2.3.7 2024-09-07 21:29:22 +08:00
手瓜一十雪
b7772e867b Merge pull request #344 from qhy040404/patch-1
feat: 允许保存的token自动填写
2024-09-07 20:05:25 +08:00
Alen
cc0e77abfb Merge pull request #345 from cnxysoft/upmain
fix: 群成员列表获取
2024-09-07 19:55:41 +08:00
Alen
537d1c6f4f fix: 群成员列表获取
修复部分群成员列表返回为空的问题
2024-09-07 19:54:46 +08:00
Seijo Cecilia
80facadd67 chore: fix prefer-const 2024-09-07 19:49:54 +08:00
Seijo Cecilia
ba097dad23 update: recallMsgV2 2024-09-07 19:49:18 +08:00
qhy040404
c13c15d046 feat: 允许保存的token自动填写 2024-09-07 19:37:39 +08:00
手瓜一十雪
4f52128a06 fix 2024-09-07 17:17:07 +08:00
手瓜一十雪
500b2d0e6d release: 2.3.6 2024-09-07 13:31:32 +08:00
手瓜一十雪
e59d094feb feat: 提升使用体验 2024-09-07 10:45:45 +08:00
手瓜一十雪
a8372f14f8 fix: member info 2024-09-07 09:18:29 +08:00
Wesley F. Young
5174ff422d update: optimize message logging to console 2024-09-07 01:29:50 +08:00
Wesley F. Young
5c06751c3b fix: reference error 2024-09-07 00:04:35 +08:00
67 changed files with 385 additions and 455 deletions

View File

@@ -28,10 +28,12 @@ NapCatQQ (aka 猫猫框架) 是现代化的基于 NTQQ 的 Bot 协议端实现
[Telegram Link](https://t.me/+nLZEnpne-pQ1OWFl)
## 猫猫朋友
感谢 [LLOneBot](https://github.com/LLOneBot/LLOneBot) 提供初始版本基础
感谢 [LLOneBot](https://github.com/LLOneBot/LLOneBot) 提供部分参考
感谢 [Lagrange](https://github.com/LagrangeDev/Lagrange.Core) 对本项目的大力支持
不过最最重要的 还是需要感谢屏幕前的你哦~
---
## 约法三章

View File

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

View File

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

View File

@@ -215,6 +215,10 @@ export async function checkUriType(Uri: string) {
}
return { Uri: filePath, Type: FileUriType.Local };
}
if (uri.startsWith('data:')) {
const data = uri.split(',')[1];
if (data) return { Uri: data, Type: FileUriType.Base64 };
}
}, Uri);
if (OtherFileRet) return OtherFileRet;
@@ -231,7 +235,8 @@ export async function uri2local(dir: string, uri: string, filename: string | und
//解析File协议和本地文件
if (UriType == FileUriType.Local) {
const fileExt = path.extname(HandledUri);
const filename = path.basename(HandledUri, fileExt);
let filename = path.basename(HandledUri, fileExt);
filename += fileExt;
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: HandledUri, isLocal: true };
}
//接下来都要有文件名
@@ -251,7 +256,7 @@ export async function uri2local(dir: string, uri: string, filename: string | und
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 };
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath, isLocal: false };
}
//解析Base64
if (UriType == FileUriType.Base64) {
@@ -266,7 +271,7 @@ export async function uri2local(dir: string, uri: string, filename: string | und
fileExt = ext;
filename = filename + '.' + ext;
}
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath, isLocal: true };
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath, isLocal: false };
}
return { success: false, errMsg: '未知文件类型', fileName: '', ext: '', path: '', isLocal: false };
}

View File

@@ -25,8 +25,13 @@ export async function solveAsyncProblem<T extends (...args: any[]) => Promise<an
}
export class FileNapCatOneBotUUID {
static encodeModelId(peer: Peer, modelId: string, fileId: string): string {
return `NapCatOneBot|ModelIdFile|${peer.chatType}|${peer.peerUid}|${modelId}|${fileId}`;
static encodeModelId(peer: Peer, modelId: string, fileId: string, endString: string = ""): string {
const data = `NapCatOneBot|ModelIdFile|${peer.chatType}|${peer.peerUid}|${modelId}|${fileId}`;
//前四个字节塞data长度
const length = Buffer.alloc(4 + data.length);
length.writeUInt32BE(data.length * 2, 0);//储存data的hex长度
length.write(data, 4);
return length.toString('hex') + endString;
}
static decodeModelId(uuid: string): undefined | {
@@ -34,8 +39,14 @@ export class FileNapCatOneBotUUID {
modelId: string,
fileId: string
} {
if (!uuid.startsWith('NapCatOneBot|ModelIdFile|')) return undefined;
const data = uuid.split('|');
//前四个字节是data长度
const length = Buffer.from(uuid.slice(0, 8), 'hex').readUInt32BE(0);
//根据length计算需要读取的长度
const dataId = uuid.slice(8, 8 + length);
//hex还原为string
const realData = Buffer.from(dataId, 'hex').toString();
if (!realData.startsWith('NapCatOneBot|ModelIdFile|')) return undefined;
const data = realData.split('|');
if (data.length !== 6) return undefined;
const [, , chatType, peerUid, modelId, fileId] = data;
return {
@@ -48,8 +59,14 @@ export class FileNapCatOneBotUUID {
};
}
static encode(peer: Peer, msgId: string, elementId: string): string {
return `NapCatOneBot|MsgFile|${peer.chatType}|${peer.peerUid}|${msgId}|${elementId}`;
static encode(peer: Peer, msgId: string, elementId: string, endString: string = ""): string {
const data = `NapCatOneBot|MsgFile|${peer.chatType}|${peer.peerUid}|${msgId}|${elementId}`;
//前四个字节塞data长度
//一个字节8位 一个ascii字符1字节 一个hex字符4位 表示一个ascii字符需要两个hex字符
const length = Buffer.alloc(4 + data.length);
length.writeUInt32BE(data.length * 2, 0);
length.write(data, 4);
return length.toString('hex') + endString;
}
static decode(uuid: string): undefined | {
@@ -57,8 +74,14 @@ export class FileNapCatOneBotUUID {
msgId: string,
elementId: string
} {
if (!uuid.startsWith('NapCatOneBot|MsgFile|')) return undefined;
const data = uuid.split('|');
//前四个字节是data长度
const length = Buffer.from(uuid.slice(0, 8), 'hex').readUInt32BE(0);
//根据length计算需要读取的长度
const dataId = uuid.slice(8, 8 + length);
//hex还原为string
const realData = Buffer.from(dataId, 'hex').toString();
if (!realData.startsWith('NapCatOneBot|MsgFile|')) return undefined;
const data = realData.split('|');
if (data.length !== 6) return undefined;
const [, , chatType, peerUid, msgId, elementId] = data;
return {

View File

@@ -167,7 +167,8 @@ export function rawMessageToText(msg: RawMessage, recursiveLevel = 0): string {
function msgElementToText(element: MessageElement) {
if (element.textElement) {
if (element.textElement.atType === AtType.notAt) {
return element.textElement.content;
const originalContentLines = element.textElement.content.split('\n');
return `${originalContentLines[0]}${originalContentLines.length > 1 ? ' ...' : ''}`;
} else if (element.textElement.atType === AtType.atAll) {
return `@全体成员`;
} else if (element.textElement.atType === AtType.atUser) {
@@ -189,7 +190,7 @@ export function rawMessageToText(msg: RawMessage, recursiveLevel = 0): string {
}
if (element.picElement) {
return `[图片 ${element.picElement.fileName}]`;
return '[图片]';
}
if (element.fileElement) {
@@ -197,7 +198,7 @@ export function rawMessageToText(msg: RawMessage, recursiveLevel = 0): string {
}
if (element.videoElement) {
return `[视频 ${element.videoElement.fileName}]`;
return '[视频]';
}
if (element.pttElement) {
@@ -205,7 +206,7 @@ export function rawMessageToText(msg: RawMessage, recursiveLevel = 0): string {
}
if (element.arkElement) {
return `[卡片消息 ${element.arkElement.bytesData}]`;
return '[卡片消息]';
}
if (element.faceElement) {
@@ -213,19 +214,19 @@ export function rawMessageToText(msg: RawMessage, recursiveLevel = 0): string {
}
if (element.marketFaceElement) {
return `[商城表情 ${element.marketFaceElement.faceName}]`;
return element.marketFaceElement.faceName;
}
if (element.markdownElement) {
return `[Markdown ${element.markdownElement.content}]`;
return '[Markdown 消息]';
}
if (element.multiForwardMsgElement) {
return `[转发消息]`;
return '[转发消息]';
}
if (element.elementType === ElementType.GreyTip) {
return `[灰条消息]`; // TODO: resolve the text
return '[灰条消息]';
}
return `[未实现 (ElementType = ${element.elementType})]`;

View File

@@ -53,23 +53,23 @@ export class QQBasicInfoWrapper {
//此方法不要直接使用
getQUAInternal() {
switch (systemPlatform) {
case 'linux':
return `V1_LNX_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`;
case 'darwin':
return `V1_MAC_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`;
default:
return `V1_WIN_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`;
case 'linux':
return `V1_LNX_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`;
case 'darwin':
return `V1_MAC_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`;
default:
return `V1_WIN_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`;
}
}
getAppidInternal() {
switch (systemPlatform) {
case 'linux':
return '537243600';
case 'darwin':
return '537243441';
default:
return '537243538';
case 'linux':
return '537243600';
case 'darwin':
return '537243441';
default:
return '537243538';
}
}

View File

@@ -1 +1 @@
export const napCatVersion = '2.3.5';
export const napCatVersion = '2.4.2';

View File

@@ -1,9 +1,8 @@
import { MsfChangeReasonType, MsfStatusType } from "../entities/adapter";
export class NodeIDependsAdapter {
onMSFStatusChange(arg1: number, arg2: number) {
// console.log(arg1, arg2);
// if (arg1 == 2 && arg2 == 2) {
// log("NapCat丢失网络连接,请检查网络")
// }
onMSFStatusChange(statusType: MsfStatusType, changeReasonType: MsfChangeReasonType) {
}
onMSFSsoError(args: unknown) {

View File

@@ -339,12 +339,12 @@ export class NTQQFileApi {
if (!element) {
return '';
}
const url: string = element.originImageUrl!; // 没有域名
const url: string = element.originImageUrl ?? '';
const md5HexStr = element.md5HexStr;
const fileMd5 = element.md5HexStr;
if (url) {
const parsedUrl = new URL(IMAGE_HTTP_HOST + url);//临时解析拼接
const parsedUrl = new URL(IMAGE_HTTP_HOST + url);
const imageAppid = parsedUrl.searchParams.get('appid');
const isNTFlavoredPic = imageAppid && ['1406', '1407'].includes(imageAppid);
if (isNTFlavoredPic) {

View File

@@ -6,14 +6,9 @@ export class NTQQFriendApi {
context: InstanceContext;
core: NapCatCore;
// friends: Map<string, Friend> = new Map<string, FriendV2>();
constructor(context: InstanceContext, core: NapCatCore) {
this.context = context;
this.core = core;
// if (!this.context.basicInfoWrapper.requireMinNTQQBuild('26702')) {
// this.getFriends(true);
// }
}
async getBuddyV2SimpleInfoMap(refresh = false) {

View File

@@ -9,8 +9,9 @@ import {
MemberExtSourceType,
NapCatCore,
} from '@/core';
import { isNumeric } from '@/common/helper';
import { isNumeric, solveAsyncProblem } from '@/common/helper';
import { LimitedHashTable } from '@/common/message-unique';
import { NTEventWrapper } from '@/common/event';
export class NTQQGroupApi {
context: InstanceContext;
@@ -31,6 +32,10 @@ export class NTQQGroupApi {
for (const group of this.groups) {
this.groupCache.set(group.groupCode, group);
}
// let text = await this.context.session.getMsgService().sendSsoCmdReqByContend(
// 'LightAppSvc.mini_app_share.AdaptShareInfo',
// JSON.stringify({ data: 'test' }));
// console.log(text);
this.context.logger.logDebug(`加载${this.groups.length}个群组缓存完成`);
}
@@ -43,8 +48,8 @@ export class NTQQGroupApi {
}, pskey);
}
async clearGroupNotifiesUnreadCount(unk: boolean) {
return this.context.session.getGroupService().clearGroupNotifiesUnreadCount(unk);
async clearGroupNotifiesUnreadCount(uk: boolean) {
return this.context.session.getGroupService().clearGroupNotifiesUnreadCount(uk);
}
async setGroupAvatar(gc: string, filePath: string) {
@@ -60,9 +65,9 @@ export class NTQQGroupApi {
return groupList;
}
async getGroupExtFE0Info(GroupCode: string[], forced = true) {
async getGroupExtFE0Info(groupCode: string[], forced = true) {
return this.context.session.getGroupService().getGroupExt0xEF0Info(
GroupCode,
groupCode,
[],
{
bindGuildId: 1,
@@ -120,8 +125,8 @@ export class NTQQGroupApi {
return group;
}
async getGroupMemberAll(GroupCode: string, forced = false) {
return this.context.session.getGroupService().getAllMemberList(GroupCode, forced);
async getGroupMemberAll(groupCode: string, forced = false) {
return this.context.session.getGroupService().getAllMemberList(groupCode, forced);
}
async getGroupMember(groupCode: string | number, memberUinOrUid: string | number) {
@@ -156,8 +161,8 @@ export class NTQQGroupApi {
}
return member;
}
async getGroupRecommendContactArkJson(GroupCode: string) {
return this.context.session.getGroupService().getGroupRecommendContactArkJson(GroupCode);
async getGroupRecommendContactArkJson(groupCode: string) {
return this.context.session.getGroupService().getGroupRecommendContactArkJson(groupCode);
}
async CreatGroupFileFolder(groupCode: string, folderName: string) {
@@ -173,7 +178,6 @@ export class NTQQGroupApi {
}
async addGroupEssence(GroupCode: string, msgId: string) {
// 需要 ob11msgId -> msgId + (peer) -> msgSeq + msgRandom
const MsgData = await this.context.session.getMsgService().getMsgsIncludeSelf({
chatType: 2,
guildId: '',
@@ -184,7 +188,6 @@ export class NTQQGroupApi {
msgRandom: parseInt(MsgData.msgList[0].msgRandom),
msgSeq: parseInt(MsgData.msgList[0].msgSeq),
};
// GetMsgByShortID(shortID); -> MsgService.getMsgs(Peer,MsgId,1,false); -> 组出参数
return this.context.session.getGroupService().addGroupEssence(param);
}
@@ -202,7 +205,6 @@ export class NTQQGroupApi {
groupCode: GroupCode,
needDeleteLocalMsg: needDeleteLocalMsg,
};
//应该是直接返回不需要Listener的 未经测试 需测试再发布
return this.context.session.getGroupService().quitGroupV2(param);
}
@@ -264,14 +266,34 @@ export class NTQQGroupApi {
}
return member;
}
async getGroupMemberEx(GroupCode: string, uid: string, forced = false, retry = 2) {
const data = await solveAsyncProblem((eventWrapper: NTEventWrapper, GroupCode: string, uid: string, forced = false) => {
return eventWrapper.callNormalEventV2(
'NodeIKernelGroupService/getMemberInfo',
'NodeIKernelGroupListener/onMemberInfoChange',
[GroupCode, [uid], forced],
(ret) => ret.result === 0,
(params, _, members) => params === GroupCode && members.size > 0 && members.has(uid),
1,
forced ? 2500 : 250
);
}, this.core.eventWrapper, GroupCode, uid, forced);
if (data && data[3] instanceof Map && data[3].has(uid)) {
return data[3].get(uid);
}
if (retry > 0) {
const trydata = await this.getGroupMemberEx(GroupCode, uid, true, retry - 1) as GroupMember | undefined;
if (trydata) return trydata;
}
return undefined;
}
async getGroupMembersV2(groupQQ: string, num = 3000): Promise<Map<string, GroupMember>> {
const groupService = this.context.session.getGroupService();
const sceneId = groupService.createMemberListScene(groupQQ, 'groupMemberList_MainWindow');
const listener = this.core.eventWrapper.registerListen(
'NodeIKernelGroupListener/onMemberListChange',
1,
500,
5000,
(params) => params.sceneId === sceneId,
);
try {
@@ -304,8 +326,7 @@ export class NTQQGroupApi {
if (result.errCode !== 0) {
throw new Error('获取群成员列表出错,' + result.errMsg);
}
this.context.logger.logDebug(`获取群(${groupQQ})成员列表结果:`, `members: ${result.result.infos.size}`); //, Array.from(result.result.infos.values()));
this.context.logger.logDebug(`获取群(${groupQQ})成员列表结果:`, `members: ${result.result.infos.size}`);
return result.result.infos;
}
@@ -336,12 +357,12 @@ export class NTQQGroupApi {
return this.context.session.getGroupService().operateSysNotify(
false,
{
'operateType': operateType, // 2 拒绝
'targetMsg': {
'seq': seq, // 通知序列号
'type': type,
'groupCode': groupCode,
'postscript': reason ?? ' ', // 仅传空值可能导致处理失败,故默认给个空格
operateType: operateType, // 2 拒绝
targetMsg: {
seq: seq, // 通知序列号
type: type,
groupCode: groupCode,
postscript: reason ?? ' ', // 仅传空值可能导致处理失败,故默认给个空格
},
});
}
@@ -397,7 +418,6 @@ export class NTQQGroupApi {
}
async getMemberExtInfo(groupCode: string, uin: string) {
// 仅NTQQ 9.9.11 24568测试 容易炸开谨慎使用
return this.context.session.getGroupService().getMemberExtInfo(
{
groupCode: groupCode,

View File

@@ -19,27 +19,16 @@ export class NTQQMsgApi {
return this.context.session.getMsgService().getAioFirstViewLatestMsgs(peer, MsgCount);
}
async getLatestDbMsgs(peer: Peer, MsgCount: number) {
return this.context.session.getMsgService().getLatestDbMsgs(peer, MsgCount);
}
async FetchLongMsg(peer: Peer, msgId: string) {
return this.context.session.getMsgService().fetchLongMsg(peer, msgId);
}
async sendShowInputStatusReq(peer: Peer, eventType: number) {
return this.context.session.getMsgService().sendShowInputStatusReq(peer.chatType, eventType, peer.peerUid);
}
async getMsgEmojiLikesList(peer: Peer, msgSeq: string, emojiId: string, emojiType: string, count: number = 20) {
//注意此处emojiType 可选值一般为1-2 2好像是unicode表情dec值 大部分情况 Taged M likiowa
//注意此处emojiType 可选值一般为1-2 2好像是unicode表情dec值 大部分情况 Taged Mlikiowa
return this.context.session.getMsgService().getMsgEmojiLikesList(peer, msgSeq, emojiId, emojiType, '', false, count);
}
async setEmojiLike(peer: Peer, msgSeq: string, emojiId: string, set: boolean = true) {
// nt_qq//global//nt_data//Emoji//emoji-resource//sysface_res/apng/ 下可以看到所有QQ表情预览
// nt_qq\global\nt_data\Emoji\emoji-resource\face_config.json 里面有所有表情的id, 自带表情id是QSid, 标准emoji表情id是QCid
// 其实以官方文档为准是最好的https://bot.q.qq.com/wiki/develop/api-v2/openapi/emoji/model.html#EmojiType
emojiId = emojiId.toString();
return this.context.session.getMsgService().setMsgEmojiLikes(peer, msgSeq, emojiId, emojiId.length > 3 ? '2' : '1', set);
}
@@ -108,14 +97,6 @@ export class NTQQMsgApi {
async getMsgsBySeqAndCount(peer: Peer, seq: string, count: number, desc: boolean, z: boolean) {
return await this.context.session.getMsgService().getMsgsBySeqAndCount(peer, seq, count, desc, z);
}
async getMsgBySeqList(peer: Peer, msgSeqList: string[]) {
//坏的
return await this.context.session.getMsgService().getMsgsBySeqList(peer, msgSeqList);
}
async getMsgBySeqExFirstMsg(peer: Peer, rootMsgId: string, replyMsgId: string) {
let reply = await this.context.session.getMsgService().getSourceOfReplyMsgV2(peer, rootMsgId, replyMsgId);
console.log(reply);
}
async getMsgExBySeq(peer: Peer, msgSeq: string) {
const DateNow = Math.floor(Date.now() / 1000);
const filterMsgFromTime = (DateNow - 300).toString();
@@ -157,11 +138,16 @@ export class NTQQMsgApi {
return this.context.session.getMsgService().getMsgsIncludeSelf(peer, msgId, count, isReverseOrder);
}
async recallMsg(peer: Peer, msgIds: string[]) {
await this.context.session.getMsgService().recallMsg({
chatType: peer.chatType,
peerUid: peer.peerUid,
}, msgIds);
async recallMsg(peer: Peer, msgId: string) {
await this.core.eventWrapper.callNormalEventV2(
'NodeIKernelMsgService/recallMsg',
'NodeIKernelMsgListener/onMsgInfoListUpdate',
[peer, [msgId]],
() => true,
(updatedList) => updatedList.find(m => m.msgId === msgId && m.recallTime !== '0') !== undefined,
1,
1000,
);
}
async PrepareTempChat(toUserUid: string, GroupCode: string, nickname: string) {
@@ -195,7 +181,7 @@ export class NTQQMsgApi {
await this.PrepareTempChat(peer.peerUid, peer.guildId, member.nick);
}
}
const msgId = await this.generateMsgUniqueId(peer.chatType, await this.getServerTime());
const msgId = await this.generateMsgUniqueId(peer.chatType);
peer.guildId = msgId;
const [, msgList] = await this.core.eventWrapper.callNormalEventV2(
'NodeIKernelMsgService/sendMsg',
@@ -221,12 +207,8 @@ export class NTQQMsgApi {
return msgList.find(msgRecord => msgRecord.guildId === msgId);
}
async generateMsgUniqueId(chatType: number, time: string) {
return this.context.session.getMsgService().generateMsgUniqueId(chatType, time);
}
async getServerTime() {
return this.context.session.getMSFService().getServerTime();
async generateMsgUniqueId(chatType: number) {
return this.context.session.getMsgService().generateMsgUniqueId(chatType, this.context.session.getMSFService().getServerTime());
}
async forwardMsg(srcPeer: Peer, destPeer: Peer, msgIds: string[]) {

View File

@@ -214,11 +214,6 @@ export class NTQQMusicSignApi {
//console.log(MusicReal);
return { ...MusicReal.data, mid: signedMid };
}
async CreateMusicThirdWay1(id: string = '', mid: string = '') {
}
//转换外域名为 https://qq.ugcimg.cn/v1/cpqcbu4b8870i61bde6k7cbmjgejq8mr3in82qir4qi7ielffv5slv8ck8g42novtmev26i233ujtuab6tvu2l2sjgtupfr389191v00s1j5oh5325j5eqi40774jv1i/khovifoh7jrqd6eahoiv7koh8o
//https://cgi.connect.qq.com/qqconnectopen/openapi/change_image_url?url=https://th.bing.com/th?id=OSK.b8ed36f1fb1889de6dc84fd81c187773&w=46&h=46&c=11&rs=1&qlt=80&o=6&dpr=2&pid=SANGAM

View File

@@ -22,7 +22,7 @@ export class NTQQSystemApi {
}
async getOnlineDev() {
return this.context.session.getMsgService().getOnLineDev();
this.context.session.getMsgService().getOnLineDev();
}
async getArkJsonCollection(cid: string) {

View File

@@ -1,7 +1,6 @@
import type { ModifyProfileParams, User } from '@/core/entities';
import { ModifyProfileParams, User, UserDetailSource } from '@/core/entities';
import { RequestUtil } from '@/common/request';
import { ProfileBizType, UserDetailSource } from '@/core/services';
import { InstanceContext, NapCatCore } from '..';
import { InstanceContext, NapCatCore, ProfileBizType } from '..';
import { solveAsyncProblem } from '@/common/helper';
export class NTQQUserApi {

View File

@@ -157,7 +157,7 @@ export class NTQQWebApi {
const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com');
try {
let settings = JSON.stringify({
const settings = JSON.stringify({
is_show_edit_card: is_show_edit_card,
tip_window_type: tip_window_type,
confirm_required: confirm_required
@@ -167,7 +167,7 @@ export class NTQQWebApi {
imgWidth: imgWidth.toString(),
imgHeight: imgHeight.toString(),
};
let ret: SetNoticeRetSuccess = await RequestUtil.HttpGetJson<SetNoticeRetSuccess>(
const ret: SetNoticeRetSuccess = await RequestUtil.HttpGetJson<SetNoticeRetSuccess>(
`https://web.qun.qq.com/cgi-bin/announce/add_qun_notice?${new URLSearchParams({
bkn: this.getBknFromCookie(cookieObject),
qid: GroupCode,

View File

@@ -0,0 +1,11 @@
export enum MsfStatusType {
KUNKNOWN,
KDISCONNECTED,
KCONNECTED
}
export enum MsfChangeReasonType {
KUNKNOWN,
KUSERLOGININ,
KUSERLOGINOUT,
KAUTO
}

View File

@@ -0,0 +1,12 @@
export interface FSABRecentContactParams {
anchorPointContact: {
contactId: string;
sortField: string;
pos: number;
};
relativeMoveCount: number;
listType: number;
count: number;
fetchOld: boolean;
}

View File

@@ -1,4 +1,4 @@
import { GroupMemberRole } from '@/core';
import { GroupMemberRole, Peer } from '@/core';
export interface Peer {
chatType: ChatType;
@@ -934,3 +934,28 @@ export interface RawMessage {
elements: MessageElement[];
}
export interface QueryMsgsParams {
chatInfo: Peer;
filterMsgType: [];
filterSendersUid: string[];
filterMsgFromTime: string;
filterMsgToTime: string;
pageLimit: number;
isReverseOrder: boolean;
isIncludeCurrent: boolean;
}
export interface TmpChatInfoApi {
errMsg: string;
result: number;
tmpChatInfo?: TmpChatInfo;
}
export interface TmpChatInfo {
chatType: number;
fromNick: string;
groupCode: string;
peerUid: string;
sessionType: number;
sig: string;
}

View File

@@ -153,7 +153,10 @@ interface CommonExt {
labels: any[];
qqLevel: QQLevel;
}
export enum BuddyListReqType {
KNOMAL,
KLETTER
}
interface Pic {
picId: string;
picTime: number;
@@ -364,3 +367,15 @@ export interface UserDetailInfoByUin {
vipNameColorId: string
}
}
export enum UserDetailSource {
KDB,
KSERVER
}
export enum ProfileBizType {
KALL,
KBASEEXTEND,
KVAS,
KQZONE,
KOTHER
}

View File

@@ -145,8 +145,10 @@ export class NapCatCore {
if (Info.status == 20) {
this.selfInfo.online = false;
this.context.logger.log("账号状态变更为离线");
return;
} else {
this.selfInfo.online = true;
}
this.selfInfo.online = true;
};
this.context.session.getProfileService().addKernelProfileListener(
proxiedListenerOf(profileListener, this.context.logger),

View File

@@ -1,4 +1,5 @@
export interface NodeIKernelAlbumService {
setAlbumServiceInfo(...args: any[]): unknown;// needs 3 arguments
getMainPage(...args: any[]): unknown;// needs 2 arguments

View File

@@ -1,7 +1,7 @@
export interface NodeIKernelAvatarService {
addAvatarListener(arg: unknown): unknown;
addAvatarListener(listener: unknown): void;
removeAvatarListener(arg: unknown): unknown;
removeAvatarListener(listenerId: number): void;
getAvatarPath(arg1: unknown, arg2: unknown): unknown;

View File

@@ -1,13 +1,8 @@
import { GeneralCallResult } from '@/core/services/common';
import { NodeIKernelBuddyListener } from '@/core/listeners';
export enum BuddyListReqType {
KNOMAL,
KLETTER
}
import { BuddyListReqType } from '../entities/user';
export interface NodeIKernelBuddyService {
// 26702 以上
getBuddyListV2(callFrom: string, reqType: BuddyListReqType): Promise<GeneralCallResult & {
data: Array<{
categoryId: number,
@@ -19,8 +14,7 @@ export interface NodeIKernelBuddyService {
}>
}>;
//26702 以上
getBuddyListFromCache(callFrom: string): Promise<Array<
getBuddyListFromCache(reqType: BuddyListReqType): Promise<Array<
{
categoryId: number,//9999应该跳过 那是兜底数据吧
categorySortId: number,//排序方式
@@ -30,18 +24,13 @@ export interface NodeIKernelBuddyService {
buddyUids: Array<string>//Uids
}>>;
// 以下为原生方法
addKernelBuddyListener(listener: NodeIKernelBuddyListener): number;
getAllBuddyCount(): number;
removeKernelBuddyListener(listener: unknown): void;
removeKernelBuddyListener(listenerId: number): void;
/**
* @deprecated
* @param nocache 使用缓存
*/
getBuddyList(nocache: boolean): Promise<GeneralCallResult>;
//getBuddyList(nocache: boolean): Promise<GeneralCallResult>;
getBuddyNick(uid: number): string;

View File

@@ -1,9 +1,9 @@
import { GeneralCallResult } from './common';
export interface NodeIKernelCollectionService {
addKernelCollectionListener(...args: any[]): unknown;//needs 1 arguments
addKernelCollectionListener(...args: any[]): void;//needs 1 arguments
removeKernelCollectionListener(...args: any[]): unknown;//needs 1 arguments
removeKernelCollectionListener(listenerId: number): void;
getCollectionItemList(param: {
category: number,
@@ -14,46 +14,46 @@ export interface NodeIKernelCollectionService {
count: number,
searchDown: boolean
}): Promise<GeneralCallResult &
{
collectionSearchList: {
collectionItemList: Array<
{
cid: string,
{
collectionSearchList: {
collectionItemList: Array<
{
cid: string,
type: number,
status: number,
author: {
type: number,
status: number,
author: {
type: number,
numId: string,
strId: string,
groupId: string,
groupName: string,
uid: string
},
bid: number,
category: number,
createTime: string,
collectTime: string,
modifyTime: string,
sequence: string,
shareUrl: string,
customGroupId: number,
securityBeat: boolean,
summary: {
textSummary: unknown,
linkSummary: unknown,
gallerySummary: unknown,
audioSummary: unknown,
videoSummary: unknown,
fileSummary: unknown,
locationSummary: unknown,
richMediaSummary: unknown,
}
}>,
hasMore: boolean,
bottomTimeStamp: string
}
numId: string,
strId: string,
groupId: string,
groupName: string,
uid: string
},
bid: number,
category: number,
createTime: string,
collectTime: string,
modifyTime: string,
sequence: string,
shareUrl: string,
customGroupId: number,
securityBeat: boolean,
summary: {
textSummary: unknown,
linkSummary: unknown,
gallerySummary: unknown,
audioSummary: unknown,
videoSummary: unknown,
fileSummary: unknown,
locationSummary: unknown,
richMediaSummary: unknown,
}
}>,
hasMore: boolean,
bottomTimeStamp: string
}
>;//needs 1 arguments
}
>;
getCollectionContent(...args: any[]): unknown;//needs 5 arguments

View File

@@ -1,7 +1,9 @@
export interface NodeIKernelDbToolsService {
depositDatabase(...args: unknown[]): unknown;
backupDatabase(...args: unknown[]): unknown;
retrieveDatabase(...args: unknown[]): unknown;
}

View File

@@ -1,3 +1,2 @@
export interface NodeIKernelECDHService {
}

View File

@@ -11,8 +11,6 @@ import {
} from '@/core/entities';
import { GeneralCallResult } from '@/core/services/common';
//高版本的接口不应该随意使用 使用应该严格进行pr审核 同时部分ipc中未出现的接口不要过于依赖 应该做好数据兜底
export interface NodeIKernelGroupService {
getGroupExt0xEF0Info(enableGroupCodes: string[], bannedGroupCodes: string[], filter: GroupExt0xEF0InfoFilter, forceFetch: boolean):
Promise<GeneralCallResult & { result: { groupExtInfos: Map<string, any> } }>;
@@ -82,11 +80,11 @@ export interface NodeIKernelGroupService {
}): Promise<unknown>;
isEssenceMsg(Req: { groupCode: string, msgRandom: number, msgSeq: number }): Promise<unknown>;
isEssenceMsg(req: { groupCode: string, msgRandom: number, msgSeq: number }): Promise<unknown>;
queryCachedEssenceMsg(Req: { groupCode: string, msgRandom: number, msgSeq: number }): Promise<unknown>;
queryCachedEssenceMsg(req: { groupCode: string, msgRandom: number, msgSeq: number }): Promise<unknown>;
fetchGroupEssenceList(Req: {
fetchGroupEssenceList(req: {
groupCode: string,
pageStart: number,
pageLimit: number
@@ -110,13 +108,12 @@ export interface NodeIKernelGroupService {
addKernelGroupListener(listener: NodeIKernelGroupListener): number;
removeKernelGroupListener(listenerId: unknown): void;
removeKernelGroupListener(listenerId: number): void;
createMemberListScene(groupCode: string, scene: string): string;
destroyMemberListScene(SceneId: string): void;
//About Arg (a) name: lastId 根据手Q来看为object {index:?(number),uid:string}
getNextMemberList(sceneId: string, a: undefined, num: number): Promise<{
errCode: number, errMsg: string,
result: { ids: string[], infos: Map<string, GroupMember>, finish: boolean, hasRobot: boolean }
@@ -247,14 +244,12 @@ export interface NodeIKernelGroupService {
modifyGroupExtInfo(groupCode: string, arg: unknown): void;
//需要提前判断是否存在 高版本新增
addGroupEssence(param: {
groupCode: string
msgRandom: number,
msgSeq: number
}): Promise<unknown>;
//需要提前判断是否存在 高版本新增
removeGroupEssence(param: {
groupCode: string
msgRandom: number,

View File

@@ -59,6 +59,7 @@ export interface QuickLoginResult {
}
export interface NodeIKernelLoginService {
connect(): boolean;
// eslint-disable-next-line @typescript-eslint/no-misused-new
new(): NodeIKernelLoginService;

View File

@@ -1,7 +1,7 @@
export interface NodeIKernelMsgBackupService {
addKernelMsgBackupListener(...args: any[]): unknown;// needs 1 arguments
addKernelMsgBackupListener(listener: unknown): number;
removeKernelMsgBackupListener(...args: any[]): unknown;// needs 1 arguments
removeKernelMsgBackupListener(listenerId: number): void;
getMsgBackupLocation(...args: any[]): unknown;// needs 0 arguments

View File

@@ -1,32 +1,7 @@
import { ElementType, MessageElement, Peer, RawMessage, SendMessageElement } from '@/core/entities';
import { NodeIKernelMsgListener } from '@/core/listeners/NodeIKernelMsgListener';
import { GeneralCallResult } from '@/core/services/common';
export interface QueryMsgsParams {
chatInfo: Peer,
filterMsgType: [],
filterSendersUid: string[],
filterMsgFromTime: string,
filterMsgToTime: string,
pageLimit: number,
isReverseOrder: boolean,
isIncludeCurrent: boolean
}
export interface TmpChatInfoApi {
errMsg: string;
result: number;
tmpChatInfo?: TmpChatInfo;
}
export interface TmpChatInfo {
chatType: number;
fromNick: string;
groupCode: string;
peerUid: string;
sessionType: number;
sig: string;
}
import { QueryMsgsParams, TmpChatInfoApi } from '../entities/msg';
export interface NodeIKernelMsgService {
@@ -76,18 +51,12 @@ export interface NodeIKernelMsgService {
downloadOnlineStatusCommonByUrl(arg0: string, arg1: string): unknown;
// this.tokenType = i2;
// this.apnsToken = bArr;
// this.voipToken = bArr2;
// this.profileId = str;
setToken(arg: unknown): unknown;
switchForeGround(): unknown;
switchBackGround(arg: unknown): unknown;
//hex
setTokenForMqq(token: string): unknown;
switchForeGroundForMqq(...args: unknown[]): unknown;
@@ -124,7 +93,6 @@ export interface NodeIKernelMsgService {
forwardFile(...args: unknown[]): unknown;
//Array<Msg>, Peer from, Peer to
multiForwardMsg(...args: unknown[]): unknown;
multiForwardMsgWithComment(...args: unknown[]): unknown;
@@ -185,11 +153,6 @@ export interface NodeIKernelMsgService {
msgList: RawMessage[]
}>;
// this.$peer = contact;
// this.$msgTime = j2;
// this.$clientSeq = j3;
// this.$cnt = i2;
getMsgsWithMsgTimeAndClientSeqForC2C(...args: unknown[]): Promise<GeneralCallResult & { msgList: RawMessage[] }>;
getMsgsWithStatus(params: {
@@ -226,7 +189,6 @@ export interface NodeIKernelMsgService {
getSourceOfReplyMsgByClientSeqAndTime(peer: Peer, clientSeq: string, time: string): unknown;
//cnt clientSeq?并不是吧
getMsgsByTypeFilter(peer: Peer, msgId: string, cnt: unknown, queryOrder: boolean, typeFilter: {
type: number,
subtype: Array<number>
@@ -241,49 +203,15 @@ export interface NodeIKernelMsgService {
queryMsgsWithFilter(...args: unknown[]): unknown;
/**
* @deprecated 该函数已被标记为废弃,请使用新的替代方法。
* 使用过滤条件查询消息列表的版本2接口。
*
* 该函数通过一系列过滤条件来查询特定聊天中的消息列表。这些条件包括消息类型、发送者、时间范围等。
* 函数返回一个Promise解析为查询结果的未知类型对象。
*
* @param MsgId 消息ID用于特定消息的查询。
* @param MsgTime 消息时间,用于指定消息的时间范围。
* @param param 查询参数对象,包含详细的过滤条件和分页信息。
* @param param.chatInfo 聊天信息包括聊天类型和对方用户ID。
* @param param.filterMsgType 需要过滤的消息类型数组,留空表示不过滤。
* @param param.filterSendersUid 需要过滤的发送者用户ID数组。
* @param param.filterMsgFromTime 查询消息的起始时间。
* @param param.filterMsgToTime 查询消息的结束时间。
* @param param.pageLimit 每页的消息数量限制。
* @param param.isReverseOrder 是否按时间顺序倒序返回消息。
* @param param.isIncludeCurrent 是否包含当前页码。
* @returns 返回一个Promise解析为查询结果的未知类型对象。
*/
queryMsgsWithFilterVer2(MsgId: string, MsgTime: string, param: QueryMsgsParams): Promise<unknown>;
//queryMsgsWithFilterVer2(MsgId: string, MsgTime: string, param: QueryMsgsParams): Promise<unknown>;
// this.chatType = i2;
// this.peerUid = str;
// this.chatInfo = new ChatInfo();
// this.filterMsgType = new ArrayList<>();
// this.filterSendersUid = new ArrayList<>();
// this.chatInfo = chatInfo;
// this.filterMsgType = arrayList;
// this.filterSendersUid = arrayList2;
// this.filterMsgFromTime = j2;
// this.filterMsgToTime = j3;
// this.pageLimit = i2;
// this.isReverseOrder = z;
// this.isIncludeCurrent = z2;
//queryMsgsWithFilterEx(0L, 0L, 0L, new QueryMsgsParams(new ChatInfo(2, str), new ArrayList(), new ArrayList(), 0L, 0L, 250, false, true))
queryMsgsWithFilterEx(msgId: string, msgTime: string, megSeq: string, param: QueryMsgsParams): Promise<GeneralCallResult & {
msgList: RawMessage[]
}>;
//queryMsgsWithFilterEx(this.$msgId, this.$msgTime, this.$msgSeq, this.$param)
queryFileMsgsDesktop(...args: unknown[]): unknown;
queryFileMsgsDesktop(msgId: string, msgTime: string, msgSeq: string, param: QueryMsgsParams): Promise<GeneralCallResult & {
msgList: RawMessage[]
}>;
setMsgRichInfoFlag(...args: unknown[]): unknown;
@@ -390,17 +318,11 @@ export interface NodeIKernelMsgService {
getFileThumbSavePath(...args: unknown[]): unknown;
//猜测居多
translatePtt2Text(MsgId: string, Peer: Peer, MsgElement: unknown): unknown;
translatePtt2Text(msgId: string, peer: Peer, msgElement: unknown): unknown;
setPttPlayedState(...args: unknown[]): unknown;
// NodeIQQNTWrapperSession fetchFavEmojiList [
// "",
// 48,
// true,
// true
// ]
//uk1 uk2 true
fetchFavEmojiList(str: string, num: number, uk1: boolean, uk2: boolean): Promise<GeneralCallResult & {
emojiInfoList: Array<{
uin: string,
@@ -496,7 +418,7 @@ export interface NodeIKernelMsgService {
getFirstUnreadMsgSeq(args: {
peerUid: string
guildId: string
}): unknown;
}): Promise<unknown>;
getFirstUnreadCommonMsg(...args: unknown[]): unknown;
@@ -590,7 +512,7 @@ export interface NodeIKernelMsgService {
getFirstUnreadAtMsg(peer: Peer): unknown;
clearMsgRecords(...args: unknown[]): unknown;//设置已读后调用我觉得比较好 清理记录 现在别了
clearMsgRecords(...args: unknown[]): unknown;
IsExistOldDb(...args: unknown[]): unknown;
@@ -626,25 +548,10 @@ export interface NodeIKernelMsgService {
enterOrExitAio(...args: unknown[]): unknown;
// this.peerUid = "";
// this.peerNickname = "";
// this.fromGroupCode = "";
// this.sig = new byte[0];
// this.selfUid = "";
// this.selfPhone = "";
// this.chatType = i2;
// this.peerUid = str;
// this.peerNickname = str2;
// this.fromGroupCode = str3;
// this.sig = bArr;
// this.selfUid = str4;
// this.selfPhone = str5;
// this.gameSession = tempChatGameSession;
prepareTempChat(args: unknown): unknown;//主动临时消息 不做
prepareTempChat(args: unknown): unknown;
sendSsoCmdReqByContend(cmd: string, param: string): Promise<unknown>;
//chattype,uid->Promise<any>
getTempChatInfo(ChatType: number, Uid: string): Promise<TmpChatInfoApi>;
setContactLocalTop(...args: unknown[]): unknown;
@@ -708,7 +615,6 @@ export interface NodeIKernelMsgService {
dataMigrationStopOperation(...args: unknown[]): unknown;
//新的希望
dataMigrationImportMsgPbRecord(DataMigrationMsgInfo: Array<{
extensionData: string//"Hex"
extraData: string //""
@@ -760,6 +666,6 @@ export interface NodeIKernelMsgService {
getGuildMsgAbFlag(...args: unknown[]): unknown;
getGroupMsgStorageTime(): unknown;//这是嘛啊
getGroupMsgStorageTime(): unknown;
}

View File

@@ -1,6 +1,5 @@
import { GeneralCallResult } from './common';
//没扒干净 因为用不着
export interface NodeIKernelNodeMiscService {
getMiniAppPath(): unknown;
@@ -11,7 +10,4 @@ export interface NodeIKernelNodeMiscService {
SendMiniAppMsg(arg1: string, arg2: string, arg3: string): unknown;
startNewMiniApp(appfile: string, params: string): unknown;
// 我的计划是转发给一个新程序避免吃掉Electron_AS_Node的环境 然后重写启动MiniApp 挂载相应JS脚本 这样有个问题
// 需要自己转发ipc参数 然后必须处在gui环境 且完成校验破解 才能实现发包 有点抽象了
}

View File

@@ -1,8 +1,8 @@
export interface NodeIKernelOnlineStatusService {
addKernelOnlineStatusListener(listener: unknown): void;
addKernelOnlineStatusListener(listener: unknown): number;
removeKernelOnlineStatusListener(listenerId: unknown): void;
removeKernelOnlineStatusListener(listenerId: number): void;
getShouldShowAIOStatusAnimation(arg: unknown): unknown;

View File

@@ -1,17 +1,17 @@
import { BuddyProfileLikeReq, GeneralCallResult } from '@/core';
export interface NodeIKernelProfileLikeService {
addKernelProfileLikeListener(listener: NodeIKernelProfileLikeService): void;
addKernelProfileLikeListener(listener: unknown): number;
removeKernelProfileLikeListener(listener: unknown): void;
removeKernelProfileLikeListener(listenerId: unknown): void;
setBuddyProfileLike(...args: unknown[]): { result: number, errMsg: string, succCounts: number };
getBuddyProfileLike(req: BuddyProfileLikeReq): Promise<GeneralCallResult & {
'info': {
'userLikeInfos': Array<any>,
'friendMaxVotes': number,
'start': number
info: {
userLikeInfos: Array<any>,
friendMaxVotes: number,
start: number
}
}>;

View File

@@ -1,38 +1,21 @@
import { AnyCnameRecord } from 'node:dns';
import { BizKey, ModifyProfileParams, NodeIKernelProfileListener, SimpleInfo, UserDetailInfoByUinV2 } from '@/core';
import { BizKey, ModifyProfileParams, NodeIKernelProfileListener, ProfileBizType, SimpleInfo, UserDetailInfoByUinV2, UserDetailSource } from '@/core';
import { GeneralCallResult } from '@/core/services/common';
export enum UserDetailSource {
KDB,
KSERVER
}
export enum ProfileBizType {
KALL,
KBASEEXTEND,
KVAS,
KQZONE,
KOTHER
}
export interface NodeIKernelProfileService {
getOtherFlag(callfrom: string, uids: string[]): Promise<Map<string, any>>;
getVasInfo(callfrom: string, uids: string[]): Promise<Map<string, any>>;
getUidByUin(callfrom: string, uin: Array<string>): Promise<Map<string, string>>;//uin->uid
getRelationFlag(callfrom: string, uids: string[]): Promise<Map<string, any>>;
getUidByUin(callfrom: string, uin: Array<string>): Promise<Map<string, string>>;
getUinByUid(callfrom: string, uid: Array<string>): Promise<Map<string, string>>;
// {
// coreInfo: CoreInfo,
// baseInfo: BaseInfo,
// status: null,
// vasInfo: null,
// relationFlags: null,
// otherFlags: null,
// intimate: null
// }
getCoreAndBaseInfo(callfrom: string, uids: string[]): Promise<Map<string, SimpleInfo>>;
fetchUserDetailInfo(trace: string, uids: string[], arg2: number, arg3: number[]): Promise<unknown>;
fetchUserDetailInfo(trace: string, uids: string[], source: UserDetailSource, bizType: ProfileBizType[]): Promise<GeneralCallResult>;
addKernelProfileListener(listener: NodeIKernelProfileListener): number;
@@ -44,30 +27,17 @@ export interface NodeIKernelProfileService {
enumCountryOptions(): Array<string>;
enumProvinceOptions(Country: string): Array<string>;
enumProvinceOptions(country: string): Array<string>;
enumCityOptions(Country: string, Province: string): unknown;
enumCityOptions(country: string, province: string): unknown;
enumAreaOptions(...args: unknown[]): unknown;
//SimpleInfo
// this.uid = "";
// this.uid = str;
// this.uin = j2;
// this.isBuddy = z;
// this.coreInfo = coreInfo;
// this.baseInfo = baseInfo;
// this.status = statusInfo;
// this.vasInfo = vasInfo;
// this.relationFlags = relationFlag;
// this.otherFlags = otherFlag;
// this.intimate = intimate;
modifySelfProfile(...args: unknown[]): Promise<unknown>;
modifyDesktopMiniProfile(param: ModifyProfileParams): Promise<GeneralCallResult>;
setNickName(NickName: string): Promise<unknown>;
setNickName(nickName: string): Promise<unknown>;
setLongNick(longNick: string): Promise<unknown>;
@@ -95,14 +65,12 @@ export interface NodeIKernelProfileService {
getSelfStatus(): Promise<unknown>;
//
setdisableEmojiShortCuts(...args: unknown[]): unknown;
getProfileQzonePicInfo(uid: string, type: number, force: boolean): Promise<unknown>;
//profileService.getCoreInfo("UserRemarkServiceImpl::getStrangerRemarkByUid", arrayList);
getCoreInfo(name: string, arg: any[]): unknown;
// UserRemarkServiceImpl::getStrangerRemarkByUid []
getCoreInfo(sceneId: string, arg: any[]): unknown;
//m429253e12.getOtherFlag("FriendListInfoCache_getKernelDataAndPutCache", new ArrayList<>());
isNull(): boolean;
}

View File

@@ -1,30 +1,8 @@
import { ChatType, Peer } from '../entities';
import { NodeIKernelRecentContactListener } from '../listeners/NodeIKernelRecentContactListener';
import { GeneralCallResult } from './common';
import { FSABRecentContactParams } from '../entities/contact';
export interface FSABRecentContactParams {
anchorPointContact: {
contactId: string;
sortField: string;
pos: number;
},
relativeMoveCount: number;
listType: number;
count: number;
fetchOld: boolean;
}
// {
// "anchorPointContact": {
// "contactId": "",
// "sortField": "",
// "pos": 0
// },
// "relativeMoveCount": 0,
// "listType": 1,
// "count": 200,
// "fetchOld": true
// }
export interface NodeIKernelRecentContactService {
setGuildDisplayStatus(...args: unknown[]): unknown; // 2 arguments
@@ -36,7 +14,6 @@ export interface NodeIKernelRecentContactService {
enterOrExitMsgList(...args: unknown[]): unknown; // 1 arguments
/*!---!*/
getRecentContactListSnapShot(count: number): Promise<GeneralCallResult & {
info: {
errCode: number,
@@ -58,7 +35,6 @@ export interface NodeIKernelRecentContactService {
jumpToSpecifyRecentContact(...args: unknown[]): unknown; // 1 arguments
/*!---!*/
fetchAndSubscribeABatchOfRecentContact(params: FSABRecentContactParams): unknown; // 1 arguments
addRecentContact(peer: Peer): unknown;

View File

@@ -99,23 +99,6 @@ export interface NodeIKernelRichMediaService {
getRichMediaFileDir(elementType: number, downType: number, isTemp: boolean): unknown;
// this.senderUid = "";
// this.peerUid = "";
// this.guildId = "";
// this.elem = new MsgElement();
// this.downloadType = i2;
// this.thumbSize = i3;
// this.msgId = j2;
// this.msgRandom = j3;
// this.msgSeq = j4;
// this.msgTime = j5;
// this.chatType = i4;
// this.senderUid = str;
// this.peerUid = str2;
// this.guildId = str3;
// this.elem = msgElement;
// this.useHttps = num;
getVideoPlayUrlInVisit(arg: {
downloadType: number,
thumbSize: number,
@@ -131,7 +114,6 @@ export interface NodeIKernelRichMediaService {
useHttps: boolean
}): Promise<unknown>;
//arg双端number
isFileExpired(arg: number): unknown;
deleteGroupFolder(GroupCode: string, FolderId: string): Promise<GeneralCallResult & {
@@ -154,7 +136,6 @@ export interface NodeIKernelRichMediaService {
useHttps: boolean
}): unknown;
//arg3为“”
downloadFileForModelId(peer: Peer, ModelId: string[], unknown: string): Promise<unknown>;
//第三个参数 Array<Type>

View File

@@ -1,11 +1,12 @@
import { ChatType } from '../entities';
export interface NodeIKernelSearchService {
addKernelSearchListener(...args: any[]): unknown;// needs 1 arguments
removeKernelSearchListener(...args: any[]): unknown;// needs 1 arguments
addKernelSearchListener(listener: unknown): number;
searchStranger(...args: any[]): unknown;// needs 3 arguments
removeKernelSearchListener(listenerId: number): void;
searchStranger(unknown: string, searchStranger: unknown, searchParams: unknown): Promise<unknown>;
searchGroup(...args: any[]): unknown;// needs 1 arguments
@@ -125,4 +126,5 @@ export interface NodeIKernelSearchService {
searchCache(...args: any[]): unknown;// needs 3 arguments
clearSearchCache(...args: any[]): unknown;// needs 1 arguments
}

View File

@@ -3,9 +3,9 @@ import { GeneralCallResult } from './common';
export interface NodeIKernelStorageCleanService {
addKernelStorageCleanListener(Listener: NodeIKernelStorageCleanListener): number;
addKernelStorageCleanListener(listener: NodeIKernelStorageCleanListener): number;
removeKernelStorageCleanListener(ListenerId: number): void;
removeKernelStorageCleanListener(listenerId: number): void;
addCacheScanedPaths(arg: unknown): unknown;

View File

@@ -1,9 +1,7 @@
export interface NodeIKernelTianShuService {
addKernelTianShuListener(...args: any[]): unknown;// needs 1 arguments
addKernelTianShuListener(listener:unknown): number;
removeKernelTianShuListener(...args: any[]): unknown;// needs 1 arguments
requesTianShuNumeralRe(...args: any[]): unknown;//d needs 1 arguments
removeKernelTianShuListener(listenerId:number): void;
reportTianShuNumeralRed(...args: any[]): unknown;// needs 1 arguments

View File

@@ -2,9 +2,9 @@ import { ForceFetchClientKeyRetType } from './common';
export interface NodeIKernelTicketService {
addKernelTicketListener(listener: unknown): void;
addKernelTicketListener(listener: unknown): number;
removeKernelTicketListener(listenerId: unknown): void;
removeKernelTicketListener(listenerId: number): void;
forceFetchClientKey(arg: string): Promise<ForceFetchClientKeyRetType>;

View File

@@ -2,7 +2,7 @@ import { GeneralCallResult } from './common';
export interface NodeIKernelTipOffService {
addKernelTipOffListener(listener: unknown): void;
addKernelTipOffListener(listener: unknown): number;
removeKernelTipOffListener(listenerId: unknown): void;
@@ -10,7 +10,7 @@ export interface NodeIKernelTipOffService {
getPskey(domainList: string[], nocache: boolean): Promise<GeneralCallResult & {
domainPskeyMap: Map<string, string>
}>;//2
}>;
tipOffSendJsData(args: unknown[]): Promise<unknown>;//2

View File

@@ -1,7 +1,8 @@
export interface NodeIKernelUnitedConfigService {
addKernelUnitedConfigListener(...args: any[]): unknown;// needs 1 arguments
removeKernelUnitedConfigListener(...args: any[]): unknown;// needs 1 arguments
addKernelUnitedConfigListener(listener:unknown): number;
removeKernelUnitedConfigListener(listenerId:number): void;
fetchUnitedCommendConfig(...args: any[]): unknown;// needs 1 arguments
@@ -12,4 +13,5 @@ export interface NodeIKernelUnitedConfigService {
isUnitedConfigSwitchOn(...args: any[]): unknown;// needs 1 arguments
registerUnitedConfigPushGroupList(...args: any[]): unknown;// needs 1 arguments
}

View File

@@ -1,5 +1,5 @@
// public interface IYellowFaceForManagerService extends QRouteApi {
// void download(@NotNull String resourceConfigJson, @NotNull String resourceDir, @NotNull String cacheDir, boolean force, @NotNull IKernelYellowFaceDownloadCallback callback);
export interface NodeIYellowFaceService {
download(resourceConfigJson: string, resourceDir: string, cacheDir: string, force: boolean): void;
// void setHistory(@NotNull String fullMd5, @NotNull IOperateCallback callback);
// }
setHistory(fullMd5: string): void;
}

View File

@@ -1,6 +1,7 @@
import { MessageElement, Peer } from '../entities';
export interface NodeIkernelTestPerformanceService {
insertMsg(MsgParam: {
peer: Peer
msgTime: string

View File

@@ -1,6 +1,5 @@
export enum GeneralCallResultStatus {
OK = 0,
// ERROR = 1,
OK = 0
}
export interface GeneralCallResult {

View File

@@ -11,7 +11,7 @@ export default class GetGroupAddRequest extends BaseAction<null, OB11GroupReques
actionName = ActionName.GetGroupIgnoreAddRequest;
async _handle(payload: null): Promise<OB11GroupRequestNotify[] | null> {
const data = await this.core.apis.GroupApi.getGroupIgnoreNotifies();
// const data = await this.core.apis.GroupApi.getGroupIgnoreNotifies();
// log(data);
// const notifies: GroupNotify[] = data.notifies.filter(notify => notify.status === GroupNotifyStatus.WAIT_HANDLE);
// const returnData: OB11GroupRequestNotify[] = [];

View File

@@ -43,12 +43,12 @@ export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
const fileName = mixElementInner.fileName ?? '';
let url = '';
if (mixElement?.picElement && rawMessage) {
let tempData =
const tempData =
await this.obContext.apis.MsgApi.rawToOb11Converters.picElement?.(mixElement?.picElement, rawMessage, mixElement) as OB11MessageImage | undefined;
url = tempData?.data.url ?? '';
}
if (mixElement?.videoElement && rawMessage) {
let tempData =
const tempData =
await this.obContext.apis.MsgApi.rawToOb11Converters.videoElement?.(mixElement?.videoElement, rawMessage, mixElement) as OB11MessageVideo | undefined;
url = tempData?.data.url ?? '';
}

View File

@@ -28,6 +28,7 @@ export default class GoCQHTTPGetStrangerInfo extends BaseAction<Payload, OB11Use
...extendData.detail.commonExt,
...extendData.detail.simpleInfo.baseInfo,
...extendData.detail.simpleInfo.relationFlags,
...extendData.detail.simpleInfo.status,
user_id: parseInt(extendData.detail.uin) || 0,
nickname: extendData.detail.simpleInfo.coreInfo.nick,
sex: OB11UserSex.unknown,

View File

@@ -51,7 +51,7 @@ export class GetGroupEssence extends BaseAction<Payload, any> {
operator_nick: msg.add_digest_nick,
message_id: message_id,
operator_time: msg.add_digest_time,
content: (await this.obContext.apis.MsgApi.parseMessage(rawMessage, 'array'))?.message
content: (await this.obContext.apis.MsgApi.parseMessage(rawMessage))?.message
};
}
const msgTempData = JSON.stringify({

View File

@@ -26,7 +26,7 @@ class GetGroupMemberInfo extends BaseAction<Payload, OB11GroupMember> {
const uid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
if (!uid) throw new Error(`Uin2Uid Error ${payload.user_id}不存在`);
const [member, info] = await Promise.allSettled([
this.core.apis.GroupApi.getGroupMemberV2(payload.group_id.toString(), uid, isNocache),
this.core.apis.GroupApi.getGroupMemberEx(payload.group_id.toString(), uid, isNocache),
this.core.apis.UserApi.getUserDetailInfo(uid),
]);
if (member.status !== 'fulfilled') throw new Error(`群(${payload.group_id})成员${payload.user_id}获取失败 ${member.reason}`);

View File

@@ -25,15 +25,7 @@ class DeleteMsg extends BaseAction<Payload, void> {
async _handle(payload: Payload) {
const msg = MessageUnique.getMsgIdAndPeerByShortId(Number(payload.message_id));
if (msg) {
const ret = this.core.eventWrapper.registerListen(
'NodeIKernelMsgListener/onMsgInfoListUpdate',
1,
1000,
(msgs) => !!msgs.find(m => m.msgId === msg.MsgId && m.recallTime !== '0'),
).catch(() => undefined);
await this.core.apis.MsgApi.recallMsg(msg.Peer, [msg.MsgId]);
const data = await ret;
if (!data) throw new Error('Recall failed');
await this.core.apis.MsgApi.recallMsg(msg.Peer, msg.MsgId);
} else {
throw new Error('Recall failed');
}

View File

@@ -35,7 +35,7 @@ class GetMsg extends BaseAction<Payload, OB11Message> {
const msg = await this.core.apis.MsgApi.getMsgsByMsgId(
peer,
[msgIdWithPeer?.MsgId || payload.message_id.toString()]);
const retMsg = await this.obContext.apis.MsgApi.parseMessage(msg.msgList[0], 'array');
const retMsg = await this.obContext.apis.MsgApi.parseMessage(msg.msgList[0]);
if (!retMsg) throw Error('消息为空');
try {
retMsg.message_id = MessageUnique.createUniqueMsgId(peer, msg.msgList[0].msgId)!;

View File

@@ -21,7 +21,7 @@ export default class GetRecentContact extends BaseAction<Payload, any> {
const FastMsg = await this.core.apis.MsgApi.getMsgsByMsgId({ chatType: t.chatType, peerUid: t.peerUid }, [t.msgId]);
if (FastMsg.msgList.length > 0) {
//扩展ret.info.changedList
const lastestMsg = await this.obContext.apis.MsgApi.parseMessage(FastMsg.msgList[0], 'array');
const lastestMsg = await this.obContext.apis.MsgApi.parseMessage(FastMsg.msgList[0]);
return {
lastestMsg: lastestMsg,
peerUin: t.peerUin,

View File

@@ -18,7 +18,6 @@ export class OneBotFriendApi {
let pokedetail: any[] = json.items;
//筛选item带有uid的元素
pokedetail = pokedetail.filter(item => item.uid);
//console.log("[NapCat] 群拍一拍 群:", pokedetail, parseInt(msg.peerUid), " ", await NTQQUserApi.getUinByUid(pokedetail[0].uid), "拍了拍", await NTQQUserApi.getUinByUid(pokedetail[1].uid));
if (pokedetail.length == 2) {
return new OB11FriendPokeEvent(
this.core,

View File

@@ -19,6 +19,7 @@ import { OB11GroupPokeEvent } from '@/onebot/event/notice/OB11PokeEvent';
import { OB11GroupEssenceEvent } from '@/onebot/event/notice/OB11GroupEssenceEvent';
import { OB11GroupTitleEvent } from '@/onebot/event/notice/OB11GroupTitleEvent';
import { FileNapCatOneBotUUID } from '@/common/helper';
import { pathToFileURL } from 'node:url';
export class OneBotGroupApi {
obContext: NapCatOneBot11Adapter;
@@ -77,7 +78,8 @@ export class OneBotGroupApi {
id: FileNapCatOneBotUUID.encode({
chatType: ChatType.KCHATTYPEGROUP,
peerUid: msg.peerUid,
}, msg.msgId, element.elementId),
}, msg.msgId, element.elementId, "." + element.fileElement.fileName),
url: pathToFileURL(element.fileElement.filePath).href,
name: element.fileElement.fileName,
size: parseInt(element.fileElement.fileSize),
busid: element.fileElement.fileBizId || 0,

View File

@@ -1,5 +1,6 @@
import { FileNapCatOneBotUUID } from '@/common/helper';
import { MessageUnique } from '@/common/message-unique';
import { pathToFileURL } from 'node:url';
import {
AtType,
ChatType,
@@ -106,7 +107,7 @@ export class OneBotMsgApi {
peerUid: msg.peerUid,
guildId: '',
};
const encodedFileId = FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId);
const encodedFileId = FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId, "."+element.fileName);
return {
type: OB11MessageDataType.image,
data: {
@@ -114,6 +115,7 @@ export class OneBotMsgApi {
sub_type: element.picSubType,
file_id: encodedFileId,
url: await this.core.apis.FileApi.getImageUrl(element),
path: element.filePath,
file_size: element.fileSize,
file_unique: element.fileName
},
@@ -135,8 +137,8 @@ export class OneBotMsgApi {
data: {
file: element.fileName,
path: element.filePath,
url: element.filePath,
file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId),
url: pathToFileURL(element.filePath).href,
file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId, "."+element.fileName),
file_size: element.fileSize,
file_unique: element.fileName,
},
@@ -175,13 +177,16 @@ export class OneBotMsgApi {
peerUid: msg.peerUid,
guildId: '',
};
const { emojiId } = _;
const dir = emojiId.substring(0, 2);
const url = `https://gxh.vip.qq.com/club/item/parcel/item/${dir}/${emojiId}/raw300.gif`;
return {
type: OB11MessageDataType.image,
data: {
file: 'marketface',
file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId),
file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId, "."+_.key+".jpg"),
path: elementWrapper.elementId,
url: elementWrapper.elementId,
url: url,
file_unique: _.key
},
};
@@ -209,7 +214,7 @@ export class OneBotMsgApi {
if (records.peerUin === '284840486') {
return createReplyData(records.msgId);
}
let 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]))
.msgList.find(msg => msg.msgRandom === records.msgRandom);
if (!replyMsg || records.msgRandom !== replyMsg.msgRandom) {
@@ -257,14 +262,14 @@ export class OneBotMsgApi {
if (!videoDownUrl) {
videoDownUrl = element.filePath;
}
const fileCode = FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId, "."+element.fileName);
return {
type: OB11MessageDataType.video,
data: {
file: element.fileName,
file: fileCode,
path: videoDownUrl,
url: videoDownUrl,
file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId),
url: videoDownUrl ?? pathToFileURL(element.filePath).href,
file_id: fileCode,
file_size: element.fileSize,
file_unique: element.fileName,
},
@@ -277,13 +282,16 @@ export class OneBotMsgApi {
peerUid: msg.peerUid,
guildId: '',
};
const fileCode = FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId, "."+element.fileName);
return {
type: OB11MessageDataType.voice,
data: {
file: element.fileName,
file: fileCode,
path: element.filePath,
file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId),
url: pathToFileURL(element.filePath).href,
file_id: fileCode,
file_size: element.fileSize,
file_unique: element.fileName
},
};
},
@@ -792,18 +800,20 @@ export class OneBotMsgApi {
) {
const isBlankUrl = !inputdata.url || inputdata.url === '';
const isBlankFile = !inputdata.file || inputdata.file === '';
const isBlankPath = !inputdata.path || inputdata.path === '';
if (isBlankUrl && isBlankFile) {
this.core.context.logger.logError('文件消息缺少参数', inputdata);
throw Error('文件消息缺少参数');
}
const fileOrUrl = (isBlankUrl ? inputdata.file : inputdata.url) ?? '';
//path->url->file
const realUri = (!isBlankUrl ? inputdata.url :(!isBlankPath ? inputdata.path:inputdata.file ))??'';
const {
path,
isLocal,
fileName,
errMsg,
success,
} = (await uri2local(this.core.NapCatTempPath, fileOrUrl));
} = (await uri2local(this.core.NapCatTempPath, realUri));
if (!success) {
this.core.context.logger.logError('文件下载失败', errMsg);

View File

@@ -109,7 +109,7 @@ export class OB11Entities {
static file(peerId: string, file: Exclude<GroupFileInfoUpdateParamType['item'][0]['fileInfo'], undefined>): OB11GroupFile {
return {
group_id: parseInt(peerId),
file_id: FileNapCatOneBotUUID.encodeModelId({ chatType: 2, peerUid: peerId }, file.fileModelId, file.fileId),
file_id: FileNapCatOneBotUUID.encodeModelId({ chatType: 2, peerUid: peerId }, file.fileModelId, file.fileId, file.fileName),
file_name: file.fileName,
busid: file.busId,
size: parseInt(file.fileSize),

View File

@@ -6,6 +6,7 @@ export interface GroupUploadFile {
name: string,
size: number,
busid: number,
url:string;
}
export class OB11GroupUploadNoticeEvent extends OB11GroupNoticeEvent {

View File

@@ -84,6 +84,8 @@ export interface OB11MessageText {
export interface OB11MessageFileBase {
data: {
file_unique?:string,
path?: string;
thumb?: string;
name?: string;
file: string,

View File

@@ -17,7 +17,6 @@ export interface QuickActionGroupMessage extends QuickActionPrivateMessage {
kick?: boolean;
ban?: boolean;
ban_duration?: number;
//
}
export interface QuickActionFriendRequest {

View File

@@ -150,7 +150,12 @@ export async function NCoreInitShell() {
};
loginService.addKernelLoginListener(proxiedListenerOf(loginListener, logger) as any);
const isConnect = loginService.connect();
if (!isConnect) {
logger.logError('核心登录服务连接失败!');
return;
}
logger.log('核心登录服务连接成功!');
// 实现WebUi快速登录
loginService.getLoginList().then((res) => {
// 遍历 res.LocalLoginInfoList[x].isQuickLogin是否可以 res.LocalLoginInfoList[x].uin 转为string 加入string[] 最后遍历完成调用WebUiDataRuntime.setQQQuickLoginList
@@ -199,7 +204,7 @@ export async function NCoreInitShell() {
logger.log(`可用于快速登录的 QQ\n${historyLoginList
.map((u, index) => `${index + 1}. ${u.uin} ${u.nickName}`)
.join('\n')
}`);
}`);
}
loginService.getQRCodePicture();
}
@@ -229,7 +234,7 @@ export async function NCoreInitShell() {
sessionConfig,
new NodeIDependsAdapter(),
new NodeIDispatcherAdapter(),
sessionListener as any,
sessionListener,
);
try {
session.startNT(0);

View File

@@ -3,6 +3,7 @@ import { ALLRouter } from './src/router';
import { LogWrapper } from '@/common/log';
import { NapCatPathWrapper } from '@/common/path';
import { WebUiConfigWrapper } from './src/helper/config';
import { RequestUtil } from '@/common/request';
const app = express();
@@ -38,7 +39,23 @@ export async function InitWebUi(logger: LogWrapper, pathWrapper: NapCatPathWrapp
app.use(config.prefix + '/api', ALLRouter);
app.listen(config.port, config.host, async () => {
log(`[NapCat] [WebUi] Current WebUi is running at http://${config.host}:${config.port}${config.prefix}`);
log(`[NapCat] [WebUi] Login URL is http://${config.host}:${config.port}${config.prefix}/webui`);
log(`[NapCat] [WebUi] Login Token is ${config.token}`);
log(`[NapCat] [WebUi] WebUi User Panel Url: http://${config.host}:${config.port}${config.prefix}/webui?token=${config.token}`);
log(`[NapCat] [WebUi] WebUi Local Panel Url: http://127.0.0.1:${config.port}${config.prefix}/webui?token=${config.token}`);
//获取上网Ip
//https://www.ip.cn/api/index?ip&type=0
RequestUtil.HttpGetJson<{ IP: {IP:string} }>(
'https://ip.011102.xyz/',
'GET',
{},
{},
true,
true
).then((data) => {
log(`[NapCat] [WebUi] WebUi Publish Panel Url: http://${data.IP.IP}:${config.port}${config.prefix}/webui/?token=${config.token}`);
}).catch((err) => {
logger.logError(`[NapCat] [WebUi] Get Publish Panel Url Error: ${err}`);
});
});
}

View File

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

View File

@@ -29,7 +29,7 @@
margin-bottom: 20px;
}
input[type="text"] {
input[type="password"] {
width: 90%;
padding: 10px;
font-size: 16px;
@@ -64,7 +64,7 @@
<form id="token-form" onsubmit="event.preventDefault(); submitToken();">
<div class="input-group">
<label for="token-input">Enter Token:</label>
<input type="text" id="token-input" required>
<input type="password" id="token-input" required>
</div>
<p class="error-message hidden" id="error-message"></p>
<button type="submit">Login</button>
@@ -133,4 +133,4 @@
</script>
</body>
</html>
</html>