Merge branch 'main' into feat.rebuild

This commit is contained in:
Jerry 2025-06-16 13:20:42 +08:00
commit d821003899
3 changed files with 82 additions and 79 deletions

View File

@ -111,11 +111,11 @@ class BotController {
try { try {
const token = req.body.token; const token = req.body.token;
if (tools.checkToken(token.toString())) { if (tools.checkToken(token.toString())) {
const groupId: number = req.body.groupId; const groupId: number = Number(req.body.groupId);
const message: string = req.body.message; const message: string = req.body.message.toString();
const flag: boolean = await BotService.sendMessage(groupId, message); const flag: boolean = await BotService.sendMessage(groupId, message);
if (flag) { if (flag) {
await response.success(res, {}); await response.success(res, { message: '消息发送成功..' });
} else { } else {
await response.error(res); await response.error(res);
} }

View File

@ -21,26 +21,16 @@ class BotService {
if (!fileName.endsWith('.json')) continue; if (!fileName.endsWith('.json')) continue;
try { try {
const raw: [] | undefined = await redisService.fetch('crystelfBots', fileName); const raw = await redisService.fetch('crystelfBots', fileName);
if (!raw) continue; if (!raw || !Array.isArray(raw)) continue;
let botList: any[]; for (const bot of raw) {
try { const uin = Number(bot.uin);
botList = raw; const nickName = bot.nickName || '';
if (!Array.isArray(botList)) { if (!isNaN(uin)) {
logger.warn(`${fileName}不是数组,已跳过`); uins.push({ uin, nickName });
continue;
} }
} catch (e) {
logger.warn(`解析 ${fileName} 出错: ${e}`);
continue;
} }
botList.forEach((bot) => {
//logger.debug(bot);
if (bot.uin) {
uins.push({ uin: bot.uin, nickName: bot.nickName });
}
});
} catch (err) { } catch (err) {
logger.error(`读取或解析 ${fileName} 出错: ${err}`); logger.error(`读取或解析 ${fileName} 出错: ${err}`);
} }
@ -50,7 +40,7 @@ class BotService {
} }
/** /**
* *
* @param data * @param data
*/ */
public async getGroupInfo(data: { public async getGroupInfo(data: {
@ -59,30 +49,24 @@ class BotService {
clientId?: string; clientId?: string;
}): Promise<any> { }): Promise<any> {
logger.debug('GetGroupInfo..'); logger.debug('GetGroupInfo..');
const sendBot: number | undefined = data.botId const sendBot: number | undefined = data.botId ?? (await this.getGroupBot(data.groupId));
? data.botId
: await this.getGroupBot(data.groupId);
if (!sendBot) { if (!sendBot) {
logger.warn(`不存在能向群聊${data.groupId}发送消息的Bot!`); logger.warn(`不存在能向群聊${data.groupId}发送消息的Bot!`);
return undefined; return undefined;
} }
let sendData = {
const sendData = {
type: 'getGroupInfo', type: 'getGroupInfo',
data: { data: {
botId: sendBot, botId: sendBot,
groupId: data.groupId, groupId: data.groupId,
clientID: data.clientId ? data.clientId : await this.getBotClient(sendBot), clientID: data.clientId ?? (await this.getBotClient(sendBot)),
}, },
}; };
//logger.debug(sendData);
if (sendData.data.clientID) { if (sendData.data.clientID) {
const returnData = await wsClientManager.sendAndWait(sendData.data.clientID, sendData); const returnData = await wsClientManager.sendAndWait(sendData.data.clientID, sendData);
if (returnData) { return returnData ?? undefined;
return returnData;
} else {
logger.warn(`未查询到${data.groupId}的信息..`);
return undefined;
}
} }
return undefined; return undefined;
} }
@ -94,14 +78,14 @@ class BotService {
*/ */
public async sendMessage(groupId: number, message: string): Promise<boolean> { public async sendMessage(groupId: number, message: string): Promise<boolean> {
logger.info(`发送${message}${groupId}..`); logger.info(`发送${message}${groupId}..`);
const sendBot: number | undefined = await this.getGroupBot(groupId); const sendBot = await this.getGroupBot(groupId);
if (!sendBot) { if (!sendBot) {
logger.warn(`不存在能向群聊${groupId}发送消息的Bot!`); logger.warn(`不存在能向群聊${groupId}发送消息的Bot!`);
return false; return false;
} }
const client = await this.getBotClient(sendBot); const client = await this.getBotClient(sendBot);
if (!client) { if (!client) {
logger.warn(`不存${sendBot}对应的client!`); logger.warn(`不存${sendBot}对应的client!`);
return false; return false;
} }
const sendData = { const sendData = {
@ -113,11 +97,8 @@ class BotService {
message: message, message: message,
}, },
}; };
if (client) { await wsClientManager.send(client, sendData);
await wsClientManager.send(sendData.data.clientId, sendData); return true;
return true;
}
return false;
} }
/** /**
@ -137,49 +118,64 @@ class BotService {
const clientId = path.basename(fileName, '.json'); const clientId = path.basename(fileName, '.json');
const botList = await redisService.fetch('crystelfBots', fileName); const botList = await redisService.fetch('crystelfBots', fileName);
if (!Array.isArray(botList)) continue; if (!Array.isArray(botList)) continue;
for (const bot of botList) { for (const bot of botList) {
if (!bot.uin || !bot.groups) continue; const botId = Number(bot.uin);
for (const group of bot.groups) { const groups = bot.groups;
if (!groupMap.has(group.group_id)) {
groupMap.set(group.group_id, []); if (!botId || !Array.isArray(groups)) continue;
for (const group of groups) {
if (group.group_id === '未知') continue;
const groupId = Number(group.group_id);
if (isNaN(groupId)) continue;
if (!groupMap.has(groupId)) {
groupMap.set(groupId, []);
} }
groupMap.get(group.group_id)?.push({ botId: bot.uin, clientId }); groupMap.get(groupId)!.push({ botId, clientId });
} }
} }
} }
for (const [groupId, botEntries] of groupMap.entries()) { for (const [groupId, botEntries] of groupMap.entries()) {
logger.debug(`[群 ${groupId}] 候选Bot列表: ${JSON.stringify(botEntries)}`);
const clientGroups = new Map<string, number[]>(); const clientGroups = new Map<string, number[]>();
botEntries.forEach(({ botId, clientId }) => { botEntries.forEach(({ botId, clientId }) => {
if (!clientGroups.has(clientId)) clientGroups.set(clientId, []); if (!clientGroups.has(clientId)) clientGroups.set(clientId, []);
clientGroups.get(clientId)!.push(botId); clientGroups.get(clientId)!.push(botId);
}); });
const selectedClientId = tools.getRandomItem([...clientGroups.keys()]); const selectedClientId = tools.getRandomItem([...clientGroups.keys()]);
const botCandidates = clientGroups.get(selectedClientId)!; const botCandidates = clientGroups.get(selectedClientId)!;
const selectedBotId = tools.getRandomItem(botCandidates); const selectedBotId = tools.getRandomItem(botCandidates);
const delay = tools.getRandomDelay(30_000, 90_000); const delay = tools.getRandomDelay(10_000, 150_000);
setTimeout(() => {
const sendData = { ((groupId, selectedClientId, selectedBotId, delay) => {
type: 'sendMessage', setTimeout(() => {
data: { const sendData = {
botId: selectedBotId, type: 'sendMessage',
groupId, data: {
clientId: selectedClientId, botId: selectedBotId,
message, groupId: groupId,
}, clientId: selectedClientId,
}; message: message,
logger.info( },
`[广播] 向群 ${groupId} 使用Bot ${selectedBotId}(客户端 ${selectedClientId})发送消息,延迟 ${delay / 1000}` };
); logger.info(
wsClientManager.send(selectedClientId, sendData).catch((e) => { `[广播] 向群 ${groupId} 使用Bot ${selectedBotId}(客户端 ${selectedClientId})发送消息${message},延迟 ${delay / 1000}`
logger.error(`发送到群${groupId}失败:`, e); );
}); wsClientManager.send(selectedClientId, sendData).catch((e) => {
}, delay); logger.error(`发送到群${groupId}失败:`, e);
});
}, delay);
})(groupId, selectedClientId, selectedBotId, delay);
} }
} }
/** /**
* `botId``client` * botId对应的client
* @param botId * @param botId
* @private * @private
*/ */
@ -187,14 +183,20 @@ class BotService {
const userPath = paths.get('userData'); const userPath = paths.get('userData');
const botsPath = path.join(userPath, '/crystelfBots'); const botsPath = path.join(userPath, '/crystelfBots');
const dirData = await fs.readdir(botsPath); const dirData = await fs.readdir(botsPath);
for (const clientId of dirData) { for (const clientId of dirData) {
if (!clientId.endsWith('.json')) continue; if (!clientId.endsWith('.json')) continue;
try { try {
const raw: const raw = await redisService.fetch('crystelfBots', clientId);
| { uin: number; groups: { group_id: number; group_name: string }[]; nickName: string }[] if (!Array.isArray(raw)) continue;
| undefined = await redisService.fetch('crystelfBots', clientId);
if (!raw) continue; for (const bot of raw) {
if (raw.find((bot) => bot.uin == botId)) return path.basename(clientId, '.json'); const uin = Number(bot.uin);
if (!isNaN(uin) && uin === botId) {
return path.basename(clientId, '.json');
}
}
} catch (err) { } catch (err) {
logger.error(`读取${clientId}出错..`); logger.error(`读取${clientId}出错..`);
} }
@ -203,7 +205,7 @@ class BotService {
} }
/** /**
* `groupId``botId` * groupId对应的botId
* @param groupId * @param groupId
* @private * @private
*/ */
@ -216,15 +218,16 @@ class BotService {
if (!clientId.endsWith('.json')) continue; if (!clientId.endsWith('.json')) continue;
try { try {
const raw: const raw = await redisService.fetch('crystelfBots', clientId);
| { uin: number; groups: { group_id: number; group_name: string }[]; nickName: string }[] if (!Array.isArray(raw)) continue;
| undefined = await redisService.fetch('crystelfBots', clientId);
if (!raw) continue;
for (const bot of raw) { for (const bot of raw) {
if (bot.uin && bot.groups) { const uin = Number(bot.uin);
const found = bot.groups.find((group) => group.group_id == groupId); const groups = bot.groups;
if (found) return bot.uin; if (!uin || !Array.isArray(groups)) continue;
if (groups.find((g) => Number(g.group_id) === groupId)) {
return uin;
} }
} }
} catch (err) { } catch (err) {

View File

@ -50,8 +50,8 @@ async function testGetAPI() {
async function testPostAPI() { async function testPostAPI() {
try { try {
const response = await axios.post('https://core.crystelf.top/api/bot/getGroupInfo', { const response = await axios.post('https://core.crystelf.top/api/bot/getGroupInfo', {
token: '阿弥诺斯', token: '114113',
groupId: '1042721418', groupId: 796070855,
}); });
logger.info('[HTTP][POST] Response:', response.data); logger.info('[HTTP][POST] Response:', response.data);
} catch (err) { } catch (err) {