mirror of
https://github.com/LLOneBot/LLOneBot.git
synced 2024-11-22 01:56:33 +00:00
Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
1da086ce0a | ||
![]() |
e9d43a9449 | ||
![]() |
ce31052661 | ||
![]() |
3fd9b0a183 | ||
![]() |
7e1dee8e07 | ||
![]() |
f2854fdf00 | ||
![]() |
1fad95a55b | ||
![]() |
5342e1521c | ||
![]() |
3c532526df | ||
![]() |
05c6cae86f |
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"manifest_version": 4,
|
||||
"type": "extension",
|
||||
"name": "LLOneBot v3.24.0",
|
||||
"name": "LLOneBot v3.24.1",
|
||||
"slug": "LLOneBot",
|
||||
"description": "使你的NTQQ支持OneBot11协议进行QQ机器人开发, 不支持商店在线更新",
|
||||
"version": "3.24.0",
|
||||
"version": "3.24.1",
|
||||
"icon": "./icon.jpg",
|
||||
"authors": [
|
||||
{
|
||||
|
@@ -49,7 +49,7 @@ class DBUtil {
|
||||
setTimeout(initDB, 300)
|
||||
}
|
||||
}
|
||||
initDB()
|
||||
setTimeout(initDB)
|
||||
}).then()
|
||||
|
||||
const expiredMilliSecond = 1000 * 60 * 60
|
||||
@@ -154,12 +154,12 @@ class DBUtil {
|
||||
this.updateMsg(msg).then()
|
||||
return existMsg.msgShortId
|
||||
}
|
||||
this.addCache(msg)
|
||||
|
||||
const shortMsgId = await this.genMsgShortId()
|
||||
const shortIdKey = this.DB_KEY_PREFIX_MSG_SHORT_ID + shortMsgId
|
||||
const seqIdKey = this.DB_KEY_PREFIX_MSG_SEQ_ID + msg.msgSeq
|
||||
msg.msgShortId = shortMsgId
|
||||
this.addCache(msg)
|
||||
// log("新增消息记录", msg.msgId)
|
||||
this.db.put(shortIdKey, msg.msgId).then().catch()
|
||||
this.db.put(longIdKey, JSON.stringify(msg)).then().catch()
|
||||
|
@@ -176,6 +176,7 @@ export async function uri2local(uri: string, fileName: string = null): Promise<U
|
||||
// res.ext = pathInfo.ext
|
||||
}
|
||||
}
|
||||
fileName = fileName.replace(/[/\\:*?"<>|]/g, '_')
|
||||
res.fileName = fileName
|
||||
filePath = path.join(TEMP_DIR, uuidv4() + fileName)
|
||||
fs.writeFileSync(filePath, buffer)
|
||||
|
@@ -198,6 +198,7 @@ function onLoad() {
|
||||
postOB11Event(friendAddEvent)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,39 +225,28 @@ function onLoad() {
|
||||
log('report message error: ', e.stack.toString())
|
||||
}
|
||||
})
|
||||
const recallMsgIds: string[] = []; // 避免重复上报
|
||||
registerReceiveHook<{ msgList: Array<RawMessage> }>([ReceiveCmdS.UPDATE_MSG], async (payload) => {
|
||||
for (const message of payload.msgList) {
|
||||
// log("message update", message)
|
||||
log("message update", message.msgId, message)
|
||||
if (message.recallTime != '0') {
|
||||
//todo: 这个判断方法不太好,应该使用灰色消息元素来判断
|
||||
// 撤回消息上报
|
||||
if (recallMsgIds.includes(message.msgId)) {
|
||||
continue
|
||||
}
|
||||
recallMsgIds.push(message.msgId);
|
||||
const oriMessage = await dbUtil.getMsgByLongId(message.msgId)
|
||||
if (!oriMessage) {
|
||||
continue
|
||||
}
|
||||
oriMessage.recallTime = message.recallTime
|
||||
dbUtil.updateMsg(oriMessage).then()
|
||||
if (message.chatType == ChatType.friend) {
|
||||
const friendRecallEvent = new OB11FriendRecallNoticeEvent(
|
||||
parseInt(message.senderUin),
|
||||
oriMessage.msgShortId,
|
||||
)
|
||||
postOB11Event(friendRecallEvent)
|
||||
} else if (message.chatType == ChatType.group) {
|
||||
let operatorId = message.senderUin
|
||||
for (const element of message.elements) {
|
||||
const operatorUid = element.grayTipElement?.revokeElement.operatorUid
|
||||
const operator = await getGroupMember(message.peerUin, operatorUid)
|
||||
operatorId = operator.uin
|
||||
message.msgShortId = oriMessage.msgShortId;
|
||||
OB11Constructor.RecallEvent(message).then((recallEvent) => {
|
||||
if (recallEvent) {
|
||||
log("post recall event", recallEvent);
|
||||
postOB11Event(recallEvent)
|
||||
}
|
||||
const groupRecallEvent = new OB11GroupRecallNoticeEvent(
|
||||
parseInt(message.peerUin),
|
||||
parseInt(message.senderUin),
|
||||
parseInt(operatorId),
|
||||
oriMessage.msgShortId,
|
||||
)
|
||||
postOB11Event(groupRecallEvent)
|
||||
}
|
||||
})
|
||||
// 不让入库覆盖原来消息,不然就获取不到撤回的消息内容了
|
||||
continue
|
||||
}
|
||||
|
@@ -225,7 +225,8 @@ 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`
|
||||
}
|
||||
|
@@ -20,6 +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();
|
||||
return await callNTQQApi<GeneralCallResult>({
|
||||
methodName: NTQQApiMethod.EMOJI_LIKE,
|
||||
args: [
|
||||
|
BIN
src/ntqqapi/external/moehook/MoeHoo-win32-x64.node
vendored
BIN
src/ntqqapi/external/moehook/MoeHoo-win32-x64.node
vendored
Binary file not shown.
@@ -201,6 +201,7 @@ export interface PicElement {
|
||||
}
|
||||
|
||||
export enum GrayTipElementSubType {
|
||||
RECALL = 1,
|
||||
INVITE_NEW_MEMBER = 12,
|
||||
MEMBER_NEW_TITLE = 17,
|
||||
}
|
||||
@@ -213,6 +214,8 @@ export interface GrayTipElement {
|
||||
operatorNick: string
|
||||
operatorRemark: string
|
||||
operatorMemRemark?: string
|
||||
origMsgSenderUid?: string
|
||||
isSelfOperate?: boolean
|
||||
wording: string // 自定义的撤回提示语
|
||||
}
|
||||
aioOpGrayTipElement: TipAioOpGrayTipElement
|
||||
|
@@ -46,6 +46,8 @@ import { NTQQGroupApi } from '../ntqqapi/api'
|
||||
import { OB11GroupMsgEmojiLikeEvent } from './event/notice/OB11MsgEmojiLikeEvent'
|
||||
import { mFaceCache } from '../ntqqapi/constructor'
|
||||
import { OB11FriendAddNoticeEvent } from './event/notice/OB11FriendAddNoticeEvent'
|
||||
import { OB11FriendRecallNoticeEvent } from './event/notice/OB11FriendRecallNoticeEvent'
|
||||
import { OB11GroupRecallNoticeEvent } from './event/notice/OB11GroupRecallNoticeEvent'
|
||||
|
||||
let lastRKeyUpdateTime = 0
|
||||
|
||||
@@ -63,6 +65,7 @@ export class OB11Constructor {
|
||||
time: parseInt(msg.msgTime) || Date.now(),
|
||||
message_id: msg.msgShortId,
|
||||
real_id: msg.msgShortId,
|
||||
message_seq: msg.msgShortId,
|
||||
message_type: msg.chatType == ChatType.group ? 'group' : 'private',
|
||||
sender: {
|
||||
user_id: parseInt(msg.senderUin),
|
||||
@@ -84,13 +87,15 @@ 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) {
|
||||
@@ -108,7 +113,8 @@ 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') {
|
||||
@@ -122,14 +128,16 @@ 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 {
|
||||
@@ -137,13 +145,15 @@ 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
|
||||
@@ -172,7 +182,8 @@ 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
|
||||
@@ -201,7 +212,8 @@ 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
|
||||
@@ -221,22 +233,27 @@ 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
|
||||
@@ -249,11 +266,13 @@ export class OB11Constructor {
|
||||
message_data['data']['emoji_id'] = element.marketFaceElement.emojiId
|
||||
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) {
|
||||
mFaceCache.set(md5, element.marketFaceElement.faceName)
|
||||
}
|
||||
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
|
||||
}
|
||||
@@ -261,7 +280,8 @@ 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
|
||||
}
|
||||
@@ -310,7 +330,8 @@ 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
|
||||
@@ -321,7 +342,8 @@ 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
|
||||
@@ -338,7 +360,8 @@ 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()
|
||||
@@ -358,7 +381,8 @@ 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,
|
||||
@@ -423,7 +447,8 @@ 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)
|
||||
/*
|
||||
{
|
||||
@@ -463,14 +488,32 @@ export class OB11Constructor {
|
||||
|
||||
static async FriendAddEvent(msg: RawMessage): Promise<OB11FriendAddNoticeEvent | undefined> {
|
||||
if (msg.chatType !== ChatType.friend) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
if (msg.msgType === 5 && msg.subMsgType === 12) {
|
||||
const event = new OB11FriendAddNoticeEvent(parseInt(msg.peerUin));
|
||||
return event;
|
||||
const event = new OB11FriendAddNoticeEvent(parseInt(msg.peerUin))
|
||||
return event
|
||||
}
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
static async RecallEvent(msg: RawMessage): Promise<OB11FriendRecallNoticeEvent | OB11GroupRecallNoticeEvent | undefined>{
|
||||
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{
|
||||
return new OB11FriendRecallNoticeEvent(parseInt(msg.senderUin), msg.msgShortId)
|
||||
}
|
||||
}
|
||||
|
||||
static friend(friend: User): OB11User {
|
||||
return {
|
||||
user_id: parseInt(friend.uin),
|
||||
|
@@ -75,6 +75,7 @@ export interface OB11Message {
|
||||
self_id?: number
|
||||
time: number
|
||||
message_id: number
|
||||
message_seq: number // go-cqhttp字段,实际上是message_id
|
||||
real_id: number
|
||||
user_id: number
|
||||
group_id?: number
|
||||
|
@@ -1 +1 @@
|
||||
export const version = '3.24.0'
|
||||
export const version = '3.24.2'
|
||||
|
Reference in New Issue
Block a user