mirror of
https://github.com/LLOneBot/LLOneBot.git
synced 2024-11-22 01:56:33 +00:00
Compare commits
26 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
debe3a8597 | ||
![]() |
f36c5e849f | ||
![]() |
abbd6797c4 | ||
![]() |
fdb7784a7d | ||
![]() |
92b49015b0 | ||
![]() |
1765ffff7b | ||
![]() |
3024316b5b | ||
![]() |
9a0d89bfbf | ||
![]() |
807ef3b700 | ||
![]() |
948f10d4e3 | ||
![]() |
0f99b5cb87 | ||
![]() |
6413b0ff82 | ||
![]() |
39713d8e11 | ||
![]() |
739a497af6 | ||
![]() |
de2fe9b0aa | ||
![]() |
44448895a0 | ||
![]() |
cfd9097769 | ||
![]() |
627042fd25 | ||
![]() |
b51ce24d0c | ||
![]() |
fc0881eccc | ||
![]() |
6b8509d2b2 | ||
![]() |
cf1d67a5cf | ||
![]() |
473ebd25b8 | ||
![]() |
d4427cfff4 | ||
![]() |
9d2e9786cc | ||
![]() |
9968f714c7 |
@@ -1,4 +1,4 @@
|
|||||||
# LLOneBot API
|
# LLOneBot
|
||||||
|
|
||||||
LiteLoaderQQNT插件,使你的NTQQ支持OneBot11协议进行QQ机器人开发
|
LiteLoaderQQNT插件,使你的NTQQ支持OneBot11协议进行QQ机器人开发
|
||||||
|
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"manifest_version": 4,
|
"manifest_version": 4,
|
||||||
"type": "extension",
|
"type": "extension",
|
||||||
"name": "LLOneBot v3.24.4",
|
"name": "LLOneBot v3.26.1",
|
||||||
"slug": "LLOneBot",
|
"slug": "LLOneBot",
|
||||||
"description": "使你的NTQQ支持OneBot11协议进行QQ机器人开发, 不支持商店在线更新",
|
"description": "使你的NTQQ支持OneBot11协议进行QQ机器人开发, 不支持商店在线更新",
|
||||||
"version": "3.24.4",
|
"version": "3.26.1",
|
||||||
"icon": "./icon.jpg",
|
"icon": "./icon.jpg",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
|
@@ -1,4 +1,12 @@
|
|||||||
import { type Friend, type FriendRequest, type Group, type GroupMember, type SelfInfo } from '../ntqqapi/types'
|
import {
|
||||||
|
CategoryFriend,
|
||||||
|
type Friend,
|
||||||
|
type FriendRequest,
|
||||||
|
type Group,
|
||||||
|
type GroupMember,
|
||||||
|
type SelfInfo,
|
||||||
|
User,
|
||||||
|
} from '../ntqqapi/types'
|
||||||
import { type FileCache, type LLOneBotError } from './types'
|
import { type FileCache, type LLOneBotError } from './types'
|
||||||
import { NTQQGroupApi } from '../ntqqapi/api/group'
|
import { NTQQGroupApi } from '../ntqqapi/api/group'
|
||||||
import { log } from './utils/log'
|
import { log } from './utils/log'
|
||||||
@@ -14,8 +22,8 @@ export const selfInfo: SelfInfo = {
|
|||||||
}
|
}
|
||||||
export const WebGroupData = {
|
export const WebGroupData = {
|
||||||
GroupData: new Map<string, Array<WebApiGroupMember>>(),
|
GroupData: new Map<string, Array<WebApiGroupMember>>(),
|
||||||
GroupTime: new Map<string, number>()
|
GroupTime: new Map<string, number>(),
|
||||||
};
|
}
|
||||||
export let groups: Group[] = []
|
export let groups: Group[] = []
|
||||||
export let friends: Friend[] = []
|
export let friends: Friend[] = []
|
||||||
export let friendRequests: Map<number, FriendRequest> = new Map<number, FriendRequest>()
|
export let friendRequests: Map<number, FriendRequest> = new Map<number, FriendRequest>()
|
||||||
@@ -53,7 +61,8 @@ 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
|
||||||
}
|
}
|
||||||
@@ -111,3 +120,5 @@ export function getUidByUin(uin: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export let tempGroupCodeMap: Record<string, string> = {} // peerUid => 群号
|
export let tempGroupCodeMap: Record<string, string> = {} // peerUid => 群号
|
||||||
|
|
||||||
|
export let rawFriends: CategoryFriend[] = []
|
@@ -45,5 +45,6 @@ export interface FileCache {
|
|||||||
fileUuid?: string
|
fileUuid?: string
|
||||||
url?: string
|
url?: string
|
||||||
msgId?: string
|
msgId?: string
|
||||||
|
elementId: string
|
||||||
downloadFunc?: () => Promise<void>
|
downloadFunc?: () => Promise<void>
|
||||||
}
|
}
|
||||||
|
@@ -38,7 +38,7 @@ import {
|
|||||||
import { httpHeart, ob11HTTPServer } from '../onebot11/server/http'
|
import { httpHeart, ob11HTTPServer } from '../onebot11/server/http'
|
||||||
import { OB11FriendRecallNoticeEvent } from '../onebot11/event/notice/OB11FriendRecallNoticeEvent'
|
import { OB11FriendRecallNoticeEvent } from '../onebot11/event/notice/OB11FriendRecallNoticeEvent'
|
||||||
import { OB11GroupRecallNoticeEvent } from '../onebot11/event/notice/OB11GroupRecallNoticeEvent'
|
import { OB11GroupRecallNoticeEvent } from '../onebot11/event/notice/OB11GroupRecallNoticeEvent'
|
||||||
import { postOB11Event } from '../onebot11/server/postOB11Event'
|
import { postOb11Event } from '../onebot11/server/post-ob11-event'
|
||||||
import { ob11ReverseWebsockets } from '../onebot11/server/ws/ReverseWebsocket'
|
import { ob11ReverseWebsockets } from '../onebot11/server/ws/ReverseWebsocket'
|
||||||
import { OB11GroupAdminNoticeEvent } from '../onebot11/event/notice/OB11GroupAdminNoticeEvent'
|
import { OB11GroupAdminNoticeEvent } from '../onebot11/event/notice/OB11GroupAdminNoticeEvent'
|
||||||
import { OB11GroupRequestEvent } from '../onebot11/event/request/OB11GroupRequest'
|
import { OB11GroupRequestEvent } from '../onebot11/event/request/OB11GroupRequest'
|
||||||
@@ -142,7 +142,8 @@ function onLoad() {
|
|||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
log('保存设置失败', e.stack)
|
log('保存设置失败', e.stack)
|
||||||
})
|
})
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
@@ -169,13 +170,9 @@ function onLoad() {
|
|||||||
|
|
||||||
OB11Constructor.message(message)
|
OB11Constructor.message(message)
|
||||||
.then((msg) => {
|
.then((msg) => {
|
||||||
if (debug) {
|
if (!debug && msg.message.length === 0) {
|
||||||
msg.raw = message
|
|
||||||
} else {
|
|
||||||
if (msg.message.length === 0) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
|
||||||
const isSelfMsg = msg.user_id.toString() == selfInfo.uin
|
const isSelfMsg = msg.user_id.toString() == selfInfo.uin
|
||||||
if (isSelfMsg && !reportSelfMessage) {
|
if (isSelfMsg && !reportSelfMessage) {
|
||||||
return
|
return
|
||||||
@@ -183,20 +180,20 @@ function onLoad() {
|
|||||||
if (isSelfMsg) {
|
if (isSelfMsg) {
|
||||||
msg.target_id = parseInt(message.peerUin)
|
msg.target_id = parseInt(message.peerUin)
|
||||||
}
|
}
|
||||||
postOB11Event(msg)
|
postOb11Event(msg)
|
||||||
// log("post msg", msg)
|
// log("post msg", msg)
|
||||||
})
|
})
|
||||||
.catch((e) => log('constructMessage error: ', e.stack.toString()))
|
.catch((e) => log('constructMessage error: ', e.stack.toString()))
|
||||||
OB11Constructor.GroupEvent(message).then((groupEvent) => {
|
OB11Constructor.GroupEvent(message).then((groupEvent) => {
|
||||||
if (groupEvent) {
|
if (groupEvent) {
|
||||||
// log("post group event", groupEvent);
|
// log("post group event", groupEvent);
|
||||||
postOB11Event(groupEvent)
|
postOb11Event(groupEvent)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
OB11Constructor.FriendAddEvent(message).then((friendAddEvent) => {
|
OB11Constructor.FriendAddEvent(message).then((friendAddEvent) => {
|
||||||
if (friendAddEvent) {
|
if (friendAddEvent) {
|
||||||
// log("post friend add event", friendAddEvent);
|
// log("post friend add event", friendAddEvent);
|
||||||
postOB11Event(friendAddEvent)
|
postOb11Event(friendAddEvent)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -210,10 +207,11 @@ function onLoad() {
|
|||||||
let pokeEvent: OB11FriendPokeEvent | OB11GroupPokeEvent
|
let pokeEvent: OB11FriendPokeEvent | OB11GroupPokeEvent
|
||||||
if (isGroup) {
|
if (isGroup) {
|
||||||
pokeEvent = new OB11GroupPokeEvent(parseInt(id))
|
pokeEvent = new OB11GroupPokeEvent(parseInt(id))
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
pokeEvent = new OB11FriendPokeEvent(parseInt(id))
|
pokeEvent = new OB11FriendPokeEvent(parseInt(id))
|
||||||
}
|
}
|
||||||
postOB11Event(pokeEvent)
|
postOb11Event(pokeEvent)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
registerReceiveHook<{
|
registerReceiveHook<{
|
||||||
@@ -244,7 +242,7 @@ function onLoad() {
|
|||||||
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)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// 不让入库覆盖原来消息,不然就获取不到撤回的消息内容了
|
// 不让入库覆盖原来消息,不然就获取不到撤回的消息内容了
|
||||||
@@ -322,11 +320,13 @@ function onLoad() {
|
|||||||
? 'unset'
|
? 'unset'
|
||||||
: 'set'
|
: '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 {
|
||||||
log('获取群通知的成员信息失败', notify, getGroup(notify.group.groupCode))
|
log('获取群通知的成员信息失败', notify, getGroup(notify.group.groupCode))
|
||||||
}
|
}
|
||||||
} else if (notify.type == GroupNotifyTypes.MEMBER_EXIT || notify.type == GroupNotifyTypes.KICK_MEMBER) {
|
}
|
||||||
|
else if (notify.type == GroupNotifyTypes.MEMBER_EXIT || notify.type == GroupNotifyTypes.KICK_MEMBER) {
|
||||||
log('有成员退出通知', notify)
|
log('有成员退出通知', notify)
|
||||||
try {
|
try {
|
||||||
const member1 = await NTQQUserApi.getUserDetailInfo(notify.user1.uid)
|
const member1 = await NTQQUserApi.getUserDetailInfo(notify.user1.uid)
|
||||||
@@ -344,11 +344,12 @@ function onLoad() {
|
|||||||
parseInt(operatorId),
|
parseInt(operatorId),
|
||||||
subType,
|
subType,
|
||||||
)
|
)
|
||||||
postOB11Event(groupDecreaseEvent, true)
|
postOb11Event(groupDecreaseEvent, true)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log('获取群通知的成员信息失败', notify, e.stack.toString())
|
log('获取群通知的成员信息失败', notify, e.stack.toString())
|
||||||
}
|
}
|
||||||
} else if ([GroupNotifyTypes.JOIN_REQUEST].includes(notify.type)) {
|
}
|
||||||
|
else if ([GroupNotifyTypes.JOIN_REQUEST].includes(notify.type)) {
|
||||||
log('有加群请求')
|
log('有加群请求')
|
||||||
let groupRequestEvent = new OB11GroupRequestEvent()
|
let groupRequestEvent = new OB11GroupRequestEvent()
|
||||||
groupRequestEvent.group_id = parseInt(notify.group.groupCode)
|
groupRequestEvent.group_id = parseInt(notify.group.groupCode)
|
||||||
@@ -362,8 +363,9 @@ function onLoad() {
|
|||||||
groupRequestEvent.sub_type = 'add'
|
groupRequestEvent.sub_type = 'add'
|
||||||
groupRequestEvent.comment = notify.postscript
|
groupRequestEvent.comment = notify.postscript
|
||||||
groupRequestEvent.flag = notify.seq
|
groupRequestEvent.flag = notify.seq
|
||||||
postOB11Event(groupRequestEvent)
|
postOb11Event(groupRequestEvent)
|
||||||
} else if (notify.type == GroupNotifyTypes.INVITE_ME) {
|
}
|
||||||
|
else if (notify.type == GroupNotifyTypes.INVITE_ME) {
|
||||||
log('收到邀请我加群通知')
|
log('收到邀请我加群通知')
|
||||||
let groupInviteEvent = new OB11GroupRequestEvent()
|
let groupInviteEvent = new OB11GroupRequestEvent()
|
||||||
groupInviteEvent.group_id = parseInt(notify.group.groupCode)
|
groupInviteEvent.group_id = parseInt(notify.group.groupCode)
|
||||||
@@ -374,13 +376,14 @@ function onLoad() {
|
|||||||
groupInviteEvent.user_id = parseInt(user_id)
|
groupInviteEvent.user_id = parseInt(user_id)
|
||||||
groupInviteEvent.sub_type = 'invite'
|
groupInviteEvent.sub_type = 'invite'
|
||||||
groupInviteEvent.flag = notify.seq
|
groupInviteEvent.flag = notify.seq
|
||||||
postOB11Event(groupInviteEvent)
|
postOb11Event(groupInviteEvent)
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log('解析群通知失败', e.stack.toString())
|
log('解析群通知失败', e.stack.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (payload.doubt) {
|
}
|
||||||
|
else if (payload.doubt) {
|
||||||
// 可能有群管理员变动
|
// 可能有群管理员变动
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -400,7 +403,7 @@ function onLoad() {
|
|||||||
}
|
}
|
||||||
friendRequestEvent.flag = flag
|
friendRequestEvent.flag = flag
|
||||||
friendRequestEvent.comment = req.extWords
|
friendRequestEvent.comment = req.extWords
|
||||||
postOB11Event(friendRequestEvent)
|
postOb11Event(friendRequestEvent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -473,7 +476,8 @@ function onLoad() {
|
|||||||
|
|
||||||
getUserNick().then()
|
getUserNick().then()
|
||||||
start().then()
|
start().then()
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
setTimeout(init, 1000)
|
setTimeout(init, 1000)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -15,6 +15,54 @@ export interface Peer {
|
|||||||
guildId?: ''
|
guildId?: ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function sendWaiter(peer: Peer, waitComplete = true, timeout: number = 10000) {
|
||||||
|
// 等待上一个相同的peer发送完
|
||||||
|
const peerUid = peer.peerUid
|
||||||
|
let checkLastSendUsingTime = 0
|
||||||
|
const waitLastSend = async () => {
|
||||||
|
if (checkLastSendUsingTime > timeout) {
|
||||||
|
throw '发送超时'
|
||||||
|
}
|
||||||
|
let lastSending = sendMessagePool[peer.peerUid]
|
||||||
|
if (lastSending) {
|
||||||
|
// log("有正在发送的消息,等待中...")
|
||||||
|
await sleep(500)
|
||||||
|
checkLastSendUsingTime += 500
|
||||||
|
return await waitLastSend()
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await waitLastSend()
|
||||||
|
|
||||||
|
let sentMessage: RawMessage = null
|
||||||
|
sendMessagePool[peerUid] = async (rawMessage: RawMessage) => {
|
||||||
|
delete sendMessagePool[peerUid]
|
||||||
|
sentMessage = rawMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
let checkSendCompleteUsingTime = 0
|
||||||
|
const checkSendComplete = async (): Promise<RawMessage> => {
|
||||||
|
if (sentMessage) {
|
||||||
|
if (waitComplete) {
|
||||||
|
if ((await dbUtil.getMsgByLongId(sentMessage.msgId)).sendStatus == 2) {
|
||||||
|
return sentMessage
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return sentMessage
|
||||||
|
}
|
||||||
|
// log(`给${peerUid}发送消息成功`)
|
||||||
|
}
|
||||||
|
checkSendCompleteUsingTime += 500
|
||||||
|
if (checkSendCompleteUsingTime > timeout) {
|
||||||
|
throw '发送超时'
|
||||||
|
}
|
||||||
|
await sleep(500)
|
||||||
|
return await checkSendComplete()
|
||||||
|
}
|
||||||
|
return checkSendComplete();
|
||||||
|
}
|
||||||
|
|
||||||
export class NTQQMsgApi {
|
export class NTQQMsgApi {
|
||||||
static async setEmojiLike(peer: Peer, msgSeq: string, emojiId: string, set: boolean = true) {
|
static async setEmojiLike(peer: Peer, msgSeq: string, emojiId: string, set: boolean = true) {
|
||||||
// nt_qq//global//nt_data//Emoji//emoji-resource//sysface_res/apng/ 下可以看到所有QQ表情预览
|
// nt_qq//global//nt_data//Emoji//emoji-resource//sysface_res/apng/ 下可以看到所有QQ表情预览
|
||||||
@@ -116,52 +164,7 @@ export class NTQQMsgApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static async sendMsg(peer: Peer, msgElements: SendMessageElement[], waitComplete = true, timeout = 10000) {
|
static async sendMsg(peer: Peer, msgElements: SendMessageElement[], waitComplete = true, timeout = 10000) {
|
||||||
const peerUid = peer.peerUid
|
const waiter = sendWaiter(peer, waitComplete, timeout);
|
||||||
|
|
||||||
// 等待上一个相同的peer发送完
|
|
||||||
let checkLastSendUsingTime = 0
|
|
||||||
const waitLastSend = async () => {
|
|
||||||
if (checkLastSendUsingTime > timeout) {
|
|
||||||
throw '发送超时'
|
|
||||||
}
|
|
||||||
let lastSending = sendMessagePool[peer.peerUid]
|
|
||||||
if (lastSending) {
|
|
||||||
// log("有正在发送的消息,等待中...")
|
|
||||||
await sleep(500)
|
|
||||||
checkLastSendUsingTime += 500
|
|
||||||
return await waitLastSend()
|
|
||||||
} else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await waitLastSend()
|
|
||||||
|
|
||||||
let sentMessage: RawMessage = null
|
|
||||||
sendMessagePool[peerUid] = async (rawMessage: RawMessage) => {
|
|
||||||
delete sendMessagePool[peerUid]
|
|
||||||
sentMessage = rawMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
let checkSendCompleteUsingTime = 0
|
|
||||||
const checkSendComplete = async (): Promise<RawMessage> => {
|
|
||||||
if (sentMessage) {
|
|
||||||
if (waitComplete) {
|
|
||||||
if ((await dbUtil.getMsgByLongId(sentMessage.msgId)).sendStatus == 2) {
|
|
||||||
return sentMessage
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return sentMessage
|
|
||||||
}
|
|
||||||
// log(`给${peerUid}发送消息成功`)
|
|
||||||
}
|
|
||||||
checkSendCompleteUsingTime += 500
|
|
||||||
if (checkSendCompleteUsingTime > timeout) {
|
|
||||||
throw '发送超时'
|
|
||||||
}
|
|
||||||
await sleep(500)
|
|
||||||
return await checkSendComplete()
|
|
||||||
}
|
|
||||||
|
|
||||||
callNTQQApi({
|
callNTQQApi({
|
||||||
methodName: NTQQApiMethod.SEND_MSG,
|
methodName: NTQQApiMethod.SEND_MSG,
|
||||||
args: [
|
args: [
|
||||||
@@ -174,11 +177,12 @@ export class NTQQMsgApi {
|
|||||||
null,
|
null,
|
||||||
],
|
],
|
||||||
}).then()
|
}).then()
|
||||||
return await checkSendComplete()
|
return await waiter;
|
||||||
}
|
}
|
||||||
|
|
||||||
static async forwardMsg(srcPeer: Peer, destPeer: Peer, msgIds: string[]) {
|
static async forwardMsg(srcPeer: Peer, destPeer: Peer, msgIds: string[]) {
|
||||||
return await callNTQQApi<GeneralCallResult>({
|
const waiter = sendWaiter(destPeer, true, 10000);
|
||||||
|
callNTQQApi<GeneralCallResult>({
|
||||||
methodName: NTQQApiMethod.FORWARD_MSG,
|
methodName: NTQQApiMethod.FORWARD_MSG,
|
||||||
args: [
|
args: [
|
||||||
{
|
{
|
||||||
@@ -190,7 +194,8 @@ export class NTQQMsgApi {
|
|||||||
},
|
},
|
||||||
null,
|
null,
|
||||||
],
|
],
|
||||||
})
|
}).then().catch(log)
|
||||||
|
return await waiter;
|
||||||
}
|
}
|
||||||
|
|
||||||
static async multiForwardMsg(srcPeer: Peer, destPeer: Peer, msgIds: string[]) {
|
static async multiForwardMsg(srcPeer: Peer, destPeer: Peer, msgIds: string[]) {
|
||||||
|
@@ -76,6 +76,10 @@ export class SendMsgElementConstructor {
|
|||||||
if (fileSize === 0) {
|
if (fileSize === 0) {
|
||||||
throw '文件异常,大小为0'
|
throw '文件异常,大小为0'
|
||||||
}
|
}
|
||||||
|
const maxMB = 30;
|
||||||
|
if (fileSize > 1024 * 1024 * 30){
|
||||||
|
throw `图片过大,最大支持${maxMB}MB,当前文件大小${fileSize}B`
|
||||||
|
}
|
||||||
const imageSize = await NTQQFileApi.getImageSize(picPath)
|
const imageSize = await NTQQFileApi.getImageSize(picPath)
|
||||||
const picElement = {
|
const picElement = {
|
||||||
md5HexStr: md5,
|
md5HexStr: md5,
|
||||||
@@ -131,6 +135,10 @@ export class SendMsgElementConstructor {
|
|||||||
if (fileSize === 0) {
|
if (fileSize === 0) {
|
||||||
throw '文件异常,大小为0'
|
throw '文件异常,大小为0'
|
||||||
}
|
}
|
||||||
|
const maxMB = 100;
|
||||||
|
if (fileSize > 1024 * 1024 * maxMB) {
|
||||||
|
throw `视频过大,最大支持${maxMB}MB,当前文件大小${fileSize}B`
|
||||||
|
}
|
||||||
const pathLib = require('path')
|
const pathLib = require('path')
|
||||||
let thumbDir = path.replace(`${pathLib.sep}Ori${pathLib.sep}`, `${pathLib.sep}Thumb${pathLib.sep}`)
|
let thumbDir = path.replace(`${pathLib.sep}Ori${pathLib.sep}`, `${pathLib.sep}Thumb${pathLib.sep}`)
|
||||||
thumbDir = pathLib.dirname(thumbDir)
|
thumbDir = pathLib.dirname(thumbDir)
|
||||||
|
@@ -1,26 +1,26 @@
|
|||||||
import { BrowserWindow } from 'electron'
|
import { BrowserWindow } from 'electron'
|
||||||
import { NTQQApiClass, NTQQApiMethod } from './ntcall'
|
import { NTQQApiClass, NTQQApiMethod } from './ntcall'
|
||||||
import { NTQQMsgApi, sendMessagePool } from './api/msg'
|
import { NTQQMsgApi, sendMessagePool } from './api/msg'
|
||||||
import { ChatType, Group, GroupMember, GroupMemberRole, RawMessage, User } from './types'
|
import { CategoryFriend, ChatType, Group, GroupMember, GroupMemberRole, RawMessage, User } from './types'
|
||||||
import {
|
import {
|
||||||
deleteGroup,
|
deleteGroup,
|
||||||
friends,
|
friends,
|
||||||
getFriend,
|
getFriend,
|
||||||
getGroupMember,
|
getGroupMember,
|
||||||
groups,
|
groups, rawFriends,
|
||||||
selfInfo,
|
selfInfo,
|
||||||
tempGroupCodeMap,
|
tempGroupCodeMap,
|
||||||
uidMaps,
|
uidMaps,
|
||||||
} from '../common/data'
|
} from '@/common/data'
|
||||||
import { OB11GroupDecreaseEvent } from '../onebot11/event/notice/OB11GroupDecreaseEvent'
|
import { OB11GroupDecreaseEvent } from '../onebot11/event/notice/OB11GroupDecreaseEvent'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import { postOB11Event } from '../onebot11/server/postOB11Event'
|
import { postOb11Event } from '../onebot11/server/post-ob11-event'
|
||||||
import { getConfigUtil, HOOK_LOG } from '../common/config'
|
import { getConfigUtil, HOOK_LOG } from '@/common/config'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import { dbUtil } from '../common/db'
|
import { dbUtil } from '@/common/db'
|
||||||
import { NTQQGroupApi } from './api/group'
|
import { NTQQGroupApi } from './api/group'
|
||||||
import { log } from '../common/utils/log'
|
import { log } from '@/common/utils'
|
||||||
import { isNumeric, sleep } from '../common/utils/helper'
|
import { isNumeric, sleep } from '@/common/utils'
|
||||||
import { OB11Constructor } from '../onebot11/constructor'
|
import { OB11Constructor } from '../onebot11/constructor'
|
||||||
|
|
||||||
export let hookApiCallbacks: Record<string, (apiReturn: any) => void> = {}
|
export let hookApiCallbacks: Record<string, (apiReturn: any) => void> = {}
|
||||||
@@ -299,7 +299,7 @@ async function processGroupEvent(payload: { groupList: Group[] }) {
|
|||||||
}
|
}
|
||||||
for (const member of oldMembers) {
|
for (const member of oldMembers) {
|
||||||
if (!newMembersSet.has(member.uin) && member.uin != selfInfo.uin) {
|
if (!newMembersSet.has(member.uin) && member.uin != selfInfo.uin) {
|
||||||
postOB11Event(
|
postOb11Event(
|
||||||
new OB11GroupDecreaseEvent(
|
new OB11GroupDecreaseEvent(
|
||||||
parseInt(group.groupCode),
|
parseInt(group.groupCode),
|
||||||
parseInt(member.uin),
|
parseInt(member.uin),
|
||||||
@@ -380,8 +380,10 @@ registerReceiveHook<{
|
|||||||
|
|
||||||
// 好友列表变动
|
// 好友列表变动
|
||||||
registerReceiveHook<{
|
registerReceiveHook<{
|
||||||
data: { categoryId: number; categroyName: string; categroyMbCount: number; buddyList: User[] }[]
|
data:CategoryFriend[]
|
||||||
}>(ReceiveCmdS.FRIENDS, (payload) => {
|
}>(ReceiveCmdS.FRIENDS, (payload) => {
|
||||||
|
rawFriends.length = 0;
|
||||||
|
rawFriends.push(...payload.data);
|
||||||
for (const fData of payload.data) {
|
for (const fData of payload.data) {
|
||||||
const _friends = fData.buddyList
|
const _friends = fData.buddyList
|
||||||
for (let friend of _friends) {
|
for (let friend of _friends) {
|
||||||
@@ -497,7 +499,7 @@ registerReceiveHook<{
|
|||||||
let lastTempMsg = msgList.pop()
|
let lastTempMsg = msgList.pop()
|
||||||
log('激活窗口之前的第一条临时会话消息:', lastTempMsg)
|
log('激活窗口之前的第一条临时会话消息:', lastTempMsg)
|
||||||
if (Date.now() / 1000 - parseInt(lastTempMsg.msgTime) < 5) {
|
if (Date.now() / 1000 - parseInt(lastTempMsg.msgTime) < 5) {
|
||||||
OB11Constructor.message(lastTempMsg).then((r) => postOB11Event(r))
|
OB11Constructor.message(lastTempMsg).then((r) => postOb11Event(r))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@@ -10,6 +10,7 @@ export interface QQLevel {
|
|||||||
moonNum: number
|
moonNum: number
|
||||||
starNum: number
|
starNum: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface User {
|
export interface User {
|
||||||
uid: string // 加密的字符串
|
uid: string // 加密的字符串
|
||||||
uin: string // QQ号
|
uin: string // QQ号
|
||||||
@@ -72,4 +73,12 @@ export interface SelfInfo extends User {
|
|||||||
online?: boolean
|
online?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Friend extends User {}
|
export interface Friend extends User {
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CategoryFriend {
|
||||||
|
categoryId: number;
|
||||||
|
categroyName: string;
|
||||||
|
categroyMbCount: number;
|
||||||
|
buddyList: User[]
|
||||||
|
}
|
@@ -21,13 +21,12 @@ export interface GetFileResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
|
export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
|
||||||
private getElement(msg: RawMessage): { id: string; element: VideoElement | FileElement } {
|
private getElement(msg: RawMessage, elementId: string): VideoElement | FileElement {
|
||||||
let element = msg.elements.find((e) => e.fileElement)
|
let element = msg.elements.find((e) => e.elementId === elementId)
|
||||||
if (!element) {
|
if (!element) {
|
||||||
element = msg.elements.find((e) => e.videoElement)
|
throw new Error('element not found')
|
||||||
return { id: element.elementId, element: element.videoElement }
|
|
||||||
}
|
}
|
||||||
return { id: element.elementId, element: element.fileElement }
|
return element.fileElement
|
||||||
}
|
}
|
||||||
private async download(cache: FileCache, file: string) {
|
private async download(cache: FileCache, file: string) {
|
||||||
log('需要调用 NTQQ 下载文件api')
|
log('需要调用 NTQQ 下载文件api')
|
||||||
@@ -35,14 +34,14 @@ export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
|
|||||||
let msg = await dbUtil.getMsgByLongId(cache.msgId)
|
let msg = await dbUtil.getMsgByLongId(cache.msgId)
|
||||||
if (msg) {
|
if (msg) {
|
||||||
log('找到了文件 msg', msg)
|
log('找到了文件 msg', msg)
|
||||||
let element = this.getElement(msg)
|
let element = this.getElement(msg, cache.elementId)
|
||||||
log('找到了文件 element', element)
|
log('找到了文件 element', element)
|
||||||
// 构建下载函数
|
// 构建下载函数
|
||||||
await NTQQFileApi.downloadMedia(msg.msgId, msg.chatType, msg.peerUid, element.id, '', '', true)
|
await NTQQFileApi.downloadMedia(msg.msgId, msg.chatType, msg.peerUid, cache.elementId, '', '', true)
|
||||||
await sleep(1000)
|
await sleep(1000) // 这里延时是为何?
|
||||||
msg = await dbUtil.getMsgByLongId(cache.msgId)
|
msg = await dbUtil.getMsgByLongId(cache.msgId)
|
||||||
log('下载完成后的msg', msg)
|
log('下载完成后的msg', msg)
|
||||||
cache.filePath = this.getElement(msg).element.filePath
|
cache.filePath = this.getElement(msg, cache.elementId).filePath
|
||||||
dbUtil.addFileCache(file, cache).then()
|
dbUtil.addFileCache(file, cache).then()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,7 +6,8 @@ import { OB11Constructor } from '../../constructor'
|
|||||||
import { ActionName } from '../types'
|
import { ActionName } from '../types'
|
||||||
|
|
||||||
interface Payload {
|
interface Payload {
|
||||||
message_id: string // long msg id
|
message_id: string // long msg id,gocq
|
||||||
|
id?: string // long msg id, onebot11
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Response {
|
interface Response {
|
||||||
@@ -16,7 +17,11 @@ interface Response {
|
|||||||
export class GoCQHTTGetForwardMsgAction extends BaseAction<Payload, any> {
|
export class GoCQHTTGetForwardMsgAction extends BaseAction<Payload, any> {
|
||||||
actionName = ActionName.GoCQHTTP_GetForwardMsg
|
actionName = ActionName.GoCQHTTP_GetForwardMsg
|
||||||
protected async _handle(payload: Payload): Promise<any> {
|
protected async _handle(payload: Payload): Promise<any> {
|
||||||
const rootMsg = await dbUtil.getMsgByLongId(payload.message_id)
|
const message_id = payload.id || payload.message_id
|
||||||
|
if (!message_id) {
|
||||||
|
throw Error('message_id不能为空')
|
||||||
|
}
|
||||||
|
const rootMsg = await dbUtil.getMsgByLongId(message_id)
|
||||||
if (!rootMsg) {
|
if (!rootMsg) {
|
||||||
throw Error('msg not found')
|
throw Error('msg not found')
|
||||||
}
|
}
|
||||||
|
17
src/onebot11/action/go-cqhttp/QuickOperation.ts
Normal file
17
src/onebot11/action/go-cqhttp/QuickOperation.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import BaseAction from '../BaseAction'
|
||||||
|
import { handleQuickOperation, QuickOperation, QuickOperationEvent } from '../quick-operation'
|
||||||
|
import { log } from '@/common/utils'
|
||||||
|
import { ActionName } from '../types'
|
||||||
|
|
||||||
|
interface Payload{
|
||||||
|
context: QuickOperationEvent,
|
||||||
|
operation: QuickOperation
|
||||||
|
}
|
||||||
|
|
||||||
|
export class GoCQHTTHandleQuickOperation extends BaseAction<Payload, null>{
|
||||||
|
actionName = ActionName.GoCQHTTP_HandleQuickOperation
|
||||||
|
protected async _handle(payload: Payload): Promise<null> {
|
||||||
|
handleQuickOperation(payload.context, payload.operation).then().catch(log);
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
@@ -1,6 +1,6 @@
|
|||||||
import GetMsg from './msg/GetMsg'
|
import GetMsg from './msg/GetMsg'
|
||||||
import GetLoginInfo from './system/GetLoginInfo'
|
import GetLoginInfo from './system/GetLoginInfo'
|
||||||
import GetFriendList from './user/GetFriendList'
|
import { GetFriendList, GetFriendWithCategory} from './user/GetFriendList'
|
||||||
import GetGroupList from './group/GetGroupList'
|
import GetGroupList from './group/GetGroupList'
|
||||||
import GetGroupInfo from './group/GetGroupInfo'
|
import GetGroupInfo from './group/GetGroupInfo'
|
||||||
import GetGroupMemberList from './group/GetGroupMemberList'
|
import GetGroupMemberList from './group/GetGroupMemberList'
|
||||||
@@ -49,6 +49,7 @@ import { SetMsgEmojiLike } from './msg/SetMsgEmojiLike'
|
|||||||
import { ForwardFriendSingleMsg, ForwardSingleGroupMsg } from './msg/ForwardSingleMsg'
|
import { ForwardFriendSingleMsg, ForwardSingleGroupMsg } from './msg/ForwardSingleMsg'
|
||||||
import { GetGroupEssence } from './group/GetGroupEssence'
|
import { GetGroupEssence } from './group/GetGroupEssence'
|
||||||
import { GetGroupHonorInfo } from './group/GetGroupHonorInfo'
|
import { GetGroupHonorInfo } from './group/GetGroupHonorInfo'
|
||||||
|
import { GoCQHTTHandleQuickOperation } from './go-cqhttp/QuickOperation'
|
||||||
|
|
||||||
export const actionHandlers = [
|
export const actionHandlers = [
|
||||||
new GetFile(),
|
new GetFile(),
|
||||||
@@ -57,6 +58,7 @@ export const actionHandlers = [
|
|||||||
new SetConfigAction(),
|
new SetConfigAction(),
|
||||||
new GetGroupAddRequest(),
|
new GetGroupAddRequest(),
|
||||||
new SetQQAvatar(),
|
new SetQQAvatar(),
|
||||||
|
new GetFriendWithCategory(),
|
||||||
// onebot11
|
// onebot11
|
||||||
new SendLike(),
|
new SendLike(),
|
||||||
new GetMsg(),
|
new GetMsg(),
|
||||||
@@ -104,6 +106,7 @@ export const actionHandlers = [
|
|||||||
new GoCQHTTPUploadPrivateFile(),
|
new GoCQHTTPUploadPrivateFile(),
|
||||||
new GoCQHTTPGetGroupMsgHistory(),
|
new GoCQHTTPGetGroupMsgHistory(),
|
||||||
new GoCQHTTGetForwardMsgAction(),
|
new GoCQHTTGetForwardMsgAction(),
|
||||||
|
new GoCQHTTHandleQuickOperation()
|
||||||
]
|
]
|
||||||
|
|
||||||
function initActionMap() {
|
function initActionMap() {
|
||||||
|
@@ -11,7 +11,11 @@ interface Payload {
|
|||||||
user_id?: number
|
user_id?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
class ForwardSingleMsg extends BaseAction<Payload, null> {
|
interface Response {
|
||||||
|
message_id: number
|
||||||
|
}
|
||||||
|
|
||||||
|
class ForwardSingleMsg extends BaseAction<Payload, Response> {
|
||||||
protected async getTargetPeer(payload: Payload): Promise<Peer> {
|
protected async getTargetPeer(payload: Payload): Promise<Peer> {
|
||||||
if (payload.user_id) {
|
if (payload.user_id) {
|
||||||
return { chatType: ChatType.friend, peerUid: getUidByUin(payload.user_id.toString()) }
|
return { chatType: ChatType.friend, peerUid: getUidByUin(payload.user_id.toString()) }
|
||||||
@@ -19,10 +23,10 @@ class ForwardSingleMsg extends BaseAction<Payload, null> {
|
|||||||
return { chatType: ChatType.group, peerUid: payload.group_id.toString() }
|
return { chatType: ChatType.group, peerUid: payload.group_id.toString() }
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async _handle(payload: Payload): Promise<null> {
|
protected async _handle(payload: Payload): Promise<Response> {
|
||||||
const msg = await dbUtil.getMsgByShortId(payload.message_id)
|
const msg = await dbUtil.getMsgByShortId(payload.message_id)
|
||||||
const peer = await this.getTargetPeer(payload)
|
const peer = await this.getTargetPeer(payload)
|
||||||
await NTQQMsgApi.forwardMsg(
|
const sentMsg = await NTQQMsgApi.forwardMsg(
|
||||||
{
|
{
|
||||||
chatType: msg.chatType,
|
chatType: msg.chatType,
|
||||||
peerUid: msg.peerUid,
|
peerUid: msg.peerUid,
|
||||||
@@ -30,7 +34,8 @@ class ForwardSingleMsg extends BaseAction<Payload, null> {
|
|||||||
peer,
|
peer,
|
||||||
[msg.msgId],
|
[msg.msgId],
|
||||||
)
|
)
|
||||||
return null
|
const ob11MsgId = await dbUtil.addMsg(sentMsg)
|
||||||
|
return {message_id: ob11MsgId}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -50,22 +50,28 @@ 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']) {
|
}
|
||||||
return 400
|
else if (type === 'at' && !data['qq']) {
|
||||||
} else if (type === 'reply' && !data['id']) {
|
|
||||||
return 400
|
return 400
|
||||||
}
|
}
|
||||||
} else {
|
else if (type === 'reply' && !data['id']) {
|
||||||
|
return 400
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
return 400
|
return 400
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -87,10 +93,12 @@ 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
|
||||||
@@ -108,16 +116,14 @@ 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
|
||||||
}
|
}
|
||||||
@@ -136,12 +142,14 @@ 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) {
|
||||||
@@ -153,8 +161,7 @@ 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))
|
||||||
@@ -171,16 +178,14 @@ 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(
|
SendMsgElementConstructor.mface(
|
||||||
sendMsg.data.emoji_package_id,
|
sendMsg.data.emoji_package_id,
|
||||||
@@ -194,8 +199,7 @@ export async function createSendElements(
|
|||||||
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
|
||||||
@@ -204,10 +208,12 @@ 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)
|
||||||
@@ -224,7 +230,8 @@ 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,9 +241,11 @@ 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,
|
||||||
@@ -249,18 +258,17 @@ 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)
|
||||||
}
|
}
|
||||||
@@ -270,14 +278,12 @@ 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))
|
||||||
}
|
}
|
||||||
@@ -300,10 +306,34 @@ export async function sendMsg(
|
|||||||
if (!sendElements.length) {
|
if (!sendElements.length) {
|
||||||
throw '消息体无法解析,请检查是否发送了不支持的消息类型'
|
throw '消息体无法解析,请检查是否发送了不支持的消息类型'
|
||||||
}
|
}
|
||||||
const returnMsg = await NTQQMsgApi.sendMsg(peer, sendElements, waitComplete, 20000)
|
// 计算发送的文件大小
|
||||||
|
let totalSize = 0
|
||||||
|
for (const fileElement of sendElements) {
|
||||||
|
try {
|
||||||
|
if (fileElement.elementType === ElementType.PTT) {
|
||||||
|
totalSize += fs.statSync(fileElement.pttElement.filePath).size
|
||||||
|
}
|
||||||
|
if (fileElement.elementType === ElementType.FILE) {
|
||||||
|
totalSize += fs.statSync(fileElement.fileElement.filePath).size
|
||||||
|
}
|
||||||
|
if (fileElement.elementType === ElementType.VIDEO) {
|
||||||
|
totalSize += fs.statSync(fileElement.videoElement.filePath).size
|
||||||
|
}
|
||||||
|
if (fileElement.elementType === ElementType.PIC) {
|
||||||
|
totalSize += fs.statSync(fileElement.picElement.sourcePath).size
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
log('文件大小计算失败', e, fileElement)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log('发送消息总大小', totalSize, 'bytes')
|
||||||
|
let timeout = ((totalSize / 1024 / 512) * 1000) + 5000 // 512kb/s
|
||||||
|
log('设置消息超时时间', timeout)
|
||||||
|
const returnMsg = await NTQQMsgApi.sendMsg(peer, sendElements, waitComplete, timeout)
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,7 +432,8 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw '发送转发消息失败 ' + e.toString()
|
throw '发送转发消息失败 ' + e.toString()
|
||||||
}
|
}
|
||||||
} else if (this.getSpecialMsgNum(messages, OB11MessageDataType.music)) {
|
}
|
||||||
|
else if (this.getSpecialMsgNum(messages, 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()
|
||||||
@@ -439,7 +470,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
let jsonContent: string
|
let jsonContent: string
|
||||||
try {
|
try {
|
||||||
jsonContent = await new MusicSign(musicSignUrl).sign(postData)
|
jsonContent = await new MusicSign(musicSignUrl).sign(postData)
|
||||||
if (!jsonContent){
|
if (!jsonContent) {
|
||||||
throw '音乐消息生成失败,提交内容有误或者签名服务器签名失败'
|
throw '音乐消息生成失败,提交内容有误或者签名服务器签名失败'
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -459,7 +490,8 @@ 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 }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -562,7 +594,8 @@ 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)
|
||||||
}
|
}
|
||||||
|
146
src/onebot11/action/quick-operation.ts
Normal file
146
src/onebot11/action/quick-operation.ts
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
// handle quick action, create at 2024-5-18 10:54:39 by linyuchen
|
||||||
|
|
||||||
|
|
||||||
|
import { OB11Message, OB11MessageAt, OB11MessageData, OB11MessageDataType } from '../types'
|
||||||
|
import { OB11FriendRequestEvent } from '../event/request/OB11FriendRequest'
|
||||||
|
import { OB11GroupRequestEvent } from '../event/request/OB11GroupRequest'
|
||||||
|
import { dbUtil } from '@/common/db'
|
||||||
|
import { NTQQFriendApi, NTQQGroupApi, NTQQMsgApi, Peer } from '@/ntqqapi/api'
|
||||||
|
import { ChatType, Group, GroupRequestOperateTypes } from '@/ntqqapi/types'
|
||||||
|
import { getGroup, getUidByUin } from '@/common/data'
|
||||||
|
import { convertMessage2List, createSendElements, sendMsg } from './msg/SendMsg'
|
||||||
|
import { isNull, log } from '@/common/utils'
|
||||||
|
|
||||||
|
|
||||||
|
interface QuickOperationPrivateMessage {
|
||||||
|
reply?: string
|
||||||
|
auto_escape?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
interface QuickOperationGroupMessage extends QuickOperationPrivateMessage {
|
||||||
|
// 回复群消息
|
||||||
|
at_sender?: boolean
|
||||||
|
delete?: boolean
|
||||||
|
kick?: boolean
|
||||||
|
ban?: boolean
|
||||||
|
ban_duration?: number
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
interface QuickOperationFriendRequest {
|
||||||
|
approve?: boolean
|
||||||
|
remark?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface QuickOperationGroupRequest {
|
||||||
|
approve?: boolean
|
||||||
|
reason?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type QuickOperation = QuickOperationPrivateMessage &
|
||||||
|
QuickOperationGroupMessage &
|
||||||
|
QuickOperationFriendRequest &
|
||||||
|
QuickOperationGroupRequest
|
||||||
|
|
||||||
|
export type QuickOperationEvent = OB11Message | OB11FriendRequestEvent | OB11GroupRequestEvent;
|
||||||
|
|
||||||
|
export async function handleQuickOperation(context: QuickOperationEvent, quickAction: QuickOperation) {
|
||||||
|
if (context.post_type === 'message') {
|
||||||
|
handleMsg(context as OB11Message, quickAction).then().catch(log)
|
||||||
|
}
|
||||||
|
if (context.post_type === 'request') {
|
||||||
|
const friendRequest = context as OB11FriendRequestEvent;
|
||||||
|
const groupRequest = context as OB11GroupRequestEvent;
|
||||||
|
if ((friendRequest).request_type === 'friend') {
|
||||||
|
handleFriendRequest(friendRequest, quickAction).then().catch(log)
|
||||||
|
}
|
||||||
|
else if (groupRequest.request_type === 'group') {
|
||||||
|
handleGroupRequest(groupRequest, quickAction).then().catch(log)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleMsg(msg: OB11Message, quickAction: QuickOperationPrivateMessage | QuickOperationGroupMessage) {
|
||||||
|
msg = msg as OB11Message
|
||||||
|
const rawMessage = await dbUtil.getMsgByShortId(msg.message_id)
|
||||||
|
const reply = quickAction.reply
|
||||||
|
let peer: Peer = {
|
||||||
|
chatType: ChatType.friend,
|
||||||
|
peerUid: msg.user_id.toString(),
|
||||||
|
}
|
||||||
|
if (msg.message_type == 'private') {
|
||||||
|
peer.peerUid = getUidByUin(msg.user_id.toString())
|
||||||
|
if (msg.sub_type === 'group') {
|
||||||
|
peer.chatType = ChatType.temp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
peer.chatType = ChatType.group
|
||||||
|
peer.peerUid = msg.group_id.toString()
|
||||||
|
}
|
||||||
|
if (reply) {
|
||||||
|
let group: Group = null
|
||||||
|
let replyMessage: OB11MessageData[] = [
|
||||||
|
{
|
||||||
|
type: OB11MessageDataType.reply,
|
||||||
|
data: {
|
||||||
|
id: msg.message_id.toString(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
if (msg.message_type == 'group') {
|
||||||
|
group = await getGroup(msg.group_id.toString())
|
||||||
|
if ((quickAction as QuickOperationGroupMessage).at_sender) {
|
||||||
|
replyMessage.push({
|
||||||
|
type: 'at',
|
||||||
|
data: {
|
||||||
|
qq: msg.user_id.toString(),
|
||||||
|
},
|
||||||
|
} as OB11MessageAt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
replyMessage = replyMessage.concat(convertMessage2List(reply, quickAction.auto_escape))
|
||||||
|
const { sendElements, deleteAfterSentFiles } = await createSendElements(replyMessage, group)
|
||||||
|
log(`发送消息给`, peer, sendElements)
|
||||||
|
sendMsg(peer, sendElements, deleteAfterSentFiles, false).then().catch(log)
|
||||||
|
}
|
||||||
|
if (msg.message_type === 'group') {
|
||||||
|
const groupMsgQuickAction = quickAction as QuickOperationGroupMessage
|
||||||
|
// handle group msg
|
||||||
|
if (groupMsgQuickAction.delete) {
|
||||||
|
NTQQMsgApi.recallMsg(peer, [rawMessage.msgId]).then().catch(log)
|
||||||
|
}
|
||||||
|
if (groupMsgQuickAction.kick) {
|
||||||
|
NTQQGroupApi.kickMember(peer.peerUid, [rawMessage.senderUid]).then().catch(log)
|
||||||
|
}
|
||||||
|
if (groupMsgQuickAction.ban) {
|
||||||
|
NTQQGroupApi.banMember(peer.peerUid, [
|
||||||
|
{
|
||||||
|
uid: rawMessage.senderUid,
|
||||||
|
timeStamp: groupMsgQuickAction.ban_duration || 60 * 30,
|
||||||
|
},
|
||||||
|
]).then().catch(log)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleFriendRequest(request: OB11FriendRequestEvent,
|
||||||
|
quickAction: QuickOperationFriendRequest) {
|
||||||
|
if (!isNull(quickAction.approve)) {
|
||||||
|
// todo: set remark
|
||||||
|
NTQQFriendApi.handleFriendRequest(request.flag, quickAction.approve).then().catch(log)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function handleGroupRequest(request: OB11GroupRequestEvent,
|
||||||
|
quickAction: QuickOperationGroupRequest) {
|
||||||
|
if (!isNull(quickAction.approve)) {
|
||||||
|
NTQQGroupApi.handleGroupRequest(
|
||||||
|
request.flag,
|
||||||
|
quickAction.approve ? GroupRequestOperateTypes.approve : GroupRequestOperateTypes.reject,
|
||||||
|
quickAction.reason,
|
||||||
|
).then().catch(log)
|
||||||
|
}
|
||||||
|
}
|
@@ -21,6 +21,7 @@ export enum ActionName {
|
|||||||
SetConfig = 'set_config',
|
SetConfig = 'set_config',
|
||||||
Debug = 'llonebot_debug',
|
Debug = 'llonebot_debug',
|
||||||
GetFile = 'get_file',
|
GetFile = 'get_file',
|
||||||
|
GetFriendsWithCategory = 'get_friends_with_category',
|
||||||
// onebot 11
|
// onebot 11
|
||||||
SendLike = 'send_like',
|
SendLike = 'send_like',
|
||||||
GetLoginInfo = 'get_login_info',
|
GetLoginInfo = 'get_login_info',
|
||||||
@@ -67,5 +68,6 @@ export enum ActionName {
|
|||||||
GoCQHTTP_GetGroupMsgHistory = 'get_group_msg_history',
|
GoCQHTTP_GetGroupMsgHistory = 'get_group_msg_history',
|
||||||
GoCQHTTP_GetForwardMsg = 'get_forward_msg',
|
GoCQHTTP_GetForwardMsg = 'get_forward_msg',
|
||||||
GoCQHTTP_GetEssenceMsg = "get_essence_msg_list",
|
GoCQHTTP_GetEssenceMsg = "get_essence_msg_list",
|
||||||
|
GoCQHTTP_HandleQuickOperation = ".handle_quick_operation",
|
||||||
GetGroupHonorInfo = "get_group_honor_info",
|
GetGroupHonorInfo = "get_group_honor_info",
|
||||||
}
|
}
|
||||||
|
@@ -1,16 +1,16 @@
|
|||||||
import { OB11User } from '../../types'
|
import { OB11User } from '../../types'
|
||||||
import { OB11Constructor } from '../../constructor'
|
import { OB11Constructor } from '../../constructor'
|
||||||
import { friends } from '../../../common/data'
|
import { friends, rawFriends } from '@/common/data'
|
||||||
import BaseAction from '../BaseAction'
|
import BaseAction from '../BaseAction'
|
||||||
import { ActionName } from '../types'
|
import { ActionName } from '../types'
|
||||||
import { NTQQFriendApi } from '../../../ntqqapi/api'
|
import { NTQQFriendApi } from '@/ntqqapi/api'
|
||||||
import { log } from '../../../common/utils'
|
import { CategoryFriend } from '@/ntqqapi/types'
|
||||||
|
|
||||||
interface Payload {
|
interface Payload {
|
||||||
no_cache: boolean | string
|
no_cache: boolean | string
|
||||||
}
|
}
|
||||||
|
|
||||||
class GetFriendList extends BaseAction<Payload, OB11User[]> {
|
export class GetFriendList extends BaseAction<Payload, OB11User[]> {
|
||||||
actionName = ActionName.GetFriendList
|
actionName = ActionName.GetFriendList
|
||||||
|
|
||||||
protected async _handle(payload: Payload) {
|
protected async _handle(payload: Payload) {
|
||||||
@@ -26,4 +26,11 @@ class GetFriendList extends BaseAction<Payload, OB11User[]> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default GetFriendList
|
|
||||||
|
export class GetFriendWithCategory extends BaseAction<void, Array<CategoryFriend>> {
|
||||||
|
actionName = ActionName.GetFriendsWithCategory;
|
||||||
|
|
||||||
|
protected async _handle(payload: void) {
|
||||||
|
return rawFriends;
|
||||||
|
}
|
||||||
|
}
|
@@ -55,6 +55,7 @@ export class OB11Constructor {
|
|||||||
let config = getConfigUtil().getConfig()
|
let config = getConfigUtil().getConfig()
|
||||||
const {
|
const {
|
||||||
enableLocalFile2Url,
|
enableLocalFile2Url,
|
||||||
|
debug,
|
||||||
ob11: { messagePostFormat },
|
ob11: { messagePostFormat },
|
||||||
} = config
|
} = config
|
||||||
const message_type = msg.chatType == ChatType.group ? 'group' : 'private'
|
const message_type = msg.chatType == ChatType.group ? 'group' : 'private'
|
||||||
@@ -78,8 +79,11 @@ export class OB11Constructor {
|
|||||||
message_format: messagePostFormat === 'string' ? 'string' : 'array',
|
message_format: messagePostFormat === 'string' ? 'string' : 'array',
|
||||||
post_type: selfInfo.uin == msg.senderUin ? EventType.MESSAGE_SENT : EventType.MESSAGE,
|
post_type: selfInfo.uin == msg.senderUin ? EventType.MESSAGE_SENT : EventType.MESSAGE,
|
||||||
}
|
}
|
||||||
|
if (debug) {
|
||||||
|
resMsg.raw = msg
|
||||||
|
}
|
||||||
if (msg.chatType == ChatType.group) {
|
if (msg.chatType == ChatType.group) {
|
||||||
resMsg.sub_type = 'normal' // 这里go-cqhttp是group,而onebot11标准是normal, 蛋疼
|
resMsg.sub_type = 'normal'
|
||||||
resMsg.group_id = parseInt(msg.peerUin)
|
resMsg.group_id = parseInt(msg.peerUin)
|
||||||
const member = await getGroupMember(msg.peerUin, msg.senderUin)
|
const member = await getGroupMember(msg.peerUin, msg.senderUin)
|
||||||
if (member) {
|
if (member) {
|
||||||
@@ -155,21 +159,22 @@ export class OB11Constructor {
|
|||||||
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
|
||||||
let fileName = element.picElement.fileName;
|
let fileName = element.picElement.fileName
|
||||||
const sourcePath = element.picElement.sourcePath;
|
const sourcePath = element.picElement.sourcePath
|
||||||
if (element.picElement.picType === PicType.gif && !fileName.endsWith('.gif')){
|
if (element.picElement.picType === PicType.gif && !fileName.endsWith('.gif')) {
|
||||||
fileName += ".gif";
|
fileName += '.gif'
|
||||||
}
|
}
|
||||||
message_data['data']['file'] = fileName
|
message_data['data']['file'] = fileName
|
||||||
// message_data["data"]["path"] = element.picElement.sourcePath
|
// message_data["data"]["path"] = element.picElement.sourcePath
|
||||||
// let currentRKey = "CAQSKAB6JWENi5LMk0kc62l8Pm3Jn1dsLZHyRLAnNmHGoZ3y_gDZPqZt-64"
|
// let currentRKey = "CAQSKAB6JWENi5LMk0kc62l8Pm3Jn1dsLZHyRLAnNmHGoZ3y_gDZPqZt-64"
|
||||||
|
|
||||||
message_data['data']['url'] = await NTQQFileApi.getImageUrl(element.picElement, msg.chatType);
|
message_data['data']['url'] = await NTQQFileApi.getImageUrl(element.picElement, msg.chatType)
|
||||||
// message_data["data"]["file_id"] = element.picElement.fileUuid
|
// message_data["data"]["file_id"] = element.picElement.fileUuid
|
||||||
message_data['data']['file_size'] = element.picElement.fileSize
|
message_data['data']['file_size'] = element.picElement.fileSize
|
||||||
dbUtil
|
dbUtil
|
||||||
.addFileCache(fileName, {
|
.addFileCache(fileName, {
|
||||||
fileName,
|
fileName,
|
||||||
|
elementId: element.elementId,
|
||||||
filePath: sourcePath,
|
filePath: sourcePath,
|
||||||
fileSize: element.picElement.fileSize.toString(),
|
fileSize: element.picElement.fileSize.toString(),
|
||||||
url: message_data['data']['url'],
|
url: message_data['data']['url'],
|
||||||
@@ -198,6 +203,7 @@ export class OB11Constructor {
|
|||||||
dbUtil
|
dbUtil
|
||||||
.addFileCache(videoOrFileElement.fileUuid, {
|
.addFileCache(videoOrFileElement.fileUuid, {
|
||||||
msgId: msg.msgId,
|
msgId: msg.msgId,
|
||||||
|
elementId: element.elementId,
|
||||||
fileName: videoOrFileElement.fileName,
|
fileName: videoOrFileElement.fileName,
|
||||||
filePath: videoOrFileElement.filePath,
|
filePath: videoOrFileElement.filePath,
|
||||||
fileSize: videoOrFileElement.fileSize,
|
fileSize: videoOrFileElement.fileSize,
|
||||||
@@ -225,6 +231,7 @@ export class OB11Constructor {
|
|||||||
message_data['data']['file_size'] = element.pttElement.fileSize
|
message_data['data']['file_size'] = element.pttElement.fileSize
|
||||||
dbUtil
|
dbUtil
|
||||||
.addFileCache(element.pttElement.fileName, {
|
.addFileCache(element.pttElement.fileName, {
|
||||||
|
elementId: element.elementId,
|
||||||
fileName: element.pttElement.fileName,
|
fileName: element.pttElement.fileName,
|
||||||
filePath: element.pttElement.filePath,
|
filePath: element.pttElement.filePath,
|
||||||
fileSize: element.pttElement.fileSize,
|
fileSize: element.pttElement.fileSize,
|
||||||
|
@@ -3,7 +3,7 @@ import { OB11Response } from '../action/OB11Response'
|
|||||||
import { HttpServerBase } from '@/common/server/http'
|
import { HttpServerBase } from '@/common/server/http'
|
||||||
import { actionHandlers, actionMap } from '../action'
|
import { actionHandlers, actionMap } from '../action'
|
||||||
import { getConfigUtil } from '@/common/config'
|
import { getConfigUtil } from '@/common/config'
|
||||||
import { postOB11Event } from './postOB11Event'
|
import { postOb11Event } from './post-ob11-event'
|
||||||
import { OB11HeartbeatEvent } from '../event/meta/OB11HeartbeatEvent'
|
import { OB11HeartbeatEvent } from '../event/meta/OB11HeartbeatEvent'
|
||||||
import { selfInfo } from '@/common/data'
|
import { selfInfo } from '@/common/data'
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ class HTTPHeart {
|
|||||||
}
|
}
|
||||||
this.intervalId = setInterval(() => {
|
this.intervalId = setInterval(() => {
|
||||||
// ws的心跳是ws自己维护的
|
// ws的心跳是ws自己维护的
|
||||||
postOB11Event(new OB11HeartbeatEvent(selfInfo.online, true, heartInterval), false, false)
|
postOb11Event(new OB11HeartbeatEvent(selfInfo.online, true, heartInterval), false, false)
|
||||||
}, heartInterval)
|
}, heartInterval)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
81
src/onebot11/server/post-ob11-event.ts
Normal file
81
src/onebot11/server/post-ob11-event.ts
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
import { OB11Message } from '../types'
|
||||||
|
import { selfInfo } from '@/common/data'
|
||||||
|
import { OB11BaseMetaEvent } from '../event/meta/OB11BaseMetaEvent'
|
||||||
|
import { OB11BaseNoticeEvent } from '../event/notice/OB11BaseNoticeEvent'
|
||||||
|
import { WebSocket as WebSocketClass } from 'ws'
|
||||||
|
import { wsReply } from './ws/reply'
|
||||||
|
import { log } from '@/common/utils'
|
||||||
|
import { getConfigUtil } from '@/common/config'
|
||||||
|
import crypto from 'crypto'
|
||||||
|
import { handleQuickOperation, QuickOperationEvent } from '../action/quick-operation'
|
||||||
|
|
||||||
|
export type PostEventType = OB11Message | OB11BaseMetaEvent | OB11BaseNoticeEvent
|
||||||
|
|
||||||
|
const eventWSList: WebSocketClass[] = []
|
||||||
|
|
||||||
|
export function registerWsEventSender(ws: WebSocketClass) {
|
||||||
|
eventWSList.push(ws)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function unregisterWsEventSender(ws: WebSocketClass) {
|
||||||
|
let index = eventWSList.indexOf(ws)
|
||||||
|
if (index !== -1) {
|
||||||
|
eventWSList.splice(index, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function postWsEvent(event: PostEventType) {
|
||||||
|
for (const ws of eventWSList) {
|
||||||
|
new Promise(() => {
|
||||||
|
wsReply(ws, event)
|
||||||
|
}).then().catch(log)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function postOb11Event(msg: PostEventType, reportSelf = false, postWs = true) {
|
||||||
|
const config = getConfigUtil().getConfig()
|
||||||
|
// 判断msg是否是event
|
||||||
|
if (!config.reportSelfMessage && !reportSelf) {
|
||||||
|
if (msg.post_type === 'message' && (msg as OB11Message).user_id.toString() == selfInfo.uin) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (config.ob11.enableHttpPost) {
|
||||||
|
const msgStr = JSON.stringify(msg)
|
||||||
|
const hmac = crypto.createHmac('sha1', config.ob11.httpSecret)
|
||||||
|
hmac.update(msgStr)
|
||||||
|
const sig = hmac.digest('hex')
|
||||||
|
let headers = {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'x-self-id': selfInfo.uin,
|
||||||
|
}
|
||||||
|
if (config.ob11.httpSecret) {
|
||||||
|
headers['x-signature'] = 'sha1=' + sig
|
||||||
|
}
|
||||||
|
for (const host of config.ob11.httpHosts) {
|
||||||
|
fetch(host, {
|
||||||
|
method: 'POST',
|
||||||
|
headers,
|
||||||
|
body: msgStr,
|
||||||
|
}).then(
|
||||||
|
async (res) => {
|
||||||
|
log(`新消息事件HTTP上报成功: ${host} `, msgStr)
|
||||||
|
try {
|
||||||
|
const resJson = await res.json()
|
||||||
|
log(`新消息事件HTTP上报返回快速操作: `, JSON.stringify(resJson))
|
||||||
|
handleQuickOperation(msg as QuickOperationEvent, resJson).then().catch(log);
|
||||||
|
} catch (e) {
|
||||||
|
log(`新消息事件HTTP上报没有返回快速操作,不需要处理`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(err: any) => {
|
||||||
|
log(`新消息事件HTTP上报失败: ${host} `, err, msg)
|
||||||
|
},
|
||||||
|
).catch(log)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (postWs) {
|
||||||
|
postWsEvent(msg)
|
||||||
|
}
|
||||||
|
}
|
@@ -1,185 +0,0 @@
|
|||||||
import { OB11Message, OB11MessageAt, OB11MessageData } from '../types'
|
|
||||||
import { getFriend, getGroup, getUidByUin, selfInfo } from '../../common/data'
|
|
||||||
import { OB11BaseMetaEvent } from '../event/meta/OB11BaseMetaEvent'
|
|
||||||
import { OB11BaseNoticeEvent } from '../event/notice/OB11BaseNoticeEvent'
|
|
||||||
import { WebSocket as WebSocketClass } from 'ws'
|
|
||||||
import { wsReply } from './ws/reply'
|
|
||||||
import { log } from '../../common/utils/log'
|
|
||||||
import { getConfigUtil } from '../../common/config'
|
|
||||||
import crypto from 'crypto'
|
|
||||||
import { NTQQFriendApi, NTQQGroupApi, NTQQMsgApi, Peer } from '../../ntqqapi/api'
|
|
||||||
import { ChatType, Group, GroupRequestOperateTypes } from '../../ntqqapi/types'
|
|
||||||
import { convertMessage2List, createSendElements, sendMsg } from '../action/msg/SendMsg'
|
|
||||||
import { dbUtil } from '../../common/db'
|
|
||||||
import { OB11FriendRequestEvent } from '../event/request/OB11FriendRequest'
|
|
||||||
import { OB11GroupRequestEvent } from '../event/request/OB11GroupRequest'
|
|
||||||
import { isNull } from '../../common/utils'
|
|
||||||
|
|
||||||
export type PostEventType = OB11Message | OB11BaseMetaEvent | OB11BaseNoticeEvent
|
|
||||||
|
|
||||||
interface QuickActionPrivateMessage {
|
|
||||||
reply?: string
|
|
||||||
auto_escape?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
interface QuickActionGroupMessage extends QuickActionPrivateMessage {
|
|
||||||
// 回复群消息
|
|
||||||
at_sender?: boolean
|
|
||||||
delete?: boolean
|
|
||||||
kick?: boolean
|
|
||||||
ban?: boolean
|
|
||||||
ban_duration?: number
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
interface QuickActionFriendRequest {
|
|
||||||
approve?: boolean
|
|
||||||
remark?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
interface QuickActionGroupRequest {
|
|
||||||
approve?: boolean
|
|
||||||
reason?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
type QuickAction = QuickActionPrivateMessage &
|
|
||||||
QuickActionGroupMessage &
|
|
||||||
QuickActionFriendRequest &
|
|
||||||
QuickActionGroupRequest
|
|
||||||
|
|
||||||
const eventWSList: WebSocketClass[] = []
|
|
||||||
|
|
||||||
export function registerWsEventSender(ws: WebSocketClass) {
|
|
||||||
eventWSList.push(ws)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function unregisterWsEventSender(ws: WebSocketClass) {
|
|
||||||
let index = eventWSList.indexOf(ws)
|
|
||||||
if (index !== -1) {
|
|
||||||
eventWSList.splice(index, 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function postWsEvent(event: PostEventType) {
|
|
||||||
for (const ws of eventWSList) {
|
|
||||||
new Promise(() => {
|
|
||||||
wsReply(ws, event)
|
|
||||||
}).then()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function postOB11Event(msg: PostEventType, reportSelf = false, postWs = true) {
|
|
||||||
const config = getConfigUtil().getConfig()
|
|
||||||
// 判断msg是否是event
|
|
||||||
if (!config.reportSelfMessage && !reportSelf) {
|
|
||||||
if (msg.post_type === 'message' && (msg as OB11Message).user_id.toString() == selfInfo.uin) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (config.ob11.enableHttpPost) {
|
|
||||||
const msgStr = JSON.stringify(msg)
|
|
||||||
const hmac = crypto.createHmac('sha1', config.ob11.httpSecret)
|
|
||||||
hmac.update(msgStr)
|
|
||||||
const sig = hmac.digest('hex')
|
|
||||||
let headers = {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'x-self-id': selfInfo.uin,
|
|
||||||
}
|
|
||||||
if (config.ob11.httpSecret) {
|
|
||||||
headers['x-signature'] = 'sha1=' + sig
|
|
||||||
}
|
|
||||||
for (const host of config.ob11.httpHosts) {
|
|
||||||
fetch(host, {
|
|
||||||
method: 'POST',
|
|
||||||
headers,
|
|
||||||
body: msgStr,
|
|
||||||
}).then(
|
|
||||||
async (res) => {
|
|
||||||
log(`新消息事件HTTP上报成功: ${host} `, msgStr)
|
|
||||||
// todo: 处理不够优雅,应该使用高级泛型进行QuickAction类型识别
|
|
||||||
let resJson: QuickAction
|
|
||||||
try {
|
|
||||||
resJson = await res.json()
|
|
||||||
log(`新消息事件HTTP上报返回快速操作: `, JSON.stringify(resJson))
|
|
||||||
} catch (e) {
|
|
||||||
log(`新消息事件HTTP上报没有返回快速操作,不需要处理`)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (msg.post_type === 'message') {
|
|
||||||
msg = msg as OB11Message
|
|
||||||
const rawMessage = await dbUtil.getMsgByShortId(msg.message_id)
|
|
||||||
resJson = resJson as QuickActionPrivateMessage | QuickActionGroupMessage
|
|
||||||
const reply = resJson.reply
|
|
||||||
let peer: Peer = {
|
|
||||||
chatType: ChatType.friend,
|
|
||||||
peerUid: msg.user_id.toString(),
|
|
||||||
}
|
|
||||||
if (msg.message_type == 'private') {
|
|
||||||
peer.peerUid = getUidByUin(msg.user_id.toString())
|
|
||||||
if (msg.sub_type === 'group') {
|
|
||||||
peer.chatType = ChatType.temp
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
peer.chatType = ChatType.group
|
|
||||||
peer.peerUid = msg.group_id.toString()
|
|
||||||
}
|
|
||||||
if (reply) {
|
|
||||||
let group: Group = null
|
|
||||||
let replyMessage: OB11MessageData[] = []
|
|
||||||
|
|
||||||
if (msg.message_type == 'group') {
|
|
||||||
group = await getGroup(msg.group_id.toString())
|
|
||||||
if ((resJson as QuickActionGroupMessage).at_sender) {
|
|
||||||
replyMessage.push({
|
|
||||||
type: 'at',
|
|
||||||
data: {
|
|
||||||
qq: msg.user_id.toString(),
|
|
||||||
},
|
|
||||||
} as OB11MessageAt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
replyMessage = replyMessage.concat(convertMessage2List(reply, resJson.auto_escape))
|
|
||||||
const { sendElements, deleteAfterSentFiles } = await createSendElements(replyMessage, group)
|
|
||||||
log(`发送消息给`, peer, sendElements)
|
|
||||||
sendMsg(peer, sendElements, deleteAfterSentFiles, false).then()
|
|
||||||
} else if (resJson.delete) {
|
|
||||||
NTQQMsgApi.recallMsg(peer, [rawMessage.msgId]).then()
|
|
||||||
} else if (resJson.kick) {
|
|
||||||
NTQQGroupApi.kickMember(peer.peerUid, [rawMessage.senderUid]).then()
|
|
||||||
} else if (resJson.ban) {
|
|
||||||
NTQQGroupApi.banMember(peer.peerUid, [
|
|
||||||
{
|
|
||||||
uid: rawMessage.senderUid,
|
|
||||||
timeStamp: resJson.ban_duration || 60 * 30,
|
|
||||||
},
|
|
||||||
]).then()
|
|
||||||
}
|
|
||||||
} else if (msg.post_type === 'request') {
|
|
||||||
if ((msg as OB11FriendRequestEvent).request_type === 'friend') {
|
|
||||||
resJson = resJson as QuickActionFriendRequest
|
|
||||||
if (!isNull(resJson.approve)) {
|
|
||||||
// todo: set remark
|
|
||||||
NTQQFriendApi.handleFriendRequest((msg as OB11FriendRequestEvent).flag, resJson.approve).then()
|
|
||||||
}
|
|
||||||
} else if ((msg as OB11GroupRequestEvent).request_type === 'group') {
|
|
||||||
resJson = resJson as QuickActionGroupRequest
|
|
||||||
if (!isNull(resJson.approve)) {
|
|
||||||
NTQQGroupApi.handleGroupRequest(
|
|
||||||
(msg as OB11FriendRequestEvent).flag,
|
|
||||||
resJson.approve ? GroupRequestOperateTypes.approve : GroupRequestOperateTypes.reject,
|
|
||||||
resJson.reason,
|
|
||||||
).then()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(err: any) => {
|
|
||||||
log(`新消息事件HTTP上报失败: ${host} `, err, msg)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (postWs) {
|
|
||||||
postWsEvent(msg)
|
|
||||||
}
|
|
||||||
}
|
|
@@ -4,7 +4,7 @@ import { ActionName } from '../../action/types'
|
|||||||
import { OB11Response } from '../../action/OB11Response'
|
import { OB11Response } from '../../action/OB11Response'
|
||||||
import BaseAction from '../../action/BaseAction'
|
import BaseAction from '../../action/BaseAction'
|
||||||
import { actionMap } from '../../action'
|
import { actionMap } from '../../action'
|
||||||
import { postWsEvent, registerWsEventSender, unregisterWsEventSender } from '../postOB11Event'
|
import { postWsEvent, registerWsEventSender, unregisterWsEventSender } from '../post-ob11-event'
|
||||||
import { wsReply } from './reply'
|
import { wsReply } from './reply'
|
||||||
import { WebSocket as WebSocketClass } from 'ws'
|
import { WebSocket as WebSocketClass } from 'ws'
|
||||||
import { OB11HeartbeatEvent } from '../../event/meta/OB11HeartbeatEvent'
|
import { OB11HeartbeatEvent } from '../../event/meta/OB11HeartbeatEvent'
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { WebSocket } from 'ws'
|
import { WebSocket } from 'ws'
|
||||||
import { actionMap } from '../../action'
|
import { actionMap } from '../../action'
|
||||||
import { OB11Response } from '../../action/OB11Response'
|
import { OB11Response } from '../../action/OB11Response'
|
||||||
import { postWsEvent, registerWsEventSender, unregisterWsEventSender } from '../postOB11Event'
|
import { postWsEvent, registerWsEventSender, unregisterWsEventSender } from '../post-ob11-event'
|
||||||
import { ActionName } from '../../action/types'
|
import { ActionName } from '../../action/types'
|
||||||
import BaseAction from '../../action/BaseAction'
|
import BaseAction from '../../action/BaseAction'
|
||||||
import { LifeCycleSubType, OB11LifeCycleEvent } from '../../event/meta/OB11LifeCycleEvent'
|
import { LifeCycleSubType, OB11LifeCycleEvent } from '../../event/meta/OB11LifeCycleEvent'
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { WebSocket as WebSocketClass } from 'ws'
|
import { WebSocket as WebSocketClass } from 'ws'
|
||||||
import { OB11Response } from '../../action/OB11Response'
|
import { OB11Response } from '../../action/OB11Response'
|
||||||
import { PostEventType } from '../postOB11Event'
|
import { PostEventType } from '../post-ob11-event'
|
||||||
import { log } from '../../../common/utils/log'
|
import { log } from '../../../common/utils/log'
|
||||||
import { isNull } from '../../../common/utils/helper'
|
import { isNull } from '../../../common/utils/helper'
|
||||||
|
|
||||||
|
@@ -1 +1 @@
|
|||||||
export const version = '3.24.4'
|
export const version = '3.26.1'
|
||||||
|
Reference in New Issue
Block a user