ffuf.psm1

$Global:ffuf_subdomains_small = Join-Path $PSScriptRoot "wordlists\subdomains-small.txt"
$Global:ffuf_subdomains_medium = Join-Path $PSScriptRoot "wordlists\subdomains-medium.txt"
$Global:ffuf_subdomains_large = Join-Path $PSScriptRoot "wordlists\subdomains-large.txt"
$Global:ffuf_paths = Join-Path $PSScriptRoot "wordlists\paths.txt"
$Global:ffuf_parameters = Join-Path $PSScriptRoot "wordlists\parameters.txt"

function Get-FfufLatestRelease {
    $arch = switch ($env:PROCESSOR_ARCHITECTURE) {
        'AMD64' { 'windows_amd64.zip' }
        'x86'   { 'windows_386.zip' }
        default { throw "❌ Unsupported architecture: $env:PROCESSOR_ARCHITECTURE" }
    }

    $url = "https://api.github.com/repos/ffuf/ffuf/releases/latest"
    $headers = @{ "User-Agent" = "ffuf-installer" }

    $release = Invoke-RestMethod -Uri $url -Headers $headers
    $asset = $release.assets | Where-Object { $_.name -like "*$arch" }

    if (-not $asset) {
        throw "❌ Could not find ffuf binary for architecture '$arch'"
    }

    [PSCustomObject]@{
        Tag    = $release.tag_name
        Url    = $asset.browser_download_url
        Name   = $asset.name
        Arch   = $arch
    }
}


function Install-Ffuf {
    $info       = Get-FfufLatestRelease
    $baseDir    = "$env:USERPROFILE\Tools\ffuf"
    $versionDir = Join-Path $baseDir $info.Tag
    $zipPath    = "$env:TEMP\$($info.Name)"

    if (Test-Path $versionDir) {
        Write-Host "✅ ffuf $($info.Tag) already installed at $versionDir"
        return
    }

    # Ensure directories exist
    if (-not (Test-Path $baseDir)) {
        New-Item -Path $baseDir -ItemType Directory | Out-Null
    }

    New-Item -Path $versionDir -ItemType Directory -Force | Out-Null

    Write-Host "⬇️ Downloading $($info.Name)..."
    Invoke-WebRequest -Uri $info.Url -OutFile $zipPath

    Write-Host "📦 Extracting..."
    Expand-Archive -Path $zipPath -OutputPath $versionDir -Force
    Remove-Item $zipPath

    Write-Host "✅ ffuf installed at $versionDir"

    # Search for ffuf.exe
    $extractedFfuf = Get-ChildItem -Path $versionDir -Recurse -Filter "ffuf.exe" | Select-Object -First 1
    if (-not $extractedFfuf) {
        throw "❌ ffuf.exe not found in extracted archive"
    }

    $staticPath = Join-Path $baseDir "ffuf.exe"
    Copy-Item $extractedFfuf.FullName $staticPath -Force
    Write-Host "🔗 Copied latest ffuf.exe to $staticPath"

    # Add baseDir to PATH if not present
    $userPath = [Environment]::GetEnvironmentVariable("Path", "User")
    if ($userPath -notlike "*$baseDir*") {
        Write-Host "➕ Adding $baseDir to PATH..."
        [Environment]::SetEnvironmentVariable("Path", "$userPath;$baseDir", "User")
        Write-Warning "⚠️ Restart your shell to apply PATH changes"
    } else {
        Write-Host "✅ PATH already includes $baseDir"
    }
}




function Update-Ffuf {
    $info = Get-FfufLatestRelease
    $targetDir = "$env:USERPROFILE\Tools\ffuf\$($info.Tag)"

    if (Test-Path $targetDir) {
        Write-Host "✅ Already running latest version: $($info.Tag)"
    } else {
        Install-Ffuf
    }
}

function Get-FfufWordlists {
    $vars = Get-Variable -Scope Global | Where-Object {
        $_.Name -like 'ffuf_*' -and (Test-Path $_.Value)
    }

    $vars | ForEach-Object {
        $varName = $_.Name
        $fileName = Split-Path -Path $_.Value -Leaf
        $label = [IO.Path]::GetFileNameWithoutExtension($fileName)

        [PSCustomObject]@{
            Variable = '$' + $varName
            Wordlist = $label
            Path     = $_.Value
        }
    }
}

Export-ModuleMember -Function Install-Ffuf, Update-Ffuf, Get-FfufLatestRelease, Get-FfufWordlists