mirror of
https://github.com/LLOneBot/LLOneBot.git
synced 2024-11-22 01:56:33 +00:00
commit
64c5eb6c04
@ -4,7 +4,7 @@
|
||||
"name": "LLOneBot",
|
||||
"slug": "LLOneBot",
|
||||
"description": "实现 OneBot 11 协议,用于 QQ 机器人开发",
|
||||
"version": "3.32.6",
|
||||
"version": "3.32.7",
|
||||
"icon": "./icon.webp",
|
||||
"authors": [
|
||||
{
|
||||
|
@ -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)
|
||||
},
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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[] = []
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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!),
|
||||
|
@ -1 +1 @@
|
||||
export const version = '3.32.6'
|
||||
export const version = '3.32.7'
|
||||
|
Loading…
x
Reference in New Issue
Block a user