Listen to git commits for a specific repo and run a shell command
1use trust_dns_resolver::Resolver;
2use trust_dns_resolver::config::{ResolverConfig, ResolverOpts};
3
4#[derive(Debug)]
5pub struct DidDoc {
6 pub did: String,
7}
8
9fn get_txt_did(handle: &String) -> Result<String, ()> {
10 // create a txt resolver
11 let resolver = match Resolver::new(ResolverConfig::default(), ResolverOpts::default()) {
12 Ok(val) => val,
13 Err(_) => return Err(()),
14 };
15
16 // resolve _atproto.handle to a TXT record
17 let txt_res = match resolver.txt_lookup("_atproto.".to_owned() + &handle) {
18 Ok(val) => val,
19 Err(_) => return Err(()), // collect all entries and convert to strings
20 }
21 .into_iter()
22 .map(|x| x.to_string())
23 .collect::<Vec<_>>();
24
25 // filter entries which do not start with `did=`
26 let did_res = txt_res
27 .clone()
28 .extract_if(.., |x| x.starts_with("did="))
29 .collect::<Vec<_>>();
30 // only 1 did= can exist
31 // https://atproto.com/specs/handle#:~:text=If%20multiple%20valid%20records%20with%20different%20DIDs%20are%20present,%20resolution%20should%20fail.
32 if did_res.len() != 1 {
33 return Err(());
34 }
35 let did = did_res[0].clone();
36
37 return Ok(did.clone());
38}
39
40fn get_http_did(handle: &String) -> Result<String, ()> {
41 let res =
42 match reqwest::blocking::get("https://".to_owned() + handle + "/.well-known/atproto-did") {
43 Ok(val) => val,
44 Err(_) => return Err(()),
45 };
46
47 // as per spec, non 2xx code means failure
48 if !res.status().is_success() {
49 return Err(());
50 }
51
52 let did_unparsed = match res.text() {
53 Ok(val) => val,
54 Err(_) => return Err(()),
55 };
56
57 let did = did_unparsed.trim();
58
59 if !did.starts_with("did:") {
60 return Err(());
61 };
62 return Ok(String::from(did));
63}
64}
65
66pub fn get_did(handle: String) -> Result<DidDoc, ()> {
67 let did = if let Ok(did) = get_txt_did(&handle) {
68 did
69 } else {
70 if let Ok(did) = get_http_did(&handle) {
71 did
72 } else {
73 return Err(());
74 }
75 };
76
77 return Ok(DidDoc { did });
78}