use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum EventType {
ProblemCreated,
ProblemSolved,
ProblemDissolved,
ProblemReopened,
SolutionCreated,
SolutionSubmitted,
SolutionApproved,
SolutionWithdrawn,
CritiqueRaised,
CritiqueAddressed,
CritiqueDismissed,
CritiqueValidated,
CritiqueReplied,
MilestoneCreated,
MilestoneCompleted,
GithubIssueCreated,
GithubIssueImported,
GithubIssueClosed,
GithubPrCreated,
GithubPrMerged,
GithubReviewImported,
}
impl std::fmt::Display for EventType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
EventType::ProblemCreated => write!(f, "problem_created"),
EventType::ProblemSolved => write!(f, "problem_solved"),
EventType::ProblemDissolved => write!(f, "problem_dissolved"),
EventType::ProblemReopened => write!(f, "problem_reopened"),
EventType::SolutionCreated => write!(f, "solution_created"),
EventType::SolutionSubmitted => write!(f, "solution_submitted"),
EventType::SolutionApproved => write!(f, "solution_approved"),
EventType::SolutionWithdrawn => write!(f, "solution_withdrawn"),
EventType::CritiqueRaised => write!(f, "critique_raised"),
EventType::CritiqueAddressed => write!(f, "critique_addressed"),
EventType::CritiqueDismissed => write!(f, "critique_dismissed"),
EventType::CritiqueValidated => write!(f, "critique_validated"),
EventType::CritiqueReplied => write!(f, "critique_replied"),
EventType::MilestoneCreated => write!(f, "milestone_created"),
EventType::MilestoneCompleted => write!(f, "milestone_completed"),
EventType::GithubIssueCreated => write!(f, "github_issue_created"),
EventType::GithubIssueImported => write!(f, "github_issue_imported"),
EventType::GithubIssueClosed => write!(f, "github_issue_closed"),
EventType::GithubPrCreated => write!(f, "github_pr_created"),
EventType::GithubPrMerged => write!(f, "github_pr_merged"),
EventType::GithubReviewImported => write!(f, "github_review_imported"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Event {
pub when: DateTime<Utc>,
#[serde(rename = "type")]
pub event_type: EventType,
pub entity: String,
pub by: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub rationale: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub refs: Vec<String>,
#[serde(flatten)]
pub extra: EventExtra,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct EventExtra {
#[serde(skip_serializing_if = "Option::is_none")]
pub target: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub severity: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub title: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub problem: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub supersedes: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub github_number: Option<u64>,
}
impl Event {
pub fn new(event_type: EventType, entity: impl Into<String>, by: impl Into<String>) -> Self {
Self {
when: Utc::now(),
event_type,
entity: entity.into(),
by: by.into(),
rationale: None,
refs: Vec::new(),
extra: EventExtra::default(),
}
}
pub fn with_rationale(mut self, rationale: impl Into<String>) -> Self {
self.rationale = Some(rationale.into());
self
}
pub fn with_refs(mut self, refs: Vec<String>) -> Self {
self.refs = refs;
self
}
pub fn with_timestamp(mut self, when: DateTime<Utc>) -> Self {
self.when = when;
self
}
pub fn with_extra(mut self, extra: EventExtra) -> Self {
self.extra = extra;
self
}
pub fn to_json_line(&self) -> Result<String, serde_json::Error> {
serde_json::to_string(self)
}
pub fn to_commit_suffix(&self) -> Result<String, serde_json::Error> {
Ok(format!("jjj: {}", self.to_json_line()?))
}
}