From 79ef9fa6d5e1ef77bc77e1e25b5e93fb8b0407e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Fri, 18 Oct 2024 18:15:52 +0200 Subject: [PATCH] WIP Refactor stuff --- .../settings/nostr_relay_status_component.rb | 14 ++++- app/controllers/settings_controller.rb | 5 +- .../nostr_manager/discover_user_profile.rb | 23 ++------ .../nostr_manager/discover_user_relays.rb | 24 ++------ app/services/nostr_manager/fetch_event.rb | 59 +++++++++++++++++++ .../nostr_manager/fetch_latest_event.rb | 58 +++++------------- .../settings/_nostr_user_relays.html.erb | 2 +- 7 files changed, 97 insertions(+), 88 deletions(-) create mode 100644 app/services/nostr_manager/fetch_event.rb diff --git a/app/components/settings/nostr_relay_status_component.rb b/app/components/settings/nostr_relay_status_component.rb index fbdc7f8..084a54c 100644 --- a/app/components/settings/nostr_relay_status_component.rb +++ b/app/components/settings/nostr_relay_status_component.rb @@ -2,9 +2,9 @@ module Settings class NostrRelayStatusComponent < ViewComponent::Base - def initialize(relay_urls:) - if relay_urls.present? - if relay_urls.any? { |r| r.include?("wss://nostr.kosmos.org") } + def initialize(nip65_event:) + if nip65_event.present? + if relay_urls(nip65_event).any? { |r| r.include?("wss://nostr.kosmos.org") } @text = "You have a relay list, and the Kosmos relay is part of it" @icon_name = "check-circle" @icon_color = "emerald-500" @@ -19,5 +19,13 @@ module Settings @icon_color = "amber-500" end end + + private + + def relay_urls(nip65_event) + nip65_event["tags"].select{ |t| t[0] == "r" }.map{ |t| t[1] } + # @inbox_relay_urls = relay_tags&.select{ |t| t[2] == "read" }&.map{ |t| t[1] } + # @outbox_relay_urls = relay_tags&.select{ |t| t[2] != "read" }&.map{ |t| t[1] } + end end end diff --git a/app/controllers/settings_controller.rb b/app/controllers/settings_controller.rb index a140f2e..6584c91 100644 --- a/app/controllers/settings_controller.rb +++ b/app/controllers/settings_controller.rb @@ -136,10 +136,11 @@ class SettingsController < ApplicationController def fetch_nostr_user_metadata if @user.nostr_pubkey.present? if @nip65_event = NostrManager::DiscoverUserRelays.call(pubkey: @user.nostr_pubkey) - @relay_urls = @nip65_event["tags"].select{ |t| t[0] == "r" }&.map{ |t| t[1] } + relay_tags = @nip65_event["tags"].select{ |t| t[0] == "r" } + outbox_relay_urls = relay_tags&.select{ |t| t[2] != "read" }&.map{ |t| t[1] } end - @profile = NostrManager::DiscoverUserProfile.call(pubkey: @user.nostr_pubkey, relays: @relay_urls) + @profile = NostrManager::DiscoverUserProfile.call(pubkey: @user.nostr_pubkey, relays: outbox_relay_urls) else @relays, @profile = [nil, nil] end diff --git a/app/services/nostr_manager/discover_user_profile.rb b/app/services/nostr_manager/discover_user_profile.rb index e98e198..9bf2dbe 100644 --- a/app/services/nostr_manager/discover_user_profile.rb +++ b/app/services/nostr_manager/discover_user_profile.rb @@ -1,36 +1,21 @@ module NostrManager class DiscoverUserProfile < NostrManagerService - MAX_EVENTS = 2 - def initialize(pubkey:, relays: nil) @pubkey = pubkey @relays = relays.present? ? relays : Setting.nostr_discovery_relays end def call - received_events = 0 - profile_events = [] filter = Nostr::Filter.new( authors: [@pubkey], kinds: [0], limit: 1, ) - @relays.each do |url| - event = NostrManager::FetchLatestEvent.call(filter: filter, relay_url: url) - - if event.present? - profile_events << event if profile_events.none? { |e| e["id"] == event["id"] } - received_events += 1 - end - - if received_events >= MAX_EVENTS - puts "Found #{MAX_EVENTS} events, ending the search" - break - end - end - - profile_events.min_by { |e| e["created_at"] } + NostrManager::FetchLatestEvent.call( + relays: @relays, + filter: filter + ) end end end diff --git a/app/services/nostr_manager/discover_user_relays.rb b/app/services/nostr_manager/discover_user_relays.rb index 6065ae1..213eaf7 100644 --- a/app/services/nostr_manager/discover_user_relays.rb +++ b/app/services/nostr_manager/discover_user_relays.rb @@ -1,37 +1,21 @@ module NostrManager class DiscoverUserRelays < NostrManagerService - MAX_EVENTS = 2 - def initialize(pubkey:) @pubkey = pubkey @relays = Setting.nostr_discovery_relays end def call - received_events = 0 - nip65_events = [] - user_relays = [] filter = Nostr::Filter.new( authors: [@pubkey], kinds: [10002], limit: 1, ) - @relays.each do |url| - event = NostrManager::FetchLatestEvent.call(filter: filter, relay_url: url) - - if event.present? - nip65_events << event if nip65_events.none? { |e| e["id"] == event["id"] } - received_events += 1 - end - - if received_events >= MAX_EVENTS - puts "Found #{MAX_EVENTS} events, ending the search" - break - end - end - - nip65_events.min_by { |e| e["created_at"] } + NostrManager::FetchLatestEvent.call( + relays: @relays, + filter: filter + ) end end end diff --git a/app/services/nostr_manager/fetch_event.rb b/app/services/nostr_manager/fetch_event.rb new file mode 100644 index 0000000..c62a4a5 --- /dev/null +++ b/app/services/nostr_manager/fetch_event.rb @@ -0,0 +1,59 @@ +module NostrManager + class FetchEvent < NostrManagerService + TIMEOUT = 1 + + def initialize(filter:, relay_url:) + @filter = filter + @relay = new_relay(relay_url) + @client = Nostr::Client.new + end + + def call + filter, client, relay = @filter, @client, @relay + event = nil + mutex = Mutex.new + received_event = ConditionVariable.new + log_prefix = "[nostr][#{@relay.name}]" + + thread = Thread.new do + client.on :connect do + client.subscribe(filter: filter) + end + + client.on :error do |e| + Rails.logger.info "#{log_prefix} Error: #{e}" + Thread.current.exit + end + + client.on :message do |m| + msg = JSON.parse(m) rescue nil + if msg && msg[0] == "EVENT" && msg[2] + puts "#{log_prefix} Event received: #{msg[2]["id"]}" + mutex.synchronize do + event = msg[2] + received_event.signal + end + elsif msg && msg[0] == "EOSE" + Thread.current.exit + end + end + + client.connect relay + end + + begin + Timeout.timeout(TIMEOUT) do + mutex.synchronize do + received_event.wait(mutex) if event.nil? + end + end + rescue Timeout::Error + puts "#{log_prefix} Timeout: No event received within #{TIMEOUT} seconds" + ensure + thread.exit + end + + event + end + end +end diff --git a/app/services/nostr_manager/fetch_latest_event.rb b/app/services/nostr_manager/fetch_latest_event.rb index ad47174..31f0f99 100644 --- a/app/services/nostr_manager/fetch_latest_event.rb +++ b/app/services/nostr_manager/fetch_latest_event.rb @@ -1,59 +1,31 @@ module NostrManager class FetchLatestEvent < NostrManagerService - TIMEOUT = 1 - def initialize(filter:, relay_url:) + def initialize(relays:, filter:, max_events: 2) + @relays = relays @filter = filter - @relay = new_relay(relay_url) - @client = Nostr::Client.new + @max_events = max_events end def call - filter, client, relay = @filter, @client, @relay - latest_event = nil - mutex = Mutex.new - received_event = ConditionVariable.new - log_prefix = "[nostr][#{@relay.name}]" + received_events = 0 + events = [] - thread = Thread.new do - client.on :connect do - client.subscribe(filter: filter) + @relays.each do |url| + event = NostrManager::FetchEvent.call(filter: @filter, relay_url: url) + + if event.present? + events << event if events.none? { |e| e["id"] == event["id"] } + received_events += 1 end - client.on :error do |e| - Rails.logger.info "#{log_prefix} Error: #{e}" - Thread.current.exit + if received_events >= @max_events + puts "Found #{@max_events} events, ending the search" + break end - - client.on :message do |m| - msg = JSON.parse(m) rescue nil - if msg && msg[0] == "EVENT" && msg[2] - puts "#{log_prefix} Event received: #{msg[2]["id"]}" - mutex.synchronize do - latest_event = msg[2] - received_event.signal - end - elsif msg && msg[0] == "EOSE" - Thread.current.exit - end - end - - client.connect relay end - begin - Timeout.timeout(TIMEOUT) do - mutex.synchronize do - received_event.wait(mutex) if latest_event.nil? - end - end - rescue Timeout::Error - puts "#{log_prefix} Timeout: No event received within #{TIMEOUT} seconds" - ensure - thread.exit - end - - latest_event + events.min_by { |e| e["created_at"] } end end end diff --git a/app/views/settings/_nostr_user_relays.html.erb b/app/views/settings/_nostr_user_relays.html.erb index e2e69ef..3006864 100644 --- a/app/views/settings/_nostr_user_relays.html.erb +++ b/app/views/settings/_nostr_user_relays.html.erb @@ -9,7 +9,7 @@

Relays

<%= render Settings::NostrRelayStatusComponent.new( - relay_urls: @relay_urls + nip65_event: @nip65_event ) %>
<% end %>