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)
|
||||
if (typeof source === 'object' && 'kind' in source) {
|
||||
const zapSplitPercentage = settings?.zapSplitPercentage ?? 50
|
||||
addZapTags(highlightEvent, account.pubkey, source.pubkey, zapSplitPercentage)
|
||||
addZapTags(highlightEvent, account.pubkey, source, zapSplitPercentage)
|
||||
}
|
||||
|
||||
// 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)
|
||||
* Respects existing zap tags in the source event (author group)
|
||||
* @param event The highlight event to add zap tags to
|
||||
* @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)
|
||||
*/
|
||||
function addZapTags(
|
||||
event: NostrEvent,
|
||||
highlighterPubkey: string,
|
||||
authorPubkey: string,
|
||||
sourceEvent: NostrEvent,
|
||||
highlighterPercentage: number = 50
|
||||
): 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)
|
||||
const zapRelay = RELAYS.find(r => !r.includes('localhost')) || RELAYS[0]
|
||||
|
||||
// Extract existing zap tags from source event (the "author group")
|
||||
const existingZapTags = sourceEvent.tags.filter(tag => tag[0] === 'zap')
|
||||
|
||||
if (existingZapTags.length > 0) {
|
||||
// Calculate total weight from existing zap tags
|
||||
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, highlighterWeight.toString()])
|
||||
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 (authorPubkey !== highlighterPubkey) {
|
||||
event.tags.push(['zap', authorPubkey, zapRelay, authorWeight.toString()])
|
||||
if (sourceEvent.pubkey !== highlighterPubkey && authorWeight > 0) {
|
||||
event.tags.push(['zap', sourceEvent.pubkey, zapRelay, authorWeight.toString()])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user