Merge branch 'main' into dev

# Conflicts:
#	src/ntqqapi/external/cpmodule.ts
#	src/ntqqapi/external/crychic/index.ts
#	src/ntqqapi/external/moehook/hook.ts
#	src/onebot11/action/msg/SendMsg.ts
#	tsconfig.json
This commit is contained in:
linyuchen 2024-05-10 20:28:44 +08:00
commit fdf96b479c
22 changed files with 425 additions and 385 deletions

View File

@ -1,10 +1,10 @@
{ {
"manifest_version": 4, "manifest_version": 4,
"type": "extension", "type": "extension",
"name": "LLOneBot v3.24.1", "name": "LLOneBot v3.24.2",
"slug": "LLOneBot", "slug": "LLOneBot",
"description": "使你的NTQQ支持OneBot11协议进行QQ机器人开发, 不支持商店在线更新", "description": "使你的NTQQ支持OneBot11协议进行QQ机器人开发, 不支持商店在线更新",
"version": "3.24.1", "version": "3.24.2",
"icon": "./icon.jpg", "icon": "./icon.jpg",
"authors": [ "authors": [
{ {
@ -20,11 +20,7 @@
"name": "LLOneBot.zip" "name": "LLOneBot.zip"
} }
}, },
"platform": [ "platform": ["win32", "linux", "darwin"],
"win32",
"linux",
"darwin"
],
"injects": { "injects": {
"renderer": "./renderer/index.js", "renderer": "./renderer/index.js",
"main": "./main/main.cjs", "main": "./main/main.cjs",

View File

@ -10,7 +10,8 @@
"deploy-mac": "cp -r dist/* ~/Library/Containers/com.tencent.qq/Data/LiteLoaderQQNT/plugins/LLOneBot/", "deploy-mac": "cp -r dist/* ~/Library/Containers/com.tencent.qq/Data/LiteLoaderQQNT/plugins/LLOneBot/",
"build-win": "npm run build && npm run deploy-win", "build-win": "npm run build && npm run deploy-win",
"deploy-win": "cmd /c \"xcopy /C /S /Y dist\\* %USERPROFILE%\\documents\\LiteLoaderQQNT\\plugins\\LLOneBot\\\"", "deploy-win": "cmd /c \"xcopy /C /S /Y dist\\* %USERPROFILE%\\documents\\LiteLoaderQQNT\\plugins\\LLOneBot\\\"",
"format": "prettier -cw ." "format": "prettier -cw .",
"check": "tsc"
}, },
"author": "", "author": "",
"license": "MIT", "license": "MIT",

View File

@ -82,9 +82,12 @@ export class ConfigUtil {
fs.writeFileSync(this.configPath, JSON.stringify(config, null, 2), 'utf-8') fs.writeFileSync(this.configPath, JSON.stringify(config, null, 2), 'utf-8')
} }
private checkOldConfig(currentConfig: Config | OB11Config, private checkOldConfig(
currentConfig: Config | OB11Config,
oldConfig: Config | OB11Config, oldConfig: Config | OB11Config,
currentKey: string, oldKey: string) { currentKey: string,
oldKey: string,
) {
// 迁移旧的配置到新配置,避免用户重新填写配置 // 迁移旧的配置到新配置,避免用户重新填写配置
const oldValue = oldConfig[oldKey] const oldValue = oldConfig[oldKey]
if (oldValue) { if (oldValue) {

View File

@ -27,13 +27,13 @@ export async function getFriend(uinOrUid: string): Promise<Friend | undefined> {
let friend = friends.find((friend) => friend[filterKey] === filterValue.toString()) let friend = friends.find((friend) => friend[filterKey] === filterValue.toString())
if (!friend) { if (!friend) {
try { try {
const _friends = (await NTQQFriendApi.getFriends(true)) const _friends = await NTQQFriendApi.getFriends(true)
friend = _friends.find(friend => friend[filterKey] === filterValue.toString()) friend = _friends.find((friend) => friend[filterKey] === filterValue.toString())
if (friend) { if (friend) {
friends.push(friend) friends.push(friend)
} }
} catch (e) { } catch (e) {
log("刷新好友列表失败", e.stack.toString()) log('刷新好友列表失败', e.stack.toString())
} }
} }
return friend return friend
@ -48,8 +48,7 @@ export async function getGroup(qq: string): Promise<Group | undefined> {
if (group) { if (group) {
groups.push(group) groups.push(group)
} }
} catch (e) { } catch (e) {}
}
} }
return group return group
} }

View File

@ -12,7 +12,7 @@ export interface OB11Config {
enableHttpHeart?: boolean enableHttpHeart?: boolean
} }
export interface CheckVersion { export interface CheckVersion {
result: boolean, result: boolean
version: string version: string
} }
export interface Config { export interface Config {

View File

@ -198,7 +198,6 @@ function onLoad() {
postOB11Event(friendAddEvent) postOB11Event(friendAddEvent)
} }
}) })
} }
} }
@ -225,25 +224,25 @@ function onLoad() {
log('report message error: ', e.stack.toString()) log('report message error: ', e.stack.toString())
} }
}) })
const recallMsgIds: string[] = []; // 避免重复上报 const recallMsgIds: string[] = [] // 避免重复上报
registerReceiveHook<{ msgList: Array<RawMessage> }>([ReceiveCmdS.UPDATE_MSG], async (payload) => { registerReceiveHook<{ msgList: Array<RawMessage> }>([ReceiveCmdS.UPDATE_MSG], async (payload) => {
for (const message of payload.msgList) { for (const message of payload.msgList) {
log("message update", message.msgId, message) log('message update', message.msgId, message)
if (message.recallTime != '0') { if (message.recallTime != '0') {
if (recallMsgIds.includes(message.msgId)) { if (recallMsgIds.includes(message.msgId)) {
continue continue
} }
recallMsgIds.push(message.msgId); recallMsgIds.push(message.msgId)
const oriMessage = await dbUtil.getMsgByLongId(message.msgId) const oriMessage = await dbUtil.getMsgByLongId(message.msgId)
if (!oriMessage) { if (!oriMessage) {
continue continue
} }
oriMessage.recallTime = message.recallTime oriMessage.recallTime = message.recallTime
dbUtil.updateMsg(oriMessage).then() dbUtil.updateMsg(oriMessage).then()
message.msgShortId = oriMessage.msgShortId; message.msgShortId = oriMessage.msgShortId
OB11Constructor.RecallEvent(message).then((recallEvent) => { OB11Constructor.RecallEvent(message).then((recallEvent) => {
if (recallEvent) { if (recallEvent) {
log("post recall event", recallEvent); log('post recall event', recallEvent)
postOB11Event(recallEvent) postOB11Event(recallEvent)
} }
}) })
@ -301,7 +300,11 @@ function onLoad() {
// if (notify.user2.uid) { // if (notify.user2.uid) {
// member2 = await getGroupMember(notify.group.groupCode, null, 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) const member1 = await getGroupMember(notify.group.groupCode, notify.user1.uid)
log('有管理员变动通知') log('有管理员变动通知')
refreshGroupMembers(notify.group.groupCode).then() refreshGroupMembers(notify.group.groupCode).then()
@ -311,7 +314,12 @@ function onLoad() {
if (member1) { if (member1) {
log('变动管理员获取成功') log('变动管理员获取成功')
groupAdminNoticeEvent.user_id = parseInt(member1.uin) 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; // member1.role = notify.type == GroupNotifyTypes.ADMIN_SET ? GroupMemberRole.admin : GroupMemberRole.normal;
postOB11Event(groupAdminNoticeEvent, true) postOB11Event(groupAdminNoticeEvent, true)
} else { } else {

View File

@ -7,7 +7,10 @@ import {
ChatCacheList, ChatCacheList,
ChatCacheListItemBasic, ChatCacheListItemBasic,
ChatType, ChatType,
ElementType, IMAGE_HTTP_HOST, IMAGE_HTTP_HOST_NT, RawMessage, ElementType,
IMAGE_HTTP_HOST,
IMAGE_HTTP_HOST_NT,
RawMessage,
} from '../types' } from '../types'
import path from 'path' import path from 'path'
import fs from 'fs' import fs from 'fs'
@ -26,7 +29,9 @@ const rkeyExpireTime = 1000 * 60 * 30
export class NTQQFileApi { export class NTQQFileApi {
static async getFileType(filePath: string) { static async getFileType(filePath: string) {
return await callNTQQApi<{ ext: 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<string>({ return await callNTQQApi<string>({
className: NTQQApiClass.FS_API, className: NTQQApiClass.FS_API,
methodName: NTQQApiMethod.FILE_COPY, methodName: NTQQApiMethod.FILE_COPY,
args: [{ args: [
{
fromPath: filePath, fromPath: filePath,
toPath: destPath, toPath: destPath,
}], },
],
}) })
} }
static async getFileSize(filePath: string) { static async getFileSize(filePath: string) {
return await callNTQQApi<number>({ return await callNTQQApi<number>({
className: NTQQApiClass.FS_API, methodName: NTQQApiMethod.FILE_SIZE, args: [filePath], className: NTQQApiClass.FS_API,
methodName: NTQQApiMethod.FILE_SIZE,
args: [filePath],
}) })
} }
@ -70,7 +79,8 @@ export class NTQQFileApi {
} }
const mediaPath = await callNTQQApi<string>({ const mediaPath = await callNTQQApi<string>({
methodName: NTQQApiMethod.MEDIA_FILE_PATH, methodName: NTQQApiMethod.MEDIA_FILE_PATH,
args: [{ args: [
{
path_info: { path_info: {
md5HexStr: md5, md5HexStr: md5,
fileName: fileName, fileName: fileName,
@ -81,7 +91,8 @@ export class NTQQFileApi {
downloadType: 1, downloadType: 1,
file_uuid: '', file_uuid: '',
}, },
}], },
],
}) })
log('media path', mediaPath) log('media path', mediaPath)
await NTQQFileApi.copyFile(filePath, 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 (sourcePath && fs.existsSync(sourcePath)) {
if (force) { if (force) {
@ -126,7 +145,7 @@ export class NTQQFileApi {
methodName: NTQQApiMethod.DOWNLOAD_MEDIA, methodName: NTQQApiMethod.DOWNLOAD_MEDIA,
args: apiParams, args: apiParams,
cbCmd: ReceiveCmdS.MEDIA_DOWNLOAD_COMPLETE, 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) log('media 下载完成判断', payload.notifyInfo.msgId, msgId)
return payload.notifyInfo.msgId == msgId return payload.notifyInfo.msgId == msgId
}, },
@ -135,14 +154,16 @@ export class NTQQFileApi {
} }
static async getImageSize(filePath: string) { static async getImageSize(filePath: string) {
return await callNTQQApi<{ width: number, height: number }>({ return await callNTQQApi<{ width: number; height: number }>({
className: NTQQApiClass.FS_API, methodName: NTQQApiMethod.IMAGE_SIZE, args: [filePath], className: NTQQApiClass.FS_API,
methodName: NTQQApiMethod.IMAGE_SIZE,
args: [filePath],
}) })
} }
static async getImageUrl(msg: RawMessage) { static async getImageUrl(msg: RawMessage) {
const isPrivateImage = msg.chatType !== ChatType.group const isPrivateImage = msg.chatType !== ChatType.group
const msgElement = msg.elements.find(e => !!e.picElement) const msgElement = msg.elements.find((e) => !!e.picElement)
if (!msgElement) { if (!msgElement) {
return '' return ''
} }
@ -174,8 +195,17 @@ export class NTQQFileApi {
const refreshRKey = async () => { const refreshRKey = async () => {
log('获取图片rkey...') 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) await sleep(1000)
const _rkey = hookApi.getRKey() const _rkey = hookApi.getRKey()
if (_rkey) { if (_rkey) {
@ -183,13 +213,15 @@ export class NTQQFileApi {
// 验证_rkey是否有效 // 验证_rkey是否有效
try { try {
await new Promise((res, rej) => { await new Promise((res, rej) => {
https.get(imageUrl, response => { https
.get(imageUrl, (response) => {
if (response.statusCode !== 200) { if (response.statusCode !== 200) {
rej('图片rkey获取失败') rej('图片rkey获取失败')
} else { } else {
res(response) res(response)
} }
}).on('error', e => { })
.on('error', (e) => {
rej(e) rej(e)
}) })
}) })
@ -204,7 +236,7 @@ export class NTQQFileApi {
const existsRKey = isPrivateImage ? privateImageRKey : groupImageRKey const existsRKey = isPrivateImage ? privateImageRKey : groupImageRKey
const lastGetRKeyTime = isPrivateImage ? lastGetPrivateRKeyTime : lastGetGroupRKeyTime const lastGetRKeyTime = isPrivateImage ? lastGetPrivateRKeyTime : lastGetGroupRKeyTime
if ((Date.now() - lastGetRKeyTime > rkeyExpireTime)) { if (Date.now() - lastGetRKeyTime > rkeyExpireTime) {
// rkey过期 // rkey过期
const newRKey = await refreshRKey() const newRKey = await refreshRKey()
if (newRKey) { if (newRKey) {
@ -225,52 +257,62 @@ export class NTQQFileApi {
// 老的图片url不需要rkey // 老的图片url不需要rkey
return IMAGE_HTTP_HOST + url return IMAGE_HTTP_HOST + url
} }
} } else if (fileMd5 || md5HexStr) {
else if (fileMd5 || md5HexStr) {
// 没有url需要自己拼接 // 没有url需要自己拼接
return `${IMAGE_HTTP_HOST}/gchatpic_new/0/0-0-${(fileMd5 || md5HexStr)!.toUpperCase()}/0` return `${IMAGE_HTTP_HOST}/gchatpic_new/0/0-0-${(fileMd5 || md5HexStr)!.toUpperCase()}/0`
} }
log('图片url获取失败', msg) log('图片url获取失败', msg)
return '' return ''
} }
} }
export class NTQQFileCacheApi { export class NTQQFileCacheApi {
static async setCacheSilentScan(isSilent: boolean = true) { static async setCacheSilentScan(isSilent: boolean = true) {
return await callNTQQApi<GeneralCallResult>({ return await callNTQQApi<GeneralCallResult>({
methodName: NTQQApiMethod.CACHE_SET_SILENCE, methodName: NTQQApiMethod.CACHE_SET_SILENCE,
args: [{ args: [
{
isSilent, isSilent,
}, null], },
null,
],
}) })
} }
static getCacheSessionPathList() { static getCacheSessionPathList() {
return callNTQQApi<{ return callNTQQApi<
key: string, {
key: string
value: string value: string
}[]>({ }[]
>({
className: NTQQApiClass.OS_API, className: NTQQApiClass.OS_API,
methodName: NTQQApiMethod.CACHE_PATH_SESSION, methodName: NTQQApiMethod.CACHE_PATH_SESSION,
}) })
} }
static clearCache(cacheKeys: Array<string> = ['tmp', 'hotUpdate']) { static clearCache(cacheKeys: Array<string> = ['tmp', 'hotUpdate']) {
return callNTQQApi<any>({ // TODO: 目前还不知道真正的返回值是什么 return callNTQQApi<any>({
// TODO: 目前还不知道真正的返回值是什么
methodName: NTQQApiMethod.CACHE_CLEAR, methodName: NTQQApiMethod.CACHE_CLEAR,
args: [{ args: [
{
keys: cacheKeys, keys: cacheKeys,
}, null], },
null,
],
}) })
} }
static addCacheScannedPaths(pathMap: object = {}) { static addCacheScannedPaths(pathMap: object = {}) {
return callNTQQApi<GeneralCallResult>({ return callNTQQApi<GeneralCallResult>({
methodName: NTQQApiMethod.CACHE_ADD_SCANNED_PATH, methodName: NTQQApiMethod.CACHE_ADD_SCANNED_PATH,
args: [{ args: [
{
pathMap: { ...pathMap }, pathMap: { ...pathMap },
}, null], },
null,
],
}) })
} }
@ -304,14 +346,18 @@ export class NTQQFileCacheApi {
return new Promise<ChatCacheList>((res, rej) => { return new Promise<ChatCacheList>((res, rej) => {
callNTQQApi<ChatCacheList>({ callNTQQApi<ChatCacheList>({
methodName: NTQQApiMethod.CACHE_CHAT_GET, methodName: NTQQApiMethod.CACHE_CHAT_GET,
args: [{ args: [
{
chatType: type, chatType: type,
pageSize, pageSize,
order: 1, order: 1,
pageIndex, pageIndex,
}, null], },
}).then(list => res(list)) null,
.catch(e => rej(e)) ],
})
.then((list) => res(list))
.catch((e) => rej(e))
}) })
} }
@ -320,24 +366,29 @@ export class NTQQFileCacheApi {
return callNTQQApi<CacheFileList>({ return callNTQQApi<CacheFileList>({
methodName: NTQQApiMethod.CACHE_FILE_GET, methodName: NTQQApiMethod.CACHE_FILE_GET,
args: [{ args: [
{
fileType: fileType, fileType: fileType,
restart: true, restart: true,
pageSize: pageSize, pageSize: pageSize,
order: 1, order: 1,
lastRecord: _lastRecord, lastRecord: _lastRecord,
}, null], },
null,
],
}) })
} }
static async clearChatCache(chats: ChatCacheListItemBasic[] = [], fileKeys: string[] = []) { static async clearChatCache(chats: ChatCacheListItemBasic[] = [], fileKeys: string[] = []) {
return await callNTQQApi<GeneralCallResult>({ return await callNTQQApi<GeneralCallResult>({
methodName: NTQQApiMethod.CACHE_CHAT_CLEAR, methodName: NTQQApiMethod.CACHE_CHAT_CLEAR,
args: [{ args: [
{
chats, chats,
fileKeys, fileKeys,
}, null], },
null,
],
}) })
} }
} }

View File

@ -74,7 +74,11 @@ export class NTQQGroupApi {
} }
static async getGroupIgnoreNotifies() { static async getGroupIgnoreNotifies() {
await NTQQGroupApi.getGroupNotifies() await NTQQGroupApi.getGroupNotifies()
return await NTQQWindowApi.openWindow(NTQQWindows.GroupNotifyFilterWindow, [], ReceiveCmdS.GROUP_NOTIFY) return await NTQQWindowApi.openWindow<GeneralCallResult & GroupNotifies>(
NTQQWindows.GroupNotifyFilterWindow,
[],
ReceiveCmdS.GROUP_NOTIFY,
)
} }
static async handleGroupRequest(seq: string, operateType: GroupRequestOperateTypes, reason?: string) { static async handleGroupRequest(seq: string, operateType: GroupRequestOperateTypes, reason?: string) {
const notify: GroupNotify = await dbUtil.getGroupNotify(seq) const notify: GroupNotify = await dbUtil.getGroupNotify(seq)

View File

@ -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//sysface_res/apng/ 下可以看到所有QQ表情预览
// nt_qq\global\nt_data\Emoji\emoji-resource\face_config.json 里面有所有表情的id, 自带表情id是QSid, 标准emoji表情id是QCid // 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 // 其实以官方文档为准是最好的https://bot.q.qq.com/wiki/develop/api-v2/openapi/emoji/model.html#EmojiType
emojiId = emojiId.toString(); emojiId = emojiId.toString()
return await callNTQQApi<GeneralCallResult>({ return await callNTQQApi<GeneralCallResult>({
methodName: NTQQApiMethod.EMOJI_LIKE, methodName: NTQQApiMethod.EMOJI_LIKE,
args: [ args: [

View File

@ -23,7 +23,7 @@ import { defaultVideoThumb, getVideoInfo } from '../common/utils/video'
import { encodeSilk } from '../common/utils/audio' import { encodeSilk } from '../common/utils/audio'
import { isNull } from '../common/utils' import { isNull } from '../common/utils'
export const mFaceCache = new Map<string, string>(); // emojiId -> faceName export const mFaceCache = new Map<string, string>() // emojiId -> faceName
export class SendMsgElementConstructor { export class SendMsgElementConstructor {
static poke(groupCode: string, uin: string) { static poke(groupCode: string, uin: string) {
@ -124,10 +124,10 @@ export class SendMsgElementConstructor {
} catch (e) { } catch (e) {
throw `文件${filePath}异常,不存在` throw `文件${filePath}异常,不存在`
} }
log("复制视频到QQ目录", filePath) log('复制视频到QQ目录', filePath)
let { fileName: _fileName, path, fileSize, md5 } = await NTQQFileApi.uploadFile(filePath, ElementType.VIDEO) let { fileName: _fileName, path, fileSize, md5 } = await NTQQFileApi.uploadFile(filePath, ElementType.VIDEO)
log("复制视频到QQ目录完成", path) log('复制视频到QQ目录完成', path)
if (fileSize === 0) { if (fileSize === 0) {
throw '文件异常大小为0' throw '文件异常大小为0'
} }

View File

@ -14,13 +14,10 @@ class GetGroupList extends BaseAction<Payload, OB11Group[]> {
actionName = ActionName.GetGroupList actionName = ActionName.GetGroupList
protected async _handle(payload: Payload) { protected async _handle(payload: Payload) {
if ( if (groups.length === 0 || payload?.no_cache === true || payload?.no_cache === 'true') {
groups.length === 0
|| payload?.no_cache === true || payload?.no_cache === 'true'
) {
try { try {
const groups = await NTQQGroupApi.getGroups(true) const groups = await NTQQGroupApi.getGroups(true)
log("强制刷新群列表, 数量:", groups.length) log('强制刷新群列表, 数量:', groups.length)
return OB11Constructor.groups(groups) return OB11Constructor.groups(groups)
} catch (e) {} } catch (e) {}
} }

View File

@ -7,7 +7,7 @@ import { NTQQGroupApi } from '../../../ntqqapi/api/group'
import { log } from '../../../common/utils' import { log } from '../../../common/utils'
export interface PayloadType { export interface PayloadType {
group_id: number, group_id: number
no_cache: boolean | string no_cache: boolean | string
} }

View File

@ -14,11 +14,13 @@ import { friends, getFriend, getGroup, getGroupMember, getUidByUin, selfInfo } f
import { import {
OB11MessageCustomMusic, OB11MessageCustomMusic,
OB11MessageData, OB11MessageData,
OB11MessageDataType, OB11MessageFile, OB11MessageDataType,
OB11MessageFile,
OB11MessageJson, OB11MessageJson,
OB11MessageMixType, OB11MessageMixType,
OB11MessageMusic, OB11MessageMusic,
OB11MessageNode, OB11MessageVideo, OB11MessageNode,
OB11MessageVideo,
OB11PostSendMsg, OB11PostSendMsg,
} from '../../types' } from '../../types'
import { NTQQMsgApi, Peer } from '../../../ntqqapi/api/msg' import { NTQQMsgApi, Peer } from '../../../ntqqapi/api/msg'
@ -48,28 +50,22 @@ function checkSendMessage(sendMsgList: OB11MessageData[]) {
let data = msg['data'] let data = msg['data']
if (type === 'text' && !data['text']) { if (type === 'text' && !data['text']) {
return 400 return 400
} } else if (['image', 'voice', 'record'].includes(type)) {
else if (['image', 'voice', 'record'].includes(type)) {
if (!data['file']) { if (!data['file']) {
return 400 return 400
} } else {
else {
if (checkUri(data['file'])) { if (checkUri(data['file'])) {
return 200 return 200
} } else {
else {
return 400 return 400
} }
} }
} } else if (type === 'at' && !data['qq']) {
else if (type === 'at' && !data['qq']) { return 400
} else if (type === 'reply' && !data['id']) {
return 400 return 400
} }
else if (type === 'reply' && !data['id']) { } else {
return 400
}
}
else {
return 400 return 400
} }
} }
@ -91,12 +87,10 @@ export function convertMessage2List(message: OB11MessageMixType, autoEscape = fa
}, },
}, },
] ]
} } else {
else {
message = decodeCQCode(message.toString()) message = decodeCQCode(message.toString())
} }
} } else if (!Array.isArray(message)) {
else if (!Array.isArray(message)) {
message = [message] message = [message]
} }
return message return message
@ -114,14 +108,16 @@ export async function createSendElements(
continue continue
} }
switch (sendMsg.type) { switch (sendMsg.type) {
case OB11MessageDataType.text: { case OB11MessageDataType.text:
{
const text = sendMsg.data?.text const text = sendMsg.data?.text
if (text) { if (text) {
sendElements.push(SendMsgElementConstructor.text(sendMsg.data!.text)) sendElements.push(SendMsgElementConstructor.text(sendMsg.data!.text))
} }
} }
break break
case OB11MessageDataType.at: { case OB11MessageDataType.at:
{
if (!target) { if (!target) {
continue continue
} }
@ -140,14 +136,12 @@ export async function createSendElements(
log(`${groupCode}剩余at全体次数`, remainAtAllCount) log(`${groupCode}剩余at全体次数`, remainAtAllCount)
const self = await getGroupMember((target as Group)?.groupCode, selfInfo.uin) const self = await getGroupMember((target as Group)?.groupCode, selfInfo.uin)
isAdmin = self.role === GroupMemberRole.admin || self.role === GroupMemberRole.owner isAdmin = self.role === GroupMemberRole.admin || self.role === GroupMemberRole.owner
} catch (e) { } catch (e) {}
}
} }
if (isAdmin && remainAtAllCount > 0) { if (isAdmin && remainAtAllCount > 0) {
sendElements.push(SendMsgElementConstructor.at(atQQ, atQQ, AtType.atAll, '全体成员')) sendElements.push(SendMsgElementConstructor.at(atQQ, atQQ, AtType.atAll, '全体成员'))
} }
} } else {
else {
// const atMember = group?.members.find(m => m.uin == atQQ) // const atMember = group?.members.find(m => m.uin == atQQ)
const atMember = await getGroupMember((target as Group)?.groupCode, atQQ) const atMember = await getGroupMember((target as Group)?.groupCode, atQQ)
if (atMember) { if (atMember) {
@ -159,7 +153,8 @@ export async function createSendElements(
} }
} }
break break
case OB11MessageDataType.reply: { case OB11MessageDataType.reply:
{
let replyMsgId = sendMsg.data.id let replyMsgId = sendMsg.data.id
if (replyMsgId) { if (replyMsgId) {
const replyMsg = await dbUtil.getMsgByShortId(parseInt(replyMsgId)) const replyMsg = await dbUtil.getMsgByShortId(parseInt(replyMsgId))
@ -176,23 +171,31 @@ export async function createSendElements(
} }
} }
break break
case OB11MessageDataType.face: { case OB11MessageDataType.face:
{
const faceId = sendMsg.data?.id const faceId = sendMsg.data?.id
if (faceId) { if (faceId) {
sendElements.push(SendMsgElementConstructor.face(parseInt(faceId))) sendElements.push(SendMsgElementConstructor.face(parseInt(faceId)))
} }
} }
break break
case OB11MessageDataType.mface: { case OB11MessageDataType.mface:
{
sendElements.push( sendElements.push(
SendMsgElementConstructor.mface(sendMsg.data.emoji_package_id, sendMsg.data.emoji_id, sendMsg.data.key, sendMsg.data.summary), SendMsgElementConstructor.mface(
sendMsg.data.emoji_package_id,
sendMsg.data.emoji_id,
sendMsg.data.key,
sendMsg.data.summary,
),
) )
} }
break break
case OB11MessageDataType.image: case OB11MessageDataType.image:
case OB11MessageDataType.file: case OB11MessageDataType.file:
case OB11MessageDataType.video: case OB11MessageDataType.video:
case OB11MessageDataType.voice: { case OB11MessageDataType.voice:
{
const data = (sendMsg as OB11MessageFile).data const data = (sendMsg as OB11MessageFile).data
let file = data.file let file = data.file
const payloadFileName = data?.name const payloadFileName = data?.name
@ -201,12 +204,10 @@ export async function createSendElements(
if (cache) { if (cache) {
if (fs.existsSync(cache.filePath)) { if (fs.existsSync(cache.filePath)) {
file = 'file://' + cache.filePath file = 'file://' + cache.filePath
} } else if (cache.downloadFunc) {
else if (cache.downloadFunc) {
await cache.downloadFunc() await cache.downloadFunc()
file = cache.filePath file = cache.filePath
} } else if (cache.url) {
else if (cache.url) {
file = cache.url file = cache.url
} }
log('找到文件缓存', file) log('找到文件缓存', file)
@ -223,8 +224,7 @@ export async function createSendElements(
if (sendMsg.type === OB11MessageDataType.file) { if (sendMsg.type === OB11MessageDataType.file) {
log('发送文件', path, payloadFileName || fileName) log('发送文件', path, payloadFileName || fileName)
sendElements.push(await SendMsgElementConstructor.file(path, payloadFileName || fileName)) sendElements.push(await SendMsgElementConstructor.file(path, payloadFileName || fileName))
} } else if (sendMsg.type === OB11MessageDataType.video) {
else if (sendMsg.type === OB11MessageDataType.video) {
log('发送视频', path, payloadFileName || fileName) log('发送视频', path, payloadFileName || fileName)
let thumb = sendMsg.data?.thumb let thumb = sendMsg.data?.thumb
if (thumb) { if (thumb) {
@ -234,11 +234,9 @@ export async function createSendElements(
} }
} }
sendElements.push(await SendMsgElementConstructor.video(path, payloadFileName || fileName, thumb)) sendElements.push(await SendMsgElementConstructor.video(path, payloadFileName || fileName, thumb))
} } else if (sendMsg.type === OB11MessageDataType.voice) {
else if (sendMsg.type === OB11MessageDataType.voice) {
sendElements.push(await SendMsgElementConstructor.ptt(path)) sendElements.push(await SendMsgElementConstructor.ptt(path))
} } else if (sendMsg.type === OB11MessageDataType.image) {
else if (sendMsg.type === OB11MessageDataType.image) {
sendElements.push( sendElements.push(
await SendMsgElementConstructor.pic( await SendMsgElementConstructor.pic(
path, path,
@ -251,17 +249,18 @@ export async function createSendElements(
} }
} }
break break
case OB11MessageDataType.json: { case OB11MessageDataType.json:
{
sendElements.push(SendMsgElementConstructor.ark(sendMsg.data.data)) sendElements.push(SendMsgElementConstructor.ark(sendMsg.data.data))
} }
break break
case OB11MessageDataType.poke: { case OB11MessageDataType.poke:
{
let qq = sendMsg.data?.qq || sendMsg.data?.id let qq = sendMsg.data?.qq || sendMsg.data?.id
if (qq) { if (qq) {
if ('groupCode' in target) { if ('groupCode' in target) {
crychic.sendGroupPoke(target.groupCode, qq.toString()) crychic.sendGroupPoke(target.groupCode, qq.toString())
} } else {
else {
if (!qq) { if (!qq) {
qq = parseInt(target.uin) qq = parseInt(target.uin)
} }
@ -271,12 +270,14 @@ export async function createSendElements(
} }
} }
break break
case OB11MessageDataType.dice: { case OB11MessageDataType.dice:
{
const resultId = sendMsg.data?.result const resultId = sendMsg.data?.result
sendElements.push(SendMsgElementConstructor.dice(resultId)) sendElements.push(SendMsgElementConstructor.dice(resultId))
} }
break break
case OB11MessageDataType.RPS: { case OB11MessageDataType.RPS:
{
const resultId = sendMsg.data?.result const resultId = sendMsg.data?.result
sendElements.push(SendMsgElementConstructor.rps(resultId)) sendElements.push(SendMsgElementConstructor.rps(resultId))
} }
@ -302,8 +303,7 @@ export async function sendMsg(
const returnMsg = await NTQQMsgApi.sendMsg(peer, sendElements, waitComplete, 20000) const returnMsg = await NTQQMsgApi.sendMsg(peer, sendElements, waitComplete, 20000)
log('消息发送结果', returnMsg) log('消息发送结果', returnMsg)
returnMsg.msgShortId = await dbUtil.addMsg(returnMsg) returnMsg.msgShortId = await dbUtil.addMsg(returnMsg)
deleteAfterSentFiles.map((f) => fs.unlink(f, () => { deleteAfterSentFiles.map((f) => fs.unlink(f, () => {}))
}))
return returnMsg return returnMsg
} }
@ -312,14 +312,14 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
protected async check(payload: OB11PostSendMsg): Promise<BaseCheckResult> { protected async check(payload: OB11PostSendMsg): Promise<BaseCheckResult> {
const messages = convertMessage2List(payload.message) const messages = convertMessage2List(payload.message)
const fmNum = this.getSpecialMsgNum(payload, OB11MessageDataType.node) const fmNum = this.getSpecialMsgNum(messages, OB11MessageDataType.node)
if (fmNum && fmNum != messages.length) { if (fmNum && fmNum != messages.length) {
return { return {
valid: false, valid: false,
message: '转发消息不能和普通消息混在一起发送,转发需要保证message只有type为node的元素', message: '转发消息不能和普通消息混在一起发送,转发需要保证message只有type为node的元素',
} }
} }
const musicNum = this.getSpecialMsgNum(payload, OB11MessageDataType.music) const musicNum = this.getSpecialMsgNum(messages, OB11MessageDataType.music)
if (musicNum && messages.length > 1) { if (musicNum && messages.length > 1) {
return { return {
valid: false, valid: false,
@ -395,15 +395,14 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
payload.message, payload.message,
payload.auto_escape === true || payload.auto_escape === 'true', payload.auto_escape === true || payload.auto_escape === 'true',
) )
if (this.getSpecialMsgNum(payload, OB11MessageDataType.node)) { if (this.getSpecialMsgNum(messages, OB11MessageDataType.node)) {
try { try {
const returnMsg = await this.handleForwardNode(peer, messages as OB11MessageNode[], group) const returnMsg = await this.handleForwardNode(peer, messages as OB11MessageNode[], group)
return { message_id: returnMsg.msgShortId } return { message_id: returnMsg.msgShortId }
} catch (e) { } catch (e) {
throw '发送转发消息失败 ' + e.toString() throw '发送转发消息失败 ' + e.toString()
} }
} } else if (this.getSpecialMsgNum(messages, OB11MessageDataType.music)) {
else if (this.getSpecialMsgNum(payload, OB11MessageDataType.music)) {
const music = messages[0] as OB11MessageMusic const music = messages[0] as OB11MessageMusic
if (music) { if (music) {
const { musicSignUrl } = getConfigUtil().getConfig() const { musicSignUrl } = getConfigUtil().getConfig()
@ -416,20 +415,19 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
} }
const postData: MusicSignPostData = { ...music.data } const postData: MusicSignPostData = { ...music.data }
if (type === 'custom' && music.data.content) { if (type === 'custom' && music.data.content) {
;(postData as CustomMusicSignPostData).singer = music.data.content ;(postData as CustomMusicSignPostData).singer = music.data.content
delete (postData as OB11MessageCustomMusic['data']).content delete (postData as OB11MessageCustomMusic['data']).content
} }
if (type === 'custom') { if (type === 'custom') {
const customMusicData = music.data as CustomMusicSignPostData const customMusicData = music.data as CustomMusicSignPostData
if (!customMusicData.url) { if (!customMusicData.url) {
throw ('自定义音卡缺少参数url') throw '自定义音卡缺少参数url'
} }
if (!customMusicData.audio) { if (!customMusicData.audio) {
throw ('自定义音卡缺少参数audio') throw '自定义音卡缺少参数audio'
} }
if (!customMusicData.title) { if (!customMusicData.title) {
throw ('自定义音卡缺少参数title') throw '自定义音卡缺少参数title'
} }
} }
if (type === 'qq' || type === '163') { if (type === 'qq' || type === '163') {
@ -461,14 +459,13 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
} }
} }
const returnMsg = await sendMsg(peer, sendElements, deleteAfterSentFiles) const returnMsg = await sendMsg(peer, sendElements, deleteAfterSentFiles)
deleteAfterSentFiles.map((f) => fs.unlink(f, () => { deleteAfterSentFiles.map((f) => fs.unlink(f, () => {}))
}))
return { message_id: returnMsg.msgShortId } return { message_id: returnMsg.msgShortId }
} }
private getSpecialMsgNum(payload: OB11PostSendMsg, msgType: OB11MessageDataType): number { private getSpecialMsgNum(message: OB11MessageData[], msgType: OB11MessageDataType): number {
if (Array.isArray(payload.message)) { if (Array.isArray(message)) {
return payload.message.filter((msg) => msg.type == msgType).length return message.filter((msg) => msg.type == msgType).length
} }
return 0 return 0
} }
@ -565,8 +562,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
await sleep(500) await sleep(500)
log('转发节点生成成功', nodeMsg.msgId) log('转发节点生成成功', nodeMsg.msgId)
} }
deleteAfterSentFiles.map((f) => fs.unlink(f, () => { deleteAfterSentFiles.map((f) => fs.unlink(f, () => {}))
}))
} catch (e) { } catch (e) {
log('生成转发消息节点失败', e) log('生成转发消息节点失败', e)
} }

View File

@ -87,15 +87,13 @@ export class OB11Constructor {
resMsg.sender.role = OB11Constructor.groupMemberRole(member.role) resMsg.sender.role = OB11Constructor.groupMemberRole(member.role)
resMsg.sender.nickname = member.nick resMsg.sender.nickname = member.nick
} }
} } else if (msg.chatType == ChatType.friend) {
else if (msg.chatType == ChatType.friend) {
resMsg.sub_type = 'friend' resMsg.sub_type = 'friend'
const friend = await getFriend(msg.senderUin) const friend = await getFriend(msg.senderUin)
if (friend) { if (friend) {
resMsg.sender.nickname = friend.nick resMsg.sender.nickname = friend.nick
} }
} } else if (msg.chatType == ChatType.temp) {
else if (msg.chatType == ChatType.temp) {
resMsg.sub_type = 'group' resMsg.sub_type = 'group'
const tempGroupCode = tempGroupCodeMap[msg.peerUin] const tempGroupCode = tempGroupCodeMap[msg.peerUin]
if (tempGroupCode) { if (tempGroupCode) {
@ -113,8 +111,7 @@ export class OB11Constructor {
if (element.textElement.atType == AtType.atAll) { if (element.textElement.atType == AtType.atAll) {
// message_data["data"]["mention"] = "all" // message_data["data"]["mention"] = "all"
message_data['data']['qq'] = 'all' message_data['data']['qq'] = 'all'
} } else {
else {
let atUid = element.textElement.atNtUid let atUid = element.textElement.atNtUid
let atQQ = element.textElement.atUid let atQQ = element.textElement.atUid
if (!atQQ || atQQ === '0') { if (!atQQ || atQQ === '0') {
@ -128,16 +125,14 @@ export class OB11Constructor {
message_data['data']['qq'] = atQQ message_data['data']['qq'] = atQQ
} }
} }
} } else if (element.textElement) {
else if (element.textElement) {
message_data['type'] = 'text' message_data['type'] = 'text'
let text = element.textElement.content let text = element.textElement.content
if (!text.trim()) { if (!text.trim()) {
continue continue
} }
message_data['data']['text'] = text message_data['data']['text'] = text
} } else if (element.replyElement) {
else if (element.replyElement) {
message_data['type'] = 'reply' message_data['type'] = 'reply'
// log("收到回复消息", element.replyElement.replayMsgSeq) // log("收到回复消息", element.replyElement.replayMsgSeq)
try { try {
@ -145,15 +140,13 @@ export class OB11Constructor {
// log("找到回复消息", replyMsg.msgShortId, replyMsg.msgId) // log("找到回复消息", replyMsg.msgShortId, replyMsg.msgId)
if (replyMsg) { if (replyMsg) {
message_data['data']['id'] = replyMsg.msgShortId.toString() message_data['data']['id'] = replyMsg.msgShortId.toString()
} } else {
else {
continue continue
} }
} catch (e) { } catch (e) {
log('获取不到引用的消息', e.stack, element.replyElement.replayMsgSeq) log('获取不到引用的消息', e.stack, element.replyElement.replayMsgSeq)
} }
} } else if (element.picElement) {
else if (element.picElement) {
message_data['type'] = 'image' message_data['type'] = 'image'
// message_data["data"]["file"] = element.picElement.sourcePath // message_data["data"]["file"] = element.picElement.sourcePath
message_data['data']['file'] = element.picElement.fileName message_data['data']['file'] = element.picElement.fileName
@ -182,8 +175,7 @@ export class OB11Constructor {
}) })
.then() .then()
// 不在自动下载图片 // 不在自动下载图片
} } else if (element.videoElement || element.fileElement) {
else if (element.videoElement || element.fileElement) {
const videoOrFileElement = element.videoElement || element.fileElement const videoOrFileElement = element.videoElement || element.fileElement
const ob11MessageDataType = element.videoElement ? OB11MessageDataType.video : OB11MessageDataType.file const ob11MessageDataType = element.videoElement ? OB11MessageDataType.video : OB11MessageDataType.file
message_data['type'] = ob11MessageDataType message_data['type'] = ob11MessageDataType
@ -212,8 +204,7 @@ export class OB11Constructor {
}) })
.then() .then()
// 怎么拿到url呢 // 怎么拿到url呢
} } else if (element.pttElement) {
else if (element.pttElement) {
message_data['type'] = OB11MessageDataType.voice message_data['type'] = OB11MessageDataType.voice
message_data['data']['file'] = element.pttElement.fileName message_data['data']['file'] = element.pttElement.fileName
message_data['data']['path'] = element.pttElement.filePath message_data['data']['path'] = element.pttElement.filePath
@ -233,27 +224,22 @@ export class OB11Constructor {
// }).catch(err => { // }).catch(err => {
// console.log("语音转文字失败", err); // console.log("语音转文字失败", err);
// }) // })
} } else if (element.arkElement) {
else if (element.arkElement) {
message_data['type'] = OB11MessageDataType.json message_data['type'] = OB11MessageDataType.json
message_data['data']['data'] = element.arkElement.bytesData message_data['data']['data'] = element.arkElement.bytesData
} } else if (element.faceElement) {
else if (element.faceElement) {
const faceId = element.faceElement.faceIndex const faceId = element.faceElement.faceIndex
if (faceId === FaceIndex.dice) { if (faceId === FaceIndex.dice) {
message_data['type'] = OB11MessageDataType.dice message_data['type'] = OB11MessageDataType.dice
message_data['data']['result'] = element.faceElement.resultId message_data['data']['result'] = element.faceElement.resultId
} } else if (faceId === FaceIndex.RPS) {
else if (faceId === FaceIndex.RPS) {
message_data['type'] = OB11MessageDataType.RPS message_data['type'] = OB11MessageDataType.RPS
message_data['data']['result'] = element.faceElement.resultId message_data['data']['result'] = element.faceElement.resultId
} } else {
else {
message_data['type'] = OB11MessageDataType.face message_data['type'] = OB11MessageDataType.face
message_data['data']['id'] = element.faceElement.faceIndex.toString() message_data['data']['id'] = element.faceElement.faceIndex.toString()
} }
} } else if (element.marketFaceElement) {
else if (element.marketFaceElement) {
message_data['type'] = OB11MessageDataType.mface message_data['type'] = OB11MessageDataType.mface
message_data['data']['summary'] = element.marketFaceElement.faceName message_data['data']['summary'] = element.marketFaceElement.faceName
const md5 = element.marketFaceElement.emojiId 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']['emoji_package_id'] = String(element.marketFaceElement.emojiPackageId)
message_data['data']['key'] = element.marketFaceElement.key message_data['data']['key'] = element.marketFaceElement.key
mFaceCache.set(md5, element.marketFaceElement.faceName) mFaceCache.set(md5, element.marketFaceElement.faceName)
} } else if (element.markdownElement) {
else if (element.markdownElement) {
message_data['type'] = OB11MessageDataType.markdown message_data['type'] = OB11MessageDataType.markdown
message_data['data']['data'] = element.markdownElement.content message_data['data']['data'] = element.markdownElement.content
} } else if (element.multiForwardMsgElement) {
else if (element.multiForwardMsgElement) {
message_data['type'] = OB11MessageDataType.forward message_data['type'] = OB11MessageDataType.forward
message_data['data']['id'] = msg.msgId message_data['data']['id'] = msg.msgId
} }
@ -280,8 +264,7 @@ export class OB11Constructor {
const cqCode = encodeCQCode(message_data) const cqCode = encodeCQCode(message_data)
if (messagePostFormat === 'string') { if (messagePostFormat === 'string') {
;(resMsg.message as string) += cqCode ;(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 resMsg.raw_message += cqCode
} }
@ -330,8 +313,7 @@ export class OB11Constructor {
// log("构造群增加事件", event) // log("构造群增加事件", event)
return event return event
} }
} } else if (groupElement.type === TipGroupElementType.ban) {
else if (groupElement.type === TipGroupElementType.ban) {
log('收到群群员禁言提示', groupElement) log('收到群群员禁言提示', groupElement)
const memberUid = groupElement.shutUp.member.uid const memberUid = groupElement.shutUp.member.uid
const adminUid = groupElement.shutUp.admin.uid const adminUid = groupElement.shutUp.admin.uid
@ -342,8 +324,7 @@ export class OB11Constructor {
memberUin = memberUin =
(await getGroupMember(msg.peerUid, memberUid))?.uin || (await getGroupMember(msg.peerUid, memberUid))?.uin ||
(await NTQQUserApi.getUserDetailInfo(memberUid))?.uin (await NTQQUserApi.getUserDetailInfo(memberUid))?.uin
} } else {
else {
memberUin = '0' // 0表示全员禁言 memberUin = '0' // 0表示全员禁言
if (duration > 0) { if (duration > 0) {
duration = -1 duration = -1
@ -360,8 +341,7 @@ export class OB11Constructor {
sub_type, sub_type,
) )
} }
} } else if (groupElement.type == TipGroupElementType.kicked) {
else if (groupElement.type == TipGroupElementType.kicked) {
log(`收到我被踢出或退群提示, 群${msg.peerUid}`, groupElement) log(`收到我被踢出或退群提示, 群${msg.peerUid}`, groupElement)
deleteGroup(msg.peerUid) deleteGroup(msg.peerUid)
NTQQGroupApi.quitGroup(msg.peerUid).then() NTQQGroupApi.quitGroup(msg.peerUid).then()
@ -381,8 +361,7 @@ export class OB11Constructor {
return new OB11GroupDecreaseEvent(parseInt(msg.peerUid), parseInt(selfInfo.uin), 0, 'leave') 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), { return new OB11GroupUploadNoticeEvent(parseInt(msg.peerUid), parseInt(msg.senderUin), {
id: element.fileElement.fileUuid, id: element.fileElement.fileUuid,
name: element.fileElement.fileName, name: element.fileElement.fileName,
@ -447,8 +426,7 @@ export class OB11Constructor {
return new OB11GroupIncreaseEvent(parseInt(msg.peerUid), parseInt(invitee), parseInt(inviter), 'invite') 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) const json = JSON.parse(grayTipElement.jsonGrayTipElement.jsonStr)
/* /*
{ {
@ -497,19 +475,27 @@ export class OB11Constructor {
return return
} }
static async RecallEvent(msg: RawMessage): Promise<OB11FriendRecallNoticeEvent | OB11GroupRecallNoticeEvent | undefined>{ static async RecallEvent(
let msgElement = msg.elements.find((element) => element.grayTipElement?.subElementType === GrayTipElementSubType.RECALL); msg: RawMessage,
): Promise<OB11FriendRecallNoticeEvent | OB11GroupRecallNoticeEvent | undefined> {
let msgElement = msg.elements.find(
(element) => element.grayTipElement?.subElementType === GrayTipElementSubType.RECALL,
)
if (!msgElement) { if (!msgElement) {
return return
} }
const isGroup = msg.chatType === ChatType.group; const isGroup = msg.chatType === ChatType.group
const revokeElement = msgElement.grayTipElement.revokeElement; const revokeElement = msgElement.grayTipElement.revokeElement
if (isGroup) { if (isGroup) {
const operator = await getGroupMember(msg.peerUid, revokeElement.operatorUid); const operator = await getGroupMember(msg.peerUid, revokeElement.operatorUid)
const sender = await getGroupMember(msg.peerUid, revokeElement.origMsgSenderUid); const sender = await getGroupMember(msg.peerUid, revokeElement.origMsgSenderUid)
return new OB11GroupRecallNoticeEvent(parseInt(msg.peerUid), parseInt(sender.uin), parseInt(operator.uin), msg.msgShortId) return new OB11GroupRecallNoticeEvent(
} parseInt(msg.peerUid),
else{ parseInt(sender.uin),
parseInt(operator.uin),
msg.msgShortId,
)
} else {
return new OB11FriendRecallNoticeEvent(parseInt(msg.senderUin), msg.msgShortId) return new OB11FriendRecallNoticeEvent(parseInt(msg.senderUin), msg.msgShortId)
} }
} }

View File

@ -1,11 +1,11 @@
import { OB11BaseNoticeEvent } from './OB11BaseNoticeEvent'; import { OB11BaseNoticeEvent } from './OB11BaseNoticeEvent'
export class OB11FriendAddNoticeEvent extends OB11BaseNoticeEvent { export class OB11FriendAddNoticeEvent extends OB11BaseNoticeEvent {
notice_type = 'friend_add'; notice_type = 'friend_add'
user_id: number; user_id: number
public constructor(userId: number) { public constructor(userId: number) {
super(); super()
this.user_id = userId; this.user_id = userId
} }
} }

View File

@ -1 +1 @@
export const version = '3.24.1' export const version = '3.24.2'

View File

@ -1,12 +1,18 @@
import http from 'https' import http from 'https'
function checkUrl(imageUrl) { function checkUrl(imageUrl) {
http.get(imageUrl, response => { http
.get(imageUrl, (response) => {
console.log(response.statusCode) console.log(response.statusCode)
}).on('error', e => { })
.on('error', (e) => {
console.log(e) console.log(e)
}) })
} }
checkUrl('https://gchat.qpic.cn/download?appid=1407&fileid=CgoxMzMyNTI0MjIxEhRrdaUgQP5MjweWa4uR8pviUDaGQhjcxQUg_wooiYTj39fphQNQgL2jAQ&spec=0&rkey=CAQSKAB6JWENi5LMk0kc62l8Pm3Jn1dsLZHyRLAnNmHGoZ3y_gDZPqZt-64') checkUrl(
checkUrl('https://multimedia.nt.qq.com.cn/download?appid=1407&fileid=CgoxMzMyNTI0MjIxEhRrdaUgQP5MjweWa4uR8pviUDaGQhjcxQUg_wooiYTj39fphQNQgL2jAQ&spec=0&rkey=CAQSKAB6JWENi5LMk0kc62l8Pm3Jn1dsLZHyRLAnNmHGoZ3y_gDZPqZt-64') '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',
)

View File

@ -8,7 +8,6 @@
"allowJs": true, "allowJs": true,
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"moduleResolution": "node", "moduleResolution": "node",
// "sourceMap": true
"paths": { "paths": {
"@/common/*": [ "@/common/*": [
"./src/common/*" "./src/common/*"
@ -19,15 +18,9 @@
"@/ntqqapi/*": [ "@/ntqqapi/*": [
"./src/ntqqapi/*" "./src/ntqqapi/*"
] ]
}
}, },
"include": [ "noEmit": true
"src/*", },
"src/**/*", "include": ["src/*", "src/**/*", "scripts/*"],
"scripts/*" "exclude": ["node_modules"]
],
"exclude": [
"node_modules"
],
} }