issuerss/src/gitlab/structs.rs

137 lines
3.2 KiB
Rust

use chrono::{DateTime, FixedOffset};
use serde::de::{self, Visitor};
use serde::{Deserialize, Deserializer};
use std::fmt;
use std::marker::PhantomData;
pub const ISSUE_QUERY: &str = r#"query ($repo: ID!, $id: String) {
project (fullPath: $repo) {
issue (iid: $id) {
id
descriptionHtml
author {
username
}
title
createdAt
webUrl
notes {
nodes {
id
author {
username
}
body
bodyHtml
createdAt
url
}
}
}
}
}"#;
pub const MR_QUERY: &str = r#"query ($repo: ID!, $id: String!) {
project (fullPath: $repo) {
mergeRequest (iid: $id) {
id
descriptionHtml
author {
username
}
title
createdAt
webUrl
notes {
nodes {
id
author {
username
}
body
bodyHtml
createdAt
url
}
}
}
}
}"#;
#[derive(Deserialize, Debug)]
pub struct Data {
pub data: Project,
}
#[derive(Deserialize, Debug)]
pub struct Project {
pub project: IssueOrMR,
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub enum IssueOrMR {
Issue(IssueInfo),
MergeRequest(IssueInfo),
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct IssueInfo {
pub id: String,
pub description_html: String,
pub author: Author,
pub title: String,
#[serde(deserialize_with = "deserialize_datetime")]
pub created_at: DateTime<FixedOffset>,
pub web_url: String,
pub notes: NoteConnection,
}
#[derive(Deserialize, Debug)]
pub struct Author {
pub username: String,
}
#[derive(Deserialize, Debug)]
pub struct NoteConnection {
pub nodes: Vec<Note>,
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Note {
pub id: String,
pub author: Author,
pub body: String,
pub body_html: String,
#[serde(deserialize_with = "deserialize_datetime")]
pub created_at: DateTime<FixedOffset>,
pub url: String,
}
fn deserialize_datetime<'de, D>(deserializer: D) -> Result<DateTime<FixedOffset>, D::Error>
where
D: Deserializer<'de>,
{
struct DeserializeDateTime<T>(PhantomData<fn() -> T>);
impl<'de> Visitor<'de> for DeserializeDateTime<DateTime<FixedOffset>> {
type Value = DateTime<FixedOffset>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("RFC3339 datetime string")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
// https://brokenco.de/2020/08/03/serde-deserialize-with-string.html
DateTime::parse_from_rfc3339(value).map_err(serde::de::Error::custom)
}
}
deserializer.deserialize_any(DeserializeDateTime(PhantomData))
}