114 lines
2.9 KiB
Rust
114 lines
2.9 KiB
Rust
|
use axum::extract::Query;
|
||
|
use axum::response::IntoResponse;
|
||
|
use axum::routing::get;
|
||
|
use axum::{Json, Router};
|
||
|
use chrono::{Datelike, Months, NaiveDate, NaiveDateTime, TimeDelta, Weekday};
|
||
|
use serde::{Deserialize, Serialize};
|
||
|
use std::ops::{Add, Sub};
|
||
|
|
||
|
#[derive(Deserialize)]
|
||
|
enum Recurring {
|
||
|
Daily,
|
||
|
Weeky,
|
||
|
BiWeekly,
|
||
|
Monthly,
|
||
|
Quarterly,
|
||
|
Yearly,
|
||
|
}
|
||
|
|
||
|
#[derive(Deserialize)]
|
||
|
enum Move {
|
||
|
Before,
|
||
|
After,
|
||
|
}
|
||
|
|
||
|
#[derive(Deserialize)]
|
||
|
struct EventQuery {
|
||
|
/// Start date
|
||
|
start_date_time: NaiveDateTime,
|
||
|
/// Recurring date
|
||
|
recurring: Recurring,
|
||
|
// If set, will ignore time on start_date
|
||
|
all_day: bool,
|
||
|
/// Title of the event
|
||
|
title: String,
|
||
|
// Optionals
|
||
|
end_date: Option<NaiveDate>,
|
||
|
avoid_weekends: Option<bool>,
|
||
|
on_collition: Option<Move>,
|
||
|
}
|
||
|
|
||
|
#[derive(Deserialize)]
|
||
|
enum Time {
|
||
|
/// Specific time at day
|
||
|
DateTime {
|
||
|
start: NaiveDateTime,
|
||
|
end: NaiveDateTime,
|
||
|
},
|
||
|
/// All day
|
||
|
Date(NaiveDate),
|
||
|
}
|
||
|
|
||
|
#[derive(Deserialize)]
|
||
|
struct EventBody {
|
||
|
/// Start date
|
||
|
time: Time,
|
||
|
/// Recurring date
|
||
|
recurring: Recurring,
|
||
|
/// Title of the event
|
||
|
title: String,
|
||
|
// Optionals
|
||
|
end_date: Option<NaiveDate>,
|
||
|
ignore_weekdays: Vec<Weekday>,
|
||
|
on_collition: Option<Move>,
|
||
|
}
|
||
|
|
||
|
/// TODO create ical object
|
||
|
/// TODO implement Before / After
|
||
|
/// TODO what if start_date is weekend
|
||
|
async fn get_calendar(Query(query): Query<EventQuery>) -> impl IntoResponse {
|
||
|
let start = query.start_date_time;
|
||
|
let start_day = start.day();
|
||
|
let end = query
|
||
|
.end_date
|
||
|
.unwrap_or_else(|| (start + TimeDelta::days(365)).date());
|
||
|
|
||
|
let mut events = vec![start];
|
||
|
let mut previous_date_time = start;
|
||
|
while previous_date_time.date() < end {
|
||
|
previous_date_time = previous_date_time.with_day(start_day).unwrap();
|
||
|
let next = match query.recurring {
|
||
|
Recurring::Daily => todo!(),
|
||
|
Recurring::Weeky => todo!(),
|
||
|
Recurring::BiWeekly => todo!(),
|
||
|
Recurring::Monthly => {
|
||
|
let new_date = previous_date_time
|
||
|
.checked_add_months(Months::new(1))
|
||
|
.unwrap();
|
||
|
if let Some(true) = query.avoid_weekends {
|
||
|
match new_date.weekday() {
|
||
|
Weekday::Sat => new_date.sub(TimeDelta::days(1)),
|
||
|
Weekday::Sun => new_date.sub(TimeDelta::days(2)),
|
||
|
_ => new_date,
|
||
|
}
|
||
|
} else {
|
||
|
new_date
|
||
|
}
|
||
|
}
|
||
|
Recurring::Quarterly => todo!(),
|
||
|
Recurring::Yearly => todo!(),
|
||
|
};
|
||
|
events.push(next);
|
||
|
previous_date_time = next;
|
||
|
}
|
||
|
Json(events)
|
||
|
}
|
||
|
|
||
|
#[tokio::main]
|
||
|
async fn main() {
|
||
|
let app = Router::new().route("/", get(get_calendar));
|
||
|
|
||
|
let listener = tokio::net::TcpListener::bind("0.0.0.0:8000").await.unwrap();
|
||
|
axum::serve(listener, app).await.unwrap();
|
||
|
}
|