diff --git a/.gitignore b/.gitignore index 03a17e2..7ed0de4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ # SPDX-FileCopyrightText: 2022 Matteo Settenvini # SPDX-License-Identifier: CC0-1.0 +.~*# /target diff --git a/Cargo.lock b/Cargo.lock index 3a34c7b..2a83d89 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "anyhow" version = "1.0.58" @@ -93,6 +99,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "chunked_transfer" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fff857943da45f546682664a79488be82e69e43c1a7a2307679ab9afb3a66d2e" + [[package]] name = "ci_info" version = "0.10.2" @@ -149,6 +161,7 @@ dependencies = [ "directories", "futures", "ics", + "minicaldav", "reqwest", "rusty-hook", "serde", @@ -177,6 +190,15 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + [[package]] name = "csv" version = "1.1.6" @@ -282,6 +304,16 @@ dependencies = [ "instant", ] +[[package]] +name = "flate2" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "fnv" version = "1.0.7" @@ -667,6 +699,28 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +[[package]] +name = "minicaldav" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb263a7d12c40d5f200dda93b3665b9ae714d4fe64a6467938c92d974a579edb" +dependencies = [ + "base64", + "log", + "ureq", + "url", + "xmltree", +] + +[[package]] +name = "miniz_oxide" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" +dependencies = [ + "adler", +] + [[package]] name = "mio" version = "0.8.4" @@ -1026,6 +1080,33 @@ dependencies = [ "winreg", ] +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "rustls" +version = "0.20.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aab8ee6c7097ed6057f43c187a62418d0c05a4bd5f18b3571db50ee0f9ce033" +dependencies = [ + "log", + "ring", + "sct", + "webpki", +] + [[package]] name = "rustversion" version = "1.0.8" @@ -1069,6 +1150,16 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "security-framework" version = "2.6.1" @@ -1161,6 +1252,12 @@ dependencies = [ "strum_macros", ] +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + [[package]] name = "strsim" version = "0.10.0" @@ -1396,6 +1493,30 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "ureq" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97acb4c28a254fd7a4aeec976c46a7fa404eac4d7c134b30c75144846d7cb8f" +dependencies = [ + "base64", + "chunked_transfer", + "encoding_rs", + "flate2", + "log", + "once_cell", + "rustls", + "url", + "webpki", + "webpki-roots", +] + [[package]] name = "url" version = "2.2.2" @@ -1547,6 +1668,25 @@ dependencies = [ "winapi", ] +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "webpki-roots" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1c760f0d366a6c24a02ed7816e23e691f5d92291f94d15e836006fd11b04daf" +dependencies = [ + "webpki", +] + [[package]] name = "widestring" version = "0.5.1" @@ -1635,3 +1775,18 @@ checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" dependencies = [ "winapi", ] + +[[package]] +name = "xml-rs" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" + +[[package]] +name = "xmltree" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7d8a75eaf6557bb84a65ace8609883db44a29951042ada9b393151532e41fcb" +dependencies = [ + "xml-rs", +] diff --git a/Cargo.toml b/Cargo.toml index a6e6247..9ac7e8c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,6 +42,9 @@ version = "0.3" [dependencies.ics] version = "0.5" +[dependencies.minicaldav] +version = "0.2" + [dependencies.reqwest] version = "0.11" features = ["json", "blocking"] diff --git a/examples/example-schedule.csv b/examples/example-schedule.csv index 838e9b9..72261c7 100644 --- a/examples/example-schedule.csv +++ b/examples/example-schedule.csv @@ -1,366 +1,366 @@ "day","lunch","dinner" -2022-08-01,"https://ricette.giallozafferano.it/Pasta-fredda-con-pesto-senz-aglio.html","https://ricette.giallozafferano.it/Riso-freddo-con-tonno-zucchine-e-limone.html" -2022-08-02,, -2022-08-03,, -2022-08-04,, -2022-08-05,, -2022-08-06,, -2022-08-07,, -2022-08-08,, -2022-08-09,, -2022-08-10,, -2022-08-11,, -2022-08-12,, -2022-08-13,, -2022-08-14,, -2022-08-15,, -2022-08-16,, -2022-08-17,, -2022-08-18,, -2022-08-19,, -2022-08-20,, -2022-08-21,, -2022-08-22,, -2022-08-23,, -2022-08-24,, -2022-08-25,, -2022-08-26,, -2022-08-27,, -2022-08-28,, -2022-08-29,, -2022-08-30,, -2022-08-31,, -2022-09-01,, -2022-09-02,, -2022-09-03,, -2022-09-04,, -2022-09-05,, -2022-09-06,, -2022-09-07,, -2022-09-08,, -2022-09-09,, -2022-09-10,, -2022-09-11,, -2022-09-12,, -2022-09-13,, -2022-09-14,, -2022-09-15,, -2022-09-16,, -2022-09-17,, -2022-09-18,, -2022-09-19,, -2022-09-20,, -2022-09-21,, -2022-09-22,, -2022-09-23,, -2022-09-24,, -2022-09-25,, -2022-09-26,, -2022-09-27,, -2022-09-28,, -2022-09-29,, -2022-09-30,, -2022-10-01,, -2022-10-02,, -2022-10-03,, -2022-10-04,, -2022-10-05,, -2022-10-06,, -2022-10-07,, -2022-10-08,, -2022-10-09,, -2022-10-10,, -2022-10-11,, -2022-10-12,, -2022-10-13,, -2022-10-14,, -2022-10-15,, -2022-10-16,, -2022-10-17,, -2022-10-18,, -2022-10-19,, -2022-10-20,, -2022-10-21,, -2022-10-22,, -2022-10-23,, -2022-10-24,, -2022-10-25,, -2022-10-26,, -2022-10-27,, -2022-10-28,, -2022-10-29,, -2022-10-30,, -2022-10-31,, -2022-11-01,, -2022-11-02,, -2022-11-03,, -2022-11-04,, -2022-11-05,, -2022-11-06,, -2022-11-07,, -2022-11-08,, -2022-11-09,, -2022-11-10,, -2022-11-11,, -2022-11-12,, -2022-11-13,, -2022-11-14,, -2022-11-15,, -2022-11-16,, -2022-11-17,, -2022-11-18,, -2022-11-19,, -2022-11-20,, -2022-11-21,, -2022-11-22,, -2022-11-23,, -2022-11-24,, -2022-11-25,, -2022-11-26,, -2022-11-27,, -2022-11-28,, -2022-11-29,, -2022-11-30,, -2022-12-01,, -2022-12-02,, -2022-12-03,, -2022-12-04,, -2022-12-05,, -2022-12-06,, -2022-12-07,, -2022-12-08,, -2022-12-09,, -2022-12-10,, -2022-12-11,, -2022-12-12,, -2022-12-13,, -2022-12-14,, -2022-12-15,, -2022-12-16,, -2022-12-17,, -2022-12-18,, -2022-12-19,, -2022-12-20,, -2022-12-21,, -2022-12-22,, -2022-12-23,, -2022-12-24,, -2022-12-25,, -2022-12-26,, -2022-12-27,, -2022-12-28,, -2022-12-29,, -2022-12-30,, -2022-12-31,, -2023-01-01,, -2023-01-02,, -2023-01-03,, -2023-01-04,, -2023-01-05,, -2023-01-06,, -2023-01-07,, -2023-01-08,, -2023-01-09,, -2023-01-10,, -2023-01-11,, -2023-01-12,, -2023-01-13,, -2023-01-14,, -2023-01-15,, -2023-01-16,, -2023-01-17,, -2023-01-18,, -2023-01-19,, -2023-01-20,, -2023-01-21,, -2023-01-22,, -2023-01-23,, -2023-01-24,, -2023-01-25,, -2023-01-26,, -2023-01-27,, -2023-01-28,, -2023-01-29,, -2023-01-30,, -2023-01-31,, -2023-02-01,, -2023-02-02,, -2023-02-03,, -2023-02-04,, -2023-02-05,, -2023-02-06,, -2023-02-07,, -2023-02-08,, -2023-02-09,, -2023-02-10,, -2023-02-11,, -2023-02-12,, -2023-02-13,, -2023-02-14,, -2023-02-15,, -2023-02-16,, -2023-02-17,, -2023-02-18,, -2023-02-19,, -2023-02-20,, -2023-02-21,, -2023-02-22,, -2023-02-23,, -2023-02-24,, -2023-02-25,, -2023-02-26,, -2023-02-27,, -2023-02-28,, -2023-03-01,, -2023-03-02,, -2023-03-03,, -2023-03-04,, -2023-03-05,, -2023-03-06,, -2023-03-07,, -2023-03-08,, -2023-03-09,, -2023-03-10,, -2023-03-11,, -2023-03-12,, -2023-03-13,, -2023-03-14,, -2023-03-15,, -2023-03-16,, -2023-03-17,, -2023-03-18,, -2023-03-19,, -2023-03-20,, -2023-03-21,, -2023-03-22,, -2023-03-23,, -2023-03-24,, -2023-03-25,, -2023-03-26,, -2023-03-27,, -2023-03-28,, -2023-03-29,, -2023-03-30,, -2023-03-31,, -2023-04-01,, -2023-04-02,, -2023-04-03,, -2023-04-04,, -2023-04-05,, -2023-04-06,, -2023-04-07,, -2023-04-08,, -2023-04-09,, -2023-04-10,, -2023-04-11,, -2023-04-12,, -2023-04-13,, -2023-04-14,, -2023-04-15,, -2023-04-16,, -2023-04-17,, -2023-04-18,, -2023-04-19,, -2023-04-20,, -2023-04-21,, -2023-04-22,, -2023-04-23,, -2023-04-24,, -2023-04-25,, -2023-04-26,, -2023-04-27,, -2023-04-28,, -2023-04-29,, -2023-04-30,, -2023-05-01,, -2023-05-02,, -2023-05-03,, -2023-05-04,, -2023-05-05,, -2023-05-06,, -2023-05-07,, -2023-05-08,, -2023-05-09,, -2023-05-10,, -2023-05-11,, -2023-05-12,, -2023-05-13,, -2023-05-14,, -2023-05-15,, -2023-05-16,, -2023-05-17,, -2023-05-18,, -2023-05-19,, -2023-05-20,, -2023-05-21,, -2023-05-22,, -2023-05-23,, -2023-05-24,, -2023-05-25,, -2023-05-26,, -2023-05-27,, -2023-05-28,, -2023-05-29,, -2023-05-30,, -2023-05-31,, -2023-06-01,, -2023-06-02,, -2023-06-03,, -2023-06-04,, -2023-06-05,, -2023-06-06,, -2023-06-07,, -2023-06-08,, -2023-06-09,, -2023-06-10,, -2023-06-11,, -2023-06-12,, -2023-06-13,, -2023-06-14,, -2023-06-15,, -2023-06-16,, -2023-06-17,, -2023-06-18,, -2023-06-19,, -2023-06-20,, -2023-06-21,, -2023-06-22,, -2023-06-23,, -2023-06-24,, -2023-06-25,, -2023-06-26,, -2023-06-27,, -2023-06-28,, -2023-06-29,, -2023-06-30,, -2023-07-01,, -2023-07-02,, -2023-07-03,, -2023-07-04,, -2023-07-05,, -2023-07-06,, -2023-07-07,, -2023-07-08,, -2023-07-09,, -2023-07-10,, -2023-07-11,, -2023-07-12,, -2023-07-13,, -2023-07-14,, -2023-07-15,, -2023-07-16,, -2023-07-17,, -2023-07-18,, -2023-07-19,, -2023-07-20,, -2023-07-21,, -2023-07-22,, -2023-07-23,, -2023-07-24,, -2023-07-25,, -2023-07-26,, -2023-07-27,, -2023-07-28,, -2023-07-29,, -2023-07-30,, -2023-07-31,, +"2022-08-01","https://ricette.giallozafferano.it/Pasta-fredda-con-pesto-senz-aglio.html","https://ricette.giallozafferano.it/Riso-freddo-con-tonno-zucchine-e-limone.html" +"2022-08-02",, +"2022-08-03",, +"2022-08-04",, +"2022-08-05",, +"2022-08-06",, +"2022-08-07",, +"2022-08-08",, +"2022-08-09",, +"2022-08-10",, +"2022-08-11",, +"2022-08-12",, +"2022-08-13",, +"2022-08-14",, +"2022-08-15",, +"2022-08-16",, +"2022-08-17",, +"2022-08-18",, +"2022-08-19",, +"2022-08-20",, +"2022-08-21",, +"2022-08-22",, +"2022-08-23",, +"2022-08-24",, +"2022-08-25",, +"2022-08-26",, +"2022-08-27",, +"2022-08-28",, +"2022-08-29",, +"2022-08-30",, +"2022-08-31",, +"2022-09-01",, +"2022-09-02",, +"2022-09-03",, +"2022-09-04",, +"2022-09-05",, +"2022-09-06",, +"2022-09-07",, +"2022-09-08",, +"2022-09-09",, +"2022-09-10",, +"2022-09-11",, +"2022-09-12",, +"2022-09-13",, +"2022-09-14",, +"2022-09-15",, +"2022-09-16",, +"2022-09-17",, +"2022-09-18",, +"2022-09-19",, +"2022-09-20",, +"2022-09-21",, +"2022-09-22",, +"2022-09-23",, +"2022-09-24",, +"2022-09-25",, +"2022-09-26",, +"2022-09-27",, +"2022-09-28",, +"2022-09-29",, +"2022-09-30",, +"2022-10-01",, +"2022-10-02",, +"2022-10-03",, +"2022-10-04",, +"2022-10-05",, +"2022-10-06",, +"2022-10-07",, +"2022-10-08",, +"2022-10-09",, +"2022-10-10",, +"2022-10-11",, +"2022-10-12",, +"2022-10-13",, +"2022-10-14",, +"2022-10-15",, +"2022-10-16",, +"2022-10-17",, +"2022-10-18",, +"2022-10-19",, +"2022-10-20",, +"2022-10-21",, +"2022-10-22",, +"2022-10-23",, +"2022-10-24",, +"2022-10-25",, +"2022-10-26",, +"2022-10-27",, +"2022-10-28",, +"2022-10-29",, +"2022-10-30",, +"2022-10-31",, +"2022-11-01",, +"2022-11-02",, +"2022-11-03",, +"2022-11-04",, +"2022-11-05",, +"2022-11-06",, +"2022-11-07",, +"2022-11-08",, +"2022-11-09",, +"2022-11-10",, +"2022-11-11",, +"2022-11-12",, +"2022-11-13",, +"2022-11-14",, +"2022-11-15",, +"2022-11-16",, +"2022-11-17",, +"2022-11-18",, +"2022-11-19",, +"2022-11-20",, +"2022-11-21",, +"2022-11-22",, +"2022-11-23",, +"2022-11-24",, +"2022-11-25",, +"2022-11-26",, +"2022-11-27",, +"2022-11-28",, +"2022-11-29",, +"2022-11-30",, +"2022-12-01",, +"2022-12-02",, +"2022-12-03",, +"2022-12-04",, +"2022-12-05",, +"2022-12-06",, +"2022-12-07",, +"2022-12-08",, +"2022-12-09",, +"2022-12-10",, +"2022-12-11",, +"2022-12-12",, +"2022-12-13",, +"2022-12-14",, +"2022-12-15",, +"2022-12-16",, +"2022-12-17",, +"2022-12-18",, +"2022-12-19",, +"2022-12-20",, +"2022-12-21",, +"2022-12-22",, +"2022-12-23",, +"2022-12-24",, +"2022-12-25",, +"2022-12-26",, +"2022-12-27",, +"2022-12-28",, +"2022-12-29",, +"2022-12-30",, +"2022-12-31",, +"2023-01-01",, +"2023-01-02",, +"2023-01-03",, +"2023-01-04",, +"2023-01-05",, +"2023-01-06",, +"2023-01-07",, +"2023-01-08",, +"2023-01-09",, +"2023-01-10",, +"2023-01-11",, +"2023-01-12",, +"2023-01-13",, +"2023-01-14",, +"2023-01-15",, +"2023-01-16",, +"2023-01-17",, +"2023-01-18",, +"2023-01-19",, +"2023-01-20",, +"2023-01-21",, +"2023-01-22",, +"2023-01-23",, +"2023-01-24",, +"2023-01-25",, +"2023-01-26",, +"2023-01-27",, +"2023-01-28",, +"2023-01-29",, +"2023-01-30",, +"2023-01-31",, +"2023-02-01",, +"2023-02-02",, +"2023-02-03",, +"2023-02-04",, +"2023-02-05",, +"2023-02-06",, +"2023-02-07",, +"2023-02-08",, +"2023-02-09",, +"2023-02-10",, +"2023-02-11",, +"2023-02-12",, +"2023-02-13",, +"2023-02-14",, +"2023-02-15",, +"2023-02-16",, +"2023-02-17",, +"2023-02-18",, +"2023-02-19",, +"2023-02-20",, +"2023-02-21",, +"2023-02-22",, +"2023-02-23",, +"2023-02-24",, +"2023-02-25",, +"2023-02-26",, +"2023-02-27",, +"2023-02-28",, +"2023-03-01",, +"2023-03-02",, +"2023-03-03",, +"2023-03-04",, +"2023-03-05",, +"2023-03-06",, +"2023-03-07",, +"2023-03-08",, +"2023-03-09",, +"2023-03-10",, +"2023-03-11",, +"2023-03-12",, +"2023-03-13",, +"2023-03-14",, +"2023-03-15",, +"2023-03-16",, +"2023-03-17",, +"2023-03-18",, +"2023-03-19",, +"2023-03-20",, +"2023-03-21",, +"2023-03-22",, +"2023-03-23",, +"2023-03-24",, +"2023-03-25",, +"2023-03-26",, +"2023-03-27",, +"2023-03-28",, +"2023-03-29",, +"2023-03-30",, +"2023-03-31",, +"2023-04-01",, +"2023-04-02",, +"2023-04-03",, +"2023-04-04",, +"2023-04-05",, +"2023-04-06",, +"2023-04-07",, +"2023-04-08",, +"2023-04-09",, +"2023-04-10",, +"2023-04-11",, +"2023-04-12",, +"2023-04-13",, +"2023-04-14",, +"2023-04-15",, +"2023-04-16",, +"2023-04-17",, +"2023-04-18",, +"2023-04-19",, +"2023-04-20",, +"2023-04-21",, +"2023-04-22",, +"2023-04-23",, +"2023-04-24",, +"2023-04-25",, +"2023-04-26",, +"2023-04-27",, +"2023-04-28",, +"2023-04-29",, +"2023-04-30",, +"2023-05-01",, +"2023-05-02",, +"2023-05-03",, +"2023-05-04",, +"2023-05-05",, +"2023-05-06",, +"2023-05-07",, +"2023-05-08",, +"2023-05-09",, +"2023-05-10",, +"2023-05-11",, +"2023-05-12",, +"2023-05-13",, +"2023-05-14",, +"2023-05-15",, +"2023-05-16",, +"2023-05-17",, +"2023-05-18",, +"2023-05-19",, +"2023-05-20",, +"2023-05-21",, +"2023-05-22",, +"2023-05-23",, +"2023-05-24",, +"2023-05-25",, +"2023-05-26",, +"2023-05-27",, +"2023-05-28",, +"2023-05-29",, +"2023-05-30",, +"2023-05-31",, +"2023-06-01",, +"2023-06-02",, +"2023-06-03",, +"2023-06-04",, +"2023-06-05",, +"2023-06-06",, +"2023-06-07",, +"2023-06-08",, +"2023-06-09",, +"2023-06-10",, +"2023-06-11",, +"2023-06-12",, +"2023-06-13",, +"2023-06-14",, +"2023-06-15",, +"2023-06-16",, +"2023-06-17",, +"2023-06-18",, +"2023-06-19",, +"2023-06-20",, +"2023-06-21",, +"2023-06-22",, +"2023-06-23",, +"2023-06-24",, +"2023-06-25",, +"2023-06-26",, +"2023-06-27",, +"2023-06-28",, +"2023-06-29",, +"2023-06-30",, +"2023-07-01",, +"2023-07-02",, +"2023-07-03",, +"2023-07-04",, +"2023-07-05",, +"2023-07-06",, +"2023-07-07",, +"2023-07-08",, +"2023-07-09",, +"2023-07-10",, +"2023-07-11",, +"2023-07-12",, +"2023-07-13",, +"2023-07-14",, +"2023-07-15",, +"2023-07-16",, +"2023-07-17",, +"2023-07-18",, +"2023-07-19",, +"2023-07-20",, +"2023-07-21",, +"2023-07-22",, +"2023-07-23",, +"2023-07-24",, +"2023-07-25",, +"2023-07-26",, +"2023-07-27",, +"2023-07-28",, +"2023-07-29",, +"2023-07-30",, +"2023-07-31",, \ No newline at end of file diff --git a/src/commands/schedule_csv.rs b/src/commands/schedule_csv.rs index 50615d3..4fa0c44 100644 --- a/src/commands/schedule_csv.rs +++ b/src/commands/schedule_csv.rs @@ -5,18 +5,17 @@ use { crate::api_client::ApiClient, crate::commands::import, crate::constants, + crate::event::{Event, Meal}, crate::recipe, anyhow::{bail, Result}, - chrono::naive::{NaiveDate, NaiveDateTime, NaiveTime}, - chrono::{DateTime, Local, TimeZone}, + chrono::naive::NaiveDate, futures::future::try_join_all, - ics::properties as calprop, - ics::Event, reqwest::StatusCode, std::collections::{HashMap, HashSet}, std::fmt::Write, std::iter::Iterator, std::path::Path, + std::rc::Rc, }; #[derive(serde::Deserialize)] @@ -26,12 +25,6 @@ struct CsvRecord { dinner: String, } -#[derive(strum_macros::Display)] -enum Meal { - Lunch, - Dinner, -} - pub async fn with(api_client: &ApiClient, calendar: &str, csv_file: &Path) -> Result<()> { let mut csv = csv::Reader::from_path(csv_file)?; let records = csv.deserialize::().flatten().collect::>(); @@ -47,8 +40,8 @@ pub async fn with(api_client: &ApiClient, calendar: &str, csv_file: &Path) -> Re let dinner = recipes.get(&r.dinner); let events = [ - lunch.map(|recipe| to_event(r.day, Meal::Lunch, recipe)), - dinner.map(|recipe| to_event(r.day, Meal::Dinner, recipe)), + lunch.map(|recipe| Event::new(r.day, Meal::Lunch, recipe.clone())), + dinner.map(|recipe| Event::new(r.day, Meal::Dinner, recipe.clone())), ]; events @@ -59,46 +52,6 @@ pub async fn with(api_client: &ApiClient, calendar: &str, csv_file: &Path) -> Re Ok(()) } -fn to_event(date: NaiveDate, meal: Meal, recipe: &recipe::Recipe) -> (String, Event) { - // TODO: this is momentarily hardcoded, should be an option - let meal_time = match meal { - Meal::Lunch => NaiveTime::from_hms(12, 00, 00), - Meal::Dinner => NaiveTime::from_hms(19, 00, 00), - }; - - let uid = format!( - "{}-{}@{}.montecristosoftware.eu", - date, - meal, - env!("CARGO_PKG_NAME") - ); - - let end_time = NaiveDateTime::new(date, meal_time); - let start_time = end_time - recipe.total_time(); - - let mut event = Event::new(uid.clone(), dt_fmt(&Local::now())); - event.push(calprop::Summary::new(&recipe.name)); - event.push(calprop::Description::new(format!("cookbook@{}", recipe.id))); - event.push(calprop::Location::new(&recipe.url)); - event.push(calprop::DtStart::new(dt_fmt( - &Local.from_local_datetime(&start_time).unwrap(), - ))); - event.push(calprop::DtEnd::new(dt_fmt( - &Local.from_local_datetime(&end_time).unwrap(), - ))); - - // TODO make configurable yearly repetition, for now this suits my personal uses - event.push(calprop::RRule::new("FREQ=YEARLY")); - - let alarm = ics::Alarm::display( - calprop::Trigger::new("-P15M"), - calprop::Description::new(&recipe.name), - ); - event.add_alarm(alarm); - - (uid, event) -} - fn urls_from_csv<'a, RecordsIter>(records: RecordsIter) -> Result> where RecordsIter: Iterator, @@ -116,11 +69,7 @@ where ) } -fn dt_fmt(datetime: &DateTime) -> String { - datetime.format("%Y%m%dT%H%M%S").to_string() -} - -async fn get_all_recipes(api_client: &ApiClient) -> Result> { +async fn get_all_recipes(api_client: &ApiClient) -> Result>> { let metadata = api_client .rest .get(api_client.base_url.join("apps/cookbook/api/recipes")?) @@ -144,7 +93,7 @@ async fn get_all_recipes(api_client: &ApiClient) -> Result().await + response.json::().await.map(|r| Rc::new(r)) }); let recipes = try_join_all(recipes).await?; @@ -159,7 +108,7 @@ async fn publish_events<'a, EventsIter>( events: EventsIter, ) -> Result<()> where - EventsIter: Iterator)>, + EventsIter: Iterator, { let calendar_prototype: ics::ICalendar = ics::ICalendar::new( "2.0", @@ -184,11 +133,11 @@ where let calendar_prototype = &calendar_prototype; let calendar_url = &calendar_url; - let update_requests = events.map(|(event_id, event)| async move { + let update_requests = events.map(|ev| async move { + let url = calendar_url.join(&format!("{}.ics", ev.uid)).unwrap(); let mut cal = calendar_prototype.clone(); - cal.add_event(event); + cal.add_event(ev.into()); - let url = calendar_url.join(&format!("{}.ics", event_id)).unwrap(); api_client .rest .put(url) diff --git a/src/event.rs b/src/event.rs new file mode 100644 index 0000000..e79a379 --- /dev/null +++ b/src/event.rs @@ -0,0 +1,80 @@ +// SPDX-FileCopyrightText: 2022 Matteo Settenvini +// SPDX-License-Identifier: AGPL-3.0-or-later + +use { + crate::recipe::Recipe, + chrono::{DateTime, Local, NaiveDate, NaiveDateTime, NaiveTime, TimeZone}, + ics::properties as calprop, + ics::Event as CalEvent, + std::rc::Rc, +}; + +pub struct Event { + pub uid: String, + pub ends_at: NaiveDateTime, + pub recipe: Rc, +} + +#[derive(strum_macros::Display)] +pub enum Meal { + Lunch, + Dinner, +} + +impl Event { + pub fn new(date: NaiveDate, meal: Meal, recipe: Rc) -> Self { + let uid = format!( + "{}-{}@{}.montecristosoftware.eu", + date, + meal, + env!("CARGO_PKG_NAME") + ); + + let meal_time = match meal { + Meal::Lunch => NaiveTime::from_hms(12, 00, 00), + Meal::Dinner => NaiveTime::from_hms(19, 00, 00), + }; + + let ends_at = NaiveDateTime::new(date, meal_time); + + Event { + uid, + ends_at, + recipe, + } + } +} + +impl<'a> From for CalEvent<'a> { + fn from(ev: Event) -> Self { + let start_time = ev.ends_at - ev.recipe.total_time(); + + let mut event = ics::Event::new(ev.uid.clone(), dt_fmt(&Local::now())); + event.push(calprop::Summary::new(ev.recipe.name.clone())); + event.push(calprop::Description::new(format!( + "cookbook@{}", + ev.recipe.id + ))); + event.push(calprop::Location::new(ev.recipe.url.clone())); + event.push(calprop::DtStart::new(dt_fmt( + &Local.from_local_datetime(&start_time).unwrap(), + ))); + event.push(calprop::DtEnd::new(dt_fmt( + &Local.from_local_datetime(&ev.ends_at).unwrap(), + ))); + + // TODO make configurable yearly repetition, for now this suits my personal uses + event.push(calprop::RRule::new("FREQ=YEARLY")); + + let alarm = ics::Alarm::display( + calprop::Trigger::new("-P15M"), + calprop::Description::new(ev.recipe.name.clone()), + ); + event.add_alarm(alarm); + event + } +} + +fn dt_fmt(datetime: &DateTime) -> String { + datetime.format("%Y%m%dT%H%M%S").to_string() +} diff --git a/src/main.rs b/src/main.rs index 3fb9c3d..69aa993 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,7 @@ mod api_client; mod commands; mod config; mod constants; +mod event; mod recipe; use {