home/modules/downloads-sorter: init
This commit is contained in:
@@ -150,6 +150,7 @@
|
|||||||
cargo = ./home/modules/programs/cargo;
|
cargo = ./home/modules/programs/cargo;
|
||||||
colors = ./home/modules/colors.nix;
|
colors = ./home/modules/colors.nix;
|
||||||
direnv-auto-prune = ./home/modules/programs/direnv/auto-prune.nix;
|
direnv-auto-prune = ./home/modules/programs/direnv/auto-prune.nix;
|
||||||
|
downloads-sorter = ./home/modules/services/downloads-sorter.nix;
|
||||||
gpg = ./home/modules/programs/gpg;
|
gpg = ./home/modules/programs/gpg;
|
||||||
mpd-auto-updater = ./home/modules/services/mpd.nix;
|
mpd-auto-updater = ./home/modules/services/mpd.nix;
|
||||||
neovim-auto-clean-swapfiles = ./home/modules/programs/neovim/auto-clean-swapfiles.nix;
|
neovim-auto-clean-swapfiles = ./home/modules/programs/neovim/auto-clean-swapfiles.nix;
|
||||||
|
13
home/config/downloads-sorter.nix
Normal file
13
home/config/downloads-sorter.nix
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
services.downloads-sorter = {
|
||||||
|
enable = true;
|
||||||
|
mappings = {
|
||||||
|
"pictures" = [
|
||||||
|
"*.jpg"
|
||||||
|
"*.png"
|
||||||
|
"*.gif"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
@@ -8,6 +8,7 @@ in {
|
|||||||
|
|
||||||
./config/xdg
|
./config/xdg
|
||||||
./config/ensure-homedir-structure.nix
|
./config/ensure-homedir-structure.nix
|
||||||
|
./config/downloads-sorter.nix
|
||||||
|
|
||||||
./programs/aria2.nix
|
./programs/aria2.nix
|
||||||
./programs/atuin.nix
|
./programs/atuin.nix
|
||||||
|
@@ -1,5 +1,110 @@
|
|||||||
{ ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.services.downloads-sorter;
|
||||||
|
in
|
||||||
{
|
{
|
||||||
# TODO: create abstraction over `systemd.path` thingy that looks at incoming files and
|
imports = [
|
||||||
# sorts them into subdirs by extension.
|
../systemd-tmpfiles.nix
|
||||||
|
];
|
||||||
|
|
||||||
|
options.services.downloads-sorter = {
|
||||||
|
enable = lib.mkEnableOption "downloads sorter units, path activated units to keep the download dir clean";
|
||||||
|
|
||||||
|
downloadsDir = lib.mkOption {
|
||||||
|
type = lib.types.path;
|
||||||
|
description = "Which directory to keep clean";
|
||||||
|
default = if config.xdg.userDirs.enable then config.xdg.userDirs.download else "${config.home.homeDirectory}/Downloads";
|
||||||
|
defaultText = ''
|
||||||
|
if config.xdg.userDirs.enable then config.xdg.userDirs.download else "''${config.home.homeDirectory}/Downloads"
|
||||||
|
'';
|
||||||
|
example = ''
|
||||||
|
"''${config.home.homeDirectory}/downloads"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
# TODO: allow specifying a dynamic filter together with a system path trigger in an attrset.
|
||||||
|
mappings = lib.mkOption {
|
||||||
|
type = with lib.types; attrsOf (listOf str);
|
||||||
|
description = ''
|
||||||
|
A mapping from a file pattern to the location where it should be moved.
|
||||||
|
|
||||||
|
By default, the output mapping is relative to the download dir.
|
||||||
|
If an absolute path is given, the sorter will move the files out of the downloads dir.
|
||||||
|
'';
|
||||||
|
default = { };
|
||||||
|
example = {
|
||||||
|
"pictures" = [
|
||||||
|
"*.png"
|
||||||
|
"*.jpg"
|
||||||
|
];
|
||||||
|
"documents" = [ "*.pdf" ];
|
||||||
|
"/home/<user>/archives" = [ "*.rar" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
systemd.user.paths = lib.mapAttrs' (dir: globs: let
|
||||||
|
unitName = "downloads-sorter@${dir}";
|
||||||
|
in {
|
||||||
|
name = unitName;
|
||||||
|
value = {
|
||||||
|
Install.WantedBy = [ "paths.target" ];
|
||||||
|
Path = {
|
||||||
|
PathExistsGlob = map (g: "${cfg.downloadsDir}/${g}") globs;
|
||||||
|
Unit = "${unitName}.service";
|
||||||
|
TriggerLimitIntervalSec = "1s";
|
||||||
|
TriggerLimitBurst = "1";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}) cfg.mappings;
|
||||||
|
|
||||||
|
# TODO: deduplicate
|
||||||
|
systemd.user.services = lib.mapAttrs' (dir: globs: let
|
||||||
|
unitName = "downloads-sorter@${dir}";
|
||||||
|
in {
|
||||||
|
name = unitName;
|
||||||
|
value = {
|
||||||
|
Unit.Description = "Downloads directory watchdog, sorts the downloads directory";
|
||||||
|
Service = {
|
||||||
|
Type = "oneshot";
|
||||||
|
SyslogIdentifier = unitName;
|
||||||
|
ExecStart = let
|
||||||
|
absolutePath = if (builtins.substring 0 1 dir) == "/" then dir else "${cfg.downloadsDir}/${dir}";
|
||||||
|
|
||||||
|
script = pkgs.writeShellApplication {
|
||||||
|
name = "downloads-sorter-${dir}.sh";
|
||||||
|
runtimeInputs = [ pkgs.coreutils ];
|
||||||
|
text = ''
|
||||||
|
shopt -s nullglob
|
||||||
|
|
||||||
|
FILES=(${lib.concatMapStringsSep " " (g: "'${cfg.downloadsDir}'/${g}") globs})
|
||||||
|
|
||||||
|
for file in "''${FILES[@]}"; do
|
||||||
|
echo "$file -> ${absolutePath}"
|
||||||
|
mv "$file" '${absolutePath}'
|
||||||
|
done
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
in lib.getExe script;
|
||||||
|
|
||||||
|
PrivateUsers = true;
|
||||||
|
ProtectSystem = true;
|
||||||
|
NoNewPrivileges = true;
|
||||||
|
ProtectKernelTunables = true;
|
||||||
|
ProtectControlGroups = true;
|
||||||
|
PrivateNetwork = true;
|
||||||
|
RestrictNamespaces = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}) cfg.mappings;
|
||||||
|
|
||||||
|
systemd.user.tmpfiles.settings."10-downloads-sorter-service" = let
|
||||||
|
absolutePaths = map (p: if (builtins.substring 0 1 p) == "/" then p else "${cfg.downloadsDir}/${p}") (builtins.attrNames cfg.mappings);
|
||||||
|
in lib.genAttrs absolutePaths (_: {
|
||||||
|
d = {
|
||||||
|
user = config.home.username;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user