feat: add create_domain_connection

This commit is contained in:
kozabrada123 2024-08-18 10:14:51 +02:00
parent b7d549756a
commit 2f4198c0a4
2 changed files with 130 additions and 3 deletions

View File

@ -2,13 +2,14 @@ use futures_util::FutureExt;
use reqwest::Client;
use crate::{
errors::ChorusResult,
errors::{ChorusError, ChorusResult},
instance::ChorusUser,
ratelimiter::ChorusRequest,
types::{
AuthorizeConnectionReturn, AuthorizeConnectionSchema, Connection, ConnectionSubreddit,
ConnectionType, CreateConnectionCallbackSchema, CreateContactSyncConnectionSchema,
GetConnectionAccessTokenReturn, LimitType, ModifyConnectionSchema,
CreateDomainConnectionError, CreateDomainConnectionReturn, GetConnectionAccessTokenReturn,
LimitType, ModifyConnectionSchema,
},
};
@ -121,6 +122,92 @@ impl ChorusUser {
chorus_request.deserialize_response(self).await
}
/// Creates a new domain connection for the current user.
///
/// This route has two possible successful return values:
/// [CreateDomainConnectionReturn::Ok] and [CreateDomainConnectionReturn::ProofNeeded]
///
/// To properly handle both, please see their respective documentation pages.
///
/// # Notes
/// To create normal connection types, see [Self::authorize_connection] and
/// [Self::create_connection_callback]
///
/// # Examples
/// ```no_run
/// let domain = "example.com".to_string();
///
/// let result = user.create_domain_connection(&domain).await;
///
/// if let Ok(returned) = result {
/// match returned {
/// CreateDomainConnectionReturn::ProofNeeded(proof) => {
/// println!("Additional proof needed!");
/// println!("Either:");
/// println!("");
/// println!("- create a DNS TXT record with the name _discord.{domain} and content {proof}");
/// println!("or");
/// println!("- create a file at https://{domain}/.well-known/discord with the content {proof}");
/// // Once the user has added the proof, retry calling the endpoint
/// }
/// CreateDomainConnectionReturn::Ok(connection) => {
/// println!("Successfulyl created connection! {:?}", connection);
/// }
/// }
/// } else {
/// println!("Failed to create connection: {:?}", result);
/// }
/// ```
///
/// # Reference
/// See <https://docs.discord.sex/resources/user#create-domain-connection>
pub async fn create_domain_connection(
&mut self,
domain: &String,
) -> ChorusResult<CreateDomainConnectionReturn> {
let request = Client::new()
.post(format!(
"{}/users/@me/connections/domain/{}",
self.belongs_to.read().unwrap().urls.api,
domain
))
.header("Authorization", self.token());
let chorus_request = ChorusRequest {
request,
limit_type: LimitType::default(),
};
let result = chorus_request
.deserialize_response::<Connection>(self)
.await;
if let Ok(connection) = result {
return Ok(CreateDomainConnectionReturn::Ok(connection));
}
let error = result.err().unwrap();
if let ChorusError::ReceivedErrorCode {
error_code,
error: ref error_string,
} = error
{
if error_code == 400 {
let try_deserialize: Result<CreateDomainConnectionError, serde_json::Error> =
serde_json::from_str(error_string);
if let Ok(deserialized_error) = try_deserialize {
return Ok(CreateDomainConnectionReturn::ProofNeeded(
deserialized_error.proof,
));
}
}
}
return Err(error);
}
// TODO: Add create_domain_connection (<https://docs.discord.sex/resources/user#create-domain-connection>)
// It requires changing how chorus handles errors to support properly

View File

@ -8,7 +8,7 @@ use chrono::NaiveDate;
use serde::{Deserialize, Serialize};
use crate::types::{
GuildAffinity, HarvestBackendType, Snowflake, ThemeColors, TwoWayLinkType, UserAffinity,
Connection, GuildAffinity, HarvestBackendType, Snowflake, ThemeColors, TwoWayLinkType, UserAffinity
};
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq)]
@ -395,3 +395,43 @@ pub struct UserAffinities {
pub struct GuildAffinities {
pub guild_affinities: Vec<GuildAffinity>,
}
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
/// Return type for the error in the [crate::instance::ChorusUser::create_domain_connection] endpoint.
///
/// This allows us to retrieve the needed proof for actually verifying the connection.
///
/// See <https://docs.discord.sex/resources/user#create-domain-connection>
pub(crate) struct CreateDomainConnectionError {
pub message: String,
pub code: u16,
pub proof: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
/// Return type for the [crate::instance::ChorusUser::create_domain_connection] endpoint.
///
/// See <https://docs.discord.sex/resources/user#create-domain-connection>
pub enum CreateDomainConnectionReturn {
/// Additional proof is needed to verify domain ownership.
///
/// The inner object is a proof string (e.g.
/// `dh=dceaca792e3c40fcf356a9297949940af5cfe538`)
///
/// To verify ownership, either:
///
/// - add the proof string as a TXT DNS record to the domain,
/// with the name of the record being `_discord.{domain}`
///
/// or
///
/// - serve the proof string as a file at `https://{domain}/.well-known/discord`
///
/// After either of these proofs are added, the request should be retried.
///
ProofNeeded(String),
/// The domain connection was successfully created, no further action is needed.
///
/// The inner object is the new connection.
Ok(Connection)
}