server: render text extract calendar info w/ ics template
This commit is contained in:
parent
3fd41062d7
commit
3311f2fc00
@ -189,10 +189,6 @@ pub fn extract_calendar_metadata_from_mail(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Fallback: if body_html is still None, generate a minimal calendar HTML using all available metadata
|
// Fallback: if body_html is still None, generate a minimal calendar HTML using all available metadata
|
||||||
let summary_val = summary.clone().unwrap_or_default();
|
|
||||||
let organizer_val = organizer.clone().unwrap_or_default();
|
|
||||||
let start_val = start_date.clone().unwrap_or_default();
|
|
||||||
let end_val = end_date.clone().unwrap_or_default();
|
|
||||||
// Improved recurrence detection: check for common recurrence phrases in subject, HTML, and plain text body
|
// Improved recurrence detection: check for common recurrence phrases in subject, HTML, and plain text body
|
||||||
let mut has_recurrence = false;
|
let mut has_recurrence = false;
|
||||||
let recurrence_phrases = [
|
let recurrence_phrases = [
|
||||||
@ -220,31 +216,54 @@ pub fn extract_calendar_metadata_from_mail(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let recurrence_html: &str = if has_recurrence { "<div class='ical-recurrence'>Repeats</div>" } else { "" };
|
|
||||||
let minimal_html = format!(
|
|
||||||
r#"<div class='ical-flex'><div class='ical-summary'>{}</div><div class='ical-organizer'>{}</div><div class='ical-dates'>{} to {}</div>{}</div>"#,
|
|
||||||
html_escape::encode_text(&summary_val),
|
|
||||||
html_escape::encode_text(&organizer_val),
|
|
||||||
html_escape::encode_text(&start_val),
|
|
||||||
html_escape::encode_text(&end_val),
|
|
||||||
recurrence_html
|
|
||||||
);
|
|
||||||
let needs_ical_flex = summary.is_some() || start_date.is_some() || end_date.is_some() || has_recurrence;
|
let needs_ical_flex = summary.is_some() || start_date.is_some() || end_date.is_some() || has_recurrence;
|
||||||
if needs_ical_flex {
|
if needs_ical_flex {
|
||||||
|
let summary_val = summary.clone().unwrap_or_default();
|
||||||
|
let organizer_val = organizer.clone().unwrap_or_default();
|
||||||
|
let start_val = start_date.clone().unwrap_or_default();
|
||||||
|
let end_val = end_date.clone().unwrap_or_default();
|
||||||
|
let recurrence_display = if has_recurrence { "Repeats".to_string() } else { String::new() };
|
||||||
|
let template = IcalSummaryTemplate {
|
||||||
|
summary: &summary_val,
|
||||||
|
local_fmt_start: &start_val,
|
||||||
|
local_fmt_end: &end_val,
|
||||||
|
organizer: &organizer_val,
|
||||||
|
organizer_cn: "",
|
||||||
|
all_days: vec![],
|
||||||
|
event_days: vec![],
|
||||||
|
caption: String::new(),
|
||||||
|
description_paragraphs: &[],
|
||||||
|
today: Some(chrono::Local::now().date_naive()),
|
||||||
|
recurrence_display,
|
||||||
|
};
|
||||||
|
let fallback_html = template.render().unwrap_or_else(|_| String::from("<div class='ical-flex'></div>"));
|
||||||
match &mut body_html {
|
match &mut body_html {
|
||||||
Some(existing) => {
|
Some(existing) => {
|
||||||
if !existing.starts_with(&minimal_html) {
|
if !existing.starts_with(&fallback_html) {
|
||||||
*existing = format!("{}{}", minimal_html, existing);
|
*existing = format!("{}{}", fallback_html, existing);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
body_html = Some(minimal_html);
|
body_html = Some(fallback_html);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Final guarantee: if body_html is still None, set to minimal ical-flex HTML with empty fields
|
// Final guarantee: if body_html is still None, set to minimal ical-flex HTML with empty fields using the template
|
||||||
if body_html.is_none() {
|
if body_html.is_none() {
|
||||||
body_html = Some("<div class='ical-flex'><div class='ical-summary'></div><div class='ical-organizer'></div><div class='ical-dates'> to </div></div>".to_string());
|
let template = IcalSummaryTemplate {
|
||||||
|
summary: "",
|
||||||
|
local_fmt_start: "",
|
||||||
|
local_fmt_end: "",
|
||||||
|
organizer: "",
|
||||||
|
organizer_cn: "",
|
||||||
|
all_days: vec![],
|
||||||
|
event_days: vec![],
|
||||||
|
caption: String::new(),
|
||||||
|
description_paragraphs: &[],
|
||||||
|
today: Some(chrono::Local::now().date_naive()),
|
||||||
|
recurrence_display: String::new(),
|
||||||
|
};
|
||||||
|
body_html = Some(template.render().unwrap_or_else(|_| String::from("<div class='ical-flex'></div>")));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Improved fallback: extract summary, start_date, end_date, and recurrence from subject/body if not found
|
// Improved fallback: extract summary, start_date, end_date, and recurrence from subject/body if not found
|
||||||
@ -314,11 +333,7 @@ pub fn extract_calendar_metadata_from_mail(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Try to detect recurrence from subject
|
// Try to detect recurrence from subject
|
||||||
if recurrence_html.is_empty() {
|
// recurrence detection and rendering is now handled by the template logic
|
||||||
if subject.to_lowercase().contains("recurr") || subject.to_lowercase().contains("repeat") {
|
|
||||||
// recurrence_html assignment removed; handled at HTML generation
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Try to extract summary from body if still missing
|
// Try to extract summary from body if still missing
|
||||||
if summary.is_none() {
|
if summary.is_none() {
|
||||||
@ -2154,19 +2169,20 @@ mod tests {
|
|||||||
// Calendar widget should be rendered
|
// Calendar widget should be rendered
|
||||||
let html = meta.body_html.expect("body_html");
|
let html = meta.body_html.expect("body_html");
|
||||||
println!("Rendered HTML for verification:\n{}", html);
|
println!("Rendered HTML for verification:\n{}", html);
|
||||||
// Check that the HTML contains the summary, organizer, start, and end times
|
// Check that the HTML contains the summary, organizer, start, and end times with labels
|
||||||
assert!(html.contains(">McClure BLT<"), "HTML should contain the summary/title");
|
assert!(html.contains("<b>Summary:</b> McClure BLT"), "HTML should contain the labeled summary/title");
|
||||||
assert!(html.contains(">calendar-notification@google.com<"), "HTML should contain the organizer");
|
assert!(html.contains("<b>Organizer:</b> calendar-notification@google.com"), "HTML should contain the labeled organizer");
|
||||||
assert!(html.contains(">20250911 to 20260131<"), "HTML should contain the start and end times");
|
assert!(html.contains("<b>Start:</b> 20250911"), "HTML should contain the labeled start time");
|
||||||
|
assert!(html.contains("<b>End:</b> 20260131"), "HTML should contain the labeled end time");
|
||||||
if !html.contains("ical-flex") {
|
if !html.contains("ical-flex") {
|
||||||
println!("FAIL: html did not contain 'ical-flex':\n{}", html);
|
println!("FAIL: html did not contain 'ical-flex':\n{}", html);
|
||||||
}
|
}
|
||||||
assert!(html.contains("ical-flex"), "Calendar widget should be rendered");
|
assert!(html.contains("ical-flex"), "Calendar widget should be rendered");
|
||||||
// Recurrence info should be present
|
// Recurrence info should be present
|
||||||
if !(html.contains("Repeats") || html.contains("recurr") || html.contains("RRULE")) {
|
if !(html.contains("<b>Repeats:</b> Repeats") || html.contains("recurr") || html.contains("RRULE")) {
|
||||||
println!("FAIL: html did not contain recurrence info:\n{}", html);
|
println!("FAIL: html did not contain recurrence info:\n{}", html);
|
||||||
}
|
}
|
||||||
assert!(html.contains("Repeats") || html.contains("recurr") || html.contains("RRULE"), "Recurrence info should be present in HTML");
|
assert!(html.contains("<b>Repeats:</b> Repeats") || html.contains("recurr") || html.contains("RRULE"), "Recurrence info should be present in HTML");
|
||||||
}
|
}
|
||||||
use super::*;
|
use super::*;
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user