Droplink 消息协议设计
本文档定义了 Droplink 系统的消息通信格式。
📋 协议概述
设计理念
- 基于 Gotify:利用 Gotify 的
extras字段扩展,无需修改 Gotify - 命名空间隔离:使用
extras.droplink避免与其他工具冲突 - 动作数组:支持一条消息触发多个处理端协同工作
- 处理端解耦:各处理端独立监听,过滤自己关心的动作
核心概念
发送端(Android/iOS/Web)
↓ 构造消息
Gotify Server(消息引擎)
↓ 广播
多个处理端并行执行
├─ Chrome Extension(过滤 handler=chrome 或 handler 为空)
├─ Notion Worker(过滤 handler=notion-worker)
└─ 其他处理端...🎯 完整消息格式
Gotify 消息体
json
{
"title": "Droplink",
"message": "https://github.com/yaotutu/droplink",
"priority": 5,
"extras": {
"droplink": {
"id": "msg_1736524800000_abc123",
"timestamp": 1736524800000,
"sender": "android",
"content": {
"type": "url",
"value": "https://github.com/yaotutu/droplink"
},
"actions": [
{
"type": "openTab"
},
{
"type": "archive",
"handler": "notion-worker",
"params": {
"enrich": true,
"aiSummary": true,
"database": "reading_list"
}
}
],
"metadata": {
"tags": ["github", "tools"]
}
}
}
}📐 TypeScript 类型定义
typescript
// Gotify 原生消息格式
interface GotifyMessage {
title: string
message: string
priority: number
extras: {
droplink: DropLinkMessage
}
}
// Droplink 消息协议
interface DropLinkMessage {
// 元数据
id: string // 消息唯一ID,格式:msg_{timestamp}_{random}
timestamp: number // Unix 时间戳(毫秒)
sender: string // 发送端标识:android | ios | web | cli
// 内容
content: {
type: 'url' | 'text' | 'file'
value: string // URL / 纯文本 / 文件路径
}
// 动作列表
actions: Action[]
// 元数据(可选)
metadata?: {
title?: string // 标题
tags?: string[] // 标签
source?: string // 来源
[key: string]: any // 其他自定义字段
}
}
// 动作定义
interface Action {
type: string // 动作类型:openTab, archive, notify, summarize...
handler?: string // 处理端(可选):chrome, safari, notion-worker, ai-worker...
params?: { // 动作参数(可选)
[key: string]: any
}
}📊 字段说明
Gotify 层级字段
| 字段 | 必填 | 类型 | 说明 |
|---|---|---|---|
title | ✅ | string | Gotify 消息标题,固定为 "Droplink" |
message | ✅ | string | Gotify 消息内容,通常为 URL |
priority | ✅ | number | Gotify 优先级,建议为 5 |
extras.droplink | ✅ | object | Droplink 协议数据 |
DropLink 协议字段
| 字段 | 必填 | 类型 | 说明 |
|---|---|---|---|
id | ✅ | string | 消息唯一标识,建议格式:msg_{timestamp}_{random} |
timestamp | ✅ | number | Unix 时间戳(毫秒) |
sender | ✅ | string | 发送端标识:android / ios / web / cli |
content.type | ✅ | string | 内容类型:url / text / file |
content.value | ✅ | string | 内容值 |
actions | ✅ | array | 动作列表(至少包含1个动作) |
actions[].type | ✅ | string | 动作类型(做什么) |
actions[].handler | ❌ | string | 处理端(谁来做,可选,省略表示任何处理端都可以) |
actions[].params | ❌ | object | 动作参数(怎么做,可选) |
metadata | ❌ | object | 元数据(可选) |
🎨 典型场景示例
场景 1: 分享 URL - 快速打开
content.type: url用途:临时查看链接
json
{
"title": "Droplink",
"message": "https://www.youtube.com/watch?v=xxx",
"priority": 5,
"extras": {
"droplink": {
"id": "msg_1736524800001_abc123",
"timestamp": 1736524800001,
"sender": "android",
"content": {
"type": "url",
"value": "https://www.youtube.com/watch?v=xxx"
},
"actions": [
{
"type": "openTab"
}
]
}
}
}执行流程:
- Chrome Extension 收到 → 验证 content.type=url → 打开浏览器标签页
场景 2: 分享 URL - 重要链接(多端协同)
content.type: url用途:有价值的内容,需要打开 + 归档 + AI 分析
json
{
"title": "Droplink",
"message": "https://github.com/yaotutu/droplink",
"priority": 5,
"extras": {
"droplink": {
"id": "msg_1736524800002_def456",
"timestamp": 1736524800002,
"sender": "android",
"content": {
"type": "url",
"value": "https://github.com/yaotutu/droplink"
},
"actions": [
{
"type": "openTab",
"params": {
"activate": true
}
},
{
"type": "archive",
"handler": "notion-worker",
"params": {
"enrich": true,
"aiSummary": true,
"database": "reading_list"
}
}
],
"metadata": {
"tags": ["github", "tools", "productivity"]
}
}
}
}执行流程:
- Chrome Extension 收到 → 验证 handler 为空或 chrome → 验证 openTab 兼容 url → 立即打开浏览器标签页
- Notion Worker 收到 → 验证 handler=notion-worker → 验证 archive 兼容 url → 后台拉取数据 → AI 总结 → 归档到 Notion
完整的场景示例、动作类型定义、设计原则等详细内容,请参阅完整的消息协议文档。
🎯 设计原则
1. 最小必需
必填字段只包含核心信息:
id,timestamp,sender(元数据)content(内容)actions[].type(动作类型)
2. 扩展友好
metadata可选,支持任意自定义字段actions[].handler可选,省略表示任何处理端都可以处理actions[].params可选,支持动作特定参数content.type可扩展新类型
3. 处理端解耦
- 每个处理端独立监听 Gotify
- 通过
action.handler过滤(handler 匹配或为空) - 通过
action.type过滤(动作类型) - 各处理端并行执行,互不影响
4. 一次分享,多端协同
actions为数组,支持多个动作- 一条消息可触发多个处理端
- 示例:打开浏览器 + AI分析 + Notion归档
📌 版本信息
- 协议版本: v2.0
- 创建日期: 2026-01-10
- 最后更新: 2026-01-16
版本历史
- v2.0 (2026-01-16):引入
handler字段,实现动作类型与处理端的分离 - v1.0 (2026-01-10):初始版本,使用组合式动作命名(如 archiveToNotion)