atmosphere explorer
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

add fallback to resolve lexicon authority in search

Juliet 693cf161 6ad2a565

+37 -4
+9 -4
src/components/search.tsx
··· 11 11 Show, 12 12 } from "solid-js"; 13 13 import { isTouchDevice } from "../layout"; 14 - import { resolveLexiconAuthority } from "../utils/api"; 14 + import { resolveLexiconAuthority, resolveLexiconAuthorityDirect } from "../utils/api"; 15 15 import { appHandleLink, appList, appName, AppUrl } from "../utils/app-urls"; 16 16 import { createDebouncedValue } from "../utils/hooks/debounced"; 17 17 import { Modal } from "./modal"; ··· 160 160 } else if (prefix === "at:") { 161 161 navigate(`/${input}`); 162 162 } else if (prefix === "lex:") { 163 - const nsid = query as Nsid; 164 - const res = await resolveLexiconAuthority(nsid); 165 - navigate(`/at://${res}/com.atproto.lexicon.schema/${nsid}`); 163 + if (query.split(".").length >= 3) { 164 + const nsid = query as Nsid; 165 + const res = await resolveLexiconAuthority(nsid); 166 + navigate(`/at://${res}/com.atproto.lexicon.schema/${nsid}`); 167 + } else { 168 + const did = await resolveLexiconAuthorityDirect(query); 169 + navigate(`/at://${did}/com.atproto.lexicon.schema`); 170 + } 166 171 } else if (prefix === "pds:") { 167 172 navigate(`/${query}`); 168 173 } else if (input.startsWith("https://") || input.startsWith("http://")) {
+28
src/utils/api.ts
··· 112 112 return await authorityResolver.resolve(nsid); 113 113 }; 114 114 115 + const resolveLexiconAuthorityDirect = async (authority: string) => { 116 + const dohUrl = "https://dns.google/resolve?"; 117 + const reversedAuthority = authority.split(".").reverse().join("."); 118 + const domain = `_lexicon.${reversedAuthority}`; 119 + const url = new URL(dohUrl); 120 + url.searchParams.set("name", domain); 121 + url.searchParams.set("type", "TXT"); 122 + 123 + const response = await fetch(url.toString()); 124 + if (!response.ok) { 125 + throw new Error(`Failed to resolve lexicon authority for ${authority}`); 126 + } 127 + 128 + const data = await response.json(); 129 + if (!data.Answer || data.Answer.length === 0) { 130 + throw new Error(`No lexicon authority found for ${authority}`); 131 + } 132 + 133 + const txtRecord = data.Answer[0].data.replace(/"/g, ""); 134 + 135 + if (!txtRecord.startsWith("did=")) { 136 + throw new Error(`Invalid lexicon authority record for ${authority}`); 137 + } 138 + 139 + return txtRecord.replace("did=", ""); 140 + }; 141 + 115 142 const resolveLexiconSchema = async (authority: AtprotoDid, nsid: Nsid) => { 116 143 return await schemaResolver.resolve(authority, nsid); 117 144 }; ··· 178 205 resolveDidDoc, 179 206 resolveHandle, 180 207 resolveLexiconAuthority, 208 + resolveLexiconAuthorityDirect, 181 209 resolveLexiconSchema, 182 210 resolvePDS, 183 211 validateHandle,