From 5f0f9999fcd89d99c16673f9ad7ac219db1eb724 Mon Sep 17 00:00:00 2001 From: Joeri Exelmans Date: Tue, 23 Sep 2025 11:53:22 +0200 Subject: [PATCH] initial commit --- .devenv.flake.nix | 163 ++++ .devenv/devenv.json | 1 + .devenv/flake.json | 1 + .devenv/imports.txt | 0 .devenv/nix-eval-cache.db | Bin 0 -> 4096 bytes .devenv/nix-eval-cache.db-shm | Bin 0 -> 32768 bytes .devenv/nix-eval-cache.db-wal | Bin 0 -> 197792 bytes .gitignore | 1 + Cargo.lock | 1559 +++++++++++++++++++++++++++++++++ Cargo.toml | 9 + flake.lock | 27 + flake.nix | 26 + src/main.rs | 67 ++ 13 files changed, 1854 insertions(+) create mode 100644 .devenv.flake.nix create mode 100644 .devenv/devenv.json create mode 100644 .devenv/flake.json create mode 100644 .devenv/imports.txt create mode 100644 .devenv/nix-eval-cache.db create mode 100644 .devenv/nix-eval-cache.db-shm create mode 100644 .devenv/nix-eval-cache.db-wal create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 src/main.rs diff --git a/.devenv.flake.nix b/.devenv.flake.nix new file mode 100644 index 0000000..305e471 --- /dev/null +++ b/.devenv.flake.nix @@ -0,0 +1,163 @@ +{ + inputs = + let + version = "1.6.1"; +system = "x86_64-linux"; +devenv_root = "/home/maestro/repos/icomidal"; +devenv_dotfile = ./.devenv; +devenv_dotfile_string = ".devenv"; +container_name = null; +devenv_tmpdir = "/run/user/1000"; +devenv_runtime = "/run/user/1000/devenv-091177c"; +devenv_istesting = false; +devenv_direnvrc_latest_version = 1; + + in { + git-hooks.url = "github:cachix/git-hooks.nix"; + git-hooks.inputs.nixpkgs.follows = "nixpkgs"; + pre-commit-hooks.follows = "git-hooks"; + nixpkgs.url = "github:cachix/devenv-nixpkgs/rolling"; + devenv.url = "github:cachix/devenv?dir=src/modules"; + } // (if builtins.pathExists (devenv_dotfile + "/flake.json") + then builtins.fromJSON (builtins.readFile (devenv_dotfile + "/flake.json")) + else { }); + + outputs = { nixpkgs, ... }@inputs: + let + version = "1.6.1"; +system = "x86_64-linux"; +devenv_root = "/home/maestro/repos/icomidal"; +devenv_dotfile = ./.devenv; +devenv_dotfile_string = ".devenv"; +container_name = null; +devenv_tmpdir = "/run/user/1000"; +devenv_runtime = "/run/user/1000/devenv-091177c"; +devenv_istesting = false; +devenv_direnvrc_latest_version = 1; + + devenv = + if builtins.pathExists (devenv_dotfile + "/devenv.json") + then builtins.fromJSON (builtins.readFile (devenv_dotfile + "/devenv.json")) + else { }; + getOverlays = inputName: inputAttrs: + map + (overlay: + let + input = inputs.${inputName} or (throw "No such input `${inputName}` while trying to configure overlays."); + in + input.overlays.${overlay} or (throw "Input `${inputName}` has no overlay called `${overlay}`. Supported overlays: ${nixpkgs.lib.concatStringsSep ", " (builtins.attrNames input.overlays)}")) + inputAttrs.overlays or [ ]; + overlays = nixpkgs.lib.flatten (nixpkgs.lib.mapAttrsToList getOverlays (devenv.inputs or { })); + pkgs = import nixpkgs { + inherit system; + config = { + allowUnfree = devenv.allowUnfree or false; + allowBroken = devenv.allowBroken or false; + permittedInsecurePackages = devenv.permittedInsecurePackages or [ ]; + }; + inherit overlays; + }; + lib = pkgs.lib; + importModule = path: + if lib.hasPrefix "./" path + then if lib.hasSuffix ".nix" path + then ./. + (builtins.substring 1 255 path) + else ./. + (builtins.substring 1 255 path) + "/devenv.nix" + else if lib.hasPrefix "../" path + then throw "devenv: ../ is not supported for imports" + else + let + paths = lib.splitString "/" path; + name = builtins.head paths; + input = inputs.${name} or (throw "Unknown input ${name}"); + subpath = "/${lib.concatStringsSep "/" (builtins.tail paths)}"; + devenvpath = "${input}" + subpath; + devenvdefaultpath = devenvpath + "/devenv.nix"; + in + if lib.hasSuffix ".nix" devenvpath + then devenvpath + else if builtins.pathExists devenvdefaultpath + then devenvdefaultpath + else throw (devenvdefaultpath + " file does not exist for input ${name}."); + project = pkgs.lib.evalModules { + specialArgs = inputs // { inherit inputs; }; + modules = [ + ({ config, ... }: { + _module.args.pkgs = pkgs.appendOverlays (config.overlays or [ ]); + }) + (inputs.devenv.modules + /top-level.nix) + { + devenv.cliVersion = version; + devenv.root = devenv_root; + devenv.dotfile = devenv_root + "/" + devenv_dotfile_string; + } + (pkgs.lib.optionalAttrs (inputs.devenv.isTmpDir or false) { + devenv.tmpdir = devenv_tmpdir; + devenv.runtime = devenv_runtime; + }) + (pkgs.lib.optionalAttrs (inputs.devenv.hasIsTesting or false) { + devenv.isTesting = devenv_istesting; + }) + (pkgs.lib.optionalAttrs (container_name != null) { + container.isBuilding = pkgs.lib.mkForce true; + containers.${container_name}.isBuilding = true; + }) + ({ options, ... }: { + config.devenv = pkgs.lib.optionalAttrs (builtins.hasAttr "direnvrcLatestVersion" options.devenv) { + direnvrcLatestVersion = devenv_direnvrc_latest_version; + }; + }) + ] ++ (map importModule (devenv.imports or [ ])) ++ [ + (if builtins.pathExists ./devenv.nix then ./devenv.nix else { }) + (devenv.devenv or { }) + (if builtins.pathExists ./devenv.local.nix then ./devenv.local.nix else { }) + (if builtins.pathExists (devenv_dotfile + "/cli-options.nix") then import (devenv_dotfile + "/cli-options.nix") else { }) + ]; + }; + config = project.config; + + options = pkgs.nixosOptionsDoc { + options = builtins.removeAttrs project.options [ "_module" ]; + warningsAreErrors = false; + # Unpack Nix types, e.g. literalExpression, mDoc. + transformOptions = + let isDocType = v: builtins.elem v [ "literalDocBook" "literalExpression" "literalMD" "mdDoc" ]; + in lib.attrsets.mapAttrs (_: v: + if v ? _type && isDocType v._type then + v.text + else if v ? _type && v._type == "derivation" then + v.name + else + v + ); + }; + + build = options: config: + lib.concatMapAttrs + (name: option: + if builtins.hasAttr "type" option then + if option.type.name == "output" || option.type.name == "outputOf" then { + ${name} = config.${name}; + } else { } + else + let v = build option config.${name}; + in if v != { } then { + ${name} = v; + } else { } + ) + options; + + systems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ]; + in + { + devShell = lib.genAttrs systems (system: config.shell); + packages = lib.genAttrs systems (system: { + optionsJSON = options.optionsJSON; + # deprecated + inherit (config) info procfileScript procfileEnv procfile; + ci = config.ciDerivation; + }); + devenv = config; + build = build project.options project.config; + }; + } diff --git a/.devenv/devenv.json b/.devenv/devenv.json new file mode 100644 index 0000000..ad68ab3 --- /dev/null +++ b/.devenv/devenv.json @@ -0,0 +1 @@ +{"inputs":{"rust-overlay":{"url":"github:oxalica/rust-overlay","inputs":{"nixpkgs":{"follows":"nixpkgs"}}}}} \ No newline at end of file diff --git a/.devenv/flake.json b/.devenv/flake.json new file mode 100644 index 0000000..dcc7dbe --- /dev/null +++ b/.devenv/flake.json @@ -0,0 +1 @@ +{"rust-overlay":{"url":"github:oxalica/rust-overlay","inputs":{"nixpkgs":{"follows":"nixpkgs"}}}} \ No newline at end of file diff --git a/.devenv/imports.txt b/.devenv/imports.txt new file mode 100644 index 0000000..e69de29 diff --git a/.devenv/nix-eval-cache.db b/.devenv/nix-eval-cache.db new file mode 100644 index 0000000000000000000000000000000000000000..7ee7c113a09428e4daafacb6e70a35d18573e608 GIT binary patch literal 4096 zcmWFz^vNtqRY=P(%1ta$FlG>7U}9o$P*7lCU|@t|1_}TpgI-kuFUSA^5HX5JLtr!n lMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz11B1ON|k2KxX2 literal 0 HcmV?d00001 diff --git a/.devenv/nix-eval-cache.db-shm b/.devenv/nix-eval-cache.db-shm new file mode 100644 index 0000000000000000000000000000000000000000..f681988f52a3c3bdf1710b5e6630b7b07d3f9d1e GIT binary patch literal 32768 zcmb1mq{{#Tj0_A6j0_9{1`G@g0t^fc%{uPu%p17PGV5A>;x?_0;!ZG6z2W`yJE`hH zW`i)u-2X@bBnHADaS#o%pNWBiff?cs1{j-#fq{XQfq{XIfq{XYfq{X8fq{XOfq{XG zfq{XWfq{XCfq{XSfq{XKfdQ-s*&KeTUqEJ&Vh&6nx*lwH!qkHNFp5V*U^E0qLtr!n zMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ON zU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU z1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3Tu0Y(NE z24PY)jjA6FfngB>Obo0HLJT4d62rnbqn;QI0a8MMnSqT#loSo4YDYt0*n|K(gCv96 zu<^~PM@B<{ln~%xkYZ3LMZ>7t(GVCmA;8HX&7d)Cd^75i(GVad1h^Pv7&J-IFsgPm z1cprra5Kmb8^4TtWHbaw3jrPmInp$YsvZr2VG{zp4Dt+G!^StG9vKY*QbK@_L4iS= z6b++lM?+xPgaAK-B7@Gb@y)15Mniy<5D;KcVu0LpLyE3ZwWA?096~^lL772sICx~# z52GPKatMeqs4(c0tZP)mXb2345D;fjWq{qWHyr#k>W9$~7!85Z5Eu=C(GVC7fzc2c Y4S~@R7!85Z5Eu=C(GVC70n$SN0N_F@Z~y=R literal 0 HcmV?d00001 diff --git a/.devenv/nix-eval-cache.db-wal b/.devenv/nix-eval-cache.db-wal new file mode 100644 index 0000000000000000000000000000000000000000..8740055ff77c8403dc6328d0b954fea473d59461 GIT binary patch literal 197792 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%0DQ_B)_bdwX4GeG)a`ayzV zWm&~wOZ1c>9@PUW%&bsKOH4B|vM^3gwJyiGfy$LNJ&mHHaAJKG)XZvN=`I2Ge|VDOf*ccR!YrFOv*`BvMMPm zP1R8`0 zQ;uBK;K~H87hvSy&A`7KBs+>nLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$( zGz11&2)M8`@^Vr-q`|iaRE@MjN;J{7!85Z5Eu=C(GVC7 zfzc2c4S~@R7!83@Fd71*Auwn|fLh}M>>wY)#s&6ou~m=yV&e$fN5Ia@&%nQ%-->S+ zUkx7d^0D%d#~VmKOk zSy=F`)Ypfs%hsz*%*`<}wM< z#uk~FA%k#$=|STPylDZXKgq((GRfS;G%eXU8RQ%jQ!`5wi`3L4%S7WelO)U3 zltcsL6eGjLwA3Wiv^1k6vqV$l#Iz&>3)AEzi{#XdOM#6b`|FuF7_x}AUms#WXd{Dx zv2lutfnlO~N{W$XQmRQ}GRQ$mmKMfFrWR(VNoGcdW+`UIX=X`=7Urf&iKYgLsTP(g z#;N9pW~oU@Mj4j^KZ6|L%*f7ALNNHC{?|{=$%O9KCf&VxE7yh^W&-m~2-{8LpQaOr8Ltr!nMnhmU z1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz1212(YnmGBUEWgDEyPFvZFWrdU|O6f-lJ zVq#)p;RKHh@PPaR8y7I@t-jFRp?MB6E^v>5{}2Cn{!jdG`Csrq=D!D0If_R^U^E0q zLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1cpWkurPBnvV#aV5Wxx}SU?0bh+tx7 z29FDXwhX}c5ioGXFSCmO$pRS{xB(g$_{RT%{}ule{(Jm4hK8?4T{#*8qaiRF0;3@? z8UmvsFd71*Aut*OqaiRF0;3@?8UiCd1X!6ts|G+M8ykpZWd)HeEFhAZ8ALL{#s&C5 zVFg<+5U`82@A{9ze8{-K=sp5a*o@-Q5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7 zfzc2cG9duoBtX(W0`M&ZuyKI`!2;3UFIl&N77?)Umoo4_;XlH^kiT@u_ zJU-MfI5Z%@KPbf2B|bPZIK&}5kP^pbR|wf z{@$*BAbBZ9HU>^zUKSVEFjv2@cxQjV5Jyix*C3D_0|SEq2*bt&*1796n{hXogVqbM z@b@wBzvjQlzlFbVum|a=`$j`xGz3ONU^E0qLtr!nMnhmU1V%$(6pV(zXb6mkz|ao? pRTfTPMna, +} + +#[derive(Deserialize)] +struct Response { + data: Data, +} + +fn main() -> Result<(), Box> { + let now = chrono::Local::now(); + + println!("BEGIN:VCALENDAR"); + + for days_in_future in 0..14 { + let date = now + chrono::Days::new(days_in_future); + + // komida API expects local time + let date_komida_fmt = date.format("%Y-%m-%d"); + + let res: Response = get(format!( + "https://app.growzer.be/MenuPlanner/GetMenuPlanner?locationId={}&stringDate={}&customerId={}", + location_id, + date_komida_fmt, + customer_id, + ))?.json()?; + + // ical uses UTC + let lunch_starts_at = date.with_time(chrono::NaiveTime::from_hms(11, 30, 00)).unwrap().to_utc(); + let lunch_ends_at = date.with_time(chrono::NaiveTime::from_hms(13, 45, 00)).unwrap().to_utc(); + + for item in res.data.menuPlannerList.iter() { + if item.SectionName.contains("Streetfood") + || item.SectionName.contains("Dailyfood") + || item.SectionName.contains("Soep") { + // let d = NaiveDate::parse_from_str(&e.date, "%Y-%m-%d")?; + println!("BEGIN:VEVENT"); + println!("SUMMARY:{}", item.MenuName); + println!("DTSTART:{}T{}Z", + lunch_starts_at.format("%Y%m%d"), + lunch_starts_at.format("%H%M%S"), + ); + println!("DTEND:{}T{}Z", + lunch_ends_at.format("%Y%m%d"), + lunch_ends_at.format("%H%M%S"), + ); + println!("END:VEVENT"); + } + } + } + + println!("END:VCALENDAR"); + Ok(()) +}