# === Copyright (C) 20XX "PS.Wrangler" by zetod1ce [github.com/ztd38f] === # <# [!] ДИСКЛЕЙМЕР [!] Автор полностью отказывается от какой-либо ответственности за использование данного скрипта. Скрипт предоставляется "КАК ЕСТЬ", может быть изменён или дополнен в любое время без уведомления. Использование допускается только для личного обучения в строго контролируемой среде под надзором профессионалов. Всё использование осуществляется исключительно на ваш страх и риск. [!] DISCLAIMER [!] The author fully disclaims any responsibility for the use of this script. The script is provided "AS IS" and may be changed or updated at any time without notice. Use is permitted only for personal educational purposes in a strictly controlled environment under professional supervision. All use is entirely at your own risk. #> function PS.Wrangler { # -- Console UI Settings -- # $InformationPreference = $ErrorActionPreference = $WarningPreference = $ProgressPreference = $VerbosePreference = 0 $OutputEncoding = [Text.Encoding]::UTF8 [console]::Title = "PS.Wrangler [github.com/ztd38f]" [console]::SetWindowSize(80, 25) [console]::SetBufferSize(80, 25) [console]::BackgroundColor = "Black" [console]::ForegroundColor = "White" Cls # -- Update Environment Variables For Current User -- # function Update-UserVars { $ConsoleUser = ([Security.Principal.WindowsIdentity]::GetCurrent().Name.Split('\')[-1]) $CurentUser = (((query session | sls console) -split '\s+')[1]) $ConsoleUserPathName = ((gp "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$((New-Object Security.Principal.NTAccount($ConsoleUser)).Translate([Security.Principal.SecurityIdentifier]).Value)").ProfileImagePath).Split('\',2)[1] $CurentUserPathName = ((gp "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$((New-Object Security.Principal.NTAccount($CurentUser)).Translate([Security.Principal.SecurityIdentifier]).Value)").ProfileImagePath).Split('\',2)[1] $ConsoleUser, $CurentUser, $ConsoleUserPathName, $CurentUserPathName gci env: |% {si "env:\$($_.Name)" ($_.Value -replace [regex]::Escape($ConsoleUserPathName), $CurentUserPathName -replace [regex]::Escape($ConsoleUser), $CurentUser)} }; Update-UserVars function Create-IndexJs([string]$filePath, [string]$url) { $dir = Split-Path -Parent $filePath if (!(Test-Path $dir)) {ni -ItemType Directory -Path $dir -force | Out-Null} if ([string]::IsNullOrWhiteSpace($url)) {Write-Host "URL is empty!" -f Red; return $false} try { $js = "export async function onRequest(c){const hash='?' + Math.floor(Math.random()*1e6),r=await fetch('$url', {redirect:'follow'}),url=new URL(r.url);url.search=hash;return Response.redirect(url.toString(),302);}" Set-Content -Path $filePath -Value $js -Encoding UTF8 return $true } catch {Write-Host "Error generating index.js!" -f Red; return $false} } function Clear-TempDir([string]$path) { if ([string]::IsNullOrWhiteSpace($path)) {Write-Host "Folder for cleanup not specified." -f Yellow; return} if (Test-Path $path) {try {rd -Path $path -Recurse -force -ea 0} catch {}} } function Setup-NodeAndWrangler { $nodeInstalled = $false try { Write-Host "Installing Node.js..." -f Cyan & winget install openjs.nodejs --silent Write-Host "Node.js installed." -f Green $nodeInstalled = $true } catch {Write-Host "Node.js installation failed!" -f Red} if ($nodeInstalled) { try { Write-Host "Installing Wrangler..." -f Cyan & npm install -g wrangler@latest Write-Host "Wrangler installed." -f Green } catch {Write-Host "Wrangler installation failed!" -f Red} } } function Verify-ProjectName([string]$name) { $ErrorActionPreference = 2 $domain = "$name.pages.dev" try { Write-Host "Checking $domain" -f Cyan $result = ((nslookup $domain 2>&1) -join "`n") if ($result -match "Non-existent domain") {Write-Host "Name is available." -f Green; return $true} else {Write-Host "Name is taken!" -f Red; return $false} } catch {Write-Host "Error checking domain!" -f Red; return $false} $ErrorActionPreference = 0 } function Run-WranglerDeploy([string]$projName, [string]$projDir) { if (!(Test-Path $projDir)) {Write-Host "Deployment folder missing: $projDir!" -f Red; return $false} $cmd = "wrangler pages deploy . --project-name '$projName' --branch main --commit-dirty true --skip-caching true" do { try { Push-Location $projDir Invoke-Expression $cmd Pop-Location Write-Host "Deployment completed." -f Green Write-Host "Press any key to continue..." -f Yellow $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") return $true } catch { Write-Host "Deployment error!" -f Red Write-Host "Installing Node.js & Wrangler..." -f Yellow Setup-NodeAndWrangler Write-Host "Retrying deployment..." -f Cyan } } while ($true) } function Read-Host-BackspaceAble([string]$prompt, [string]$color) { Write-Host; Write-Host $prompt -n -f $color $input = "" while ($true) { $key = [Console]::ReadKey($true) switch ($key.Key) { 'Y' {Write-Host "Yes" -f Green; return "Y"} 'Enter' {Write-Host "Yes" -f Green; return "Y"} 'N' {Write-Host "No" -f Red; return "N"} 'Backspace' {Write-Host "Restart" -f Magenta; return $null} default {$input += $key.KeyChar; Write-Host $key.KeyChar -n} } } } function Show-Header { Clear-Host Write-Host "==================" -f Magenta Write-Host " Project Deploy " -f Magenta Write-Host "==================" -f Magenta } do { Show-Header $tempDir = if ([string]::IsNullOrEmpty($tempDir)) { $tempPath = Join-Path $env:TEMP "ps-wrangler" try {if (!(Test-Path $tempPath)) {ni -ItemType Directory -Path $tempPath -force | Out-Null}} catch { $fallbackPath = Join-Path $env:ProgramData "ps-wrangler" if (!(Test-Path $fallbackPath)) {ni -ItemType Directory -Path $fallbackPath -force | Out-Null} Write-Host "Failed to create temp in $env:TEMP, using $env:ProgramData" -f Yellow } $tempPath } else {$tempDir} if (!(Test-Path $tempDir)) {ni -ItemType Directory -Path $tempDir -force | Out-Null} $restart = $false $nameValid = $false while (!($nameValid)) { $projName = "" while ([string]::IsNullOrWhiteSpace($projName) -or $projName -notmatch '^[a-zA-Z0-9\-]+$') { Write-Host; Write-Host "Enter project name: " -f Yellow -n; $projName = Read-Host if ($null -eq $projName) {$restart = $true; break} if ([string]::IsNullOrWhiteSpace($projName)) {Write-Host "Name is required!" -f Red} elseif ($projName -notmatch '^[a-zA-Z0-9\-]+$') {Write-Host "Invalid name! Only letters, numbers, and hyphens are allowed!" -f Red} } if ($restart) {break} $invalidChars = try {[IO.Path]::GetInvalidFileNameChars() |% {[Regex]::Escape($_)}} catch {'[\\/:\*\?"<>|]'} $projName = ($projName -replace ($invalidChars -join '|'), '-').Trim('-').ToLower() if ([string]::IsNullOrEmpty($projName)) {Write-Host "Invalid name. Restart!" -f Red; continue} $isAvailable = Verify-ProjectName $projName if (!($isAvailable)) { $continue = Read-Host-BackspaceAble "Use anyway? [y/n]: " Yellow if ($continue -eq $null) {$restart = $true; break} if ([string]::IsNullOrWhiteSpace($continue)) {$continue = "Y"} if ($continue.ToUpper() -ne "Y") {Show-Header; continue} } $nameValid = $true } if ($restart) {continue} $redirectUrl = "" while ([string]::IsNullOrWhiteSpace($redirectUrl)) { Write-Host "`nEnter URL for index.js: " -n -f Yellow; $redirectUrl = Read-Host if ($null -eq $redirectUrl) {$restart = $true; break} if ([string]::IsNullOrWhiteSpace($redirectUrl)) {Write-Host "URL is required!" -f Red} } if ($restart) {continue} $projDir = Join-Path $tempDir $projName $funcDir = Join-Path $projDir "functions" try { if (Test-Path $projDir) {rd -Path $projDir -Recurse -force -ea 0} if (!(Test-Path $funcDir)) {ni -ItemType Directory -Path $funcDir -force | Out-Null} $indexFile = Join-Path $funcDir "index.js" if (!(Create-IndexJs $indexFile $redirectUrl)) {Clear-TempDir $tempDir; return} } catch { Write-Host "Project structure error: $_!" -f Red Clear-TempDir $tempDir return } Run-WranglerDeploy $projName $projDir Clear-TempDir $tempDir Write-Host "Temp folder cleared." -f Yellow } while ($true) }; PS.Wrangler