announcement/reminder
This commit is contained in:
parent
fecf6ebed5
commit
7093280d80
|
@ -80,6 +80,14 @@ impl SimpleEmail {
|
||||||
self.in_reply_to.clone(),
|
self.in_reply_to.clone(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
pub fn into_parts(self) -> (Email, String, Vec<String>, Option<String>) {
|
||||||
|
(self.base, self.from, self.to, self.in_reply_to)
|
||||||
|
}
|
||||||
|
pub fn from_parts(
|
||||||
|
base: Email, from: String, to: Vec<String>, in_reply_to: Option<String>,
|
||||||
|
) -> Self {
|
||||||
|
Self { base, from, to, in_reply_to }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Email {
|
impl Email {
|
||||||
|
|
144
src/main.rs
144
src/main.rs
|
@ -76,6 +76,7 @@ const CONFIG_SPEC: CfgSpec<'static> = CfgSpec {
|
||||||
default: "NORMAL",
|
default: "NORMAL",
|
||||||
description: "Named state of the program logic. (NORMAL, ANNOUNCED, REMINDED, LOGGED)",
|
description: "Named state of the program logic. (NORMAL, ANNOUNCED, REMINDED, LOGGED)",
|
||||||
},
|
},
|
||||||
|
CfgField::Optional { key: "toc", description: "Table of contents / pad summary." },
|
||||||
CfgField::Optional { key: "last-run",
|
CfgField::Optional { key: "last-run",
|
||||||
description: "Last run of the program (used to figure out state of previous plenum mails.)",
|
description: "Last run of the program (used to figure out state of previous plenum mails.)",
|
||||||
},
|
},
|
||||||
|
@ -267,7 +268,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||||
&config["email-password"],
|
&config["email-password"],
|
||||||
is_dry_run(),
|
is_dry_run(),
|
||||||
);
|
);
|
||||||
let email = SimpleEmail::new(
|
let mut email = SimpleEmail::new(
|
||||||
email_,
|
email_,
|
||||||
&config["email-from"],
|
&config["email-from"],
|
||||||
&config["email-to"],
|
&config["email-to"],
|
||||||
|
@ -299,8 +300,12 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||||
eprintln!("WARNING: last run was a long time ago, resetting state.");
|
eprintln!("WARNING: last run was a long time ago, resetting state.");
|
||||||
last_state = ProgramState::Normal;
|
last_state = ProgramState::Normal;
|
||||||
do_cleanup(999, &today, &config, &hedgedoc, &email, &wiki)?;
|
do_cleanup(999, &today, &config, &hedgedoc, &email, &wiki)?;
|
||||||
|
// reset will have cleared in-reply-to if it existed
|
||||||
|
let (base, from, to, _) = email.into_parts();
|
||||||
|
email = SimpleEmail::from_parts(base, from, to, config.get("email-in-reply-to").ok());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let email = email;
|
||||||
let last_state = last_state;
|
let last_state = last_state;
|
||||||
// figure out where we should be
|
// figure out where we should be
|
||||||
// deltas has either 2 or 3 days, if 3 then the middle one is == 0 (i.e. today)
|
// deltas has either 2 or 3 days, if 3 then the middle one is == 0 (i.e. today)
|
||||||
|
@ -415,7 +420,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||||
.get("hedgedoc-next-id")
|
.get("hedgedoc-next-id")
|
||||||
.expect("ID des nächsten Pads undefiniert. Bitte in der DB eintragen oder generieren.");
|
.expect("ID des nächsten Pads undefiniert. Bitte in der DB eintragen oder generieren.");
|
||||||
|
|
||||||
let mut message_id: Option<String> = None;
|
let mut message_id: String;
|
||||||
|
|
||||||
// let in_3_days_is_plenum = true;
|
// let in_3_days_is_plenum = true;
|
||||||
//TEMPORÄR ANFANG: BEI PRODUCTION MUSS DAS HIER RAUS
|
//TEMPORÄR ANFANG: BEI PRODUCTION MUSS DAS HIER RAUS
|
||||||
|
@ -453,7 +458,7 @@ Und hier ein TL;DR von den aktuellen Themen:
|
||||||
|
|
||||||
Bis morgen, 20 Uhr!"#
|
Bis morgen, 20 Uhr!"#
|
||||||
); // ADJ_TIMEYWIMEY
|
); // ADJ_TIMEYWIMEY
|
||||||
message_id = send_email(&betreff, &message, &email, &config);
|
message_id = send_email(&betreff, &message, &email, &config)?;
|
||||||
// .expect("Plenum findet statt. Mail wurde versucht zu senden, konnte aber nicht gesendet werden!")
|
// .expect("Plenum findet statt. Mail wurde versucht zu senden, konnte aber nicht gesendet werden!")
|
||||||
} else {
|
} else {
|
||||||
// Mail an alle senden und absagen
|
// Mail an alle senden und absagen
|
||||||
|
@ -467,23 +472,9 @@ Hier ist der Link zum Pad vom nächsten Plenum, das am {} statt finden wird:
|
||||||
Bis zum nächsten Plenum."#,
|
Bis zum nächsten Plenum."#,
|
||||||
nächster_plenumtermin
|
nächster_plenumtermin
|
||||||
);
|
);
|
||||||
message_id = send_email(&betreff, &message, &email, &config);
|
message_id = send_email(&betreff, &message, &email, &config)?;
|
||||||
// .expect("Plenum wird abgesagt. Mail wurde versucht zu senden, konnte aber nicht gesendet werden!"))
|
// .expect("Plenum wird abgesagt. Mail wurde versucht zu senden, konnte aber nicht gesendet werden!"))
|
||||||
}
|
}
|
||||||
} else if in_3_days_is_plenum {
|
|
||||||
println!("In 3 Tagen ist Plenum, deshalb wird eine Erinnerung raus geschickt!");
|
|
||||||
if number_of_tops(&pad_content_without_top_instructions) == 0 {
|
|
||||||
// Mail an alle senden und sagen, dass es noch keine Themen gibt
|
|
||||||
let betreff = format!("Plenum vom {}: Bisher noch keine Themen", nächster_plenumtermin);
|
|
||||||
let message: String = format!(
|
|
||||||
r#"Es sind bisher leider keine Themen zusammengekommen. Wenn es bis Sonntag Abend keine Themen gibt, wird das Plenum voraussichtlich nicht statt finden.
|
|
||||||
|
|
||||||
Hier ist der Link zum Pad, wo ihr noch Themen eintragen könnt:
|
|
||||||
{current_pad_link}"#
|
|
||||||
);
|
|
||||||
message_id = send_email(&betreff, &message, &email, &config);
|
|
||||||
// .expect("Noch nicht genug Themen. Mail wurde versucht zu senden, konnte aber nicht gesendet werden!"))
|
|
||||||
}
|
|
||||||
} else if yesterday_was_plenum {
|
} else if yesterday_was_plenum {
|
||||||
// This logic breaks on 02/2034, but on every other month it works
|
// This logic breaks on 02/2034, but on every other month it works
|
||||||
let old_pad_content =
|
let old_pad_content =
|
||||||
|
@ -516,7 +507,7 @@ Und hier ist das Protokoll des letzten Plenums:
|
||||||
let betreff: String =
|
let betreff: String =
|
||||||
format!("Plenumsprotokoll vom {}: Es gab {} TOPs", nächster_plenumtermin, top_anzahl);
|
format!("Plenumsprotokoll vom {}: Es gab {} TOPs", nächster_plenumtermin, top_anzahl);
|
||||||
// XXX option x expect
|
// XXX option x expect
|
||||||
message_id = send_email(&betreff, &message, &email, &config);
|
message_id = send_email(&betreff, &message, &email, &config)?;
|
||||||
// .expect("Mail mit Plenumsprotokoll wurde versucht zu senden, konnte aber nicht gesendet werden!"));
|
// .expect("Mail mit Plenumsprotokoll wurde versucht zu senden, konnte aber nicht gesendet werden!"));
|
||||||
mediawiki::pad_ins_wiki(old_pad_content_without_top_instructions);
|
mediawiki::pad_ins_wiki(old_pad_content_without_top_instructions);
|
||||||
}
|
}
|
||||||
|
@ -674,42 +665,103 @@ fn upper_first(s: &str) -> String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ***** transition actions ***** */
|
fn topic_count(n: usize, dative: bool) -> String {
|
||||||
|
match n {
|
||||||
|
0 => format!("noch keine{} Themen", if dative { "n" } else { "" }),
|
||||||
|
1 => format!("ein{} Thema", if dative { "em" } else { "" }),
|
||||||
|
_ => format!("{} Themen", n),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// BBBBBBBBBB
|
/* ***** repeating action parts ***** */
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
fn get_pad_info(config: &KV, hedgedoc: &HedgeDoc) -> (String, String, usize) {
|
||||||
fn do_announcement(
|
|
||||||
ttp: i64, plenum_day: &NaiveDate, config: &KV, hedgedoc: &HedgeDoc, email: &SimpleEmail,
|
|
||||||
wiki: &Mediawiki,
|
|
||||||
) -> Result<(), Box<dyn Error>> {
|
|
||||||
let current_pad_id = &config["hedgedoc-last-id"];
|
let current_pad_id = &config["hedgedoc-last-id"];
|
||||||
let pad_content = hedgedoc.download(current_pad_id).expect("Hedgedoc: Download-Fehler");
|
let pad_content = hedgedoc.download(current_pad_id).expect("Hedgedoc: Download-Fehler");
|
||||||
let toc = hedgedoc::summarize(pad_content);
|
let toc = hedgedoc::summarize(pad_content);
|
||||||
verboseln!("Zusammenfassung des aktuellen Plenum-Pads:\n{}", toc.cyan());
|
verboseln!("Zusammenfassung des aktuellen Plenum-Pads:\n{}", toc.cyan());
|
||||||
let n_topics = toc.lines().count();
|
let n_topics = toc.lines().count();
|
||||||
verboseln!("(Das sind {} Themen.)", n_topics.to_string().cyan());
|
verboseln!("(Also {}.)", topic_count(n_topics, false).cyan());
|
||||||
// TODO: if
|
(current_pad_id.to_string(), toc, n_topics)
|
||||||
// summary empty: write message variant
|
}
|
||||||
// summary not empty: write other message variant
|
|
||||||
// TODO: set/write state as Announced
|
/* ***** transition actions ***** */
|
||||||
// TODO: write summary
|
|
||||||
todo!()
|
// BBBBBBBBBB
|
||||||
|
|
||||||
|
fn do_announcement(
|
||||||
|
ttp: i64, plenum_day: &NaiveDate, config: &KV, hedgedoc: &HedgeDoc, email: &SimpleEmail,
|
||||||
|
_wiki: &Mediawiki,
|
||||||
|
) -> Result<(), Box<dyn Error>> {
|
||||||
|
// fetch current pad contents & summarize
|
||||||
|
let (current_pad_id, toc, n_topics) = get_pad_info(config, hedgedoc);
|
||||||
|
// construct email
|
||||||
|
let subject = format!(
|
||||||
|
"Plenum {} (am {}): bisher {}",
|
||||||
|
relative_date(ttp),
|
||||||
|
plenum_day.format("%d.%m.%Y"),
|
||||||
|
topic_count(n_topics, false)
|
||||||
|
);
|
||||||
|
let line1 = if n_topics == 0 {
|
||||||
|
format!( "Es sind bisher leider noch keine Themen zusammengekommen. Wenn am Montag immer noch nix ist, dann fällt das Plenum aus." )
|
||||||
|
} else {
|
||||||
|
format!("Die bisherigen Themen für das Plenum sind:\n\n{toc}")
|
||||||
|
};
|
||||||
|
let line2 = format!(
|
||||||
|
"Falls ihr noch Themen ergänzen wollt ist hier der Link zum Pad:\n {}",
|
||||||
|
hedgedoc.format_url(¤t_pad_id)
|
||||||
|
);
|
||||||
|
let body = format!("{line1}\n\n{line2}");
|
||||||
|
// send it
|
||||||
|
let message_id = send_email(&subject, &body, &email, &config)?;
|
||||||
|
// on success, update state (ignore write errors, they'll be checked later)
|
||||||
|
config.set("email-message-id", &message_id).ok();
|
||||||
|
config.set("state-name", &ProgramState::Announced.to_string()).ok();
|
||||||
|
config.set("state-toc", &toc).ok();
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn do_reminder(
|
fn do_reminder(
|
||||||
ttp: i64, plenum_day: &NaiveDate, config: &KV, hedgedoc: &HedgeDoc, email: &SimpleEmail,
|
ttp: i64, plenum_day: &NaiveDate, config: &KV, hedgedoc: &HedgeDoc, email: &SimpleEmail,
|
||||||
wiki: &Mediawiki,
|
_wiki: &Mediawiki,
|
||||||
) -> Result<(), Box<dyn Error>> {
|
) -> Result<(), Box<dyn Error>> {
|
||||||
// TODO: get pad
|
// fetch current pad contents & summarize
|
||||||
// TODO: make summary
|
let (current_pad_id, toc, n_topics) = get_pad_info(config, hedgedoc);
|
||||||
// TODO: if
|
let old_toc = config.get("state-toc").unwrap_or_default();
|
||||||
// summary empty: write message variant
|
// construct email
|
||||||
// summary not empty: make diff, send diff etc.
|
let subject_suffix = if n_topics == 0 {
|
||||||
// TODO: set/write state as Reminded
|
" fällt aus (keine Themen)".to_string()
|
||||||
// TODO: write summary
|
} else {
|
||||||
todo!()
|
format!(" findet mit {} statt", topic_count(n_topics, true))
|
||||||
|
};
|
||||||
|
let subject = format!(
|
||||||
|
"Plenum {} (am {}) {}",
|
||||||
|
relative_date(ttp),
|
||||||
|
plenum_day.format("%d.%m.%Y"),
|
||||||
|
subject_suffix
|
||||||
|
);
|
||||||
|
let body_prefix = if old_toc == toc {
|
||||||
|
format!("Die Themen sind gleich geblieben. ")
|
||||||
|
} else {
|
||||||
|
format!("Es gab nochmal Änderungen, die aktualisierten Themen für das Plenum sind:\n\n{toc}\n\n")
|
||||||
|
};
|
||||||
|
let body = if n_topics > 0 {
|
||||||
|
format!(
|
||||||
|
"{body_prefix}Die vollen Details findet ihr im Pad:\n {}",
|
||||||
|
hedgedoc.format_url(¤t_pad_id)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
"Da es immer noch keine Themen gibt fällt das Plenum aus.\n\n".to_string()
|
||||||
|
+ "(Natürlich könnt ihr im Bedarfsfall immer noch kurzfristig ein Treffen einberufen, aber bitte "
|
||||||
|
+ "kündigt das so früh wie möglich an, damit Leute sich darauf einstellen können.)"
|
||||||
|
// TODO generate + add link for next pad
|
||||||
|
};
|
||||||
|
// send it
|
||||||
|
let _message_id = send_email(&subject, &body, &email, &config)?;
|
||||||
|
// on success, update state (ignore write errors, they'll be checked later)
|
||||||
|
config.set("state-name", &ProgramState::Reminded.to_string()).ok();
|
||||||
|
config.set("state-toc", &toc).ok();
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
|
@ -880,11 +932,13 @@ impl std::fmt::Display for ProgramState {
|
||||||
|
|
||||||
/* ***** wrappers ***** */
|
/* ***** wrappers ***** */
|
||||||
|
|
||||||
fn send_email(subject: &str, body: &str, email: &SimpleEmail, config: &KV) -> Option<String> {
|
fn send_email(
|
||||||
|
subject: &str, body: &str, email: &SimpleEmail, config: &KV,
|
||||||
|
) -> Result<String, Box<dyn Error>> {
|
||||||
let full_subject = format!("[PleB] {}", subject);
|
let full_subject = format!("[PleB] {}", subject);
|
||||||
let full_body = format!(
|
let full_body = format!(
|
||||||
"{}\n\n{}\n\n{}",
|
"{}\n\n{}\n\n{}",
|
||||||
&config["text-email-greeting"], body, &config["text-email-signature"]
|
&config["text-email-greeting"], body, &config["text-email-signature"]
|
||||||
);
|
);
|
||||||
email.send_email(full_subject, full_body).ok()
|
email.send_email(full_subject, full_body)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue