magnetar/ext_federation/src/lib.rs

103 lines
2.8 KiB
Rust

use std::{io::Cursor, sync::Arc};
use client::federation_client::{FederationClient, FederationClientError};
use magnetar_common::{config::MagnetarNetworkingProtocol, util::FediverseTag};
use magnetar_host_meta::{Xrd, XrdXml};
use magnetar_webfinger::webfinger::WebFinger;
use serde::{Deserialize, Serialize};
use url::Url;
pub mod client;
/// The *visible* domain of fediverse handles, that gets resolved by WebFinger
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(transparent)]
pub struct HostUnmapped(String);
/// The real domain of fediverse handles used for federation
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(transparent)]
pub struct HostMapped(String);
pub trait HostMetaResolverService {
type Error;
async fn resolve(&self, host: &HostUnmapped) -> Result<Xrd, Self::Error>;
}
pub struct HostMetaResolverProviderDefault {
client: Arc<FederationClient>,
protocol: MagnetarNetworkingProtocol,
}
impl HostMetaResolverService for HostMetaResolverProviderDefault {
type Error = FederationClientError;
async fn resolve(&self, HostUnmapped(host): &HostUnmapped) -> Result<Xrd, Self::Error> {
let host_meta_xml = self
.client
.get(Url::parse(&format!(
"{}://{}/.well-known/host-meta",
self.protocol.as_ref(),
host
))?)
.send()
.await?;
let XrdXml::Xrd(xrd) = quick_xml::de::from_reader(Cursor::new(host_meta_xml))?;
Ok(xrd)
}
}
pub trait WebFingerResolverService {
type Error;
async fn resolve_url(&self, url: &str) -> Result<WebFinger, Self::Error>;
async fn resolve(
&self,
template_url: &str,
resolved_uri: &str,
) -> Result<WebFinger, Self::Error> {
self.resolve_url(
&template_url.replace(
"{}",
&percent_encoding::utf8_percent_encode(
resolved_uri,
percent_encoding::NON_ALPHANUMERIC,
)
.to_string(),
),
)
.await
}
}
pub struct WebFingerResolverProviderDefault {
client: Arc<FederationClient>,
}
impl WebFingerResolverService for WebFingerResolverProviderDefault {
type Error = FederationClientError;
async fn resolve_url(&self, url: &str) -> Result<WebFinger, Self::Error> {
let host_meta_xml = self.client.get(Url::parse(url)?).send().await?;
let webfinger = serde_json::from_reader(Cursor::new(host_meta_xml))?;
Ok(webfinger)
}
}
#[derive(Debug)]
pub struct MappedUser {
pub host_meta: Xrd,
pub webfinger: WebFinger,
pub tag_mapped: FediverseTag,
}
pub trait FederationService {
type Error;
async fn map_fedi_tag(&self, host: &HostUnmapped) -> Result<MappedUser, Self::Error>;
}