mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-07-19 12:03:37 +00:00
Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
fe04fa5986 | ||
![]() |
c382f541b4 | ||
![]() |
f420527207 | ||
![]() |
e0c83ebf79 | ||
![]() |
c7fb18fc08 | ||
![]() |
2db8ab937d | ||
![]() |
819f5dd8e5 | ||
![]() |
d4a8ed735e | ||
![]() |
f07e3bb4d5 | ||
![]() |
fa5ef0c221 | ||
![]() |
da7499ec0b | ||
![]() |
d2f4327e44 | ||
![]() |
29ae55f340 |
@@ -4,7 +4,7 @@
|
|||||||
"name": "NapCatQQ",
|
"name": "NapCatQQ",
|
||||||
"slug": "NapCat.Framework",
|
"slug": "NapCat.Framework",
|
||||||
"description": "高性能的 OneBot 11 协议实现",
|
"description": "高性能的 OneBot 11 协议实现",
|
||||||
"version": "4.5.20",
|
"version": "4.5.21",
|
||||||
"icon": "./logo.png",
|
"icon": "./logo.png",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
"name": "napcat",
|
"name": "napcat",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "4.5.20",
|
"version": "4.5.21",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build:universal": "npm run build:webui && vite build --mode universal || exit 1",
|
"build:universal": "npm run build:webui && vite build --mode universal || exit 1",
|
||||||
"build:framework": "npm run build:webui && vite build --mode framework || exit 1",
|
"build:framework": "npm run build:webui && vite build --mode framework || exit 1",
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
"async-mutex": "^0.5.0",
|
"async-mutex": "^0.5.0",
|
||||||
"commander": "^13.0.0",
|
"commander": "^13.0.0",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"esbuild": "0.24.0",
|
"esbuild": "0.25.0",
|
||||||
"eslint": "^9.14.0",
|
"eslint": "^9.14.0",
|
||||||
"eslint-import-resolver-typescript": "^3.6.1",
|
"eslint-import-resolver-typescript": "^3.6.1",
|
||||||
"eslint-plugin-import": "^2.29.1",
|
"eslint-plugin-import": "^2.29.1",
|
||||||
|
@@ -1 +1 @@
|
|||||||
export const napCatVersion = '4.5.20';
|
export const napCatVersion = '4.5.21';
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { ChatType, GetFileListParam, Peer, RawMessage, SendMessageElement, SendStatusType } from '@/core/types';
|
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';
|
import { GeneralCallResult } from '@/core/services/common';
|
||||||
|
|
||||||
export class NTQQMsgApi {
|
export class NTQQMsgApi {
|
||||||
@@ -12,6 +12,11 @@ export class NTQQMsgApi {
|
|||||||
this.context = context;
|
this.context = context;
|
||||||
this.core = core;
|
this.core = core;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async clickInlineKeyboardButton(...params: Parameters<NodeIKernelMsgService['clickInlineKeyboardButton']>) {
|
||||||
|
return this.context.session.getMsgService().clickInlineKeyboardButton(...params);
|
||||||
|
}
|
||||||
|
|
||||||
getMsgByClientSeqAndTime(peer: Peer, replyMsgClientSeq: string, replyMsgTime: string) {
|
getMsgByClientSeqAndTime(peer: Peer, replyMsgClientSeq: string, replyMsgTime: string) {
|
||||||
// https://bot.q.qq.com/wiki/develop/api-v2/openapi/emoji/model.html#EmojiType 可以用过特殊方式拉取
|
// https://bot.q.qq.com/wiki/develop/api-v2/openapi/emoji/model.html#EmojiType 可以用过特殊方式拉取
|
||||||
return this.context.session.getMsgService().getMsgByClientSeqAndTime(peer, replyMsgClientSeq, replyMsgTime);
|
return this.context.session.getMsgService().getMsgByClientSeqAndTime(peer, replyMsgClientSeq, replyMsgTime);
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import { DownloadBaseEmojiByIdReq, DownloadBaseEmojiByUrlReq, GetBaseEmojiPathReq, PullSysEmojisReq } from '../types';
|
import { DownloadBaseEmojiByIdReq, DownloadBaseEmojiByUrlReq, GetBaseEmojiPathReq, PullSysEmojisReq } from '../types';
|
||||||
|
import { GeneralCallResult } from './common';
|
||||||
|
|
||||||
export interface NodeIKernelBaseEmojiService {
|
export interface NodeIKernelBaseEmojiService {
|
||||||
removeKernelBaseEmojiListener(listenerId: number): void;
|
removeKernelBaseEmojiListener(listenerId: number): void;
|
||||||
@@ -7,7 +8,26 @@ export interface NodeIKernelBaseEmojiService {
|
|||||||
|
|
||||||
isBaseEmojiPathExist(args: Array<string>): unknown;
|
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;
|
getBaseEmojiPathByIds(getBaseEmojiPathReqs: Array<GetBaseEmojiPathReq>): unknown;
|
||||||
|
|
||||||
|
@@ -253,7 +253,7 @@ export interface NodeIKernelGroupService {
|
|||||||
|
|
||||||
getGroupShutUpMemberList(groupCode: string): Promise<GeneralCallResult>;
|
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 }>;
|
getGroupRecommendContactArkJson(groupCode: string): Promise<GeneralCallResult & { arkJson: string }>;
|
||||||
|
|
||||||
|
@@ -464,11 +464,20 @@ export interface NodeIKernelMsgService {
|
|||||||
|
|
||||||
setMsgEmojiLikesForRole(...args: unknown[]): unknown;
|
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;
|
setCurOnScreenMsg(...args: unknown[]): unknown;
|
||||||
|
|
||||||
setCurOnScreenMsgForMsgEvent(...args: unknown[]): unknown;
|
setCurOnScreenMsgForMsgEvent(peer: Peer, msgRegList: Map<string, Uint8Array>): void;
|
||||||
|
|
||||||
getMiscData(key: string): unknown;
|
getMiscData(key: string): unknown;
|
||||||
|
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import { NodeIKernelRobotListener } from '@/core/listeners';
|
import { NodeIKernelRobotListener } from '@/core/listeners';
|
||||||
|
import { GeneralCallResult, Peer } from '..';
|
||||||
|
|
||||||
export interface NodeIKernelRobotService {
|
export interface NodeIKernelRobotService {
|
||||||
fetchGroupRobotStoreDiscovery(arg: unknown): unknown;
|
fetchGroupRobotStoreDiscovery(arg: unknown): unknown;
|
||||||
@@ -31,5 +32,17 @@ export interface NodeIKernelRobotService {
|
|||||||
|
|
||||||
getRobotUinRange(data: unknown): Promise<{ response: { robotUinRanges: Array<unknown> } }>;
|
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;
|
isNull(): boolean;
|
||||||
}
|
}
|
||||||
|
10
src/onebot/action/extends/BotExit.ts
Normal file
10
src/onebot/action/extends/BotExit.ts
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
30
src/onebot/action/extends/ClickInlineKeyboardButton.ts
Normal file
30
src/onebot/action/extends/ClickInlineKeyboardButton.ts
Normal 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
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@@ -13,12 +13,13 @@ type Payload = Static<typeof SchemaData>;
|
|||||||
export default class SetGroupBan extends OneBotAction<Payload, null> {
|
export default class SetGroupBan extends OneBotAction<Payload, null> {
|
||||||
override actionName = ActionName.SetGroupBan;
|
override actionName = ActionName.SetGroupBan;
|
||||||
override payloadSchema = SchemaData;
|
override payloadSchema = SchemaData;
|
||||||
|
|
||||||
async _handle(payload: Payload): Promise<null> {
|
async _handle(payload: Payload): Promise<null> {
|
||||||
const uid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
|
const uid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
|
||||||
if (!uid) throw new Error('uid error');
|
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 }]);
|
[{ uid: uid, timeStamp: +payload.duration }]);
|
||||||
|
if (ret.result !== 0) throw new Error(ret.errMsg);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -104,6 +104,8 @@ import { GetClientkey } from './extends/GetClientkey';
|
|||||||
import { SendPacket } from './extends/SendPacket';
|
import { SendPacket } from './extends/SendPacket';
|
||||||
import { SendPoke } from '@/onebot/action/packet/SendPoke';
|
import { SendPoke } from '@/onebot/action/packet/SendPoke';
|
||||||
import { SetDiyOnlineStatus } from './extends/SetDiyOnlineStatus';
|
import { SetDiyOnlineStatus } from './extends/SetDiyOnlineStatus';
|
||||||
|
import { BotExit } from './extends/BotExit';
|
||||||
|
import { ClickInlineKeyboardButton } from './extends/ClickInlineKeyboardButton';
|
||||||
|
|
||||||
export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCore) {
|
export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCore) {
|
||||||
|
|
||||||
@@ -221,6 +223,8 @@ export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCo
|
|||||||
new SendPacket(obContext, core),
|
new SendPacket(obContext, core),
|
||||||
new SendPoke(obContext, core),
|
new SendPoke(obContext, core),
|
||||||
new GetGroupSystemMsg(obContext, core),
|
new GetGroupSystemMsg(obContext, core),
|
||||||
|
new BotExit(obContext, core),
|
||||||
|
new ClickInlineKeyboardButton(obContext, core),
|
||||||
];
|
];
|
||||||
|
|
||||||
type HandlerUnion = typeof actionHandlers[number];
|
type HandlerUnion = typeof actionHandlers[number];
|
||||||
|
@@ -10,6 +10,8 @@ export interface InvalidCheckResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const ActionName = {
|
export const ActionName = {
|
||||||
|
ClickInlineKeyboardButton: 'click_inline_keyboard_button',
|
||||||
|
GetUnidirectionalFriendList: 'get_unidirectional_friend_list',
|
||||||
// onebot 11
|
// onebot 11
|
||||||
SendPrivateMsg: 'send_private_msg',
|
SendPrivateMsg: 'send_private_msg',
|
||||||
SendGroupMsg: 'send_group_msg',
|
SendGroupMsg: 'send_group_msg',
|
||||||
@@ -49,7 +51,7 @@ export const ActionName = {
|
|||||||
GetVersionInfo: 'get_version_info',
|
GetVersionInfo: 'get_version_info',
|
||||||
// Reboot : 'set_restart',
|
// Reboot : 'set_restart',
|
||||||
// CleanCache : 'clean_cache',
|
// CleanCache : 'clean_cache',
|
||||||
|
Exit: 'bot_exit',
|
||||||
// go-cqhttp
|
// go-cqhttp
|
||||||
SetQQProfile: 'set_qq_profile',
|
SetQQProfile: 'set_qq_profile',
|
||||||
// QidianGetAccountInfo : 'qidian_get_account_info',
|
// QidianGetAccountInfo : 'qidian_get_account_info',
|
||||||
|
@@ -996,24 +996,17 @@ export class OneBotMsgApi {
|
|||||||
this.core.context.logger.logError('文件消息缺少参数', inputdata);
|
this.core.context.logger.logError('文件消息缺少参数', inputdata);
|
||||||
throw new Error('文件消息缺少参数');
|
throw new Error('文件消息缺少参数');
|
||||||
}
|
}
|
||||||
|
realUri = await this.handleObfuckName(realUri) ?? realUri;
|
||||||
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 };
|
|
||||||
};
|
|
||||||
try {
|
try {
|
||||||
const { path, fileName } = await downloadFile(realUri);
|
const { path, fileName, errMsg, success } = await uriToLocalFile(this.core.NapCatTempPath, realUri);
|
||||||
deleteAfterSentFiles.push(path);
|
if (!success) {
|
||||||
return { path, fileName: inputdata.name ?? fileName };
|
this.core.context.logger.logError('文件处理失败', errMsg);
|
||||||
} catch {
|
throw new Error('文件处理失败: ' + errMsg);
|
||||||
realUri = await this.handleObfuckName(realUri);
|
}
|
||||||
const { path, fileName } = await downloadFile(realUri);
|
|
||||||
deleteAfterSentFiles.push(path);
|
deleteAfterSentFiles.push(path);
|
||||||
return { path, fileName: inputdata.name ?? fileName };
|
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, '', '');
|
return url !== '' ? url : await this.core.apis.FileApi.downloadMedia(msgId, peer.chatType, peer.peerUid, elementId, '', '');
|
||||||
}
|
}
|
||||||
throw new Error('文件名解析失败');
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
groupChangDecreseType2String(type: number): GroupDecreaseSubType {
|
groupChangDecreseType2String(type: number): GroupDecreaseSubType {
|
||||||
|
Reference in New Issue
Block a user