入門
NIP-25 反應
深入了解 Nostr 的反應系統,按讚、表情符號反應和反應統計。
8 分鐘
什麼是 NIP-25?
NIP-25 定義了 Nostr 中的反應(Reactions)機制,讓用戶可以對事件表達 喜歡、不喜歡或使用表情符號反應。反應是 kind 7 事件,透過標籤引用目標事件。
核心概念: 反應使用 content 欄位表達反應類型:"+" 表示喜歡,"-" 表示不喜歡, 或任何表情符號如 "👍"、"❤️"、"🔥"。
事件結構
{
"kind": 7,
"content": "+", // 或 "-" 或表情符號
"tags": [
["e", "<event-id>", "<relay>"], // 被反應的事件
["p", "<event-author-pubkey>"] // 事件作者
],
"created_at": 1234567890,
"pubkey": "<reactor-pubkey>",
"id": "...",
"sig": "..."
} 反應類型
| Content | 含義 | 說明 |
|---|---|---|
| + | 喜歡 / 按讚 | 正面反應,通常顯示為愛心或讚 |
| - | 不喜歡 | 負面反應,部分客戶端可能不顯示 |
| 👍 ❤️ 🔥 😂 😢 | 表情反應 | 任何 Unicode 表情符號 |
| :custom: | 自訂表情 | 需配合 emoji 標籤使用 |
範例
按讚
{
"kind": 7,
"content": "+",
"tags": [
["e", "abc123...", "wss://relay.damus.io"],
["p", "def456..."]
]
} 表情反應
{
"kind": 7,
"content": "🔥",
"tags": [
["e", "abc123...", "wss://relay.damus.io"],
["p", "def456..."]
]
} 自訂表情
{
"kind": 7,
"content": ":sats:",
"tags": [
["e", "abc123..."],
["p", "def456..."],
["emoji", "sats", "https://example.com/sats.png"]
]
}
// emoji 標籤格式:["emoji", "shortcode", "image-url"] 程式碼範例
發送反應
async function sendReaction(targetEvent, reaction = '+') {
const event = {
kind: 7,
created_at: Math.floor(Date.now() / 1000),
content: reaction,
tags: [
['e', targetEvent.id, 'wss://relay.damus.io'],
['p', targetEvent.pubkey]
]
}
// 簽名並發送
const signedEvent = await window.nostr.signEvent(event)
relay.send(JSON.stringify(['EVENT', signedEvent]))
return signedEvent
}
// 使用
await sendReaction(somePost, '❤️') // 愛心反應
await sendReaction(somePost, '+') // 按讚
await sendReaction(somePost, '🚀') // 火箭反應 查詢反應
// 查詢特定事件的所有反應
["REQ", "reactions", {
"kinds": [7],
"#e": ["<event-id>"]
}]
// 查詢我收到的所有反應
["REQ", "my-reactions", {
"kinds": [7],
"#p": ["<my-pubkey>"]
}]
// 查詢特定用戶發出的反應
["REQ", "user-reactions", {
"kinds": [7],
"authors": ["<user-pubkey>"]
}] 統計反應
function countReactions(reactions) {
const counts = {
likes: 0, // + 反應
dislikes: 0, // - 反應
emojis: {} // 其他表情
}
for (const r of reactions) {
if (r.content === '+') {
counts.likes++
} else if (r.content === '-') {
counts.dislikes++
} else {
counts.emojis[r.content] = (counts.emojis[r.content] || 0) + 1
}
}
return counts
}
// 結果範例
// {
// likes: 42,
// dislikes: 2,
// emojis: { '🔥': 10, '❤️': 8, '😂': 5 }
// } 反應到其他事件類型
NIP-25 可以對任何事件類型反應,不只是貼文:
// 反應到長文 (kind 30023)
{
"kind": 7,
"content": "👏",
"tags": [
["e", "<article-event-id>"],
["p", "<author-pubkey>"],
["a", "30023:<author>:<d-tag>", "wss://relay.com"]
]
}
// "a" 標籤用於可替換事件,確保反應指向正確的內容 UI 設計考量
反應選擇器
提供快速按讚按鈕和表情選擇器
👍 ❤️ 😂 😢 😡 🔥 反應計數
顯示每種反應的數量
❤️ 42 🔥 15 😂 8 反應列表
點擊可查看誰給了反應
Alice, Bob 和其他 40 人 我的反應
高亮顯示用戶自己的反應
已按讚(點擊取消) 刪除反應
使用 kind 5(刪除事件)來撤回反應:
{
"kind": 5,
"content": "取消反應",
"tags": [
["e", "<reaction-event-id>"] // 要刪除的反應事件
]
}
// 注意:中繼器可能不會立即刪除
// 客戶端應該檢查 kind 5 事件來過濾已刪除的反應 與 Zaps 的關係
| 特性 | NIP-25 反應 | NIP-57 Zaps |
|---|---|---|
| 類型 | 社交互動 | 金錢打賞 |
| 成本 | 免費 | 比特幣(聰) |
| Kind | 7 | 9735 |
| 用途 | 表達情感 | 經濟支持 |
提示: 許多客戶端將 "+" 反應顯示為愛心圖示。如果你想支持更多表情反應, 確保你的 UI 可以正確渲染各種 Unicode 表情符號。
已複製連結