nip10: marker replies

This should drastically increase compatibility for damus replies in
other clients.

Also filter non-pubkey references when replying so we don't run into the
q-tag bug.

Changelog-Added: Added nip10 marker replies
Changelog-Fixed: Fixed issue where some replies were including the q tag
Fixes: https://github.com/damus-io/damus/issues/2239
Fixes: https://github.com/damus-io/damus/issues/2233
Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
William Casarin
2024-05-09 13:33:04 -07:00
parent 0b199a18b4
commit 514a053dce
10 changed files with 231 additions and 28 deletions

View File

@@ -1,156 +0,0 @@
//
// EventRef.swift
// damus
//
// Created by William Casarin on 2022-05-08.
//
import Foundation
enum EventRef: Equatable {
case mention(Mention<NoteRef>)
case thread_id(NoteRef)
case reply(NoteRef)
case reply_to_root(NoteRef)
var note_ref: NoteRef {
switch self {
case .mention(let mnref): return mnref.ref
case .thread_id(let ref): return ref
case .reply(let ref): return ref
case .reply_to_root(let ref): return ref
}
}
var is_mention: NoteRef? {
if case .mention(let m) = self { return m.ref }
return nil
}
var is_direct_reply: NoteRef? {
switch self {
case .mention:
return nil
case .thread_id:
return nil
case .reply(let refid):
return refid
case .reply_to_root(let refid):
return refid
}
}
var is_thread_id: NoteRef? {
switch self {
case .mention:
return nil
case .thread_id(let referencedId):
return referencedId
case .reply:
return nil
case .reply_to_root(let referencedId):
return referencedId
}
}
var is_reply: NoteRef? {
switch self {
case .mention:
return nil
case .thread_id:
return nil
case .reply(let refid):
return refid
case .reply_to_root(let refid):
return refid
}
}
}
func build_mention_indices(_ blocks: [Block], type: MentionType) -> Set<Int> {
return blocks.reduce(into: []) { acc, block in
switch block {
case .mention(let m):
if m.ref.key == type, let idx = m.index {
acc.insert(idx)
}
case .relay:
return
case .text:
return
case .hashtag:
return
case .url:
return
case .invoice:
return
}
}
}
func interp_event_refs_without_mentions(_ refs: [NoteRef]) -> [EventRef] {
if refs.count == 0 {
return []
}
if refs.count == 1 {
return [.reply_to_root(refs[0])]
}
var evrefs: [EventRef] = []
var first: Bool = true
for ref in refs {
if first {
evrefs.append(.thread_id(ref))
first = false
} else {
evrefs.append(.reply(ref))
}
}
return evrefs
}
func interp_event_refs_with_mentions(tags: Tags, mention_indices: Set<Int>) -> [EventRef] {
var mentions: [EventRef] = []
var ev_refs: [NoteRef] = []
var i: Int = 0
for tag in tags {
if let ref = NoteRef.from_tag(tag: tag) {
if mention_indices.contains(i) {
let mention = Mention<NoteRef>(index: i, ref: ref)
mentions.append(.mention(mention))
} else {
ev_refs.append(ref)
}
}
i += 1
}
var replies = interp_event_refs_without_mentions(ev_refs)
replies.append(contentsOf: mentions)
return replies
}
func interpret_event_refs(blocks: [Block], tags: Tags) -> [EventRef] {
if tags.count == 0 {
return []
}
/// build a set of indices for each event mention
let mention_indices = build_mention_indices(blocks, type: .e)
/// simpler case with no mentions
if mention_indices.count == 0 {
return interp_event_refs_without_mentions_ndb(References<NoteRef>(tags: tags))
}
return interp_event_refs_with_mentions(tags: tags, mention_indices: mention_indices)
}
func event_is_reply(_ refs: [EventRef]) -> Bool {
return refs.contains { evref in
return evref.is_reply != nil
}
}

View File

@@ -292,9 +292,8 @@ func make_post_tags(post_blocks: [Block], tags: [[String]]) -> PostTags {
}
func post_to_event(post: NostrPost, keypair: FullKeypair) -> NostrEvent? {
let tags = post.references.map({ r in r.tag }) + post.tags
let post_blocks = parse_post_blocks(content: post.content)
let post_tags = make_post_tags(post_blocks: post_blocks, tags: tags)
let post_tags = make_post_tags(post_blocks: post_blocks, tags: post.tags)
let content = post_tags.blocks
.map(\.asString)
.joined(separator: "")

View File

@@ -10,12 +10,10 @@ import Foundation
struct NostrPost {
let kind: NostrKind
let content: String
let references: [RefId]
let tags: [[String]]
init(content: String, references: [RefId], kind: NostrKind = .text, tags: [[String]] = []) {
init(content: String, kind: NostrKind = .text, tags: [[String]] = []) {
self.content = content
self.references = references
self.kind = kind
self.tags = tags
}