feat(feeds): site-scoped RSS add infers account, parser and poll

Adding a feed from a site page now only asks for the URL, purpose
(discover / track / promotion) and an optional note. POST /feed-sources
with siteId infers the site account (passkey holder first), records the
site definition version as parserVersion, defaults the name to
"<site> RSS" and polling to 30 minutes, and returns non-blocking
warnings when the URL host does not match the site. The dialog shows the
redacted URL, fetches once right after saving and reports the item count
or the error.

The generic feed form on the sources page suggests linking a registered
site when the URL host matches (can be undone). name is now optional.

Takes effect after the stack is rebuilt.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-09-29 14:43:19 +08:00
1 parent 00ebdda7ed
commit 4a92dfd2dc
10 files changed
+512 -17

No files matched your search

+8 -1
View File
@@ -328,9 +328,15 @@ export const FeedSource = EntityBase.extend({
possibleGap: z
.object({ detectedAt: Timestamp, previousFetchedAt: Timestamp.nullable(), backfillQueued: z.boolean() })
.nullable(),
/** 只在创建响应里出现:不拦截的提示(如地址域名与所选站点不一致) */
warnings: z.array(z.string()).optional(),
});
export type FeedSource = z.infer<typeof FeedSource>;
/** url 为只写明文(可能含 passkey),服务端加密存为 secret 并生成 urlDisplay */
/**
* url 为只写明文(可能含 passkey),服务端加密存为 secret 并生成 urlDisplay。
* 带 siteId 时可只给 url(+ purpose):账号缺省取该站启用账号(优先带 passkey)、解析器按站点定义、名称缺省「站点名 RSS」;
* 不带 siteId 时名称缺省为地址主机名。
*/
export const FeedSourceCreate = FeedSource.pick({
siteId: true,
siteAccountId: true,
@@ -344,6 +350,7 @@ export const FeedSourceCreate = FeedSource.pick({
.partial({
siteId: true,
siteAccountId: true,
name: true,
purpose: true,
kind: true,
enabled: true,