magnetar/magnetar_sdk/src/types/mod.rs

214 lines
5.4 KiB
Rust

pub mod drive;
pub mod emoji;
pub mod instance;
pub mod note;
pub mod timeline;
pub mod user;
use crate::endpoints::ErrorKind;
use crate::util_types::U64Range;
use chrono::{DateTime, Utc};
use serde::de::Error;
use serde::{Deserialize, Deserializer, Serialize};
use ts_rs::TS;
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
pub struct RangeFilter {
pub time_start: DateTime<Utc>,
pub time_end: DateTime<Utc>,
pub id_start: String,
pub id_end: String,
}
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
pub struct StartFilter {
pub time_start: DateTime<Utc>,
pub id_start: String,
}
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
pub struct EndFilter {
pub time_end: DateTime<Utc>,
pub id_end: String,
}
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
pub struct NoFilter {}
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
#[serde(untagged)]
pub enum SpanFilter {
Range(RangeFilter),
Start(StartFilter),
End(EndFilter),
None(NoFilter),
}
impl SpanFilter {
pub fn is_desc(&self) -> bool {
!matches!(self, Self::Start(_))
}
pub fn start(&self) -> Option<(DateTime<Utc>, String)> {
match self {
Self::Start(StartFilter {
time_start,
id_start,
})
| Self::Range(RangeFilter {
time_start,
id_start,
..
}) => Some((*time_start, id_start.clone())),
_ => None,
}
}
pub fn end(&self) -> Option<(DateTime<Utc>, String)> {
match self {
Self::End(EndFilter { time_end, id_end })
| Self::Range(RangeFilter {
time_end, id_end, ..
}) => Some((*time_end, id_end.clone())),
_ => None,
}
}
pub fn prev(&self, first_date: DateTime<Utc>, first_id: &str) -> Option<SpanFilter> {
match self {
Self::Start(_) => Some(SpanFilter::End(EndFilter {
time_end: first_date,
id_end: first_id.to_string(),
})),
Self::End(_) => Some(SpanFilter::Start(StartFilter {
time_start: first_date,
id_start: first_id.to_string(),
})),
// TODO: This is jank
// It forgets the bounds of the cursor
Self::Range(_) => Some(SpanFilter::Start(StartFilter {
time_start: first_date,
id_start: first_id.to_string(),
})),
Self::None(_) => None,
}
}
pub fn next(&self, last_date: DateTime<Utc>, last_id: &str) -> Option<SpanFilter> {
match self {
Self::Start(_) => Some(SpanFilter::Start(StartFilter {
time_start: last_date,
id_start: last_id.to_string(),
})),
Self::End(_) | Self::None(_) => Some(SpanFilter::End(EndFilter {
time_end: last_date,
id_end: last_id.to_string(),
})),
Self::Range(RangeFilter { time_start, .. }) if *time_start > last_date => None,
Self::Range(RangeFilter {
time_start,
id_start,
..
}) => Some(SpanFilter::Range(RangeFilter {
time_start: *time_start,
id_start: id_start.clone(),
time_end: last_date,
id_end: last_id.to_string(),
})),
}
}
}
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
pub struct PaginationShape {
#[serde(default = "pagination_default")]
#[serde(deserialize_with = "deserialize_pagination")]
pub pagination: SpanFilter,
#[serde(default = "limit_defalt")]
#[serde(deserialize_with = "deserialize_limit")]
pub limit: U64Range<10, 100>,
}
fn pagination_default() -> SpanFilter {
SpanFilter::None(NoFilter {})
}
fn limit_defalt() -> U64Range<10, 100> {
U64Range::try_from(20).unwrap()
}
fn deserialize_limit<'de, D>(deserializer: D) -> Result<U64Range<10, 100>, D::Error>
where
D: Deserializer<'de>,
{
let str_val = String::deserialize(deserializer)?;
U64Range::try_from(str_val.parse::<u64>().map_err(Error::custom)?)
.map_err(|_| Error::custom("number out of range"))
}
fn deserialize_pagination<'de, D>(deserializer: D) -> Result<SpanFilter, D::Error>
where
D: Deserializer<'de>,
{
let str_val = String::deserialize(deserializer)?;
serde_urlencoded::from_str::<SpanFilter>(&str_val).map_err(Error::custom)
}
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
#[repr(transparent)]
pub struct Id {
pub id: String,
}
impl<T: AsRef<str>> From<T> for Id {
fn from(id: T) -> Self {
Self {
id: id.as_ref().to_string(),
}
}
}
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
#[repr(transparent)]
pub struct MmXml(pub String);
#[derive(Copy, Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
pub enum NotificationType {
Follow,
Mention,
Reply,
Renote,
Quote,
Reaction,
PollVote,
PollEnded,
FollowRequest,
FollowRequestAccepted,
App,
}
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
pub struct NotificationSettings {
pub enabled: Vec<NotificationType>,
}
#[derive(Copy, Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
pub enum FollowVisibility {
Public,
Followers,
Private,
}