Browse Source

relays: keep in sync with user relay list

Still need to figure out how to ensure new bootstrap relays are added...

Changelog-Changed: Ensure contact relay list is kept in sync with internal relay pool
post-button-style
William Casarin 2 years ago
parent
commit
3824e95f29
  1. 1
      damus/ContentView.swift
  2. 9
      damus/Models/Contacts.swift
  3. 75
      damus/Models/HomeModel.swift
  4. 2
      damus/Nostr/Relay.swift
  5. 16
      damus/Nostr/RelayPool.swift
  6. 6
      damus/Util/Notifications.swift
  7. 9
      damus/Views/ConfigView.swift
  8. 10
      damus/Views/RelayView.swift

1
damus/ContentView.swift

@ -15,6 +15,7 @@ var BOOTSTRAP_RELAYS = [
"wss://nostr.fmt.wiz.biz",
"wss://relay.nostr.bg",
"wss://nostr.oxtr.dev",
"wss://nostr.v0l.io",
]
struct TimestampedProfile {

9
damus/Models/Contacts.swift

@ -139,13 +139,8 @@ func decode_json_relays(_ content: String) -> [String: RelayInfo]? {
return decode_json(content)
}
func remove_relay(ev: NostrEvent, privkey: String, relay: String) -> NostrEvent? {
let damus_relay = RelayDescriptor(url: URL(string: "wss://relay.damus.io")!, info: .rw)
var relays = ensure_relay_info(relays: [damus_relay], content: ev.content)
guard relays.index(forKey: relay) != nil else {
return nil
}
func remove_relay(ev: NostrEvent, current_relays: [RelayDescriptor], privkey: String, relay: String) -> NostrEvent? {
var relays = ensure_relay_info(relays: current_relays, content: ev.content)
relays.removeValue(forKey: relay)

75
damus/Models/HomeModel.swift

@ -446,21 +446,7 @@ func add_contact_if_friend(contacts: Contacts, ev: NostrEvent) {
contacts.add_friend_contact(ev)
}
func load_our_contacts(contacts: Contacts, our_pubkey: String, ev: NostrEvent) {
guard ev.pubkey == our_pubkey else {
return
}
// only use new stuff
if let current_ev = contacts.event {
guard ev.created_at > current_ev.created_at else {
return
}
}
let m_old_ev = contacts.event
contacts.event = ev
func load_our_contacts(contacts: Contacts, our_pubkey: String, m_old_ev: NostrEvent?, ev: NostrEvent) {
var new_pks = Set<String>()
// our contacts
for tag in ev.tags {
@ -572,34 +558,67 @@ func robohash(_ pk: String) -> String {
return "https://robohash.org/" + pk
}
func process_contact_event(pool: RelayPool, contacts: Contacts, pubkey: String, ev: NostrEvent) {
load_our_contacts(contacts: contacts, our_pubkey: pubkey, ev: ev)
load_our_relays(contacts: contacts, our_pubkey: pubkey, pool: pool, ev: ev)
add_contact_if_friend(contacts: contacts, ev: ev)
func load_our_stuff(pool: RelayPool, contacts: Contacts, pubkey: String, ev: NostrEvent) {
guard ev.pubkey == pubkey else {
return
}
func load_our_relays(contacts: Contacts, our_pubkey: String, pool: RelayPool, ev: NostrEvent) {
guard ev.pubkey == our_pubkey else {
// only use new stuff
if let current_ev = contacts.event {
guard ev.created_at > current_ev.created_at else {
return
}
}
// only load new stuff
if let old_contacts = contacts.event {
guard ev.created_at > old_contacts.created_at else {
return
let m_old_ev = contacts.event
contacts.event = ev
load_our_contacts(contacts: contacts, our_pubkey: pubkey, m_old_ev: m_old_ev, ev: ev)
load_our_relays(contacts: contacts, our_pubkey: pubkey, pool: pool, m_old_ev: m_old_ev, ev: ev)
}
func process_contact_event(pool: RelayPool, contacts: Contacts, pubkey: String, ev: NostrEvent) {
load_our_stuff(pool: pool, contacts: contacts, pubkey: pubkey, ev: ev)
add_contact_if_friend(contacts: contacts, ev: ev)
}
func load_our_relays(contacts: Contacts, our_pubkey: String, pool: RelayPool, m_old_ev: NostrEvent?, ev: NostrEvent) {
let bootstrap_dict: [String: RelayInfo] = [:]
let old_decoded = m_old_ev.flatMap { decode_json_relays($0.content) } ?? BOOTSTRAP_RELAYS.reduce(into: bootstrap_dict) { (d, r) in
d[r] = .rw
}
guard let decoded = decode_json_relays(ev.content) else {
return
}
var changed = false
var new = Set<String>()
for key in decoded.keys {
if let url = URL(string: key) {
if let _ = try? pool.add_relay(url, info: decoded[key]!) {
pool.connect(to: [key])
new.insert(key)
}
var old = Set<String>()
for key in old_decoded.keys {
old.insert(key)
}
let diff = old.symmetricDifference(new)
for d in diff {
changed = true
if new.contains(d) {
if let url = URL(string: d) {
try? pool.add_relay(url, info: decoded[d] ?? .rw)
}
} else {
pool.remove_relay(d)
}
}
if changed {
notify(.relays_changed, ())
}
}

2
damus/Nostr/Relay.swift

@ -28,12 +28,14 @@ class Relay: Identifiable {
let descriptor: RelayDescriptor
let connection: RelayConnection
var last_pong: UInt32
var flags: Int
init(descriptor: RelayDescriptor, connection: RelayConnection) {
self.flags = 0
self.descriptor = descriptor
self.connection = connection
self.last_pong = 0
}
func mark_broken() {

16
damus/Nostr/RelayPool.swift

@ -180,7 +180,22 @@ class RelayPool {
return nil
}
func record_last_pong(relay_id: String, event: NostrConnectionEvent) {
if case .ws_event(let ws_event) = event {
if case .pong = ws_event {
for relay in relays {
if relay.id == relay_id {
relay.last_pong = UInt32(Date.now.timeIntervalSince1970)
return
}
}
}
}
}
func handle_event(relay_id: String, event: NostrConnectionEvent) {
record_last_pong(relay_id: relay_id, event: event)
// handle reconnect logic, etc?
for handler in handlers {
handler.callback(relay_id, event)
@ -193,3 +208,4 @@ func add_rw_relay(_ pool: RelayPool, _ url: String) {
try? pool.add_relay(url_, info: RelayInfo.rw)
}

6
damus/Util/Notifications.swift

@ -13,6 +13,12 @@ extension Notification.Name {
}
}
extension Notification.Name {
static var relays_changed: Notification.Name {
return Notification.Name("relays_changed")
}
}
extension Notification.Name {
static var select_event: Notification.Name {
return Notification.Name("select_event")

9
damus/Views/ConfigView.swift

@ -41,13 +41,9 @@ struct ConfigView: View {
var body: some View {
ZStack(alignment: .leading) {
Form {
if let ev = state.contacts.event {
Section("Relays") {
if let relays = decode_json_relays(ev.content) {
List(Array(relays.keys.sorted()), id: \.self) { relay in
RelayView(state: state, ev: ev, relay: relay)
}
}
List(Array(state.pool.relays), id: \.descriptor.url) { relay in
RelayView(state: state, relay: relay.descriptor.url.absoluteString)
}
}
@ -113,7 +109,6 @@ struct ConfigView: View {
}
.sheet(isPresented: $show_add_relay) {
AddRelayView(show_add_relay: $show_add_relay, relay: $new_relay) { m_relay in
guard let relay = m_relay else {
return
}

10
damus/Views/RelayView.swift

@ -9,7 +9,6 @@ import SwiftUI
struct RelayView: View {
let state: DamusState
let ev: NostrEvent
let relay: String
let timer = Timer.publish(every: 2, on: .main, in: .common).autoconnect()
@ -46,7 +45,12 @@ struct RelayView: View {
.swipeActions {
if let privkey = state.keypair.privkey {
Button {
guard let new_ev = remove_relay( ev: ev, privkey: privkey, relay: relay) else {
guard let ev = state.contacts.event else {
return
}
let descriptors = state.pool.descriptors
guard let new_ev = remove_relay( ev: ev, current_relays: descriptors, privkey: privkey, relay: relay) else {
return
}
@ -64,6 +68,6 @@ struct RelayView: View {
struct RelayView_Previews: PreviewProvider {
static var previews: some View {
RelayView(state: test_damus_state(), ev: NostrEvent(content: "content", pubkey: "pk"), relay: "wss://relay.damus.io", conn_color: .red)
RelayView(state: test_damus_state(), relay: "wss://relay.damus.io", conn_color: .red)
}
}

Loading…
Cancel
Save