Collect ingredients from recipes for grocery list
This commit is contained in:
parent
c649fbf88c
commit
ed5a6d2306
7 changed files with 168 additions and 239 deletions
|
@ -3,16 +3,17 @@
|
|||
|
||||
use {
|
||||
crate::api_client::ApiClient,
|
||||
crate::constants,
|
||||
crate::recipe::{Ingredient, Recipe},
|
||||
anyhow::{anyhow, Result},
|
||||
chrono::{Duration, Local, NaiveDateTime},
|
||||
anyhow::Result,
|
||||
chrono::{Duration, Local},
|
||||
icalendar::Component,
|
||||
regex::Regex,
|
||||
std::collections::HashSet,
|
||||
std::ops::Range,
|
||||
};
|
||||
|
||||
pub async fn with(api_client: &ApiClient, calendar_name: &str, days: u32) -> Result<()> {
|
||||
let ids = map_events_to_recipe_ids(api_client, calendar_name, days)?;
|
||||
let ids = map_events_to_recipe_ids(api_client, calendar_name, days).await?;
|
||||
let ingredients = get_ingredients(api_client, ids).await?;
|
||||
|
||||
todo!("Recipe ingredients: {:?}", ingredients)
|
||||
|
@ -22,57 +23,25 @@ pub async fn with(api_client: &ApiClient, calendar_name: &str, days: u32) -> Res
|
|||
// save_grocery_list(api_client, "", md).await?;
|
||||
}
|
||||
|
||||
fn map_events_to_recipe_ids(
|
||||
async fn map_events_to_recipe_ids(
|
||||
api_client: &ApiClient,
|
||||
calendar_name: &str,
|
||||
days: u32,
|
||||
) -> Result<HashSet<usize>> {
|
||||
// minicaldav is quite hamfisted in retrieving events (it gets everything, every time).
|
||||
// Consider crafting an XML request and use something else for ical parsing.
|
||||
let date_range = Range {
|
||||
start: Local::now(),
|
||||
end: Local::now() + Duration::days(days as i64),
|
||||
};
|
||||
|
||||
let calendars = api_client
|
||||
.get_calendars()
|
||||
.map_err(|err| convert_caldav_err(err))?;
|
||||
let calendar = calendars
|
||||
.into_iter()
|
||||
.filter(|c| c.name() == calendar_name)
|
||||
.next()
|
||||
.ok_or(anyhow!(
|
||||
"Unable to find calendar '{}' on server",
|
||||
calendar_name
|
||||
))?;
|
||||
|
||||
let all_events = api_client
|
||||
.get_events(&calendar)
|
||||
.map_err(|err| convert_caldav_err(err))?
|
||||
.0;
|
||||
|
||||
let relevant_events = all_events.into_iter().filter(|ev| {
|
||||
ev.get("PRODID")
|
||||
.map(|p| p == constants::CALENDAR_PROVIDER)
|
||||
.unwrap_or(false)
|
||||
&& {
|
||||
let start_time = NaiveDateTime::parse_from_str(
|
||||
ev.property("DTSTART").unwrap().value(),
|
||||
"%Y%m%dT%H%M%S",
|
||||
)
|
||||
.unwrap_or(NaiveDateTime::from_timestamp(0, 0));
|
||||
let now = Local::now().naive_local();
|
||||
start_time >= now && start_time < now + Duration::days(days as i64)
|
||||
}
|
||||
});
|
||||
let all_events = api_client.get_events(calendar_name, date_range).await?;
|
||||
|
||||
let recipe_id_regex: Regex = Regex::new(r"cookbook@(\d+)").unwrap();
|
||||
let recipe_ids = relevant_events
|
||||
.flat_map(|event| {
|
||||
event
|
||||
.property("DESCRIPTION")
|
||||
.iter()
|
||||
.flat_map(|descr| recipe_id_regex.captures(descr.value()))
|
||||
.flat_map(|c| c.get(1))
|
||||
.flat_map(|m| m.as_str().parse::<usize>())
|
||||
.collect::<Vec<usize>>()
|
||||
})
|
||||
let recipe_ids = all_events
|
||||
.iter()
|
||||
.flat_map(|event| event.property_value("DESCRIPTION"))
|
||||
.flat_map(|descr| recipe_id_regex.captures(descr))
|
||||
.flat_map(|c| c.get(1))
|
||||
.flat_map(|m| m.as_str().parse::<usize>())
|
||||
.collect::<HashSet<_>>();
|
||||
|
||||
Ok(recipe_ids)
|
||||
|
@ -101,7 +70,3 @@ where
|
|||
let ingredients = futures::future::try_join_all(ingredients).await?;
|
||||
Ok(ingredients.into_iter().flatten().collect())
|
||||
}
|
||||
|
||||
fn convert_caldav_err(err: minicaldav::Error) -> anyhow::Error {
|
||||
anyhow!(format!("{:?}", err))
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue