Compare commits

...

13 Commits

Author SHA1 Message Date
手瓜一十雪
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
13 changed files with 77 additions and 24 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.3.7",
"icon": "./logo.png",
"authors": [
{

View File

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

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

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

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;
@@ -264,14 +265,34 @@ export class NTQQGroupApi {
}
return member;
}
async getGroupMemberEx(GroupCode: string, uid: string, forced = false, retry = 2) {
let 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) {
let 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 {

View File

@@ -113,7 +113,7 @@ export class NTQQMsgApi {
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);
const reply = await this.context.session.getMsgService().getSourceOfReplyMsgV2(peer, rootMsgId, replyMsgId);
console.log(reply);
}
async getMsgExBySeq(peer: Peer, msgSeq: string) {
@@ -164,6 +164,18 @@ export class NTQQMsgApi {
}, msgIds);
}
async recallMsgV2(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) {
return this.context.session.getMsgService().prepareTempChat({
chatType: ChatType.KCHATTYPETEMPC2CFROMGROUP,

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

@@ -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

@@ -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.3.7', '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.3.7", "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>