@zhin.js/plugin-rss 1.1.17 → 1.1.19

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.
@@ -1 +1 @@
1
- {"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../src/console.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,gBAAgB,EAItB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AA4BhE,wBAAgB,mBAAmB,CAAC,cAAc,CAAC,EAAE,UAAU,GAAG,gBAAgB,CAkDjF"}
1
+ {"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../src/console.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,gBAAgB,EAItB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AA4BhE,wBAAgB,mBAAmB,CAAC,cAAc,CAAC,EAAE,UAAU,GAAG,gBAAgB,CA0IjF"}
package/lib/console.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { definePluginConsoleRpc, PluginConsoleRpcError, } from 'zhin.js';
2
- import { listAllSubscriptions } from './db-store.js';
2
+ import { getRssSubs, listAllSubscriptions } from './db-store.js';
3
3
  import { cleanOldSeen, pollAllFeeds } from './poll.js';
4
4
  import { rssRuntimeToken } from './runtime.js';
5
5
  function sanitizeFeedUrl(rawUrl) {
@@ -44,6 +44,85 @@ export function createRssConsoleRpc(defaultRuntime) {
44
44
  },
45
45
  },
46
46
  actions: {
47
+ 'add-subscription': {
48
+ page: 'index',
49
+ requiredPermissions: ['rss:write'],
50
+ async handler(input, call) {
51
+ const runtime = resolveRssRuntime(call, defaultRuntime);
52
+ const url = typeof input.url === 'string' ? input.url.trim() : '';
53
+ let parsedUrl;
54
+ try {
55
+ parsedUrl = new URL(url);
56
+ if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') {
57
+ throw new Error('invalid protocol');
58
+ }
59
+ }
60
+ catch {
61
+ throw new PluginConsoleRpcError('invalid_input', '请提供有效的 HTTP/HTTPS RSS 订阅源 URL');
62
+ }
63
+ const title = typeof input.title === 'string' && input.title.trim()
64
+ ? input.title.trim()
65
+ : parsedUrl.hostname;
66
+ const adapter = typeof input.adapter === 'string' && input.adapter.trim()
67
+ ? input.adapter.trim()
68
+ : 'sandbox';
69
+ const targetType = input.targetType === 'private' ? 'private' : 'group';
70
+ const targetId = typeof input.targetId === 'string' && input.targetId.trim()
71
+ ? input.targetId.trim()
72
+ : 'console';
73
+ const Subs = getRssSubs(runtime.db);
74
+ if (!Subs) {
75
+ throw new PluginConsoleRpcError('unavailable', 'RSS 订阅表尚未初始化');
76
+ }
77
+ await Subs.insert({
78
+ url,
79
+ feed_title: title,
80
+ adapter_name: adapter,
81
+ endpoint_id: adapter,
82
+ channel_type: targetType,
83
+ channel_id: targetId,
84
+ creator_id: 'console',
85
+ creator_name: 'Console',
86
+ created_at: new Date().toISOString(),
87
+ });
88
+ return {
89
+ ok: true,
90
+ url,
91
+ title,
92
+ adapter,
93
+ targetType,
94
+ targetId,
95
+ message: `已添加 RSS 订阅:${title} (${url})`,
96
+ };
97
+ },
98
+ },
99
+ 'remove-subscription': {
100
+ page: 'index',
101
+ requiredPermissions: ['rss:write'],
102
+ async handler(input, call) {
103
+ const runtime = resolveRssRuntime(call, defaultRuntime);
104
+ const url = typeof input.url === 'string' ? input.url.trim() : '';
105
+ const id = typeof input.id === 'string' ? input.id.trim() : '';
106
+ if (!url && !id) {
107
+ throw new PluginConsoleRpcError('invalid_input', '请提供要移除的 RSS 订阅 URL 或 ID');
108
+ }
109
+ const Subs = getRssSubs(runtime.db);
110
+ if (!Subs) {
111
+ throw new PluginConsoleRpcError('unavailable', 'RSS 订阅表尚未初始化');
112
+ }
113
+ if (url) {
114
+ await Subs.delete().where({ url });
115
+ }
116
+ else {
117
+ await Subs.delete().where({ id });
118
+ }
119
+ return {
120
+ ok: true,
121
+ url: url || id,
122
+ message: `已移除 RSS 订阅:${url || id}`,
123
+ };
124
+ },
125
+ },
47
126
  'poll-now': {
48
127
  page: 'index',
49
128
  requiredPermissions: ['rss:write'],
@@ -67,7 +146,15 @@ export function createRssConsoleRpc(defaultRuntime) {
67
146
  const methods = rpc.methods;
68
147
  const origGet = methods.get.bind(methods);
69
148
  const origHas = methods.has.bind(methods);
70
- const normalizeKey = (key) => key === 'pollNow' ? 'poll-now' : key === 'cleanSeen' ? 'clean-seen' : key;
149
+ const normalizeKey = (key) => key === 'pollNow'
150
+ ? 'poll-now'
151
+ : key === 'cleanSeen'
152
+ ? 'clean-seen'
153
+ : key === 'addSubscription'
154
+ ? 'add-subscription'
155
+ : key === 'removeSubscription'
156
+ ? 'remove-subscription'
157
+ : key;
71
158
  methods.get = (key) => origGet(normalizeKey(key));
72
159
  methods.has = (key) => origHas(normalizeKey(key));
73
160
  return rpc;
@@ -1 +1 @@
1
- {"version":3,"file":"console.js","sourceRoot":"","sources":["../src/console.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"console.js","sourceRoot":"","sources":["../src/console.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/plugin-rss",
3
- "version": "1.1.17",
3
+ "version": "1.1.19",
4
4
  "description": "RSS/Atom feed subscription plugin for Zhin.js (Plugin Runtime)",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -42,25 +42,25 @@
42
42
  "license": "MIT",
43
43
  "dependencies": {
44
44
  "rss-parser": "^3.13.0",
45
- "@zhin.js/im-contract": "1.1.13",
46
- "@zhin.js/console-contract": "1.1.4",
47
- "@zhin.js/page": "1.1.16",
48
- "@zhin.js/skill": "1.1.15",
49
- "@zhin.js/tool": "1.1.17"
45
+ "@zhin.js/console-contract": "1.1.5",
46
+ "@zhin.js/page": "1.1.17",
47
+ "@zhin.js/skill": "1.1.16",
48
+ "@zhin.js/tool": "1.1.18",
49
+ "@zhin.js/im-contract": "1.1.13"
50
50
  },
51
51
  "devDependencies": {
52
52
  "typescript": "^6.0.3",
53
53
  "vitest": "^4.1.10",
54
54
  "zod": "^4.4.3",
55
- "zhin.js": "1.1.23"
55
+ "zhin.js": "1.1.25"
56
56
  },
57
57
  "peerDependencies": {
58
58
  "zod": "^4.0.0",
59
- "@zhin.js/page": "^1.1.16",
60
- "@zhin.js/skill": "^1.1.15",
61
- "@zhin.js/tool": "^1.1.17",
62
- "zhin.js": "^1.1.23",
63
- "@zhin.js/command": "^1.1.16"
59
+ "@zhin.js/page": "^1.1.17",
60
+ "@zhin.js/tool": "^1.1.18",
61
+ "@zhin.js/skill": "^1.1.16",
62
+ "@zhin.js/command": "^1.1.17",
63
+ "zhin.js": "^1.1.25"
64
64
  },
65
65
  "peerDependenciesMeta": {
66
66
  "@zhin.js/command": {
@@ -1,5 +1,5 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
- import { definePage, createDeclarativePage } from '@zhin.js/console-contract';
2
+ import { definePage, definePageBlueprint } from '@zhin.js/console-contract';
3
3
  export const meta = definePage({
4
4
  title: 'RSS 订阅',
5
5
  titleI18n: { en: 'RSS Subscriptions' },
@@ -7,7 +7,7 @@ export const meta = definePage({
7
7
  order: 52,
8
8
  requiredPermissions: ['rss:read'],
9
9
  });
10
- export default createDeclarativePage({
10
+ export default definePageBlueprint({
11
11
  title: { zh: 'RSS 订阅', en: 'RSS Subscriptions' },
12
12
  description: {
13
13
  zh: '管理 RSS/Atom 订阅源、轮询频率与已读缓存',
@@ -32,19 +32,73 @@ export default createDeclarativePage({
32
32
  ],
33
33
  actions: [
34
34
  {
35
- name: 'poll-now',
36
- label: { zh: '立即轮询', en: 'Poll now' },
35
+ name: 'addSubscription',
36
+ label: { zh: '添加订阅', en: 'Add Subscription' },
37
37
  variant: 'primary',
38
+ fields: [
39
+ {
40
+ key: 'url',
41
+ label: { zh: 'RSS 订阅源 URL', en: 'RSS Feed URL' },
42
+ type: 'text',
43
+ required: true,
44
+ },
45
+ {
46
+ key: 'title',
47
+ label: { zh: '订阅名称', en: 'Feed Title' },
48
+ type: 'text',
49
+ },
50
+ {
51
+ key: 'adapter',
52
+ label: { zh: '推送平台', en: 'Adapter' },
53
+ type: 'text',
54
+ defaultValue: 'sandbox',
55
+ },
56
+ {
57
+ key: 'targetType',
58
+ label: { zh: '目标类型', en: 'Target Type' },
59
+ type: 'select',
60
+ defaultValue: 'group',
61
+ options: [
62
+ { value: 'group', label: { zh: '群聊 (group)', en: 'Group' } },
63
+ { value: 'private', label: { zh: '私聊 (private)', en: 'Private' } },
64
+ ],
65
+ },
66
+ {
67
+ key: 'targetId',
68
+ label: { zh: '推送目标 ID', en: 'Target ID' },
69
+ type: 'text',
70
+ defaultValue: 'console',
71
+ },
72
+ ],
73
+ },
74
+ {
75
+ name: 'removeSubscription',
76
+ label: { zh: '移除订阅', en: 'Remove Subscription' },
77
+ variant: 'danger',
78
+ fields: [
79
+ {
80
+ key: 'url',
81
+ label: { zh: 'RSS 订阅源 URL', en: 'RSS Feed URL' },
82
+ type: 'text',
83
+ required: true,
84
+ },
85
+ ],
86
+ },
87
+ {
88
+ name: 'pollNow',
89
+ label: { zh: '立即轮询', en: 'Poll Now' },
90
+ variant: 'secondary',
38
91
  },
39
92
  {
40
93
  name: 'clean-seen',
41
94
  label: { zh: '清理已读缓存', en: 'Clean seen cache' },
42
- variant: 'secondary',
95
+ variant: 'ghost',
43
96
  },
44
97
  ],
45
98
  sections: [
46
99
  {
47
100
  id: 'subscriptions',
101
+ layout: 'table',
48
102
  title: { zh: '当前订阅列表', en: 'Active Subscriptions' },
49
103
  emptyText: { zh: '暂无 RSS 订阅', en: 'No RSS subscriptions' },
50
104
  items: 'subscriptions',
@@ -59,11 +113,11 @@ export default createDeclarativePage({
59
113
  {
60
114
  id: 'config',
61
115
  title: { zh: '配置详情', en: 'Configuration Details' },
62
- entries: (data) => ({
63
- pollCron: data.pollCron,
64
- maxItemsPerPoll: String(data.maxItemsPerPoll),
65
- fetchTimeoutMs: `${data.fetchTimeoutMs} ms`,
66
- }),
116
+ entries: [
117
+ { label: 'pollCron', dataKey: 'pollCron' },
118
+ { label: 'maxItemsPerPoll', dataKey: 'maxItemsPerPoll' },
119
+ { label: 'fetchTimeoutMs', value: { $format: '{0} ms', args: ['fetchTimeoutMs'] } },
120
+ ],
67
121
  },
68
122
  ],
69
123
  });
@@ -1,4 +1,4 @@
1
- import { definePage, createDeclarativePage } from '@zhin.js/console-contract';
1
+ import { definePage, definePageBlueprint } from '@zhin.js/console-contract';
2
2
 
3
3
  export interface RssSubscriptionItem {
4
4
  readonly id: string;
@@ -29,7 +29,7 @@ export const meta = definePage({
29
29
  requiredPermissions: ['rss:read'],
30
30
  });
31
31
 
32
- export default createDeclarativePage<RssConsoleStatus>({
32
+ export default definePageBlueprint<RssConsoleStatus>({
33
33
  title: { zh: 'RSS 订阅', en: 'RSS Subscriptions' },
34
34
  description: {
35
35
  zh: '管理 RSS/Atom 订阅源、轮询频率与已读缓存',
@@ -54,19 +54,73 @@ export default createDeclarativePage<RssConsoleStatus>({
54
54
  ],
55
55
  actions: [
56
56
  {
57
- name: 'poll-now',
58
- label: { zh: '立即轮询', en: 'Poll now' },
57
+ name: 'addSubscription',
58
+ label: { zh: '添加订阅', en: 'Add Subscription' },
59
59
  variant: 'primary',
60
+ fields: [
61
+ {
62
+ key: 'url',
63
+ label: { zh: 'RSS 订阅源 URL', en: 'RSS Feed URL' },
64
+ type: 'text',
65
+ required: true,
66
+ },
67
+ {
68
+ key: 'title',
69
+ label: { zh: '订阅名称', en: 'Feed Title' },
70
+ type: 'text',
71
+ },
72
+ {
73
+ key: 'adapter',
74
+ label: { zh: '推送平台', en: 'Adapter' },
75
+ type: 'text',
76
+ defaultValue: 'sandbox',
77
+ },
78
+ {
79
+ key: 'targetType',
80
+ label: { zh: '目标类型', en: 'Target Type' },
81
+ type: 'select',
82
+ defaultValue: 'group',
83
+ options: [
84
+ { value: 'group', label: { zh: '群聊 (group)', en: 'Group' } },
85
+ { value: 'private', label: { zh: '私聊 (private)', en: 'Private' } },
86
+ ],
87
+ },
88
+ {
89
+ key: 'targetId',
90
+ label: { zh: '推送目标 ID', en: 'Target ID' },
91
+ type: 'text',
92
+ defaultValue: 'console',
93
+ },
94
+ ],
95
+ },
96
+ {
97
+ name: 'removeSubscription',
98
+ label: { zh: '移除订阅', en: 'Remove Subscription' },
99
+ variant: 'danger',
100
+ fields: [
101
+ {
102
+ key: 'url',
103
+ label: { zh: 'RSS 订阅源 URL', en: 'RSS Feed URL' },
104
+ type: 'text',
105
+ required: true,
106
+ },
107
+ ],
108
+ },
109
+ {
110
+ name: 'pollNow',
111
+ label: { zh: '立即轮询', en: 'Poll Now' },
112
+ variant: 'secondary',
60
113
  },
61
114
  {
62
115
  name: 'clean-seen',
63
116
  label: { zh: '清理已读缓存', en: 'Clean seen cache' },
64
- variant: 'secondary',
117
+ variant: 'ghost',
65
118
  },
66
119
  ],
67
120
  sections: [
68
121
  {
69
122
  id: 'subscriptions',
123
+ layout: 'table',
70
124
  title: { zh: '当前订阅列表', en: 'Active Subscriptions' },
71
125
  emptyText: { zh: '暂无 RSS 订阅', en: 'No RSS subscriptions' },
72
126
  items: 'subscriptions',
@@ -81,11 +135,11 @@ export default createDeclarativePage<RssConsoleStatus>({
81
135
  {
82
136
  id: 'config',
83
137
  title: { zh: '配置详情', en: 'Configuration Details' },
84
- entries: (data) => ({
85
- pollCron: data.pollCron,
86
- maxItemsPerPoll: String(data.maxItemsPerPoll),
87
- fetchTimeoutMs: `${data.fetchTimeoutMs} ms`,
88
- }),
138
+ entries: [
139
+ { label: 'pollCron', dataKey: 'pollCron' },
140
+ { label: 'maxItemsPerPoll', dataKey: 'maxItemsPerPoll' },
141
+ { label: 'fetchTimeoutMs', value: { $format: '{0} ms', args: ['fetchTimeoutMs'] } },
142
+ ],
89
143
  },
90
144
  ],
91
145
  });
package/plugin.js CHANGED
@@ -52,9 +52,9 @@ export default definePlugin({
52
52
  ],
53
53
  injects: [databaseHostToken, outboundHostToken, scheduleHostToken, projectLocaleToken],
54
54
  features: {
55
- commands: ['rss-add', 'rss-check', 'rss-list', 'rss-preview', 'rss-remove'],
55
+ commands: ['rss-add/[url]', 'rss-check/[[url]]', 'rss-list', 'rss-preview/[url]', 'rss-remove/[url]'],
56
56
  skills: ['rss'],
57
- tools: ['rss_list_subscriptions', 'rss_preview_feed'],
57
+ tools: ['skill/rss/rss_list_subscriptions', 'skill/rss/rss_preview_feed'],
58
58
  pages: ['index'],
59
59
  },
60
60
  }),
@@ -85,10 +85,17 @@ export default definePlugin({
85
85
  await run();
86
86
  };
87
87
  }
88
+ let projectLocale;
89
+ try {
90
+ projectLocale = context.resources.use(projectLocaleToken);
91
+ }
92
+ catch {
93
+ projectLocale = undefined;
94
+ }
88
95
  const runtime = rssRuntimeStore.provide(context, Object.freeze({
89
96
  db,
90
97
  migrationScopes,
91
- locale: resolveLocale(context.resources.use(projectLocaleToken)),
98
+ locale: resolveLocale(projectLocale),
92
99
  config: Object.freeze({ ...config }),
93
100
  outbound: outboundPush,
94
101
  }));
package/src/console.ts CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  type PluginConsoleRpcInput,
8
8
  type PluginConsoleRpcJson,
9
9
  } from 'zhin.js';
10
- import { listAllSubscriptions } from './db-store.js';
10
+ import { getRssSubs, listAllSubscriptions } from './db-store.js';
11
11
  import { cleanOldSeen, pollAllFeeds } from './poll.js';
12
12
  import { rssRuntimeToken, type RssRuntime } from './runtime.js';
13
13
 
@@ -58,6 +58,86 @@ export function createRssConsoleRpc(defaultRuntime?: RssRuntime): PluginConsoleR
58
58
  },
59
59
  },
60
60
  actions: {
61
+ 'add-subscription': {
62
+ page: 'index',
63
+ requiredPermissions: ['rss:write'],
64
+ async handler(input: PluginConsoleRpcInput, call: PluginConsoleRpcCall): Promise<PluginConsoleRpcJson> {
65
+ const runtime = resolveRssRuntime(call, defaultRuntime);
66
+ const url = typeof input.url === 'string' ? input.url.trim() : '';
67
+ let parsedUrl: URL;
68
+ try {
69
+ parsedUrl = new URL(url);
70
+ if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') {
71
+ throw new Error('invalid protocol');
72
+ }
73
+ } catch {
74
+ throw new PluginConsoleRpcError('invalid_input', '请提供有效的 HTTP/HTTPS RSS 订阅源 URL');
75
+ }
76
+ const title =
77
+ typeof input.title === 'string' && input.title.trim()
78
+ ? input.title.trim()
79
+ : parsedUrl.hostname;
80
+ const adapter =
81
+ typeof input.adapter === 'string' && input.adapter.trim()
82
+ ? input.adapter.trim()
83
+ : 'sandbox';
84
+ const targetType = input.targetType === 'private' ? 'private' : 'group';
85
+ const targetId =
86
+ typeof input.targetId === 'string' && input.targetId.trim()
87
+ ? input.targetId.trim()
88
+ : 'console';
89
+ const Subs = getRssSubs(runtime.db);
90
+ if (!Subs) {
91
+ throw new PluginConsoleRpcError('unavailable', 'RSS 订阅表尚未初始化');
92
+ }
93
+ await Subs.insert({
94
+ url,
95
+ feed_title: title,
96
+ adapter_name: adapter,
97
+ endpoint_id: adapter,
98
+ channel_type: targetType,
99
+ channel_id: targetId,
100
+ creator_id: 'console',
101
+ creator_name: 'Console',
102
+ created_at: new Date().toISOString(),
103
+ });
104
+ return {
105
+ ok: true,
106
+ url,
107
+ title,
108
+ adapter,
109
+ targetType,
110
+ targetId,
111
+ message: `已添加 RSS 订阅:${title} (${url})`,
112
+ };
113
+ },
114
+ },
115
+ 'remove-subscription': {
116
+ page: 'index',
117
+ requiredPermissions: ['rss:write'],
118
+ async handler(input: PluginConsoleRpcInput, call: PluginConsoleRpcCall): Promise<PluginConsoleRpcJson> {
119
+ const runtime = resolveRssRuntime(call, defaultRuntime);
120
+ const url = typeof input.url === 'string' ? input.url.trim() : '';
121
+ const id = typeof input.id === 'string' ? input.id.trim() : '';
122
+ if (!url && !id) {
123
+ throw new PluginConsoleRpcError('invalid_input', '请提供要移除的 RSS 订阅 URL 或 ID');
124
+ }
125
+ const Subs = getRssSubs(runtime.db);
126
+ if (!Subs) {
127
+ throw new PluginConsoleRpcError('unavailable', 'RSS 订阅表尚未初始化');
128
+ }
129
+ if (url) {
130
+ await Subs.delete().where({ url });
131
+ } else {
132
+ await Subs.delete().where({ id });
133
+ }
134
+ return {
135
+ ok: true,
136
+ url: url || id,
137
+ message: `已移除 RSS 订阅:${url || id}`,
138
+ };
139
+ },
140
+ },
61
141
  'poll-now': {
62
142
  page: 'index',
63
143
  requiredPermissions: ['rss:write'],
@@ -83,7 +163,15 @@ export function createRssConsoleRpc(defaultRuntime?: RssRuntime): PluginConsoleR
83
163
  const origGet = methods.get.bind(methods);
84
164
  const origHas = methods.has.bind(methods);
85
165
  const normalizeKey = (key: string) =>
86
- key === 'pollNow' ? 'poll-now' : key === 'cleanSeen' ? 'clean-seen' : key;
166
+ key === 'pollNow'
167
+ ? 'poll-now'
168
+ : key === 'cleanSeen'
169
+ ? 'clean-seen'
170
+ : key === 'addSubscription'
171
+ ? 'add-subscription'
172
+ : key === 'removeSubscription'
173
+ ? 'remove-subscription'
174
+ : key;
87
175
  methods.get = (key: string) => origGet(normalizeKey(key));
88
176
  methods.has = (key: string) => origHas(normalizeKey(key));
89
177
  return rpc;