Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 144 additions & 8 deletions project-downloader.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ $WEBSITE_CONFIG = @{
}
AssetBaseUrl = { param($id) return "https://html-classic.itch.zone/html/$id/assets" }
Method = "embedded_or_json"
Unpackager = "https://turbowarp.github.io/unpackager/" # Most of the time Turbowarp unpackager works.
Unpackager = "https://turbowarp.github.io/unpackager/"
}
"scratch" = @{
Aliases = @("scratch.mit.edu", "turbowarp.org")
Expand Down Expand Up @@ -96,6 +96,16 @@ function Get-WebsiteConfig {
return $null
}

function Is-ValidUrl {
param([string]$Url)
try {
$uri = [System.Uri]$Url
return $uri.Scheme -in @('http', 'https')
} catch {
return $false
}
}

function Download-ScratchAssets {
param(
[string]$JsonFile,
Expand Down Expand Up @@ -132,7 +142,7 @@ function Download-Assets {
[string]$JsonFile,
[string]$BaseUrl,
[string]$AssetsDir,
[string]$AssetType # "costumes" or "sounds"
[string]$AssetType
)

$json = Get-Content $JsonFile -Raw | ConvertFrom-Json -AsHashtable
Expand Down Expand Up @@ -183,12 +193,139 @@ if ([string]::IsNullOrWhiteSpace($INPUT_URL)) {
$websiteInfo = Get-WebsiteConfig $INPUT_URL

if ($null -eq $websiteInfo) {
Write-Red "✗ Unrecognized URL format."
Write-Yellow "Supported websites:"
foreach ($site in $WEBSITE_CONFIG.GetEnumerator()) {
Write-Yellow " • $($site.Value.Aliases -join ', ')"
# Fallback: Try to use the URL as a direct HTML project
Write-Yellow "`n⚠ URL not found in website configuration."

if (Is-ValidUrl $INPUT_URL) {
Write-Yellow "Attempting to use URL as direct HTML project..."

$headers = @{ "User-Agent" = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:124.0) Gecko/20100101 Firefox/124.0" }

try {
$PAGE_HTML = (Invoke-WebRequest -Uri $INPUT_URL -Headers $headers -UseBasicParsing -ErrorAction Stop).Content
} catch {
Write-Red "✗ Failed to fetch the page: $_"
Write-Yellow "`nSupported websites:"
foreach ($site in $WEBSITE_CONFIG.GetEnumerator()) {
Write-Yellow " • $($site.Value.Aliases -join ', ')"
}
exit 1
}

if ([string]::IsNullOrWhiteSpace($PAGE_HTML)) {
Write-Red "✗ Failed to fetch the page (empty response)."
exit 1
}

Write-Green "✓ Successfully fetched HTML from URL"

# Generate a short hash from the URL for filenames
$urlHashBytes = [System.Security.Cryptography.MD5]::Create().ComputeHash([System.Text.Encoding]::UTF8.GetBytes($INPUT_URL))
$urlHash = ($urlHashBytes | ForEach-Object { $_.ToString("x2") }) -join ""
$urlHash = $urlHash.Substring(0, 8)

if ($PAGE_HTML -match '<script data=') {
# Type A: project data embedded in HTML
Write-Yellow "`n→ Detected embedded project (data inside HTML)."
Write-Blue " Saving HTML file..."

$SAVE_PATH = Join-Path (Get-Location) "project_fallback_$urlHash.html"
$PAGE_HTML | Out-File -FilePath $SAVE_PATH -Encoding UTF8

Write-Green "✓ Saved to: $SAVE_PATH"
Write-Yellow "`n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
Write-Yellow " This HTML file was downloaded from an unrecognized source."
Write-Yellow " To unpack this project, upload the saved HTML file to:"
Write-Green " https://turbowarp.github.io/unpackager/"
Write-Yellow "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`n"

} elseif ($PAGE_HTML -match 'assets/project\.json') {
# Type B: project.json + assets relative to the page URL
Write-Blue "`n→ Detected downloadable project (project.json + assets)."

# Derive asset base URL from the page URL (strip filename, append assets/)
$pageBaseUrl = $INPUT_URL.Substring(0, $INPUT_URL.LastIndexOf('/'))
$ASSETS_BASE_URL = "$pageBaseUrl/assets"
$PROJECT_JSON_URL = "$ASSETS_BASE_URL/project.json"

Write-Blue " Assets URL : $ASSETS_BASE_URL"

$WORK_DIR = Join-Path (Get-Location) "project_fallback_$urlHash"
New-Item -ItemType Directory -Path $WORK_DIR -Force | Out-Null

$JSON_FILE = Join-Path $WORK_DIR "project.json"
Write-Blue "`n→ Downloading project.json..."

try {
Invoke-WebRequest -Uri $PROJECT_JSON_URL -OutFile $JSON_FILE -UseBasicParsing -ErrorAction Stop
} catch {
Write-Red "✗ Failed to download project.json: $_"
exit 1
}

if (-not (Validate-File $JSON_FILE)) { exit 1 }
Write-Green "✓ project.json downloaded"

$ASSETS_DIR = Join-Path $WORK_DIR "assets"
New-Item -ItemType Directory -Path $ASSETS_DIR -Force | Out-Null

Write-Blue "`nDownloading costumes..."
Download-Assets -JsonFile $JSON_FILE -BaseUrl $ASSETS_BASE_URL -AssetsDir $ASSETS_DIR -AssetType "costumes"

Write-Blue "`nDownloading sounds..."
Download-Assets -JsonFile $JSON_FILE -BaseUrl $ASSETS_BASE_URL -AssetsDir $ASSETS_DIR -AssetType "sounds"

Write-Green "`n✓ Asset download complete!`n"

Write-Host "Do you want to create an .sb3 file? (y/n): " -ForegroundColor Cyan -NoNewline
$create_zip = Read-Host

if ($create_zip -match '^[Yy]$') {
$ZIP_FILENAME = Prompt-Input "Enter sb3 filename" "project_$urlHash.sb3"

if ($ZIP_FILENAME -notmatch '\.') {
$ZIP_FILENAME = "$ZIP_FILENAME.sb3"
Write-Blue "No extension provided, using: $ZIP_FILENAME"
}

Write-Blue "`nCreating sb3 file..."

$TEMP_ZIP_DIR = Join-Path ([System.IO.Path]::GetTempPath()) ([System.IO.Path]::GetRandomFileName())
New-Item -ItemType Directory -Path $TEMP_ZIP_DIR -Force | Out-Null

try {
Copy-Item $JSON_FILE (Join-Path $TEMP_ZIP_DIR "project.json")
foreach ($f in (Get-ChildItem $ASSETS_DIR -File -ErrorAction SilentlyContinue)) {
Copy-Item $f.FullName (Join-Path $TEMP_ZIP_DIR $f.Name)
}
$OUTPUT_ZIP = Join-Path (Get-Location) $ZIP_FILENAME
Compress-Archive -Path "$TEMP_ZIP_DIR\*" -DestinationPath $OUTPUT_ZIP -Force
$zip_size = "{0:N2} MB" -f ((Get-Item $OUTPUT_ZIP).Length / 1MB)
Write-Green "✓ SB3 created: $OUTPUT_ZIP ($zip_size)"
} catch {
Write-Red "✗ Failed to create sb3 file: $_"
} finally {
Remove-Item $TEMP_ZIP_DIR -Recurse -Force -ErrorAction SilentlyContinue
}
}

} else {
Write-Red "✗ Could not determine project type from the page."
Write-Yellow " The page may use an unsupported packaging format."
exit 1
}

Write-Green "`nDone!"
exit 0

} else {
Write-Red "✗ Invalid URL format."
Write-Yellow "Supported websites:"
foreach ($site in $WEBSITE_CONFIG.GetEnumerator()) {
Write-Yellow " • $($site.Value.Aliases -join ', ')"
}
exit 1
}
exit 1
}

$siteName = $websiteInfo.Name
Expand Down Expand Up @@ -369,7 +506,6 @@ if ($PAGE_HTML -match '<script data=') {

Write-Green "`n✓ Asset download complete!`n"

# SB3 creation block (same as the existing one — paste it here)
Write-Host "Do you want to create an .sb3 file? (y/n): " -ForegroundColor Cyan -NoNewline
$create_zip = Read-Host
if ($create_zip -match '^[Yy]$') {
Expand Down
130 changes: 123 additions & 7 deletions project-downloader.sh
Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,129 @@ fi
SITE_ID=$(get_site_id "$INPUT_URL")

if [[ -z "$SITE_ID" ]]; then
write_red "✗ Unrecognized URL format."
write_yellow "Supported websites:"
for site_id in "${SITES[@]}"; do
aliases_var="SITE_${site_id}_ALIASES"
write_yellow " • ${!aliases_var}"
done
exit 1
write_yellow "\n⚠ URL not found in website configuration."

# Validate that it at least looks like an http(s) URL
if [[ "$INPUT_URL" =~ ^https?:// ]]; then
write_yellow "Attempting to use URL as direct HTML project..."

PAGE_HTML=$(curl -s -f -L \
-A "Mozilla/5.0 (X11; Linux x86_64; rv:124.0) Gecko/20100101 Firefox/124.0" \
"$INPUT_URL")

if [[ $? -ne 0 || -z "$PAGE_HTML" ]]; then
write_red "✗ Failed to fetch the page."
write_yellow "\nSupported websites:"
for site_id in "${SITES[@]}"; do
aliases_var="SITE_${site_id}_ALIASES"
write_yellow " • ${!aliases_var}"
done
exit 1
fi

write_green "✓ Successfully fetched HTML from URL"

URL_HASH=$(echo -n "$INPUT_URL" | md5sum | cut -c1-8)

if echo "$PAGE_HTML" | grep -q '<script data='; then
# Type A: project data embedded in HTML
write_yellow "\n→ Detected embedded project (data inside HTML)."
write_blue " Saving HTML file..."

SAVE_PATH="$(pwd)/project_fallback_${URL_HASH}.html"
echo "$PAGE_HTML" > "$SAVE_PATH"

write_green "✓ Saved to: $SAVE_PATH"
write_yellow "\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
write_yellow " This HTML file was downloaded from an unrecognized source."
write_yellow " To unpack this project, upload the saved HTML file to:"
write_green " https://turbowarp.github.io/unpackager/"
write_yellow "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"

elif echo "$PAGE_HTML" | grep -q 'assets/project\.json'; then
# Type B: project.json + assets relative to the page URL
write_blue "\n→ Detected downloadable project (project.json + assets)."

# Derive asset base URL from the page URL (strip filename, append assets/)
PAGE_BASE_URL="${INPUT_URL%/*}"
ASSETS_BASE_URL="${PAGE_BASE_URL}/assets"
PROJECT_JSON_URL="${ASSETS_BASE_URL}/project.json"

write_blue " Assets URL : $ASSETS_BASE_URL"

WORK_DIR="$(pwd)/project_fallback_${URL_HASH}"
mkdir -p "$WORK_DIR"

JSON_FILE="${WORK_DIR}/project.json"
write_blue "\n→ Downloading project.json..."

if ! curl -s -f -o "$JSON_FILE" "$PROJECT_JSON_URL"; then
write_red "✗ Failed to download project.json"
exit 1
fi

validate_file "$JSON_FILE" || exit 1
write_green "✓ project.json downloaded"

ASSETS_DIR="${WORK_DIR}/assets"
mkdir -p "$ASSETS_DIR"

write_blue "\nDownloading costumes..."
download_assets "$JSON_FILE" "$ASSETS_BASE_URL" "$ASSETS_DIR" "costumes"

write_blue "\nDownloading sounds..."
download_assets "$JSON_FILE" "$ASSETS_BASE_URL" "$ASSETS_DIR" "sounds"

write_green "\n✓ Asset download complete!\n"

echo -ne "${CYAN}Do you want to create an .sb3 file? (y/n): ${NC}"
read create_zip

if [[ "$create_zip" =~ ^[Yy]$ ]]; then
ZIP_FILENAME=$(prompt_input "Enter sb3 filename" "project_${URL_HASH}.sb3")

if [[ "$ZIP_FILENAME" != *.* ]]; then
ZIP_FILENAME="${ZIP_FILENAME}.sb3"
write_blue "No extension provided, using: $ZIP_FILENAME"
fi

write_blue "\nCreating sb3 file..."

TEMP_ZIP_DIR=$(mktemp -d)
trap "rm -rf $TEMP_ZIP_DIR" EXIT

cp "$JSON_FILE" "${TEMP_ZIP_DIR}/project.json"
for f in "$ASSETS_DIR"/*; do
[[ -f "$f" ]] && cp "$f" "$TEMP_ZIP_DIR/"
done

OUTPUT_ZIP="$(pwd)/${ZIP_FILENAME}"

if (cd "$TEMP_ZIP_DIR" && zip -r "$OUTPUT_ZIP" .); then
ZIP_SIZE=$(du -sh "$OUTPUT_ZIP" | cut -f1)
write_green "✓ SB3 created: $OUTPUT_ZIP ($ZIP_SIZE)"
else
write_red "✗ Failed to create sb3 file"
fi
fi

else
write_red "✗ Could not determine project type from the page."
write_yellow " The page may use an unsupported packaging format."
exit 1
fi

write_green "\nDone!"
exit 0
else
write_red "✗ Invalid URL format."
write_yellow "Supported websites:"
for site_id in "${SITES[@]}"; do
aliases_var="SITE_${site_id}_ALIASES"
write_yellow " • ${!aliases_var}"
done
exit 1
fi
fi

aliases_var="SITE_${SITE_ID}_ALIASES"
Expand Down
Loading