From 95d396defbe3b5c2fb3566b336f9b27700eae3ac Mon Sep 17 00:00:00 2001 From: Ashlynne Mitchell Date: Sun, 29 Mar 2026 16:23:53 -0700 Subject: [PATCH] refactor: split out `Atex.IdentityResolver.Handle.query_dns/2` --- lib/atex/identity_resolver/handle.ex | 13 +---- lib/atex/util.ex | 86 ++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 12 deletions(-) create mode 100644 lib/atex/util.ex diff --git a/lib/atex/identity_resolver/handle.ex b/lib/atex/identity_resolver/handle.ex index 4069638..420b151 100644 --- a/lib/atex/identity_resolver/handle.ex +++ b/lib/atex/identity_resolver/handle.ex @@ -45,7 +45,7 @@ defmodule Atex.IdentityResolver.Handle do @spec resolve_via_dns(String.t()) :: {:ok, String.t()} | :error defp resolve_via_dns(handle) do - with ["did=" <> did] <- query_dns("_atproto.#{handle}", :txt), + with ["did=" <> did] <- Atex.Util.query_dns("_atproto.#{handle}", :txt), "did:" <> _ <- did do {:ok, did} else @@ -60,15 +60,4 @@ defmodule Atex.IdentityResolver.Handle do _ -> :error end end - - @spec query_dns(String.t(), :inet_res.dns_rr_type()) :: list(String.t() | list(String.t())) - defp query_dns(domain, type) do - domain - |> String.to_charlist() - |> :inet_res.lookup(:in, type) - |> Enum.map(fn - [result] -> to_string(result) - result -> result - end) - end end diff --git a/lib/atex/util.ex b/lib/atex/util.ex new file mode 100644 index 0000000..efb43a4 --- /dev/null +++ b/lib/atex/util.ex @@ -0,0 +1,86 @@ +defmodule Atex.Util do + # IDK why I can't use `:inet.dns_rr_type()`, I get a warning it doesn't exist, but it does. + @type dns_type() :: + :a + | :aaaa + | :caa + | :cname + | :gid + | :hinfo + | :ns + | :mb + | :md + | :mg + | :mf + | :minfo + | :mx + | :naptr + | :null + | :ptr + | :soa + | :spf + | :srv + | :txt + | :uid + | :uinfo + | :unspec + | :uri + | :wks + + defguardp is_ipv4(a, b, c, d) + when is_integer(a) and is_integer(b) and is_integer(c) and is_integer(d) + + defguardp is_ipv4(value) + when is_tuple(value) and tuple_size(value) == 4 and + is_ipv4(elem(value, 0), elem(value, 1), elem(value, 2), elem(value, 3)) + + defguardp is_ipv6(a, b, c, d, e, f, g, h) + when is_integer(a) and is_integer(b) and is_integer(c) and is_integer(d) and + is_integer(e) and is_integer(f) and is_integer(g) and is_integer(h) + + defguardp is_ipv6(value) + when is_tuple(value) and tuple_size(value) == 8 and + is_ipv6( + elem(value, 0), + elem(value, 1), + elem(value, 2), + elem(value, 3), + elem(value, 4), + elem(value, 5), + elem(value, 6), + elem(value, 7) + ) + + @spec query_dns(String.t(), dns_type()) :: + list(String.t() | {priority :: integer(), String.t()}) + def query_dns(domain, type) do + domain + |> String.to_charlist() + |> :inet_res.lookup(:in, type) + |> Enum.map(fn + [result] -> + to_string(result) + + value when is_ipv4(value) -> + format_ipv4(value) + + value when is_ipv6(value) -> + format_ipv6(value) + + {prio, dns_name} when is_integer(prio) -> + {prio, to_string(dns_name)} + + result when is_binary(result) -> + result + end) + end + + defp format_ipv4({a, b, c, d}) when is_ipv4(a, b, c, d), do: "#{a}.#{b}.#{c}.#{d}" + + defp format_ipv6({a, b, c, d, e, f, g, h}) when is_ipv6(a, b, c, d, e, f, g, h) do + [a, b, c, d, e, f, g, h] + |> Enum.map(&Integer.to_string(&1, 16)) + |> Enum.join(":") + |> String.downcase() + end +end -- 2.51.2