@zhin.js/plugin-rss 1.1.4 → 1.1.6

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.
package/README.md CHANGED
@@ -5,21 +5,20 @@ RSS/Atom 订阅推送插件 —— 订阅 feed 源,自动轮询并推送新内
5
5
  ## 安装
6
6
 
7
7
  ```bash
8
- npm install @zhin.js/plugin-rss
8
+ pnpm exec zhin install @zhin.js/plugin-rss
9
9
  ```
10
10
 
11
11
  ## 配置
12
12
 
13
- 在 `zhin.config.yml` 中添加:
13
+ 在应用目录运行安装命令,会安装依赖并挂载到 `package.json#zhin.plugins`,实例名为 `rss`。在 `zhin.config.yml` 的实例节点修改配置:
14
14
 
15
15
  ```yaml
16
16
  plugins:
17
- - "@zhin.js/plugin-rss"
18
- rss:
19
- pollCron: "*/5 * * * *" # 轮询频率,Cron 表达式(默认每 5 分钟)
20
- maxPerGroup: 30 # 每个会话最大订阅数(默认 30)
21
- maxItems: 5 # 单次推送最多展示条数(默认 5)
22
- timeout: 15000 # 拉取 feed 的超时时间 ms(默认 15s)
17
+ rss:
18
+ pollCron: "0 */5 * * * *" # 六段 Cron(秒、分、时、日、月、周),每 5 分钟
19
+ maxPerGroup: 30 # 每个会话最大订阅数(默认 30)
20
+ maxItems: 5 # 单次推送最多展示条数(默认 5)
21
+ timeout: 15000 # 拉取 feed 的超时时间 ms(默认 15s)
23
22
  ```
24
23
 
25
24
  ## 命令
@@ -32,6 +31,10 @@ rss:
32
31
  | `rss-check [url]` | 手动检查更新 | `rss-check` |
33
32
  | `rss-preview <url>` | 预览 feed 最新内容(不订阅) | `rss-preview https://rsshub.app/bilibili/hot-search` |
34
33
 
34
+ 订阅管理命令需要真实的 IM 会话来源,不会为无会话调用创建全局订阅。当前支持不含父容器或线程信息的私聊、群聊与频道;当 `conversation.parent` 或 `threadId` 存在时,会明确提示暂不支持该地址,不会丢弃字段后订阅频道本体。
35
+
36
+ 如果旧订阅记录保存了错误的端点或用户身份,系统无法可靠反推出原始会话。`rss-remove` 只删除当前 Bot、当前会话的订阅,不能清理归属不明的旧记录;需由管理员在数据库中核对插件实例和完整订阅字段,备份后按记录精确删除,再在真实会话重新订阅。不要仅凭 URL 或会话 ID 批量删除,以免影响其他 Bot。缺失或非法地址不会通过猜测进行投递;字段齐全但值错误的旧记录不会被自动识别或迁移。
37
+
35
38
  ## 工作原理
36
39
 
37
40
  1. `rss-add` 时验证 feed 可达性,记录订阅关系和当前会话(适配器、Bot、群/私聊)
@@ -62,7 +65,7 @@ rss:
62
65
 
63
66
  ## 数据库
64
67
 
65
- 依赖 Zhin 数据库服务,自动创建两张表:
68
+ 有 `databaseHostToken` 时自动创建以下两张表,并按插件实例隔离表名;未配置数据库时使用实例内存存储,重启后不会保留订阅。正式使用应配置持久数据库:
66
69
 
67
70
  **rss_subscriptions** — 订阅关系
68
71
 
@@ -72,8 +75,11 @@ rss:
72
75
  | feed_title | text | Feed 标题(自动获取) |
73
76
  | adapter_name | text | 适配器名称 |
74
77
  | endpoint_id | text | Endpoint ID |
75
- | channel_type | text | 会话类型 (group/private) |
78
+ | channel_type | text | 会话类型 (group/private/channel) |
76
79
  | channel_id | text | 会话 ID |
80
+ | creator_id | text | 订阅创建者 ID |
81
+ | creator_name | text | 订阅创建者名称 |
82
+ | created_at | text | 订阅创建时间(ISO 字符串) |
77
83
 
78
84
  **rss_seen_items** — 已推送条目(去重用)
79
85
 
@@ -81,12 +87,15 @@ rss:
81
87
  |------|------|------|
82
88
  | feed_url | text | Feed 地址 |
83
89
  | item_guid | text | 条目唯一标识 |
90
+ | item_title | text | 条目标题 |
91
+ | seen_at | text | 已读时间(ISO 字符串,用于过期清理) |
84
92
 
85
93
  ## 依赖
86
94
 
87
95
  - [rss-parser](https://github.com/rbren/rss-parser) — RSS/Atom 解析
88
- - Zhin 内置 `cron` 服务 — 定时轮询
89
- - Zhin 内置 `database` 服务 — 数据持久化
96
+ - Runtime `scheduleHostToken` — 定时轮询;未提供时只能手动检查
97
+ - Runtime `databaseHostToken` — 数据持久化;未提供时退回内存存储
98
+ - Runtime `outboundHostToken` — 新内容推送到原订阅会话
90
99
 
91
100
  ## 许可
92
101
 
@@ -1,7 +1,7 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
2
  import { defineCommand } from 'zhin.js/command';
3
- import { extractChannelInfo } from "../../../lib/channel.js";
4
- import { getRssSeen, getRssSubs } from "../../../lib/db-store.js";
3
+ import { channelSourceError, extractChannelInfo, subscriptionScope } from "../../../lib/channel.js";
4
+ import { getRssSubs } from "../../../lib/db-store.js";
5
5
  import { fetchFeed, resolveRssConfig } from "../../../lib/feed.js";
6
6
  import { markItemsSeen } from "../../../lib/poll.js";
7
7
  import { rssRuntimeToken } from "../../../lib/runtime.js";
@@ -19,19 +19,17 @@ export default defineCommand({
19
19
  if (!/^https?:\/\//i.test(url))
20
20
  return '请提供有效的 HTTP/HTTPS 地址';
21
21
  const channel = extractChannelInfo(input);
22
+ if (!channel)
23
+ return channelSourceError(input);
22
24
  const cfg = resolveRssConfig(config);
23
25
  const existing = await Subs.select().where({
24
26
  url,
25
- adapter_name: channel.adapterName,
26
- channel_type: channel.channelType,
27
- channel_id: channel.channelId,
27
+ ...subscriptionScope(channel),
28
28
  });
29
29
  if (existing.length > 0)
30
30
  return '当前会话已订阅该源,无需重复添加';
31
31
  const currentSubs = await Subs.select().where({
32
- adapter_name: channel.adapterName,
33
- channel_type: channel.channelType,
34
- channel_id: channel.channelId,
32
+ ...subscriptionScope(channel),
35
33
  });
36
34
  if (currentSubs.length >= cfg.maxPerGroup) {
37
35
  return `当前会话订阅数已达上限 (${cfg.maxPerGroup}),请先取消一些`;
@@ -1,6 +1,6 @@
1
1
  import { defineCommand } from 'zhin.js/command';
2
- import { extractChannelInfo } from '../../../src/channel.js';
3
- import { getRssSeen, getRssSubs } from '../../../src/db-store.js';
2
+ import { channelSourceError, extractChannelInfo, subscriptionScope } from '../../../src/channel.js';
3
+ import { getRssSubs } from '../../../src/db-store.js';
4
4
  import { fetchFeed, resolveRssConfig, type RssConfig } from '../../../src/feed.js';
5
5
  import { markItemsSeen } from '../../../src/poll.js';
6
6
  import { rssRuntimeToken } from '../../../src/runtime.js';
@@ -18,20 +18,17 @@ export default defineCommand<RssConfig>({
18
18
  if (!/^https?:\/\//i.test(url)) return '请提供有效的 HTTP/HTTPS 地址';
19
19
 
20
20
  const channel = extractChannelInfo(input);
21
+ if (!channel) return channelSourceError(input);
21
22
  const cfg = resolveRssConfig(config);
22
23
 
23
24
  const existing = await Subs.select().where({
24
25
  url,
25
- adapter_name: channel.adapterName,
26
- channel_type: channel.channelType,
27
- channel_id: channel.channelId,
26
+ ...subscriptionScope(channel),
28
27
  });
29
28
  if (existing.length > 0) return '当前会话已订阅该源,无需重复添加';
30
29
 
31
30
  const currentSubs = await Subs.select().where({
32
- adapter_name: channel.adapterName,
33
- channel_type: channel.channelType,
34
- channel_id: channel.channelId,
31
+ ...subscriptionScope(channel),
35
32
  });
36
33
  if (currentSubs.length >= cfg.maxPerGroup) {
37
34
  return `当前会话订阅数已达上限 (${cfg.maxPerGroup}),请先取消一些`;
@@ -1,6 +1,6 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
2
  import { defineCommand } from 'zhin.js/command';
3
- import { extractChannelInfo } from "../../../lib/channel.js";
3
+ import { channelSourceError, extractChannelInfo, subscriptionScope } from "../../../lib/channel.js";
4
4
  import { getRssSubs } from "../../../lib/db-store.js";
5
5
  import { resolveRssConfig } from "../../../lib/feed.js";
6
6
  import { checkSubscriptions } from "../../../lib/poll.js";
@@ -14,14 +14,14 @@ export default defineCommand({
14
14
  if (!Subs)
15
15
  return 'RSS 数据库尚未就绪';
16
16
  const channel = extractChannelInfo(input);
17
+ if (!channel)
18
+ return channelSourceError(input);
17
19
  const targetUrl = String(params.url ?? '').trim();
18
20
  let urls;
19
21
  if (targetUrl) {
20
22
  const rows = await Subs.select().where({
21
23
  url: targetUrl,
22
- adapter_name: channel.adapterName,
23
- channel_type: channel.channelType,
24
- channel_id: channel.channelId,
24
+ ...subscriptionScope(channel),
25
25
  });
26
26
  if (rows.length === 0)
27
27
  return '当前会话未订阅该源';
@@ -29,9 +29,7 @@ export default defineCommand({
29
29
  }
30
30
  else {
31
31
  const rows = await Subs.select().where({
32
- adapter_name: channel.adapterName,
33
- channel_type: channel.channelType,
34
- channel_id: channel.channelId,
32
+ ...subscriptionScope(channel),
35
33
  });
36
34
  if (rows.length === 0)
37
35
  return '当前会话没有任何订阅';
@@ -1,5 +1,5 @@
1
1
  import { defineCommand } from 'zhin.js/command';
2
- import { extractChannelInfo } from '../../../src/channel.js';
2
+ import { channelSourceError, extractChannelInfo, subscriptionScope } from '../../../src/channel.js';
3
3
  import { getRssSubs } from '../../../src/db-store.js';
4
4
  import { resolveRssConfig, type RssConfig } from '../../../src/feed.js';
5
5
  import { checkSubscriptions } from '../../../src/poll.js';
@@ -14,23 +14,20 @@ export default defineCommand<RssConfig>({
14
14
  if (!Subs) return 'RSS 数据库尚未就绪';
15
15
 
16
16
  const channel = extractChannelInfo(input);
17
+ if (!channel) return channelSourceError(input);
17
18
  const targetUrl = String(params.url ?? '').trim();
18
19
 
19
20
  let urls: string[];
20
21
  if (targetUrl) {
21
22
  const rows = await Subs.select().where({
22
23
  url: targetUrl,
23
- adapter_name: channel.adapterName,
24
- channel_type: channel.channelType,
25
- channel_id: channel.channelId,
24
+ ...subscriptionScope(channel),
26
25
  });
27
26
  if (rows.length === 0) return '当前会话未订阅该源';
28
27
  urls = [targetUrl];
29
28
  } else {
30
29
  const rows = await Subs.select().where({
31
- adapter_name: channel.adapterName,
32
- channel_type: channel.channelType,
33
- channel_id: channel.channelId,
30
+ ...subscriptionScope(channel),
34
31
  });
35
32
  if (rows.length === 0) return '当前会话没有任何订阅';
36
33
  urls = [...new Set(rows.map((r) => String(r.url ?? '')).filter(Boolean))];
@@ -1,6 +1,6 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
2
  import { defineCommand } from 'zhin.js/command';
3
- import { extractChannelInfo } from "../../lib/channel.js";
3
+ import { channelSourceError, extractChannelInfo, subscriptionScope } from "../../lib/channel.js";
4
4
  import { getRssSubs } from "../../lib/db-store.js";
5
5
  import { resolveRssConfig } from "../../lib/feed.js";
6
6
  import { rssRuntimeToken } from "../../lib/runtime.js";
@@ -11,11 +11,11 @@ export default defineCommand({
11
11
  if (!Subs)
12
12
  return 'RSS 数据库尚未就绪';
13
13
  const channel = extractChannelInfo(input);
14
+ if (!channel)
15
+ return channelSourceError(input);
14
16
  const cfg = resolveRssConfig(config);
15
17
  const rows = await Subs.select().where({
16
- adapter_name: channel.adapterName,
17
- channel_type: channel.channelType,
18
- channel_id: channel.channelId,
18
+ ...subscriptionScope(channel),
19
19
  });
20
20
  if (rows.length === 0) {
21
21
  return '当前会话没有订阅任何 RSS 源\n使用 rss-add <URL> 添加订阅';
@@ -1,5 +1,5 @@
1
1
  import { defineCommand } from 'zhin.js/command';
2
- import { extractChannelInfo } from '../../src/channel.js';
2
+ import { channelSourceError, extractChannelInfo, subscriptionScope } from '../../src/channel.js';
3
3
  import { getRssSubs } from '../../src/db-store.js';
4
4
  import { resolveRssConfig, type RssConfig } from '../../src/feed.js';
5
5
  import { rssRuntimeToken } from '../../src/runtime.js';
@@ -11,11 +11,10 @@ export default defineCommand<RssConfig>({
11
11
  if (!Subs) return 'RSS 数据库尚未就绪';
12
12
 
13
13
  const channel = extractChannelInfo(input);
14
+ if (!channel) return channelSourceError(input);
14
15
  const cfg = resolveRssConfig(config);
15
16
  const rows = await Subs.select().where({
16
- adapter_name: channel.adapterName,
17
- channel_type: channel.channelType,
18
- channel_id: channel.channelId,
17
+ ...subscriptionScope(channel),
19
18
  });
20
19
 
21
20
  if (rows.length === 0) {
@@ -1,6 +1,6 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
2
  import { defineCommand } from 'zhin.js/command';
3
- import { extractChannelInfo } from "../../../lib/channel.js";
3
+ import { channelSourceError, extractChannelInfo, subscriptionScope } from "../../../lib/channel.js";
4
4
  import { getRssSubs } from "../../../lib/db-store.js";
5
5
  import { rssRuntimeToken } from "../../../lib/runtime.js";
6
6
  export default defineCommand({
@@ -14,11 +14,11 @@ export default defineCommand({
14
14
  if (!url)
15
15
  return '请提供要取消的 RSS 源地址';
16
16
  const channel = extractChannelInfo(input);
17
+ if (!channel)
18
+ return channelSourceError(input);
17
19
  const rows = await Subs.select().where({
18
20
  url,
19
- adapter_name: channel.adapterName,
20
- channel_type: channel.channelType,
21
- channel_id: channel.channelId,
21
+ ...subscriptionScope(channel),
22
22
  });
23
23
  if (rows.length === 0)
24
24
  return '未找到该订阅';
@@ -26,9 +26,7 @@ export default defineCommand({
26
26
  // 表结构没有 id 列,删除必须按业务键匹配(与上面的 select 条件一致)。
27
27
  await Subs.delete().where({
28
28
  url,
29
- adapter_name: channel.adapterName,
30
- channel_type: channel.channelType,
31
- channel_id: channel.channelId,
29
+ ...subscriptionScope(channel),
32
30
  });
33
31
  return `已取消订阅: ${String(row.feed_title || url)}`;
34
32
  },
@@ -1,5 +1,5 @@
1
1
  import { defineCommand } from 'zhin.js/command';
2
- import { extractChannelInfo } from '../../../src/channel.js';
2
+ import { channelSourceError, extractChannelInfo, subscriptionScope } from '../../../src/channel.js';
3
3
  import { getRssSubs } from '../../../src/db-store.js';
4
4
  import type { RssConfig } from '../../../src/feed.js';
5
5
  import { rssRuntimeToken } from '../../../src/runtime.js';
@@ -15,11 +15,10 @@ export default defineCommand<RssConfig>({
15
15
  if (!url) return '请提供要取消的 RSS 源地址';
16
16
 
17
17
  const channel = extractChannelInfo(input);
18
+ if (!channel) return channelSourceError(input);
18
19
  const rows = await Subs.select().where({
19
20
  url,
20
- adapter_name: channel.adapterName,
21
- channel_type: channel.channelType,
22
- channel_id: channel.channelId,
21
+ ...subscriptionScope(channel),
23
22
  });
24
23
 
25
24
  if (rows.length === 0) return '未找到该订阅';
@@ -28,9 +27,7 @@ export default defineCommand<RssConfig>({
28
27
  // 表结构没有 id 列,删除必须按业务键匹配(与上面的 select 条件一致)。
29
28
  await Subs.delete().where({
30
29
  url,
31
- adapter_name: channel.adapterName,
32
- channel_type: channel.channelType,
33
- channel_id: channel.channelId,
30
+ ...subscriptionScope(channel),
34
31
  });
35
32
  return `已取消订阅: ${String(row.feed_title || url)}`;
36
33
  },
package/lib/channel.d.ts CHANGED
@@ -1,16 +1,18 @@
1
- /**
2
- * Extract subscription channel keys from Runtime Message (`input`).
3
- * Gaps vs legacy: no `$channel` / `$group` — use `conversation` / `metadata`.
4
- */
1
+ /** A subscription destination uses public Message fields, never CapabilityId internals. */
5
2
  export interface ChannelInfo {
6
3
  adapterName: string;
7
4
  endpointKey: string;
8
- channelType: string;
5
+ channelType: 'private' | 'group' | 'channel';
9
6
  channelId: string;
10
7
  senderId: string;
11
8
  senderName: string;
12
9
  }
13
- /** Smoke / agent / execute()-without-dispatch fallback. */
14
- export declare const SMOKE_CHANNEL: ChannelInfo;
15
- export declare function extractChannelInfo(input: unknown): ChannelInfo;
10
+ export declare const CHANNEL_REQUIRED_MESSAGE = "\u8BF7\u5728\u673A\u5668\u4EBA\u79C1\u804A\u3001\u7FA4\u804A\u6216\u9891\u9053\u5185\u6267\u884C\u6B64\u547D\u4EE4\uFF1B\u5F53\u524D\u8C03\u7528\u6CA1\u6709\u6709\u6548\u7684\u8BA2\u9605\u4F1A\u8BDD";
11
+ export declare const UNSUPPORTED_ADDRESS_MESSAGE = "\u6682\u4E0D\u652F\u6301\u7EBF\u7A0B\uFF0F\u7236\u9891\u9053\u5BFB\u5740\u7684\u8BA2\u9605\uFF0C\u8BF7\u5728\u65E0\u9700\u7EBF\u7A0B\u6216\u7236\u9891\u9053\u4FE1\u606F\u7684\u4F1A\u8BDD\u5185\u6267\u884C";
12
+ /** Explain rejection without silently flattening a thread/container address. */
13
+ export declare function channelSourceError(input: unknown): string;
14
+ /** No IM source means no destination; callers must not invent a global subscription. */
15
+ export declare function extractChannelInfo(input: unknown): ChannelInfo | null;
16
+ /** Complete subscription scope, including the bot instance for multi-endpoint adapters. */
17
+ export declare function subscriptionScope(channel: ChannelInfo): Record<string, string>;
16
18
  //# sourceMappingURL=channel.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,2DAA2D;AAC3D,eAAO,MAAM,aAAa,EAAE,WAO3B,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CA4C9D"}
1
+ {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAE3F,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,wBAAwB,2MAAsC,CAAC;AAC5E,eAAO,MAAM,2BAA2B,iNAAuC,CAAC;AAehF,gFAAgF;AAChF,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEzD;AAED,wFAAwF;AACxF,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,GAAG,IAAI,CAoBrE;AAED,2FAA2F;AAC3F,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAO9E"}
package/lib/channel.js CHANGED
@@ -1,42 +1,52 @@
1
- /**
2
- * Extract subscription channel keys from Runtime Message (`input`).
3
- * Gaps vs legacy: no `$channel` / `$group` — use `conversation` / `metadata`.
4
- */
5
- /** Smoke / agent / execute()-without-dispatch fallback. */
6
- export const SMOKE_CHANNEL = {
7
- adapterName: 'smoke',
8
- endpointKey: 'local',
9
- channelType: 'private',
10
- channelId: 'global',
11
- senderId: '',
12
- senderName: '',
13
- };
1
+ /** A subscription destination uses public Message fields, never CapabilityId internals. */
2
+ export const CHANNEL_REQUIRED_MESSAGE = '请在机器人私聊、群聊或频道内执行此命令;当前调用没有有效的订阅会话';
3
+ export const UNSUPPORTED_ADDRESS_MESSAGE = '暂不支持线程/父频道寻址的订阅,请在无需线程或父频道信息的会话内执行';
4
+ function isRecord(value) {
5
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
6
+ }
7
+ function isIdentifier(value) {
8
+ return typeof value === 'string' && value.trim().length > 0;
9
+ }
10
+ function hasUnsupportedAddress(input) {
11
+ return isRecord(input) && isRecord(input.conversation)
12
+ && (input.conversation.parent !== undefined || input.conversation.threadId !== undefined);
13
+ }
14
+ /** Explain rejection without silently flattening a thread/container address. */
15
+ export function channelSourceError(input) {
16
+ return hasUnsupportedAddress(input) ? UNSUPPORTED_ADDRESS_MESSAGE : CHANNEL_REQUIRED_MESSAGE;
17
+ }
18
+ /** No IM source means no destination; callers must not invent a global subscription. */
14
19
  export function extractChannelInfo(input) {
15
- if (!input || typeof input !== 'object')
16
- return { ...SMOKE_CHANNEL };
17
- const msg = input;
18
- const meta = msg.metadata ?? {};
19
- const conversation = msg.conversation;
20
- const channelType = String(meta.channelType ?? meta.type ?? meta.channel_type ?? conversation?.kind ?? 'private');
21
- const channelId = String(meta.channelId ?? meta.channel_id ?? conversation?.id ?? SMOKE_CHANNEL.channelId);
22
- const endpointCapabilityId = typeof conversation?.endpoint?.id === 'string'
23
- ? conversation.endpoint.id
24
- : undefined;
25
- const adapterName = String((endpointCapabilityId?.split('\0').pop() ?? endpointCapabilityId)?.split('~')[0]
26
- ?? meta.adapter
27
- ?? SMOKE_CHANNEL.adapterName);
28
- const endpointKey = String(meta.endpoint ?? meta.endpointKey ?? meta.endpoint_id ?? adapterName);
29
- const senderId = String(msg.sender ?? meta.senderId ?? '');
30
- const senderName = String(meta.senderName ?? meta.name ?? '');
31
- if (!channelId)
32
- return { ...SMOKE_CHANNEL, adapterName, endpointKey, senderId, senderName };
20
+ if (!isRecord(input) || !isRecord(input.conversation))
21
+ return null;
22
+ if (hasUnsupportedAddress(input))
23
+ return null;
24
+ const conversation = input.conversation;
25
+ const kind = conversation.kind;
26
+ if (kind !== 'private' && kind !== 'group' && kind !== 'channel')
27
+ return null;
28
+ if (!isIdentifier(input.clientAdapter) || !isIdentifier(input.endpointId)
29
+ || !isIdentifier(conversation.id))
30
+ return null;
31
+ const sender = input.sender;
32
+ if (sender !== undefined && (!isRecord(sender) || !isIdentifier(sender.id)))
33
+ return null;
34
+ return {
35
+ adapterName: input.clientAdapter,
36
+ endpointKey: input.endpointId,
37
+ channelType: kind,
38
+ channelId: conversation.id,
39
+ senderId: isRecord(sender) && isIdentifier(sender.id) ? sender.id : '',
40
+ senderName: isRecord(sender) && typeof sender.name === 'string' ? sender.name : '',
41
+ };
42
+ }
43
+ /** Complete subscription scope, including the bot instance for multi-endpoint adapters. */
44
+ export function subscriptionScope(channel) {
33
45
  return {
34
- adapterName,
35
- endpointKey,
36
- channelType,
37
- channelId,
38
- senderId,
39
- senderName,
46
+ adapter_name: channel.adapterName,
47
+ endpoint_id: channel.endpointKey,
48
+ channel_type: channel.channelType,
49
+ channel_id: channel.channelId,
40
50
  };
41
51
  }
42
52
  //# sourceMappingURL=channel.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"channel.js","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAWH,2DAA2D;AAC3D,MAAM,CAAC,MAAM,aAAa,GAAgB;IACxC,WAAW,EAAE,OAAO;IACpB,WAAW,EAAE,OAAO;IACpB,WAAW,EAAE,SAAS;IACtB,SAAS,EAAE,QAAQ;IACnB,QAAQ,EAAE,EAAE;IACZ,UAAU,EAAE,EAAE;CACf,CAAC;AAEF,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,EAAE,GAAG,aAAa,EAAE,CAAC;IAErE,MAAM,GAAG,GAAG,KAQX,CAAC;IACF,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC;IAChC,MAAM,YAAY,GAAG,GAAG,CAAC,YAAY,CAAC;IACtC,MAAM,WAAW,GAAG,MAAM,CACxB,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,YAAY,IAAI,YAAY,EAAE,IAAI,IAAI,SAAS,CACtF,CAAC;IACF,MAAM,SAAS,GAAG,MAAM,CACtB,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,UAAU,IAAI,YAAY,EAAE,EAAE,IAAI,aAAa,CAAC,SAAS,CACjF,CAAC;IACF,MAAM,oBAAoB,GAAG,OAAO,YAAY,EAAE,QAAQ,EAAE,EAAE,KAAK,QAAQ;QACzE,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE;QAC1B,CAAC,CAAC,SAAS,CAAC;IACd,MAAM,WAAW,GAAG,MAAM,CACxB,CAAC,oBAAoB,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,oBAAoB,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;WAC7E,IAAI,CAAC,OAAO;WACZ,aAAa,CAAC,WAAW,CAC7B,CAAC;IACF,MAAM,WAAW,GAAG,MAAM,CACxB,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,WAAW,IAAI,WAAW,CACrE,CAAC;IACF,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;IAC3D,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IAE9D,IAAI,CAAC,SAAS;QAAE,OAAO,EAAE,GAAG,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;IAE5F,OAAO;QACL,WAAW;QACX,WAAW;QACX,WAAW;QACX,SAAS;QACT,QAAQ;QACR,UAAU;KACX,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"channel.js","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAW3F,MAAM,CAAC,MAAM,wBAAwB,GAAG,mCAAmC,CAAC;AAC5E,MAAM,CAAC,MAAM,2BAA2B,GAAG,oCAAoC,CAAC;AAEhF,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;AAC9D,CAAC;AAED,SAAS,qBAAqB,CAAC,KAAc;IAC3C,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC;WACjD,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,KAAK,SAAS,IAAI,KAAK,CAAC,YAAY,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC;AAC9F,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,OAAO,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,wBAAwB,CAAC;AAC/F,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC;QAAE,OAAO,IAAI,CAAC;IACnE,IAAI,qBAAqB,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC9C,MAAM,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC;IACxC,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC;IAC/B,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAC9E,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,UAAU,CAAC;WACpE,CAAC,YAAY,CAAC,YAAY,CAAC,EAAE,CAAC;QAAE,OAAO,IAAI,CAAC;IAEjD,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC5B,IAAI,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAEzF,OAAO;QACL,WAAW,EAAE,KAAK,CAAC,aAAa;QAChC,WAAW,EAAE,KAAK,CAAC,UAAU;QAC7B,WAAW,EAAE,IAAI;QACjB,SAAS,EAAE,YAAY,CAAC,EAAE;QAC1B,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;QACtE,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;KACnF,CAAC;AACJ,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,iBAAiB,CAAC,OAAoB;IACpD,OAAO;QACL,YAAY,EAAE,OAAO,CAAC,WAAW;QACjC,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,YAAY,EAAE,OAAO,CAAC,WAAW;QACjC,UAAU,EAAE,OAAO,CAAC,SAAS;KAC9B,CAAC;AACJ,CAAC"}
package/lib/index.d.ts CHANGED
@@ -2,7 +2,7 @@ export { DEFAULT_RSS_CONFIG, fetchFeed, formatFeedPreview, resolveRssConfig, str
2
2
  export type { FeedItem, RssConfig } from './feed.js';
3
3
  export { getRssSeen, getRssSubs } from './db-store.js';
4
4
  export { rssRuntimeToken, type RssRuntime, type RssOutboundPush } from './runtime.js';
5
- export { extractChannelInfo, SMOKE_CHANNEL } from './channel.js';
5
+ export { extractChannelInfo } from './channel.js';
6
6
  export { checkSubscriptions, pollAllFeeds, formatNewItems } from './poll.js';
7
7
  export type { CheckResult } from './poll.js';
8
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,SAAS,EACT,iBAAiB,EACjB,gBAAgB,EAChB,SAAS,GACV,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,KAAK,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AACtF,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC7E,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,SAAS,EACT,iBAAiB,EACjB,gBAAgB,EAChB,SAAS,GACV,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,KAAK,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AACtF,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC7E,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC"}
package/lib/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export { DEFAULT_RSS_CONFIG, fetchFeed, formatFeedPreview, resolveRssConfig, stripHtml, } from './feed.js';
2
2
  export { getRssSeen, getRssSubs } from './db-store.js';
3
3
  export { rssRuntimeToken } from './runtime.js';
4
- export { extractChannelInfo, SMOKE_CHANNEL } from './channel.js';
4
+ export { extractChannelInfo } from './channel.js';
5
5
  export { checkSubscriptions, pollAllFeeds, formatNewItems } from './poll.js';
6
6
  //# sourceMappingURL=index.js.map
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,SAAS,EACT,iBAAiB,EACjB,gBAAgB,EAChB,SAAS,GACV,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,eAAe,EAAyC,MAAM,cAAc,CAAC;AACtF,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,SAAS,EACT,iBAAiB,EACjB,gBAAgB,EAChB,SAAS,GACV,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,eAAe,EAAyC,MAAM,cAAc,CAAC;AACtF,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC"}
package/lib/poll.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"poll.d.ts","sourceRoot":"","sources":["../src/poll.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAa,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAM/C,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAY7F;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAc1G;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AA4BD;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE;IACrE,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;CACzB,GAAG,OAAO,CAAC,WAAW,CAAC,CAuCvB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBrE;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAO5E"}
1
+ {"version":3,"file":"poll.d.ts","sourceRoot":"","sources":["../src/poll.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAa,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAM/C,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAY7F;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAc1G;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAiCD;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE;IACrE,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;CACzB,GAAG,OAAO,CAAC,WAAW,CAAC,CAuCvB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBrE;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAO5E"}
package/lib/poll.js CHANGED
@@ -45,15 +45,20 @@ async function pushToSubscribers(runtime, feedUrl, content) {
45
45
  const subscribers = await Subs.select().where({ url: feedUrl });
46
46
  let pushed = 0;
47
47
  for (const sub of subscribers) {
48
- const adapterName = String(sub.adapter_name ?? '');
49
- const channelId = String(sub.channel_id ?? '');
50
- if (!adapterName || !channelId)
48
+ const adapterName = sub.adapter_name;
49
+ const endpointKey = sub.endpoint_id;
50
+ const channelType = sub.channel_type;
51
+ const channelId = sub.channel_id;
52
+ if (typeof adapterName !== 'string' || !adapterName.trim()
53
+ || typeof channelId !== 'string' || !channelId.trim()
54
+ || typeof endpointKey !== 'string' || !endpointKey.trim()
55
+ || (channelType !== 'private' && channelType !== 'group' && channelType !== 'channel'))
51
56
  continue;
52
57
  try {
53
58
  await push({
54
59
  adapterName,
55
- endpointKey: String(sub.endpoint_id ?? adapterName),
56
- channelType: String(sub.channel_type ?? 'private'),
60
+ endpointKey,
61
+ channelType,
57
62
  channelId,
58
63
  content,
59
64
  });
package/lib/poll.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"poll.js","sourceRoot":"","sources":["../src/poll.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"poll.js","sourceRoot":"","sources":["../src/poll.ts"],"names":[],"mappings":"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"}
package/lib/runtime.d.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  import type { RssConfig } from './feed.js';
2
2
  import type { RssMemoryDb } from './memory-store.js';
3
+ import type { ChannelInfo } from './channel.js';
3
4
  export type RssOutboundPush = (input: {
4
5
  readonly adapterName: string;
5
6
  readonly endpointKey: string;
6
- readonly channelType: string;
7
+ readonly channelType: ChannelInfo['channelType'];
7
8
  readonly channelId: string;
8
9
  readonly content: string;
9
10
  }) => Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE;IACpC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAEpB,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,EAAE,WAAW,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;CAC3C;AAED,eAAO,MAAM,eAAe,qCAG3B,CAAC"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE;IACpC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,aAAa,CAAC,CAAC;IACjD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAEpB,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,EAAE,WAAW,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;CAC3C;AAED,eAAO,MAAM,eAAe,qCAG3B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAkBtC,MAAM,CAAC,MAAM,eAAe,GAAG,WAAW,CACxC,kBAAkB,EAClB,0BAA0B,CAC3B,CAAC"}
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAmBtC,MAAM,CAAC,MAAM,eAAe,GAAG,WAAW,CACxC,kBAAkB,EAClB,0BAA0B,CAC3B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/plugin-rss",
3
- "version": "1.1.4",
3
+ "version": "1.1.6",
4
4
  "description": "RSS/Atom feed subscription plugin for Zhin.js (Plugin Runtime)",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -8,7 +8,6 @@
8
8
  "exports": {
9
9
  ".": {
10
10
  "types": "./lib/index.d.ts",
11
- "development": "./src/index.ts",
12
11
  "import": "./lib/index.js"
13
12
  },
14
13
  "./package.json": "./package.json"
@@ -42,19 +41,19 @@
42
41
  "license": "MIT",
43
42
  "dependencies": {
44
43
  "rss-parser": "^3.13.0",
45
- "@zhin.js/skill": "1.1.4",
46
- "@zhin.js/tool": "1.1.4"
44
+ "@zhin.js/tool": "1.1.6",
45
+ "@zhin.js/skill": "1.1.6"
47
46
  },
48
47
  "devDependencies": {
49
48
  "typescript": "^6.0.3",
50
49
  "vitest": "^4.1.10",
51
50
  "zod": "^4.4.3",
52
- "zhin.js": "1.1.6"
51
+ "zhin.js": "1.1.9"
53
52
  },
54
53
  "peerDependencies": {
55
54
  "zod": "^4.0.0",
56
- "@zhin.js/command": "^1.1.5",
57
- "zhin.js": "^1.1.6"
55
+ "@zhin.js/command": "^1.1.7",
56
+ "zhin.js": "^1.1.9"
58
57
  },
59
58
  "peerDependenciesMeta": {
60
59
  "@zhin.js/command": {
@@ -74,7 +73,7 @@
74
73
  "registry": "https://registry.npmjs.org"
75
74
  },
76
75
  "engines": {
77
- "node": "^20.19.0 || >=22.12.0"
76
+ "node": ">=22.19.0"
78
77
  },
79
78
  "zhin": {
80
79
  "protocol": 1,
package/src/channel.ts CHANGED
@@ -1,69 +1,64 @@
1
- /**
2
- * Extract subscription channel keys from Runtime Message (`input`).
3
- * Gaps vs legacy: no `$channel` / `$group` — use `conversation` / `metadata`.
4
- */
1
+ /** A subscription destination uses public Message fields, never CapabilityId internals. */
5
2
 
6
3
  export interface ChannelInfo {
7
4
  adapterName: string;
8
5
  endpointKey: string;
9
- channelType: string;
6
+ channelType: 'private' | 'group' | 'channel';
10
7
  channelId: string;
11
8
  senderId: string;
12
9
  senderName: string;
13
10
  }
14
11
 
15
- /** Smoke / agent / execute()-without-dispatch fallback. */
16
- export const SMOKE_CHANNEL: ChannelInfo = {
17
- adapterName: 'smoke',
18
- endpointKey: 'local',
19
- channelType: 'private',
20
- channelId: 'global',
21
- senderId: '',
22
- senderName: '',
23
- };
12
+ export const CHANNEL_REQUIRED_MESSAGE = '请在机器人私聊、群聊或频道内执行此命令;当前调用没有有效的订阅会话';
13
+ export const UNSUPPORTED_ADDRESS_MESSAGE = '暂不支持线程/父频道寻址的订阅,请在无需线程或父频道信息的会话内执行';
24
14
 
25
- export function extractChannelInfo(input: unknown): ChannelInfo {
26
- if (!input || typeof input !== 'object') return { ...SMOKE_CHANNEL };
15
+ function isRecord(value: unknown): value is Record<string, unknown> {
16
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
17
+ }
27
18
 
28
- const msg = input as {
29
- conversation?: {
30
- endpoint?: { id?: string; adapter?: string };
31
- kind?: string;
32
- id?: string;
33
- };
34
- sender?: string;
35
- metadata?: Record<string, unknown>;
36
- };
37
- const meta = msg.metadata ?? {};
38
- const conversation = msg.conversation;
39
- const channelType = String(
40
- meta.channelType ?? meta.type ?? meta.channel_type ?? conversation?.kind ?? 'private',
41
- );
42
- const channelId = String(
43
- meta.channelId ?? meta.channel_id ?? conversation?.id ?? SMOKE_CHANNEL.channelId,
44
- );
45
- const endpointCapabilityId = typeof conversation?.endpoint?.id === 'string'
46
- ? conversation.endpoint.id
47
- : undefined;
48
- const adapterName = String(
49
- (endpointCapabilityId?.split('\0').pop() ?? endpointCapabilityId)?.split('~')[0]
50
- ?? meta.adapter
51
- ?? SMOKE_CHANNEL.adapterName,
52
- );
53
- const endpointKey = String(
54
- meta.endpoint ?? meta.endpointKey ?? meta.endpoint_id ?? adapterName,
55
- );
56
- const senderId = String(msg.sender ?? meta.senderId ?? '');
57
- const senderName = String(meta.senderName ?? meta.name ?? '');
19
+ function isIdentifier(value: unknown): value is string {
20
+ return typeof value === 'string' && value.trim().length > 0;
21
+ }
22
+
23
+ function hasUnsupportedAddress(input: unknown): boolean {
24
+ return isRecord(input) && isRecord(input.conversation)
25
+ && (input.conversation.parent !== undefined || input.conversation.threadId !== undefined);
26
+ }
27
+
28
+ /** Explain rejection without silently flattening a thread/container address. */
29
+ export function channelSourceError(input: unknown): string {
30
+ return hasUnsupportedAddress(input) ? UNSUPPORTED_ADDRESS_MESSAGE : CHANNEL_REQUIRED_MESSAGE;
31
+ }
32
+
33
+ /** No IM source means no destination; callers must not invent a global subscription. */
34
+ export function extractChannelInfo(input: unknown): ChannelInfo | null {
35
+ if (!isRecord(input) || !isRecord(input.conversation)) return null;
36
+ if (hasUnsupportedAddress(input)) return null;
37
+ const conversation = input.conversation;
38
+ const kind = conversation.kind;
39
+ if (kind !== 'private' && kind !== 'group' && kind !== 'channel') return null;
40
+ if (!isIdentifier(input.clientAdapter) || !isIdentifier(input.endpointId)
41
+ || !isIdentifier(conversation.id)) return null;
42
+
43
+ const sender = input.sender;
44
+ if (sender !== undefined && (!isRecord(sender) || !isIdentifier(sender.id))) return null;
58
45
 
59
- if (!channelId) return { ...SMOKE_CHANNEL, adapterName, endpointKey, senderId, senderName };
46
+ return {
47
+ adapterName: input.clientAdapter,
48
+ endpointKey: input.endpointId,
49
+ channelType: kind,
50
+ channelId: conversation.id,
51
+ senderId: isRecord(sender) && isIdentifier(sender.id) ? sender.id : '',
52
+ senderName: isRecord(sender) && typeof sender.name === 'string' ? sender.name : '',
53
+ };
54
+ }
60
55
 
56
+ /** Complete subscription scope, including the bot instance for multi-endpoint adapters. */
57
+ export function subscriptionScope(channel: ChannelInfo): Record<string, string> {
61
58
  return {
62
- adapterName,
63
- endpointKey,
64
- channelType,
65
- channelId,
66
- senderId,
67
- senderName,
59
+ adapter_name: channel.adapterName,
60
+ endpoint_id: channel.endpointKey,
61
+ channel_type: channel.channelType,
62
+ channel_id: channel.channelId,
68
63
  };
69
64
  }
package/src/index.ts CHANGED
@@ -8,6 +8,6 @@ export {
8
8
  export type { FeedItem, RssConfig } from './feed.js';
9
9
  export { getRssSeen, getRssSubs } from './db-store.js';
10
10
  export { rssRuntimeToken, type RssRuntime, type RssOutboundPush } from './runtime.js';
11
- export { extractChannelInfo, SMOKE_CHANNEL } from './channel.js';
11
+ export { extractChannelInfo } from './channel.js';
12
12
  export { checkSubscriptions, pollAllFeeds, formatNewItems } from './poll.js';
13
13
  export type { CheckResult } from './poll.js';
package/src/poll.ts CHANGED
@@ -52,14 +52,19 @@ async function pushToSubscribers(runtime: RssRuntime, feedUrl: string, content:
52
52
  const subscribers = await Subs.select().where({ url: feedUrl });
53
53
  let pushed = 0;
54
54
  for (const sub of subscribers) {
55
- const adapterName = String(sub.adapter_name ?? '');
56
- const channelId = String(sub.channel_id ?? '');
57
- if (!adapterName || !channelId) continue;
55
+ const adapterName = sub.adapter_name;
56
+ const endpointKey = sub.endpoint_id;
57
+ const channelType = sub.channel_type;
58
+ const channelId = sub.channel_id;
59
+ if (typeof adapterName !== 'string' || !adapterName.trim()
60
+ || typeof channelId !== 'string' || !channelId.trim()
61
+ || typeof endpointKey !== 'string' || !endpointKey.trim()
62
+ || (channelType !== 'private' && channelType !== 'group' && channelType !== 'channel')) continue;
58
63
  try {
59
64
  await push({
60
65
  adapterName,
61
- endpointKey: String(sub.endpoint_id ?? adapterName),
62
- channelType: String(sub.channel_type ?? 'private'),
66
+ endpointKey,
67
+ channelType,
63
68
  channelId,
64
69
  content,
65
70
  });
package/src/runtime.ts CHANGED
@@ -1,11 +1,12 @@
1
1
  import { createToken } from 'zhin.js';
2
2
  import type { RssConfig } from './feed.js';
3
3
  import type { RssMemoryDb } from './memory-store.js';
4
+ import type { ChannelInfo } from './channel.js';
4
5
 
5
6
  export type RssOutboundPush = (input: {
6
7
  readonly adapterName: string;
7
8
  readonly endpointKey: string;
8
- readonly channelType: string;
9
+ readonly channelType: ChannelInfo['channelType'];
9
10
  readonly channelId: string;
10
11
  readonly content: string;
11
12
  }) => Promise<void>;