ndb: make NostrEvents immutable

Since we can't mutate NdbNotes, let's update the existing codebase to
generate and sign ids on NostrEvent constructions. This will allow us to
match NdbNote's constructor
This commit is contained in:
William Casarin
2023-07-25 08:58:06 -07:00
parent e3c04465fc
commit 2f8aa29e92
47 changed files with 2211 additions and 462 deletions

View File

@@ -40,15 +40,15 @@ class Contacts {
for d in diff {
if new.contains(d) {
new_mutes.append(d)
new_mutes.append(d.string())
} else {
new_unmutes.append(d)
new_unmutes.append(d.string())
}
}
// TODO: set local mutelist here
self.muted = Set(ev.referenced_pubkeys.map({ $0.ref_id }))
self.muted = Set(ev.referenced_pubkeys.map({ $0.ref_id.string() }))
if new_mutes.count > 0 {
notify(.new_mutes, new_mutes)
}
@@ -72,11 +72,7 @@ class Contacts {
func get_followed_hashtags() -> Set<String> {
guard let ev = self.event else { return Set() }
return ev.tags.reduce(into: Set<String>(), { htags, tag in
if tag.count >= 2 && tag[0] == "t" && tag[1] != "" {
htags.insert(tag[1])
}
})
return Set(ev.referenced_hashtags.map({ $0.ref_id.string() }))
}
func add_friend_pubkey(_ pubkey: String) {
@@ -85,18 +81,17 @@ class Contacts {
func add_friend_contact(_ contact: NostrEvent) {
friends.insert(contact.pubkey)
for tag in contact.tags {
if tag.count >= 2 && tag[0] == "p" {
friend_of_friends.insert(tag[1])
for tag in contact.referenced_pubkeys {
let pk = tag.id.string()
friend_of_friends.insert(pk)
// Exclude themself and us.
if contact.pubkey != our_pubkey && contact.pubkey != tag[1] {
if pubkey_to_our_friends[tag[1]] == nil {
pubkey_to_our_friends[tag[1]] = Set<String>()
}
pubkey_to_our_friends[tag[1]]?.insert(contact.pubkey)
// Exclude themself and us.
if contact.pubkey != our_pubkey && contact.pubkey != pk {
if pubkey_to_our_friends[pk] == nil {
pubkey_to_our_friends[pk] = Set<String>()
}
pubkey_to_our_friends[pk]?.insert(contact.pubkey)
}
}
}
@@ -128,13 +123,10 @@ class Contacts {
}
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 {
guard let ev = follow_user_event(our_contacts: our_contacts, keypair: keypair, follow: follow) else {
return nil
}
ev.calculate_id()
ev.sign(privkey: keypair.privkey)
box.send(ev)
return ev
@@ -145,28 +137,35 @@ func unfollow_reference(postbox: PostBox, our_contacts: NostrEvent?, keypair: Fu
return nil
}
let ev = unfollow_reference_event(our_contacts: cs, our_pubkey: keypair.pubkey, unfollow: unfollow)
ev.calculate_id()
ev.sign(privkey: keypair.privkey)
guard let ev = unfollow_reference_event(our_contacts: cs, keypair: keypair, unfollow: unfollow) else {
return nil
}
postbox.send(ev)
return ev
}
func unfollow_reference_event(our_contacts: NostrEvent, our_pubkey: String, unfollow: ReferencedId) -> NostrEvent {
func unfollow_reference_event(our_contacts: NostrEvent, keypair: FullKeypair, unfollow: ReferencedId) -> NostrEvent? {
let tags = our_contacts.tags.filter { tag in
if tag.count >= 2 && tag[0] == unfollow.key && tag[1] == unfollow.ref_id {
if let key = tag[safe: 0],
let ref = tag[safe: 1],
let fst = unfollow.key.first,
let afst = AsciiCharacter(fst),
key.matches_char(afst),
ref.string() == unfollow.ref_id
{
return false
}
return true
}
let kind = NostrKind.contacts.rawValue
return NostrEvent(content: our_contacts.content, pubkey: our_pubkey, kind: kind, tags: tags)
return NostrEvent(content: our_contacts.content, keypair: keypair.to_keypair(), kind: kind, tags: tags)
}
func follow_user_event(our_contacts: NostrEvent?, our_pubkey: String, follow: ReferencedId) -> NostrEvent? {
func follow_user_event(our_contacts: NostrEvent?, keypair: FullKeypair, follow: ReferencedId) -> NostrEvent? {
guard let cs = our_contacts else {
// don't create contacts for now so we don't nuke our contact list due to connectivity issues
// we should only create contacts during profile creation
@@ -174,7 +173,7 @@ func follow_user_event(our_contacts: NostrEvent?, our_pubkey: String, follow: Re
return nil
}
guard let ev = follow_with_existing_contacts(our_pubkey: our_pubkey, our_contacts: cs, follow: follow) else {
guard let ev = follow_with_existing_contacts(keypair: keypair, our_contacts: cs, follow: follow) else {
return nil
}
@@ -186,23 +185,18 @@ func decode_json_relays(_ content: String) -> [String: RelayInfo]? {
return decode_json(content)
}
func remove_relay(ev: NostrEvent, current_relays: [RelayDescriptor], privkey: String, relay: String) -> NostrEvent? {
func remove_relay(ev: NostrEvent, current_relays: [RelayDescriptor], keypair: FullKeypair, relay: String) -> NostrEvent?{
var relays = ensure_relay_info(relays: current_relays, content: ev.content)
relays.removeValue(forKey: relay)
print("remove_relay \(relays)")
guard let content = encode_json(relays) else {
return nil
}
let new_ev = NostrEvent(content: content, pubkey: ev.pubkey, kind: 3, tags: ev.tags)
new_ev.calculate_id()
new_ev.sign(privkey: privkey)
return new_ev
return NostrEvent(content: content, keypair: keypair.to_keypair(), kind: 3, tags: ev.tags)
}
func add_relay(ev: NostrEvent, privkey: String, current_relays: [RelayDescriptor], relay: String, info: RelayInfo) -> NostrEvent? {
func add_relay(ev: NostrEvent, keypair: FullKeypair, current_relays: [RelayDescriptor], relay: String, info: RelayInfo) -> NostrEvent? {
var relays = ensure_relay_info(relays: current_relays, content: ev.content)
guard relays.index(forKey: relay) == nil else {
@@ -215,10 +209,7 @@ func add_relay(ev: NostrEvent, privkey: String, current_relays: [RelayDescriptor
return nil
}
let new_ev = NostrEvent(content: content, pubkey: ev.pubkey, kind: 3, tags: ev.tags)
new_ev.calculate_id()
new_ev.sign(privkey: privkey)
return new_ev
return NostrEvent(content: content, keypair: keypair.to_keypair(), kind: 3, tags: ev.tags)
}
func ensure_relay_info(relays: [RelayDescriptor], content: String) -> [String: RelayInfo] {
@@ -229,19 +220,22 @@ func ensure_relay_info(relays: [RelayDescriptor], content: String) -> [String: R
}
func is_already_following(contacts: NostrEvent, follow: ReferencedId) -> Bool {
return contacts.references(id: follow.ref_id, key: follow.key)
guard let key = follow.key.first_char() else { return false }
return contacts.references(id: follow.ref_id, key: key)
}
func follow_with_existing_contacts(our_pubkey: String, our_contacts: NostrEvent, follow: ReferencedId) -> NostrEvent? {
func follow_with_existing_contacts(keypair: FullKeypair, our_contacts: NostrEvent, follow: ReferencedId) -> NostrEvent? {
// don't update if we're already following
if is_already_following(contacts: our_contacts, follow: follow) {
return nil
}
let kind = NostrKind.contacts.rawValue
var tags = our_contacts.tags
var tags = our_contacts.tags.strings()
tags.append(refid_to_tag(follow))
return NostrEvent(content: our_contacts.content, pubkey: our_pubkey, kind: kind, tags: tags)
return NostrEvent(content: our_contacts.content, keypair: keypair.to_keypair(), kind: kind, tags: tags)
}
func make_contact_relays(_ relays: [RelayDescriptor]) -> [String: RelayInfo] {