Skip to main content

cloudconvert_sdk/
resources.rs

1//! Account and webhook resource models returned by CloudConvert user endpoints.
2//!
3//! [`User`] represents the authenticated account. Webhook types model event
4//! subscriptions CloudConvert delivers to caller-controlled URLs.
5
6use std::{collections::BTreeMap, fmt};
7
8use serde::{Deserialize, Deserializer, Serialize, Serializer};
9use serde_json::Value;
10
11/// Authenticated CloudConvert account returned by `GET /v2/users/me`.
12#[derive(Clone, Deserialize, Serialize)]
13#[non_exhaustive]
14pub struct User {
15    pub id: String,
16    pub username: String,
17    pub email: String,
18    pub credits: f64,
19    #[serde(default)]
20    pub created_at: Option<String>,
21    #[serde(flatten)]
22    pub extra: BTreeMap<String, Value>,
23}
24
25impl fmt::Debug for User {
26    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27        f.debug_struct("User")
28            .field("id", &self.id)
29            .field("username", &self.username)
30            .field("email", &"REDACTED")
31            .field("credits", &self.credits)
32            .field("created_at", &self.created_at)
33            .field("extra", &self.extra)
34            .finish()
35    }
36}
37
38/// Event name CloudConvert can deliver to a registered webhook URL.
39#[derive(Clone, Debug, PartialEq, Eq)]
40#[non_exhaustive]
41pub enum WebhookEvent {
42    JobCreated,
43    JobFinished,
44    JobFailed,
45    TaskCreated,
46    TaskFinished,
47    TaskFailed,
48    Other(String),
49}
50
51impl WebhookEvent {
52    pub fn as_str(&self) -> &str {
53        match self {
54            Self::JobCreated => "job.created",
55            Self::JobFinished => "job.finished",
56            Self::JobFailed => "job.failed",
57            Self::TaskCreated => "task.created",
58            Self::TaskFinished => "task.finished",
59            Self::TaskFailed => "task.failed",
60            Self::Other(value) => value.as_str(),
61        }
62    }
63}
64
65impl Serialize for WebhookEvent {
66    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
67    where
68        S: Serializer,
69    {
70        serializer.serialize_str(self.as_str())
71    }
72}
73
74impl<'de> Deserialize<'de> for WebhookEvent {
75    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
76    where
77        D: Deserializer<'de>,
78    {
79        let value = String::deserialize(deserializer)?;
80        Ok(match value.as_str() {
81            "job.created" => Self::JobCreated,
82            "job.finished" => Self::JobFinished,
83            "job.failed" => Self::JobFailed,
84            "task.created" => Self::TaskCreated,
85            "task.finished" => Self::TaskFinished,
86            "task.failed" => Self::TaskFailed,
87            _ => Self::Other(value),
88        })
89    }
90}
91
92/// Request body for `POST /v2/webhooks`.
93#[derive(Clone, Debug, Serialize)]
94pub struct WebhookCreateRequest {
95    url: String,
96    events: Vec<WebhookEvent>,
97}
98
99impl WebhookCreateRequest {
100    pub fn new(url: impl Into<String>, events: impl Into<Vec<WebhookEvent>>) -> Self {
101        Self {
102            url: url.into(),
103            events: events.into(),
104        }
105    }
106
107    pub fn url(&self) -> &str {
108        self.url.as_str()
109    }
110
111    pub fn events(&self) -> &[WebhookEvent] {
112        &self.events
113    }
114}
115
116/// Query parameters for listing registered webhooks.
117#[derive(Clone, Debug, Default, Serialize)]
118pub struct WebhookListQuery {
119    #[serde(rename = "filter[url]", skip_serializing_if = "Option::is_none")]
120    filter_url: Option<String>,
121    #[serde(skip_serializing_if = "Option::is_none")]
122    per_page: Option<u32>,
123    #[serde(skip_serializing_if = "Option::is_none")]
124    page: Option<u32>,
125}
126
127impl WebhookListQuery {
128    pub fn url(mut self, url: impl Into<String>) -> Self {
129        self.filter_url = Some(url.into());
130        self
131    }
132
133    pub fn per_page(mut self, per_page: u32) -> Self {
134        self.per_page = Some(per_page);
135        self
136    }
137
138    pub fn page(mut self, page: u32) -> Self {
139        self.page = Some(page);
140        self
141    }
142}
143
144/// Registered webhook subscription, including optional signing secret metadata.
145#[derive(Clone, Deserialize, Serialize)]
146#[non_exhaustive]
147pub struct Webhook {
148    pub id: String,
149    pub url: String,
150    #[serde(default)]
151    pub disabled: Option<bool>,
152    #[serde(default)]
153    pub events: Vec<WebhookEvent>,
154    #[serde(default)]
155    pub failing: Option<bool>,
156    #[serde(default, skip_serializing)]
157    pub signing_secret: Option<String>,
158    #[serde(default)]
159    pub created_at: Option<String>,
160    #[serde(default)]
161    pub updated_at: Option<String>,
162    #[serde(default)]
163    pub links: BTreeMap<String, Value>,
164    #[serde(flatten)]
165    pub extra: BTreeMap<String, Value>,
166}
167
168impl fmt::Debug for Webhook {
169    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
170        f.debug_struct("Webhook")
171            .field("id", &self.id)
172            .field("url", &self.url)
173            .field("disabled", &self.disabled)
174            .field("events", &self.events)
175            .field("failing", &self.failing)
176            .field(
177                "signing_secret",
178                &self.signing_secret.as_ref().map(|_| "REDACTED"),
179            )
180            .field("created_at", &self.created_at)
181            .field("updated_at", &self.updated_at)
182            .field("links", &self.links)
183            .field("extra", &self.extra)
184            .finish()
185    }
186}