@anyul/koishi-plugin-rss 5.3.4 → 5.3.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SubscriptionStore = void 0;
4
+ /**
5
+ * 订阅数据访问仓储(Repository)。
6
+ *
7
+ * 设计目的:`rssOwl` 是订阅核心表,原本被命令层(subscription-create /
8
+ * subscription-edit / subscription-management / web-monitor)的 15 处
9
+ * 直接 `ctx.database.*('rssOwl', ...)` 调用散落访问,违反「命令层只复用
10
+ * 核心函数」的分层约定。本类作为该表的唯一封装,命令层通过依赖注入拿到
11
+ * 实例,不再直接触碰 `ctx.database`,与 `NotificationQueueStore` /
12
+ * `MessageCacheManager` 的既有分层保持一致。
13
+ *
14
+ * 注意:feeder(`core/feeder.ts`)也在核心层直接读写 `rssOwl`,那是核心层
15
+ * 对自身数据的合法访问,不强制走本仓储;强制收口会破坏 feeder 作为纯函数
16
+ * 的可测试性(见 5.3.8 的 disposed 评估取舍)。
17
+ */
18
+ class SubscriptionStore {
19
+ ctx;
20
+ constructor(ctx) {
21
+ this.ctx = ctx;
22
+ }
23
+ /**
24
+ * 按群组查询订阅列表(命令层最常用的读取入口)。
25
+ */
26
+ async findByGuild(platform, guildId) {
27
+ return this.ctx.database.get('rssOwl', { platform, guildId });
28
+ }
29
+ /**
30
+ * 按 群组 + URL 查询(用于编辑推送目标时判断目标群是否已有同源订阅)。
31
+ */
32
+ async findByGuildAndUrl(platform, guildId, url) {
33
+ return this.ctx.database.get('rssOwl', { platform, guildId, url });
34
+ }
35
+ /**
36
+ * 创建一条订阅,返回含生成主键的完整行。
37
+ */
38
+ async create(data) {
39
+ return this.ctx.database.create('rssOwl', data);
40
+ }
41
+ /**
42
+ * 按主键更新任意字段。
43
+ */
44
+ async update(id, patch) {
45
+ await this.ctx.database.set('rssOwl', id, patch);
46
+ }
47
+ /**
48
+ * 按主键删除单条订阅。
49
+ */
50
+ async remove(id) {
51
+ await this.ctx.database.remove('rssOwl', { id });
52
+ }
53
+ /**
54
+ * 删除某个群组的全部订阅(rsso.remove --all)。
55
+ */
56
+ async removeAllByGuild(platform, guildId) {
57
+ await this.ctx.database.remove('rssOwl', { platform, guildId });
58
+ }
59
+ }
60
+ exports.SubscriptionStore = SubscriptionStore;
package/lib/index.js CHANGED
@@ -31,13 +31,24 @@ const commands_1 = require("./commands");
31
31
  // Import core modules
32
32
  const item_processor_1 = require("./core/item-processor");
33
33
  const feeder_1 = require("./core/feeder");
34
+ const subscription_store_1 = require("./core/subscription-store");
34
35
  const message_cache_1 = require("./utils/message-cache");
35
36
  const message_cache_service_1 = require("./services/message-cache-service");
36
37
  const notification_queue_1 = require("./core/notification-queue");
37
38
  // Import database and constants
38
39
  const database_1 = require("./database");
39
40
  const constants_1 = require("./constants");
40
- exports.inject = { required: ["database"], optional: ["puppeteer", "censor", "assets", "server", "ffmpeg"] };
41
+ // Koishi 4.11+ / cordis 3.x:服务声明用 inject 对象形式。
42
+ // - required:缺失则插件不加载(database 必需)。
43
+ // - optional:缺失仍加载,且抑制「property X is not registered」警告。
44
+ // 关键:cordis 的 Context 是 Proxy,读取未声明的服务属性(哪怕仅判空
45
+ // `if (!ctx.server)` 或可选链 `ctx.server?.x()`)都会触发警告;只有声明进
46
+ // inject/using,Proxy 才会经 internal/inject 事件短路 checkInject。
47
+ // 详见 @cordisjs/core index.cjs:271,284,866。
48
+ exports.inject = {
49
+ required: ['database'],
50
+ optional: ['assets', 'ffmpeg', 'puppeteer', 'server'],
51
+ };
41
52
  function apply(ctx, config) {
42
53
  // Setup database
43
54
  (0, database_1.setupDatabase)(ctx);
@@ -65,6 +76,8 @@ function apply(ctx, config) {
65
76
  const commandRuntime = (0, commands_1.createCommandRuntimeDeps)(ctx, config, $http, processor);
66
77
  // Initialize notification queue manager
67
78
  const queueManager = new notification_queue_1.NotificationQueueManager(ctx, config);
79
+ // Initialize subscription repository (rssOwl 表的唯一封装)
80
+ const subscriptionStore = new subscription_store_1.SubscriptionStore(ctx);
68
81
  // Initialize message cache
69
82
  if (config.cache?.enabled) {
70
83
  (0, message_cache_1.initMessageCache)(ctx, config, config.cache.maxSize || 100);
@@ -77,8 +90,12 @@ function apply(ctx, config) {
77
90
  });
78
91
  ctx.on('dispose', async () => {
79
92
  (0, feeder_1.stopFeeder)(config);
80
- if (config.basic.imageMode === 'File') {
81
- (0, media_1.delCache)(config);
93
+ // 销毁消息缓存单例:避免热重载后复用持有旧 ctx 的实例(P1-2)
94
+ if (config.cache?.enabled) {
95
+ (0, message_cache_1.disposeMessageCache)();
96
+ }
97
+ if (config.basic?.imageMode === 'File') {
98
+ await (0, media_1.delCache)(config);
82
99
  }
83
100
  });
84
101
  // ============================================
@@ -87,6 +104,7 @@ function apply(ctx, config) {
87
104
  (0, commands_1.registerSubscriptionManagementCommands)({
88
105
  ctx,
89
106
  config,
107
+ store: subscriptionStore,
90
108
  parsePubDate: commandRuntime.parsePubDate,
91
109
  parseQuickUrl: commandRuntime.parseQuickUrl,
92
110
  getRssData: commandRuntime.getRssData,
@@ -96,6 +114,7 @@ function apply(ctx, config) {
96
114
  (0, commands_1.registerSubscriptionCreateCommand)({
97
115
  ctx,
98
116
  config,
117
+ store: subscriptionStore,
99
118
  usage: constants_1.usage,
100
119
  quickList: constants_1.quickList,
101
120
  parseQuickUrl: commandRuntime.parseQuickUrl,
@@ -109,6 +128,7 @@ function apply(ctx, config) {
109
128
  (0, commands_1.registerWebMonitorCommands)({
110
129
  ctx,
111
130
  config,
131
+ store: subscriptionStore,
112
132
  debug: commandRuntime.debug,
113
133
  mixinArg: commandRuntime.mixinArg,
114
134
  getRssData: commandRuntime.getRssData,
@@ -119,6 +139,7 @@ function apply(ctx, config) {
119
139
  (0, commands_1.registerSubscriptionEditCommand)({
120
140
  ctx,
121
141
  config,
142
+ store: subscriptionStore,
122
143
  });
123
144
  (0, commands_1.registerManagementCommands)({
124
145
  ctx,