likes, mention parsing, lots of stuff
Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
@@ -9,14 +9,21 @@ import Foundation
|
||||
|
||||
|
||||
class ActionBarModel: ObservableObject {
|
||||
@Published var our_like_event: NostrEvent? = nil
|
||||
@Published var our_boost_event: NostrEvent? = nil
|
||||
@Published var our_like: NostrEvent?
|
||||
@Published var our_boost: NostrEvent?
|
||||
@Published var likes: Int
|
||||
|
||||
init(likes: Int, our_like: NostrEvent?, our_boost: NostrEvent?) {
|
||||
self.likes = likes
|
||||
self.our_like = our_like
|
||||
self.our_boost = our_boost
|
||||
}
|
||||
|
||||
var liked: Bool {
|
||||
return our_like_event != nil
|
||||
return our_like != nil
|
||||
}
|
||||
|
||||
var boosted: Bool {
|
||||
return our_boost_event != nil
|
||||
return our_boost != nil
|
||||
}
|
||||
}
|
||||
|
||||
16
damus/Models/DamusState.swift
Normal file
16
damus/Models/DamusState.swift
Normal file
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// DamusState.swift
|
||||
// damus
|
||||
//
|
||||
// Created by William Casarin on 2022-04-30.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
struct DamusState {
|
||||
let pool: RelayPool
|
||||
let pubkey: String
|
||||
let likes: EventCounter
|
||||
let boosts: EventCounter
|
||||
|
||||
}
|
||||
53
damus/Models/LikeCounter.swift
Normal file
53
damus/Models/LikeCounter.swift
Normal file
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// LikeCounter.swift
|
||||
// damus
|
||||
//
|
||||
// Created by William Casarin on 2022-04-30.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
class EventCounter {
|
||||
var counts: [String: Int] = [:]
|
||||
var user_events: [String: Set<String>] = [:]
|
||||
var our_events: [String: NostrEvent] = [:]
|
||||
var our_pubkey: String
|
||||
|
||||
enum LikeResult {
|
||||
case user_already_liked
|
||||
case success(Int)
|
||||
}
|
||||
|
||||
init (our_pubkey: String) {
|
||||
self.our_pubkey = our_pubkey
|
||||
}
|
||||
|
||||
func add_event(_ ev: NostrEvent) -> LikeResult {
|
||||
let pubkey = ev.pubkey
|
||||
|
||||
if self.user_events[pubkey] == nil {
|
||||
self.user_events[pubkey] = Set()
|
||||
}
|
||||
|
||||
if user_events[pubkey]!.contains(ev.id) {
|
||||
// don't double count
|
||||
return .user_already_liked
|
||||
}
|
||||
|
||||
user_events[pubkey]!.insert(ev.id)
|
||||
|
||||
if ev.pubkey == self.our_pubkey {
|
||||
our_events[ev.id] = ev
|
||||
}
|
||||
|
||||
if counts[ev.id] == nil {
|
||||
counts[ev.id] = 1
|
||||
return .success(1)
|
||||
}
|
||||
|
||||
counts[ev.id]! += 1
|
||||
|
||||
return .success(counts[ev.id]!)
|
||||
}
|
||||
}
|
||||
19
damus/Models/Liked.swift
Normal file
19
damus/Models/Liked.swift
Normal file
@@ -0,0 +1,19 @@
|
||||
//
|
||||
// Liked.swift
|
||||
// damus
|
||||
//
|
||||
// Created by William Casarin on 2022-04-30.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
struct Liked {
|
||||
let like: NostrEvent
|
||||
let id: String
|
||||
let total: Int
|
||||
}
|
||||
|
||||
struct LikeRefs {
|
||||
let thread_id: String?
|
||||
let like_id: String
|
||||
}
|
||||
132
damus/Models/Mentions.swift
Normal file
132
damus/Models/Mentions.swift
Normal file
@@ -0,0 +1,132 @@
|
||||
//
|
||||
// Mentions.swift
|
||||
// damus
|
||||
//
|
||||
// Created by William Casarin on 2022-05-04.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
enum MentionType {
|
||||
case pubkey
|
||||
case event
|
||||
}
|
||||
|
||||
struct Mention {
|
||||
let index: Int
|
||||
let kind: MentionType
|
||||
}
|
||||
|
||||
enum Block {
|
||||
case text(String)
|
||||
case mention(Mention)
|
||||
|
||||
var is_text: Bool {
|
||||
if case .text = self {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var is_mention: Bool {
|
||||
if case .mention = self {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
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 {
|
||||
return .text(String(substring(str, start: from, end: to)))
|
||||
}
|
||||
|
||||
func parse_mentions(content: String, tags: [[String]]) -> [Block] {
|
||||
let p = Parser(pos: 0, str: content)
|
||||
var blocks: [Block] = []
|
||||
var starting_from: Int = 0
|
||||
|
||||
while p.pos < content.count {
|
||||
if (!consume_until(p, match: "#")) {
|
||||
blocks.append(parse_textblock(str: p.str, from: starting_from, to: p.str.count))
|
||||
return blocks
|
||||
}
|
||||
|
||||
let pre_mention = p.pos
|
||||
if let mention = parse_mention(p, tags: tags) {
|
||||
blocks.append(parse_textblock(str: p.str, from: starting_from, to: pre_mention))
|
||||
blocks.append(.mention(mention))
|
||||
starting_from = p.pos
|
||||
}
|
||||
}
|
||||
|
||||
return blocks
|
||||
}
|
||||
|
||||
func parse_mention(_ p: Parser, tags: [[String]]) -> Mention? {
|
||||
let start = p.pos
|
||||
|
||||
if !parse_str(p, "#[") {
|
||||
return nil
|
||||
}
|
||||
|
||||
guard let digit = parse_digit(p) else {
|
||||
p.pos = start
|
||||
return nil
|
||||
}
|
||||
|
||||
if !parse_char(p, "]") {
|
||||
return nil
|
||||
}
|
||||
|
||||
var kind: MentionType = .pubkey
|
||||
if digit > tags.count - 1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if tags[digit].count == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch tags[digit][0] {
|
||||
case "e": kind = .event
|
||||
case "p": kind = .pubkey
|
||||
default: return nil
|
||||
}
|
||||
|
||||
return Mention(index: digit, kind: kind)
|
||||
}
|
||||
|
||||
15
damus/Models/ParsedRefs.swift
Normal file
15
damus/Models/ParsedRefs.swift
Normal file
@@ -0,0 +1,15 @@
|
||||
//
|
||||
// ParsedRefs.swift
|
||||
// damus
|
||||
//
|
||||
// Created by William Casarin on 2022-04-30.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
struct ReplyRefs {
|
||||
let thread_id: String
|
||||
let direct_reply: String
|
||||
}
|
||||
|
||||
@@ -10,34 +10,35 @@ import Foundation
|
||||
class ProfileModel: ObservableObject {
|
||||
@Published var events: [NostrEvent] = []
|
||||
let pubkey: String
|
||||
let pool: RelayPool
|
||||
let damus: DamusState
|
||||
|
||||
var seen_event: Set<String> = Set()
|
||||
var sub_id = UUID().description
|
||||
|
||||
|
||||
init(pubkey: String, pool: RelayPool) {
|
||||
init(pubkey: String, damus: DamusState) {
|
||||
self.pubkey = pubkey
|
||||
self.pool = pool
|
||||
self.damus = damus
|
||||
}
|
||||
|
||||
func unsubscribe() {
|
||||
print("unsubscribing from profile \(pubkey) with sub_id \(sub_id)")
|
||||
pool.unsubscribe(sub_id: sub_id)
|
||||
damus.pool.unsubscribe(sub_id: sub_id)
|
||||
}
|
||||
|
||||
func subscribe() {
|
||||
let kinds: [Int] = [
|
||||
NostrKind.text.rawValue,
|
||||
NostrKind.delete.rawValue,
|
||||
NostrKind.contacts.rawValue,
|
||||
NostrKind.metadata.rawValue,
|
||||
NostrKind.boost.rawValue
|
||||
]
|
||||
|
||||
var filter = NostrFilter.filter_kinds(kinds)
|
||||
filter.authors = [pubkey]
|
||||
|
||||
var filter = NostrFilter.filter_authors([pubkey])
|
||||
filter.kinds = kinds
|
||||
|
||||
print("subscribing to profile \(pubkey) with sub_id \(sub_id)")
|
||||
pool.subscribe(sub_id: sub_id, filters: [filter], handler: handle_event)
|
||||
damus.pool.subscribe(sub_id: sub_id, filters: [filter], handler: handle_event)
|
||||
}
|
||||
|
||||
func add_event(_ ev: NostrEvent) {
|
||||
|
||||
@@ -62,14 +62,16 @@ class ThreadModel: ObservableObject {
|
||||
}
|
||||
|
||||
func subscribe() {
|
||||
let kinds: [Int] = [1, 5, 6]
|
||||
let kinds: [Int] = [1, 5, 6, 7]
|
||||
var ref_events = NostrFilter.filter_kinds(kinds)
|
||||
var events_filter = NostrFilter.filter_kinds(kinds)
|
||||
//var likes_filter = NostrFilter.filter_kinds(7])
|
||||
|
||||
// TODO: add referenced relays
|
||||
ref_events.referenced_ids = event.referenced_ids.map { $0.ref_id }
|
||||
ref_events.referenced_ids!.append(event.id)
|
||||
|
||||
//likes_filter.ids = ref_events.referenced_ids!
|
||||
events_filter.ids = ref_events.referenced_ids!
|
||||
|
||||
print("subscribing to thread \(event.id) with sub_id \(sub_id)")
|
||||
@@ -110,7 +112,9 @@ class ThreadModel: ObservableObject {
|
||||
switch res {
|
||||
case .event(let sub_id, let ev):
|
||||
if sub_id == self.sub_id {
|
||||
add_event(ev)
|
||||
if ev.known_kind == .text {
|
||||
add_event(ev)
|
||||
}
|
||||
}
|
||||
|
||||
case .notice(let note):
|
||||
|
||||
Reference in New Issue
Block a user