add support for CommonNinja calendars
This commit is contained in:
parent
4140010bf2
commit
097745aeed
5 changed files with 166 additions and 18 deletions
121
src/wac_common_ninja.rs
Normal file
121
src/wac_common_ninja.rs
Normal file
|
@ -0,0 +1,121 @@
|
|||
use super::{CalendarUi, EventInstance, Parameters, SimpleDownload};
|
||||
use crate::prelude::*;
|
||||
|
||||
#[derive(Clone, Default, Deserialize)]
|
||||
struct SillyDownloadable {
|
||||
/// URL to scrape to download the file from
|
||||
download_url: Option<Url>,
|
||||
|
||||
/// Disk location to cache the file for debugging
|
||||
file_path: Utf8PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, Deserialize)]
|
||||
pub(crate) struct Config {
|
||||
#[serde(flatten)]
|
||||
pub(crate) dl: SillyDownloadable,
|
||||
|
||||
#[serde(flatten)]
|
||||
pub(crate) ui: CalendarUi,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub(crate) fn simple_download(&self) -> SimpleDownload {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct Event {
|
||||
#[serde(alias = "durationInMinutes")]
|
||||
duration_in_minutes: u32,
|
||||
timestamp: i64,
|
||||
title: String,
|
||||
description: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct Data {
|
||||
items: Vec<Event>,
|
||||
}
|
||||
|
||||
/// The bit that we deserialize directly from JSON
|
||||
#[derive(Deserialize)]
|
||||
struct CalendarInner {
|
||||
data: Data,
|
||||
}
|
||||
|
||||
pub(crate) struct Calendar {
|
||||
config: Config,
|
||||
inner: CalendarInner,
|
||||
}
|
||||
|
||||
impl Calendar {
|
||||
fn to_event_instance(&self, params: &Parameters, ev: &Event) -> Result<Option<EventInstance>> {
|
||||
let dt = chrono::DateTime::from_timestamp_millis(ev.timestamp)
|
||||
.context("cannot represent timestamp as a date")?
|
||||
.with_timezone(¶ms.tz);
|
||||
let dtstart = crate::DatePerhapsTime { dt, all_day: false };
|
||||
if dtstart.dt < params.output_start || dtstart.dt > params.output_stop {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
Ok(Some(EventInstance {
|
||||
calendar_ui: self.config.ui.clone(),
|
||||
dtstart,
|
||||
location: None,
|
||||
recurrence_id: None,
|
||||
summary: Some(ev.title.clone()),
|
||||
uid: None,
|
||||
url: None,
|
||||
}))
|
||||
}
|
||||
|
||||
pub(crate) fn event_instances(&self, params: &Parameters) -> Result<Vec<EventInstance>> {
|
||||
self.inner
|
||||
.data
|
||||
.items
|
||||
.iter()
|
||||
.filter_map(|ev| self.to_event_instance(params, ev).transpose())
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub(crate) fn read_from_str(config: Config, s: &str) -> Result<Self> {
|
||||
let inner = serde_json::from_str(s)?;
|
||||
Ok(Self { config, inner })
|
||||
}
|
||||
|
||||
pub(crate) fn read_from_config(config: Config) -> Result<Self> {
|
||||
let s = std::fs::read_to_string(&config.dl.file_path)?;
|
||||
Self::read_from_str(config, &s)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn end_to_end() {
|
||||
let s = r#"
|
||||
{"data":{"items":[{"timestamp":1748989800000,"durationInMinutes":90,"title":"Foo Bar","description":""},{"timestamp":1749999600000,"durationInMinutes":30,"title":"Snaf Oo","description":""}]},"success":true,"message":""}
|
||||
"#;
|
||||
|
||||
let cfg = Config {
|
||||
dl: SillyDownloadable {
|
||||
download_url: None,
|
||||
file_path: ".".into(),
|
||||
},
|
||||
ui: CalendarUi {
|
||||
html_url: None,
|
||||
short_name: "asdf".into(),
|
||||
},
|
||||
};
|
||||
let cal = Calendar::read_from_str(cfg, s).unwrap();
|
||||
let params =
|
||||
Parameters::new(Utc::now().with_timezone(&chrono_tz::America::Chicago)).unwrap();
|
||||
let instances = cal.event_instances(¶ms).unwrap();
|
||||
|
||||
assert_eq!(instances.len(), 2);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue