From 1ed4500cea5d0993d905273aa76bf6e7aa32be1f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Geoffrey=20=E2=80=9CFrogeye=E2=80=9D=20Preud=27homme?=
 <geoffrey@frogeye.fr>
Date: Sat, 1 Mar 2025 22:14:06 +0100
Subject: [PATCH] nextcloud: Added

---
 flake.nix                 |   1 +
 hm/accounts/default.nix   |   1 +
 hm/accounts/nextcloud.nix | 109 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 111 insertions(+)
 create mode 100644 hm/accounts/nextcloud.nix

diff --git a/flake.nix b/flake.nix
index ac88b3e..d66ecf3 100644
--- a/flake.nix
+++ b/flake.nix
@@ -66,6 +66,7 @@
               jjui = upkgs.jjui;
               labelle = upkgs.labelle;
               orca-slicer = upkgs.orca-slicer; # Not prebuilt in 24.11 for some reason
+              nextcloud-client = upkgs.nextcloud-client; # Need https://github.com/nextcloud/desktop/pull/7714
             }
           )
         ];
diff --git a/hm/accounts/default.nix b/hm/accounts/default.nix
index e907928..8821a04 100644
--- a/hm/accounts/default.nix
+++ b/hm/accounts/default.nix
@@ -81,6 +81,7 @@ in
   };
   imports = [
     ./netrc.nix
+    ./nextcloud.nix
   ];
   # UPST Thunderbird-specific options (should be named so), to be included in HM Thunderbird module
   options = {
diff --git a/hm/accounts/nextcloud.nix b/hm/accounts/nextcloud.nix
new file mode 100644
index 0000000..e036623
--- /dev/null
+++ b/hm/accounts/nextcloud.nix
@@ -0,0 +1,109 @@
+{
+  pkgs,
+  lib,
+  config,
+  ...
+}:
+let
+  cfg = config.frogeye.nextcloud;
+in
+{
+  config = {
+    systemd.user = lib.mkIf (builtins.length cfg > 0) {
+      services.nextcloud_sync = {
+        Service = {
+          Type = "oneshot";
+          ExecStart = lib.getExe (
+            pkgs.writeShellApplication {
+              name = "nextcloud_sync";
+              runtimeInputs = with pkgs; [
+                nextcloud-client
+              ];
+              text =
+                ''
+                  sync() {
+                    url="$1"
+                    remote="$2"
+                    local="$3"
+                    echo "Syncing $url $remote to $local"
+
+                    # Adding to Syncthing ignores (so it's not double-synced)
+                    dir="$local"
+                    while [ "$dir" != "/" ]
+                    do
+                        if [ -d "$dir/.stfolder" ]
+                        then
+                            if [ ! -f "$dir/.stignore" ]
+                            then
+                                touch "$dir/.stignore"
+                            fi
+                            rule="''${local#"$dir/"}/**"
+                            if ! grep -qFx "$rule" "$dir/.stignore"
+                            then
+                                echo "$rule" >> "$dir/.stignore"
+                            fi
+                        fi
+                        dir="$(dirname "$dir")"
+                    done
+
+                    # Actual syncing
+                    mkdir -p "$local"
+                    nextcloudcmd -n -h --path "$remote" "$local" "$url"
+                  }
+
+                ''
+                + (lib.trivial.pipe cfg [
+                  (builtins.map (n: ''
+                    sync ${
+                      lib.strings.escapeShellArgs [
+                        n.url
+                        n.remote
+                        "${config.home.homeDirectory}/${n.local}"
+                      ]
+                    }
+                  ''))
+                  lib.strings.concatLines
+                ]);
+            }
+          );
+        };
+      };
+      timers.nextcloud_sync = {
+        Timer = {
+          OnCalendar = "*:1/5";
+        };
+        Install = {
+          WantedBy = [ "timers.target" ];
+        };
+      };
+    };
+  };
+  options = {
+    frogeye.nextcloud = lib.mkOption {
+      default = { };
+      description = "Sync Nextcloud folders. Uses netrc for authentication";
+      type = lib.types.listOf (
+        lib.types.submodule (
+          { config, ... }:
+          {
+            options = {
+              url = lib.mkOption {
+                type = lib.types.str;
+                description = "URL of the Nextcloud instance";
+              };
+              local = lib.mkOption {
+                type = lib.types.str;
+                description = "Local path (relative to home) to sync";
+              };
+              remote = lib.mkOption {
+                type = lib.types.str;
+                description = "Remote path to sync";
+                default = "/";
+              };
+            };
+          }
+        )
+      );
+    };
+  };
+}