3 request::{retry, RecvError},
4 settings::structs::Settings,
9 use serde::{Deserialize, Serialize};
12 #[derive(Serialize, Deserialize, Debug)]
13 pub struct WebfingerLink {
14 pub rel: Option<String>,
15 #[serde(rename(serialize = "type", deserialize = "type"))]
16 pub type_: Option<String>,
17 pub href: Option<Url>,
18 #[serde(skip_serializing_if = "Option::is_none")]
19 pub template: Option<String>,
22 #[derive(Serialize, Deserialize, Debug)]
23 pub struct WebfingerResponse {
25 pub aliases: Vec<Url>,
26 pub links: Vec<WebfingerLink>,
29 pub enum WebfingerType {
34 /// Turns a person id like `@name@example.com` into an apub ID, like `https://example.com/user/name`,
36 pub async fn webfinger_resolve_actor(
39 webfinger_type: WebfingerType,
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 Settings::get().get_protocol_string(),
54 debug!("Fetching webfinger url: {}", &fetch_url);
56 let response = retry(|| client.get(&fetch_url).send()).await?;
58 let res: WebfingerResponse = response
61 .map_err(|e| RecvError(e.to_string()))?;
66 .find(|l| l.type_.eq(&Some("application/activity+json".to_string())))
67 .ok_or_else(|| anyhow!("No application/activity+json link found."))?;
71 .ok_or_else(|| anyhow!("No href found.").into())