Add scheduled command module
This commit is contained in:
parent
cc0077a5ae
commit
479535c294
3 changed files with 123 additions and 142 deletions
|
|
@ -5,6 +5,7 @@
|
||||||
../home-default.nix
|
../home-default.nix
|
||||||
../../../modules/syncthing.nix
|
../../../modules/syncthing.nix
|
||||||
../../../modules/tex.nix
|
../../../modules/tex.nix
|
||||||
|
../../../modules/scheduled-commands.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
# hs-specific home configuration
|
# hs-specific home configuration
|
||||||
|
|
@ -13,21 +14,28 @@
|
||||||
programs.yt-dlp-custom = {
|
programs.yt-dlp-custom = {
|
||||||
enable = true;
|
enable = true;
|
||||||
downloadDir = "/mnt/storage/Media/web";
|
downloadDir = "/mnt/storage/Media/web";
|
||||||
subscriptions = {
|
};
|
||||||
|
|
||||||
|
# Scheduled YouTube downloads
|
||||||
|
services.scheduled-commands = {
|
||||||
enable = true;
|
enable = true;
|
||||||
feeds = [
|
serviceName = "video-downloads";
|
||||||
"https://www.youtube.com/feeds/videos.xml?channel_id=UCm22FAXZMw1BaWeFszZxUKw" # Kitboga
|
serviceDescription = "Download web videos from favorite channels";
|
||||||
"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";
|
interval = "*-*-* 08:00:00";
|
||||||
randomDelay = "1h";
|
randomDelay = "1h";
|
||||||
maxVideosPerFeed = 5;
|
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 = {
|
programs.zsh.shellAliases = {
|
||||||
|
|
|
||||||
97
modules/scheduled-commands.nix
Normal file
97
modules/scheduled-commands.nix
Normal file
|
|
@ -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" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -23,40 +23,6 @@ in
|
||||||
example = "/mnt/storage/videos";
|
example = "/mnt/storage/videos";
|
||||||
description = "Base directory for downloaded 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 {
|
config = mkIf cfg.enable {
|
||||||
|
|
@ -66,8 +32,6 @@ in
|
||||||
cfg.package
|
cfg.package
|
||||||
deno # Required for YouTube downloads due to JS challenges
|
deno # Required for YouTube downloads due to JS challenges
|
||||||
ffmpeg
|
ffmpeg
|
||||||
] ++ lib.optionals cfg.subscriptions.enable [
|
|
||||||
libxml2 # For xmllint to parse RSS feeds
|
|
||||||
];
|
];
|
||||||
|
|
||||||
# Cookie files - managed by Nix (read-only)
|
# Cookie files - managed by Nix (read-only)
|
||||||
|
|
@ -123,9 +87,6 @@ in
|
||||||
|
|
||||||
# Help
|
# Help
|
||||||
dl-help = "download-help";
|
dl-help = "download-help";
|
||||||
} // lib.optionalAttrs cfg.subscriptions.enable {
|
|
||||||
# YouTube subscription management
|
|
||||||
dl-subs-yt = "check-youtube-subscriptions";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
programs.zsh.initContent = ''
|
programs.zsh.initContent = ''
|
||||||
|
|
@ -393,91 +354,6 @@ in
|
||||||
|
|
||||||
# Alias for backward compatibility
|
# Alias for backward compatibility
|
||||||
alias dlv-clear-archive='dl-clear-archive'
|
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" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue