diff --git a/hosts/nixos/hs/home.nix b/hosts/nixos/hs/home.nix index cf01173..f78a567 100644 --- a/hosts/nixos/hs/home.nix +++ b/hosts/nixos/hs/home.nix @@ -5,6 +5,7 @@ ../home-default.nix ../../../modules/syncthing.nix ../../../modules/tex.nix + ../../../modules/scheduled-commands.nix ]; # hs-specific home configuration @@ -13,21 +14,28 @@ programs.yt-dlp-custom = { enable = true; downloadDir = "/mnt/storage/Media/web"; - subscriptions = { - enable = true; - feeds = [ - "https://www.youtube.com/feeds/videos.xml?channel_id=UCm22FAXZMw1BaWeFszZxUKw" # Kitboga - "https://www.youtube.com/feeds/videos.xml?channel_id=UCYwVxWpjeKFWwu8TML-Te9A" # JCS - Criminal Psychology - "https://www.youtube.com/feeds/videos.xml?channel_id=UCPJVs54XcE8RrdA_uW-lfUw" # Shane McGillicuddy - "https://www.youtube.com/feeds/videos.xml?channel_id=UCFQMnBA3CS502aghlcr0_aw" # Coffeezilla - "https://www.youtube.com/feeds/videos.xml?channel_id=UCSUf5_EPEfl4zlBKZHkZdmw" # Danny Gonzalez - "https://www.youtube.com/feeds/videos.xml?channel_id=UC-ufRLYrXxrIEApGn9VG5pQ" # Reject Convenience - "https://www.youtube.com/feeds/videos.xml?channel_id=UCj1VqrHhDte54oLgPG4xpuQ" # Stuff Made Here - ]; - interval = "*-*-* 08:00:00"; - randomDelay = "1h"; - maxVideosPerFeed = 5; - }; + }; + + # Scheduled YouTube downloads + services.scheduled-commands = { + enable = true; + serviceName = "video-downloads"; + serviceDescription = "Download web videos from favorite channels"; + interval = "*-*-* 08:00:00"; + randomDelay = "1h"; + commands = [ + "dl-yt -n 3 https://www.youtube.com/@KitbogaShow" + "dl-yt -n 3 https://www.youtube.com/@JCS" + "dl-yt -n 3 https://www.youtube.com/@Shane_McGillicuddy" + "dl-yt -n 3 https://www.youtube.com/@Coffeezilla" + "dl-yt -n 3 https://www.youtube.com/@Danny-Gonzalez" + "dl-yt -n 3 https://www.youtube.com/@rejectconvenience" + "dl-yt -n 3 https://www.youtube.com/@StuffMadeHere" + "dl-yt -n 3 https://www.youtube.com/@AdamSomething" + "dl-yt -n 3 https://www.youtube.com/@_gerg" + "dl-yt -n 3 https://www.youtube.com/@Yeah_Jaron" + "dl-yt -n 3 https://www.youtube.com/@WolfgangsChannel" + ]; }; programs.zsh.shellAliases = { diff --git a/modules/scheduled-commands.nix b/modules/scheduled-commands.nix new file mode 100644 index 0000000..c27a9d0 --- /dev/null +++ b/modules/scheduled-commands.nix @@ -0,0 +1,97 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + cfg = config.services.scheduled-commands; + + # Create wrapper script that sources user shell environment + commandScript = pkgs.writeScriptBin "${cfg.serviceName}-run" '' + #!${pkgs.zsh}/bin/zsh + # Source user shell to get environment and functions + source ${config.home.homeDirectory}/.zshrc + + # Execute commands sequentially + ${concatStringsSep "\n" cfg.commands} + ''; +in + +{ + options.services.scheduled-commands = { + enable = mkEnableOption "scheduled command execution service"; + + commands = mkOption { + type = types.listOf types.str; + default = []; + example = [ + "echo 'Starting backup...'" + "rsync -av /source /destination" + "echo 'Backup completed'" + ]; + description = "List of shell commands to execute sequentially"; + }; + + interval = mkOption { + type = types.str; + default = "daily"; + example = "*-*-* 08:00:00"; + description = "Systemd timer schedule (OnCalendar format)"; + }; + + randomDelay = mkOption { + type = types.str; + default = "0"; + example = "1h"; + description = "Random delay before execution (e.g., '30m', '1h')"; + }; + + serviceName = mkOption { + type = types.str; + default = "scheduled-commands"; + example = "video-downloads"; + description = "Name for the systemd service and timer"; + }; + + serviceDescription = mkOption { + type = types.str; + default = "Execute scheduled commands"; + example = "Download YouTube videos from subscriptions"; + description = "Description for the systemd service"; + }; + }; + + config = mkIf cfg.enable { + # Install the wrapper script + home.packages = [ commandScript ]; + + systemd.user.services.${cfg.serviceName} = { + Unit = { + Description = cfg.serviceDescription; + After = [ "network-online.target" ]; + }; + + Service = { + Type = "oneshot"; + ExecStart = "${commandScript}/bin/${cfg.serviceName}-run"; + StandardOutput = "journal"; + StandardError = "journal"; + }; + }; + + systemd.user.timers.${cfg.serviceName} = { + Unit = { + Description = "Timer for ${cfg.serviceDescription}"; + }; + + Timer = { + OnCalendar = cfg.interval; + Persistent = true; + RandomizedDelaySec = cfg.randomDelay; + }; + + Install = { + WantedBy = [ "timers.target" ]; + }; + }; + }; +} diff --git a/modules/yt-dlp.nix b/modules/yt-dlp.nix index 9f0e05b..ffde965 100644 --- a/modules/yt-dlp.nix +++ b/modules/yt-dlp.nix @@ -23,40 +23,6 @@ in example = "/mnt/storage/videos"; description = "Base directory for downloaded videos"; }; - - subscriptions = { - enable = mkEnableOption "RSS subscription checking for automatic video downloads"; - - feeds = mkOption { - type = types.listOf types.str; - default = []; - example = [ - "https://www.youtube.com/feeds/videos.xml?channel_id=UCRHXUZ0BxbkU2MYZgsuFgkQ" - ]; - description = "List of YouTube RSS feed URLs to monitor for new videos"; - }; - - interval = mkOption { - type = types.str; - default = "hourly"; - example = "*-*-* */4:00:00"; - description = "Systemd timer schedule for checking subscriptions"; - }; - - randomDelay = mkOption { - type = types.str; - default = "0"; - example = "30m"; - description = "Random delay before running subscription check (e.g., '30m', '1h')"; - }; - - maxVideosPerFeed = mkOption { - type = types.int; - default = 5; - example = 10; - description = "Maximum number of videos to process per feed (newest first)"; - }; - }; }; config = mkIf cfg.enable { @@ -66,8 +32,6 @@ in cfg.package deno # Required for YouTube downloads due to JS challenges ffmpeg - ] ++ lib.optionals cfg.subscriptions.enable [ - libxml2 # For xmllint to parse RSS feeds ]; # Cookie files - managed by Nix (read-only) @@ -116,16 +80,13 @@ in # YouTube downloads dl-yt = "download-youtube"; dl-yt-p = "download-youtube-playlist"; - - # Bilibili downloads + + # Bilibili downloads dl-bili = "download-bilibili"; dl-bili-p = "download-bilibili-playlist"; - + # Help dl-help = "download-help"; - } // lib.optionalAttrs cfg.subscriptions.enable { - # YouTube subscription management - dl-subs-yt = "check-youtube-subscriptions"; }; programs.zsh.initContent = '' @@ -393,91 +354,6 @@ in # Alias for backward compatibility alias dlv-clear-archive='dl-clear-archive' - - # YouTube RSS subscription checker - check-youtube-subscriptions() { - ${lib.optionalString cfg.subscriptions.enable '' - local max_videos="${toString cfg.subscriptions.maxVideosPerFeed}" - local feeds=(${lib.concatMapStringsSep " " (feed: ''"${feed}"'') cfg.subscriptions.feeds}) - - if [[ ''${#feeds[@]} -eq 0 ]]; then - echo "No RSS feeds configured" - return 0 - fi - - echo "Checking ''${#feeds[@]} YouTube subscription feeds..." - echo "Processing up to $max_videos videos per feed" - echo "" - - for feed in "''${feeds[@]}"; do - echo "Processing feed: $feed" - - # Fetch and parse the RSS feed, extract video links - local links=$(${pkgs.curl}/bin/curl -s "$feed" | \ - ${pkgs.libxml2}/bin/xmllint --xpath "//*[local-name()='entry']/*[local-name()='link'][@rel='alternate']/@href" - 2>/dev/null | \ - sed 's/href="//g; s/"//g' | \ - head -n "$max_videos") - - if [[ -z "$links" ]]; then - echo " No videos found or feed unavailable" - continue - fi - - local count=0 - while IFS= read -r link; do - if [[ -n "$link" ]]; then - ((count++)) - echo " [$count] Downloading: $link" - download-youtube "$link" - fi - done <<< "$links" - - echo " Processed $count videos from this feed" - echo "" - done - - echo "✓ Subscription check completed" - ''} - } ''; - - # Systemd user service and timer for subscription checking - systemd.user.services.yt-dlp-subscriptions = mkIf cfg.subscriptions.enable { - Unit = { - Description = "Check YouTube RSS subscriptions and download new videos"; - After = [ "network-online.target" ]; - }; - - Service = { - Type = "oneshot"; - ExecStart = "${pkgs.writeShellScript "yt-dlp-check-subs" '' - export PATH="${pkgs.coreutils}/bin:${pkgs.curl}/bin:${pkgs.libxml2}/bin:${pkgs.gnused}/bin:${cfg.package}/bin:$PATH" - - # Source the shell init to get our functions - source ${config.home.homeDirectory}/.zshrc - - # Run the subscription check - check-youtube-subscriptions - ''}"; - StandardOutput = "journal"; - StandardError = "journal"; - }; - }; - - systemd.user.timers.yt-dlp-subscriptions = mkIf cfg.subscriptions.enable { - Unit = { - Description = "Timer for YouTube subscription checks"; - }; - - Timer = { - OnCalendar = cfg.subscriptions.interval; - Persistent = true; - RandomizedDelaySec = cfg.subscriptions.randomDelay; - }; - - Install = { - WantedBy = [ "timers.target" ]; - }; - }; }; }