Merge pull request #422 from LLOneBot/dev

release: 3.32.7
This commit is contained in:
idranme 2024-09-16 20:48:15 +08:00 committed by GitHub
commit 64c5eb6c04
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 64 additions and 93 deletions

View File

@ -4,7 +4,7 @@
"name": "LLOneBot",
"slug": "LLOneBot",
"description": "实现 OneBot 11 协议,用于 QQ 机器人开发",
"version": "3.32.6",
"version": "3.32.7",
"icon": "./icon.webp",
"authors": [
{

View File

@ -23,8 +23,7 @@ export default class Log {
return
}
const dateTime = new Date(record.timestamp).toLocaleString()
const userInfo = selfInfo.uin ? `${selfInfo.nick}(${selfInfo.uin})` : ''
const content = `${dateTime} [${record.type}] ${userInfo} | ${record.name} ${record.content}\n\n`
const content = `${dateTime} [${record.type}] ${selfInfo.nick}(${selfInfo.uin}) | ${record.name} ${record.content}\n\n`
appendFile(file, content, noop)
},
}

View File

@ -183,7 +183,7 @@ export class NTQQMsgApi extends Service {
if (!arkElement) {
continue
}
const forwardData = JSON.parse(arkElement.arkElement.bytesData)
const forwardData = JSON.parse(arkElement.arkElement!.bytesData)
if (forwardData.app != 'com.tencent.multimsg') {
continue
}

View File

@ -27,8 +27,8 @@ declare module 'cordis' {
}
interface Events {
'nt/message-created': (input: RawMessage[]) => void
'nt/message-deleted': (input: RawMessage[]) => void
'nt/message-sent': (input: RawMessage[]) => void
'nt/message-deleted': (input: RawMessage) => void
'nt/message-sent': (input: RawMessage) => void
'nt/group-notify': (input: GroupNotify[]) => void
'nt/friend-request': (input: FriendRequest[]) => void
'nt/group-member-info-updated': (input: { groupCode: string, members: GroupMember[] }) => void
@ -96,7 +96,7 @@ class Core extends Service {
}
for (const path of pathList) {
if (path) {
fs.unlink(picPath, () => {
fs.unlink(path, () => {
this.ctx.logger.info('删除文件成功', path)
})
}
@ -174,23 +174,26 @@ class Core extends Service {
this.ctx.parallel('nt/message-created', payload.msgList)
})
const sentMsgIds = new Map<string, boolean>()
const recallMsgIds: string[] = [] // 避免重复上报
registerReceiveHook<{ msgList: RawMessage[] }>([ReceiveCmdS.UPDATE_MSG], payload => {
const list = payload.msgList.filter(v => {
if (recallMsgIds.includes(v.msgId)) {
return false
for (const msg of payload.msgList) {
if (msg.recallTime !== '0' && !recallMsgIds.includes(msg.msgId)) {
recallMsgIds.push(msg.msgId)
this.ctx.parallel('nt/message-deleted', msg)
} else if (sentMsgIds.get(msg.msgId)) {
sentMsgIds.delete(msg.msgId)
this.ctx.parallel('nt/message-sent', msg)
}
recallMsgIds.push(v.msgId)
return true
})
this.ctx.parallel('nt/message-deleted', list)
}
})
registerReceiveHook<{ msgRecord: RawMessage }>(ReceiveCmdS.SELF_SEND_MSG, payload => {
if (!this.config.reportSelfMessage) {
return
}
this.ctx.parallel('nt/message-sent', [payload.msgRecord])
sentMsgIds.set(payload.msgRecord.msgId, true)
})
const groupNotifyFlags: string[] = []

View File

@ -102,7 +102,7 @@ export interface SendPicElement {
export interface SendReplyElement {
elementType: ElementType.REPLY
elementId: ''
replyElement: ReplyElement
replyElement: Partial<ReplyElement>
}
export interface SendFaceElement {
@ -129,6 +129,12 @@ export interface ReplyElement {
replayMsgId: string
senderUin: string
senderUinStr: string
sourceMsgIdInRecords: string
senderUid: string
senderUidStr: string
sourceMsgIsIncPic: boolean // 原消息是否有图片
sourceMsgText: string
replyMsgTime: string
}
export interface FileElement {
@ -303,7 +309,7 @@ export enum GrayTipElementSubType {
export interface GrayTipElement {
subElementType: GrayTipElementSubType
revokeElement: {
revokeElement?: {
operatorRole: string
operatorUid: string
operatorNick: string
@ -313,14 +319,14 @@ export interface GrayTipElement {
isSelfOperate?: boolean
wording: string // 自定义的撤回提示语
}
aioOpGrayTipElement: TipAioOpGrayTipElement
groupElement: TipGroupElement
xmlElement: {
aioOpGrayTipElement?: TipAioOpGrayTipElement
groupElement?: TipGroupElement
xmlElement?: {
templId: string
content: string
}
jsonGrayTipElement: {
busiId: number
jsonGrayTipElement?: {
busiId: string
jsonStr: string
}
}
@ -485,36 +491,7 @@ export interface RawMessage {
sendStatus?: number // 消息状态别人发的2是已撤回自己发的2是已发送
recallTime: string // 撤回时间, "0"是没有撤回
records: RawMessage[]
elements: {
elementId: string
elementType: ElementType
replyElement: {
sourceMsgIdInRecords: string
senderUid: string // 原消息发送者QQ号
sourceMsgIsIncPic: boolean // 原消息是否有图片
sourceMsgText: string
replayMsgSeq: string // 源消息的msgSeq可以通过这个找到源消息的msgId
senderUidStr: string
replyMsgTime: string
}
textElement: {
atType: AtType
atUid: string // QQ号
content: string
atNtUid: string // uid号
}
picElement: PicElement
pttElement: PttElement
arkElement: ArkElement
grayTipElement: GrayTipElement
faceElement: FaceElement
videoElement: VideoElement
fileElement: FileElement
marketFaceElement: MarketFaceElement
inlineKeyboardElement: InlineKeyboardElement
markdownElement: MarkdownElement
multiForwardMsgElement: MultiForwardMsgElement
}[]
elements: MessageElement[]
}
export interface Peer {
@ -529,7 +506,7 @@ export interface MessageElement {
extBufForUI: string //"0x"
textElement?: TextElement
faceElement?: FaceElement
marketFaceElement?: MarkdownElement
marketFaceElement?: MarketFaceElement
replyElement?: ReplyElement
picElement?: PicElement
pttElement?: PttElement

View File

@ -59,7 +59,7 @@ export abstract class GetFileBase extends BaseAction<GetFilePayload, GetFileResp
if (!findEle) {
throw new Error('element not found')
}
res.url = await this.ctx.ntFileApi.getImageUrl(findEle.picElement)
res.url = await this.ctx.ntFileApi.getImageUrl(findEle.picElement!)
} else if (fileCache[0].elementType === ElementType.VIDEO) {
res.url = await this.ctx.ntFileApi.getVideoUrl(peer, fileCache[0].msgId, fileCache[0].elementId)
}

View File

@ -226,20 +226,16 @@ class OneBot11Adapter extends Service {
}
}
private handleRecallMsg(msgList: RawMessage[]) {
for (const message of msgList) {
if (message.recallTime != '0') {
const oriMessageId = MessageUnique.getShortIdByMsgId(message.msgId)
if (!oriMessageId) {
continue
}
OB11Entities.recallEvent(this.ctx, message, oriMessageId).then((recallEvent) => {
if (recallEvent) {
this.dispatch(recallEvent)
}
})
}
private handleRecallMsg(message: RawMessage) {
const oriMessageId = MessageUnique.getShortIdByMsgId(message.msgId)
if (!oriMessageId) {
return
}
OB11Entities.recallEvent(this.ctx, message, oriMessageId).then((recallEvent) => {
if (recallEvent) {
this.dispatch(recallEvent)
}
})
}
private async handleFriendRequest(buddyReqs: FriendRequest[]) {
@ -404,7 +400,7 @@ class OneBot11Adapter extends Service {
this.handleRecallMsg(input)
})
this.ctx.on('nt/message-sent', input => {
this.handleMsg(input)
this.handleMsg([input])
})
this.ctx.on('nt/group-notify', input => {
this.handleGroupNotify(input)

View File

@ -375,29 +375,25 @@ export namespace OB11Entities {
for (const element of msg.elements) {
if (element.grayTipElement) {
const { grayTipElement } = element
if (grayTipElement.subElementType === GrayTipElementSubType.JSON) {
if (grayTipElement.jsonGrayTipElement?.busiId === '1061') {
const json = JSON.parse(grayTipElement.jsonGrayTipElement.jsonStr)
if (grayTipElement.jsonGrayTipElement.busiId === 1061) {
const pokedetail: Dict[] = json.items
//筛选item带有uid的元素
const poke_uid = pokedetail.filter(item => item.uid)
if (poke_uid.length == 2) {
return new OB11FriendPokeEvent(
parseInt(await ctx.ntUserApi.getUinByUid(poke_uid[0].uid)),
parseInt(await ctx.ntUserApi.getUinByUid(poke_uid[1].uid)),
pokedetail
)
}
const pokedetail: Dict[] = json.items
//筛选item带有uid的元素
const poke_uid = pokedetail.filter(item => item.uid)
if (poke_uid.length === 2) {
return new OB11FriendPokeEvent(
Number(await ctx.ntUserApi.getUinByUid(poke_uid[0].uid)),
Number(await ctx.ntUserApi.getUinByUid(poke_uid[1].uid)),
pokedetail
)
}
}
if (grayTipElement.xmlElement?.templId === '10229') {
const uin = +msg.peerUin || +(await ctx.ntUserApi.getUinByUid(msg.peerUid))
return new OB11FriendAddNoticeEvent(uin)
}
}
}
// 好友增加事件
if (msg.msgType === 5 && msg.subMsgType === 12) {
const uin = +msg.peerUin || +(await ctx.ntUserApi.getUinByUid(msg.peerUid))
const event = new OB11FriendAddNoticeEvent(uin)
return event
}
}
export async function groupEvent(ctx: Context, msg: RawMessage): Promise<OB11GroupNoticeEvent | void> {
@ -564,8 +560,8 @@ export namespace OB11Entities {
}
}
else if (grayTipElement.subElementType == GrayTipElementSubType.JSON) {
const json = JSON.parse(grayTipElement.jsonGrayTipElement.jsonStr)
if (grayTipElement.jsonGrayTipElement.busiId == 1061) {
const json = JSON.parse(grayTipElement.jsonGrayTipElement!.jsonStr)
if (grayTipElement.jsonGrayTipElement?.busiId === '1061') {
const pokedetail: Dict[] = json.items
//筛选item带有uid的元素
const poke_uid = pokedetail.filter(item => item.uid)
@ -578,7 +574,7 @@ export namespace OB11Entities {
)
}
}
if (grayTipElement.jsonGrayTipElement.busiId == 2401) {
if (grayTipElement.jsonGrayTipElement?.busiId === '2401') {
ctx.logger.info('收到群精华消息', json)
const searchParams = new URL(json.items[0].jp).searchParams
const msgSeq = searchParams.get('msgSeq')!
@ -605,7 +601,7 @@ export namespace OB11Entities {
)
// 获取MsgSeq+Peer可获取具体消息
}
if (grayTipElement.jsonGrayTipElement.busiId == 2407) {
if (grayTipElement.jsonGrayTipElement?.busiId === '2407') {
const memberUin = json.items[1].param[0]
const title = json.items[3].txt
ctx.logger.info('收到群成员新头衔消息', json)
@ -632,9 +628,9 @@ export namespace OB11Entities {
if (!msgElement) {
return
}
const revokeElement = msgElement.grayTipElement.revokeElement
const revokeElement = msgElement.grayTipElement!.revokeElement
if (msg.chatType === ChatType.group) {
const operator = await ctx.ntGroupApi.getGroupMember(msg.peerUid, revokeElement.operatorUid)
const operator = await ctx.ntGroupApi.getGroupMember(msg.peerUid, revokeElement!.operatorUid)
return new OB11GroupRecallNoticeEvent(
parseInt(msg.peerUid),
parseInt(msg.senderUin!),

View File

@ -1 +1 @@
export const version = '3.32.6'
export const version = '3.32.7'