This commit is contained in:
parent
04a9061663
commit
79ef9fa6d5
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
module Settings
|
module Settings
|
||||||
class NostrRelayStatusComponent < ViewComponent::Base
|
class NostrRelayStatusComponent < ViewComponent::Base
|
||||||
def initialize(relay_urls:)
|
def initialize(nip65_event:)
|
||||||
if relay_urls.present?
|
if nip65_event.present?
|
||||||
if relay_urls.any? { |r| r.include?("wss://nostr.kosmos.org") }
|
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"
|
@text = "You have a relay list, and the Kosmos relay is part of it"
|
||||||
@icon_name = "check-circle"
|
@icon_name = "check-circle"
|
||||||
@icon_color = "emerald-500"
|
@icon_color = "emerald-500"
|
||||||
@ -19,5 +19,13 @@ module Settings
|
|||||||
@icon_color = "amber-500"
|
@icon_color = "amber-500"
|
||||||
end
|
end
|
||||||
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
|
||||||
end
|
end
|
||||||
|
@ -136,10 +136,11 @@ class SettingsController < ApplicationController
|
|||||||
def fetch_nostr_user_metadata
|
def fetch_nostr_user_metadata
|
||||||
if @user.nostr_pubkey.present?
|
if @user.nostr_pubkey.present?
|
||||||
if @nip65_event = NostrManager::DiscoverUserRelays.call(pubkey: @user.nostr_pubkey)
|
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
|
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
|
else
|
||||||
@relays, @profile = [nil, nil]
|
@relays, @profile = [nil, nil]
|
||||||
end
|
end
|
||||||
|
@ -1,36 +1,21 @@
|
|||||||
module NostrManager
|
module NostrManager
|
||||||
class DiscoverUserProfile < NostrManagerService
|
class DiscoverUserProfile < NostrManagerService
|
||||||
MAX_EVENTS = 2
|
|
||||||
|
|
||||||
def initialize(pubkey:, relays: nil)
|
def initialize(pubkey:, relays: nil)
|
||||||
@pubkey = pubkey
|
@pubkey = pubkey
|
||||||
@relays = relays.present? ? relays : Setting.nostr_discovery_relays
|
@relays = relays.present? ? relays : Setting.nostr_discovery_relays
|
||||||
end
|
end
|
||||||
|
|
||||||
def call
|
def call
|
||||||
received_events = 0
|
|
||||||
profile_events = []
|
|
||||||
filter = Nostr::Filter.new(
|
filter = Nostr::Filter.new(
|
||||||
authors: [@pubkey],
|
authors: [@pubkey],
|
||||||
kinds: [0],
|
kinds: [0],
|
||||||
limit: 1,
|
limit: 1,
|
||||||
)
|
)
|
||||||
|
|
||||||
@relays.each do |url|
|
NostrManager::FetchLatestEvent.call(
|
||||||
event = NostrManager::FetchLatestEvent.call(filter: filter, relay_url: url)
|
relays: @relays,
|
||||||
|
filter: filter
|
||||||
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"] }
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,37 +1,21 @@
|
|||||||
module NostrManager
|
module NostrManager
|
||||||
class DiscoverUserRelays < NostrManagerService
|
class DiscoverUserRelays < NostrManagerService
|
||||||
MAX_EVENTS = 2
|
|
||||||
|
|
||||||
def initialize(pubkey:)
|
def initialize(pubkey:)
|
||||||
@pubkey = pubkey
|
@pubkey = pubkey
|
||||||
@relays = Setting.nostr_discovery_relays
|
@relays = Setting.nostr_discovery_relays
|
||||||
end
|
end
|
||||||
|
|
||||||
def call
|
def call
|
||||||
received_events = 0
|
|
||||||
nip65_events = []
|
|
||||||
user_relays = []
|
|
||||||
filter = Nostr::Filter.new(
|
filter = Nostr::Filter.new(
|
||||||
authors: [@pubkey],
|
authors: [@pubkey],
|
||||||
kinds: [10002],
|
kinds: [10002],
|
||||||
limit: 1,
|
limit: 1,
|
||||||
)
|
)
|
||||||
|
|
||||||
@relays.each do |url|
|
NostrManager::FetchLatestEvent.call(
|
||||||
event = NostrManager::FetchLatestEvent.call(filter: filter, relay_url: url)
|
relays: @relays,
|
||||||
|
filter: filter
|
||||||
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"] }
|
|
||||||
end
|
end
|
||||||
end
|
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
|
module NostrManager
|
||||||
class FetchLatestEvent < NostrManagerService
|
class FetchLatestEvent < NostrManagerService
|
||||||
TIMEOUT = 1
|
|
||||||
|
|
||||||
def initialize(filter:, relay_url:)
|
def initialize(relays:, filter:, max_events: 2)
|
||||||
|
@relays = relays
|
||||||
@filter = filter
|
@filter = filter
|
||||||
@relay = new_relay(relay_url)
|
@max_events = max_events
|
||||||
@client = Nostr::Client.new
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def call
|
def call
|
||||||
filter, client, relay = @filter, @client, @relay
|
received_events = 0
|
||||||
latest_event = nil
|
events = []
|
||||||
mutex = Mutex.new
|
|
||||||
received_event = ConditionVariable.new
|
|
||||||
log_prefix = "[nostr][#{@relay.name}]"
|
|
||||||
|
|
||||||
thread = Thread.new do
|
@relays.each do |url|
|
||||||
client.on :connect do
|
event = NostrManager::FetchEvent.call(filter: @filter, relay_url: url)
|
||||||
client.subscribe(filter: filter)
|
|
||||||
|
if event.present?
|
||||||
|
events << event if events.none? { |e| e["id"] == event["id"] }
|
||||||
|
received_events += 1
|
||||||
end
|
end
|
||||||
|
|
||||||
client.on :error do |e|
|
if received_events >= @max_events
|
||||||
Rails.logger.info "#{log_prefix} Error: #{e}"
|
puts "Found #{@max_events} events, ending the search"
|
||||||
Thread.current.exit
|
break
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
begin
|
events.min_by { |e| e["created_at"] }
|
||||||
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
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
<section>
|
<section>
|
||||||
<h3>Relays</h3>
|
<h3>Relays</h3>
|
||||||
<%= render Settings::NostrRelayStatusComponent.new(
|
<%= render Settings::NostrRelayStatusComponent.new(
|
||||||
relay_urls: @relay_urls
|
nip65_event: @nip65_event
|
||||||
) %>
|
) %>
|
||||||
</section>
|
</section>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user