mirror of
https://github.com/dergigi/boris.git
synced 2025-12-17 06:34:24 +01:00
feat: respect existing zap tags in source content when creating highlights
- Updated addZapTags function to check for existing zap tags in source event - When source has zap tags (author group), split proportionally: - Highlighter gets their configured percentage - Remaining percentage distributed among existing authors proportionally - Example: 50/50 split with 2 source authors = 50% highlighter, 25% each author - Falls back to simple two-way split if no existing zap tags - Prevents duplicate entries if highlighter is already in author group
This commit is contained in:
20
.cursor/rules/zaps-and-zap-splits.mdc
Normal file
20
.cursor/rules/zaps-and-zap-splits.mdc
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
description: Specification for zaps and zaps splits
|
||||||
|
alwaysApply: false
|
||||||
|
---
|
||||||
|
|
||||||
|
When we create highlights, we want to add `zap` tags to the event, to allow for value splits between the highlighter/curator and the author (or authors).
|
||||||
|
|
||||||
|
`zap` tags are defined in Appendix G of NIP-57:
|
||||||
|
- https://github.com/nostr-protocol/nips/blob/master/57.md
|
||||||
|
|
||||||
|
More on `zap` tags here:
|
||||||
|
- https://nostrbook.dev/tags/zap
|
||||||
|
|
||||||
|
Note that nostr-native content might have `zap` tags already, which can be seen as the "author group" of e.g. the long-form article (writer, editor, designer, etc). We should respect these `zap` tags and include them into our "zap splits" appropriately.
|
||||||
|
|
||||||
|
Example: if our zap-split setting is 50/50, and the nostr-native blog post has two authors, our zap splits should be as follows:
|
||||||
|
|
||||||
|
- Highlighter: 50%
|
||||||
|
- Author1: 25%
|
||||||
|
- Author2: 25%
|
||||||
@@ -77,7 +77,7 @@ export async function createHighlight(
|
|||||||
// Add zap tags for nostr-native content (NIP-57 Appendix G)
|
// Add zap tags for nostr-native content (NIP-57 Appendix G)
|
||||||
if (typeof source === 'object' && 'kind' in source) {
|
if (typeof source === 'object' && 'kind' in source) {
|
||||||
const zapSplitPercentage = settings?.zapSplitPercentage ?? 50
|
const zapSplitPercentage = settings?.zapSplitPercentage ?? 50
|
||||||
addZapTags(highlightEvent, account.pubkey, source.pubkey, zapSplitPercentage)
|
addZapTags(highlightEvent, account.pubkey, source, zapSplitPercentage)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sign the event
|
// Sign the event
|
||||||
@@ -186,31 +186,67 @@ function extractContext(selectedText: string, articleContent: string): string |
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds zap tags to a highlight event for split payments (NIP-57 Appendix G)
|
* Adds zap tags to a highlight event for split payments (NIP-57 Appendix G)
|
||||||
|
* Respects existing zap tags in the source event (author group)
|
||||||
* @param event The highlight event to add zap tags to
|
* @param event The highlight event to add zap tags to
|
||||||
* @param highlighterPubkey The pubkey of the user creating the highlight
|
* @param highlighterPubkey The pubkey of the user creating the highlight
|
||||||
* @param authorPubkey The pubkey of the original article author
|
* @param sourceEvent The source event (may contain existing zap tags)
|
||||||
* @param highlighterPercentage Percentage (0-100) to give to the highlighter (default 50)
|
* @param highlighterPercentage Percentage (0-100) to give to the highlighter (default 50)
|
||||||
*/
|
*/
|
||||||
function addZapTags(
|
function addZapTags(
|
||||||
event: NostrEvent,
|
event: NostrEvent,
|
||||||
highlighterPubkey: string,
|
highlighterPubkey: string,
|
||||||
authorPubkey: string,
|
sourceEvent: NostrEvent,
|
||||||
highlighterPercentage: number = 50
|
highlighterPercentage: number = 50
|
||||||
): void {
|
): void {
|
||||||
// Calculate weights based on percentage
|
|
||||||
// Using simple integer weights where highlighterPercentage:authorPercentage ratio is maintained
|
|
||||||
const highlighterWeight = Math.round(highlighterPercentage)
|
|
||||||
const authorWeight = Math.round(100 - highlighterPercentage)
|
|
||||||
|
|
||||||
// Use a reliable relay for zap metadata lookup (first non-local relay)
|
// Use a reliable relay for zap metadata lookup (first non-local relay)
|
||||||
const zapRelay = RELAYS.find(r => !r.includes('localhost')) || RELAYS[0]
|
const zapRelay = RELAYS.find(r => !r.includes('localhost')) || RELAYS[0]
|
||||||
|
|
||||||
// Add zap tag for the highlighter
|
// Extract existing zap tags from source event (the "author group")
|
||||||
event.tags.push(['zap', highlighterPubkey, zapRelay, highlighterWeight.toString()])
|
const existingZapTags = sourceEvent.tags.filter(tag => tag[0] === 'zap')
|
||||||
|
|
||||||
// Add zap tag for the original author (only if different from highlighter)
|
if (existingZapTags.length > 0) {
|
||||||
if (authorPubkey !== highlighterPubkey) {
|
// Calculate total weight from existing zap tags
|
||||||
event.tags.push(['zap', authorPubkey, zapRelay, authorWeight.toString()])
|
const totalExistingWeight = existingZapTags.reduce((sum, tag) => {
|
||||||
|
const weight = parseInt(tag[3] || '1', 10)
|
||||||
|
return sum + weight
|
||||||
|
}, 0)
|
||||||
|
|
||||||
|
// Calculate author group percentage (what remains after highlighter's share)
|
||||||
|
const authorGroupPercentage = 100 - highlighterPercentage
|
||||||
|
|
||||||
|
// Add zap tag for the highlighter
|
||||||
|
event.tags.push(['zap', highlighterPubkey, zapRelay, highlighterPercentage.toString()])
|
||||||
|
|
||||||
|
// Add proportionally adjusted zap tags for each existing author
|
||||||
|
// Don't add the highlighter again if they're already in the author group
|
||||||
|
for (const zapTag of existingZapTags) {
|
||||||
|
const authorPubkey = zapTag[1]
|
||||||
|
|
||||||
|
// Skip if this is the highlighter (they already have their share)
|
||||||
|
if (authorPubkey === highlighterPubkey) continue
|
||||||
|
|
||||||
|
const originalWeight = parseInt(zapTag[3] || '1', 10)
|
||||||
|
const originalRelay = zapTag[2] || zapRelay
|
||||||
|
|
||||||
|
// Calculate proportional weight: (original weight / total weight) * author group percentage
|
||||||
|
const adjustedWeight = Math.round((originalWeight / totalExistingWeight) * authorGroupPercentage)
|
||||||
|
|
||||||
|
// Only add if weight is greater than 0
|
||||||
|
if (adjustedWeight > 0) {
|
||||||
|
event.tags.push(['zap', authorPubkey, originalRelay, adjustedWeight.toString()])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No existing zap tags, use simple two-way split between highlighter and source author
|
||||||
|
const authorWeight = Math.round(100 - highlighterPercentage)
|
||||||
|
|
||||||
|
// Add zap tag for the highlighter
|
||||||
|
event.tags.push(['zap', highlighterPubkey, zapRelay, highlighterPercentage.toString()])
|
||||||
|
|
||||||
|
// Add zap tag for the original author (only if different from highlighter)
|
||||||
|
if (sourceEvent.pubkey !== highlighterPubkey && authorWeight > 0) {
|
||||||
|
event.tags.push(['zap', sourceEvent.pubkey, zapRelay, authorWeight.toString()])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user