@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.
- package/lib/console.d.ts.map +1 -1
- package/lib/console.js +89 -2
- package/lib/console.js.map +1 -1
- package/package.json +12 -12
- package/pages/index/index.js +64 -10
- package/pages/index/index.ts +64 -10
- package/plugin.js +10 -3
- package/src/console.ts +90 -2
package/lib/console.d.ts.map
CHANGED
|
@@ -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,
|
|
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'
|
|
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;
|
package/lib/console.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"console.js","sourceRoot":"","sources":["../src/console.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,qBAAqB,GAMtB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"console.js","sourceRoot":"","sources":["../src/console.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,qBAAqB,GAMtB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EAAE,eAAe,EAAmB,MAAM,cAAc,CAAC;AAMhE,SAAS,eAAe,CAAC,MAAc;IACrC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;QAC/B,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACvC,MAAM,CAAC,QAAQ,GAAG,EAAE,CAAC;YACrB,MAAM,CAAC,QAAQ,GAAG,EAAE,CAAC;YACrB,OAAO,MAAM,CAAC,QAAQ,EAAE,CAAC;QAC3B,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC;IAChB,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,IAA0B,EAAE,QAAqB;IAC1E,MAAM,OAAO,GAAI,IAAI,CAAC,OAAwC,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,IAAI,QAAQ,CAAC;IACnG,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,qBAAqB,CAAC,aAAa,EAAE,gCAAgC,CAAC,CAAC;IACnF,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,cAA2B;IAC7D,MAAM,GAAG,GAAG,sBAAsB,CAAC;QACjC,MAAM,EAAE;YACN,IAAI,EAAE,OAAO;YACb,mBAAmB,EAAE,CAAC,UAAU,CAAC;YACjC,KAAK,CAAC,OAAO,CAAC,MAA6B,EAAE,IAA0B;gBACrE,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;gBACxD,MAAM,gBAAgB,GAAG,MAAM,oBAAoB,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;gBAChE,OAAO;oBACL,iBAAiB,EAAE,gBAAgB,CAAC,MAAM;oBAC1C,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ;oBACjC,eAAe,EAAE,OAAO,CAAC,MAAM,CAAC,eAAe,IAAI,OAAO,CAAC,MAAM,CAAC,QAAQ;oBAC1E,cAAc,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,OAAO;oBACvE,aAAa,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;wBAC1D,GAAG,GAAG;wBACN,GAAG,EAAE,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC;qBAC9B,CAAC,CAAC;iBAC+B,CAAC;YACvC,CAAC;SACF;QACD,OAAO,EAAE;YACP,kBAAkB,EAAE;gBAClB,IAAI,EAAE,OAAO;gBACb,mBAAmB,EAAE,CAAC,WAAW,CAAC;gBAClC,KAAK,CAAC,OAAO,CAAC,KAA4B,EAAE,IAA0B;oBACpE,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;oBACxD,MAAM,GAAG,GAAG,OAAO,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAClE,IAAI,SAAc,CAAC;oBACnB,IAAI,CAAC;wBACH,SAAS,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;wBACzB,IAAI,SAAS,CAAC,QAAQ,KAAK,OAAO,IAAI,SAAS,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;4BACtE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;wBACtC,CAAC;oBACH,CAAC;oBAAC,MAAM,CAAC;wBACP,MAAM,IAAI,qBAAqB,CAAC,eAAe,EAAE,+BAA+B,CAAC,CAAC;oBACpF,CAAC;oBACD,MAAM,KAAK,GACT,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE;wBACnD,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE;wBACpB,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC;oBACzB,MAAM,OAAO,GACX,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE;wBACvD,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE;wBACtB,CAAC,CAAC,SAAS,CAAC;oBAChB,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;oBACxE,MAAM,QAAQ,GACZ,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE;wBACzD,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE;wBACvB,CAAC,CAAC,SAAS,CAAC;oBAChB,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;oBACpC,IAAI,CAAC,IAAI,EAAE,CAAC;wBACV,MAAM,IAAI,qBAAqB,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;oBACjE,CAAC;oBACD,MAAM,IAAI,CAAC,MAAM,CAAC;wBAChB,GAAG;wBACH,UAAU,EAAE,KAAK;wBACjB,YAAY,EAAE,OAAO;wBACrB,WAAW,EAAE,OAAO;wBACpB,YAAY,EAAE,UAAU;wBACxB,UAAU,EAAE,QAAQ;wBACpB,UAAU,EAAE,SAAS;wBACrB,YAAY,EAAE,SAAS;wBACvB,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;qBACrC,CAAC,CAAC;oBACH,OAAO;wBACL,EAAE,EAAE,IAAI;wBACR,GAAG;wBACH,KAAK;wBACL,OAAO;wBACP,UAAU;wBACV,QAAQ;wBACR,OAAO,EAAE,cAAc,KAAK,KAAK,GAAG,GAAG;qBACxC,CAAC;gBACJ,CAAC;aACF;YACD,qBAAqB,EAAE;gBACrB,IAAI,EAAE,OAAO;gBACb,mBAAmB,EAAE,CAAC,WAAW,CAAC;gBAClC,KAAK,CAAC,OAAO,CAAC,KAA4B,EAAE,IAA0B;oBACpE,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;oBACxD,MAAM,GAAG,GAAG,OAAO,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAClE,MAAM,EAAE,GAAG,OAAO,KAAK,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC/D,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;wBAChB,MAAM,IAAI,qBAAqB,CAAC,eAAe,EAAE,yBAAyB,CAAC,CAAC;oBAC9E,CAAC;oBACD,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;oBACpC,IAAI,CAAC,IAAI,EAAE,CAAC;wBACV,MAAM,IAAI,qBAAqB,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;oBACjE,CAAC;oBACD,IAAI,GAAG,EAAE,CAAC;wBACR,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;oBACrC,CAAC;yBAAM,CAAC;wBACN,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;oBACpC,CAAC;oBACD,OAAO;wBACL,EAAE,EAAE,IAAI;wBACR,GAAG,EAAE,GAAG,IAAI,EAAE;wBACd,OAAO,EAAE,cAAc,GAAG,IAAI,EAAE,EAAE;qBACnC,CAAC;gBACJ,CAAC;aACF;YACD,UAAU,EAAE;gBACV,IAAI,EAAE,OAAO;gBACb,mBAAmB,EAAE,CAAC,WAAW,CAAC;gBAClC,KAAK,CAAC,OAAO,CAAC,MAA6B,EAAE,IAA0B;oBACrE,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;oBACxD,MAAM,YAAY,CAAC,OAAO,CAAC,CAAC;oBAC5B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;gBAC5C,CAAC;aACF;YACD,YAAY,EAAE;gBACZ,IAAI,EAAE,OAAO;gBACb,mBAAmB,EAAE,CAAC,WAAW,CAAC;gBAClC,KAAK,CAAC,OAAO,CAAC,MAA6B,EAAE,IAA0B;oBACrE,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;oBACxD,MAAM,YAAY,CAAC,OAAO,CAAC,CAAC;oBAC5B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;gBAC7C,CAAC;aACF;SACF;KACF,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,GAAG,CAAC,OAAwD,CAAC;IAC7E,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,YAAY,GAAG,CAAC,GAAW,EAAE,EAAE,CACnC,GAAG,KAAK,SAAS;QACf,CAAC,CAAC,UAAU;QACZ,CAAC,CAAC,GAAG,KAAK,WAAW;YACnB,CAAC,CAAC,YAAY;YACd,CAAC,CAAC,GAAG,KAAK,iBAAiB;gBACzB,CAAC,CAAC,kBAAkB;gBACpB,CAAC,CAAC,GAAG,KAAK,oBAAoB;oBAC5B,CAAC,CAAC,qBAAqB;oBACvB,CAAC,CAAC,GAAG,CAAC;IAChB,OAAO,CAAC,GAAG,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1D,OAAO,GAAG,CAAC;AACb,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/plugin-rss",
|
|
3
|
-
"version": "1.1.
|
|
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/
|
|
46
|
-
"@zhin.js/
|
|
47
|
-
"@zhin.js/
|
|
48
|
-
"@zhin.js/
|
|
49
|
-
"@zhin.js/
|
|
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.
|
|
55
|
+
"zhin.js": "1.1.25"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
58
|
"zod": "^4.0.0",
|
|
59
|
-
"@zhin.js/page": "^1.1.
|
|
60
|
-
"@zhin.js/
|
|
61
|
-
"@zhin.js/
|
|
62
|
-
"zhin.js": "^1.1.
|
|
63
|
-
"
|
|
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": {
|
package/pages/index/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
-
import { definePage,
|
|
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
|
|
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: '
|
|
36
|
-
label: { zh: '
|
|
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: '
|
|
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:
|
|
63
|
-
pollCron:
|
|
64
|
-
maxItemsPerPoll:
|
|
65
|
-
fetchTimeoutMs:
|
|
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
|
});
|
package/pages/index/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { definePage,
|
|
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
|
|
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: '
|
|
58
|
-
label: { zh: '
|
|
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: '
|
|
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:
|
|
85
|
-
pollCron:
|
|
86
|
-
maxItemsPerPoll:
|
|
87
|
-
fetchTimeoutMs:
|
|
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(
|
|
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'
|
|
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;
|