initial reply revamp
It now understands mentions Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
@@ -53,6 +53,10 @@ class NostrEvent: Codable, Identifiable, CustomStringConvertible {
|
||||
return parse_mentions(content: self.content, tags: self.tags)
|
||||
}()
|
||||
|
||||
lazy var event_refs: [EventRef] = {
|
||||
return interpret_event_refs(blocks: self.blocks, tags: self.tags)
|
||||
}()
|
||||
|
||||
var description: String {
|
||||
let p = pow.map { String($0) } ?? "?"
|
||||
return "NostrEvent { id: \(id) pubkey \(pubkey) kind \(kind) tags \(tags) pow \(p) content '\(content)' }"
|
||||
@@ -79,28 +83,12 @@ class NostrEvent: Codable, Identifiable, CustomStringConvertible {
|
||||
return true
|
||||
}
|
||||
|
||||
/// find a non-root reply
|
||||
public func find_direct_reply() -> String? {
|
||||
var i = tags.count - 1
|
||||
var first: String? = nil
|
||||
var matches: Int = 0
|
||||
|
||||
while i >= 0 {
|
||||
let tag = tags[i]
|
||||
if tag.count >= 2 && tag[0] == "e" {
|
||||
if first == nil {
|
||||
first = tag[1]
|
||||
}
|
||||
matches += 1
|
||||
public func direct_replies() -> [ReferencedId] {
|
||||
return event_refs.reduce(into: []) { acc, evref in
|
||||
if let direct_reply = evref.is_direct_reply {
|
||||
acc.append(direct_reply)
|
||||
}
|
||||
i -= 1
|
||||
}
|
||||
|
||||
if matches <= 1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return first
|
||||
}
|
||||
|
||||
public func last_refid() -> ReferencedId? {
|
||||
@@ -120,29 +108,6 @@ class NostrEvent: Codable, Identifiable, CustomStringConvertible {
|
||||
return tag_to_refid(tags[last])
|
||||
}
|
||||
|
||||
public func directly_references(_ id: String) -> Bool {
|
||||
// conditions: if it only has 1 e ref
|
||||
// OR it has more than 1 e ref, ignoring the first
|
||||
|
||||
var nrefs = 0
|
||||
var i = 0
|
||||
var first_matched = false
|
||||
var matched = true
|
||||
|
||||
for tag in tags {
|
||||
if tag.count >= 2 && tag[0] == "e" {
|
||||
nrefs += 1
|
||||
if tag[1] == id {
|
||||
matched = true
|
||||
first_matched = nrefs == 1
|
||||
}
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
|
||||
return (nrefs == 1 && matched) || (nrefs > 1 && matched && !first_matched)
|
||||
}
|
||||
|
||||
public func references(id: String, key: String) -> Bool {
|
||||
for tag in tags {
|
||||
if tag.count >= 2 && tag[0] == key {
|
||||
@@ -156,13 +121,7 @@ class NostrEvent: Codable, Identifiable, CustomStringConvertible {
|
||||
}
|
||||
|
||||
public var is_reply: Bool {
|
||||
for tag in tags {
|
||||
if tag[0] == "e" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
return event_is_reply(self)
|
||||
}
|
||||
|
||||
public var referenced_ids: [ReferencedId] {
|
||||
@@ -438,3 +397,146 @@ func gather_reply_ids(our_pubkey: String, from: NostrEvent) -> [ReferencedId] {
|
||||
return ids
|
||||
}
|
||||
|
||||
enum EventRef {
|
||||
case mention(Mention)
|
||||
case thread_id(ReferencedId)
|
||||
case reply(ReferencedId)
|
||||
case reply_to_root(ReferencedId)
|
||||
|
||||
var is_mention: Mention? {
|
||||
if case .mention(let m) = self {
|
||||
return m
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var is_direct_reply: ReferencedId? {
|
||||
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: ReferencedId? {
|
||||
switch self {
|
||||
case .mention(let mention):
|
||||
return nil
|
||||
case .thread_id(let referencedId):
|
||||
return referencedId
|
||||
case .reply(let referencedId):
|
||||
return nil
|
||||
case .reply_to_root(let referencedId):
|
||||
return referencedId
|
||||
}
|
||||
}
|
||||
|
||||
var is_reply: ReferencedId? {
|
||||
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 has_any_e_refs(_ tags: [[String]]) -> Bool {
|
||||
for tag in tags {
|
||||
if tag.count >= 2 && tag[0] == "e" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
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.type == type {
|
||||
acc.insert(m.index)
|
||||
}
|
||||
case .text:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func interp_event_refs_without_mentions(_ refs: [ReferencedId]) -> [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: [[String]], mention_indices: Set<Int>) -> [EventRef] {
|
||||
var mentions: [EventRef] = []
|
||||
var ev_refs: [ReferencedId] = []
|
||||
var i: Int = 0
|
||||
|
||||
for tag in tags {
|
||||
if tag.count >= 2 && tag[0] == "e" {
|
||||
let ref = tag_to_refid(tag)!
|
||||
if mention_indices.contains(i) {
|
||||
let mention = Mention(index: i, type: .event, 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: [[String]]) -> [EventRef] {
|
||||
if tags.count == 0 {
|
||||
return []
|
||||
}
|
||||
|
||||
/// build a set of indices for each event mention
|
||||
let mention_indices = build_mention_indices(blocks, type: .event)
|
||||
|
||||
/// simpler case with no mentions
|
||||
if mention_indices.count == 0 {
|
||||
let ev_refs = get_referenced_ids(tags: tags, key: "e")
|
||||
return interp_event_refs_without_mentions(ev_refs)
|
||||
}
|
||||
|
||||
return interp_event_refs_with_mentions(tags: tags, mention_indices: mention_indices)
|
||||
}
|
||||
|
||||
|
||||
func event_is_reply(_ ev: NostrEvent) -> Bool {
|
||||
return ev.event_refs.contains { evref in
|
||||
return evref.is_reply != nil
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user