notra 0.1.1

Unofficial Rust SDK for the Notra API
Documentation
use serde::{Deserialize, Serialize};

use crate::client::Notra;
use crate::error::Result;
use crate::models::{BrandIdentity, BrandIdentityJob, Language, Organization, ToneProfile};

// ── List Brand Identities ───────────────────────────────────────────────

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ListBrandIdentitiesResponse {
    pub organization: Organization,
    pub brand_identities: Vec<BrandIdentity>,
}

pub struct ListBrandIdentitiesBuilder<'a> {
    client: &'a Notra,
}

impl<'a> ListBrandIdentitiesBuilder<'a> {
    pub(crate) fn new(client: &'a Notra) -> Self {
        Self { client }
    }

    pub async fn send(self) -> Result<ListBrandIdentitiesResponse> {
        self.client.get("/v1/brand-identities", &[]).await
    }
}

// ── Create Brand Identity ───────────────────────────────────────────────

#[derive(Debug, Deserialize)]
pub struct CreateBrandIdentityResponse {
    pub organization: Organization,
    pub job: BrandIdentityJob,
}

#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct CreateBrandIdentityBody {
    website_url: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    name: Option<String>,
}

pub struct CreateBrandIdentityBuilder<'a> {
    client: &'a Notra,
    website_url: String,
    name: Option<String>,
}

impl<'a> CreateBrandIdentityBuilder<'a> {
    pub(crate) fn new(client: &'a Notra, website_url: impl Into<String>) -> Self {
        Self {
            client,
            website_url: website_url.into(),
            name: None,
        }
    }

    pub fn name(mut self, name: impl Into<String>) -> Self {
        self.name = Some(name.into());
        self
    }

    pub async fn send(self) -> Result<CreateBrandIdentityResponse> {
        let body = CreateBrandIdentityBody {
            website_url: self.website_url,
            name: self.name,
        };
        self.client
            .post("/v1/brand-identities/generate", &body)
            .await
    }
}

// ── Get Brand Identity Generation ───────────────────────────────────────

#[derive(Debug, Deserialize)]
pub struct GetBrandIdentityGenerationResponse {
    pub organization: Organization,
    pub job: BrandIdentityJob,
}

pub struct GetBrandIdentityGenerationBuilder<'a> {
    client: &'a Notra,
    job_id: String,
}

impl<'a> GetBrandIdentityGenerationBuilder<'a> {
    pub(crate) fn new(client: &'a Notra, job_id: impl Into<String>) -> Self {
        Self {
            client,
            job_id: job_id.into(),
        }
    }

    pub async fn send(self) -> Result<GetBrandIdentityGenerationResponse> {
        let path = format!("/v1/brand-identities/generate/{}", self.job_id);
        self.client.get(&path, &[]).await
    }
}

// ── Get Brand Identity ──────────────────────────────────────────────────

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GetBrandIdentityResponse {
    pub organization: Organization,
    pub brand_identity: Option<BrandIdentity>,
}

pub struct GetBrandIdentityBuilder<'a> {
    client: &'a Notra,
    brand_identity_id: String,
}

impl<'a> GetBrandIdentityBuilder<'a> {
    pub(crate) fn new(client: &'a Notra, brand_identity_id: impl Into<String>) -> Self {
        Self {
            client,
            brand_identity_id: brand_identity_id.into(),
        }
    }

    pub async fn send(self) -> Result<GetBrandIdentityResponse> {
        let path = format!("/v1/brand-identities/{}", self.brand_identity_id);
        self.client.get(&path, &[]).await
    }
}

// ── Update Brand Identity ───────────────────────────────────────────────

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UpdateBrandIdentityResponse {
    pub organization: Organization,
    pub brand_identity: BrandIdentity,
}

#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct UpdateBrandIdentityBody {
    #[serde(skip_serializing_if = "Option::is_none")]
    name: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    audience: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    company_description: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    company_name: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    custom_instructions: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    custom_tone: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    is_default: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    language: Option<Language>,
    #[serde(skip_serializing_if = "Option::is_none")]
    tone_profile: Option<ToneProfile>,
    #[serde(skip_serializing_if = "Option::is_none")]
    website_url: Option<String>,
}

pub struct UpdateBrandIdentityBuilder<'a> {
    client: &'a Notra,
    brand_identity_id: String,
    name: Option<String>,
    audience: Option<String>,
    company_description: Option<String>,
    company_name: Option<String>,
    custom_instructions: Option<String>,
    custom_tone: Option<String>,
    is_default: Option<bool>,
    language: Option<Language>,
    tone_profile: Option<ToneProfile>,
    website_url: Option<String>,
}

impl<'a> UpdateBrandIdentityBuilder<'a> {
    pub(crate) fn new(client: &'a Notra, brand_identity_id: impl Into<String>) -> Self {
        Self {
            client,
            brand_identity_id: brand_identity_id.into(),
            name: None,
            audience: None,
            company_description: None,
            company_name: None,
            custom_instructions: None,
            custom_tone: None,
            is_default: None,
            language: None,
            tone_profile: None,
            website_url: None,
        }
    }

    pub fn name(mut self, name: impl Into<String>) -> Self {
        self.name = Some(name.into());
        self
    }

    pub fn audience(mut self, audience: impl Into<String>) -> Self {
        self.audience = Some(audience.into());
        self
    }

    pub fn company_description(mut self, desc: impl Into<String>) -> Self {
        self.company_description = Some(desc.into());
        self
    }

    pub fn company_name(mut self, name: impl Into<String>) -> Self {
        self.company_name = Some(name.into());
        self
    }

    pub fn custom_instructions(mut self, instructions: impl Into<String>) -> Self {
        self.custom_instructions = Some(instructions.into());
        self
    }

    pub fn custom_tone(mut self, tone: impl Into<String>) -> Self {
        self.custom_tone = Some(tone.into());
        self
    }

    pub fn is_default(mut self, is_default: bool) -> Self {
        self.is_default = Some(is_default);
        self
    }

    pub fn language(mut self, language: Language) -> Self {
        self.language = Some(language);
        self
    }

    pub fn tone_profile(mut self, tone_profile: ToneProfile) -> Self {
        self.tone_profile = Some(tone_profile);
        self
    }

    pub fn website_url(mut self, url: impl Into<String>) -> Self {
        self.website_url = Some(url.into());
        self
    }

    pub async fn send(self) -> Result<UpdateBrandIdentityResponse> {
        let path = format!("/v1/brand-identities/{}", self.brand_identity_id);
        let body = UpdateBrandIdentityBody {
            name: self.name,
            audience: self.audience,
            company_description: self.company_description,
            company_name: self.company_name,
            custom_instructions: self.custom_instructions,
            custom_tone: self.custom_tone,
            is_default: self.is_default,
            language: self.language,
            tone_profile: self.tone_profile,
            website_url: self.website_url,
        };
        self.client.patch(&path, &body).await
    }
}

// ── Delete Brand Identity ───────────────────────────────────────────────

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DeleteBrandIdentityResponse {
    pub id: String,
    pub organization: Organization,
    #[serde(default)]
    pub disabled_schedules: Vec<DisabledItem>,
    #[serde(default)]
    pub disabled_events: Vec<DisabledItem>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct DisabledItem {
    pub id: String,
}

pub struct DeleteBrandIdentityBuilder<'a> {
    client: &'a Notra,
    brand_identity_id: String,
}

impl<'a> DeleteBrandIdentityBuilder<'a> {
    pub(crate) fn new(client: &'a Notra, brand_identity_id: impl Into<String>) -> Self {
        Self {
            client,
            brand_identity_id: brand_identity_id.into(),
        }
    }

    pub async fn send(self) -> Result<DeleteBrandIdentityResponse> {
        let path = format!("/v1/brand-identities/{}", self.brand_identity_id);
        self.client.delete(&path).await
    }
}