damus

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

NostrLink.swift (2415B)


      1 //
      2 //  NostrLink.swift
      3 //  damus
      4 //
      5 //  Created by William Casarin on 2022-05-05.
      6 //
      7 
      8 import Foundation
      9 
     10 
     11 enum NostrLink: Equatable {
     12     case ref(RefId)
     13     case filter(NostrFilter)
     14     case script([UInt8])
     15 }
     16 
     17 func encode_pubkey_uri(_ pubkey: Pubkey) -> String {
     18     return "p:" + pubkey.hex()
     19 }
     20 
     21 // TODO: bech32 and relay hints
     22 func encode_event_id_uri(_ noteid: NoteId) -> String {
     23     return "e:" + noteid.hex()
     24 }
     25 
     26 func parse_nostr_ref_uri_type(_ p: Parser) -> String? {
     27     if parse_char(p, "p") {
     28         return "p"
     29     }
     30     
     31     if parse_char(p, "e") {
     32         return "e"
     33     }
     34     
     35     return nil
     36 }
     37 
     38 func parse_hexstr(_ p: Parser, len: Int) -> String? {
     39     var i: Int = 0
     40     
     41     if len % 2 != 0 {
     42         return nil
     43     }
     44     
     45     let start = p.pos
     46     
     47     while i < len {
     48         guard parse_hex_char(p) != nil else {
     49             p.pos = start
     50             return nil
     51         }
     52         i += 1
     53     }
     54     
     55     return String(substring(p.str, start: start, end: p.pos))
     56 }
     57 
     58 func decode_nostr_bech32_uri(_ s: String) -> NostrLink? {
     59     guard let obj = Bech32Object.parse(s) else {
     60         return nil
     61     }
     62     
     63     switch obj {
     64         case .nsec(let privkey):
     65             guard let pubkey = privkey_to_pubkey(privkey: privkey) else { return nil }
     66             return .ref(.pubkey(pubkey))
     67         case .npub(let pubkey):
     68             return .ref(.pubkey(pubkey))
     69         case .note(let id):
     70             return .ref(.event(id))
     71         case .nscript(let data):
     72             return .script(data)
     73         case .naddr(let naddr):
     74             return .ref(.naddr(naddr))
     75         case .nevent(let nevent):
     76             return .ref(.event(nevent.noteid))
     77         case .nprofile(let nprofile):
     78             return .ref(.pubkey(nprofile.author))
     79         case .nrelay(_):
     80             return .none
     81         }
     82 }
     83 
     84 func decode_nostr_uri(_ s: String) -> NostrLink? {
     85     let uri = remove_nostr_uri_prefix(s)
     86     
     87     let parts = uri.split(separator: ":")
     88         .reduce(into: Array<String>()) { acc, str in
     89             guard let decoded = str.removingPercentEncoding else {
     90                 return
     91             }
     92             acc.append(decoded)
     93             return
     94         }
     95 
     96     if parts.count >= 2 && parts[0] == "t" {
     97         return .filter(NostrFilter(hashtag: [parts[1].lowercased()]))
     98     }
     99 
    100     guard parts.count == 1 else {
    101         return nil
    102     }
    103 
    104     let part = parts[0]
    105     
    106     return decode_nostr_bech32_uri(part)
    107 }