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

View File

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

View File

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

View File

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

View File

@@ -26,7 +26,7 @@ export class SetMsgEmojiLike extends BaseAction<Payload, any> {
if (!payload.emoji_id){ if (!payload.emoji_id){
throw new Error('emojiId not found'); 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); return await NTQQMsgApi.setEmojiLike(msg.Peer, msgSeq, payload.emoji_id.toString(), true);
} }
} }

View File

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

View File

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

View File

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

View File

@@ -265,7 +265,7 @@ export class NapCatOnebot11 {
//console.log('ob11 onGroupNotifiesUpdated', notifies[0]); //console.log('ob11 onGroupNotifiesUpdated', notifies[0]);
if (![GroupNotifyTypes.ADMIN_SET, GroupNotifyTypes.ADMIN_UNSET, GroupNotifyTypes.ADMIN_UNSET_OTHER].includes(notifies[0].type)) { 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)); this.postGroupNotifies(notifies).then().catch(e => logError('postGroupNotifies error: ', e));
}; }
}; };
groupListener.onMemberInfoChange = async (groupCode: string, changeType: number, members: Map<string, GroupMember>) => { groupListener.onMemberInfoChange = async (groupCode: string, changeType: number, members: Map<string, GroupMember>) => {
//console.log("ob11 onMemberInfoChange", groupCode, changeType, members) //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 { OB11FriendRequestEvent } from '../event/request/OB11FriendRequest';
import { OB11GroupRequestEvent } from '../event/request/OB11GroupRequest'; import { OB11GroupRequestEvent } from '../event/request/OB11GroupRequest';
import { isNull } from '@/common/utils/helper'; import { isNull } from '@/common/utils/helper';
import { dbUtil } from '@/common/utils/db';
import { getGroup, selfInfo } from '@/core/data'; import { getGroup, selfInfo } from '@/core/data';
import { NTQQFriendApi, NTQQGroupApi, NTQQUserApi } from '@/core/apis'; import { NTQQFriendApi, NTQQGroupApi, NTQQUserApi } from '@/core/apis';
import createSendElements from '../action/msg/SendMsg/create-send-elements'; 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 babel from 'vite-plugin-babel';
import { version } from 'os'; import { version } from 'os';
// "@rollup/plugin-babel": "^6.0.4", // "@rollup/plugin-babel": "^6.0.4",
const external = ['silk-wasm', 'ws', 'express', 'uuid', 'fluent-ffmpeg', 'sqlite3', 'log4js', const external = ['silk-wasm', 'ws', 'express', 'uuid', 'fluent-ffmpeg', 'log4js', 'qrcode-terminal'];
'qrcode-terminal'];
const nodeModules = [...builtinModules, builtinModules.map(m => `node:${m}`)].flat(); const nodeModules = [...builtinModules, builtinModules.map(m => `node:${m}`)].flat();
// let nodeModules = ["fs", "path", "events", "buffer", "url", "crypto", "fs/promise", "fsPromise", "os", "http", "net"] // 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') { } else if (process.env.NAPCAT_BUILDSYS == 'win32') {
if (process.env.NAPCAT_BUILDARCH == 'x64') { 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 { } 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[] = [ const baseConfigPlugin: PluginOption[] = [