@zhin.js/plugin-rss 1.1.7 → 1.1.9
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 +4 -0
- package/lib/storage.d.ts +3 -0
- package/lib/storage.d.ts.map +1 -0
- package/lib/storage.js +56 -0
- package/lib/storage.js.map +1 -0
- package/package.json +7 -7
- package/plugin.js +7 -3
- package/src/storage.ts +58 -0
package/README.md
CHANGED
package/lib/storage.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA,OAAO,EACiF,KAAK,kBAAkB,EAA6B,MAAM,wBAAwB,CAAC;AAsD3K,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,kBAAkB,sCAEvE"}
|
package/lib/storage.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { createRelationalStateStore, TASK_TARGET_COLUMNS, TASK_RECEIPT_COLUMNS, encodeTaskTarget, decodeTaskTarget, encodeTaskReceipts, decodeTaskReceipts, encodeStorageIdentity, decodeStorageIdentity } from 'zhin.js/plugin-runtime';
|
|
2
|
+
import { ADMIN_RSS_STATE_KEY } from './admin-tasks.js';
|
|
3
|
+
const tasks = 'admin_rss_tasks', seen = 'admin_rss_seen', items = 'admin_rss_pending_items', receipts = 'admin_rss_receipts';
|
|
4
|
+
const text = { type: 'text', nullable: true };
|
|
5
|
+
const time = { type: 'bigint', nullable: true };
|
|
6
|
+
const child = { id: { type: 'text', length: 80, primary: true }, task_id: { type: 'text', length: 36, nullable: false }, position: { type: 'integer', nullable: false } };
|
|
7
|
+
const codec = {
|
|
8
|
+
key: ADMIN_RSS_STATE_KEY,
|
|
9
|
+
header: { table: 'admin_rss_book', definition: { version: { type: 'integer', nullable: true }, revision: text } },
|
|
10
|
+
tables: {
|
|
11
|
+
[tasks]: { id: { type: 'text', length: 36, primary: true }, position: { type: 'integer', nullable: false }, ...TASK_TARGET_COLUMNS,
|
|
12
|
+
creation: text, version: text, url: text, state: text, created_at: time, claim_id: text, last_check_at: time, last_run_at: time, detail: text,
|
|
13
|
+
seen_known: { type: 'boolean', nullable: false }, quiet_timezone: text, quiet_start: text, quiet_end: text,
|
|
14
|
+
pending_kind: text, pending_from: time, pending_to: time, pending_count: { type: 'integer', nullable: true },
|
|
15
|
+
pending_capped: { type: 'boolean', nullable: true } },
|
|
16
|
+
[seen]: { ...child, item_key: { type: 'text', nullable: false } },
|
|
17
|
+
[items]: { ...child, item_key: text, title: text, link: text },
|
|
18
|
+
[receipts]: TASK_RECEIPT_COLUMNS,
|
|
19
|
+
},
|
|
20
|
+
encode(value) {
|
|
21
|
+
const book = value;
|
|
22
|
+
if (![1, 2].includes(book.version) || !Array.isArray(book.tasks) || !Array.isArray(book.receipts))
|
|
23
|
+
throw new Error('Unsupported RSS book; original state was preserved');
|
|
24
|
+
return { header: { version: book.version, revision: book.revision }, rows: {
|
|
25
|
+
[tasks]: book.tasks.map((task, position) => ({ id: task.id, position, ...encodeTaskTarget(task.target),
|
|
26
|
+
creation: task.creation, version: task.version, url: encodeStorageIdentity(task.url), state: task.state, created_at: task.createdAt,
|
|
27
|
+
claim_id: task.claimId, last_check_at: task.lastCheckAt, last_run_at: task.lastRunAt, detail: encodeStorageIdentity(task.detail),
|
|
28
|
+
seen_known: task.seen !== null, quiet_timezone: task.quiet?.timezone ?? null, quiet_start: task.quiet?.start ?? null, quiet_end: task.quiet?.end ?? null,
|
|
29
|
+
pending_kind: task.pending === undefined ? 'absent' : task.pending === null ? 'null' : 'value',
|
|
30
|
+
pending_from: task.pending?.from ?? null, pending_to: task.pending?.to ?? null,
|
|
31
|
+
pending_count: task.pending?.count ?? null, pending_capped: task.pending?.countCapped ?? null,
|
|
32
|
+
})),
|
|
33
|
+
[seen]: book.tasks.flatMap((task) => (task.seen ?? []).map((key, position) => ({ id: `${task.id}:${position}`, task_id: task.id, position, item_key: encodeStorageIdentity(key) }))),
|
|
34
|
+
[items]: book.tasks.flatMap((task) => (task.pending?.items ?? []).map((item, position) => ({ id: `${task.id}:${position}`, task_id: task.id, position, item_key: encodeStorageIdentity(item.key), title: encodeStorageIdentity(item.title), link: encodeStorageIdentity(item.link) }))),
|
|
35
|
+
[receipts]: encodeTaskReceipts(book.receipts),
|
|
36
|
+
} };
|
|
37
|
+
},
|
|
38
|
+
decode(header, rows) {
|
|
39
|
+
return { version: Number(header.version), revision: String(header.revision), receipts: decodeTaskReceipts(rows[receipts]),
|
|
40
|
+
tasks: rows[tasks].map(row => ({ id: String(row.id), target: decodeTaskTarget(row), creation: String(row.creation), version: String(row.version),
|
|
41
|
+
url: decodeStorageIdentity(row.url), state: String(row.state), createdAt: Number(row.created_at), claimId: row.claim_id == null ? null : String(row.claim_id),
|
|
42
|
+
lastCheckAt: row.last_check_at == null ? null : Number(row.last_check_at), lastRunAt: row.last_run_at == null ? null : Number(row.last_run_at), detail: decodeStorageIdentity(row.detail),
|
|
43
|
+
seen: row.seen_known ? rows[seen].filter(item => item.task_id === row.id).map(item => decodeStorageIdentity(item.item_key)) : null,
|
|
44
|
+
...(row.quiet_timezone == null ? {} : { quiet: { timezone: String(row.quiet_timezone), start: String(row.quiet_start), end: String(row.quiet_end) } }),
|
|
45
|
+
...(row.pending_kind === 'absent' ? {} : { pending: row.pending_kind === 'null' ? null : {
|
|
46
|
+
from: Number(row.pending_from), to: Number(row.pending_to), count: Number(row.pending_count), countCapped: Boolean(row.pending_capped),
|
|
47
|
+
items: rows[items].filter(item => item.task_id === row.id).map(item => ({ key: decodeStorageIdentity(item.item_key), title: decodeStorageIdentity(item.title), link: decodeStorageIdentity(item.link) })),
|
|
48
|
+
} }),
|
|
49
|
+
})),
|
|
50
|
+
};
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
export function createAdministratorRssState(database) {
|
|
54
|
+
return createRelationalStateStore(database, [codec]);
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.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.
|
|
3
|
+
"version": "1.1.9",
|
|
4
4
|
"description": "RSS/Atom feed subscription plugin for Zhin.js (Plugin Runtime)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -41,20 +41,20 @@
|
|
|
41
41
|
"license": "MIT",
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"rss-parser": "^3.13.0",
|
|
44
|
-
"@zhin.js/im-contract": "1.1.
|
|
45
|
-
"@zhin.js/tool": "1.1.
|
|
46
|
-
"@zhin.js/skill": "1.1.
|
|
44
|
+
"@zhin.js/im-contract": "1.1.6",
|
|
45
|
+
"@zhin.js/tool": "1.1.9",
|
|
46
|
+
"@zhin.js/skill": "1.1.9"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"typescript": "^6.0.3",
|
|
50
50
|
"vitest": "^4.1.10",
|
|
51
51
|
"zod": "^4.4.3",
|
|
52
|
-
"zhin.js": "1.1.
|
|
52
|
+
"zhin.js": "1.1.15"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
55
|
"zod": "^4.0.0",
|
|
56
|
-
"@zhin.js/command": "^1.1.
|
|
57
|
-
"zhin.js": "^1.1.
|
|
56
|
+
"@zhin.js/command": "^1.1.10",
|
|
57
|
+
"zhin.js": "^1.1.15"
|
|
58
58
|
},
|
|
59
59
|
"peerDependenciesMeta": {
|
|
60
60
|
"@zhin.js/command": {
|
package/plugin.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
-
import { definePlugin, databaseHostToken, outboundHostToken, scheduleHostToken, } from 'zhin.js';
|
|
2
|
+
import { definePlugin, logger, databaseHostToken, outboundHostToken, scheduleHostToken, } from 'zhin.js';
|
|
3
3
|
import { pluginTaskProviderToken } from 'zhin.js/plugin-runtime';
|
|
4
|
+
import { createAdministratorRssState } from "./lib/storage.js";
|
|
4
5
|
import { AdministratorRssTasks } from "./lib/admin-tasks.js";
|
|
5
6
|
import { resolveRssConfig } from "./lib/feed.js";
|
|
6
7
|
import { createInMemoryRssDb, RSS_SEEN_TABLE, RSS_SUBS_TABLE, } from "./lib/db-store.js";
|
|
@@ -69,14 +70,17 @@ export default definePlugin({
|
|
|
69
70
|
// Keep optional in-memory/chat-only installations working. Administrator tasks
|
|
70
71
|
// must have the real durable state port, exact outbound and an active scheduler.
|
|
71
72
|
let administrator;
|
|
72
|
-
|
|
73
|
+
const structuredTasks = database && ['sqlite', 'mysql', 'pg'].includes(database.dialect);
|
|
74
|
+
if (database && !structuredTasks)
|
|
75
|
+
logger.warn('RSS 管理员任务持久化仅支持 SQLite、MySQL、PostgreSQL;聊天订阅保留现有存储方式');
|
|
76
|
+
if (structuredTasks && database && outbound?.sendTarget && context.resources.has(scheduleHostToken)) {
|
|
73
77
|
let state;
|
|
74
78
|
try {
|
|
75
79
|
state = database.state;
|
|
76
80
|
}
|
|
77
81
|
catch { /* No persistent state port: no administrator provider. */ }
|
|
78
82
|
if (state) {
|
|
79
|
-
administrator = new AdministratorRssTasks(
|
|
83
|
+
administrator = new AdministratorRssTasks(createAdministratorRssState(database), outbound, config);
|
|
80
84
|
context.resources.provide(pluginTaskProviderToken, administrator);
|
|
81
85
|
context.lifecycle.add(() => administrator?.stop());
|
|
82
86
|
}
|
package/src/storage.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { createRelationalStateStore, TASK_TARGET_COLUMNS, TASK_RECEIPT_COLUMNS, encodeTaskTarget, decodeTaskTarget,
|
|
2
|
+
encodeTaskReceipts, decodeTaskReceipts, encodeStorageIdentity, decodeStorageIdentity, type PluginDatabaseHost, type RelationalStateCodec } from 'zhin.js/plugin-runtime';
|
|
3
|
+
import { ADMIN_RSS_STATE_KEY, type AdministratorRssBook } from './admin-tasks.js';
|
|
4
|
+
|
|
5
|
+
const tasks = 'admin_rss_tasks', seen = 'admin_rss_seen', items = 'admin_rss_pending_items', receipts = 'admin_rss_receipts';
|
|
6
|
+
const text = { type: 'text', nullable: true } as const;
|
|
7
|
+
const time = { type: 'bigint', nullable: true } as const;
|
|
8
|
+
const child = { id: { type: 'text', length: 80, primary: true }, task_id: { type: 'text', length: 36, nullable: false }, position: { type: 'integer', nullable: false } };
|
|
9
|
+
|
|
10
|
+
const codec: RelationalStateCodec = {
|
|
11
|
+
key: ADMIN_RSS_STATE_KEY,
|
|
12
|
+
header: { table: 'admin_rss_book', definition: { version: { type: 'integer', nullable: true }, revision: text } },
|
|
13
|
+
tables: {
|
|
14
|
+
[tasks]: { id: { type: 'text', length: 36, primary: true }, position: { type: 'integer', nullable: false }, ...TASK_TARGET_COLUMNS,
|
|
15
|
+
creation: text, version: text, url: text, state: text, created_at: time, claim_id: text, last_check_at: time, last_run_at: time, detail: text,
|
|
16
|
+
seen_known: { type: 'boolean', nullable: false }, quiet_timezone: text, quiet_start: text, quiet_end: text,
|
|
17
|
+
pending_kind: text, pending_from: time, pending_to: time, pending_count: { type: 'integer', nullable: true },
|
|
18
|
+
pending_capped: { type: 'boolean', nullable: true } },
|
|
19
|
+
[seen]: { ...child, item_key: { type: 'text', nullable: false } },
|
|
20
|
+
[items]: { ...child, item_key: text, title: text, link: text },
|
|
21
|
+
[receipts]: TASK_RECEIPT_COLUMNS,
|
|
22
|
+
},
|
|
23
|
+
encode(value) {
|
|
24
|
+
const book = value as AdministratorRssBook;
|
|
25
|
+
if (![1, 2].includes(book.version) || !Array.isArray(book.tasks) || !Array.isArray(book.receipts)) throw new Error('Unsupported RSS book; original state was preserved');
|
|
26
|
+
return { header: { version: book.version, revision: book.revision }, rows: {
|
|
27
|
+
[tasks]: book.tasks.map((task, position) => ({ id: task.id, position, ...encodeTaskTarget(task.target),
|
|
28
|
+
creation: task.creation, version: task.version, url: encodeStorageIdentity(task.url), state: task.state, created_at: task.createdAt,
|
|
29
|
+
claim_id: task.claimId, last_check_at: task.lastCheckAt, last_run_at: task.lastRunAt, detail: encodeStorageIdentity(task.detail),
|
|
30
|
+
seen_known: task.seen !== null, quiet_timezone: task.quiet?.timezone ?? null, quiet_start: task.quiet?.start ?? null, quiet_end: task.quiet?.end ?? null,
|
|
31
|
+
pending_kind: task.pending === undefined ? 'absent' : task.pending === null ? 'null' : 'value',
|
|
32
|
+
pending_from: task.pending?.from ?? null, pending_to: task.pending?.to ?? null,
|
|
33
|
+
pending_count: task.pending?.count ?? null, pending_capped: task.pending?.countCapped ?? null,
|
|
34
|
+
})),
|
|
35
|
+
[seen]: book.tasks.flatMap((task: AdministratorRssBook['tasks'][number]) => (task.seen ?? []).map((key, position) => ({ id: `${task.id}:${position}`, task_id: task.id, position, item_key: encodeStorageIdentity(key) }))),
|
|
36
|
+
[items]: book.tasks.flatMap((task: AdministratorRssBook['tasks'][number]) => (task.pending?.items ?? []).map((item, position) => ({ id: `${task.id}:${position}`, task_id: task.id, position, item_key: encodeStorageIdentity(item.key), title: encodeStorageIdentity(item.title), link: encodeStorageIdentity(item.link) }))),
|
|
37
|
+
[receipts]: encodeTaskReceipts(book.receipts),
|
|
38
|
+
} };
|
|
39
|
+
},
|
|
40
|
+
decode(header, rows) {
|
|
41
|
+
return { version: Number(header.version), revision: String(header.revision), receipts: decodeTaskReceipts(rows[receipts]!),
|
|
42
|
+
tasks: rows[tasks]!.map(row => ({ id: String(row.id), target: decodeTaskTarget(row), creation: String(row.creation), version: String(row.version),
|
|
43
|
+
url: decodeStorageIdentity(row.url), state: String(row.state), createdAt: Number(row.created_at), claimId: row.claim_id == null ? null : String(row.claim_id),
|
|
44
|
+
lastCheckAt: row.last_check_at == null ? null : Number(row.last_check_at), lastRunAt: row.last_run_at == null ? null : Number(row.last_run_at), detail: decodeStorageIdentity(row.detail),
|
|
45
|
+
seen: row.seen_known ? rows[seen]!.filter(item => item.task_id === row.id).map(item => decodeStorageIdentity(item.item_key)) : null,
|
|
46
|
+
...(row.quiet_timezone == null ? {} : { quiet: { timezone: String(row.quiet_timezone), start: String(row.quiet_start), end: String(row.quiet_end) } }),
|
|
47
|
+
...(row.pending_kind === 'absent' ? {} : { pending: row.pending_kind === 'null' ? null : {
|
|
48
|
+
from: Number(row.pending_from), to: Number(row.pending_to), count: Number(row.pending_count), countCapped: Boolean(row.pending_capped),
|
|
49
|
+
items: rows[items]!.filter(item => item.task_id === row.id).map(item => ({ key: decodeStorageIdentity(item.item_key), title: decodeStorageIdentity(item.title), link: decodeStorageIdentity(item.link) })),
|
|
50
|
+
} }),
|
|
51
|
+
})),
|
|
52
|
+
};
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export function createAdministratorRssState(database: PluginDatabaseHost) {
|
|
57
|
+
return createRelationalStateStore(database, [codec]);
|
|
58
|
+
}
|