Compare commits

...

4 Commits

Author SHA1 Message Date
linyuchen
ac417cedd3 fix: reply msg id 2024-03-07 10:43:17 +08:00
linyuchen
ade509f26d perf: 优化数据库缓存 2024-03-07 09:00:22 +08:00
linyuchen
a66c1a9779 Merge remote-tracking branch 'origin/main' 2024-03-06 23:33:35 +08:00
linyuchen
239cf18887 fix: init db failed 2024-03-06 23:33:19 +08:00
9 changed files with 118 additions and 64 deletions

View File

@@ -1,10 +1,10 @@
{
"manifest_version": 4,
"type": "extension",
"name": "LLOneBot v3.13.1",
"name": "LLOneBot v3.13.2",
"slug": "LLOneBot",
"description": "LiteLoaderQQNT的OneBotApi",
"version": "3.13.1",
"version": "3.13.2",
"thumbnail": "./icon.png",
"authors": [
{

View File

@@ -4,6 +4,8 @@ import {mergeNewProperties} from "./utils";
export const HOOK_LOG = false;
export const ALLOW_SEND_TEMP_MSG = false;
export class ConfigUtil {
private readonly configPath: string;
private config: Config | null = null;

View File

@@ -11,6 +11,7 @@ import {
import {type FileCache, type LLOneBotError} from './types'
import {dbUtil} from "./db";
import {raw} from "express";
import {log} from "./utils";
export const selfInfo: SelfInfo = {
uid: '',
@@ -30,28 +31,33 @@ export const llonebotError: LLOneBotError = {
export const fileCache = new Map<string, FileCache>()
export async function getHistoryMsgByShortId(shortId: number) {
// log("getHistoryMsgByShortId", shortId, Object.values(msgHistory).map(m=>m.msgShortId))
return await dbUtil.getMsgByShortId(shortId);
}
export async function getFriend(qq: string): Promise<Friend | undefined> {
let friend = friends.find(friend => friend.uin === qq)
if (!friend){
friends = (await NTQQApi.getFriends(true))
friend = friends.find(friend => friend.uin === qq)
export async function getFriend(qq: string, uid: string = ""): Promise<Friend | undefined> {
let filterKey = uid ? "uid" : "uin"
let filterValue = uid ? uid : qq
let friend = friends.find(friend => friend[filterKey] === filterValue.toString())
if (!friend) {
try {
friends = (await NTQQApi.getFriends(true))
friend = friends.find(friend => friend[filterKey] === filterValue.toString())
} catch (e) {
// log("刷新好友列表失败", e.stack.toString())
}
}
return friend
}
export async function getGroup(qq: string): Promise<Group | undefined> {
let group = groups.find(group => group.groupCode === qq)
if (!group){
const _groups = await NTQQApi.getGroups(true);
group = _groups.find(group => group.groupCode === qq)
if (group){
groups.push(group)
let group = groups.find(group => group.groupCode === qq.toString())
if (!group) {
try {
const _groups = await NTQQApi.getGroups(true);
group = _groups.find(group => group.groupCode === qq.toString())
if (group) {
groups.push(group)
}
} catch (e) {
}
}
return group
}
@@ -63,18 +69,20 @@ export async function getGroupMember(groupQQ: string | number, memberQQ: string
}
const group = await getGroup(groupQQ)
if (group) {
let filterFunc: (member: GroupMember) => boolean
if (memberQQ) {
filterFunc = member => member.uin === memberQQ
} else if (memberUid) {
filterFunc = member => member.uid === memberUid
}
const filterKey = memberQQ ? "uin" : "uid"
const filterValue = memberQQ ? memberQQ : memberUid
let filterFunc: (member: GroupMember) => boolean = member => member[filterKey] === filterValue
let member = group.members?.find(filterFunc)
if (!member) {
const _members = await NTQQApi.getGroupMembers(groupQQ)
if (_members.length > 0) {
group.members = _members
try {
const _members = await NTQQApi.getGroupMembers(groupQQ)
if (_members.length > 0) {
group.members = _members
}
} catch (e) {
// log("刷新群成员列表失败", e.stack.toString())
}
member = group.members?.find(filterFunc)
}
return member

View File

@@ -11,6 +11,7 @@ class DBUtil {
private readonly DB_KEY_PREFIX_MSG_SEQ_ID = "msg_seq_id_";
private db: Level;
private cache: Record<string, RawMessage> = {} // <msg_id_ | msg_short_id_ | msg_seq_id_><id>: RawMessage
private currentShortId: number;
/*
* 数据库结构
@@ -24,9 +25,9 @@ class DBUtil {
new Promise((resolve, reject) => {
const initDB = () => {
initCount++;
if (initCount > 50) {
return reject("init db fail")
}
// if (initCount > 50) {
// return reject("init db fail")
// }
try {
if (!selfInfo.uin) {
@@ -38,7 +39,7 @@ class DBUtil {
console.log("llonebot init db success")
resolve(null)
} catch (e) {
// console.log("init db fail", e.stack.toString())
console.log("init db fail", e.stack.toString())
setTimeout(initDB, 300);
}
}
@@ -110,10 +111,10 @@ class DBUtil {
const seqIdKey = this.DB_KEY_PREFIX_MSG_SEQ_ID + msg.msgSeq;
msg.msgShortId = shortMsgId;
try {
await this.db.put(shortIdKey, msg.msgId);
await this.db.put(longIdKey, JSON.stringify(msg));
await this.db.put(seqIdKey, msg.msgId);
this.db.put(shortIdKey, msg.msgId).then();
this.db.put(longIdKey, JSON.stringify(msg)).then();
this.db.put(seqIdKey, msg.msgId).then();
log(`消息入库 ${seqIdKey}: ${msg.msgId}, ${shortMsgId}: ${msg.msgId}`);
} catch (e) {
log("addMsg db error", e.stack.toString());
}
@@ -133,20 +134,27 @@ class DBUtil {
}
Object.assign(existMsg, msg)
await this.db.put(longIdKey, JSON.stringify(existMsg));
this.db.put(longIdKey, JSON.stringify(existMsg)).then();
const shortIdKey = this.DB_KEY_PREFIX_MSG_SHORT_ID + existMsg.msgShortId;
const seqIdKey = this.DB_KEY_PREFIX_MSG_SEQ_ID + msg.msgSeq;
this.db.put(shortIdKey, msg.msgId).then();
this.db.put(seqIdKey, msg.msgId).then();
}
private async genMsgShortId(): Promise<number> {
let shortId = -2147483640
const key = "msg_current_short_id";
try {
let id: string = await this.db.get(key);
shortId = parseInt(id);
} catch (e) {
if (this.currentShortId === undefined){
try {
let id: string = await this.db.get(key);
this.currentShortId = parseInt(id);
} catch (e) {
this.currentShortId = -2147483640
}
}
shortId++;
await this.db.put(key, shortId.toString());
return shortId;
this.currentShortId++;
await this.db.put(key, this.currentShortId.toString());
return this.currentShortId;
}
}

View File

@@ -13,7 +13,7 @@ import {
import {ob11WebsocketServer} from "../onebot11/server/ws/WebsocketServer";
import {checkFfmpeg, DATA_DIR, getConfigUtil, log} from "../common/utils";
import {
friendRequests,
friendRequests, getFriend,
getGroup,
getGroupMember,
groupNotifies,
@@ -305,7 +305,10 @@ function onLoad() {
log("收到邀请我加群通知")
let groupInviteEvent = new OB11GroupRequestEvent();
groupInviteEvent.group_id = parseInt(notify.group.groupCode);
let user_id = (await NTQQApi.getUserDetailInfo(notify.user2.uid))?.uin
let user_id = (await getFriend("", notify.user2.uid))?.uin
if (!user_id){
user_id = (await NTQQApi.getUserDetailInfo(notify.user2.uid))?.uin
}
groupInviteEvent.user_id = parseInt(user_id);
groupInviteEvent.sub_type = "invite";
groupInviteEvent.flag = notify.seq;

View File

@@ -17,7 +17,7 @@ import {
type User
} from './types'
import * as fs from 'node:fs'
import {friendRequests, groupNotifies, selfInfo} from '../common/data'
import {friendRequests, groupNotifies, selfInfo, uidMaps} from '../common/data'
import {v4 as uuidv4} from 'uuid'
import path from 'path'
import {dbUtil} from "../common/db";
@@ -292,7 +292,7 @@ export class NTQQApi {
const members: GroupMember[] = Array.from(values)
for (const member of members) {
// uidMaps[member.uid] = member.uin;
uidMaps[member.uid] = member.uin;
}
// log(uidMaps);
// log("members info", values);
@@ -469,7 +469,7 @@ export class NTQQApi {
await sleep(500)
return await checkSendComplete()
}
log("开始发送消息", peer, msgElements)
callNTQQApi({
methodName: NTQQApiMethod.SEND_MSG,
args: [{

View File

@@ -1,5 +1,5 @@
import {AtType, ChatType, Group, RawMessage, SendArkElement, SendMessageElement} from "../../ntqqapi/types";
import {friends, getGroup, getGroupMember, getUidByUin, selfInfo,} from "../../common/data";
import {friends, getFriend, getGroup, getGroupMember, getUidByUin, selfInfo,} from "../../common/data";
import {
OB11MessageCustomMusic,
OB11MessageData,
@@ -17,6 +17,7 @@ import * as fs from "node:fs";
import {log} from "../../common/utils";
import {decodeCQCode} from "../cqcode";
import {dbUtil} from "../../common/db";
import {ALLOW_SEND_TEMP_MSG} from "../../common/config";
function checkSendMessage(sendMsgList: OB11MessageData[]) {
function checkUri(uri: string): boolean {
@@ -69,6 +70,22 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
message: "转发消息不能和普通消息混在一起发送,转发需要保证message只有type为node的元素"
}
}
if (payload.group_id && !(await getGroup(payload.group_id))) {
return {
valid: false,
message: `${payload.group_id}不存在`
}
}
if (payload.user_id && payload.message_type !== "group") {
if (!(await getFriend(payload.user_id))) {
if (!ALLOW_SEND_TEMP_MSG) {
return {
valid: false,
message: `不能发送临时消息`
}
}
}
}
return {
valid: true,
}
@@ -79,17 +96,16 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
chatType: ChatType.friend,
peerUid: ""
}
let isTempMsg = false;
let group: Group | undefined = undefined;
if (payload?.group_id) {
const genGroupPeer = async () => {
group = await getGroup(payload.group_id.toString())
if (!group) {
throw (`${payload.group_id}不存在`)
}
peer.chatType = ChatType.group
// peer.name = group.name
peer.peerUid = group.groupCode
} else if (payload?.user_id) {
}
const genFriendPeer = () => {
const friend = friends.find(f => f.uin == payload.user_id.toString())
if (friend) {
// peer.name = friend.nickName
@@ -101,9 +117,20 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
throw (`找不到私聊对象${payload.user_id}`)
}
// peer.name = tempUser.nickName
isTempMsg = true;
peer.peerUid = tempUserUid;
}
}
if (payload?.group_id && payload.message_type === "group") {
await genGroupPeer()
} else if (payload?.user_id) {
genFriendPeer()
} else if (payload.group_id) {
await genGroupPeer()
} else {
throw ("发送消息参数错误, 请指定group_id或user_id")
}
const messages = this.convertMessage2List(payload.message);
if (this.getSpecialMsgNum(payload, OB11MessageDataType.node)) {
try {
@@ -130,7 +157,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
// log("send msg:", peer, sendElements)
const {sendElements, deleteAfterSentFiles} = await this.createSendElements(messages, group)
try {
const returnMsg = await this.send(peer, sendElements, deleteAfterSentFiles)
const returnMsg = await this.send(peer, sendElements, deleteAfterSentFiles, isTempMsg)
return {message_id: returnMsg.msgShortId}
} catch (e) {
log("发送消息失败", e.stack.toString())
@@ -278,7 +305,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
case OB11MessageDataType.reply: {
let replyMsgId = sendMsg.data.id;
if (replyMsgId) {
const replyMsg = await dbUtil.getMsgByShortId(parseInt(replyMsgId))
const replyMsg = await dbUtil.getMsgBySeqId(replyMsgId)
if (replyMsg) {
sendElements.push(SendMsgElementConstructor.reply(replyMsg.msgSeq, replyMsg.msgId, replyMsg.senderUin, replyMsg.senderUin))
}

View File

@@ -96,12 +96,18 @@ export class OB11Constructor {
message_data["data"]["text"] = text
} else if (element.replyElement) {
message_data["type"] = "reply"
const replyMsg = await dbUtil.getMsgBySeqId(element.replyElement.replayMsgSeq)
if (replyMsg) {
message_data["data"]["id"] = replyMsg.msgShortId.toString()
} else {
continue
log("收到回复消息", element.replyElement.replayMsgSeq)
try{
const replyMsg = await dbUtil.getMsgBySeqId(element.replyElement.replayMsgSeq)
if (replyMsg) {
message_data["data"]["id"] = replyMsg.msgShortId.toString()
} else {
continue
}
}catch (e) {
log("获取不到引用的消息", e.stack)
}
} else if (element.picElement) {
message_data["type"] = "image"
// message_data["data"]["file"] = element.picElement.sourcePath

View File

@@ -1 +1 @@
export const version = "3.13.2"
export const version = "3.13.3"