mirror of
https://github.com/asmogo/nws.git
synced 2024-12-13 18:56:21 +00:00
64 lines
1.6 KiB
Go
64 lines
1.6 KiB
Go
package netstr
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"net"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/asmogo/nws/protocol"
|
|
"github.com/nbd-wtf/go-nostr"
|
|
)
|
|
|
|
// NostrDNS does not resolve anything.
|
|
type NostrDNS struct {
|
|
pool *nostr.SimplePool
|
|
nostrRelays []string
|
|
}
|
|
|
|
var (
|
|
errPoolIsNil = errors.New("pool is nil")
|
|
errFailedToFindExitNodeEvent = errors.New("failed to find exit node event")
|
|
errExitNodeEventIsExpired = errors.New("exit node event is expired")
|
|
)
|
|
|
|
func NewNostrDNS(pool *nostr.SimplePool, nostrRelays []string) *NostrDNS {
|
|
return &NostrDNS{
|
|
pool: pool,
|
|
nostrRelays: nostrRelays,
|
|
}
|
|
}
|
|
|
|
func (d NostrDNS) Resolve(ctx context.Context, name string) (context.Context, net.IP, error) {
|
|
if strings.HasSuffix(name, ".nostr") || strings.HasPrefix(name, "npub") || strings.HasPrefix(name, "nprofile") {
|
|
|
|
return ctx, nil, nil
|
|
}
|
|
addr, err := net.ResolveIPAddr("ip", name)
|
|
if err != nil {
|
|
return ctx, nil, fmt.Errorf("failed to resolve ip address: %w", err)
|
|
}
|
|
if d.pool == nil {
|
|
return ctx, nil, errPoolIsNil
|
|
}
|
|
since := nostr.Timestamp(time.Now().Add(-time.Second * 10).Unix())
|
|
ev := d.pool.QuerySingle(ctx, d.nostrRelays, nostr.Filter{
|
|
Kinds: []int{protocol.KindAnnouncementEvent},
|
|
Since: &since,
|
|
})
|
|
if ev == nil {
|
|
return ctx, nil, errFailedToFindExitNodeEvent
|
|
}
|
|
if ev.CreatedAt < since {
|
|
return ctx, nil, errExitNodeEventIsExpired
|
|
}
|
|
ctx = context.WithValue(ctx, TargetPublicKey, ev.PubKey)
|
|
return ctx, addr.IP, nil
|
|
}
|
|
|
|
type ContextKeyTargetPublicKey string
|
|
|
|
const TargetPublicKey ContextKeyTargetPublicKey = "TargetPublicKey"
|