package nostr import ( "encoding/json" "net" "net/http" "strings" "git.minhas.io/asara/gologger" "git.minhas.io/asara/well-goknown/config" "github.com/jmoiron/sqlx" ) var ( DB *sqlx.DB ) type nostrUser struct { Pubkey string `db:"pubkey"` Relays *string `db:"relays,omitempty"` } type nostrWellKnown struct { Names map[string]string `json:"names"` Relays map[string][]string `json:"relays,omitempty"` } func GetNostrAddr(w http.ResponseWriter, r *http.Request) { l := gologger.Get(config.GetConfig().LogLevel).With().Str("context", "nostr").Logger() // get query string for username r.ParseForm() name := strings.ToLower(r.FormValue("name")) // normalize domain domain, _, err := net.SplitHostPort(r.Host) if err != nil { l.Debug().Msgf("unable to split hostname: %s", r.Host) domain = r.Host return } // get owner id for nip05 request var uid int DB.QueryRow("SELECT owner_id FROM nip05s WHERE name=$1 AND domain=$2", name, domain).Scan(&uid) // get the pubkey and relays associated with the nip05 user := nostrUser{} err = DB.QueryRow("SELECT pubkey, relays FROM users WHERE id=$1", uid).Scan(&user.Pubkey, &user.Relays) if err != nil { l.Error().Msgf("unable to get user for uid %v: %s", uid, err.Error()) return } // get all names associated with the pubkey names := []string{} err = DB.Select(&names, "SELECT nip05s.name FROM nip05s JOIN users ON nip05s.owner_id = users.id WHERE nip05s.owner_id = $1", uid) if err != nil { l.Error().Msgf("unable to get user for uid %v: %s", uid, err.Error()) return } // map of names n := make(map[string]string) for _, name := range names { n[name] = user.Pubkey } // map of relays s := make(map[string][]string) if user.Relays != nil { if strings.Contains(*user.Relays, ",") { s[user.Pubkey] = strings.Split(*user.Relays, ",") } else { s[user.Pubkey] = []string{*user.Relays} } } ret := nostrWellKnown{ Names: n, Relays: s, } j, err := json.Marshal(ret) if err != nil { l.Error().Msg(err.Error()) return } w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) w.Write(j) return }