1use std::collections::BTreeMap;
2
3use serde::{Deserialize, Deserializer, Serialize, Serializer};
4use serde_json::Value as JsonValue;
5use time::OffsetDateTime;
6
7use super::util::{parse_json_i64ish, parse_string_array};
8
9#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
10pub struct GitHubEventCommon {
11 pub event: String,
12 pub action: Option<String>,
13 pub delivery_id: Option<String>,
14 pub installation_id: Option<i64>,
15 #[serde(default, skip_serializing_if = "Option::is_none")]
16 pub topic: Option<String>,
17 #[serde(default)]
18 pub reaction_topics: Vec<String>,
19 #[serde(default, skip_serializing_if = "Option::is_none")]
20 pub repository: Option<JsonValue>,
21 #[serde(default, skip_serializing_if = "Option::is_none")]
22 pub repo: Option<JsonValue>,
23 pub raw: JsonValue,
24}
25
26#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
27pub struct GitHubIssuesEventPayload {
28 #[serde(flatten)]
29 pub common: GitHubEventCommon,
30 pub issue: JsonValue,
31}
32
33#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
34pub struct GitHubPullRequestEventPayload {
35 #[serde(flatten)]
36 pub common: GitHubEventCommon,
37 pub pull_request: JsonValue,
38}
39
40#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
41pub struct GitHubIssueCommentEventPayload {
42 #[serde(flatten)]
43 pub common: GitHubEventCommon,
44 pub issue: JsonValue,
45 pub comment: JsonValue,
46}
47
48#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
49pub struct GitHubPullRequestReviewEventPayload {
50 #[serde(flatten)]
51 pub common: GitHubEventCommon,
52 pub pull_request: JsonValue,
53 pub review: JsonValue,
54}
55
56#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
57pub struct GitHubPushEventPayload {
58 #[serde(flatten)]
59 pub common: GitHubEventCommon,
60 #[serde(default)]
61 pub commits: Vec<JsonValue>,
62 pub distinct_size: Option<i64>,
63}
64
65#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
66pub struct GitHubWorkflowRunEventPayload {
67 #[serde(flatten)]
68 pub common: GitHubEventCommon,
69 pub workflow_run: JsonValue,
70}
71
72#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
73pub struct GitHubDeploymentStatusEventPayload {
74 #[serde(flatten)]
75 pub common: GitHubEventCommon,
76 pub deployment_status: JsonValue,
77 pub deployment: JsonValue,
78}
79
80#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
81pub struct GitHubCheckRunEventPayload {
82 #[serde(flatten)]
83 pub common: GitHubEventCommon,
84 pub check_run: JsonValue,
85}
86
87#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
88pub struct GitHubCheckSuiteEventPayload {
89 #[serde(flatten)]
90 pub common: GitHubEventCommon,
91 pub check_suite: JsonValue,
92 #[serde(default, skip_serializing_if = "Option::is_none")]
93 pub check_suite_id: Option<i64>,
94 #[serde(default, skip_serializing_if = "Option::is_none")]
95 pub pull_request_number: Option<i64>,
96 #[serde(default, skip_serializing_if = "Option::is_none")]
97 pub head_sha: Option<String>,
98 #[serde(default, skip_serializing_if = "Option::is_none")]
99 pub head_ref: Option<String>,
100 #[serde(default, skip_serializing_if = "Option::is_none")]
101 pub base_ref: Option<String>,
102 #[serde(default, skip_serializing_if = "Option::is_none")]
103 pub status: Option<String>,
104 #[serde(default, skip_serializing_if = "Option::is_none")]
105 pub conclusion: Option<String>,
106}
107
108#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
109pub struct GitHubStatusEventPayload {
110 #[serde(flatten)]
111 pub common: GitHubEventCommon,
112 #[serde(default, skip_serializing_if = "Option::is_none")]
113 pub commit_status: Option<JsonValue>,
114 #[serde(default, skip_serializing_if = "Option::is_none")]
115 pub status_id: Option<i64>,
116 #[serde(default, skip_serializing_if = "Option::is_none")]
117 pub head_sha: Option<String>,
118 #[serde(default, skip_serializing_if = "Option::is_none")]
119 pub head_ref: Option<String>,
120 #[serde(default, skip_serializing_if = "Option::is_none")]
121 pub base_ref: Option<String>,
122 #[serde(default, skip_serializing_if = "Option::is_none")]
123 pub state: Option<String>,
124 #[serde(default, skip_serializing_if = "Option::is_none")]
125 pub context: Option<String>,
126 #[serde(default, skip_serializing_if = "Option::is_none")]
127 pub target_url: Option<String>,
128}
129
130#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
131pub struct GitHubMergeGroupEventPayload {
132 #[serde(flatten)]
133 pub common: GitHubEventCommon,
134 pub merge_group: JsonValue,
135 #[serde(default, skip_serializing_if = "Option::is_none")]
136 pub merge_group_id: Option<JsonValue>,
137 #[serde(default, skip_serializing_if = "Option::is_none")]
138 pub head_sha: Option<String>,
139 #[serde(default, skip_serializing_if = "Option::is_none")]
140 pub head_ref: Option<String>,
141 #[serde(default, skip_serializing_if = "Option::is_none")]
142 pub base_sha: Option<String>,
143 #[serde(default, skip_serializing_if = "Option::is_none")]
144 pub base_ref: Option<String>,
145 #[serde(default)]
146 pub pull_requests: Vec<JsonValue>,
147 #[serde(default)]
148 pub pull_request_numbers: Vec<i64>,
149}
150
151#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
152pub struct GitHubInstallationEventPayload {
153 #[serde(flatten)]
154 pub common: GitHubEventCommon,
155 #[serde(default, skip_serializing_if = "Option::is_none")]
156 pub installation: Option<JsonValue>,
157 #[serde(default, skip_serializing_if = "Option::is_none")]
158 pub account: Option<JsonValue>,
159 #[serde(default, skip_serializing_if = "Option::is_none")]
160 pub installation_state: Option<String>,
161 #[serde(default, skip_serializing_if = "Option::is_none")]
162 pub suspended: Option<bool>,
163 #[serde(default, skip_serializing_if = "Option::is_none")]
164 pub revoked: Option<bool>,
165 #[serde(default)]
166 pub repositories: Vec<JsonValue>,
167}
168
169#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
170pub struct GitHubInstallationRepositoriesEventPayload {
171 #[serde(flatten)]
172 pub common: GitHubEventCommon,
173 #[serde(default, skip_serializing_if = "Option::is_none")]
174 pub installation: Option<JsonValue>,
175 #[serde(default, skip_serializing_if = "Option::is_none")]
176 pub account: Option<JsonValue>,
177 #[serde(default, skip_serializing_if = "Option::is_none")]
178 pub installation_state: Option<String>,
179 #[serde(default, skip_serializing_if = "Option::is_none")]
180 pub suspended: Option<bool>,
181 #[serde(default, skip_serializing_if = "Option::is_none")]
182 pub revoked: Option<bool>,
183 #[serde(default, skip_serializing_if = "Option::is_none")]
184 pub repository_selection: Option<String>,
185 #[serde(default)]
186 pub repositories_added: Vec<JsonValue>,
187 #[serde(default)]
188 pub repositories_removed: Vec<JsonValue>,
189}
190
191#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
192#[serde(untagged)]
193pub enum GitHubEventPayload {
194 Issues(GitHubIssuesEventPayload),
195 PullRequest(GitHubPullRequestEventPayload),
196 IssueComment(GitHubIssueCommentEventPayload),
197 PullRequestReview(GitHubPullRequestReviewEventPayload),
198 Push(GitHubPushEventPayload),
199 WorkflowRun(GitHubWorkflowRunEventPayload),
200 DeploymentStatus(GitHubDeploymentStatusEventPayload),
201 CheckRun(GitHubCheckRunEventPayload),
202 CheckSuite(GitHubCheckSuiteEventPayload),
203 Status(GitHubStatusEventPayload),
204 MergeGroup(GitHubMergeGroupEventPayload),
205 Installation(GitHubInstallationEventPayload),
206 InstallationRepositories(GitHubInstallationRepositoriesEventPayload),
207 Other(GitHubEventCommon),
208}
209
210impl<'de> Deserialize<'de> for GitHubEventPayload {
215 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
216 where
217 D: Deserializer<'de>,
218 {
219 let value = JsonValue::deserialize(deserializer)?;
220 let kind = value
221 .get("event")
222 .and_then(JsonValue::as_str)
223 .unwrap_or("")
224 .to_string();
225 let from_value = |v: JsonValue| -> Result<GitHubEventPayload, D::Error> {
226 let payload = match kind.as_str() {
227 "issues" => GitHubEventPayload::Issues(
228 serde_json::from_value(v).map_err(serde::de::Error::custom)?,
229 ),
230 "pull_request" => GitHubEventPayload::PullRequest(
231 serde_json::from_value(v).map_err(serde::de::Error::custom)?,
232 ),
233 "issue_comment" => GitHubEventPayload::IssueComment(
234 serde_json::from_value(v).map_err(serde::de::Error::custom)?,
235 ),
236 "pull_request_review" => GitHubEventPayload::PullRequestReview(
237 serde_json::from_value(v).map_err(serde::de::Error::custom)?,
238 ),
239 "push" => GitHubEventPayload::Push(
240 serde_json::from_value(v).map_err(serde::de::Error::custom)?,
241 ),
242 "workflow_run" => GitHubEventPayload::WorkflowRun(
243 serde_json::from_value(v).map_err(serde::de::Error::custom)?,
244 ),
245 "deployment_status" => GitHubEventPayload::DeploymentStatus(
246 serde_json::from_value(v).map_err(serde::de::Error::custom)?,
247 ),
248 "check_run" => GitHubEventPayload::CheckRun(
249 serde_json::from_value(v).map_err(serde::de::Error::custom)?,
250 ),
251 "check_suite" => GitHubEventPayload::CheckSuite(
252 serde_json::from_value(v).map_err(serde::de::Error::custom)?,
253 ),
254 "status" => GitHubEventPayload::Status(
255 serde_json::from_value(v).map_err(serde::de::Error::custom)?,
256 ),
257 "merge_group" => GitHubEventPayload::MergeGroup(
258 serde_json::from_value(v).map_err(serde::de::Error::custom)?,
259 ),
260 "installation" => GitHubEventPayload::Installation(
261 serde_json::from_value(v).map_err(serde::de::Error::custom)?,
262 ),
263 "installation_repositories" => GitHubEventPayload::InstallationRepositories(
264 serde_json::from_value(v).map_err(serde::de::Error::custom)?,
265 ),
266 _ => GitHubEventPayload::Other(
267 serde_json::from_value(v).map_err(serde::de::Error::custom)?,
268 ),
269 };
270 Ok(payload)
271 };
272 from_value(value)
273 }
274}
275
276#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
277pub struct SlackEventCommon {
278 pub event: String,
279 pub event_id: Option<String>,
280 pub api_app_id: Option<String>,
281 pub team_id: Option<String>,
282 pub channel_id: Option<String>,
283 pub user_id: Option<String>,
284 pub event_ts: Option<String>,
285 pub raw: JsonValue,
286}
287
288#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
289pub struct SlackMessageEventPayload {
290 #[serde(flatten)]
291 pub common: SlackEventCommon,
292 pub subtype: Option<String>,
293 pub channel_type: Option<String>,
294 pub channel: Option<String>,
295 pub user: Option<String>,
296 pub text: Option<String>,
297 pub ts: Option<String>,
298 pub thread_ts: Option<String>,
299}
300
301#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
302pub struct SlackAppMentionEventPayload {
303 #[serde(flatten)]
304 pub common: SlackEventCommon,
305 pub channel: Option<String>,
306 pub user: Option<String>,
307 pub text: Option<String>,
308 pub ts: Option<String>,
309 pub thread_ts: Option<String>,
310}
311
312#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
313pub struct SlackReactionAddedEventPayload {
314 #[serde(flatten)]
315 pub common: SlackEventCommon,
316 pub reaction: Option<String>,
317 pub item_user: Option<String>,
318 pub item: JsonValue,
319}
320
321#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
322pub struct SlackAppHomeOpenedEventPayload {
323 #[serde(flatten)]
324 pub common: SlackEventCommon,
325 pub user: Option<String>,
326 pub channel: Option<String>,
327 pub tab: Option<String>,
328 pub view: JsonValue,
329}
330
331#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
332pub struct SlackAssistantThreadStartedEventPayload {
333 #[serde(flatten)]
334 pub common: SlackEventCommon,
335 pub assistant_thread: JsonValue,
336 pub thread_ts: Option<String>,
337 pub context: JsonValue,
338}
339
340#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
341#[serde(untagged)]
342pub enum SlackEventPayload {
343 Message(SlackMessageEventPayload),
344 AppMention(SlackAppMentionEventPayload),
345 ReactionAdded(SlackReactionAddedEventPayload),
346 AppHomeOpened(SlackAppHomeOpenedEventPayload),
347 AssistantThreadStarted(SlackAssistantThreadStartedEventPayload),
348 Other(SlackEventCommon),
349}
350
351#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
352pub struct LinearEventCommon {
353 pub event: String,
354 pub action: Option<String>,
355 pub delivery_id: Option<String>,
356 pub organization_id: Option<String>,
357 pub webhook_timestamp: Option<i64>,
358 pub webhook_id: Option<String>,
359 pub url: Option<String>,
360 pub created_at: Option<String>,
361 pub actor: JsonValue,
362 pub raw: JsonValue,
363}
364
365#[derive(Clone, Debug, PartialEq)]
366pub enum LinearIssueChange {
367 Title { previous: Option<String> },
368 Description { previous: Option<String> },
369 Priority { previous: Option<i64> },
370 Estimate { previous: Option<i64> },
371 StateId { previous: Option<String> },
372 TeamId { previous: Option<String> },
373 AssigneeId { previous: Option<String> },
374 ProjectId { previous: Option<String> },
375 CycleId { previous: Option<String> },
376 DueDate { previous: Option<String> },
377 ParentId { previous: Option<String> },
378 SortOrder { previous: Option<f64> },
379 LabelIds { previous: Vec<String> },
380 CompletedAt { previous: Option<String> },
381 Other { field: String, previous: JsonValue },
382}
383
384impl Serialize for LinearIssueChange {
385 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
386 where
387 S: Serializer,
388 {
389 let value = match self {
390 Self::Title { previous } => {
391 serde_json::json!({ "field_name": "title", "previous": previous })
392 }
393 Self::Description { previous } => {
394 serde_json::json!({ "field_name": "description", "previous": previous })
395 }
396 Self::Priority { previous } => {
397 serde_json::json!({ "field_name": "priority", "previous": previous })
398 }
399 Self::Estimate { previous } => {
400 serde_json::json!({ "field_name": "estimate", "previous": previous })
401 }
402 Self::StateId { previous } => {
403 serde_json::json!({ "field_name": "state_id", "previous": previous })
404 }
405 Self::TeamId { previous } => {
406 serde_json::json!({ "field_name": "team_id", "previous": previous })
407 }
408 Self::AssigneeId { previous } => {
409 serde_json::json!({ "field_name": "assignee_id", "previous": previous })
410 }
411 Self::ProjectId { previous } => {
412 serde_json::json!({ "field_name": "project_id", "previous": previous })
413 }
414 Self::CycleId { previous } => {
415 serde_json::json!({ "field_name": "cycle_id", "previous": previous })
416 }
417 Self::DueDate { previous } => {
418 serde_json::json!({ "field_name": "due_date", "previous": previous })
419 }
420 Self::ParentId { previous } => {
421 serde_json::json!({ "field_name": "parent_id", "previous": previous })
422 }
423 Self::SortOrder { previous } => {
424 serde_json::json!({ "field_name": "sort_order", "previous": previous })
425 }
426 Self::LabelIds { previous } => {
427 serde_json::json!({ "field_name": "label_ids", "previous": previous })
428 }
429 Self::CompletedAt { previous } => {
430 serde_json::json!({ "field_name": "completed_at", "previous": previous })
431 }
432 Self::Other { field, previous } => {
433 serde_json::json!({ "field_name": "other", "field": field, "previous": previous })
434 }
435 };
436 value.serialize(serializer)
437 }
438}
439
440impl<'de> Deserialize<'de> for LinearIssueChange {
441 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
442 where
443 D: Deserializer<'de>,
444 {
445 let value = JsonValue::deserialize(deserializer)?;
446 let field_name = value
447 .get("field_name")
448 .and_then(JsonValue::as_str)
449 .ok_or_else(|| serde::de::Error::custom("linear issue change missing field_name"))?;
450 let previous = value.get("previous").cloned().unwrap_or(JsonValue::Null);
451 Ok(match field_name {
452 "title" => Self::Title {
453 previous: previous.as_str().map(ToString::to_string),
454 },
455 "description" => Self::Description {
456 previous: previous.as_str().map(ToString::to_string),
457 },
458 "priority" => Self::Priority {
459 previous: parse_json_i64ish(&previous),
460 },
461 "estimate" => Self::Estimate {
462 previous: parse_json_i64ish(&previous),
463 },
464 "state_id" => Self::StateId {
465 previous: previous.as_str().map(ToString::to_string),
466 },
467 "team_id" => Self::TeamId {
468 previous: previous.as_str().map(ToString::to_string),
469 },
470 "assignee_id" => Self::AssigneeId {
471 previous: previous.as_str().map(ToString::to_string),
472 },
473 "project_id" => Self::ProjectId {
474 previous: previous.as_str().map(ToString::to_string),
475 },
476 "cycle_id" => Self::CycleId {
477 previous: previous.as_str().map(ToString::to_string),
478 },
479 "due_date" => Self::DueDate {
480 previous: previous.as_str().map(ToString::to_string),
481 },
482 "parent_id" => Self::ParentId {
483 previous: previous.as_str().map(ToString::to_string),
484 },
485 "sort_order" => Self::SortOrder {
486 previous: previous.as_f64(),
487 },
488 "label_ids" => Self::LabelIds {
489 previous: parse_string_array(&previous),
490 },
491 "completed_at" => Self::CompletedAt {
492 previous: previous.as_str().map(ToString::to_string),
493 },
494 "other" => Self::Other {
495 field: value
496 .get("field")
497 .and_then(JsonValue::as_str)
498 .map(ToString::to_string)
499 .unwrap_or_else(|| "unknown".to_string()),
500 previous,
501 },
502 other => Self::Other {
503 field: other.to_string(),
504 previous,
505 },
506 })
507 }
508}
509
510#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
511pub struct LinearIssueEventPayload {
512 #[serde(flatten)]
513 pub common: LinearEventCommon,
514 pub issue: JsonValue,
515 #[serde(default)]
516 pub changes: Vec<LinearIssueChange>,
517}
518
519#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
520pub struct LinearIssueCommentEventPayload {
521 #[serde(flatten)]
522 pub common: LinearEventCommon,
523 pub comment: JsonValue,
524}
525
526#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
527pub struct LinearIssueLabelEventPayload {
528 #[serde(flatten)]
529 pub common: LinearEventCommon,
530 pub label: JsonValue,
531}
532
533#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
534pub struct LinearProjectEventPayload {
535 #[serde(flatten)]
536 pub common: LinearEventCommon,
537 pub project: JsonValue,
538}
539
540#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
541pub struct LinearCycleEventPayload {
542 #[serde(flatten)]
543 pub common: LinearEventCommon,
544 pub cycle: JsonValue,
545}
546
547#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
548pub struct LinearCustomerEventPayload {
549 #[serde(flatten)]
550 pub common: LinearEventCommon,
551 pub customer: JsonValue,
552}
553
554#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
555pub struct LinearCustomerRequestEventPayload {
556 #[serde(flatten)]
557 pub common: LinearEventCommon,
558 pub customer_request: JsonValue,
559}
560
561#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
562#[serde(untagged)]
563pub enum LinearEventPayload {
564 Issue(LinearIssueEventPayload),
565 IssueComment(LinearIssueCommentEventPayload),
566 IssueLabel(LinearIssueLabelEventPayload),
567 Project(LinearProjectEventPayload),
568 Cycle(LinearCycleEventPayload),
569 Customer(LinearCustomerEventPayload),
570 CustomerRequest(LinearCustomerRequestEventPayload),
571 Other(LinearEventCommon),
572}
573
574#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
575pub struct NotionPolledChangeEvent {
576 pub resource: String,
577 pub source_id: String,
578 pub entity_id: String,
579 pub high_water_mark: String,
580 pub before: Option<JsonValue>,
581 pub after: JsonValue,
582}
583
584#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
585pub struct NotionEventPayload {
586 pub event: String,
587 pub workspace_id: Option<String>,
588 pub request_id: Option<String>,
589 pub subscription_id: Option<String>,
590 pub integration_id: Option<String>,
591 pub attempt_number: Option<u32>,
592 pub entity_id: Option<String>,
593 pub entity_type: Option<String>,
594 pub api_version: Option<String>,
595 pub verification_token: Option<String>,
596 pub polled: Option<NotionPolledChangeEvent>,
597 pub raw: JsonValue,
598}
599
600#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
601pub struct CronEventPayload {
602 pub cron_id: Option<String>,
603 pub schedule: Option<String>,
604 #[serde(with = "time::serde::rfc3339")]
605 pub tick_at: OffsetDateTime,
606 pub raw: JsonValue,
607}
608
609#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
610pub struct GenericWebhookPayload {
611 pub source: Option<String>,
612 pub content_type: Option<String>,
613 pub raw: JsonValue,
614}
615
616#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
617pub struct A2aPushPayload {
618 pub task_id: Option<String>,
619 pub task_state: Option<String>,
620 pub artifact: Option<JsonValue>,
621 pub sender: Option<String>,
622 #[serde(default, skip_serializing_if = "Option::is_none")]
623 pub actor_chain: Option<JsonValue>,
624 pub raw: JsonValue,
625 pub kind: String,
626}
627
628#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
629pub struct StreamEventPayload {
630 pub event: String,
631 pub source: Option<String>,
632 pub stream: Option<String>,
633 pub partition: Option<String>,
634 pub offset: Option<String>,
635 pub key: Option<String>,
636 pub timestamp: Option<String>,
637 #[serde(default)]
638 pub headers: BTreeMap<String, String>,
639 pub raw: JsonValue,
640}
641
642#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
652pub struct ChannelEventPayload {
653 pub id: String,
654 pub name: String,
655 pub name_resolved: String,
656 pub scope: String,
657 pub scope_id: String,
658 pub payload: JsonValue,
659 pub emitted_by: String,
660 #[serde(skip_serializing_if = "Option::is_none")]
661 pub tenant_id: Option<String>,
662 #[serde(skip_serializing_if = "Option::is_none")]
663 pub session_id: Option<String>,
664 #[serde(skip_serializing_if = "Option::is_none")]
665 pub pipeline_id: Option<String>,
666}
667
668#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
669pub struct ExtensionProviderPayload {
670 pub provider: String,
671 pub schema_name: String,
672 pub raw: JsonValue,
673}
674
675#[allow(clippy::large_enum_variant)]
676#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
677#[serde(untagged)]
678pub enum ProviderPayload {
679 Known(KnownProviderPayload),
680 Extension(ExtensionProviderPayload),
681}
682
683impl ProviderPayload {
684 pub fn provider(&self) -> &str {
685 match self {
686 Self::Known(known) => known.provider(),
687 Self::Extension(payload) => payload.provider.as_str(),
688 }
689 }
690}
691
692#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
693#[serde(tag = "provider")]
694pub enum KnownProviderPayload {
695 #[serde(rename = "github")]
696 GitHub(Box<GitHubEventPayload>),
697 #[serde(rename = "slack")]
698 Slack(Box<SlackEventPayload>),
699 #[serde(rename = "linear")]
700 Linear(LinearEventPayload),
701 #[serde(rename = "notion")]
702 Notion(Box<NotionEventPayload>),
703 #[serde(rename = "cron")]
704 Cron(CronEventPayload),
705 #[serde(rename = "webhook")]
706 Webhook(GenericWebhookPayload),
707 #[serde(rename = "a2a-push")]
708 A2aPush(A2aPushPayload),
709 #[serde(rename = "kafka")]
710 Kafka(StreamEventPayload),
711 #[serde(rename = "nats")]
712 Nats(StreamEventPayload),
713 #[serde(rename = "pulsar")]
714 Pulsar(StreamEventPayload),
715 #[serde(rename = "postgres-cdc")]
716 PostgresCdc(StreamEventPayload),
717 #[serde(rename = "email")]
718 Email(StreamEventPayload),
719 #[serde(rename = "websocket")]
720 Websocket(StreamEventPayload),
721 #[serde(rename = "channel")]
722 Channel(ChannelEventPayload),
723}
724
725impl KnownProviderPayload {
726 pub fn provider(&self) -> &str {
727 match self {
728 Self::GitHub(_) => "github",
729 Self::Slack(_) => "slack",
730 Self::Linear(_) => "linear",
731 Self::Notion(_) => "notion",
732 Self::Cron(_) => "cron",
733 Self::Webhook(_) => "webhook",
734 Self::A2aPush(_) => "a2a-push",
735 Self::Kafka(_) => "kafka",
736 Self::Nats(_) => "nats",
737 Self::Pulsar(_) => "pulsar",
738 Self::PostgresCdc(_) => "postgres-cdc",
739 Self::Email(_) => "email",
740 Self::Websocket(_) => "websocket",
741 Self::Channel(_) => "channel",
742 }
743 }
744}