concord 2.2.3

A terminal user interface client for Discord
Documentation
use crate::discord::fingerprint::discord_rest_client;
use crate::{AppError, Result};

use reqwest::{RequestBuilder, header::AUTHORIZATION};
use serde::de::DeserializeOwned;

mod application_commands;
mod connection;
mod forum;
mod guilds;
mod messages;
mod notification_settings;
mod polls;
mod presence;
mod profile;
mod reactions;
mod read_state;
mod search;

pub use forum::ForumPostPage;

#[derive(Clone, Debug)]
pub struct DiscordRest {
    raw_http: reqwest::Client,
    token: String,
}

impl DiscordRest {
    pub fn new(token: String) -> Self {
        Self {
            raw_http: discord_rest_client(),
            token,
        }
    }

    fn authenticated(&self, request: RequestBuilder) -> RequestBuilder {
        request.header(AUTHORIZATION, &self.token)
    }

    async fn send_unit(&self, request: RequestBuilder, label: &str) -> Result<()> {
        self.authenticated(request)
            .send()
            .await
            .map_err(|error| AppError::DiscordRequest(format!("{label} request failed: {error}")))?
            .error_for_status()
            .map_err(|error| AppError::DiscordRequest(format!("{label} failed: {error}")))?;
        Ok(())
    }

    async fn send_json<T: DeserializeOwned>(
        &self,
        request: RequestBuilder,
        label: &str,
    ) -> Result<T> {
        self.authenticated(request)
            .send()
            .await
            .map_err(|error| AppError::DiscordRequest(format!("{label} request failed: {error}")))?
            .error_for_status()
            .map_err(|error| AppError::DiscordRequest(format!("{label} failed: {error}")))?
            .json()
            .await
            .map_err(|error| AppError::DiscordRequest(format!("{label} decode failed: {error}")))
    }
}

#[cfg(test)]
mod tests;