Compare commits

..

13 Commits

Author SHA1 Message Date
手瓜一十雪
fe04fa5986 Merge branch 'main' of https://github.com/NapNeko/NapCatQQ 2025-02-14 17:41:40 +08:00
手瓜一十雪
c382f541b4 fix: 优化文件处理错误信息并简化下载逻辑 2025-02-14 17:41:25 +08:00
手瓜一十雪
f420527207 Update msg.ts 2025-02-14 17:41:03 +08:00
手瓜一十雪
e0c83ebf79 fix: #793 2025-02-14 17:15:19 +08:00
手瓜一十雪
c7fb18fc08 feat: 补全一些type 2025-02-14 15:39:06 +08:00
手瓜一十雪
2db8ab937d feat: GetUnidirectionalFriendList router 2025-02-14 15:06:36 +08:00
手瓜一十雪
819f5dd8e5 fix: #785 2025-02-14 14:50:00 +08:00
手瓜一十雪
d4a8ed735e fix: #789 2025-02-14 14:48:36 +08:00
手瓜一十雪
f07e3bb4d5 fix: type 2025-02-14 14:44:10 +08:00
手瓜一十雪
fa5ef0c221 fix: #797 2025-02-14 14:41:16 +08:00
手瓜一十雪
da7499ec0b Merge pull request #790 from NapNeko/dependabot/npm_and_yarn/esbuild-0.25.0
chore(deps-dev): bump esbuild from 0.24.0 to 0.25.0
2025-02-14 13:51:47 +08:00
Mlikiowa
d2f4327e44 release: v4.5.21 2025-02-12 18:57:14 +00:00
dependabot[bot]
29ae55f340 chore(deps-dev): bump esbuild from 0.24.0 to 0.25.0
Bumps [esbuild](https://github.com/evanw/esbuild) from 0.24.0 to 0.25.0.
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG-2024.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.24.0...v0.25.0)

---
updated-dependencies:
- dependency-name: esbuild
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-10 08:16:17 +00:00
14 changed files with 116 additions and 29 deletions

View File

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

View File

@@ -2,7 +2,7 @@
"name": "napcat",
"private": true,
"type": "module",
"version": "4.5.20",
"version": "4.5.21",
"scripts": {
"build:universal": "npm run build:webui && vite build --mode universal || exit 1",
"build:framework": "npm run build:webui && vite build --mode framework || exit 1",
@@ -43,7 +43,7 @@
"async-mutex": "^0.5.0",
"commander": "^13.0.0",
"cors": "^2.8.5",
"esbuild": "0.24.0",
"esbuild": "0.25.0",
"eslint": "^9.14.0",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.29.1",

View File

@@ -1 +1 @@
export const napCatVersion = '4.5.20';
export const napCatVersion = '4.5.21';

View File

@@ -1,5 +1,5 @@
import { ChatType, GetFileListParam, Peer, RawMessage, SendMessageElement, SendStatusType } from '@/core/types';
import { GroupFileInfoUpdateItem, InstanceContext, NapCatCore } from '@/core';
import { GroupFileInfoUpdateItem, InstanceContext, NapCatCore, NodeIKernelMsgService } from '@/core';
import { GeneralCallResult } from '@/core/services/common';
export class NTQQMsgApi {
@@ -12,6 +12,11 @@ export class NTQQMsgApi {
this.context = context;
this.core = core;
}
async clickInlineKeyboardButton(...params: Parameters<NodeIKernelMsgService['clickInlineKeyboardButton']>) {
return this.context.session.getMsgService().clickInlineKeyboardButton(...params);
}
getMsgByClientSeqAndTime(peer: Peer, replyMsgClientSeq: string, replyMsgTime: string) {
// https://bot.q.qq.com/wiki/develop/api-v2/openapi/emoji/model.html#EmojiType 可以用过特殊方式拉取
return this.context.session.getMsgService().getMsgByClientSeqAndTime(peer, replyMsgClientSeq, replyMsgTime);

View File

@@ -1,4 +1,5 @@
import { DownloadBaseEmojiByIdReq, DownloadBaseEmojiByUrlReq, GetBaseEmojiPathReq, PullSysEmojisReq } from '../types';
import { GeneralCallResult } from './common';
export interface NodeIKernelBaseEmojiService {
removeKernelBaseEmojiListener(listenerId: number): void;
@@ -7,7 +8,26 @@ export interface NodeIKernelBaseEmojiService {
isBaseEmojiPathExist(args: Array<string>): unknown;
fetchFullSysEmojis(pullSysEmojisReq: PullSysEmojisReq): unknown;
fetchFullSysEmojis(pullSysEmojisReq: PullSysEmojisReq): Promise<GeneralCallResult & {
rsp: {
otherPanelResult: {
SysEmojiGroupList: Array<unknown>,
downloadInfo: Array<unknown>
},
normalPanelResult: {
SysEmojiGroupList: Array<unknown>,
downloadInfo: Array<unknown>
},
superPanelResult: {
SysEmojiGroupList: Array<unknown>,
downloadInfo: Array<unknown>
},
redHeartPanelResult: {
SysEmojiGroupList: Array<unknown>,
downloadInfo: Array<unknown>
}
}
}>;
getBaseEmojiPathByIds(getBaseEmojiPathReqs: Array<GetBaseEmojiPathReq>): unknown;

View File

@@ -253,7 +253,7 @@ export interface NodeIKernelGroupService {
getGroupShutUpMemberList(groupCode: string): Promise<GeneralCallResult>;
setMemberShutUp(groupCode: string, memberTimes: { uid: string, timeStamp: number }[]): Promise<void>;
setMemberShutUp(groupCode: string, memberTimes: { uid: string, timeStamp: number }[]): Promise<GeneralCallResult>;
getGroupRecommendContactArkJson(groupCode: string): Promise<GeneralCallResult & { arkJson: string }>;

View File

@@ -464,11 +464,20 @@ export interface NodeIKernelMsgService {
setMsgEmojiLikesForRole(...args: unknown[]): unknown;
clickInlineKeyboardButton(...args: unknown[]): unknown;
clickInlineKeyboardButton(params: {
guildId: string,
peerId: string,
botAppid: string,
msgSeq: string,
buttonId: string,
callback_data: string,
dmFlag: number,
chatType: number
}): Promise<GeneralCallResult & { status: number, promptText: string, promptType: number, promptIcon: number }>;
setCurOnScreenMsg(...args: unknown[]): unknown;
setCurOnScreenMsgForMsgEvent(...args: unknown[]): unknown;
setCurOnScreenMsgForMsgEvent(peer: Peer, msgRegList: Map<string, Uint8Array>): void;
getMiscData(key: string): unknown;

View File

@@ -1,4 +1,5 @@
import { NodeIKernelRobotListener } from '@/core/listeners';
import { GeneralCallResult, Peer } from '..';
export interface NodeIKernelRobotService {
fetchGroupRobotStoreDiscovery(arg: unknown): unknown;
@@ -31,5 +32,17 @@ export interface NodeIKernelRobotService {
getRobotUinRange(data: unknown): Promise<{ response: { robotUinRanges: Array<unknown> } }>;
getRobotFunctions(peer: Peer, params: {
uins: Array<string>,
num: 0,
client_info: { platform: 4, version: '', build_num: 9999 },
tinyids: [],
page: 0,
full_fetch: false,
scene: 4,
filter: 1,
bkn: ''
}): Promise<GeneralCallResult & { response: { bot_features: Array<unknown>, next_page: number } }>;
isNull(): boolean;
}

View File

@@ -0,0 +1,10 @@
import { ActionName } from '@/onebot/action/router';
import { OneBotAction } from '../OneBotAction';
export class BotExit extends OneBotAction<void, void> {
override actionName = ActionName.Exit;
async _handle() {
process.exit(0);
}
}

View File

@@ -0,0 +1,30 @@
import { ActionName } from '@/onebot/action/router';
import { OneBotAction } from '../OneBotAction';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
bot_appid: Type.String(),
button_id: Type.String({ default: '' }),
callback_data: Type.String({ default: '' }),
});
type Payload = Static<typeof SchemaData>;
export class ClickInlineKeyboardButton extends OneBotAction<Payload, unknown> {
override actionName = ActionName.ClickInlineKeyboardButton;
override payloadSchema = SchemaData;
async _handle(payload: Payload) {
return await this.core.apis.MsgApi.clickInlineKeyboardButton({
buttonId: payload.button_id,
guildId: '',// 频道使用
peerId: payload.group_id.toString(),
botAppid: payload.bot_appid,
msgSeq: '10086',
callback_data: payload.callback_data,
dmFlag: 0,
chatType: 1
})
}
}

View File

@@ -13,12 +13,13 @@ type Payload = Static<typeof SchemaData>;
export default class SetGroupBan extends OneBotAction<Payload, null> {
override actionName = ActionName.SetGroupBan;
override payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<null> {
const uid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
if (!uid) throw new Error('uid error');
await this.core.apis.GroupApi.banMember(payload.group_id.toString(),
// 例如无管理员权限时 result为 120101005 errMsg为 'ERR_NOT_GROUP_ADMIN'
let ret = await this.core.apis.GroupApi.banMember(payload.group_id.toString(),
[{ uid: uid, timeStamp: +payload.duration }]);
if (ret.result !== 0) throw new Error(ret.errMsg);
return null;
}
}

View File

@@ -104,6 +104,8 @@ import { GetClientkey } from './extends/GetClientkey';
import { SendPacket } from './extends/SendPacket';
import { SendPoke } from '@/onebot/action/packet/SendPoke';
import { SetDiyOnlineStatus } from './extends/SetDiyOnlineStatus';
import { BotExit } from './extends/BotExit';
import { ClickInlineKeyboardButton } from './extends/ClickInlineKeyboardButton';
export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCore) {
@@ -221,6 +223,8 @@ export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCo
new SendPacket(obContext, core),
new SendPoke(obContext, core),
new GetGroupSystemMsg(obContext, core),
new BotExit(obContext, core),
new ClickInlineKeyboardButton(obContext, core),
];
type HandlerUnion = typeof actionHandlers[number];

View File

@@ -10,6 +10,8 @@ export interface InvalidCheckResult {
}
export const ActionName = {
ClickInlineKeyboardButton: 'click_inline_keyboard_button',
GetUnidirectionalFriendList: 'get_unidirectional_friend_list',
// onebot 11
SendPrivateMsg: 'send_private_msg',
SendGroupMsg: 'send_group_msg',
@@ -49,7 +51,7 @@ export const ActionName = {
GetVersionInfo: 'get_version_info',
// Reboot : 'set_restart',
// CleanCache : 'clean_cache',
Exit: 'bot_exit',
// go-cqhttp
SetQQProfile: 'set_qq_profile',
// QidianGetAccountInfo : 'qidian_get_account_info',
@@ -141,6 +143,6 @@ export const ActionName = {
SendGroupAiRecord: 'send_group_ai_record',
GetClientkey: 'get_clientkey',
SendPoke: 'send_poke',
} as const;

View File

@@ -996,24 +996,17 @@ export class OneBotMsgApi {
this.core.context.logger.logError('文件消息缺少参数', inputdata);
throw new Error('文件消息缺少参数');
}
const downloadFile = async (uri: string) => {
const { path, fileName, errMsg, success } = await uriToLocalFile(this.core.NapCatTempPath, uri);
if (!success) {
this.core.context.logger.logError('文件下载失败', errMsg);
throw new Error('文件下载失败: ' + errMsg);
}
return { path, fileName };
};
realUri = await this.handleObfuckName(realUri) ?? realUri;
try {
const { path, fileName } = await downloadFile(realUri);
deleteAfterSentFiles.push(path);
return { path, fileName: inputdata.name ?? fileName };
} catch {
realUri = await this.handleObfuckName(realUri);
const { path, fileName } = await downloadFile(realUri);
const { path, fileName, errMsg, success } = await uriToLocalFile(this.core.NapCatTempPath, realUri);
if (!success) {
this.core.context.logger.logError('文件处理失败', errMsg);
throw new Error('文件处理失败: ' + errMsg);
}
deleteAfterSentFiles.push(path);
return { path, fileName: inputdata.name ?? fileName };
} catch (e: unknown) {
throw new Error((e as Error).message);
}
}
@@ -1038,7 +1031,7 @@ export class OneBotMsgApi {
}
return url !== '' ? url : await this.core.apis.FileApi.downloadMedia(msgId, peer.chatType, peer.peerUid, elementId, '', '');
}
throw new Error('文件名解析失败');
return undefined;
}
groupChangDecreseType2String(type: number): GroupDecreaseSubType {