···1from aiodns import DNSResolver, error as dns_error
2from aiohttp.client import ClientSession
03from os import getenv
4from re import match as regex_match
5from typing import Any
···3536 if is_valid_handle(query):
37 handle = query.lower()
38- did = await resolve_did_from_handle(handle, didkv)
39 if not did:
40 return None
41 doc = await resolve_doc_from_did(client, did)
···54 handle = handle_from_doc(doc)
55 if not handle:
56 return None
57- if await resolve_did_from_handle(handle, didkv) != did:
58 return None
59 return (did, handle, doc)
60···737475async def resolve_did_from_handle(
076 handle: str,
77 kv: KV = nokv,
78 reload: bool = False,
79) -> str | None:
80- """Returns the DID for a given handle"""
8182 if not is_valid_handle(handle):
83 return None
···86 if did is not None and not reload:
87 return did
8889- resolver = DNSResolver()
90- try:
91- result = await resolver.query(f"_atproto.{handle}", "TXT")
92- except dns_error.DNSError:
93- return None
0000000000000000000000009495 for record in result:
96- value = str(record.text).replace('"', "")
97 if value.startswith("did="):
98 did = value[4:]
99 if is_valid_did(did):
100- kv.set(handle, value=did)
101 return did
102103 return None
···1from aiodns import DNSResolver, error as dns_error
2from aiohttp.client import ClientSession
3+from asyncio import tasks
4from os import getenv
5from re import match as regex_match
6from typing import Any
···3637 if is_valid_handle(query):
38 handle = query.lower()
39+ did = await resolve_did_from_handle(client, handle, didkv)
40 if not did:
41 return None
42 doc = await resolve_doc_from_did(client, did)
···55 handle = handle_from_doc(doc)
56 if not handle:
57 return None
58+ if await resolve_did_from_handle(client, handle, didkv) != did:
59 return None
60 return (did, handle, doc)
61···747576async def resolve_did_from_handle(
77+ client: ClientSession,
78 handle: str,
79 kv: KV = nokv,
80 reload: bool = False,
81) -> str | None:
82+ """Returns the DID for a given handle."""
8384 if not is_valid_handle(handle):
85 return None
···88 if did is not None and not reload:
89 return did
9091+ did = await _resolve_did_from_handle_dns(handle)
92+ if did is None:
93+ did = await _resolve_did_from_handle_wk(client, handle)
94+95+ if did is not None and is_valid_did(did):
96+ kv.set(handle, value=did)
97+ return did
98+99+ return None
100+101+102+async def _resolve_did_from_handle_wk(client: ClientSession, handle: str) -> str | None:
103+ """Resolve the DID for a given handle via .well-known"""
104+105+ url = f"https://{handle}/.well-known/atproto-did"
106+ response = await client.get(url)
107+ if response.ok:
108+ return await response.text()
109+ return None
110+111+112+async def _resolve_did_from_handle_dns(handle: str) -> str | None:
113+ """Resolve the DID for a given handle via DNS."""
114+115+ async with DNSResolver() as resolver:
116+ try:
117+ result = await resolver.query(f"_atproto.{handle}", "TXT")
118+ except dns_error.DNSError:
119+ return None
120121 for record in result:
122+ value = str(record.text).strip('"')
123 if value.startswith("did="):
124 did = value[4:]
125 if is_valid_did(did):
0126 return did
127128 return None