damus

nostr ios client
git clone git://jb55.com/damus
Log | Files | Refs | README | LICENSE

ContentParsing.swift (3395B)


      1 //
      2 //  ContentParsing.swift
      3 //  damus
      4 //
      5 //  Created by William Casarin on 2023-07-22.
      6 //
      7 
      8 import Foundation
      9 
     10 enum NoteContent {
     11     case note(NostrEvent)
     12     case content(String, TagsSequence?)
     13 
     14     init(note: NostrEvent, keypair: Keypair) {
     15         if note.known_kind == .dm {
     16             self = .content(note.get_content(keypair), note.tags)
     17         } else {
     18             self = .note(note)
     19         }
     20     }
     21 }
     22 
     23 func parsed_blocks_finish(bs: inout note_blocks, tags: TagsSequence?) -> Blocks {
     24     var out: [Block] = []
     25 
     26     var i = 0
     27     while (i < bs.num_blocks) {
     28         let block = bs.blocks[i]
     29 
     30         if let converted = Block(block, tags: tags) {
     31             out.append(converted)
     32         }
     33 
     34         i += 1
     35     }
     36 
     37     let words = Int(bs.words)
     38     blocks_free(&bs)
     39 
     40     return Blocks(words: words, blocks: out)
     41 
     42 }
     43 
     44 func parse_note_content(content: NoteContent) -> Blocks {
     45     var bs = note_blocks()
     46     bs.num_blocks = 0;
     47     
     48     blocks_init(&bs)
     49 
     50     switch content {
     51     case .content(let s, let tags):
     52         return s.withCString { cptr in
     53             damus_parse_content(&bs, cptr)
     54             return parsed_blocks_finish(bs: &bs, tags: tags)
     55         }
     56     case .note(let note):
     57         damus_parse_content(&bs, note.content_raw)
     58         return parsed_blocks_finish(bs: &bs, tags: note.tags)
     59     }
     60 }
     61 
     62 func interpret_event_refs_ndb(blocks: [Block], tags: TagsSequence) -> [EventRef] {
     63     if tags.count == 0 {
     64         return []
     65     }
     66     
     67     /// build a set of indices for each event mention
     68     let mention_indices = build_mention_indices(blocks, type: .e)
     69 
     70     /// simpler case with no mentions
     71     if mention_indices.count == 0 {
     72         return interp_event_refs_without_mentions_ndb(tags.note.referenced_noterefs)
     73     }
     74     
     75     return interp_event_refs_with_mentions_ndb(tags: tags, mention_indices: mention_indices)
     76 }
     77 
     78 func interp_event_refs_without_mentions_ndb(_ ev_tags: References<NoteRef>) -> [EventRef] {
     79     var evrefs: [EventRef] = []
     80     var first: Bool = true
     81     var root_id: NoteRef? = nil
     82     var any_marker: Bool = false
     83 
     84     for ref in ev_tags {
     85         if let marker = ref.marker {
     86             any_marker = true
     87             switch marker {
     88             case .root: root_id = ref
     89             case .reply: evrefs.append(.reply(ref))
     90             case .mention: evrefs.append(.mention(.noteref(ref)))
     91             }
     92         } else {
     93             if !any_marker && first {
     94                 root_id = ref
     95                 first = false
     96             } else if !any_marker {
     97                 evrefs.append(.reply(ref))
     98             }
     99         }
    100     }
    101 
    102     if let root_id {
    103         if evrefs.count == 0 {
    104             return [.reply_to_root(root_id)]
    105         } else {
    106             evrefs.insert(.thread_id(root_id), at: 0)
    107         }
    108     }
    109 
    110     return evrefs
    111 }
    112 
    113 func interp_event_refs_with_mentions_ndb(tags: TagsSequence, mention_indices: Set<Int>) -> [EventRef] {
    114     var mentions: [EventRef] = []
    115     var ev_refs: [NoteRef] = []
    116     var i: Int = 0
    117 
    118     for tag in tags {
    119         if let note_id = NoteRef.from_tag(tag: tag) {
    120             if mention_indices.contains(i) {
    121                 mentions.append(.mention(.noteref(note_id, index: i)))
    122             } else {
    123                 ev_refs.append(note_id)
    124             }
    125         }
    126         i += 1
    127     }
    128     
    129     var replies = interp_event_refs_without_mentions(ev_refs)
    130     replies.append(contentsOf: mentions)
    131     return replies
    132 }