diff --git a/apps/coreRestart.js b/apps/coreRestart.js index 23878b8..d4c0833 100644 --- a/apps/coreRestart.js +++ b/apps/coreRestart.js @@ -1,5 +1,6 @@ import systemControl from '../lib/core/systemControl.js'; import tools from '../components/tool.js'; +import configControl from '../lib/config/configControl.js'; export default class CoreRestart extends plugin { constructor() { @@ -17,18 +18,21 @@ export default class CoreRestart extends plugin { } async restart(e) { + if (!configControl.get('core')) { + return e.reply(`晶灵核心未启用..`, true); + } const returnData = await systemControl.systemRestart(); if (returnData?.data?.success) { - e.reply(`操作成功:${returnData?.data?.data}..`); + e.reply(`操作成功:${returnData?.data?.data}..`, true); } else { - e.reply(`操作失败:${returnData?.data?.data}..`); + e.reply(`操作失败:${returnData?.data?.data}..`, true); } await tools.sleep(8000); const restartTime = await systemControl.getRestartTime(); if (restartTime) { - e.reply(`晶灵核心重启成功!耗时${restartTime?.data?.data}秒..`); + e.reply(`晶灵核心重启成功!耗时${restartTime?.data?.data}秒..`, true); } else { - e.reply(`核心重启花的时间有点久了呢..${restartTime?.data?.data}`); + e.reply(`核心重启花的时间有点久了呢..${restartTime?.data?.data}`, true); } } } diff --git a/apps/fanqie.js b/apps/fanqie.js index 89363b6..2578c45 100644 --- a/apps/fanqie.js +++ b/apps/fanqie.js @@ -163,7 +163,8 @@ export class xzq extends plugin { if (!e.isMaster) { const allowGroup = e.isGroup ? await redis.get(`fqxzq:g:${e.group_id}`) : null; const allowUser = await redis.get(`fqxzq:u:${e.user_id}`); - if (!allowGroup && !allowUser) return false; + return e.reply(`暂未开放下载功能,请等待功能更新..`); + //if (!allowGroup && !allowUser) return false; } e.reply('开始下载,请稍等', true); diff --git a/apps/reportBots.js b/apps/reportBots.js index 686fdcb..ea88add 100644 --- a/apps/reportBots.js +++ b/apps/reportBots.js @@ -1,4 +1,5 @@ import botControl from '../lib/core/botControl.js'; +import configControl from '../lib/config/configControl.js'; export default class ReportBots extends plugin { constructor() { @@ -28,15 +29,20 @@ export default class ReportBots extends plugin { } async autoReport() { - await botControl.reportBots(); + if (configControl.get('core')) { + await botControl.reportBots(); + } } async manualReport(e) { + if (!configControl.get('core')) { + return e.reply(`晶灵核心未启用..`, true); + } let success = await botControl.reportBots(); if (success) { - e.reply('crystelf Bot信息已同步到核心..'); + e.reply('crystelf Bot信息已同步到核心..', true); } else { - e.reply('crystelf Bot同步失败:核心未连接..'); + e.reply('crystelf Bot同步失败:核心未连接..', true); } } diff --git a/apps/rssPush.js b/apps/rssPush.js index c4ece56..519e927 100644 --- a/apps/rssPush.js +++ b/apps/rssPush.js @@ -3,8 +3,7 @@ import rssTools from '../models/rss/rss.js'; import path from 'path'; import screenshot from '../lib/rss/screenshot.js'; import fs from 'fs'; - -const rssCache = new Map(); // TODO 解决重启后的数据恢复问题 +import rssCache from '../lib/rss/rssCache.js'; export default class RssPlugin extends plugin { constructor() { @@ -52,7 +51,8 @@ export default class RssPlugin extends plugin { } return e.reply(`该rss已存在并包含在该群聊..`, true); } - feeds.push({ url, targetGroup: [groupId], screenshot: true }); + + feeds.push({ url, targetGroups: [groupId], screenshot: true }); await configControl.set('feeds', feeds); return e.reply(`rss解析流设置成功..`); } @@ -81,22 +81,27 @@ export default class RssPlugin extends plugin { */ async pushFeeds(e) { const feeds = configControl.get('feeds') || []; + for (const feed of feeds) { const latest = await rssTools.fetchFeed(feed.url); - if (!latest || latest.length) continue; - const cacheKey = feed.url; - const lastId = rssCache.get(cacheKey); - const newItems = lastId ? latest.filter((i) => i.link !== lastId) : latest; - if (newItems.length) rssCache.set(cacheKey, newItems[0].link); - for (const groupId of feed.targetGroups) { - const post = newItems[0]; - const tempPath = path.join(process.cwd(), 'data', `rss-${Date.now()}.png`); - if (feed.screenshot) { - await screenshot.generateScreenshot(post, tempPath); - Bot.pickGroup(groupId)?.sendMsg([segment.image(tempPath)]); - fs.unlinkSync(tempPath); - } else { - Bot.pickGroup(groupId)?.sendMsg(`[RSS推送]\n${post.title}\n${post.link}`); + if (!latest || !latest.length) continue; + + const lastLink = await rssCache.get(feed.url); + const newItems = lastLink ? latest.filter((i) => i.link !== lastLink) : latest; + + if (newItems.length) { + await rssCache.set(feed.url, newItems[0].link); + + for (const groupId of feed.targetGroups) { + const post = newItems[0]; + const tempPath = path.join(process.cwd(), 'data', `rss-${Date.now()}.png`); + if (feed.screenshot) { + await screenshot.generateScreenshot(post, tempPath); + await Bot.pickGroup(groupId)?.sendMsg([segment.image(tempPath)]); + fs.unlinkSync(tempPath); + } else { + await Bot.pickGroup(groupId)?.sendMsg(`[RSS推送]\n${post.title}\n${post.link}`); + } } } } diff --git a/constants/path.js b/constants/path.js index 4e2ad4f..c355cf7 100644 --- a/constants/path.js +++ b/constants/path.js @@ -20,6 +20,7 @@ const Path = { yunzai: path.join(rootDir, '../../'), data: path.join(rootDir, '../../data/crystelf/data'), rssHTML: path.join(rootDir, 'constants/rss/rss_template.html'), + rssCache: path.join(rootDir, '../../data/crystelf'), }; const configFile = fs.readFileSync(Path.defaultConfig, 'utf8'); diff --git a/lib/rss/rssCache.js b/lib/rss/rssCache.js new file mode 100644 index 0000000..d5b045c --- /dev/null +++ b/lib/rss/rssCache.js @@ -0,0 +1,80 @@ +import crypto from 'crypto'; +import paths from '../../constants/path.js'; +import path from 'path'; +import fs from 'fs'; + +const redis = global.redis; +const cachePath = path.join(paths.rssCache, 'rss_cache.json'); + +const rssCache = { + /** + * url转hash + * @param url + * @returns {string} + */ + urlToKey(url) { + const hash = crypto.createHash('md5').update(url).digest('hex'); + return `rss_cache:${hash}`; + }, + + async init() { + await this.loadLocalToRedis(); + }, + + /** + * 从redis中获取数据 + * @param url + * @returns {Promise<*>} + */ + async get(url) { + const key = this.urlToKey(url); + return await redis.get(key); + }, + + /** + * 保存数据至redis和本地 + * @param url + * @param latestLink + * @returns {Promise} + */ + async set(url, latestLink) { + const key = this.urlToKey(url); + await redis.set(key, latestLink); + await this.saveToLocal(url, latestLink); + }, + + /** + * 保存至本地 + * @param url + * @param latestLink + * @returns {Promise} + */ + async saveToLocal(url, latestLink) { + let localData = {}; + try { + if (fs.existsSync(cachePath)) { + localData = JSON.parse(fs.readFileSync(cachePath, 'utf-8')); + } + } catch (err) { + logger.error(`本地rss缓存读取失败..`, err); + } + localData[url] = latestLink; + fs.writeFileSync(cachePath, JSON.stringify(localData, null, 2), 'utf-8'); + }, + + /** + * 从本地加载数据至redis + * @returns {Promise} + */ + async loadLocalToRedis() { + if (!fs.existsSync(cachePath)) return; + const data = JSON.parse(fs.readFileSync(cachePath, 'utf-8')); + for (const [url, link] of Object.entries(data)) { + const key = this.urlToKey(url); + await redis.set(key, link); + } + logger.info(`[RSS]本地缓存已加载至redis..`); + }, +}; + +export default rssCache; diff --git a/lib/system/init.js b/lib/system/init.js index 97296e2..85f811c 100644 --- a/lib/system/init.js +++ b/lib/system/init.js @@ -1,9 +1,11 @@ import configControl from '../config/configControl.js'; import wsClient from '../../models/ws/wsClient.js'; +import rssCache from '../rss/rssCache.js'; export const crystelfInit = { async CSH() { await configControl.init(); + await rssCache.init(); if (configControl.get('core')) { await wsClient.initialize(); }