Skip to content

HeZeBang/keyfeeder

Repository files navigation

KeyFeeder

RSS-to-ActivityPub 代理服务 — 从 Mastodon 关注任意 RSS 源。

用户只需在 Mastodon 中搜索 @example.com@your-keyfeeder-domain.com,即可关注对应网站的 RSS 更新。

工作原理

  1. Mastodon 通过 WebFinger 查询用户
  2. KeyFeeder 自动发现该域名的 RSS 源
  3. 每天通过 Cron Job 拉取 RSS 更新(Vercel Hobby 限制,可以使用诸如 Github Action / Bot 绕过)
  4. 新内容通过 ActivityPub 协议推送给所有关注者

用户名转换规则

在 Mastodon 中搜索 @<用户名>@your-keyfeeder-domain.com,用户名即为目标网站的地址。

  • . 只用于域名部分(子域名、域名、TLD)
  • _ 代表 /(路径分隔符)
用户名 解析结果 RSS 发现地址
xkcd.com xkcd.com https://xkcd.com/
blog.example.com blog.example.com https://blog.example.com/
example.com_blog example.com/blog https://example.com/blog
example.com_blog_feed example.com/blog/feed https://example.com/blog/feed

KeyFeeder 会依次尝试直接访问、/rss.xml/feed.xml.rss 后缀、.xml 后缀、HTML 中的 <link rel="alternate"> 标签,以及 WordPress 的 /feed/ 路径来自动发现 RSS 源。如果根路径找不到,还会尝试 /blog 子路径。请注意,后几者会更加耗时,因此最好直接使用对应地址。

技术栈

  • 框架: Next.js (App Router)
  • 数据库: Neon Postgres + Drizzle ORM
  • 部署: Vercel (Serverless)
  • 定时任务: Vercel Cron Jobs (每小时)
  • 协议: ActivityPub + HTTP Signatures

部署到 Vercel

1. 前置准备

生成 RSA 密钥对(用于 ActivityPub HTTP Signature 签名):

openssl genpkey -algorithm RSA -out private.pem
openssl rsa -pubout -in private.pem -out public.pem

2. 创建 Vercel 项目

npm i -g vercel
vercel link

3. 添加 Neon Postgres 数据库

通过 Vercel Marketplace 安装 Neon,会自动注入 DATABASE_URL 环境变量:

vercel integration add neon

4. 设置环境变量

# 服务域名(不含 https://)
vercel env add SERVER_HOSTNAME
# 输入: keyfeeder.yourdomain.com

# RSA 私钥(Base64 编码)
echo "$(base64 -w 0 private.pem)" | vercel env add --sensitive RSA_PRIVATE_KEY_BASE64 production

# RSA 公钥(Base64 编码)
echo "$(base64 -w 0 public.pem)" | vercel env add RSA_PUBLIC_KEY_BASE64 production
echo "$(base64 -w 0 public.pem)" | vercel env add RSA_PUBLIC_KEY_BASE64 development
echo "$(base64 -w 0 public.pem)" | vercel env add RSA_PRIVATE_KEY_BASE64 preview

# Cron 请求验证密钥(随机字符串)
vercel env add CRON_SECRET

5. 推送数据库 Schema

# 先拉取环境变量到本地
vercel env pull .env.local

# 推送表结构到 Neon
pnpm exec dotenv -e .env.local -- pnpm exec drizzle-kit push

6. 部署

vercel deploy --prod

7. 配置域名(可选)

vercel domains add keyfeeder.yourdomain.com

环境变量汇总

变量 说明 来源
DATABASE_URL Neon Postgres 连接字符串 Marketplace 自动注入
SERVER_HOSTNAME 服务域名 手动设置
RSA_PUBLIC_KEY_BASE64 RSA 公钥 PEM(Base64 编码) 手动设置
RSA_PRIVATE_KEY_BASE64 RSA 私钥 PEM(Base64 编码) 手动设置
CRON_SECRET Cron 验证密钥 手动设置

本地开发

1. 安装依赖

pnpm install

2. 拉取环境变量

确保已经完成了上面「部署到 Vercel」的步骤 1-4,然后:

vercel env pull .env.local

这会把 Vercel 上的环境变量(包括 DATABASE_URL)拉到本地 .env.local 文件。

3. 推送数据库 Schema(首次)

pnpm exec dotenv -e .env.local -- pnpm exec drizzle-kit push

4. 启动开发服务器

pnpm dev

服务启动在 http://localhost:3000

5. 本地测试端点

WebFinger 查询:

curl "http://localhost:3000/.well-known/webfinger?resource=acct:xkcd.com@localhost:3000"

ActivityPub 用户档案:

curl -H "Accept: application/activity+json" http://localhost:3000/xkcd.com

手动触发 Cron(拉取 RSS 并推送):

curl -H "Authorization: Bearer YOUR_CRON_SECRET" http://localhost:3000/api/cron/fetch-feeds

6. 数据库管理

# 查看数据库结构
pnpm exec dotenv -e .env.local -- pnpm exec drizzle-kit studio

# 生成迁移文件
pnpm exec dotenv -e .env.local -- pnpm exec drizzle-kit generate

# 应用迁移
pnpm exec dotenv -e .env.local -- pnpm exec drizzle-kit migrate

项目结构

src/
├── app/
│   ├── .well-known/webfinger/route.ts   # WebFinger 端点
│   ├── [hostname]/route.ts              # ActivityPub Person 档案
│   ├── [hostname]/inbox/route.ts        # Follow/Unfollow 处理
│   ├── api/cron/fetch-feeds/route.ts    # 定时 RSS 拉取
│   ├── layout.tsx
│   └── page.tsx                         # 着陆页
├── lib/
│   ├── db.ts                            # Neon + Drizzle 客户端
│   ├── env.ts                           # 环境变量
│   ├── activitypub/
│   │   ├── types.ts                     # Zod schemas
│   │   ├── send.ts                      # HTTP Signature 签名
│   │   └── accept.ts                    # Accept activity
│   ├── feed/
│   │   ├── fetch-feed.ts               # RSS 解析
│   │   ├── fetch-url-info.ts           # RSS URL 发现 + 缓存
│   │   └── fetch-and-send.ts           # Cron 核心逻辑
│   ├── xml-utils.ts                     # XML 工具
│   └── parse-domain.ts                  # 用户名 → 域名/路径 解析
├── drizzle/
│   └── schema.ts                        # 数据库 Schema

License

MIT

About

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors