style: lint

This commit is contained in:
手瓜一十雪
2024-07-22 14:12:03 +08:00
parent 72d2d3f224
commit cf9f785193
17 changed files with 482 additions and 485 deletions

View File

@@ -66,7 +66,6 @@
"log4js": "^6.9.1",
"qrcode-terminal": "^0.12.0",
"silk-wasm": "^3.6.1",
"sqlite3": "^5.1.7",
"uuid": "^10.0.0",
"ws": "^8.16.0"
}

View File

@@ -1,477 +1,477 @@
import { ElementType, FileElement, PicElement, PttElement, RawMessage, VideoElement } from '../../core/src/entities';
// import { ElementType, FileElement, PicElement, PttElement, RawMessage, VideoElement } from '../../core/src/entities';
import sqlite3 from 'sqlite3';
import { log, logDebug, logError } from '@/common/utils/log';
import { NTQQMsgApi } from '@/core';
import LRU from '@/common/utils/LRUCache';
// import sqlite3 from 'sqlite3';
// import { log, logDebug, logError } from '@/common/utils/log';
// import { NTQQMsgApi } from '@/core';
// import LRU from '@/common/utils/LRUCache';
export interface IRember {
last_sent_time: number;
join_time: number;
user_id: number;
}
// export interface IRember {
// last_sent_time: number;
// join_time: number;
// user_id: number;
// }
type DBMsg = {
id: number,
shortId: number,
longId: string,
seq: number,
peerUid: string,
chatType: number,
}
// type DBMsg = {
// id: number,
// shortId: number,
// longId: string,
// seq: number,
// peerUid: string,
// chatType: number,
// }
type DBFile = {
name: string; // 文件名
path: string;
url: string;
size: number;
uuid: string;
msgId: string;
elementId: string;
element: PicElement | VideoElement | FileElement | PttElement;
elementType: ElementType.PIC | ElementType.VIDEO | ElementType.FILE | ElementType.PTT;
}
// type DBFile = {
// name: string; // 文件名
// path: string;
// url: string;
// size: number;
// uuid: string;
// msgId: string;
// elementId: string;
// element: PicElement | VideoElement | FileElement | PttElement;
// elementType: ElementType.PIC | ElementType.VIDEO | ElementType.FILE | ElementType.PTT;
// }
class DBUtilBase {
protected db: sqlite3.Database | undefined;
// class DBUtilBase {
// protected db: sqlite3.Database | undefined;
async init(dbPath: string) {
if (this.db) {
return;
}
return new Promise<void>((resolve, reject) => {
this.db = new sqlite3.Database(dbPath, sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE, (err) => {
if (err) {
logError('Could not connect to database', err);
reject(err);
return;
}
this.createTable();
resolve();
});
});
}
// async init(dbPath: string) {
// if (this.db) {
// return;
// }
// return new Promise<void>((resolve, reject) => {
// this.db = new sqlite3.Database(dbPath, sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE, (err) => {
// if (err) {
// logError('Could not connect to database', err);
// reject(err);
// return;
// }
// this.createTable();
// resolve();
// });
// });
// }
protected createTable() {
throw new Error('Method not implemented.');
}
// protected createTable() {
// throw new Error('Method not implemented.');
// }
close() {
this.db?.close();
}
}
// close() {
// this.db?.close();
// }
// }
class DBUtil extends DBUtilBase {
private msgCache: Map<string | number, RawMessage> = new Map<string | number, RawMessage>();
private globalMsgShortId = -2147483640;
private groupIds: number[] = [];
private LURCache = new LRU<number>();
private LastSentCache = new (class {
private cache: { gid: number; uid: number }[] = [];
private maxSize: number;
// class DBUtil extends DBUtilBase {
// private msgCache: Map<string | number, RawMessage> = new Map<string | number, RawMessage>();
// private globalMsgShortId = -2147483640;
// private groupIds: number[] = [];
// private LURCache = new LRU<number>();
// private LastSentCache = new (class {
// private cache: { gid: number; uid: number }[] = [];
// private maxSize: number;
constructor(maxSize: number = 50000) {
this.maxSize = maxSize;
}
// constructor(maxSize: number = 50000) {
// this.maxSize = maxSize;
// }
get(gid: number, uid: number): boolean {
const exists = this.cache.some(
(entry) => entry.gid === gid && entry.uid === uid
);
if (!exists) {
this.cache.push({ gid, uid });
if (this.cache.length > this.maxSize) {
this.cache.shift();
}
}
// get(gid: number, uid: number): boolean {
// const exists = this.cache.some(
// (entry) => entry.gid === gid && entry.uid === uid
// );
// if (!exists) {
// this.cache.push({ gid, uid });
// if (this.cache.length > this.maxSize) {
// this.cache.shift();
// }
// }
return exists;
}
})();
// return exists;
// }
// })();
constructor() {
super();
const interval = 1000 * 60 * 10; // 10分钟清理一次缓存
setInterval(() => {
logDebug('清理消息缓存');
this.msgCache.forEach((msg, key) => {
if ((Date.now() - parseInt(msg.msgTime) * 1000) > interval) {
this.msgCache.delete(key);
}
});
}, interval);
}
// constructor() {
// super();
// const interval = 1000 * 60 * 10; // 10分钟清理一次缓存
// setInterval(() => {
// logDebug('清理消息缓存');
// this.msgCache.forEach((msg, key) => {
// if ((Date.now() - parseInt(msg.msgTime) * 1000) > interval) {
// this.msgCache.delete(key);
// }
// });
// }, interval);
// }
async init(dbPath: string) {
await super.init(dbPath);
this.globalMsgShortId = await this.getCurrentMaxShortId();
// async init(dbPath: string) {
// await super.init(dbPath);
// this.globalMsgShortId = await this.getCurrentMaxShortId();
// 初始化群缓存列表
this.db!.serialize(() => {
const sql = 'SELECT * FROM sqlite_master WHERE type=\'table\'';
this.db!.all(sql, [], (err, rows: { name: string }[]) => {
if (err) return logError(err);
rows.forEach((row) => this.groupIds.push(parseInt(row.name)));
//logDebug(`已加载 ${groupIds.length} 个群`);
});
});
// // 初始化群缓存列表
// this.db!.serialize(() => {
// const sql = 'SELECT * FROM sqlite_master WHERE type=\'table\'';
// this.db!.all(sql, [], (err, rows: { name: string }[]) => {
// if (err) return logError(err);
// rows.forEach((row) => this.groupIds.push(parseInt(row.name)));
// //logDebug(`已加载 ${groupIds.length} 个群`);
// });
// });
this.LURCache.on(async (nodeObject) => {
// this.LURCache.on(async (nodeObject) => {
Object.entries(nodeObject).forEach(async ([_groupId, datas]) => {
const userIds = datas.map(v => v.userId);
const groupId = Number(_groupId);
logDebug('插入发言时间', _groupId);
// Object.entries(nodeObject).forEach(async ([_groupId, datas]) => {
// const userIds = datas.map(v => v.userId);
// const groupId = Number(_groupId);
// logDebug('插入发言时间', _groupId);
await this.createGroupInfoTimeTableIfNotExist(groupId);
// await this.createGroupInfoTimeTableIfNotExist(groupId);
const needCreatUsers = await this.getNeedCreatList(groupId, userIds);
const updateList = needCreatUsers.length > 0 ? datas.filter(user => !needCreatUsers.includes(user.userId)) : datas;
const insertList = needCreatUsers.map(userId => datas.find(e => userId == e.userId)!);
// const needCreatUsers = await this.getNeedCreatList(groupId, userIds);
// const updateList = needCreatUsers.length > 0 ? datas.filter(user => !needCreatUsers.includes(user.userId)) : datas;
// const insertList = needCreatUsers.map(userId => datas.find(e => userId == e.userId)!);
logDebug('updateList', updateList);
logDebug('insertList', insertList);
// logDebug('updateList', updateList);
// logDebug('insertList', insertList);
if (insertList.length) {
const insertSql = `INSERT INTO "${groupId}" (last_sent_time, user_id) VALUES ${insertList.map(() => '(?, ?)').join(', ')};`;
// if (insertList.length) {
// const insertSql = `INSERT INTO "${groupId}" (last_sent_time, user_id) VALUES ${insertList.map(() => '(?, ?)').join(', ')};`;
this.db!.all(insertSql, insertList.map(v => [v.value, v.userId]).flat(), err => {
if (err) {
logError(`${groupId} 插入失败`);
logError(`更新Sql : ${insertSql}`);
}
});
}
// this.db!.all(insertSql, insertList.map(v => [v.value, v.userId]).flat(), err => {
// if (err) {
// logError(`群 ${groupId} 插入失败`);
// logError(`更新Sql : ${insertSql}`);
// }
// });
// }
if (updateList.length) {
const updateSql =
`UPDATE "${groupId}" SET last_sent_time = CASE ` +
updateList.map(v => `WHEN user_id = ${v.userId} THEN ${v.value}`).join(' ') +
' ELSE last_sent_time END WHERE user_id IN ' +
`(${updateList.map(v => v.userId).join(', ')});`;
// if (updateList.length) {
// const updateSql =
// `UPDATE "${groupId}" SET last_sent_time = CASE ` +
// updateList.map(v => `WHEN user_id = ${v.userId} THEN ${v.value}`).join(' ') +
// ' ELSE last_sent_time END WHERE user_id IN ' +
// `(${updateList.map(v => v.userId).join(', ')});`;
this.db!.all(updateSql, [], err => {
if (err) {
logError(`${groupId} 跟新失败`);
logError(`更新Sql : ${updateSql}`);
}
});
}
// this.db!.all(updateSql, [], err => {
// if (err) {
// logError(`群 ${groupId} 跟新失败`);
// logError(`更新Sql : ${updateSql}`);
// }
// });
// }
});
// });
});
}
async getNeedCreatList(groupId: number, userIds: number[]) {
// });
// }
// async getNeedCreatList(groupId: number, userIds: number[]) {
// 获取缓存中没有的
const unhas = userIds.filter(userId => !this.LastSentCache.get(groupId, userId));
// // 获取缓存中没有的
// const unhas = userIds.filter(userId => !this.LastSentCache.get(groupId, userId));
if (unhas.length == 0) {
logDebug('缓存全部命中');
return [];
}
// if (unhas.length == 0) {
// logDebug('缓存全部命中');
// return [];
// }
logDebug('缓存未全部命中');
// logDebug('缓存未全部命中');
const sql = `SELECT * FROM "${groupId}" WHERE user_id IN (${unhas.map(() => '?').join(',')})`;
// const sql = `SELECT * FROM "${groupId}" WHERE user_id IN (${unhas.map(() => '?').join(',')})`;
return new Promise<number[]>((resolve) => {
this.db!.all(sql, unhas, (err, rows: { user_id: number }[]) => {
const has = rows.map(v => v.user_id);
const needCreatUsers = unhas.filter(userId => !has.includes(userId));
// return new Promise<number[]>((resolve) => {
// this.db!.all(sql, unhas, (err, rows: { user_id: number }[]) => {
// const has = rows.map(v => v.user_id);
// const needCreatUsers = unhas.filter(userId => !has.includes(userId));
if (needCreatUsers.length == 0) {
logDebug('数据库全部命中');
} else {
logDebug('数据库未全部命中');
}
// if (needCreatUsers.length == 0) {
// logDebug('数据库全部命中');
// } else {
// logDebug('数据库未全部命中');
// }
resolve(needCreatUsers);
});
});
// resolve(needCreatUsers);
// });
// });
}
async createGroupInfoTimeTableIfNotExist(groupId: number) {
const createTableSQL = (groupId: number) =>
`CREATE TABLE IF NOT EXISTS "${groupId}" (
user_id INTEGER,
last_sent_time INTEGER,
join_time INTEGER,
PRIMARY KEY (user_id)
);`;
// }
// async createGroupInfoTimeTableIfNotExist(groupId: number) {
// const createTableSQL = (groupId: number) =>
// `CREATE TABLE IF NOT EXISTS "${groupId}" (
// user_id INTEGER,
// last_sent_time INTEGER,
// join_time INTEGER,
// PRIMARY KEY (user_id)
// );`;
if (this.groupIds.includes(groupId)) {
return;
}
return new Promise((resolve, reject) => {
const sql = createTableSQL(groupId);
this.db!.all(sql, (err) => {
if (err) {
reject(err);
return;
}
this.groupIds.push(groupId);
resolve(true);
});
});
}
protected createTable() {
// 消息记录
const createTableSQL = `
CREATE TABLE IF NOT EXISTS msgs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
shortId INTEGER NOT NULL UNIQUE,
longId TEXT NOT NULL UNIQUE,
seq INTEGER NOT NULL,
peerUid TEXT NOT NULL,
chatType INTEGER NOT NULL
)`;
this.db!.run(createTableSQL, function (err) {
if (err) {
logError('Could not create table msgs', err.stack);
}
});
// if (this.groupIds.includes(groupId)) {
// return;
// }
// return new Promise((resolve, reject) => {
// const sql = createTableSQL(groupId);
// this.db!.all(sql, (err) => {
// if (err) {
// reject(err);
// return;
// }
// this.groupIds.push(groupId);
// resolve(true);
// });
// });
// }
// protected createTable() {
// // 消息记录
// const createTableSQL = `
// CREATE TABLE IF NOT EXISTS msgs (
// id INTEGER PRIMARY KEY AUTOINCREMENT,
// shortId INTEGER NOT NULL UNIQUE,
// longId TEXT NOT NULL UNIQUE,
// seq INTEGER NOT NULL,
// peerUid TEXT NOT NULL,
// chatType INTEGER NOT NULL
// )`;
// this.db!.run(createTableSQL, function (err) {
// if (err) {
// logError('Could not create table msgs', err.stack);
// }
// });
// 文件缓存
const createFileTableSQL = `
CREATE TABLE IF NOT EXISTS files (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
path TEXT NOT NULL,
url TEXT,
size INTEGER NOT NULL,
uuid TEXT,
elementType INTEGER,
element TEXT NOT NULL,
elementId TEXT NOT NULL,
msgId TEXT NOT NULL
)`;
this.db!.run(createFileTableSQL, function (err) {
if (err) {
logError('Could not create table files', err);
}
});
}
// // 文件缓存
// const createFileTableSQL = `
// CREATE TABLE IF NOT EXISTS files (
// id INTEGER PRIMARY KEY AUTOINCREMENT,
// name TEXT NOT NULL,
// path TEXT NOT NULL,
// url TEXT,
// size INTEGER NOT NULL,
// uuid TEXT,
// elementType INTEGER,
// element TEXT NOT NULL,
// elementId TEXT NOT NULL,
// msgId TEXT NOT NULL
// )`;
// this.db!.run(createFileTableSQL, function (err) {
// if (err) {
// logError('Could not create table files', err);
// }
// });
// }
private async getCurrentMaxShortId() {
return new Promise<number>((resolve, reject) => {
this.db!.get('SELECT MAX(shortId) as maxId FROM msgs', (err, row: { maxId: number }) => {
if (err) {
logDebug('Could not get max short id, Use default -2147483640', err);
return resolve(-2147483640);
}
logDebug('数据库中消息最大短id', row?.maxId);
resolve(row?.maxId ?? -2147483640);
});
});
}
// private async getCurrentMaxShortId() {
// return new Promise<number>((resolve, reject) => {
// this.db!.get('SELECT MAX(shortId) as maxId FROM msgs', (err, row: { maxId: number }) => {
// if (err) {
// logDebug('Could not get max short id, Use default -2147483640', err);
// return resolve(-2147483640);
// }
// logDebug('数据库中消息最大短id', row?.maxId);
// resolve(row?.maxId ?? -2147483640);
// });
// });
// }
private async getMsg(query: string, params: any[]) {
const stmt = this.db!.prepare(query);
return new Promise<RawMessage | null>((resolve, reject) => {
stmt.get(...params, (err: any, row: DBMsg) => {
// log("getMsg", row, err);
if (err) {
logError('Could not get msg', err, query, params);
return resolve(null);
}
if (!row) {
// logDebug('不存在数据库中的消息,不进行处理', query, params);
resolve(null);
return;
}
const msgId = row.longId;
NTQQMsgApi.getMsgsByMsgId({ peerUid: row.peerUid, chatType: row.chatType }, [msgId]).then(res => {
const msg = res.msgList[0];
if (!msg) {
resolve(null);
return;
}
msg.id = row.shortId;
resolve(msg);
}).catch(e => {
resolve(null);
});
});
});
}
// private async getMsg(query: string, params: any[]) {
// const stmt = this.db!.prepare(query);
// return new Promise<RawMessage | null>((resolve, reject) => {
// stmt.get(...params, (err: any, row: DBMsg) => {
// // log("getMsg", row, err);
// if (err) {
// logError('Could not get msg', err, query, params);
// return resolve(null);
// }
// if (!row) {
// // logDebug('不存在数据库中的消息,不进行处理', query, params);
// resolve(null);
// return;
// }
// const msgId = row.longId;
// NTQQMsgApi.getMsgsByMsgId({ peerUid: row.peerUid, chatType: row.chatType }, [msgId]).then(res => {
// const msg = res.msgList[0];
// if (!msg) {
// resolve(null);
// return;
// }
// msg.id = row.shortId;
// resolve(msg);
// }).catch(e => {
// resolve(null);
// });
// });
// });
// }
async getMsgByShortId(shortId: number): Promise<RawMessage | null> {
if (this.msgCache.has(shortId)) {
return this.msgCache.get(shortId)!;
}
const getStmt = 'SELECT * FROM msgs WHERE shortId = ?';
return this.getMsg(getStmt, [shortId]);
}
// async getMsgByShortId(shortId: number): Promise<RawMessage | null> {
// if (this.msgCache.has(shortId)) {
// return this.msgCache.get(shortId)!;
// }
// const getStmt = 'SELECT * FROM msgs WHERE shortId = ?';
// return this.getMsg(getStmt, [shortId]);
// }
async getMsgByLongId(longId: string): Promise<RawMessage | null> {
if (this.msgCache.has(longId)) {
return this.msgCache.get(longId)!;
}
return this.getMsg('SELECT * FROM msgs WHERE longId = ?', [longId]);
}
// async getMsgByLongId(longId: string): Promise<RawMessage | null> {
// if (this.msgCache.has(longId)) {
// return this.msgCache.get(longId)!;
// }
// return this.getMsg('SELECT * FROM msgs WHERE longId = ?', [longId]);
// }
async getMsgBySeq(peerUid: string, seq: string): Promise<RawMessage | null> {
const stmt = 'SELECT * FROM msgs WHERE peerUid = ? AND seq = ?';
return this.getMsg(stmt, [peerUid, seq]);
}
// async getMsgBySeq(peerUid: string, seq: string): Promise<RawMessage | null> {
// const stmt = 'SELECT * FROM msgs WHERE peerUid = ? AND seq = ?';
// return this.getMsg(stmt, [peerUid, seq]);
// }
async addMsg(msg: RawMessage, update = true): Promise<number> {
const existMsg = await this.getMsgByLongId(msg.msgId);
if (existMsg) {
// logDebug('消息已存在,更新数据库', msg.msgId);
if (update) this.updateMsg(msg).then();
return existMsg.id!;
}
const stmt = this.db!.prepare('INSERT INTO msgs (shortId, longId, seq, peerUid, chatType) VALUES (?, ?, ?, ?, ?)');
// const runAsync = promisify(stmt.run.bind(stmt));
const shortId = ++this.globalMsgShortId;
msg.id = shortId;
//logDebug(`记录消息到数据库, 消息长id: ${msg.msgId}, 短id: ${msg.id}`);
this.msgCache.set(shortId, msg);
this.msgCache.set(msg.msgId, msg);
stmt.run(this.globalMsgShortId, msg.msgId, msg.msgSeq.toString(), msg.peerUid, msg.chatType, (err: any) => {
if (err) {
if (err.errno === 19) {
this.getMsgByLongId(msg.msgId).then((msg: RawMessage | null) => {
if (msg) {
this.msgCache.set(shortId, msg);
this.msgCache.set(msg.msgId, msg);
// logDebug('获取消息短id成功', msg.id);
} else {
logError('db could not get msg by long id', err);
}
}).catch(e => logError('db getMsgByLongId error', e));
} else {
logError('db could not add msg', err);
}
}
});
return shortId;
}
// async addMsg(msg: RawMessage, update = true): Promise<number> {
// const existMsg = await this.getMsgByLongId(msg.msgId);
// if (existMsg) {
// // logDebug('消息已存在,更新数据库', msg.msgId);
// if (update) this.updateMsg(msg).then();
// return existMsg.id!;
// }
// const stmt = this.db!.prepare('INSERT INTO msgs (shortId, longId, seq, peerUid, chatType) VALUES (?, ?, ?, ?, ?)');
// // const runAsync = promisify(stmt.run.bind(stmt));
// const shortId = ++this.globalMsgShortId;
// msg.id = shortId;
// //logDebug(`记录消息到数据库, 消息长id: ${msg.msgId}, 短id: ${msg.id}`);
// this.msgCache.set(shortId, msg);
// this.msgCache.set(msg.msgId, msg);
// stmt.run(this.globalMsgShortId, msg.msgId, msg.msgSeq.toString(), msg.peerUid, msg.chatType, (err: any) => {
// if (err) {
// if (err.errno === 19) {
// this.getMsgByLongId(msg.msgId).then((msg: RawMessage | null) => {
// if (msg) {
// this.msgCache.set(shortId, msg);
// this.msgCache.set(msg.msgId, msg);
// // logDebug('获取消息短id成功', msg.id);
// } else {
// logError('db could not get msg by long id', err);
// }
// }).catch(e => logError('db getMsgByLongId error', e));
// } else {
// logError('db could not add msg', err);
// }
// }
// });
// return shortId;
// }
async updateMsg(msg: RawMessage) {
const existMsg = this.msgCache.get(msg.msgId);
if (existMsg) {
Object.assign(existMsg, msg);
}
//logDebug(`更新消息, shortId:${msg.id}, seq: ${msg.msgSeq}, msgId: ${msg.msgId}`);
const stmt = this.db!.prepare('UPDATE msgs SET seq=? WHERE longId=?');
stmt.run(msg.msgSeq, msg.msgId, (err: any) => {
if (err) {
logError('updateMsg db error', err);
}
});
// async updateMsg(msg: RawMessage) {
// const existMsg = this.msgCache.get(msg.msgId);
// if (existMsg) {
// Object.assign(existMsg, msg);
// }
// //logDebug(`更新消息, shortId:${msg.id}, seq: ${msg.msgSeq}, msgId: ${msg.msgId}`);
// const stmt = this.db!.prepare('UPDATE msgs SET seq=? WHERE longId=?');
// stmt.run(msg.msgSeq, msg.msgId, (err: any) => {
// if (err) {
// logError('updateMsg db error', err);
// }
// });
}
// }
async addFileCache(file: DBFile) {
const stmt = this.db!.prepare('INSERT INTO files (name, path, url, size, uuid, elementType ,element, elementId, msgId) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)');
return new Promise((resolve, reject) => {
stmt.run(file.name, file.path, file.url, file.size, file.uuid,
file.elementType,
JSON.stringify(file.element),
file.elementId,
file.msgId,
function (err: any) {
if (err) {
logError('db could not add file', err);
reject(err);
}
resolve(null);
});
});
}
// async addFileCache(file: DBFile) {
// const stmt = this.db!.prepare('INSERT INTO files (name, path, url, size, uuid, elementType ,element, elementId, msgId) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)');
// return new Promise((resolve, reject) => {
// stmt.run(file.name, file.path, file.url, file.size, file.uuid,
// file.elementType,
// JSON.stringify(file.element),
// file.elementId,
// file.msgId,
// function (err: any) {
// if (err) {
// logError('db could not add file', err);
// reject(err);
// }
// resolve(null);
// });
// });
// }
private async getFileCache(query: string, params: any[]) {
const stmt = this.db!.prepare(query);
return new Promise<DBFile | null>((resolve, reject) => {
stmt.get(...params, (err: any, row: DBFile & { element: string }) => {
if (err) {
logError('db could not get file cache', err);
reject(err);
}
if (row) {
row.element = JSON.parse(row.element);
}
resolve(row);
});
});
}
// private async getFileCache(query: string, params: any[]) {
// const stmt = this.db!.prepare(query);
// return new Promise<DBFile | null>((resolve, reject) => {
// stmt.get(...params, (err: any, row: DBFile & { element: string }) => {
// if (err) {
// logError('db could not get file cache', err);
// reject(err);
// }
// if (row) {
// row.element = JSON.parse(row.element);
// }
// resolve(row);
// });
// });
// }
async getFileCacheByName(name: string): Promise<DBFile | null> {
return this.getFileCache('SELECT * FROM files WHERE name = ?', [name]);
}
// async getFileCacheByName(name: string): Promise<DBFile | null> {
// return this.getFileCache('SELECT * FROM files WHERE name = ?', [name]);
// }
async getFileCacheByUuid(uuid: string): Promise<DBFile | null> {
return this.getFileCache('SELECT * FROM files WHERE uuid = ?', [uuid]);
}
// async getFileCacheByUuid(uuid: string): Promise<DBFile | null> {
// return this.getFileCache('SELECT * FROM files WHERE uuid = ?', [uuid]);
// }
// todo: 是否所有的文件都有uuid语音消息有没有uuid
async updateFileCache(file: DBFile) {
const stmt = this.db!.prepare('UPDATE files SET path = ?, url = ? WHERE uuid = ?');
return new Promise((resolve, reject) => {
stmt.run(file.path, file.url, file.uuid, function (err: any) {
if (err) {
logError('db could not update file cache', err);
reject(err);
}
resolve(null);
});
});
}
// // todo: 是否所有的文件都有uuid语音消息有没有uuid
// async updateFileCache(file: DBFile) {
// const stmt = this.db!.prepare('UPDATE files SET path = ?, url = ? WHERE uuid = ?');
// return new Promise((resolve, reject) => {
// stmt.run(file.path, file.url, file.uuid, function (err: any) {
// if (err) {
// logError('db could not update file cache', err);
// reject(err);
// }
// resolve(null);
// });
// });
// }
async getLastSentTimeAndJoinTime(
groupId: number
): Promise<IRember[]> {
logDebug('读取发言时间', groupId);
return new Promise<IRember[]>((resolve, reject) => {
this.db!.all(`SELECT * FROM "${groupId}" `, (err, rows: IRember[]) => {
const cache = this.LURCache.get(groupId).map(e => ({ user_id: e.userId, last_sent_time: e.value }));
if (err) {
logError('查询发言时间失败', groupId);
return resolve(cache.map(e => ({ ...e, join_time: 0 })));
}
Object.assign(rows, cache);
logDebug('查询发言时间成功', groupId, rows);
resolve(rows);
});
});
}
// async getLastSentTimeAndJoinTime(
// groupId: number
// ): Promise<IRember[]> {
// logDebug('读取发言时间', groupId);
// return new Promise<IRember[]>((resolve, reject) => {
// this.db!.all(`SELECT * FROM "${groupId}" `, (err, rows: IRember[]) => {
// const cache = this.LURCache.get(groupId).map(e => ({ user_id: e.userId, last_sent_time: e.value }));
// if (err) {
// logError('查询发言时间失败', groupId);
// return resolve(cache.map(e => ({ ...e, join_time: 0 })));
// }
// Object.assign(rows, cache);
// logDebug('查询发言时间成功', groupId, rows);
// resolve(rows);
// });
// });
// }
insertLastSentTime(
groupId: number,
userId: number,
time: number
) {
this.LURCache.set(groupId, userId, time);
}
async insertJoinTime(
groupId: number,
userId: number,
time: number
) {
await this.createGroupInfoTimeTableIfNotExist(groupId);
this.db!.all(
`INSERT OR REPLACE INTO "${groupId}" (user_id, last_sent_time, join_time) VALUES (?,?,?)`,
[userId, time, time],
(err) => {
if (err)
logError(err),
Promise.reject(),
logError('插入入群时间失败', userId, groupId);
}
);
// insertLastSentTime(
// groupId: number,
// userId: number,
// time: number
// ) {
// this.LURCache.set(groupId, userId, time);
// }
// async insertJoinTime(
// groupId: number,
// userId: number,
// time: number
// ) {
// await this.createGroupInfoTimeTableIfNotExist(groupId);
// this.db!.all(
// `INSERT OR REPLACE INTO "${groupId}" (user_id, last_sent_time, join_time) VALUES (?,?,?)`,
// [userId, time, time],
// (err) => {
// if (err)
// logError(err),
// Promise.reject(),
// logError('插入入群时间失败', userId, groupId);
// }
// );
}
}
// }
// }
// export const dbUtil = new DBUtil();
// // export const dbUtil = new DBUtil();

View File

@@ -6,8 +6,8 @@ import { NTQQUserApi } from '@/core/apis';
export class GetProfileLike extends BaseAction<void, any> {
actionName = ActionName.GetProfileLike;
protected async _handle(payload: void) {
let ret = await NTQQUserApi.getProfileLike(selfInfo.uid);
let listdata: any[] = ret.info.userLikeInfos[0].favoriteInfo.userInfos;
const ret = await NTQQUserApi.getProfileLike(selfInfo.uid);
const listdata: any[] = ret.info.userLikeInfos[0].favoriteInfo.userInfos;
for (let i = 0; i < listdata.length; i++) {
listdata[i].uin = parseInt((await NTQQUserApi.getUinByUid(listdata[i].uid)) || '');
}

View File

@@ -28,8 +28,8 @@ export class GoCQHTTPGetForwardMsgAction extends BaseAction<Payload, any> {
if (!msgId) {
throw Error('message_id is required');
}
let rootMsgId = MessageUnique.getShortIdByMsgId(msgId);
let rootMsg = MessageUnique.getMsgIdAndPeerByShortId(rootMsgId || parseInt(msgId))
const rootMsgId = MessageUnique.getShortIdByMsgId(msgId);
const rootMsg = MessageUnique.getMsgIdAndPeerByShortId(rootMsgId || parseInt(msgId));
if (!rootMsg) {
throw Error('msg not found');
}
@@ -40,7 +40,7 @@ export class GoCQHTTPGetForwardMsgAction extends BaseAction<Payload, any> {
const msgList = data.msgList;
const messages = await Promise.all(msgList.map(async msg => {
const resMsg = await OB11Constructor.message(msg);
resMsg.message_id = await MessageUnique.createMsg({guildId:'',chatType:msg.chatType,peerUid:msg.peerUid},msg.msgId)!;
resMsg.message_id = await MessageUnique.createMsg({ guildId:'',chatType:msg.chatType,peerUid:msg.peerUid },msg.msgId)!;
return resMsg;
}));
messages.map(msg => {

View File

@@ -27,12 +27,12 @@ class GetMsg extends BaseAction<Payload, OB11Message> {
if (!payload.message_id) {
throw Error('参数message_id不能为空');
}
let MsgShortId = await MessageUnique.getShortIdByMsgId(payload.message_id.toString());
let msgIdWithPeer = await MessageUnique.getMsgIdAndPeerByShortId(MsgShortId || parseInt(payload.message_id.toString()));
const MsgShortId = await MessageUnique.getShortIdByMsgId(payload.message_id.toString());
const msgIdWithPeer = await MessageUnique.getMsgIdAndPeerByShortId(MsgShortId || parseInt(payload.message_id.toString()));
if (!msgIdWithPeer) {
throw ('消息不存在');
}
let msg = await NTQQMsgApi.getMsgsByMsgId(
const msg = await NTQQMsgApi.getMsgsByMsgId(
{ guildId: '', peerUid: msgIdWithPeer?.Peer.peerUid, chatType: msgIdWithPeer.Peer.chatType },
[msgIdWithPeer?.MsgId || payload.message_id.toString()]);
return await OB11Constructor.message(msg.msgList[0]);

View File

@@ -28,7 +28,7 @@ async function handleOb11FileLikeMessage(
{ data: { file, name: payloadFileName } }: OB11MessageFileBase,
{ deleteAfterSentFiles }: MessageContext
) {
let uri = file;
const uri = file;
// const cache = await dbUtil.getFileCacheByName(file);
// if (cache) {

View File

@@ -59,7 +59,7 @@ export async function handleForwardNode(destPeer: Peer, messageNodes: OB11Messag
} else {
if (nodeMsg!.Peer.peerUid !== selfInfo.uid) {
// need cloning
let rawClone = await NTQQMsgApi.getMsgsByMsgId(nodeMsg?.Peer!,[nodeMsg?.MsgId!]);
const rawClone = await NTQQMsgApi.getMsgsByMsgId(nodeMsg?.Peer!,[nodeMsg?.MsgId!]);
const clonedMsg = await cloneMsg(rawClone.msgList[0]);
if (clonedMsg) {
nodeMsgIds.push(clonedMsg.msgId);
@@ -114,7 +114,7 @@ export async function handleForwardNode(destPeer: Peer, messageNodes: OB11Messag
let needSendSelf = false;
for (const msgId of nodeMsgIds) {
const nodeMsgPeer = await MessageUnique.getPeerByMsgId(msgId);
let nodeMsg = (await NTQQMsgApi.getMsgsByMsgId(nodeMsgPeer?.Peer!, [msgId])).msgList[0];
const nodeMsg = (await NTQQMsgApi.getMsgsByMsgId(nodeMsgPeer?.Peer!, [msgId])).msgList[0];
if (nodeMsg) {
nodeMsgArray.push(nodeMsg);
if (!srcPeer) {

View File

@@ -26,7 +26,7 @@ export class SetMsgEmojiLike extends BaseAction<Payload, any> {
if (!payload.emoji_id){
throw new Error('emojiId not found');
}
let msgSeq = (await NTQQMsgApi.getMsgsByMsgId(msg.Peer, [msg.MsgId])).msgList[0].msgSeq;
const msgSeq = (await NTQQMsgApi.getMsgsByMsgId(msg.Peer, [msg.MsgId])).msgList[0].msgSeq;
return await NTQQMsgApi.setEmojiLike(msg.Peer, msgSeq, payload.emoji_id.toString(), true);
}
}

View File

@@ -94,9 +94,9 @@ export enum ActionName {
CreateCollection = 'create_collection',
GetCollectionList = 'get_collection_list',
SetLongNick = 'set_self_longnick',
SetEssenceMsg = "set_essence_msg",
DelEssenceMsg = "delete_essence_msg",
GetRecentContact = "get_recent_contact",
_MarkAllMsgAsRead = "_mark_all_as_read",
GetProfileLike = "get_profile_like"
SetEssenceMsg = 'set_essence_msg',
DelEssenceMsg = 'delete_essence_msg',
GetRecentContact = 'get_recent_contact',
_MarkAllMsgAsRead = '_mark_all_as_read',
GetProfileLike = 'get_profile_like'
}

View File

@@ -408,11 +408,11 @@ export class OB11Constructor {
const senderUin = emojiLikeData.gtip.qq.jp;
const msgSeq = emojiLikeData.gtip.url.msgseq;
const emojiId = emojiLikeData.gtip.face.id;
let replyMsgList = (await NTQQMsgApi.getMsgsBySeqAndCount({ chatType: ChatType.group, guildId: '', peerUid: msg.peerUid }, msgSeq, 1, true, true)).msgList;
const replyMsgList = (await NTQQMsgApi.getMsgsBySeqAndCount({ chatType: ChatType.group, guildId: '', peerUid: msg.peerUid }, msgSeq, 1, true, true)).msgList;
if (replyMsgList.length < 1) {
return;
}
let replyMsg = replyMsgList[0];
const replyMsg = replyMsgList[0];
return new OB11GroupMsgEmojiLikeEvent(parseInt(msg.peerUid), parseInt(senderUin), MessageUnique.getShortIdByMsgId(replyMsg?.msgId!)!, [{
emoji_id: emojiId,
count: 1
@@ -454,16 +454,16 @@ export class OB11Constructor {
}
}
if (grayTipElement.jsonGrayTipElement.busiId == 2401) {
let searchParams = new URL(json.items[0].jp).searchParams;
let msgSeq = searchParams.get('msgSeq')!;
let Group = searchParams.get('groupCode');
let Businessid = searchParams.get('businessid');
let Peer: Peer = {
const searchParams = new URL(json.items[0].jp).searchParams;
const msgSeq = searchParams.get('msgSeq')!;
const Group = searchParams.get('groupCode');
const Businessid = searchParams.get('businessid');
const Peer: Peer = {
guildId: '',
chatType: ChatType.group,
peerUid: Group!
};
let msgData = await NTQQMsgApi.getMsgsBySeqAndCount(Peer, msgSeq.toString(), 1, true, true);
const msgData = await NTQQMsgApi.getMsgsBySeqAndCount(Peer, msgSeq.toString(), 1, true, true);
return new OB11GroupEssenceEvent(parseInt(msg.peerUid), MessageUnique.getShortIdByMsgId(msgData.msgList[0].msgId)!, parseInt(msgData.msgList[0].senderUin));
// 获取MsgSeq+Peer可获取具体消息
}

View File

@@ -3,7 +3,7 @@ export class OB11GroupEssenceEvent extends OB11GroupNoticeEvent {
notice_type = 'essence';
message_id: number;
sender_id: number;
sub_type: 'add' | 'delete' = "add";
sub_type: 'add' | 'delete' = 'add';
constructor(groupId: number, message_id: number, sender_id: number) {
super();

View File

@@ -265,7 +265,7 @@ export class NapCatOnebot11 {
//console.log('ob11 onGroupNotifiesUpdated', notifies[0]);
if (![GroupNotifyTypes.ADMIN_SET, GroupNotifyTypes.ADMIN_UNSET, GroupNotifyTypes.ADMIN_UNSET_OTHER].includes(notifies[0].type)) {
this.postGroupNotifies(notifies).then().catch(e => logError('postGroupNotifies error: ', e));
};
}
};
groupListener.onMemberInfoChange = async (groupCode: string, changeType: number, members: Map<string, GroupMember>) => {
//console.log("ob11 onMemberInfoChange", groupCode, changeType, members)

View File

@@ -11,7 +11,6 @@ import { normalize, sendMsg } from '../action/msg/SendMsg';
import { OB11FriendRequestEvent } from '../event/request/OB11FriendRequest';
import { OB11GroupRequestEvent } from '../event/request/OB11GroupRequest';
import { isNull } from '@/common/utils/helper';
import { dbUtil } from '@/common/utils/db';
import { getGroup, selfInfo } from '@/core/data';
import { NTQQFriendApi, NTQQGroupApi, NTQQUserApi } from '@/core/apis';
import createSendElements from '../action/msg/SendMsg/create-send-elements';

View File

@@ -10,8 +10,7 @@ import fs from 'node:fs';
import babel from 'vite-plugin-babel';
import { version } from 'os';
// "@rollup/plugin-babel": "^6.0.4",
const external = ['silk-wasm', 'ws', 'express', 'uuid', 'fluent-ffmpeg', 'sqlite3', 'log4js',
'qrcode-terminal'];
const external = ['silk-wasm', 'ws', 'express', 'uuid', 'fluent-ffmpeg', 'log4js', 'qrcode-terminal'];
const nodeModules = [...builtinModules, builtinModules.map(m => `node:${m}`)].flat();
// let nodeModules = ["fs", "path", "events", "buffer", "url", "crypto", "fs/promise", "fsPromise", "os", "http", "net"]
@@ -28,9 +27,9 @@ if (process.env.NAPCAT_BUILDSYS == 'linux') {
} else if (process.env.NAPCAT_BUILDSYS == 'win32') {
if (process.env.NAPCAT_BUILDARCH == 'x64') {
}
startScripts = ['./script/napcat.ps1', './script/napcat.bat', './script/napcat-utf8.bat', './script/napcat-utf8.ps1', './script/napcat-log.ps1','./script/NapCat.164.bat','./script/napcat-9912.ps1','./script/napcat-9912-utf8.ps1','./script/napcat-9912.bat','./script/napcat-9912-utf8.bat'];
startScripts = ['./script/napcat.ps1', './script/napcat.bat', './script/napcat-utf8.bat', './script/napcat-utf8.ps1', './script/napcat-log.ps1', './script/NapCat.164.bat', './script/napcat-9912.ps1', './script/napcat-9912-utf8.ps1', './script/napcat-9912.bat', './script/napcat-9912-utf8.bat'];
} else {
startScripts = ['./script/napcat.sh', './script/napcat.ps1', './script/napcat.bat', './script/napcat-utf8.bat', './script/napcat-utf8.ps1', './script/napcat-log.ps1','./script/napcat-9912.ps1','./script/napcat-9912-utf8.ps1','./script/napcat-9912.bat','./script/napcat-9912-utf8.bat'];
startScripts = ['./script/napcat.sh', './script/napcat.ps1', './script/napcat.bat', './script/napcat-utf8.bat', './script/napcat-utf8.ps1', './script/napcat-log.ps1', './script/napcat-9912.ps1', './script/napcat-9912-utf8.ps1', './script/napcat-9912.bat', './script/napcat-9912-utf8.bat'];
}
const baseConfigPlugin: PluginOption[] = [