From 1da086ce0aadd8ba36b00271ce794bbd537cc24c Mon Sep 17 00:00:00 2001 From: linyuchen Date: Sun, 5 May 2024 20:20:30 +0800 Subject: [PATCH 1/3] chore: v3.24.2 --- src/version.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.ts b/src/version.ts index 0df6922..0947d34 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const version = '3.24.1' +export const version = '3.24.2' From 43e9b070a95e58d3b5ad83ace35a048cbb947207 Mon Sep 17 00:00:00 2001 From: student_2333 Date: Fri, 10 May 2024 13:33:48 +0800 Subject: [PATCH 2/3] fix: try 2 fix cannot parse msg err --- .gitignore | 2 +- manifest.json | 4 +-- package.json | 3 +- src/ntqqapi/api/group.ts | 6 +++- src/onebot11/action/msg/SendMsg.ts | 54 +++++++++++++++++------------- tsconfig.json | 5 +-- 6 files changed, 44 insertions(+), 30 deletions(-) diff --git a/.gitignore b/.gitignore index eb71599..0dc9ec5 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,4 @@ package-lock.json dist/ out/ .idea/ -.DS_Store \ No newline at end of file +.DS_Store diff --git a/manifest.json b/manifest.json index 90d3681..dca5fd4 100644 --- a/manifest.json +++ b/manifest.json @@ -1,10 +1,10 @@ { "manifest_version": 4, "type": "extension", - "name": "LLOneBot v3.24.1", + "name": "LLOneBot v3.24.2", "slug": "LLOneBot", "description": "使你的NTQQ支持OneBot11协议进行QQ机器人开发, 不支持商店在线更新", - "version": "3.24.1", + "version": "3.24.2", "icon": "./icon.jpg", "authors": [ { diff --git a/package.json b/package.json index ceb514f..9add729 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,8 @@ "deploy-mac": "cp -r dist/* ~/Library/Containers/com.tencent.qq/Data/LiteLoaderQQNT/plugins/LLOneBot/", "build-win": "npm run build && npm run deploy-win", "deploy-win": "cmd /c \"xcopy /C /S /Y dist\\* %USERPROFILE%\\documents\\LiteLoaderQQNT\\plugins\\LLOneBot\\\"", - "format": "prettier -cw ." + "format": "prettier -cw .", + "check": "tsc" }, "author": "", "license": "MIT", diff --git a/src/ntqqapi/api/group.ts b/src/ntqqapi/api/group.ts index a9d7bad..9618770 100644 --- a/src/ntqqapi/api/group.ts +++ b/src/ntqqapi/api/group.ts @@ -74,7 +74,11 @@ export class NTQQGroupApi { } static async getGroupIgnoreNotifies() { await NTQQGroupApi.getGroupNotifies() - return await NTQQWindowApi.openWindow(NTQQWindows.GroupNotifyFilterWindow, [], ReceiveCmdS.GROUP_NOTIFY) + return await NTQQWindowApi.openWindow( + NTQQWindows.GroupNotifyFilterWindow, + [], + ReceiveCmdS.GROUP_NOTIFY, + ) } static async handleGroupRequest(seq: string, operateType: GroupRequestOperateTypes, reason?: string) { const notify: GroupNotify = await dbUtil.getGroupNotify(seq) diff --git a/src/onebot11/action/msg/SendMsg.ts b/src/onebot11/action/msg/SendMsg.ts index d52e1da..39a383a 100644 --- a/src/onebot11/action/msg/SendMsg.ts +++ b/src/onebot11/action/msg/SendMsg.ts @@ -14,11 +14,13 @@ import { friends, getFriend, getGroup, getGroupMember, getUidByUin, selfInfo } f import { OB11MessageCustomMusic, OB11MessageData, - OB11MessageDataType, OB11MessageFile, + OB11MessageDataType, + OB11MessageFile, OB11MessageJson, OB11MessageMixType, OB11MessageMusic, - OB11MessageNode, OB11MessageVideo, + OB11MessageNode, + OB11MessageVideo, OB11PostSendMsg, } from '../../types' import { NTQQMsgApi, Peer } from '../../../ntqqapi/api/msg' @@ -177,11 +179,18 @@ export async function createSendElements( } } break - case OB11MessageDataType.mface: { - sendElements.push( - SendMsgElementConstructor.mface(sendMsg.data.emoji_package_id, sendMsg.data.emoji_id, sendMsg.data.key, sendMsg.data.summary), - ) - }break; + case OB11MessageDataType.mface: + { + sendElements.push( + SendMsgElementConstructor.mface( + sendMsg.data.emoji_package_id, + sendMsg.data.emoji_id, + sendMsg.data.key, + sendMsg.data.summary, + ), + ) + } + break case OB11MessageDataType.image: case OB11MessageDataType.file: case OB11MessageDataType.video: @@ -303,14 +312,14 @@ export class SendMsg extends BaseAction { protected async check(payload: OB11PostSendMsg): Promise { const messages = convertMessage2List(payload.message) - const fmNum = this.getSpecialMsgNum(payload, OB11MessageDataType.node) + const fmNum = this.getSpecialMsgNum(messages, OB11MessageDataType.node) if (fmNum && fmNum != messages.length) { return { valid: false, message: '转发消息不能和普通消息混在一起发送,转发需要保证message只有type为node的元素', } } - const musicNum = this.getSpecialMsgNum(payload, OB11MessageDataType.music) + const musicNum = this.getSpecialMsgNum(messages, OB11MessageDataType.music) if (musicNum && messages.length > 1) { return { valid: false, @@ -382,14 +391,14 @@ export class SendMsg extends BaseAction { payload.message, payload.auto_escape === true || payload.auto_escape === 'true', ) - if (this.getSpecialMsgNum(payload, OB11MessageDataType.node)) { + if (this.getSpecialMsgNum(messages, OB11MessageDataType.node)) { try { const returnMsg = await this.handleForwardNode(peer, messages as OB11MessageNode[], group) return { message_id: returnMsg.msgShortId } } catch (e) { throw '发送转发消息失败 ' + e.toString() } - } else if (this.getSpecialMsgNum(payload, OB11MessageDataType.music)) { + } else if (this.getSpecialMsgNum(messages, OB11MessageDataType.music)) { const music = messages[0] as OB11MessageMusic if (music) { const { musicSignUrl } = getConfigUtil().getConfig() @@ -402,24 +411,23 @@ export class SendMsg extends BaseAction { } const postData: MusicSignPostData = { ...music.data } if (type === 'custom' && music.data.content) { - ;(postData as CustomMusicSignPostData).singer = music.data.content delete (postData as OB11MessageCustomMusic['data']).content } - if (type === 'custom'){ + if (type === 'custom') { const customMusicData = music.data as CustomMusicSignPostData - if (!customMusicData.url){ - throw ('自定义音卡缺少参数url'); + if (!customMusicData.url) { + throw '自定义音卡缺少参数url' } - if (!customMusicData.audio){ - throw('自定义音卡缺少参数audio'); + if (!customMusicData.audio) { + throw '自定义音卡缺少参数audio' } - if (!customMusicData.title){ - throw('自定义音卡缺少参数title'); + if (!customMusicData.title) { + throw '自定义音卡缺少参数title' } } if (type === 'qq' || type === '163') { - const idMusicData = music.data as IdMusicSignPostData; + const idMusicData = music.data as IdMusicSignPostData if (!idMusicData.id) { throw '音乐卡片缺少id参数' } @@ -448,9 +456,9 @@ export class SendMsg extends BaseAction { return { message_id: returnMsg.msgShortId } } - private getSpecialMsgNum(payload: OB11PostSendMsg, msgType: OB11MessageDataType): number { - if (Array.isArray(payload.message)) { - return payload.message.filter((msg) => msg.type == msgType).length + private getSpecialMsgNum(message: OB11MessageData[], msgType: OB11MessageDataType): number { + if (Array.isArray(message)) { + return message.filter((msg) => msg.type == msgType).length } return 0 } diff --git a/tsconfig.json b/tsconfig.json index c149942..c8fda22 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,8 +7,9 @@ "esModuleInterop": true, "allowJs": true, "allowSyntheticDefaultImports": true, - "moduleResolution": "node" - // "sourceMap": true + "moduleResolution": "node", + // "sourceMap": true, + "noEmit": true }, "include": ["src/*", "src/**/*", "scripts/*"], "exclude": ["node_modules"] From 627955e7fdfbbd27b89e449e563f37c478e3440d Mon Sep 17 00:00:00 2001 From: student_2333 Date: Fri, 10 May 2024 13:34:49 +0800 Subject: [PATCH 3/3] chore: format --- manifest.json | 8 +- src/common/config.ts | 9 +- src/common/data.ts | 11 +- src/common/types.ts | 2 +- src/main/main.ts | 24 ++- src/ntqqapi/api/file.ts | 201 +++++++++++------- src/ntqqapi/api/msg.ts | 2 +- src/ntqqapi/constructor.ts | 10 +- src/ntqqapi/external/cpmodule.ts | 16 +- src/ntqqapi/external/crychic/index.ts | 88 ++++---- src/ntqqapi/external/moehook/hook.ts | 27 ++- src/ntqqapi/types/notify.ts | 4 +- src/onebot11/action/group/GetGroupList.ts | 7 +- .../action/group/GetGroupMemberList.ts | 2 +- src/onebot11/action/user/GetFriendList.ts | 2 +- src/onebot11/constructor.ts | 94 ++++---- .../event/notice/OB11FriendAddNoticeEvent.ts | 10 +- src/onebot11/types.ts | 2 +- test/check_image_url.js | 20 +- 19 files changed, 291 insertions(+), 248 deletions(-) diff --git a/manifest.json b/manifest.json index dca5fd4..bbf3bc5 100644 --- a/manifest.json +++ b/manifest.json @@ -20,14 +20,10 @@ "name": "LLOneBot.zip" } }, - "platform": [ - "win32", - "linux", - "darwin" - ], + "platform": ["win32", "linux", "darwin"], "injects": { "renderer": "./renderer/index.js", "main": "./main/main.cjs", "preload": "./preload/preload.cjs" } -} \ No newline at end of file +} diff --git a/src/common/config.ts b/src/common/config.ts index 97988d3..b6e1f4c 100644 --- a/src/common/config.ts +++ b/src/common/config.ts @@ -82,9 +82,12 @@ export class ConfigUtil { fs.writeFileSync(this.configPath, JSON.stringify(config, null, 2), 'utf-8') } - private checkOldConfig(currentConfig: Config | OB11Config, - oldConfig: Config | OB11Config, - currentKey: string, oldKey: string) { + private checkOldConfig( + currentConfig: Config | OB11Config, + oldConfig: Config | OB11Config, + currentKey: string, + oldKey: string, + ) { // 迁移旧的配置到新配置,避免用户重新填写配置 const oldValue = oldConfig[oldKey] if (oldValue) { diff --git a/src/common/data.ts b/src/common/data.ts index 0bd6744..5532c7f 100644 --- a/src/common/data.ts +++ b/src/common/data.ts @@ -27,13 +27,13 @@ export async function getFriend(uinOrUid: string): Promise { let friend = friends.find((friend) => friend[filterKey] === filterValue.toString()) if (!friend) { try { - const _friends = (await NTQQFriendApi.getFriends(true)) - friend = _friends.find(friend => friend[filterKey] === filterValue.toString()) - if (friend){ + const _friends = await NTQQFriendApi.getFriends(true) + friend = _friends.find((friend) => friend[filterKey] === filterValue.toString()) + if (friend) { friends.push(friend) } } catch (e) { - log("刷新好友列表失败", e.stack.toString()) + log('刷新好友列表失败', e.stack.toString()) } } return friend @@ -48,8 +48,7 @@ export async function getGroup(qq: string): Promise { if (group) { groups.push(group) } - } catch (e) { - } + } catch (e) {} } return group } diff --git a/src/common/types.ts b/src/common/types.ts index b0a3b90..c98795f 100644 --- a/src/common/types.ts +++ b/src/common/types.ts @@ -12,7 +12,7 @@ export interface OB11Config { enableHttpHeart?: boolean } export interface CheckVersion { - result: boolean, + result: boolean version: string } export interface Config { diff --git a/src/main/main.ts b/src/main/main.ts index c12ac53..e76f4a4 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -198,7 +198,6 @@ function onLoad() { postOB11Event(friendAddEvent) } }) - } } @@ -225,25 +224,25 @@ function onLoad() { log('report message error: ', e.stack.toString()) } }) - const recallMsgIds: string[] = []; // 避免重复上报 + const recallMsgIds: string[] = [] // 避免重复上报 registerReceiveHook<{ msgList: Array }>([ReceiveCmdS.UPDATE_MSG], async (payload) => { for (const message of payload.msgList) { - log("message update", message.msgId, message) + log('message update', message.msgId, message) if (message.recallTime != '0') { if (recallMsgIds.includes(message.msgId)) { continue } - recallMsgIds.push(message.msgId); + recallMsgIds.push(message.msgId) const oriMessage = await dbUtil.getMsgByLongId(message.msgId) if (!oriMessage) { continue } oriMessage.recallTime = message.recallTime dbUtil.updateMsg(oriMessage).then() - message.msgShortId = oriMessage.msgShortId; + message.msgShortId = oriMessage.msgShortId OB11Constructor.RecallEvent(message).then((recallEvent) => { if (recallEvent) { - log("post recall event", recallEvent); + log('post recall event', recallEvent) postOB11Event(recallEvent) } }) @@ -301,7 +300,11 @@ function onLoad() { // if (notify.user2.uid) { // member2 = await getGroupMember(notify.group.groupCode, null, notify.user2.uid); // } - if ([GroupNotifyTypes.ADMIN_SET, GroupNotifyTypes.ADMIN_UNSET, GroupNotifyTypes.ADMIN_UNSET_OTHER].includes(notify.type)) { + if ( + [GroupNotifyTypes.ADMIN_SET, GroupNotifyTypes.ADMIN_UNSET, GroupNotifyTypes.ADMIN_UNSET_OTHER].includes( + notify.type, + ) + ) { const member1 = await getGroupMember(notify.group.groupCode, notify.user1.uid) log('有管理员变动通知') refreshGroupMembers(notify.group.groupCode).then() @@ -311,7 +314,12 @@ function onLoad() { if (member1) { log('变动管理员获取成功') groupAdminNoticeEvent.user_id = parseInt(member1.uin) - groupAdminNoticeEvent.sub_type = [GroupNotifyTypes.ADMIN_UNSET, GroupNotifyTypes.ADMIN_UNSET_OTHER].includes(notify.type) ? 'unset' : 'set' + groupAdminNoticeEvent.sub_type = [ + GroupNotifyTypes.ADMIN_UNSET, + GroupNotifyTypes.ADMIN_UNSET_OTHER, + ].includes(notify.type) + ? 'unset' + : 'set' // member1.role = notify.type == GroupNotifyTypes.ADMIN_SET ? GroupMemberRole.admin : GroupMemberRole.normal; postOB11Event(groupAdminNoticeEvent, true) } else { diff --git a/src/ntqqapi/api/file.ts b/src/ntqqapi/api/file.ts index b376d51..58eb022 100644 --- a/src/ntqqapi/api/file.ts +++ b/src/ntqqapi/api/file.ts @@ -7,7 +7,10 @@ import { ChatCacheList, ChatCacheListItemBasic, ChatType, - ElementType, IMAGE_HTTP_HOST, IMAGE_HTTP_HOST_NT, RawMessage, + ElementType, + IMAGE_HTTP_HOST, + IMAGE_HTTP_HOST_NT, + RawMessage, } from '../types' import path from 'path' import fs from 'fs' @@ -26,7 +29,9 @@ const rkeyExpireTime = 1000 * 60 * 30 export class NTQQFileApi { static async getFileType(filePath: string) { return await callNTQQApi<{ ext: string }>({ - className: NTQQApiClass.FS_API, methodName: NTQQApiMethod.FILE_TYPE, args: [filePath], + className: NTQQApiClass.FS_API, + methodName: NTQQApiMethod.FILE_TYPE, + args: [filePath], }) } @@ -42,16 +47,20 @@ export class NTQQFileApi { return await callNTQQApi({ className: NTQQApiClass.FS_API, methodName: NTQQApiMethod.FILE_COPY, - args: [{ - fromPath: filePath, - toPath: destPath, - }], + args: [ + { + fromPath: filePath, + toPath: destPath, + }, + ], }) } static async getFileSize(filePath: string) { return await callNTQQApi({ - className: NTQQApiClass.FS_API, methodName: NTQQApiMethod.FILE_SIZE, args: [filePath], + className: NTQQApiClass.FS_API, + methodName: NTQQApiMethod.FILE_SIZE, + args: [filePath], }) } @@ -70,18 +79,20 @@ export class NTQQFileApi { } const mediaPath = await callNTQQApi({ methodName: NTQQApiMethod.MEDIA_FILE_PATH, - args: [{ - path_info: { - md5HexStr: md5, - fileName: fileName, - elementType: elementType, - elementSubType, - thumbSize: 0, - needCreate: true, - downloadType: 1, - file_uuid: '', + args: [ + { + path_info: { + md5HexStr: md5, + fileName: fileName, + elementType: elementType, + elementSubType, + thumbSize: 0, + needCreate: true, + downloadType: 1, + file_uuid: '', + }, }, - }], + ], }) log('media path', mediaPath) await NTQQFileApi.copyFile(filePath, mediaPath) @@ -95,7 +106,15 @@ export class NTQQFileApi { } } - static async downloadMedia(msgId: string, chatType: ChatType, peerUid: string, elementId: string, thumbPath: string, sourcePath: string, force: boolean = false) { + static async downloadMedia( + msgId: string, + chatType: ChatType, + peerUid: string, + elementId: string, + thumbPath: string, + sourcePath: string, + force: boolean = false, + ) { // 用于下载收到的消息中的图片等 if (sourcePath && fs.existsSync(sourcePath)) { if (force) { @@ -126,7 +145,7 @@ export class NTQQFileApi { methodName: NTQQApiMethod.DOWNLOAD_MEDIA, args: apiParams, cbCmd: ReceiveCmdS.MEDIA_DOWNLOAD_COMPLETE, - cmdCB: (payload: { notifyInfo: { filePath: string, msgId: string } }) => { + cmdCB: (payload: { notifyInfo: { filePath: string; msgId: string } }) => { log('media 下载完成判断', payload.notifyInfo.msgId, msgId) return payload.notifyInfo.msgId == msgId }, @@ -135,18 +154,20 @@ export class NTQQFileApi { } static async getImageSize(filePath: string) { - return await callNTQQApi<{ width: number, height: number }>({ - className: NTQQApiClass.FS_API, methodName: NTQQApiMethod.IMAGE_SIZE, args: [filePath], + return await callNTQQApi<{ width: number; height: number }>({ + className: NTQQApiClass.FS_API, + methodName: NTQQApiMethod.IMAGE_SIZE, + args: [filePath], }) } static async getImageUrl(msg: RawMessage) { const isPrivateImage = msg.chatType !== ChatType.group - const msgElement = msg.elements.find(e => !!e.picElement) + const msgElement = msg.elements.find((e) => !!e.picElement) if (!msgElement) { return '' } - const url = msgElement.picElement.originImageUrl // 没有域名 + const url = msgElement.picElement.originImageUrl // 没有域名 const md5HexStr = msgElement.picElement.md5HexStr const fileMd5 = msgElement.picElement.md5HexStr const fileUuid = msgElement.picElement.fileUuid @@ -174,8 +195,17 @@ export class NTQQFileApi { const refreshRKey = async () => { log('获取图片rkey...') - NTQQFileApi.downloadMedia(msg.msgId, msg.chatType, msg.peerUid, msgElement.elementId, '', msgElement.picElement.sourcePath, false).then().catch(() => { - }) + NTQQFileApi.downloadMedia( + msg.msgId, + msg.chatType, + msg.peerUid, + msgElement.elementId, + '', + msgElement.picElement.sourcePath, + false, + ) + .then() + .catch(() => {}) await sleep(1000) const _rkey = hookApi.getRKey() if (_rkey) { @@ -183,20 +213,22 @@ export class NTQQFileApi { // 验证_rkey是否有效 try { await new Promise((res, rej) => { - https.get(imageUrl, response => { - if (response.statusCode !== 200) { - rej('图片rkey获取失败') - } else { - res(response) - } - }).on('error', e => { - rej(e) - }) + https + .get(imageUrl, (response) => { + if (response.statusCode !== 200) { + rej('图片rkey获取失败') + } else { + res(response) + } + }) + .on('error', (e) => { + rej(e) + }) }) log('图片rkey获取成功', _rkey) saveRKey(_rkey) return _rkey - }catch (e) { + } catch (e) { log('图片rkey有误', imageUrl) } } @@ -204,14 +236,14 @@ export class NTQQFileApi { const existsRKey = isPrivateImage ? privateImageRKey : groupImageRKey const lastGetRKeyTime = isPrivateImage ? lastGetPrivateRKeyTime : lastGetGroupRKeyTime - if ((Date.now() - lastGetRKeyTime > rkeyExpireTime)) { + if (Date.now() - lastGetRKeyTime > rkeyExpireTime) { // rkey过期 const newRKey = await refreshRKey() if (newRKey) { return IMAGE_HTTP_HOST_NT + url + `${newRKey}` } else { log('图片rkey获取失败', url) - if(existsRKey){ + if (existsRKey) { return IMAGE_HTTP_HOST_NT + url + `${existsRKey}` } return '' @@ -225,52 +257,62 @@ export class NTQQFileApi { // 老的图片url,不需要rkey return IMAGE_HTTP_HOST + url } - } - else if (fileMd5 || md5HexStr) { + } else if (fileMd5 || md5HexStr) { // 没有url,需要自己拼接 return `${IMAGE_HTTP_HOST}/gchatpic_new/0/0-0-${(fileMd5 || md5HexStr)!.toUpperCase()}/0` } log('图片url获取失败', msg) return '' } - } export class NTQQFileCacheApi { static async setCacheSilentScan(isSilent: boolean = true) { return await callNTQQApi({ methodName: NTQQApiMethod.CACHE_SET_SILENCE, - args: [{ - isSilent, - }, null], + args: [ + { + isSilent, + }, + null, + ], }) } static getCacheSessionPathList() { - return callNTQQApi<{ - key: string, - value: string - }[]>({ + return callNTQQApi< + { + key: string + value: string + }[] + >({ className: NTQQApiClass.OS_API, methodName: NTQQApiMethod.CACHE_PATH_SESSION, }) } static clearCache(cacheKeys: Array = ['tmp', 'hotUpdate']) { - return callNTQQApi({ // TODO: 目前还不知道真正的返回值是什么 + return callNTQQApi({ + // TODO: 目前还不知道真正的返回值是什么 methodName: NTQQApiMethod.CACHE_CLEAR, - args: [{ - keys: cacheKeys, - }, null], + args: [ + { + keys: cacheKeys, + }, + null, + ], }) } static addCacheScannedPaths(pathMap: object = {}) { return callNTQQApi({ methodName: NTQQApiMethod.CACHE_ADD_SCANNED_PATH, - args: [{ - pathMap: { ...pathMap }, - }, null], + args: [ + { + pathMap: { ...pathMap }, + }, + null, + ], }) } @@ -304,14 +346,18 @@ export class NTQQFileCacheApi { return new Promise((res, rej) => { callNTQQApi({ methodName: NTQQApiMethod.CACHE_CHAT_GET, - args: [{ - chatType: type, - pageSize, - order: 1, - pageIndex, - }, null], - }).then(list => res(list)) - .catch(e => rej(e)) + args: [ + { + chatType: type, + pageSize, + order: 1, + pageIndex, + }, + null, + ], + }) + .then((list) => res(list)) + .catch((e) => rej(e)) }) } @@ -320,24 +366,29 @@ export class NTQQFileCacheApi { return callNTQQApi({ methodName: NTQQApiMethod.CACHE_FILE_GET, - args: [{ - fileType: fileType, - restart: true, - pageSize: pageSize, - order: 1, - lastRecord: _lastRecord, - }, null], + args: [ + { + fileType: fileType, + restart: true, + pageSize: pageSize, + order: 1, + lastRecord: _lastRecord, + }, + null, + ], }) } static async clearChatCache(chats: ChatCacheListItemBasic[] = [], fileKeys: string[] = []) { return await callNTQQApi({ methodName: NTQQApiMethod.CACHE_CHAT_CLEAR, - args: [{ - chats, - fileKeys, - }, null], + args: [ + { + chats, + fileKeys, + }, + null, + ], }) } - } diff --git a/src/ntqqapi/api/msg.ts b/src/ntqqapi/api/msg.ts index fc2d5fd..0daa919 100644 --- a/src/ntqqapi/api/msg.ts +++ b/src/ntqqapi/api/msg.ts @@ -20,7 +20,7 @@ export class NTQQMsgApi { // 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(); + emojiId = emojiId.toString() return await callNTQQApi({ methodName: NTQQApiMethod.EMOJI_LIKE, args: [ diff --git a/src/ntqqapi/constructor.ts b/src/ntqqapi/constructor.ts index e8b9b8b..344a25e 100644 --- a/src/ntqqapi/constructor.ts +++ b/src/ntqqapi/constructor.ts @@ -23,7 +23,7 @@ import { defaultVideoThumb, getVideoInfo } from '../common/utils/video' import { encodeSilk } from '../common/utils/audio' import { isNull } from '../common/utils' -export const mFaceCache = new Map(); // emojiId -> faceName +export const mFaceCache = new Map() // emojiId -> faceName export class SendMsgElementConstructor { static poke(groupCode: string, uin: string) { @@ -119,15 +119,15 @@ export class SendMsgElementConstructor { } static async video(filePath: string, fileName: string = '', diyThumbPath: string = ''): Promise { - try{ + try { await fs.stat(filePath) - }catch (e) { + } catch (e) { throw `文件${filePath}异常,不存在` } - log("复制视频到QQ目录", filePath) + log('复制视频到QQ目录', filePath) let { fileName: _fileName, path, fileSize, md5 } = await NTQQFileApi.uploadFile(filePath, ElementType.VIDEO) - log("复制视频到QQ目录完成", path) + log('复制视频到QQ目录完成', path) if (fileSize === 0) { throw '文件异常,大小为0' } diff --git a/src/ntqqapi/external/cpmodule.ts b/src/ntqqapi/external/cpmodule.ts index ab98263..da6820e 100644 --- a/src/ntqqapi/external/cpmodule.ts +++ b/src/ntqqapi/external/cpmodule.ts @@ -1,6 +1,6 @@ -import * as os from "os"; -import path from "node:path"; -import fs from "fs"; +import * as os from 'os' +import path from 'node:path' +import fs from 'fs' export function getModuleWithArchName(moduleName: string) { const systemPlatform = os.platform() @@ -9,11 +9,9 @@ export function getModuleWithArchName(moduleName: string) { } export function cpModule(moduleName: string) { - const currentDir = path.resolve(__dirname); + const currentDir = path.resolve(__dirname) const fileName = `./${getModuleWithArchName(moduleName)}` try { - fs.copyFileSync(path.join(currentDir, fileName), path.join(currentDir, `${moduleName}.node`)); - } catch (e) { - - } -} \ No newline at end of file + fs.copyFileSync(path.join(currentDir, fileName), path.join(currentDir, `${moduleName}.node`)) + } catch (e) {} +} diff --git a/src/ntqqapi/external/crychic/index.ts b/src/ntqqapi/external/crychic/index.ts index 6de1418..8145ced 100644 --- a/src/ntqqapi/external/crychic/index.ts +++ b/src/ntqqapi/external/crychic/index.ts @@ -1,54 +1,54 @@ -import {log} from "../../../common/utils"; -import {NTQQApi} from "../../ntcall"; -import {cpModule} from "../cpmodule"; +import { log } from '../../../common/utils' +import { NTQQApi } from '../../ntcall' +import { cpModule } from '../cpmodule' type PokeHandler = (id: string, isGroup: boolean) => void type CrychicHandler = (event: string, id: string, isGroup: boolean) => void let pokeRecords: Record = {} -class Crychic{ - private crychic: any = undefined +class Crychic { + private crychic: any = undefined - loadNode(){ - if (!this.crychic){ - try { - cpModule('crychic'); - this.crychic = require("./crychic.node") - this.crychic.init() - }catch (e) { - log("crychic加载失败", e) - } + loadNode() { + if (!this.crychic) { + try { + cpModule('crychic') + this.crychic = require('./crychic.node') + this.crychic.init() + } catch (e) { + log('crychic加载失败', e) + } + } + } + registerPokeHandler(fn: PokeHandler) { + this.registerHandler((event, id, isGroup) => { + if (event === 'poke') { + let existTime = pokeRecords[id] + if (existTime) { + if (Date.now() - existTime < 1500) { + return + } } - } - registerPokeHandler(fn: PokeHandler){ - this.registerHandler((event, id, isGroup)=>{ - if (event === "poke"){ - let existTime = pokeRecords[id] - if (existTime) { - if (Date.now() - existTime < 1500) { - return - } - } - pokeRecords[id] = Date.now() - fn(id, isGroup); - } - }) - } - registerHandler(fn: CrychicHandler){ - if (!this.crychic) return; - this.crychic.setCryHandler(fn) - } - sendFriendPoke(friendUid: string){ - if (!this.crychic) return; - this.crychic.sendFriendPoke(parseInt(friendUid)) - NTQQApi.fetchUnitedCommendConfig().then() - } - sendGroupPoke(groupCode: string, memberUin: string){ - if (!this.crychic) return; - this.crychic.sendGroupPoke(parseInt(memberUin), parseInt(groupCode)) - NTQQApi.fetchUnitedCommendConfig().then() - } + pokeRecords[id] = Date.now() + fn(id, isGroup) + } + }) + } + registerHandler(fn: CrychicHandler) { + if (!this.crychic) return + this.crychic.setCryHandler(fn) + } + sendFriendPoke(friendUid: string) { + if (!this.crychic) return + this.crychic.sendFriendPoke(parseInt(friendUid)) + NTQQApi.fetchUnitedCommendConfig().then() + } + sendGroupPoke(groupCode: string, memberUin: string) { + if (!this.crychic) return + this.crychic.sendGroupPoke(parseInt(memberUin), parseInt(groupCode)) + NTQQApi.fetchUnitedCommendConfig().then() + } } -export const crychic = new Crychic() \ No newline at end of file +export const crychic = new Crychic() diff --git a/src/ntqqapi/external/moehook/hook.ts b/src/ntqqapi/external/moehook/hook.ts index a1dd5fb..f4f61b3 100644 --- a/src/ntqqapi/external/moehook/hook.ts +++ b/src/ntqqapi/external/moehook/hook.ts @@ -1,34 +1,33 @@ -import * as os from "os"; -import fs from "fs"; -import path from "node:path"; -import {cpModule} from "../cpmodule"; +import * as os from 'os' +import fs from 'fs' +import path from 'node:path' +import { cpModule } from '../cpmodule' interface MoeHook { - GetRkey: () => string, // Return '&rkey=xxx' + GetRkey: () => string // Return '&rkey=xxx' HookRkey: () => string } - class HookApi { - private readonly moeHook: MoeHook | null = null; + private readonly moeHook: MoeHook | null = null constructor() { - cpModule('MoeHoo'); + cpModule('MoeHoo') try { - this.moeHook = require('./MoeHoo.node'); - console.log("hook rkey地址", this.moeHook!.HookRkey()); + this.moeHook = require('./MoeHoo.node') + console.log('hook rkey地址', this.moeHook!.HookRkey()) } catch (e) { - console.log('加载 moehoo 失败', e); + console.log('加载 moehoo 失败', e) } } getRKey(): string { - return this.moeHook?.GetRkey() || ''; + return this.moeHook?.GetRkey() || '' } isAvailable() { - return !!this.moeHook; + return !!this.moeHook } } -export const hookApi = new HookApi(); +export const hookApi = new HookApi() diff --git a/src/ntqqapi/types/notify.ts b/src/ntqqapi/types/notify.ts index c568dfc..b578c28 100644 --- a/src/ntqqapi/types/notify.ts +++ b/src/ntqqapi/types/notify.ts @@ -5,8 +5,8 @@ export enum GroupNotifyTypes { ADMIN_SET = 8, KICK_MEMBER = 9, MEMBER_EXIT = 11, // 主动退出 - ADMIN_UNSET = 12, // 我被取消管理员 - ADMIN_UNSET_OTHER = 13, // 其他人取消管理员 + ADMIN_UNSET = 12, // 我被取消管理员 + ADMIN_UNSET_OTHER = 13, // 其他人取消管理员 } export interface GroupNotifies { diff --git a/src/onebot11/action/group/GetGroupList.ts b/src/onebot11/action/group/GetGroupList.ts index b5c2ae5..8d1e0be 100644 --- a/src/onebot11/action/group/GetGroupList.ts +++ b/src/onebot11/action/group/GetGroupList.ts @@ -14,13 +14,10 @@ class GetGroupList extends BaseAction { actionName = ActionName.GetGroupList protected async _handle(payload: Payload) { - if ( - groups.length === 0 - || payload?.no_cache === true || payload?.no_cache === 'true' - ) { + if (groups.length === 0 || payload?.no_cache === true || payload?.no_cache === 'true') { try { const groups = await NTQQGroupApi.getGroups(true) - log("强制刷新群列表, 数量:", groups.length) + log('强制刷新群列表, 数量:', groups.length) return OB11Constructor.groups(groups) } catch (e) {} } diff --git a/src/onebot11/action/group/GetGroupMemberList.ts b/src/onebot11/action/group/GetGroupMemberList.ts index 2c541f8..150426b 100644 --- a/src/onebot11/action/group/GetGroupMemberList.ts +++ b/src/onebot11/action/group/GetGroupMemberList.ts @@ -7,7 +7,7 @@ import { NTQQGroupApi } from '../../../ntqqapi/api/group' import { log } from '../../../common/utils' export interface PayloadType { - group_id: number, + group_id: number no_cache: boolean | string } diff --git a/src/onebot11/action/user/GetFriendList.ts b/src/onebot11/action/user/GetFriendList.ts index 00ee660..4408ff3 100644 --- a/src/onebot11/action/user/GetFriendList.ts +++ b/src/onebot11/action/user/GetFriendList.ts @@ -6,7 +6,7 @@ import { ActionName } from '../types' import { NTQQFriendApi } from '../../../ntqqapi/api' import { log } from '../../../common/utils' -interface Payload{ +interface Payload { no_cache: boolean | string } diff --git a/src/onebot11/constructor.ts b/src/onebot11/constructor.ts index f5a6652..7eb28a5 100644 --- a/src/onebot11/constructor.ts +++ b/src/onebot11/constructor.ts @@ -87,15 +87,13 @@ export class OB11Constructor { resMsg.sender.role = OB11Constructor.groupMemberRole(member.role) resMsg.sender.nickname = member.nick } - } - else if (msg.chatType == ChatType.friend) { + } else if (msg.chatType == ChatType.friend) { resMsg.sub_type = 'friend' const friend = await getFriend(msg.senderUin) if (friend) { resMsg.sender.nickname = friend.nick } - } - else if (msg.chatType == ChatType.temp) { + } else if (msg.chatType == ChatType.temp) { resMsg.sub_type = 'group' const tempGroupCode = tempGroupCodeMap[msg.peerUin] if (tempGroupCode) { @@ -113,8 +111,7 @@ export class OB11Constructor { if (element.textElement.atType == AtType.atAll) { // message_data["data"]["mention"] = "all" message_data['data']['qq'] = 'all' - } - else { + } else { let atUid = element.textElement.atNtUid let atQQ = element.textElement.atUid if (!atQQ || atQQ === '0') { @@ -128,16 +125,14 @@ export class OB11Constructor { message_data['data']['qq'] = atQQ } } - } - else if (element.textElement) { + } else if (element.textElement) { message_data['type'] = 'text' let text = element.textElement.content if (!text.trim()) { continue } message_data['data']['text'] = text - } - else if (element.replyElement) { + } else if (element.replyElement) { message_data['type'] = 'reply' // log("收到回复消息", element.replyElement.replayMsgSeq) try { @@ -145,15 +140,13 @@ export class OB11Constructor { // log("找到回复消息", replyMsg.msgShortId, replyMsg.msgId) if (replyMsg) { message_data['data']['id'] = replyMsg.msgShortId.toString() - } - else { + } else { continue } } catch (e) { log('获取不到引用的消息', e.stack, element.replyElement.replayMsgSeq) } - } - else if (element.picElement) { + } else if (element.picElement) { message_data['type'] = 'image' // message_data["data"]["file"] = element.picElement.sourcePath message_data['data']['file'] = element.picElement.fileName @@ -182,8 +175,7 @@ export class OB11Constructor { }) .then() // 不在自动下载图片 - } - else if (element.videoElement || element.fileElement) { + } else if (element.videoElement || element.fileElement) { const videoOrFileElement = element.videoElement || element.fileElement const ob11MessageDataType = element.videoElement ? OB11MessageDataType.video : OB11MessageDataType.file message_data['type'] = ob11MessageDataType @@ -212,8 +204,7 @@ export class OB11Constructor { }) .then() // 怎么拿到url呢 - } - else if (element.pttElement) { + } else if (element.pttElement) { message_data['type'] = OB11MessageDataType.voice message_data['data']['file'] = element.pttElement.fileName message_data['data']['path'] = element.pttElement.filePath @@ -233,27 +224,22 @@ export class OB11Constructor { // }).catch(err => { // console.log("语音转文字失败", err); // }) - } - else if (element.arkElement) { + } else if (element.arkElement) { message_data['type'] = OB11MessageDataType.json message_data['data']['data'] = element.arkElement.bytesData - } - else if (element.faceElement) { + } else if (element.faceElement) { const faceId = element.faceElement.faceIndex if (faceId === FaceIndex.dice) { message_data['type'] = OB11MessageDataType.dice message_data['data']['result'] = element.faceElement.resultId - } - else if (faceId === FaceIndex.RPS) { + } else if (faceId === FaceIndex.RPS) { message_data['type'] = OB11MessageDataType.RPS message_data['data']['result'] = element.faceElement.resultId - } - else { + } else { message_data['type'] = OB11MessageDataType.face message_data['data']['id'] = element.faceElement.faceIndex.toString() } - } - else if (element.marketFaceElement) { + } else if (element.marketFaceElement) { message_data['type'] = OB11MessageDataType.mface message_data['data']['summary'] = element.marketFaceElement.faceName const md5 = element.marketFaceElement.emojiId @@ -267,12 +253,10 @@ export class OB11Constructor { message_data['data']['emoji_package_id'] = String(element.marketFaceElement.emojiPackageId) message_data['data']['key'] = element.marketFaceElement.key mFaceCache.set(md5, element.marketFaceElement.faceName) - } - else if (element.markdownElement) { + } else if (element.markdownElement) { message_data['type'] = OB11MessageDataType.markdown message_data['data']['data'] = element.markdownElement.content - } - else if (element.multiForwardMsgElement) { + } else if (element.multiForwardMsgElement) { message_data['type'] = OB11MessageDataType.forward message_data['data']['id'] = msg.msgId } @@ -280,8 +264,7 @@ export class OB11Constructor { const cqCode = encodeCQCode(message_data) if (messagePostFormat === 'string') { ;(resMsg.message as string) += cqCode - } - else (resMsg.message as OB11MessageData[]).push(message_data) + } else (resMsg.message as OB11MessageData[]).push(message_data) resMsg.raw_message += cqCode } @@ -330,8 +313,7 @@ export class OB11Constructor { // log("构造群增加事件", event) return event } - } - else if (groupElement.type === TipGroupElementType.ban) { + } else if (groupElement.type === TipGroupElementType.ban) { log('收到群群员禁言提示', groupElement) const memberUid = groupElement.shutUp.member.uid const adminUid = groupElement.shutUp.admin.uid @@ -342,8 +324,7 @@ export class OB11Constructor { memberUin = (await getGroupMember(msg.peerUid, memberUid))?.uin || (await NTQQUserApi.getUserDetailInfo(memberUid))?.uin - } - else { + } else { memberUin = '0' // 0表示全员禁言 if (duration > 0) { duration = -1 @@ -360,8 +341,7 @@ export class OB11Constructor { sub_type, ) } - } - else if (groupElement.type == TipGroupElementType.kicked) { + } else if (groupElement.type == TipGroupElementType.kicked) { log(`收到我被踢出或退群提示, 群${msg.peerUid}`, groupElement) deleteGroup(msg.peerUid) NTQQGroupApi.quitGroup(msg.peerUid).then() @@ -381,8 +361,7 @@ export class OB11Constructor { return new OB11GroupDecreaseEvent(parseInt(msg.peerUid), parseInt(selfInfo.uin), 0, 'leave') } } - } - else if (element.fileElement) { + } else if (element.fileElement) { return new OB11GroupUploadNoticeEvent(parseInt(msg.peerUid), parseInt(msg.senderUin), { id: element.fileElement.fileUuid, name: element.fileElement.fileName, @@ -447,8 +426,7 @@ export class OB11Constructor { return new OB11GroupIncreaseEvent(parseInt(msg.peerUid), parseInt(invitee), parseInt(inviter), 'invite') } } - } - else if (grayTipElement.subElementType == GrayTipElementSubType.MEMBER_NEW_TITLE) { + } else if (grayTipElement.subElementType == GrayTipElementSubType.MEMBER_NEW_TITLE) { const json = JSON.parse(grayTipElement.jsonGrayTipElement.jsonStr) /* { @@ -497,19 +475,27 @@ export class OB11Constructor { return } - static async RecallEvent(msg: RawMessage): Promise{ - let msgElement = msg.elements.find((element) => element.grayTipElement?.subElementType === GrayTipElementSubType.RECALL); + static async RecallEvent( + msg: RawMessage, + ): Promise { + let msgElement = msg.elements.find( + (element) => element.grayTipElement?.subElementType === GrayTipElementSubType.RECALL, + ) if (!msgElement) { return } - const isGroup = msg.chatType === ChatType.group; - const revokeElement = msgElement.grayTipElement.revokeElement; - if (isGroup){ - const operator = await getGroupMember(msg.peerUid, revokeElement.operatorUid); - const sender = await getGroupMember(msg.peerUid, revokeElement.origMsgSenderUid); - return new OB11GroupRecallNoticeEvent(parseInt(msg.peerUid), parseInt(sender.uin), parseInt(operator.uin), msg.msgShortId) - } - else{ + const isGroup = msg.chatType === ChatType.group + const revokeElement = msgElement.grayTipElement.revokeElement + if (isGroup) { + const operator = await getGroupMember(msg.peerUid, revokeElement.operatorUid) + const sender = await getGroupMember(msg.peerUid, revokeElement.origMsgSenderUid) + return new OB11GroupRecallNoticeEvent( + parseInt(msg.peerUid), + parseInt(sender.uin), + parseInt(operator.uin), + msg.msgShortId, + ) + } else { return new OB11FriendRecallNoticeEvent(parseInt(msg.senderUin), msg.msgShortId) } } diff --git a/src/onebot11/event/notice/OB11FriendAddNoticeEvent.ts b/src/onebot11/event/notice/OB11FriendAddNoticeEvent.ts index 25ea23a..8b85cd0 100644 --- a/src/onebot11/event/notice/OB11FriendAddNoticeEvent.ts +++ b/src/onebot11/event/notice/OB11FriendAddNoticeEvent.ts @@ -1,11 +1,11 @@ -import { OB11BaseNoticeEvent } from './OB11BaseNoticeEvent'; +import { OB11BaseNoticeEvent } from './OB11BaseNoticeEvent' export class OB11FriendAddNoticeEvent extends OB11BaseNoticeEvent { - notice_type = 'friend_add'; - user_id: number; + notice_type = 'friend_add' + user_id: number public constructor(userId: number) { - super(); - this.user_id = userId; + super() + this.user_id = userId } } diff --git a/src/onebot11/types.ts b/src/onebot11/types.ts index 34ab088..de9c2ed 100644 --- a/src/onebot11/types.ts +++ b/src/onebot11/types.ts @@ -75,7 +75,7 @@ export interface OB11Message { self_id?: number time: number message_id: number - message_seq: number // go-cqhttp字段,实际上是message_id + message_seq: number // go-cqhttp字段,实际上是message_id real_id: number user_id: number group_id?: number diff --git a/test/check_image_url.js b/test/check_image_url.js index 7a2a386..a37e091 100644 --- a/test/check_image_url.js +++ b/test/check_image_url.js @@ -1,12 +1,18 @@ import http from 'https' function checkUrl(imageUrl) { - http.get(imageUrl, response => { - console.log(response.statusCode) - }).on('error', e => { - console.log(e) - }) + http + .get(imageUrl, (response) => { + console.log(response.statusCode) + }) + .on('error', (e) => { + console.log(e) + }) } -checkUrl('https://gchat.qpic.cn/download?appid=1407&fileid=CgoxMzMyNTI0MjIxEhRrdaUgQP5MjweWa4uR8pviUDaGQhjcxQUg_wooiYTj39fphQNQgL2jAQ&spec=0&rkey=CAQSKAB6JWENi5LMk0kc62l8Pm3Jn1dsLZHyRLAnNmHGoZ3y_gDZPqZt-64') -checkUrl('https://multimedia.nt.qq.com.cn/download?appid=1407&fileid=CgoxMzMyNTI0MjIxEhRrdaUgQP5MjweWa4uR8pviUDaGQhjcxQUg_wooiYTj39fphQNQgL2jAQ&spec=0&rkey=CAQSKAB6JWENi5LMk0kc62l8Pm3Jn1dsLZHyRLAnNmHGoZ3y_gDZPqZt-64') +checkUrl( + 'https://gchat.qpic.cn/download?appid=1407&fileid=CgoxMzMyNTI0MjIxEhRrdaUgQP5MjweWa4uR8pviUDaGQhjcxQUg_wooiYTj39fphQNQgL2jAQ&spec=0&rkey=CAQSKAB6JWENi5LMk0kc62l8Pm3Jn1dsLZHyRLAnNmHGoZ3y_gDZPqZt-64', +) +checkUrl( + 'https://multimedia.nt.qq.com.cn/download?appid=1407&fileid=CgoxMzMyNTI0MjIxEhRrdaUgQP5MjweWa4uR8pviUDaGQhjcxQUg_wooiYTj39fphQNQgL2jAQ&spec=0&rkey=CAQSKAB6JWENi5LMk0kc62l8Pm3Jn1dsLZHyRLAnNmHGoZ3y_gDZPqZt-64', +)