This commit is contained in:
parent
04a9061663
commit
79ef9fa6d5
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
59
app/services/nostr_manager/fetch_event.rb
Normal file
59
app/services/nostr_manager/fetch_event.rb
Normal file
@ -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
|
@ -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
|
||||
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
|
||||
if received_events >= @max_events
|
||||
puts "Found #{@max_events} events, ending the search"
|
||||
break
|
||||
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
|
||||
|
@ -9,7 +9,7 @@
|
||||
<section>
|
||||
<h3>Relays</h3>
|
||||
<%= render Settings::NostrRelayStatusComponent.new(
|
||||
relay_urls: @relay_urls
|
||||
nip65_event: @nip65_event
|
||||
) %>
|
||||
</section>
|
||||
<% end %>
|
||||
|
Loading…
x
Reference in New Issue
Block a user