@zhin.js/plugin-rss 1.1.9 → 1.1.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.
- package/README.md +8 -0
- package/commands/rss-add/[url]/index.js +12 -10
- package/commands/rss-add/[url]/index.ts +12 -10
- package/commands/rss-check/[[url]]/index.js +8 -7
- package/commands/rss-check/[[url]]/index.ts +8 -7
- package/commands/rss-list/index.js +9 -7
- package/commands/rss-list/index.ts +9 -7
- package/commands/rss-preview/[url]/index.js +7 -6
- package/commands/rss-preview/[url]/index.ts +7 -6
- package/commands/rss-remove/[url]/index.js +8 -7
- package/commands/rss-remove/[url]/index.ts +8 -7
- package/lib/admin-i18n.d.ts +219 -0
- package/lib/admin-i18n.d.ts.map +1 -0
- package/lib/admin-i18n.js +216 -0
- package/lib/admin-i18n.js.map +1 -0
- package/lib/admin-tasks.d.ts +40 -2
- package/lib/admin-tasks.d.ts.map +1 -1
- package/lib/admin-tasks.js +99 -72
- package/lib/admin-tasks.js.map +1 -1
- package/lib/channel.d.ts +2 -1
- package/lib/channel.d.ts.map +1 -1
- package/lib/channel.js +3 -3
- package/lib/channel.js.map +1 -1
- package/lib/feed.d.ts +2 -1
- package/lib/feed.d.ts.map +1 -1
- package/lib/feed.js +6 -5
- package/lib/feed.js.map +1 -1
- package/lib/i18n.d.ts +2 -0
- package/lib/i18n.d.ts.map +1 -0
- package/lib/i18n.js +168 -0
- package/lib/i18n.js.map +1 -0
- package/lib/poll.d.ts +3 -1
- package/lib/poll.d.ts.map +1 -1
- package/lib/poll.js +23 -18
- package/lib/poll.js.map +1 -1
- package/lib/quiet-hours.d.ts +5 -0
- package/lib/quiet-hours.d.ts.map +1 -1
- package/lib/quiet-hours.js +9 -4
- package/lib/quiet-hours.js.map +1 -1
- package/lib/runtime.d.ts +3 -0
- package/lib/runtime.d.ts.map +1 -1
- package/lib/runtime.js.map +1 -1
- package/lib/storage.d.ts.map +1 -1
- package/lib/storage.js +6 -5
- package/lib/storage.js.map +1 -1
- package/package.json +7 -7
- package/plugin.js +6 -2
- package/schema.json +6 -1
- package/skills/rss/tools/rss_list_subscriptions/index.js +4 -3
- package/skills/rss/tools/rss_list_subscriptions/index.ts +4 -3
- package/skills/rss/tools/rss_preview_feed/index.js +4 -3
- package/skills/rss/tools/rss_preview_feed/index.ts +4 -3
- package/src/admin-i18n.ts +218 -0
- package/src/admin-tasks.ts +95 -72
- package/src/channel.ts +4 -2
- package/src/feed.ts +7 -5
- package/src/i18n.ts +168 -0
- package/src/poll.ts +24 -18
- package/src/quiet-hours.ts +11 -4
- package/src/runtime.ts +3 -0
- package/src/storage.ts +6 -5
package/README.md
CHANGED
|
@@ -162,3 +162,11 @@ MIT
|
|
|
162
162
|
### 事务化任务存储
|
|
163
163
|
|
|
164
164
|
提醒与管理员 RSS 的任务、认领、操作回执和文章明细使用独立数据表,在一个事务中提交;原 CAS JSON 只用于首次迁移。支持 SQLite、MySQL、PostgreSQL,升级须完整重启,不能与旧版本进程混写。`unknown` 投递仍不会自动重试。迁移和字段说明见[结构化存储](../../../docs/operations/structured-storage.md)。
|
|
165
|
+
|
|
166
|
+
## Language / 语言
|
|
167
|
+
|
|
168
|
+
命令和工具的提示使用当前操作语言,源站文章标题和正文保持原样。聊天订阅保存创建者当时的语言;管理员订阅保存项目语言。轮询按每个订阅保存的语言生成通知或静默摘要,更改个人/项目语言不会重写既有订阅;暂停、恢复和进程重启仍保持原语言。旧数据没有语言字段时保持中文。
|
|
169
|
+
|
|
170
|
+
Console 的界面语言仅影响任务列表、字段说明和操作错误;不参与 requestId 指纹,不改变任务版本或通知语言。新状态使用独立文案 key 展示,旧的文字 detail 原样保留。
|
|
171
|
+
|
|
172
|
+
Notifications use the language captured at subscription creation. Feed content remains in its original language. Changing Console language changes presentation only, including idempotent responses; it does not change delivery settings or repeat an operation.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
+
import { rssMessages as t } from "../../../lib/i18n.js";
|
|
2
3
|
import { defineCommand } from 'zhin.js/command';
|
|
3
4
|
import { channelSourceError, extractChannelInfo, subscriptionScope } from "../../../lib/channel.js";
|
|
4
5
|
import { getRssSubs } from "../../../lib/db-store.js";
|
|
@@ -6,33 +7,33 @@ import { fetchFeed, resolveRssConfig } from "../../../lib/feed.js";
|
|
|
6
7
|
import { markItemsSeen } from "../../../lib/poll.js";
|
|
7
8
|
import { rssRuntimeToken } from "../../../lib/runtime.js";
|
|
8
9
|
export default defineCommand({
|
|
9
|
-
description: '订阅一个 RSS/Atom 源',
|
|
10
|
+
description: '订阅一个 RSS/Atom 源', descriptionI18n: { en: "Subscribe to an RSS/Atom feed" },
|
|
10
11
|
params: { url: { type: 'string' } },
|
|
11
|
-
async execute({ params, config, input, use }) {
|
|
12
|
+
async execute({ params, config, input, use, locale }) {
|
|
12
13
|
const runtime = use(rssRuntimeToken);
|
|
13
14
|
const Subs = getRssSubs(runtime.db);
|
|
14
15
|
if (!Subs)
|
|
15
|
-
return
|
|
16
|
+
return t(locale, 'databaseRetry');
|
|
16
17
|
const url = String(params.url ?? '').trim();
|
|
17
18
|
if (!url)
|
|
18
|
-
return
|
|
19
|
+
return t(locale, 'urlRequired');
|
|
19
20
|
if (!/^https?:\/\//i.test(url))
|
|
20
|
-
return
|
|
21
|
+
return t(locale, 'httpRequired');
|
|
21
22
|
const channel = extractChannelInfo(input);
|
|
22
23
|
if (!channel)
|
|
23
|
-
return channelSourceError(input);
|
|
24
|
+
return channelSourceError(input, locale);
|
|
24
25
|
const cfg = resolveRssConfig(config);
|
|
25
26
|
const existing = await Subs.select().where({
|
|
26
27
|
url,
|
|
27
28
|
...subscriptionScope(channel),
|
|
28
29
|
});
|
|
29
30
|
if (existing.length > 0)
|
|
30
|
-
return '
|
|
31
|
+
return t(locale, 'existing');
|
|
31
32
|
const currentSubs = await Subs.select().where({
|
|
32
33
|
...subscriptionScope(channel),
|
|
33
34
|
});
|
|
34
35
|
if (currentSubs.length >= cfg.maxPerGroup) {
|
|
35
|
-
return
|
|
36
|
+
return t(locale, 'limit', { max: cfg.maxPerGroup });
|
|
36
37
|
}
|
|
37
38
|
let feedTitle = '';
|
|
38
39
|
try {
|
|
@@ -41,7 +42,7 @@ export default defineCommand({
|
|
|
41
42
|
await markItemsSeen(runtime, url, items);
|
|
42
43
|
}
|
|
43
44
|
catch (e) {
|
|
44
|
-
return
|
|
45
|
+
return t(locale, 'loadFailed', { error: e.message });
|
|
45
46
|
}
|
|
46
47
|
await Subs.insert({
|
|
47
48
|
url,
|
|
@@ -53,7 +54,8 @@ export default defineCommand({
|
|
|
53
54
|
creator_id: channel.senderId,
|
|
54
55
|
creator_name: channel.senderName,
|
|
55
56
|
created_at: new Date().toISOString(),
|
|
57
|
+
locale,
|
|
56
58
|
});
|
|
57
|
-
return
|
|
59
|
+
return t(locale, 'added', { feed: feedTitle || url });
|
|
58
60
|
},
|
|
59
61
|
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { rssMessages as t } from '../../../src/i18n.js';
|
|
1
2
|
import { defineCommand } from 'zhin.js/command';
|
|
2
3
|
import { channelSourceError, extractChannelInfo, subscriptionScope } from '../../../src/channel.js';
|
|
3
4
|
import { getRssSubs } from '../../../src/db-store.js';
|
|
@@ -6,32 +7,32 @@ import { markItemsSeen } from '../../../src/poll.js';
|
|
|
6
7
|
import { rssRuntimeToken } from '../../../src/runtime.js';
|
|
7
8
|
|
|
8
9
|
export default defineCommand<RssConfig>({
|
|
9
|
-
description: '订阅一个 RSS/Atom 源',
|
|
10
|
+
description: '订阅一个 RSS/Atom 源', descriptionI18n: { en: "Subscribe to an RSS/Atom feed" },
|
|
10
11
|
params: { url: { type: 'string' } },
|
|
11
|
-
async execute({ params, config, input, use }) {
|
|
12
|
+
async execute({ params, config, input, use, locale }) {
|
|
12
13
|
const runtime = use(rssRuntimeToken);
|
|
13
14
|
const Subs = getRssSubs(runtime.db);
|
|
14
|
-
if (!Subs) return
|
|
15
|
+
if (!Subs) return t(locale, 'databaseRetry');
|
|
15
16
|
|
|
16
17
|
const url = String(params.url ?? '').trim();
|
|
17
|
-
if (!url) return
|
|
18
|
-
if (!/^https?:\/\//i.test(url)) return
|
|
18
|
+
if (!url) return t(locale, 'urlRequired');
|
|
19
|
+
if (!/^https?:\/\//i.test(url)) return t(locale, 'httpRequired');
|
|
19
20
|
|
|
20
21
|
const channel = extractChannelInfo(input);
|
|
21
|
-
if (!channel) return channelSourceError(input);
|
|
22
|
+
if (!channel) return channelSourceError(input, locale);
|
|
22
23
|
const cfg = resolveRssConfig(config);
|
|
23
24
|
|
|
24
25
|
const existing = await Subs.select().where({
|
|
25
26
|
url,
|
|
26
27
|
...subscriptionScope(channel),
|
|
27
28
|
});
|
|
28
|
-
if (existing.length > 0) return '
|
|
29
|
+
if (existing.length > 0) return t(locale, 'existing');
|
|
29
30
|
|
|
30
31
|
const currentSubs = await Subs.select().where({
|
|
31
32
|
...subscriptionScope(channel),
|
|
32
33
|
});
|
|
33
34
|
if (currentSubs.length >= cfg.maxPerGroup) {
|
|
34
|
-
return
|
|
35
|
+
return t(locale, 'limit', { max: cfg.maxPerGroup });
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
let feedTitle = '';
|
|
@@ -40,7 +41,7 @@ export default defineCommand<RssConfig>({
|
|
|
40
41
|
feedTitle = title;
|
|
41
42
|
await markItemsSeen(runtime, url, items);
|
|
42
43
|
} catch (e) {
|
|
43
|
-
return
|
|
44
|
+
return t(locale, 'loadFailed', { error: (e as Error).message });
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
await Subs.insert({
|
|
@@ -53,8 +54,9 @@ export default defineCommand<RssConfig>({
|
|
|
53
54
|
creator_id: channel.senderId,
|
|
54
55
|
creator_name: channel.senderName,
|
|
55
56
|
created_at: new Date().toISOString(),
|
|
57
|
+
locale,
|
|
56
58
|
});
|
|
57
59
|
|
|
58
|
-
return
|
|
60
|
+
return t(locale, 'added', { feed: feedTitle || url });
|
|
59
61
|
},
|
|
60
62
|
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
+
import { rssMessages as t } from "../../../lib/i18n.js";
|
|
2
3
|
import { defineCommand } from 'zhin.js/command';
|
|
3
4
|
import { channelSourceError, extractChannelInfo, subscriptionScope } from "../../../lib/channel.js";
|
|
4
5
|
import { getRssSubs } from "../../../lib/db-store.js";
|
|
@@ -6,16 +7,16 @@ import { resolveRssConfig } from "../../../lib/feed.js";
|
|
|
6
7
|
import { checkSubscriptions } from "../../../lib/poll.js";
|
|
7
8
|
import { rssRuntimeToken } from "../../../lib/runtime.js";
|
|
8
9
|
export default defineCommand({
|
|
9
|
-
description: '手动触发检查 RSS 更新',
|
|
10
|
+
description: '手动触发检查 RSS 更新', descriptionI18n: { en: "Check RSS feeds for updates now" },
|
|
10
11
|
params: { url: { type: 'string', default: '' } },
|
|
11
|
-
async execute({ params, input, use }) {
|
|
12
|
+
async execute({ params, input, use, locale }) {
|
|
12
13
|
const runtime = use(rssRuntimeToken);
|
|
13
14
|
const Subs = getRssSubs(runtime.db);
|
|
14
15
|
if (!Subs)
|
|
15
|
-
return
|
|
16
|
+
return t(locale, 'databaseUnavailable');
|
|
16
17
|
const channel = extractChannelInfo(input);
|
|
17
18
|
if (!channel)
|
|
18
|
-
return channelSourceError(input);
|
|
19
|
+
return channelSourceError(input, locale);
|
|
19
20
|
const targetUrl = String(params.url ?? '').trim();
|
|
20
21
|
let urls;
|
|
21
22
|
if (targetUrl) {
|
|
@@ -24,7 +25,7 @@ export default defineCommand({
|
|
|
24
25
|
...subscriptionScope(channel),
|
|
25
26
|
});
|
|
26
27
|
if (rows.length === 0)
|
|
27
|
-
return '
|
|
28
|
+
return t(locale, 'notSubscribed');
|
|
28
29
|
urls = [targetUrl];
|
|
29
30
|
}
|
|
30
31
|
else {
|
|
@@ -32,10 +33,10 @@ export default defineCommand({
|
|
|
32
33
|
...subscriptionScope(channel),
|
|
33
34
|
});
|
|
34
35
|
if (rows.length === 0)
|
|
35
|
-
return '
|
|
36
|
+
return t(locale, 'noSubscriptions');
|
|
36
37
|
urls = [...new Set(rows.map((r) => String(r.url ?? '')).filter(Boolean))];
|
|
37
38
|
}
|
|
38
|
-
const result = await checkSubscriptions(runtime, { urls });
|
|
39
|
+
const result = await checkSubscriptions(runtime, { urls, locale });
|
|
39
40
|
return result.text;
|
|
40
41
|
},
|
|
41
42
|
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { rssMessages as t } from '../../../src/i18n.js';
|
|
1
2
|
import { defineCommand } from 'zhin.js/command';
|
|
2
3
|
import { channelSourceError, extractChannelInfo, subscriptionScope } from '../../../src/channel.js';
|
|
3
4
|
import { getRssSubs } from '../../../src/db-store.js';
|
|
@@ -6,15 +7,15 @@ import { checkSubscriptions } from '../../../src/poll.js';
|
|
|
6
7
|
import { rssRuntimeToken } from '../../../src/runtime.js';
|
|
7
8
|
|
|
8
9
|
export default defineCommand<RssConfig>({
|
|
9
|
-
description: '手动触发检查 RSS 更新',
|
|
10
|
+
description: '手动触发检查 RSS 更新', descriptionI18n: { en: "Check RSS feeds for updates now" },
|
|
10
11
|
params: { url: { type: 'string', default: '' } },
|
|
11
|
-
async execute({ params, input, use }) {
|
|
12
|
+
async execute({ params, input, use, locale }) {
|
|
12
13
|
const runtime = use(rssRuntimeToken);
|
|
13
14
|
const Subs = getRssSubs(runtime.db);
|
|
14
|
-
if (!Subs) return
|
|
15
|
+
if (!Subs) return t(locale, 'databaseUnavailable');
|
|
15
16
|
|
|
16
17
|
const channel = extractChannelInfo(input);
|
|
17
|
-
if (!channel) return channelSourceError(input);
|
|
18
|
+
if (!channel) return channelSourceError(input, locale);
|
|
18
19
|
const targetUrl = String(params.url ?? '').trim();
|
|
19
20
|
|
|
20
21
|
let urls: string[];
|
|
@@ -23,17 +24,17 @@ export default defineCommand<RssConfig>({
|
|
|
23
24
|
url: targetUrl,
|
|
24
25
|
...subscriptionScope(channel),
|
|
25
26
|
});
|
|
26
|
-
if (rows.length === 0) return '
|
|
27
|
+
if (rows.length === 0) return t(locale, 'notSubscribed');
|
|
27
28
|
urls = [targetUrl];
|
|
28
29
|
} else {
|
|
29
30
|
const rows = await Subs.select().where({
|
|
30
31
|
...subscriptionScope(channel),
|
|
31
32
|
});
|
|
32
|
-
if (rows.length === 0) return '
|
|
33
|
+
if (rows.length === 0) return t(locale, 'noSubscriptions');
|
|
33
34
|
urls = [...new Set(rows.map((r) => String(r.url ?? '')).filter(Boolean))];
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
const result = await checkSubscriptions(runtime, { urls });
|
|
37
|
+
const result = await checkSubscriptions(runtime, { urls, locale });
|
|
37
38
|
return result.text;
|
|
38
39
|
},
|
|
39
40
|
});
|
|
@@ -1,29 +1,31 @@
|
|
|
1
1
|
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
+
import { rssMessages as t } from "../../lib/i18n.js";
|
|
2
3
|
import { defineCommand } from 'zhin.js/command';
|
|
3
4
|
import { channelSourceError, extractChannelInfo, subscriptionScope } from "../../lib/channel.js";
|
|
4
5
|
import { getRssSubs } from "../../lib/db-store.js";
|
|
5
6
|
import { resolveRssConfig } from "../../lib/feed.js";
|
|
6
7
|
import { rssRuntimeToken } from "../../lib/runtime.js";
|
|
7
8
|
export default defineCommand({
|
|
8
|
-
description: '查看当前会话的所有 RSS 订阅',
|
|
9
|
-
async execute({ config, input, use }) {
|
|
9
|
+
description: '查看当前会话的所有 RSS 订阅', descriptionI18n: { en: "List this conversation's RSS subscriptions" },
|
|
10
|
+
async execute({ config, input, use, locale, formatCommand }) {
|
|
10
11
|
const Subs = getRssSubs(use(rssRuntimeToken).db);
|
|
11
12
|
if (!Subs)
|
|
12
|
-
return
|
|
13
|
+
return t(locale, 'databaseUnavailable');
|
|
13
14
|
const channel = extractChannelInfo(input);
|
|
14
15
|
if (!channel)
|
|
15
|
-
return channelSourceError(input);
|
|
16
|
+
return channelSourceError(input, locale);
|
|
16
17
|
const cfg = resolveRssConfig(config);
|
|
17
18
|
const rows = await Subs.select().where({
|
|
18
19
|
...subscriptionScope(channel),
|
|
19
20
|
});
|
|
20
21
|
if (rows.length === 0) {
|
|
21
|
-
|
|
22
|
+
const command = formatCommand('rss-add');
|
|
23
|
+
return [t(locale, 'empty'), command ? t(locale, 'addHint', { command }) : undefined].filter(Boolean).join('\n');
|
|
22
24
|
}
|
|
23
25
|
const lines = rows.map((r, i) => {
|
|
24
|
-
const title = String(r.feed_title ||
|
|
26
|
+
const title = String(r.feed_title || t(locale, 'unknownTitle'));
|
|
25
27
|
return `${i + 1}. ${title}\n ${String(r.url ?? '')}`;
|
|
26
28
|
});
|
|
27
|
-
return
|
|
29
|
+
return t(locale, 'list', { count: rows.length, max: cfg.maxPerGroup, items: lines.join('\n') });
|
|
28
30
|
},
|
|
29
31
|
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { rssMessages as t } from '../../src/i18n.js';
|
|
1
2
|
import { defineCommand } from 'zhin.js/command';
|
|
2
3
|
import { channelSourceError, extractChannelInfo, subscriptionScope } from '../../src/channel.js';
|
|
3
4
|
import { getRssSubs } from '../../src/db-store.js';
|
|
@@ -5,27 +6,28 @@ import { resolveRssConfig, type RssConfig } from '../../src/feed.js';
|
|
|
5
6
|
import { rssRuntimeToken } from '../../src/runtime.js';
|
|
6
7
|
|
|
7
8
|
export default defineCommand<RssConfig>({
|
|
8
|
-
description: '查看当前会话的所有 RSS 订阅',
|
|
9
|
-
async execute({ config, input, use }) {
|
|
9
|
+
description: '查看当前会话的所有 RSS 订阅', descriptionI18n: { en: "List this conversation's RSS subscriptions" },
|
|
10
|
+
async execute({ config, input, use, locale, formatCommand }) {
|
|
10
11
|
const Subs = getRssSubs(use(rssRuntimeToken).db);
|
|
11
|
-
if (!Subs) return
|
|
12
|
+
if (!Subs) return t(locale, 'databaseUnavailable');
|
|
12
13
|
|
|
13
14
|
const channel = extractChannelInfo(input);
|
|
14
|
-
if (!channel) return channelSourceError(input);
|
|
15
|
+
if (!channel) return channelSourceError(input, locale);
|
|
15
16
|
const cfg = resolveRssConfig(config);
|
|
16
17
|
const rows = await Subs.select().where({
|
|
17
18
|
...subscriptionScope(channel),
|
|
18
19
|
});
|
|
19
20
|
|
|
20
21
|
if (rows.length === 0) {
|
|
21
|
-
|
|
22
|
+
const command = formatCommand('rss-add');
|
|
23
|
+
return [t(locale, 'empty'), command ? t(locale, 'addHint', { command }) : undefined].filter(Boolean).join('\n');
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
const lines = rows.map((r, i) => {
|
|
25
|
-
const title = String(r.feed_title ||
|
|
27
|
+
const title = String(r.feed_title || t(locale, 'unknownTitle'));
|
|
26
28
|
return `${i + 1}. ${title}\n ${String(r.url ?? '')}`;
|
|
27
29
|
});
|
|
28
30
|
|
|
29
|
-
return
|
|
31
|
+
return t(locale, 'list', { count: rows.length, max: cfg.maxPerGroup, items: lines.join('\n') });
|
|
30
32
|
},
|
|
31
33
|
});
|
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
+
import { rssMessages as t } from "../../../lib/i18n.js";
|
|
2
3
|
import { defineCommand } from 'zhin.js/command';
|
|
3
4
|
import { fetchFeed, formatFeedPreview, resolveRssConfig } from "../../../lib/feed.js";
|
|
4
5
|
export default defineCommand({
|
|
5
|
-
description: '预览一个 RSS 源的最新内容(不订阅)',
|
|
6
|
+
description: '预览一个 RSS 源的最新内容(不订阅)', descriptionI18n: { en: "Preview the latest feed items without subscribing" },
|
|
6
7
|
params: { url: { type: 'string' } },
|
|
7
|
-
async execute({ params, config }) {
|
|
8
|
+
async execute({ params, config, locale }) {
|
|
8
9
|
const url = String(params.url ?? '').trim();
|
|
9
10
|
if (!url)
|
|
10
|
-
return
|
|
11
|
+
return t(locale, 'urlRequired');
|
|
11
12
|
if (!/^https?:\/\//i.test(url))
|
|
12
|
-
return
|
|
13
|
+
return t(locale, 'httpRequired');
|
|
13
14
|
const cfg = resolveRssConfig(config);
|
|
14
15
|
try {
|
|
15
16
|
const { title, items } = await fetchFeed(url, cfg.timeout);
|
|
16
|
-
return formatFeedPreview(title, items);
|
|
17
|
+
return formatFeedPreview(title, items, locale);
|
|
17
18
|
}
|
|
18
19
|
catch (e) {
|
|
19
|
-
return
|
|
20
|
+
return t(locale, 'previewFailed', { error: e.message });
|
|
20
21
|
}
|
|
21
22
|
},
|
|
22
23
|
});
|
|
@@ -1,19 +1,20 @@
|
|
|
1
|
+
import { rssMessages as t } from '../../../src/i18n.js';
|
|
1
2
|
import { defineCommand } from 'zhin.js/command';
|
|
2
3
|
import { fetchFeed, formatFeedPreview, resolveRssConfig, type RssConfig } from '../../../src/feed.js';
|
|
3
4
|
|
|
4
5
|
export default defineCommand<RssConfig>({
|
|
5
|
-
description: '预览一个 RSS 源的最新内容(不订阅)',
|
|
6
|
+
description: '预览一个 RSS 源的最新内容(不订阅)', descriptionI18n: { en: "Preview the latest feed items without subscribing" },
|
|
6
7
|
params: { url: { type: 'string' } },
|
|
7
|
-
async execute({ params, config }) {
|
|
8
|
+
async execute({ params, config, locale }) {
|
|
8
9
|
const url = String(params.url ?? '').trim();
|
|
9
|
-
if (!url) return
|
|
10
|
-
if (!/^https?:\/\//i.test(url)) return
|
|
10
|
+
if (!url) return t(locale, 'urlRequired');
|
|
11
|
+
if (!/^https?:\/\//i.test(url)) return t(locale, 'httpRequired');
|
|
11
12
|
const cfg = resolveRssConfig(config);
|
|
12
13
|
try {
|
|
13
14
|
const { title, items } = await fetchFeed(url, cfg.timeout);
|
|
14
|
-
return formatFeedPreview(title, items);
|
|
15
|
+
return formatFeedPreview(title, items, locale);
|
|
15
16
|
} catch (e) {
|
|
16
|
-
return
|
|
17
|
+
return t(locale, 'previewFailed', { error: (e as Error).message });
|
|
17
18
|
}
|
|
18
19
|
},
|
|
19
20
|
});
|
|
@@ -1,33 +1,34 @@
|
|
|
1
1
|
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
+
import { rssMessages as t } from "../../../lib/i18n.js";
|
|
2
3
|
import { defineCommand } from 'zhin.js/command';
|
|
3
4
|
import { channelSourceError, extractChannelInfo, subscriptionScope } from "../../../lib/channel.js";
|
|
4
5
|
import { getRssSubs } from "../../../lib/db-store.js";
|
|
5
6
|
import { rssRuntimeToken } from "../../../lib/runtime.js";
|
|
6
7
|
export default defineCommand({
|
|
7
|
-
description: '取消一个 RSS 订阅',
|
|
8
|
+
description: '取消一个 RSS 订阅', descriptionI18n: { en: "Unsubscribe from an RSS feed" },
|
|
8
9
|
params: { url: { type: 'string' } },
|
|
9
|
-
async execute({ params, input, use }) {
|
|
10
|
+
async execute({ params, input, use, locale }) {
|
|
10
11
|
const Subs = getRssSubs(use(rssRuntimeToken).db);
|
|
11
12
|
if (!Subs)
|
|
12
|
-
return
|
|
13
|
+
return t(locale, 'databaseUnavailable');
|
|
13
14
|
const url = String(params.url ?? '').trim();
|
|
14
15
|
if (!url)
|
|
15
|
-
return
|
|
16
|
+
return t(locale, 'removeUrl');
|
|
16
17
|
const channel = extractChannelInfo(input);
|
|
17
18
|
if (!channel)
|
|
18
|
-
return channelSourceError(input);
|
|
19
|
+
return channelSourceError(input, locale);
|
|
19
20
|
const rows = await Subs.select().where({
|
|
20
21
|
url,
|
|
21
22
|
...subscriptionScope(channel),
|
|
22
23
|
});
|
|
23
24
|
if (rows.length === 0)
|
|
24
|
-
return '
|
|
25
|
+
return t(locale, 'notFound');
|
|
25
26
|
const row = rows[0];
|
|
26
27
|
// 表结构没有 id 列,删除必须按业务键匹配(与上面的 select 条件一致)。
|
|
27
28
|
await Subs.delete().where({
|
|
28
29
|
url,
|
|
29
30
|
...subscriptionScope(channel),
|
|
30
31
|
});
|
|
31
|
-
return
|
|
32
|
+
return t(locale, 'removed', { feed: String(row.feed_title || url) });
|
|
32
33
|
},
|
|
33
34
|
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { rssMessages as t } from '../../../src/i18n.js';
|
|
1
2
|
import { defineCommand } from 'zhin.js/command';
|
|
2
3
|
import { channelSourceError, extractChannelInfo, subscriptionScope } from '../../../src/channel.js';
|
|
3
4
|
import { getRssSubs } from '../../../src/db-store.js';
|
|
@@ -5,23 +6,23 @@ import type { RssConfig } from '../../../src/feed.js';
|
|
|
5
6
|
import { rssRuntimeToken } from '../../../src/runtime.js';
|
|
6
7
|
|
|
7
8
|
export default defineCommand<RssConfig>({
|
|
8
|
-
description: '取消一个 RSS 订阅',
|
|
9
|
+
description: '取消一个 RSS 订阅', descriptionI18n: { en: "Unsubscribe from an RSS feed" },
|
|
9
10
|
params: { url: { type: 'string' } },
|
|
10
|
-
async execute({ params, input, use }) {
|
|
11
|
+
async execute({ params, input, use, locale }) {
|
|
11
12
|
const Subs = getRssSubs(use(rssRuntimeToken).db);
|
|
12
|
-
if (!Subs) return
|
|
13
|
+
if (!Subs) return t(locale, 'databaseUnavailable');
|
|
13
14
|
|
|
14
15
|
const url = String(params.url ?? '').trim();
|
|
15
|
-
if (!url) return
|
|
16
|
+
if (!url) return t(locale, 'removeUrl');
|
|
16
17
|
|
|
17
18
|
const channel = extractChannelInfo(input);
|
|
18
|
-
if (!channel) return channelSourceError(input);
|
|
19
|
+
if (!channel) return channelSourceError(input, locale);
|
|
19
20
|
const rows = await Subs.select().where({
|
|
20
21
|
url,
|
|
21
22
|
...subscriptionScope(channel),
|
|
22
23
|
});
|
|
23
24
|
|
|
24
|
-
if (rows.length === 0) return '
|
|
25
|
+
if (rows.length === 0) return t(locale, 'notFound');
|
|
25
26
|
|
|
26
27
|
const row = rows[0]!;
|
|
27
28
|
// 表结构没有 id 列,删除必须按业务键匹配(与上面的 select 条件一致)。
|
|
@@ -29,6 +30,6 @@ export default defineCommand<RssConfig>({
|
|
|
29
30
|
url,
|
|
30
31
|
...subscriptionScope(channel),
|
|
31
32
|
});
|
|
32
|
-
return
|
|
33
|
+
return t(locale, 'removed', { feed: String(row.feed_title || url) });
|
|
33
34
|
},
|
|
34
35
|
});
|