@@ -7,9 +7,19 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
enum MentionType {
|
||||
case pubkey
|
||||
case event
|
||||
|
||||
var ref: String {
|
||||
switch self {
|
||||
case .pubkey:
|
||||
return "p"
|
||||
case .event:
|
||||
return "e"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Mention {
|
||||
@@ -42,38 +52,15 @@ enum Block {
|
||||
}
|
||||
}
|
||||
|
||||
struct ParsedMentions {
|
||||
let blocks: [Block]
|
||||
}
|
||||
|
||||
class Parser {
|
||||
var pos: Int
|
||||
var str: String
|
||||
|
||||
init(pos: Int, str: String) {
|
||||
self.pos = pos
|
||||
self.str = str
|
||||
}
|
||||
}
|
||||
|
||||
func consume_until(_ p: Parser, match: Character) -> Bool {
|
||||
var i: Int = 0
|
||||
let sub = substring(p.str, start: p.pos, end: p.str.count)
|
||||
for c in sub {
|
||||
if c == match {
|
||||
p.pos += i
|
||||
return true
|
||||
func render_blocks(blocks: [Block]) -> String {
|
||||
return blocks.reduce("") { str, block in
|
||||
switch block {
|
||||
case .mention(let m):
|
||||
return str + "#[\(m.index)]"
|
||||
case .text(let txt):
|
||||
return str + txt
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func substring(_ s: String, start: Int, end: Int) -> Substring {
|
||||
let ind = s.index(s.startIndex, offsetBy: start)
|
||||
let end = s.index(s.startIndex, offsetBy: end)
|
||||
return s[ind..<end]
|
||||
}
|
||||
|
||||
func parse_textblock(str: String, from: Int, to: Int) -> Block {
|
||||
@@ -86,7 +73,7 @@ func parse_mentions(content: String, tags: [[String]]) -> [Block] {
|
||||
var starting_from: Int = 0
|
||||
|
||||
while p.pos < content.count {
|
||||
if (!consume_until(p, match: "#")) {
|
||||
if (!consume_until(p, match: { $0 == "#" })) {
|
||||
blocks.append(parse_textblock(str: p.str, from: starting_from, to: p.str.count))
|
||||
return blocks
|
||||
}
|
||||
@@ -142,3 +129,17 @@ func parse_mention(_ p: Parser, tags: [[String]]) -> Mention? {
|
||||
return Mention(index: digit, type: kind, ref: ref)
|
||||
}
|
||||
|
||||
func post_to_event(post: NostrPost, privkey: String, pubkey: String) -> NostrEvent {
|
||||
let new_ev = NostrEvent(content: post.content, pubkey: pubkey)
|
||||
for id in post.references {
|
||||
var tag = [id.key, id.ref_id]
|
||||
if let relay_id = id.relay_id {
|
||||
tag.append(relay_id)
|
||||
}
|
||||
new_ev.tags.append(tag)
|
||||
}
|
||||
new_ev.calculate_id()
|
||||
new_ev.sign(privkey: privkey)
|
||||
return new_ev
|
||||
}
|
||||
|
||||
|
||||
69
damus/Models/Post.swift
Normal file
69
damus/Models/Post.swift
Normal file
@@ -0,0 +1,69 @@
|
||||
//
|
||||
// Post.swift
|
||||
// damus
|
||||
//
|
||||
// Created by William Casarin on 2022-05-07.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
struct NostrPost {
|
||||
let content: String
|
||||
let references: [ReferencedId]
|
||||
}
|
||||
|
||||
// TODO: parse nostr:{e,p}:pubkey uris as well
|
||||
func parse_post_mention_type(_ p: Parser) -> MentionType? {
|
||||
if parse_char(p, "@") {
|
||||
return .pubkey
|
||||
}
|
||||
|
||||
if parse_char(p, "&") {
|
||||
return .event
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func parse_post_reference(_ p: Parser) -> ReferencedId? {
|
||||
let start = p.pos
|
||||
|
||||
guard let typ = parse_post_mention_type(p) else {
|
||||
return parse_nostr_ref_uri(p)
|
||||
}
|
||||
|
||||
guard let id = parse_hexstr(p, len: 64) else {
|
||||
p.pos = start
|
||||
return nil
|
||||
}
|
||||
|
||||
return ReferencedId(ref_id: id, relay_id: nil, key: typ.ref)
|
||||
}
|
||||
|
||||
|
||||
/// Return a list of tags
|
||||
func parse_post_blocks(content: String) -> [PostBlock] {
|
||||
let p = Parser(pos: 0, str: content)
|
||||
var blocks: [PostBlock] = []
|
||||
var starting_from: Int = 0
|
||||
|
||||
if content.count == 0 {
|
||||
return []
|
||||
}
|
||||
|
||||
while p.pos < content.count {
|
||||
let pre_mention = p.pos
|
||||
if let reference = parse_post_reference(p) {
|
||||
blocks.append(parse_post_textblock(str: p.str, from: starting_from, to: pre_mention))
|
||||
blocks.append(.ref(reference))
|
||||
starting_from = p.pos
|
||||
} else {
|
||||
p.pos += 1
|
||||
}
|
||||
}
|
||||
|
||||
blocks.append(parse_post_textblock(str: content, from: starting_from, to: content.count))
|
||||
|
||||
return blocks
|
||||
}
|
||||
|
||||
31
damus/Models/PostBlock.swift
Normal file
31
damus/Models/PostBlock.swift
Normal file
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// PostBlock.swift
|
||||
// damus
|
||||
//
|
||||
// Created by William Casarin on 2022-05-07.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
enum PostBlock {
|
||||
case text(String)
|
||||
case ref(ReferencedId)
|
||||
|
||||
var is_text: Bool {
|
||||
if case .text = self {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var is_ref: Bool {
|
||||
if case .ref = self {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func parse_post_textblock(str: String, from: Int, to: Int) -> PostBlock {
|
||||
return .text(String(substring(str, start: from, end: to)))
|
||||
}
|
||||
14
damus/Models/ProfileUpdate.swift
Normal file
14
damus/Models/ProfileUpdate.swift
Normal file
@@ -0,0 +1,14 @@
|
||||
//
|
||||
// ProfileUpdate.swift
|
||||
// damus
|
||||
//
|
||||
// Created by William Casarin on 2022-05-06.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
struct ProfileUpdate {
|
||||
let pubkey: String
|
||||
let profile: Profile
|
||||
}
|
||||
Reference in New Issue
Block a user