Compare commits

...

6 Commits

427
Cargo.lock generated

@ -89,6 +89,132 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "async-channel"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35"
dependencies = [
"concurrent-queue",
"event-listener",
"futures-core",
]
[[package]]
name = "async-executor"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fa3dc5f2a8564f07759c008b9109dc0d39de92a88d5588b8a5036d286383afb"
dependencies = [
"async-lock",
"async-task",
"concurrent-queue",
"fastrand 1.9.0",
"futures-lite",
"slab",
]
[[package]]
name = "async-global-executor"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776"
dependencies = [
"async-channel",
"async-executor",
"async-io",
"async-lock",
"blocking",
"futures-lite",
"once_cell",
]
[[package]]
name = "async-io"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af"
dependencies = [
"async-lock",
"autocfg",
"cfg-if",
"concurrent-queue",
"futures-lite",
"log",
"parking",
"polling",
"rustix 0.37.23",
"slab",
"socket2 0.4.9",
"waker-fn",
]
[[package]]
name = "async-lock"
version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b"
dependencies = [
"event-listener",
]
[[package]]
name = "async-process"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a9d28b1d97e08915212e2e45310d47854eafa69600756fc735fb788f75199c9"
dependencies = [
"async-io",
"async-lock",
"autocfg",
"blocking",
"cfg-if",
"event-listener",
"futures-lite",
"rustix 0.37.23",
"signal-hook",
"windows-sys",
]
[[package]]
name = "async-std"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d"
dependencies = [
"async-channel",
"async-global-executor",
"async-io",
"async-lock",
"async-process",
"crossbeam-utils",
"futures-channel",
"futures-core",
"futures-io",
"futures-lite",
"gloo-timers",
"kv-log-macro",
"log",
"memchr",
"once_cell",
"pin-project-lite",
"pin-utils",
"slab",
"wasm-bindgen-futures",
]
[[package]]
name = "async-task"
version = "4.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae"
[[package]]
name = "atomic-waker"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3"
[[package]]
name = "autocfg"
version = "1.1.0"
@ -128,6 +254,21 @@ version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
[[package]]
name = "blocking"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77231a1c8f801696fc0123ec6150ce92cffb8e164a02afb9c8ddee0e9b65ad65"
dependencies = [
"async-channel",
"async-lock",
"async-task",
"atomic-waker",
"fastrand 1.9.0",
"futures-lite",
"log",
]
[[package]]
name = "bumpalo"
version = "3.13.0"
@ -237,6 +378,15 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "concurrent-queue"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "core-foundation"
version = "0.9.3"
@ -253,12 +403,58 @@ version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
[[package]]
name = "crossbeam-utils"
version = "0.8.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
dependencies = [
"cfg-if",
]
[[package]]
name = "csv"
version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "626ae34994d3d8d668f4269922248239db4ae42d538b14c398b74a52208e8086"
dependencies = [
"csv-core",
"itoa",
"ryu",
"serde",
]
[[package]]
name = "csv-core"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90"
dependencies = [
"memchr",
]
[[package]]
name = "deranged"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946"
[[package]]
name = "email-encoding"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbfb21b9878cf7a348dcb8559109aabc0ec40d69924bd706fa5149846c4fef75"
dependencies = [
"base64",
"memchr",
]
[[package]]
name = "email_address"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2153bd83ebc09db15bcbdc3e2194d901804952e3dc96967e1cd3b0c5c32d112"
[[package]]
name = "encoding_rs"
version = "0.8.33"
@ -295,6 +491,21 @@ dependencies = [
"libc",
]
[[package]]
name = "event-listener"
version = "2.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
[[package]]
name = "fastrand"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
dependencies = [
"instant",
]
[[package]]
name = "fastrand"
version = "2.0.0"
@ -352,6 +563,21 @@ version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
[[package]]
name = "futures-lite"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce"
dependencies = [
"fastrand 1.9.0",
"futures-core",
"futures-io",
"memchr",
"parking",
"pin-project-lite",
"waker-fn",
]
[[package]]
name = "futures-sink"
version = "0.3.28"
@ -385,6 +611,18 @@ version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"
[[package]]
name = "gloo-timers"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c"
dependencies = [
"futures-channel",
"futures-core",
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "h2"
version = "0.3.21"
@ -428,6 +666,17 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
[[package]]
name = "hostname"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867"
dependencies = [
"libc",
"match_cfg",
"winapi",
]
[[package]]
name = "http"
version = "0.2.9"
@ -522,6 +771,16 @@ dependencies = [
"cc",
]
[[package]]
name = "idna"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
dependencies = [
"unicode-bidi",
"unicode-normalization",
]
[[package]]
name = "idna"
version = "0.4.0"
@ -552,6 +811,26 @@ dependencies = [
"hashbrown 0.14.0",
]
[[package]]
name = "instant"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if",
]
[[package]]
name = "io-lifetimes"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
dependencies = [
"hermit-abi",
"libc",
"windows-sys",
]
[[package]]
name = "ipnet"
version = "2.8.0"
@ -573,18 +852,57 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "kv-log-macro"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f"
dependencies = [
"log",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "lettre"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76bd09637ae3ec7bd605b8e135e757980b3968430ff2b1a4a94fb7769e50166d"
dependencies = [
"async-std",
"base64",
"email-encoding",
"email_address",
"fastrand 1.9.0",
"futures-util",
"hostname",
"httpdate",
"idna 0.3.0",
"mime",
"native-tls",
"nom",
"once_cell",
"quoted_printable",
"socket2 0.4.9",
"tokio",
]
[[package]]
name = "libc"
version = "0.2.147"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
[[package]]
name = "linux-raw-sys"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
[[package]]
name = "linux-raw-sys"
version = "0.4.7"
@ -596,6 +914,15 @@ name = "log"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
dependencies = [
"value-bag",
]
[[package]]
name = "match_cfg"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
[[package]]
name = "memchr"
@ -609,6 +936,12 @@ version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
version = "0.7.1"
@ -647,6 +980,16 @@ dependencies = [
"tempfile",
]
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]]
name = "num-traits"
version = "0.2.16"
@ -734,6 +1077,12 @@ dependencies = [
"vcpkg",
]
[[package]]
name = "parking"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e"
[[package]]
name = "parse-zoneinfo"
version = "0.3.0"
@ -805,6 +1154,22 @@ version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
[[package]]
name = "polling"
version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce"
dependencies = [
"autocfg",
"bitflags 1.3.2",
"cfg-if",
"concurrent-queue",
"libc",
"log",
"pin-project-lite",
"windows-sys",
]
[[package]]
name = "proc-macro2"
version = "1.0.66"
@ -823,6 +1188,12 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "quoted_printable"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a3866219251662ec3b26fc217e3e05bf9c4f84325234dfb96bf0bf840889e49"
[[package]]
name = "rand"
version = "0.8.5"
@ -919,6 +1290,20 @@ version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]]
name = "rustix"
version = "0.37.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06"
dependencies = [
"bitflags 1.3.2",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys 0.3.8",
"windows-sys",
]
[[package]]
name = "rustix"
version = "0.38.12"
@ -928,7 +1313,7 @@ dependencies = [
"bitflags 2.4.0",
"errno",
"libc",
"linux-raw-sys",
"linux-raw-sys 0.4.7",
"windows-sys",
]
@ -1022,6 +1407,25 @@ dependencies = [
"serde",
]
[[package]]
name = "signal-hook"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
dependencies = [
"libc",
"signal-hook-registry",
]
[[package]]
name = "signal-hook-registry"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
dependencies = [
"libc",
]
[[package]]
name = "simplelog"
version = "0.12.1"
@ -1106,9 +1510,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef"
dependencies = [
"cfg-if",
"fastrand",
"fastrand 2.0.0",
"redox_syscall",
"rustix",
"rustix 0.38.12",
"windows-sys",
]
@ -1158,6 +1562,8 @@ dependencies = [
"chrono",
"chrono-tz",
"clap",
"csv",
"lettre",
"log",
"reqwest",
"serde",
@ -1193,6 +1599,7 @@ dependencies = [
"mio",
"num_cpus",
"pin-project-lite",
"signal-hook-registry",
"socket2 0.5.3",
"windows-sys",
]
@ -1315,7 +1722,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5"
dependencies = [
"form_urlencoded",
"idna",
"idna 0.4.0",
"percent-encoding",
]
@ -1325,12 +1732,24 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "value-bag"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d92ccd67fb88503048c01b59152a04effd0782d035a83a6d256ce6085f08f4a3"
[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "waker-fn"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
[[package]]
name = "want"
version = "0.3.1"

@ -37,7 +37,7 @@ rust-project TODO: write shell script for automatically updating `cargoHash`
rustSettings = with pkgs; {
src = ./.;
nativeBuildInputs = [ pkg-config ];
buildInputs = [ openssl hddtemp ];
buildInputs = [ openssl hddtemp msmtp ];
cargoHash = nixpkgs.lib.fakeHash;
};
meta = with nixpkgs.lib; {
@ -61,7 +61,7 @@ rust-project TODO: write shell script for automatically updating `cargoHash`
pname = "status_cloud";
version = "0.1.0";
buildAndTestSubdir = "status_cloud";
cargoHash = "sha256-JIiUtHqppZkOa77NRmu+e47JXwZZUluk3jPoJsAusas=";
cargoHash = "sha256-XIonh2SQ8EichcZvHErSydt0qtKGodXE0yKz4BsntA8=";
preBuild = ''
sed -i 's/Command::new("hddtemp")/Command::new("${nixpkgs.lib.escape [ "/" ] "${pkgs.hddtemp}"}")/g' status_cloud/src/main.rs
'';
@ -73,7 +73,7 @@ rust-project TODO: write shell script for automatically updating `cargoHash`
pname = "time_tracker";
version = "0.1.0";
buildAndTestSubdir = "time_tracker";
cargoHash = "sha256-b8qbOh7ATsQnswgFkbeES8VHGhs1OCYCcuyJ4m0bGMs=";
cargoHash = "sha256-5Wy2+ef2BriKmvNhllDVh/clAZGV7myDc281ygj05vI=";
meta = meta // {
description = "Using nextcloud notes to track time usage.";
};

@ -9,6 +9,8 @@ edition = "2021"
chrono = "0.4.26"
chrono-tz = "0.8.3"
clap = { version = "4.4.0", features = ["derive"] }
csv = "1.2.2"
lettre = { version = "0.10.4", features = ["sendmail-transport", "builder"] }
log = "0.4.20"
reqwest = { version = "0.11.18", features = ["blocking", "json"] }
serde = { version = "1.0.184", features = ["serde_derive"] }

@ -1,6 +1,10 @@
use chrono::{DateTime, Datelike, Utc};
use chrono_tz::US::Central;
use clap::Parser;
use lettre::{
message::{Message, header::ContentType, Attachment, MultiPart, SinglePart},
SendmailTransport, Transport,
};
use log::{debug, error};
use reqwest::blocking::Client;
use serde::{Deserialize, Serialize};
@ -41,6 +45,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
};
// --- END Loading and setup ---
let mut do_email_summary: bool = false;
// --- Get checked and unchecked ---
let primary_note = Client::new()
.get(format!(
@ -59,6 +65,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut checked: Vec<String> = vec![];
for line in primary_note_lines.iter() {
if line.starts_with("- [x] Send Summary") {
do_email_summary = true;
continue;
}
if line.starts_with("- [ ] Send Summary") {
continue;
}
// if line is a checkbox
if line.starts_with("- [") {
if line.starts_with("- [ ] ") {
@ -140,7 +153,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
body_content.push(format!(
"### {item} | {}h {}m | {}/{}/{}",
elapsed_time.num_hours(),
elapsed_time.num_minutes(),
elapsed_time.num_minutes() - elapsed_time.num_hours() * 60, // yes, I'm lazy
now.month(),
now.day(),
now.year()
@ -161,8 +174,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
})
.collect();
debug!("checked: {:#?}", checked);
debug!("unchecked: {:#?}", unchecked);
debug!("Creating new logs for: {:#?}", checked);
body_content.splice(2..2, checked);
@ -181,6 +193,12 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
})?)
.send()?;
if do_email_summary {
debug!("Send email selected");
reset_email_checkbox(&cfg);
send_email_summary(&cfg, body_content);
}
Ok(())
}
@ -205,6 +223,7 @@ struct NoteUpdate {
struct Config {
user: String,
pswd: String,
email_addr: String,
primary_note_id: String,
logging_note_id: String,
server_url: String,
@ -220,3 +239,149 @@ struct CliArgs {
#[arg(short, long)]
debug: bool,
}
// All unwraps are unrecoverable errors
// All calls after depend on the success of the one before, and cannot run
// without. So it would be too much work to make an error type to handle an error
// that would cause a crash anyways
fn reset_email_checkbox(config: &Config) {
let primary_note = Client::new()
.get(format!(
"https://{}/index.php/apps/notes/api/v1/notes/{}",
&config.server_url, &config.primary_note_id
))
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.basic_auth(&config.user, Some(&config.pswd))
.send()
.unwrap()
.json::<Note>()
.unwrap();
let primary_note_lines: Vec<&str> = primary_note.content.lines().collect();
let mut body_content: Vec<&str> = vec![];
for line in primary_note_lines.iter() {
if line.starts_with("- [x] Send Summary") {
body_content.push("- [ ] Send Summary");
} else {
body_content.push(line);
}
}
Client::new()
.put(format!(
"https://{}/index.php/apps/notes/api/v1/notes/{}",
&config.server_url, &config.primary_note_id
))
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.basic_auth(&config.user, Some(&config.pswd))
.body(
serde_json::to_string(&NoteUpdate {
content: body_content.join("\n"),
})
.unwrap(),
)
.send()
.unwrap();
}
#[derive(Serialize, Deserialize, Debug)]
struct SummaryRow {
date: String,
total_time: i64,
task_name: String,
}
// All unwraps are unrecoverable errors
// All calls after depend on the success of the one before, and cannot run
// without. So it would be too much work to make an error type to handle an error
// that would cause a crash anyways
fn send_email_summary(config: &Config, body_content: Vec<String>) {
let mut wtr = csv::Writer::from_writer(vec![]);
for line in body_content {
if line.starts_with("### ") {
let mut split: Vec<&str> = line.split('|').collect();
if split.len() != 3 {
error!("There was an issue with this line: {line}");
continue;
}
let date: String = match split.pop() {
Some(val) => val,
None => continue,
}
.to_string();
let time: i64 = {
// This should never error as the len should always be 3
let data = match split.pop() {
Some(val) => val,
None => continue,
}
.trim();
// There should always be an h and an m in the second item
let h_index = match data.chars().position(|c| c == 'h') {
Some(val) => val,
None => continue,
};
let m_index = match data.chars().position(|c| c == 'm') {
Some(val) => val,
None => continue,
};
// this should always be the "10" in "10h"
let hours = match data[0..h_index].parse::<i64>() {
Ok(val) => val,
Err(_) => continue,
};
// this should always be the "20" in "10h 20m"
let minutes = match data[(h_index + 2)..m_index].parse::<i64>() {
Ok(val) => val,
Err(_) => continue,
};
hours * 60 + minutes
};
let task_name: String = match split.pop() {
Some(val) => val.trim(),
None => continue,
}
.to_string()
.replace("### ", "");
wtr.serialize(SummaryRow { date: date.trim().to_string(), total_time: time, task_name }).unwrap();
}
}
let data = String::from_utf8(wtr.into_inner().unwrap()).unwrap();
debug!("{:#?}", data);
let attachment = Attachment::new("TimeSummary.csv".to_string()).body(data, ContentType::parse("text/csv").unwrap());
let email = Message::builder()
.from("NoReplay <noreply@nickiel.net>".parse().unwrap())
.to("Nicholas Young <nicholasyoungsumner@gmail.com>".parse().unwrap())
.subject("Testing email")
.header(ContentType::TEXT_PLAIN)
.multipart(
MultiPart::mixed()
.singlepart(SinglePart::plain("Hello World".to_string()))
.singlepart(attachment)
).unwrap();
let mailer = SendmailTransport::new();
match mailer.send(&email) {
Ok(val) => debug!("email sent: {:?}", val),
Err(e) => error!("Couldn't send email {}", e)
};
}

Loading…
Cancel
Save