3 request::{retry, RecvError},
8 use serde::{Deserialize, Serialize};
11 #[derive(Serialize, Deserialize, Debug)]
12 pub struct WebfingerLink {
13 pub rel: Option<String>,
14 #[serde(rename(serialize = "type", deserialize = "type"))]
15 pub type_: Option<String>,
16 pub href: Option<Url>,
17 #[serde(skip_serializing_if = "Option::is_none")]
18 pub template: Option<String>,
21 #[derive(Serialize, Deserialize, Debug)]
22 pub struct WebfingerResponse {
24 pub aliases: Vec<Url>,
25 pub links: Vec<WebfingerLink>,
28 pub enum WebfingerType {
33 /// Turns a person id like `@name@example.com` into an apub ID, like `https://example.com/user/name`,
35 pub async fn webfinger_resolve_actor(
38 webfinger_type: WebfingerType,
40 protocol_string: &str,
41 ) -> Result<Url, LemmyError> {
42 let webfinger_type = match webfinger_type {
43 WebfingerType::Person => "acct",
44 WebfingerType::Group => "group",
46 let fetch_url = format!(
47 "{}://{}/.well-known/webfinger?resource={}:{}@{}",
48 protocol_string, domain, webfinger_type, name, domain
50 debug!("Fetching webfinger url: {}", &fetch_url);
52 let response = retry(|| client.get(&fetch_url).send()).await?;
54 let res: WebfingerResponse = response
57 .map_err(|e| RecvError(e.to_string()))?;
62 .find(|l| l.type_.eq(&Some("application/activity+json".to_string())))
63 .ok_or_else(|| anyhow!("No application/activity+json link found."))?;
67 .ok_or_else(|| anyhow!("No href found.").into())