From 1136808afa4f30a2002c051756fefb8a05cda656 Mon Sep 17 00:00:00 2001 From: William Casarin Date: Thu, 13 Jul 2023 09:01:41 -0700 Subject: [PATCH] contacts: generalize following to allow any reference I noticed we are not using the PostBox when following new users. Not good! This is probably why following users sometimes does not work. Changelog-Fixed: Fixed a bug where following a user might not work due to poor connectivity --- damus/ContentView.swift | 52 +++++++++++++++++-------------------- damus/Models/Contacts.swift | 33 ++++++++++++----------- 2 files changed, 42 insertions(+), 43 deletions(-) diff --git a/damus/ContentView.swift b/damus/ContentView.swift index a506f11c..e676fc30 100644 --- a/damus/ContentView.swift +++ b/damus/ContentView.swift @@ -880,49 +880,45 @@ func timeline_name(_ timeline: Timeline?) -> String { } func handle_unfollow(state: DamusState, notif: Notification) { - guard let privkey = state.keypair.privkey else { + guard let keypair = state.keypair.to_full() else { return } let target = notif.object as! FollowTarget let pk = target.pubkey let old_contacts = state.contacts.event - - if let ev = unfollow_user(postbox: state.postbox, - our_contacts: old_contacts, - pubkey: state.pubkey, - privkey: privkey, - unfollow: pk) { - notify(.unfollowed, pk) - state.contacts.event = ev - state.contacts.remove_friend(pk) - state.user_search_cache.updateOwnContactsPetnames(id: state.pubkey, oldEvent: old_contacts, newEvent: ev) - } + guard let ev = unfollow_reference(postbox: state.postbox, our_contacts: old_contacts, keypair: keypair, unfollow: .p(pk)) + else { return } + + notify(.unfollowed, pk) + + state.contacts.event = ev + state.contacts.remove_friend(pk) + state.user_search_cache.updateOwnContactsPetnames(id: state.pubkey, oldEvent: old_contacts, newEvent: ev) } func handle_follow(state: DamusState, notif: Notification) { - guard let privkey = state.keypair.privkey else { + guard let keypair = state.keypair.to_full() else { return } let fnotify = notif.object as! FollowTarget - if let ev = follow_user(pool: state.pool, - our_contacts: state.contacts.event, - pubkey: state.pubkey, - privkey: privkey, - follow: ReferencedId(ref_id: fnotify.pubkey, relay_id: nil, key: "p")) { - notify(.followed, fnotify.pubkey) - - state.contacts.event = ev - - switch fnotify { - case .pubkey(let pk): - state.contacts.add_friend_pubkey(pk) - case .contact(let ev): - state.contacts.add_friend_contact(ev) - } + guard let ev = follow_reference(box: state.postbox, our_contacts: state.contacts.event, keypair: keypair, follow: .p(fnotify.pubkey)) + else { + return + } + + notify(.followed, fnotify.pubkey) + + state.contacts.event = ev + + switch fnotify { + case .pubkey(let pk): + state.contacts.add_friend_pubkey(pk) + case .contact(let ev): + state.contacts.add_friend_contact(ev) } } diff --git a/damus/Models/Contacts.swift b/damus/Models/Contacts.swift index 1dbace6b..cce25c4b 100644 --- a/damus/Models/Contacts.swift +++ b/damus/Models/Contacts.swift @@ -118,37 +118,36 @@ class Contacts { } } -func follow_user(pool: RelayPool, our_contacts: NostrEvent?, pubkey: String, privkey: String, follow: ReferencedId) -> NostrEvent? { - guard let ev = follow_user_event(our_contacts: our_contacts, our_pubkey: pubkey, follow: follow) else { +func follow_reference(box: PostBox, our_contacts: NostrEvent?, keypair: FullKeypair, follow: ReferencedId) -> NostrEvent? { + guard let ev = follow_user_event(our_contacts: our_contacts, our_pubkey: keypair.pubkey, follow: follow) else { return nil } ev.calculate_id() - ev.sign(privkey: privkey) - - - pool.send(.event(ev)) - + ev.sign(privkey: keypair.privkey) + + box.send(ev) + return ev } -func unfollow_user(postbox: PostBox, our_contacts: NostrEvent?, pubkey: String, privkey: String, unfollow: String) -> NostrEvent? { +func unfollow_reference(postbox: PostBox, our_contacts: NostrEvent?, keypair: FullKeypair, unfollow: ReferencedId) -> NostrEvent? { guard let cs = our_contacts else { return nil } - let ev = unfollow_user_event(our_contacts: cs, our_pubkey: pubkey, unfollow: unfollow) + let ev = unfollow_reference_event(our_contacts: cs, our_pubkey: keypair.pubkey, unfollow: unfollow) ev.calculate_id() - ev.sign(privkey: privkey) - + ev.sign(privkey: keypair.privkey) + postbox.send(ev) return ev } -func unfollow_user_event(our_contacts: NostrEvent, our_pubkey: String, unfollow: String) -> NostrEvent { +func unfollow_reference_event(our_contacts: NostrEvent, our_pubkey: String, unfollow: ReferencedId) -> NostrEvent { let tags = our_contacts.tags.filter { tag in - if tag.count >= 2 && tag[0] == "p" && tag[1] == unfollow { + if tag.count >= 2 && tag[0] == unfollow.key && tag[1] == unfollow.ref_id { return false } return true @@ -220,12 +219,16 @@ func ensure_relay_info(relays: [RelayDescriptor], content: String) -> [String: R return relay_info } +func is_already_following(contacts: NostrEvent, follow: ReferencedId) -> Bool { + return contacts.references(id: follow.ref_id, key: follow.key) +} + func follow_with_existing_contacts(our_pubkey: String, our_contacts: NostrEvent, follow: ReferencedId) -> NostrEvent? { // don't update if we're already following - if our_contacts.references(id: follow.ref_id, key: "p") { + if is_already_following(contacts: our_contacts, follow: follow) { return nil } - + let kind = NostrKind.contacts.rawValue var tags = our_contacts.tags tags.append(refid_to_tag(follow))