flows_connector_dsi/
jira.rs

1use serde::Deserialize;
2
3#[derive(Deserialize, Debug)]
4pub struct ChangeLogItem {
5    pub field: String,
6    #[serde(rename = "fieldId")]
7    pub field_id: String,
8    pub fieldtype: String,
9    pub from: Option<String>,
10    #[serde(rename = "fromString")]
11    pub from_string: Option<String>,
12    pub to: Option<String>,
13    #[serde(rename = "toString")]
14    pub to_string: Option<String>,
15}
16
17#[derive(Deserialize, Debug)]
18pub struct ChangeLog {
19    pub items: Vec<ChangeLogItem>,
20}
21
22#[derive(Deserialize, Debug)]
23pub struct AvatarUrls {
24    #[serde(rename = "16x16")]
25    _16x16: String,
26    #[serde(rename = "24x24")]
27    _24x24: String,
28    #[serde(rename = "32x32")]
29    _32x32: String,
30    #[serde(rename = "48x48")]
31    _48x48: String,
32}
33
34#[derive(Deserialize, Debug)]
35pub struct User {
36    #[serde(rename = "accountType")]
37    pub account_type: String,
38    pub active: bool,
39    #[serde(rename = "avatarUrls")]
40    pub avatar_urls: AvatarUrls,
41    #[serde(rename = "displayName")]
42    pub display_name: String,
43    #[serde(rename = "self")]
44    pub _self: String,
45    #[serde(rename = "timeZone")]
46    pub time_zone: String,
47}
48
49#[derive(Deserialize, Debug)]
50pub struct Project {
51    #[serde(rename = "avatarUrls")]
52    pub avatar_urls: AvatarUrls,
53    pub id: String,
54    pub key: String,
55    pub name: String,
56    #[serde(rename = "projectTypeKey")]
57    pub project_type_key: String,
58    #[serde(rename = "self")]
59    pub _self: String,
60    pub simplified: bool,
61}
62
63#[derive(Deserialize, Debug)]
64pub struct Progress {
65    pub progress: u64,
66    pub total: u64,
67}
68
69#[derive(Deserialize, Debug)]
70pub struct IssueType {
71    pub description: String,
72    pub name: String,
73    #[serde(rename = "self")]
74    pub _self: String,
75    pub subtask: bool,
76}
77
78#[derive(Deserialize, Debug)]
79pub struct Votes {
80    #[serde(rename = "hasVoted")]
81    pub has_voted: bool,
82    #[serde(rename = "self")]
83    pub _self: String,
84    pub votes: u64,
85}
86
87#[derive(Deserialize, Debug)]
88pub struct IssueField {
89    pub aggregateprogress: Option<Progress>,
90    pub assignee: Option<User>,
91    pub created: Option<String>,
92    pub creator: Option<User>,
93    #[serde(default = "Vec::new")]
94    pub labels: Vec<String>,
95    #[serde(rename = "lastViewed")]
96    pub last_viewed: Option<String>,
97    pub progress: Option<Progress>,
98    pub project: Project,
99    pub reporter: Option<User>,
100    pub summary: String,
101    pub updated: Option<String>,
102    pub votes: Option<Votes>,
103}
104
105#[derive(Deserialize, Debug)]
106pub struct Issue {
107    pub fields: IssueField,
108    pub id: String,
109    pub key: String,
110    #[serde(rename = "self")]
111    pub _self: String,
112}
113
114#[derive(Deserialize, Debug)]
115pub struct Comment {
116    pub author: User,
117    pub body: String,
118    pub created: String,
119    #[serde(rename = "self")]
120    pub _self: String,
121    #[serde(rename = "updateAuthor")]
122    pub update_author: User,
123    pub updated: String,
124}
125
126#[derive(Deserialize, Debug)]
127pub struct InboundData {
128    pub changelog: Option<ChangeLog>,
129    pub issue: Option<Issue>,
130    pub comment: Option<Comment>,
131    pub timestamp: u64,
132    #[serde(rename = "webhookEvent")]
133    pub webhook_event: String,
134}
135
136impl InboundData {
137    #[inline]
138    pub fn get_changelog(&self) -> Result<&ChangeLog, String> {
139        self.changelog
140            .as_ref()
141            .ok_or("Missing changelog".to_string())
142    }
143
144    #[inline]
145    pub fn get_issue(&self) -> Result<&Issue, String> {
146        self.issue.as_ref().ok_or("Missing issue".to_string())
147    }
148
149    #[inline]
150    pub fn get_comment(&self) -> Result<&Comment, String> {
151        self.comment.as_ref().ok_or("Missing comment".to_string())
152    }
153}
154
155/// Deserialize the Jira Webhook Payload into `InboundData`.
156pub fn inbound(s: String) -> Result<InboundData, String> {
157    #[cfg(debug_assertions)]
158    return serde_json::from_str::<InboundData>(&s)
159        .map_err(|e| format!("Parsing Jira Webhook payload failed: {}", e.to_string()));
160
161    #[cfg(not(debug_assertions))]
162    serde_json::from_str::<InboundData>(&s)
163        .map_err(|_| format!("Parsing Jira Webhook payload failed: {}", s))
164}
165
166pub mod outbound {
167    use std::collections::HashMap;
168
169    use serde_json::{json, Value};
170
171    pub struct OutboundData<'a> {
172        inner: HashMap<&'a str, Value>,
173    }
174
175    impl<'a> OutboundData<'a> {
176        /// Set summary.
177        pub fn summary<S: Into<String>>(mut self, summary: S) -> OutboundData<'a> {
178            self.inner.insert("summary", json!(summary.into()));
179            self
180        }
181
182        /// Set description.
183        pub fn description<S: Into<String>>(mut self, description: S) -> OutboundData<'a> {
184            self.inner.insert("description", json!(description.into()));
185            self
186        }
187
188        /// Set transition, only used on modify issue.
189        pub fn transition<S: Into<String>>(mut self, transition: S) -> OutboundData<'a> {
190            self.inner.insert("transition", json!(transition.into()));
191            self
192        }
193
194        /// Build outbound JSON data.
195        pub fn build(self) -> Result<String, String> {
196            if self.inner.is_empty() {
197                return Err("OutboundData build failed: empty field".to_string());
198            }
199
200            serde_json::to_string(&self.inner)
201                .map_err(|e| format!("OutboundData build failed: {}", e.to_string()))
202        }
203    }
204
205    /// Create an issue with the summary.
206    pub fn create_issue<'a, S: Into<String>>(summary: S) -> OutboundData<'a> {
207        OutboundData {
208            inner: [("summary", json!(summary.into()))]
209                .into_iter()
210                .collect::<HashMap<&str, Value>>(),
211        }
212    }
213
214    /// Modified an issue like change the summary, description or transition.
215    pub fn modify_issue<'a, S: Into<String>>(issue_key: S) -> OutboundData<'a> {
216        OutboundData {
217            inner: [("issue_key", json!(issue_key.into()))]
218                .into_iter()
219                .collect::<HashMap<&str, Value>>(),
220        }
221    }
222}