forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {useQuery} from '@tanstack/react-query'
2
3import {DOH_ENDPOINT} from '#/lib/constants'
4import {STALE} from '#/state/queries'
5
6const DNS_RECORD_TYPES = ['A', 'AAAA', 'CNAME'] as const
7
8type DnsJsonResponse = {
9 Answer?: Array<{data?: string}>
10}
11
12export const RQKEY_ROOT = 'handle-link'
13export const RQKEY = (handle: string) => [RQKEY_ROOT, handle]
14
15async function hasDnsAnswers(
16 handle: string,
17 type: (typeof DNS_RECORD_TYPES)[number],
18 signal?: AbortSignal,
19) {
20 const url = new URL(DOH_ENDPOINT)
21 url.searchParams.set('name', handle)
22 url.searchParams.set('type', type)
23
24 const response = await fetch(url, {
25 headers: {
26 accept: 'application/dns-json',
27 },
28 redirect: 'follow',
29 signal,
30 })
31
32 if (!response.ok) {
33 return false
34 }
35
36 const result = (await response.json()) as DnsJsonResponse
37 return Array.isArray(result.Answer) && result.Answer.length > 0
38}
39
40export async function hasWorkingHandleLink(
41 handle: string,
42 signal?: AbortSignal,
43) {
44 const results = await Promise.allSettled(
45 DNS_RECORD_TYPES.map(type => hasDnsAnswers(handle, type, signal)),
46 )
47
48 signal?.throwIfAborted()
49
50 return results.some(
51 result => result.status === 'fulfilled' && Boolean(result.value),
52 )
53}
54
55export function useHandleLinkQuery(handle: string, enabled = true) {
56 return useQuery({
57 queryKey: RQKEY(handle),
58 queryFn: async ({signal}) => {
59 return hasWorkingHandleLink(handle, signal)
60 },
61 enabled,
62 staleTime: STALE.HOURS.ONE,
63 })
64}