From 18d5913d5eee4e0daec4fcc1e0e9e2d573762b37 Mon Sep 17 00:00:00 2001 From: Zack Meier Date: Sun, 26 Apr 2026 15:31:30 -0500 Subject: [PATCH] revamp regulation youtube scripts, start revamp of patreon --- yt-dlp/Download-RegulationGameplay_NEW.ps1 | 257 +++++++++++++++++++++ yt-dlp/Download-RegulationPatreon_NEW.ps1 | 257 +++++++++++++++++++++ yt-dlp/Download-RegulationPodcast_NEW.ps1 | 257 +++++++++++++++++++++ yt-dlp/Download-YTDLP.ps1 | 45 ++++ 4 files changed, 816 insertions(+) create mode 100644 yt-dlp/Download-RegulationGameplay_NEW.ps1 create mode 100644 yt-dlp/Download-RegulationPatreon_NEW.ps1 create mode 100644 yt-dlp/Download-RegulationPodcast_NEW.ps1 create mode 100644 yt-dlp/Download-YTDLP.ps1 diff --git a/yt-dlp/Download-RegulationGameplay_NEW.ps1 b/yt-dlp/Download-RegulationGameplay_NEW.ps1 new file mode 100644 index 0000000..fae34dc --- /dev/null +++ b/yt-dlp/Download-RegulationGameplay_NEW.ps1 @@ -0,0 +1,257 @@ +## YT Regulation Gameplay +# Set URL and Location +$URL = "https://www.youtube.com/@TheRegulationPodcast" +$folderPath = '\\truenas3.kwyjibo.info\RegulationPodcast$' + + +$rejects = @() +$RejectString = $rejects -join '|' + +Set-Location $folderPath + +function Download-YTDLP { + Param( + [Parameter(Mandatory = $true)] + [string]$videoUrl, + + [Parameter(Mandatory = $true)] + [string]$OutputPath, + + [string]$RejectString, + + [switch]$WithCookies + ) + + $ytDlpPath = "D:\yt-dlp\yt-dlp.exe" + + # Start building an array of arguments using strict comma separation (Recommended format) + $arguments = @( + $videoUrl, + "--write-info-json", + "--write-thumbnail", + "--convert-thumbnails", "jpg", + "--no-progress", + "-t", "sleep", + "--rate-limit", "5M", + "-o", $OutputPath, + '-f', "bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best", + "-S", "vcodec:h264", + "--reject-title", $RejectString, + "--playlist-reverse" + ) + + # --- Conditional Logic Applied Here --- + if ($WithCookies) { + Write-Verbose "--- Using browser cookies for download. ---" -Verbose + $arguments += "--cookies-from-browser", "firefox" + } + else { + Write-Verbose "--- Downloading without specific cookie credentials. ---" -Verbose + } + + # 1. Execute yt-dlp using the call operator (&) and passing the arguments array (@) + & $ytDlpPath $arguments + + # 2. CRITICAL: Check the Exit Code immediately after execution + if ($LASTEXITCODE -ne 0) { + # If the exit code is not 0, we throw a terminating exception. + # This exception will be caught by your external try/catch block! + $ErrorMessage = "yt-dlp failed (Exit Code: $($LASTEXITCODE)). Check standard error output for details." + throw $ErrorMessage + } + + Write-Verbose "YTDLP finished successfully." # Optional confirmation +} + +# Function to manage Short ID tracking (NEW) +function Manage-ShortTracking { + Param( + [Parameter(Mandatory=$true)] + [string]$ShortDirPath, + + [Parameter(Mandatory=$true)] + [string]$VideoId, + + [switch]$IsNewDownload + ) + + $trackingFile = Join-Path -Path $ShortDirPath -ChildPath "shorts_ids.json" + + if ($IsNewDownload) { + # 1. Check if ID already exists + if (Test-Path $trackingFile) { + try { + $existingIds = Get-Content -Path $trackingFile | ConvertFrom-Json + if ($existingIds -contains $VideoId) { + return $true # Video ID found, should skip download + } + } catch { + Write-Error "Could not read or parse existing shorts tracking file: $($_.Exception.Message)" + } + } + + # 2. If not found, write the new ID to the file (or update it) + try { + if (Test-Path $trackingFile) { + # File exists, append without duplicating + $existingIds = Get-Content -Path $trackingFile | ConvertFrom-Json + if (-not ($existingIds -contains $VideoId)) { + $newIds = $existingIds + $VideoId + $newIds | ConvertTo-Json -Depth 3 | Set-Content -Path $trackingFile + Write-Verbose "Successfully added ID '$VideoId' to shorts tracking." + } else { + Write-Verbose "ID '$VideoId' already exists in tracking file." + } + + } else { + # File does not exist, create it + @($VideoId) | ConvertTo-Json -Depth 3 | Set-Content -Path $trackingFile + Write-Verbose "Created and added ID '$VideoId' to shorts tracking file." + } + } catch { + Write-Error "Failed to write to shorts tracking file: $($_.Exception.Message)" + } + } else { + # Check mode (only needed when checking before download) + if (Test-Path $trackingFile) { + try { + $existingIds = Get-Content -Path $trackingFile | ConvertFrom-Json + return $existingIds -contains $VideoId # Returns True if ID is found + } catch { + Write-Error "Could not read or parse existing shorts tracking file: $($_.Exception.Message)" + return $false # Assume safe to download if parsing fails + } + } + return $false # No tracking file exists, assume safe to download + } +} + + +# Download flat playlist +Write-Verbose -Message "Download flat playlist" +$flat = D:\yt-dlp\yt-dlp.exe -j --flat-playlist $URL +$flat | Set-Content -Path YouTube_TheRegulationPodcast.json + + +# load json into memory, convert to psobject +$json = Get-Content -Path YouTube_TheRegulationPodcast.json | ConvertFrom-Json + +# Load all .mp4 files into memory once at the start +$mp4Files = Get-ChildItem -Path $folderPath -Recurse -Filter "*.mp4" + + +ForEach ($obj in $json) { + # Initialize $fileFound as null for each iteration + $fileFound = $false + + # Extract information from the JSON object + $videoUrl = $obj.webpage_url + $Title = $obj.title + $Id = $obj.id + + + # Log the start of the process + Write-Verbose -Message "Start $Id ##### $Title" -Verbose + + # Check if the title matches any reject term using wildcards + $reject_matches = $rejects | Where-Object { $Title -like "*$($_)*" } + If ($reject_matches) { + Write-Warning -Message "Skip $Id ##### $Title (Rejected by Title)" + continue # Jumps immediately to the next iteration of the loop + } + + # downloaded already? + # Regular expression to match the ID after "youtube-" and before the closing bracket + $regex = "(?i)youtube-$Id" + + # Check if any file already exists that matches the video ID + $fileFound = $mp4Files | Where-Object { $_.Name -match $regex } + + + # If no file is found, notify the user + if ($fileFound) { + Write-Warning "File found with the YouTube ID: $Id" + } + Else { + # Check if this is a YouTube Short by getting video info (aspect ratio or duration) + Write-Verbose -Message "Checking if video is a Short: $Title" -Verbose + $isShort = $false + $videoInfo = D:\yt-dlp\yt-dlp.exe -j $videoUrl + $videoInfoObj = $videoInfo | ConvertFrom-Json + + + if ($videoUrl -like "*shorts*") { + Write-Verbose "Identified as Shorts video because the URL contains 'shorts': $Id ##### $Title" -Verbose + $isShort = $true + } + Elseif ($videoInfoObj.duration -and $videoInfoObj.duration -lt 60) { + # Determine if this is a short based on duration + Write-Verbose "Identified as Shorts video because the duration is 60 seconds or less: $Id ##### $Title" -Verbose + $isShort = $true + } + elseif ($videoInfoObj.width -and $videoInfoObj.height) { + # Calculate aspect ratio (height/width for vertical videos) + $aspectRatio = [double]$videoInfoObj.height / [double]$videoInfoObj.width + if ($aspectRatio -gt 1.5) { + # Vertical video ( > 1.5:1) + $isShort = $true + } + } + + # Set output path based on whether it's a short or not + if ($isShort) { + Write-Verbose -Message "Video detected as Short: $Title" -Verbose + # Note: This path must be determined before running the tracking check/download + $outputPath = Join-Path $folderPath "YouTube Shorts/%(release_date>%Y%m%d,upload_date>%Y%m%d)s - %(title).180B [%(extractor)s-%(id)s].%(ext)s" + $shortDirPath = Split-Path $outputPath -Parent # Gets the directory path (e.g., \RegulationPodcast\YouTube Shorts\...) + + # Check if ID is in the tracking JSON file + $idAlreadyTracked = Manage-ShortTracking -ShortDirPath $shortDirPath -VideoId $Id -IsNewDownload:$false + + if ($idAlreadyTracked) { + Write-Warning "Skipping Short $Id ##### $Title because it was previously tracked and deleted." + continue # Skip the download attempt entirely + } + } + else { + Write-Verbose -Message "Video detected as regular: $Title" -Verbose + $outputPath = Join-Path $folderPath "Unsorted/Season %(release_date>%y,upload_date>%y|Unknown)s/%(release_date>%Y%m%d,upload_date>%Y%m%d)s - %(title).180B [%(extractor)s-%(id)s].%(ext)s" + } + + # Execute yt-dlp command for non-rejected videos + try { + Write-Warning -Message "Dwnld $Id ##### $Title" + + Download-YTDLP -videoUrl $videoUrl -OutputPath $outputPath -RejectString $RejectString + $DownloadSuccessful = $true # Set flag to true if download completes successfully + + } + catch { + $DownloadError = $true + Write-Error "Failed to download $Id - $_" + $DownloadSuccessful = $false # Ensure failure is tracked + } + + + If ($DownloadSuccessful -eq $false) { + # If the initial download failed, attempt with cookies + try { + Write-Warning -Message "Dwnld (Cookies Attempt) $Id ##### $Title" + Download-YTDLP -videoUrl $videoUrl -OutputPath $outputPath -RejectString $RejectString -WithCookies + $DownloadSuccessful = $true # Set flag to true if the second attempt succeeds + } + catch { + $DownloadError = $true + Write-Error "Failed to download $Id (Cookies Attempt) - $_" + $DownloadSuccessful = $false + } + } + + if ($isShort -and $DownloadSuccessful) { + $shortDirPath = Split-Path $outputPath -Parent # Gets the directory path (e.g., \RegulationPodcast\YouTube Shorts\...) + Manage-ShortTracking -ShortDirPath $shortDirPath -VideoId $Id -IsNewDownload:$true + } + } + # Log the end of the process + Write-Verbose -Message "End $Id ##### $Title" +} \ No newline at end of file diff --git a/yt-dlp/Download-RegulationPatreon_NEW.ps1 b/yt-dlp/Download-RegulationPatreon_NEW.ps1 new file mode 100644 index 0000000..e15f96a --- /dev/null +++ b/yt-dlp/Download-RegulationPatreon_NEW.ps1 @@ -0,0 +1,257 @@ +## YT Regulation Podcast +# Set URL and Location +$URL = "https://www.youtube.com/@theregulationpod" +$folderPath = '\\truenas3.kwyjibo.info\RegulationPodcast$' + + +$rejects = @() +$RejectString = $rejects -join '|' + +Set-Location $folderPath + +function Download-YTDLP { + Param( + [Parameter(Mandatory = $true)] + [string]$videoUrl, + + [Parameter(Mandatory = $true)] + [string]$OutputPath, + + [string]$RejectString, + + [switch]$WithCookies + ) + + $ytDlpPath = "D:\yt-dlp\yt-dlp.exe" + + # Start building an array of arguments using strict comma separation (Recommended format) + $arguments = @( + $videoUrl, + "--write-info-json", + "--write-thumbnail", + "--convert-thumbnails", "jpg", + "--no-progress", + "-t", "sleep", + "--rate-limit", "5M", + "-o", $OutputPath, + '-f', "bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best", + "-S", "vcodec:h264", + "--reject-title", $RejectString, + "--playlist-reverse" + ) + + # --- Conditional Logic Applied Here --- + if ($WithCookies) { + Write-Verbose "--- Using browser cookies for download. ---" -Verbose + $arguments += "--cookies-from-browser", "firefox" + } + else { + Write-Verbose "--- Downloading without specific cookie credentials. ---" -Verbose + } + + # 1. Execute yt-dlp using the call operator (&) and passing the arguments array (@) + & $ytDlpPath $arguments + + # 2. CRITICAL: Check the Exit Code immediately after execution + if ($LASTEXITCODE -ne 0) { + # If the exit code is not 0, we throw a terminating exception. + # This exception will be caught by your external try/catch block! + $ErrorMessage = "yt-dlp failed (Exit Code: $($LASTEXITCODE)). Check standard error output for details." + throw $ErrorMessage + } + + Write-Verbose "YTDLP finished successfully." # Optional confirmation +} + +# Function to manage Short ID tracking (NEW) +function Manage-ShortTracking { + Param( + [Parameter(Mandatory=$true)] + [string]$ShortDirPath, + + [Parameter(Mandatory=$true)] + [string]$VideoId, + + [switch]$IsNewDownload + ) + + $trackingFile = Join-Path -Path $ShortDirPath -ChildPath "shorts_ids.json" + + if ($IsNewDownload) { + # 1. Check if ID already exists + if (Test-Path $trackingFile) { + try { + $existingIds = Get-Content -Path $trackingFile | ConvertFrom-Json + if ($existingIds -contains $VideoId) { + return $true # Video ID found, should skip download + } + } catch { + Write-Error "Could not read or parse existing shorts tracking file: $($_.Exception.Message)" + } + } + + # 2. If not found, write the new ID to the file (or update it) + try { + if (Test-Path $trackingFile) { + # File exists, append without duplicating + $existingIds = Get-Content -Path $trackingFile | ConvertFrom-Json + if (-not ($existingIds -contains $VideoId)) { + $newIds = $existingIds + $VideoId + $newIds | ConvertTo-Json -Depth 3 | Set-Content -Path $trackingFile + Write-Verbose "Successfully added ID '$VideoId' to shorts tracking." + } else { + Write-Verbose "ID '$VideoId' already exists in tracking file." + } + + } else { + # File does not exist, create it + @($VideoId) | ConvertTo-Json -Depth 3 | Set-Content -Path $trackingFile + Write-Verbose "Created and added ID '$VideoId' to shorts tracking file." + } + } catch { + Write-Error "Failed to write to shorts tracking file: $($_.Exception.Message)" + } + } else { + # Check mode (only needed when checking before download) + if (Test-Path $trackingFile) { + try { + $existingIds = Get-Content -Path $trackingFile | ConvertFrom-Json + return $existingIds -contains $VideoId # Returns True if ID is found + } catch { + Write-Error "Could not read or parse existing shorts tracking file: $($_.Exception.Message)" + return $false # Assume safe to download if parsing fails + } + } + return $false # No tracking file exists, assume safe to download + } +} + + +# Download flat playlist +Write-Verbose -Message "Download flat playlist" +$flat = D:\yt-dlp\yt-dlp.exe -j --flat-playlist $URL +$flat | Set-Content -Path YT_theregulationpod.json + + +# load json into memory, convert to psobject +$json = Get-Content -Path YT_theregulationpod.json | ConvertFrom-Json + +# Load all .mp4 files into memory once at the start +$mp4Files = Get-ChildItem -Path $folderPath -Recurse -Filter "*.mp4" + + +ForEach ($obj in $json) { + # Initialize $fileFound as null for each iteration + $fileFound = $false + + # Extract information from the JSON object + $videoUrl = $obj.webpage_url + $Title = $obj.title + $Id = $obj.id + + + # Log the start of the process + Write-Verbose -Message "Start $Id ##### $Title" -Verbose + + # Check if the title matches any reject term using wildcards + $reject_matches = $rejects | Where-Object { $Title -like "*$($_)*" } + If ($reject_matches) { + Write-Warning -Message "Skip $Id ##### $Title (Rejected by Title)" + continue # Jumps immediately to the next iteration of the loop + } + + # downloaded already? + # Regular expression to match the ID after "youtube-" and before the closing bracket + $regex = "(?i)youtube-$Id" + + # Check if any file already exists that matches the video ID + $fileFound = $mp4Files | Where-Object { $_.Name -match $regex } + + + # If no file is found, notify the user + if ($fileFound) { + Write-Warning "File found with the YouTube ID: $Id" + } + Else { + # Check if this is a YouTube Short by getting video info (aspect ratio or duration) + Write-Verbose -Message "Checking if video is a Short: $Title" -Verbose + $isShort = $false + $videoInfo = D:\yt-dlp\yt-dlp.exe -j $videoUrl + $videoInfoObj = $videoInfo | ConvertFrom-Json + + + if ($videoUrl -like "*shorts*") { + Write-Verbose "Identified as Shorts video because the URL contains 'shorts': $Id ##### $Title" -Verbose + $isShort = $true + } + Elseif ($videoInfoObj.duration -and $videoInfoObj.duration -lt 60) { + # Determine if this is a short based on duration + Write-Verbose "Identified as Shorts video because the duration is 60 seconds or less: $Id ##### $Title" -Verbose + $isShort = $true + } + elseif ($videoInfoObj.width -and $videoInfoObj.height) { + # Calculate aspect ratio (height/width for vertical videos) + $aspectRatio = [double]$videoInfoObj.height / [double]$videoInfoObj.width + if ($aspectRatio -gt 1.5) { + # Vertical video ( > 1.5:1) + $isShort = $true + } + } + + # Set output path based on whether it's a short or not + if ($isShort) { + Write-Verbose -Message "Video detected as Short: $Title" -Verbose + # Note: This path must be determined before running the tracking check/download + $outputPath = Join-Path $folderPath "YouTube Shorts/%(release_date>%Y%m%d,upload_date>%Y%m%d)s - %(title).180B [%(extractor)s-%(id)s].%(ext)s" + $shortDirPath = Split-Path $outputPath -Parent # Gets the directory path (e.g., \RegulationPodcast\YouTube Shorts\...) + + # Check if ID is in the tracking JSON file + $idAlreadyTracked = Manage-ShortTracking -ShortDirPath $shortDirPath -VideoId $Id -IsNewDownload:$false + + if ($idAlreadyTracked) { + Write-Warning "Skipping Short $Id ##### $Title because it was previously tracked and deleted." + continue # Skip the download attempt entirely + } + } + else { + Write-Verbose -Message "Video detected as regular: $Title" -Verbose + $outputPath = Join-Path $folderPath "Unsorted/Season %(release_date>%y,upload_date>%y|Unknown)s/%(release_date>%Y%m%d,upload_date>%Y%m%d)s - %(title).180B [%(extractor)s-%(id)s].%(ext)s" + } + + # Execute yt-dlp command for non-rejected videos + try { + Write-Warning -Message "Dwnld $Id ##### $Title" + + Download-YTDLP -videoUrl $videoUrl -OutputPath $outputPath -RejectString $RejectString + $DownloadSuccessful = $true # Set flag to true if download completes successfully + + } + catch { + $DownloadError = $true + Write-Error "Failed to download $Id - $_" + $DownloadSuccessful = $false # Ensure failure is tracked + } + + + If ($DownloadSuccessful -eq $false) { + # If the initial download failed, attempt with cookies + try { + Write-Warning -Message "Dwnld (Cookies Attempt) $Id ##### $Title" + Download-YTDLP -videoUrl $videoUrl -OutputPath $outputPath -RejectString $RejectString -WithCookies + $DownloadSuccessful = $true # Set flag to true if the second attempt succeeds + } + catch { + $DownloadError = $true + Write-Error "Failed to download $Id (Cookies Attempt) - $_" + $DownloadSuccessful = $false + } + } + + if ($isShort -and $DownloadSuccessful) { + $shortDirPath = Split-Path $outputPath -Parent # Gets the directory path (e.g., \RegulationPodcast\YouTube Shorts\...) + Manage-ShortTracking -ShortDirPath $shortDirPath -VideoId $Id -IsNewDownload:$true + } + } + # Log the end of the process + Write-Verbose -Message "End $Id ##### $Title" +} \ No newline at end of file diff --git a/yt-dlp/Download-RegulationPodcast_NEW.ps1 b/yt-dlp/Download-RegulationPodcast_NEW.ps1 new file mode 100644 index 0000000..f42edfb --- /dev/null +++ b/yt-dlp/Download-RegulationPodcast_NEW.ps1 @@ -0,0 +1,257 @@ +## YT Regulation Podcast +# Set URL and Location +$URL = "https://www.youtube.com/@theregulationpod" +$folderPath = '\\truenas3.kwyjibo.info\RegulationPodcast$' + + +$rejects = @() +$RejectString = $rejects -join '|' + +Set-Location $folderPath + +function Download-YTDLP { + Param( + [Parameter(Mandatory = $true)] + [string]$videoUrl, + + [Parameter(Mandatory = $true)] + [string]$OutputPath, + + [string]$RejectString, + + [switch]$WithCookies + ) + + $ytDlpPath = "D:\yt-dlp\yt-dlp.exe" + + # Start building an array of arguments using strict comma separation (Recommended format) + $arguments = @( + $videoUrl, + "--write-info-json", + "--write-thumbnail", + "--convert-thumbnails", "jpg", + "--no-progress", + "-t", "sleep", + "--rate-limit", "5M", + "-o", $OutputPath, + '-f', "bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best", + "-S", "vcodec:h264", + "--reject-title", $RejectString, + "--playlist-reverse" + ) + + # --- Conditional Logic Applied Here --- + if ($WithCookies) { + Write-Verbose "--- Using browser cookies for download. ---" -Verbose + $arguments += "--cookies-from-browser", "firefox" + } + else { + Write-Verbose "--- Downloading without specific cookie credentials. ---" -Verbose + } + + # 1. Execute yt-dlp using the call operator (&) and passing the arguments array (@) + & $ytDlpPath $arguments + + # 2. CRITICAL: Check the Exit Code immediately after execution + if ($LASTEXITCODE -ne 0) { + # If the exit code is not 0, we throw a terminating exception. + # This exception will be caught by your external try/catch block! + $ErrorMessage = "yt-dlp failed (Exit Code: $($LASTEXITCODE)). Check standard error output for details." + throw $ErrorMessage + } + + Write-Verbose "YTDLP finished successfully." # Optional confirmation +} + +# Function to manage Short ID tracking (NEW) +function Manage-ShortTracking { + Param( + [Parameter(Mandatory=$true)] + [string]$ShortDirPath, + + [Parameter(Mandatory=$true)] + [string]$VideoId, + + [switch]$IsNewDownload + ) + + $trackingFile = Join-Path -Path $ShortDirPath -ChildPath "shorts_ids.json" + + if ($IsNewDownload) { + # 1. Check if ID already exists + if (Test-Path $trackingFile) { + try { + $existingIds = Get-Content -Path $trackingFile | ConvertFrom-Json + if ($existingIds -contains $VideoId) { + return $true # Video ID found, should skip download + } + } catch { + Write-Error "Could not read or parse existing shorts tracking file: $($_.Exception.Message)" + } + } + + # 2. If not found, write the new ID to the file (or update it) + try { + if (Test-Path $trackingFile) { + # File exists, append without duplicating + $existingIds = Get-Content -Path $trackingFile | ConvertFrom-Json + if (-not ($existingIds -contains $VideoId)) { + $newIds = $existingIds + $VideoId + $newIds | ConvertTo-Json -Depth 3 | Set-Content -Path $trackingFile + Write-Verbose "Successfully added ID '$VideoId' to shorts tracking." + } else { + Write-Verbose "ID '$VideoId' already exists in tracking file." + } + + } else { + # File does not exist, create it + @($VideoId) | ConvertTo-Json -Depth 3 | Set-Content -Path $trackingFile + Write-Verbose "Created and added ID '$VideoId' to shorts tracking file." + } + } catch { + Write-Error "Failed to write to shorts tracking file: $($_.Exception.Message)" + } + } else { + # Check mode (only needed when checking before download) + if (Test-Path $trackingFile) { + try { + $existingIds = Get-Content -Path $trackingFile | ConvertFrom-Json + return $existingIds -contains $VideoId # Returns True if ID is found + } catch { + Write-Error "Could not read or parse existing shorts tracking file: $($_.Exception.Message)" + return $false # Assume safe to download if parsing fails + } + } + return $false # No tracking file exists, assume safe to download + } +} + + +# Download flat playlist +Write-Verbose -Message "Download flat playlist" +$flat = D:\yt-dlp\yt-dlp.exe -j --flat-playlist $URL +$flat | Set-Content -Path YouTube_theregulationpod.json + + +# load json into memory, convert to psobject +$json = Get-Content -Path YouTube_theregulationpod.json | ConvertFrom-Json + +# Load all .mp4 files into memory once at the start +$mp4Files = Get-ChildItem -Path $folderPath -Recurse -Filter "*.mp4" + + +ForEach ($obj in $json) { + # Initialize $fileFound as null for each iteration + $fileFound = $false + + # Extract information from the JSON object + $videoUrl = $obj.webpage_url + $Title = $obj.title + $Id = $obj.id + + + # Log the start of the process + Write-Verbose -Message "Start $Id ##### $Title" -Verbose + + # Check if the title matches any reject term using wildcards + $reject_matches = $rejects | Where-Object { $Title -like "*$($_)*" } + If ($reject_matches) { + Write-Warning -Message "Skip $Id ##### $Title (Rejected by Title)" + continue # Jumps immediately to the next iteration of the loop + } + + # downloaded already? + # Regular expression to match the ID after "youtube-" and before the closing bracket + $regex = "(?i)youtube-$Id" + + # Check if any file already exists that matches the video ID + $fileFound = $mp4Files | Where-Object { $_.Name -match $regex } + + + # If no file is found, notify the user + if ($fileFound) { + Write-Warning "File found with the YouTube ID: $Id" + } + Else { + # Check if this is a YouTube Short by getting video info (aspect ratio or duration) + Write-Verbose -Message "Checking if video is a Short: $Title" -Verbose + $isShort = $false + $videoInfo = D:\yt-dlp\yt-dlp.exe -j $videoUrl + $videoInfoObj = $videoInfo | ConvertFrom-Json + + + if ($videoUrl -like "*shorts*") { + Write-Verbose "Identified as Shorts video because the URL contains 'shorts': $Id ##### $Title" -Verbose + $isShort = $true + } + Elseif ($videoInfoObj.duration -and $videoInfoObj.duration -lt 60) { + # Determine if this is a short based on duration + Write-Verbose "Identified as Shorts video because the duration is 60 seconds or less: $Id ##### $Title" -Verbose + $isShort = $true + } + elseif ($videoInfoObj.width -and $videoInfoObj.height) { + # Calculate aspect ratio (height/width for vertical videos) + $aspectRatio = [double]$videoInfoObj.height / [double]$videoInfoObj.width + if ($aspectRatio -gt 1.5) { + # Vertical video ( > 1.5:1) + $isShort = $true + } + } + + # Set output path based on whether it's a short or not + if ($isShort) { + Write-Verbose -Message "Video detected as Short: $Title" -Verbose + # Note: This path must be determined before running the tracking check/download + $outputPath = Join-Path $folderPath "YouTube Shorts/%(release_date>%Y%m%d,upload_date>%Y%m%d)s - %(title).180B [%(extractor)s-%(id)s].%(ext)s" + $shortDirPath = Split-Path $outputPath -Parent # Gets the directory path (e.g., \RegulationPodcast\YouTube Shorts\...) + + # Check if ID is in the tracking JSON file + $idAlreadyTracked = Manage-ShortTracking -ShortDirPath $shortDirPath -VideoId $Id -IsNewDownload:$false + + if ($idAlreadyTracked) { + Write-Warning "Skipping Short $Id ##### $Title because it was previously tracked and deleted." + continue # Skip the download attempt entirely + } + } + else { + Write-Verbose -Message "Video detected as regular: $Title" -Verbose + $outputPath = Join-Path $folderPath "Unsorted/Season %(release_date>%y,upload_date>%y|Unknown)s/%(release_date>%Y%m%d,upload_date>%Y%m%d)s - %(title).180B [%(extractor)s-%(id)s].%(ext)s" + } + + # Execute yt-dlp command for non-rejected videos + try { + Write-Warning -Message "Dwnld $Id ##### $Title" + + Download-YTDLP -videoUrl $videoUrl -OutputPath $outputPath -RejectString $RejectString + $DownloadSuccessful = $true # Set flag to true if download completes successfully + + } + catch { + $DownloadError = $true + Write-Error "Failed to download $Id - $_" + $DownloadSuccessful = $false # Ensure failure is tracked + } + + + If ($DownloadSuccessful -eq $false) { + # If the initial download failed, attempt with cookies + try { + Write-Warning -Message "Dwnld (Cookies Attempt) $Id ##### $Title" + Download-YTDLP -videoUrl $videoUrl -OutputPath $outputPath -RejectString $RejectString -WithCookies + $DownloadSuccessful = $true # Set flag to true if the second attempt succeeds + } + catch { + $DownloadError = $true + Write-Error "Failed to download $Id (Cookies Attempt) - $_" + $DownloadSuccessful = $false + } + } + + if ($isShort -and $DownloadSuccessful) { + $shortDirPath = Split-Path $outputPath -Parent # Gets the directory path (e.g., \RegulationPodcast\YouTube Shorts\...) + Manage-ShortTracking -ShortDirPath $shortDirPath -VideoId $Id -IsNewDownload:$true + } + } + # Log the end of the process + Write-Verbose -Message "End $Id ##### $Title" +} \ No newline at end of file diff --git a/yt-dlp/Download-YTDLP.ps1 b/yt-dlp/Download-YTDLP.ps1 new file mode 100644 index 0000000..6f22972 --- /dev/null +++ b/yt-dlp/Download-YTDLP.ps1 @@ -0,0 +1,45 @@ +function Download-YTDLP { + Param( + [Parameter(Mandatory=$true)] + [string]$videoUrl, + + [Parameter(Mandatory=$true)] + [string]$OutputPath, + + [string]$RejectString, + + [switch]$WithCookies + ) + + $ytDlpPath = "D:\yt-dlp\yt-dlp.exe" + + # Start building an array of arguments using strict comma separation (Recommended format) + $arguments = @( + $videoUrl, + "--write-info-json", + "--write-thumbnail", + "--convert-thumbnails", "jpg", + "--no-progress", + "-t", "sleep", + "--rate-limit", "5M", + "-o", $OutputPath, + '-f', "bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best", + "-S", "vcodec:h264", + "--reject-title", $RejectString, + "--playlist-reverse" + ) + + # --- Conditional Logic Applied Here --- + if ($WithCookies) { + Write-Verbose "--- Using browser cookies for download. ---" -Verbose + $arguments += "--cookies-from-browser", "firefox" # Added comma here too + } else { + Write-Verbose "--- Downloading without specific cookie credentials. ---" -Verbose + } + + # Execute yt-dlp using the call operator (&) and passing the arguments array (@) + & $ytDlpPath $arguments +} + +# Example Usage: +# Download-Video -videoUrl "URL_HERE" -OutputPath "./output" -WithCookies \ No newline at end of file