Get-Download.psm1

#Requires -Version 5.0

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

$CachePath = Join-Path -Path $env:APPDATA -ChildPath "Get-Download\PRIVATE"
$YtDlpExe = Join-Path -Path $CachePath -ChildPath "yt-dlp.exe"
$YtDlpDownloadUrl = "https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.exe"
$ModulePath = $PSScriptRoot
$GitHubRawUrl = "https://raw.githubusercontent.com/Goodwintek/Get-Download/main"

function Initialize-YtDlp {
    if (Test-Path -Path $YtDlpExe -PathType Leaf) {
        return $true
    }

    if (-not (Test-Path -Path $CachePath -PathType Container)) {
        New-Item -ItemType Directory -Path $CachePath -Force | Out-Null
    }

    try {
        Write-Host "Downloading yt-dlp.exe..."
        Invoke-WebRequest -Uri $YtDlpDownloadUrl -OutFile $YtDlpExe -ErrorAction Stop
        Write-Host "yt-dlp.exe downloaded successfully."
        return $true
    } catch {
        [System.Windows.Forms.MessageBox]::Show("Failed to download yt-dlp.exe: $($_.Exception.Message)", "Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
        return $false
    }
}

function Update-GetDownload {
    [CmdletBinding()]
    param()

    $result = [System.Windows.Forms.MessageBox]::Show("This will update Get-Download module and yt-dlp. Continue?", "Update", [System.Windows.Forms.MessageBoxButtons]::YesNo, [System.Windows.Forms.MessageBoxIcon]::Question)
    
    if ($result -ne [System.Windows.Forms.DialogResult]::Yes) {
        return
    }

    try {
        Write-Host "Updating Get-Download module..."

        $psd1Url = "$GitHubRawUrl/Get-Download.psd1"
        $psm1Url = "$GitHubRawUrl/Get-Download.psm1"
        $psd1Path = Join-Path -Path $ModulePath -ChildPath "Get-Download.psd1"
        $psm1Path = Join-Path -Path $ModulePath -ChildPath "Get-Download.psm1"

        Invoke-WebRequest -Uri $psd1Url -OutFile $psd1Path -ErrorAction Stop
        Invoke-WebRequest -Uri $psm1Url -OutFile $psm1Path -ErrorAction Stop

        Write-Host "Module updated successfully."

        if (Test-Path -Path $YtDlpExe -PathType Leaf) {
            Write-Host "Updating yt-dlp.exe..."
            & $YtDlpExe -U | Out-Null
            Write-Host "yt-dlp.exe updated successfully."
        }

        [System.Windows.Forms.MessageBox]::Show("Update complete. Application will restart.", "Success", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information)

        $global:RestartApp = $true
    } catch {
        [System.Windows.Forms.MessageBox]::Show("Update failed: $($_.Exception.Message)", "Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
        Write-Host "Update error: $_"
    }
}

function Get-Download {
    [CmdletBinding()]
    param(
        [string]$DefaultOutputPath = "",
        [switch]$U
    )

    if ($U) {
        Update-GetDownload
        return
    }

    if (-not (Initialize-YtDlp)) {
        return
    }

    if (-not (Test-Path -Path $YtDlpExe -PathType Leaf)) {
        throw "yt-dlp.exe not found at: $YtDlpExe"
    }

    do {
        $global:RestartApp = $false

        $form = New-Object System.Windows.Forms.Form
        $form.Text = "yt-dlp Downloader"
        $form.Width = 400
        $form.Height = 280
        $form.StartPosition = [System.Windows.Forms.FormStartPosition]::CenterScreen

        $menuStrip = New-Object System.Windows.Forms.MenuStrip
        $helpMenu = New-Object System.Windows.Forms.ToolStripMenuItem
        $helpMenu.Text = "Help"
        $updateItem = New-Object System.Windows.Forms.ToolStripMenuItem
        $updateItem.Text = "Check for Updates"
        $updateItem.Add_Click({ Update-GetDownload })
        $helpMenu.DropDownItems.Add($updateItem) | Out-Null
        $menuStrip.Items.Add($helpMenu) | Out-Null
        $form.Controls.Add($menuStrip)
        $form.MainMenuStrip = $menuStrip

        $urlLabel = New-Object System.Windows.Forms.Label
        $urlLabel.Location = New-Object System.Drawing.Point(10, 35)
        $urlLabel.AutoSize = $true
        $urlLabel.Text = "Playlist URL:"
        $form.Controls.Add($urlLabel)

        $script:urlTextBox = New-Object System.Windows.Forms.TextBox
        $script:urlTextBox.Location = New-Object System.Drawing.Point(100, 32)
        $script:urlTextBox.Width = 245
        $script:urlTextBox.Add_KeyDown({
            if ($_.Control -and $_.KeyCode -eq [System.Windows.Forms.Keys]::A) {
                $script:urlTextBox.SelectAll()
                $_.SuppressKeyPress = $true
            }
        })
        $script:urlTextBox.Add_DoubleClick({
            $script:urlTextBox.SelectAll()
        })
        $form.Controls.Add($script:urlTextBox)

        $clearUrlButton = New-Object System.Windows.Forms.Button
        $clearUrlButton.Location = New-Object System.Drawing.Point(350, 30)
        $clearUrlButton.Width = 30
        $clearUrlButton.Height = 22
        $clearUrlButton.Text = "X"
        $clearUrlButton.Add_Click({
            $script:urlTextBox.Clear()
            $script:urlTextBox.Focus()
        })
        $form.Controls.Add($clearUrlButton)

        $audioOnlyCheckBox = New-Object System.Windows.Forms.CheckBox
        $audioOnlyCheckBox.Location = New-Object System.Drawing.Point(10, 70)
        $audioOnlyCheckBox.AutoSize = $true
        $audioOnlyCheckBox.Text = "Extract Audio Only (-x)"
        $form.Controls.Add($audioOnlyCheckBox)

        $sslFixCheckBox = New-Object System.Windows.Forms.CheckBox
        $sslFixCheckBox.Location = New-Object System.Drawing.Point(10, 95)
        $sslFixCheckBox.AutoSize = $true
        $sslFixCheckBox.Text = "SSL Error Fix (legacy TLS + skip cert check)"
        $form.Controls.Add($sslFixCheckBox)

        $ffmpegHlsCheckBox = New-Object System.Windows.Forms.CheckBox
        $ffmpegHlsCheckBox.Location = New-Object System.Drawing.Point(10, 120)
        $ffmpegHlsCheckBox.AutoSize = $true
        $ffmpegHlsCheckBox.Text = "HLS via ffmpeg (fixes CDN m3u8 SSL/stream errors)"
        $form.Controls.Add($ffmpegHlsCheckBox)

        $outputLabel = New-Object System.Windows.Forms.Label
        $outputLabel.Location = New-Object System.Drawing.Point(10, 155)
        $outputLabel.AutoSize = $true
        $outputLabel.Text = "Output Folder:"
        $form.Controls.Add($outputLabel)

        $script:outputTextBox = New-Object System.Windows.Forms.TextBox
        $script:outputTextBox.Location = New-Object System.Drawing.Point(100, 152)
        $script:outputTextBox.Width = 200
        if ($DefaultOutputPath) {
            $script:outputTextBox.Text = $DefaultOutputPath
        }
        $form.Controls.Add($script:outputTextBox)

        $browseButton = New-Object System.Windows.Forms.Button
        $browseButton.Location = New-Object System.Drawing.Point(305, 150)
        $browseButton.Text = "Browse"
        $browseButton.Add_Click({
            $folderBrowserDialog = New-Object System.Windows.Forms.FolderBrowserDialog
            $folderBrowserDialog.Description = "Select the output folder"
            if (-not [string]::IsNullOrEmpty($script:outputTextBox.Text) -and (Test-Path $script:outputTextBox.Text)) {
                $folderBrowserDialog.SelectedPath = $script:outputTextBox.Text
            }
            if ($folderBrowserDialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {
                $script:outputTextBox.Text = $folderBrowserDialog.SelectedPath
            }
        })
        $form.Controls.Add($browseButton)

        $downloadButton = New-Object System.Windows.Forms.Button
        $downloadButton.Location = New-Object System.Drawing.Point(150, 210)
        $downloadButton.Text = "Download"
        $downloadButton.Add_Click({
            $url = $script:urlTextBox.Text
            $outputDir = $script:outputTextBox.Text
            $audioOnly = $audioOnlyCheckBox.Checked
            $sslFix = $sslFixCheckBox.Checked
            $ffmpegHls = $ffmpegHlsCheckBox.Checked

            if ([string]::IsNullOrEmpty($url) -or [string]::IsNullOrEmpty($outputDir)) {
                [System.Windows.Forms.MessageBox]::Show("Please enter a URL and select an output folder.", "Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
                return
            }

            if (-not (Test-Path $outputDir)) {
                try {
                    New-Item -ItemType Directory -Path $outputDir -Force | Out-Null
                } catch {
                    [System.Windows.Forms.MessageBox]::Show("Could not create folder: $outputDir`n$($_.Exception.Message)", "Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
                    return
                }
            }

            if ($ffmpegHls) {
                $argString = "--output `"$outputDir\%(title)s.%(ext)s`" --merge-output-format mp4"
            } else {
                $argString = "--output `"$outputDir\%(title)s.%(ext)s`" --embed-metadata"
            }
            if ($audioOnly) { $argString += " -x" }
            if ($sslFix) { $argString += " --legacy-server-connect --no-check-certificate" }
            if ($ffmpegHls) { $argString += " --downloader m3u8:ffmpeg --downloader-args `"ffmpeg:-protocol_whitelist file,http,https,tcp,tls,crypto`"" }
            $argString += " `"$url`""

            Write-Host "Running: $YtDlpExe $argString"

            try {
                $proc = & (Get-Command Start-Process) -FilePath $YtDlpExe -ArgumentList $argString -NoNewWindow -Wait -PassThru
                if ($proc.ExitCode -eq 0) {
                    Write-Host "Download completed."
                    [System.Windows.Forms.MessageBox]::Show("Download completed!", "Success", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information)
                } else {
                    Write-Host "yt-dlp exited with code $($proc.ExitCode)."
                    [System.Windows.Forms.MessageBox]::Show("yt-dlp exited with code $($proc.ExitCode). Check the console for details.", "yt-dlp error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Warning)
                }
            } catch {
                [System.Windows.Forms.MessageBox]::Show("Failed to run yt-dlp: $($_.Exception.Message)", "Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
            }
        })
        $form.Controls.Add($downloadButton)

        $form.ShowDialog() | Out-Null
        $form.Dispose()

        if ($global:RestartApp) {
            Remove-Module Get-Download -Force
            Import-Module $psd1Path -Force
        }
    } while ($global:RestartApp)

    Write-Host ""
}

Export-ModuleMember -Function Get-Download, Update-GetDownload