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