Add-Type -AssemblyName System.Net.Http $url = 'https://apis.roblox.com/assets/v1/assets' $operationUrlBase = 'https://apis.roblox.com/assets/v1/operations' $decalToImage = 'https://f3xteam.com/bt/getDecalImageID/' $apiKey = '' $userId = '' $folderPath = './dumped_frames' if (Test-Path $folderPath) { # Get all files in the folder $files = Get-ChildItem -Path $folderPath # Iterate over each file and display its name foreach ($file in $files) { $fileNameNoExtension = [System.IO.Path]::GetFileNameWithoutExtension($file.Name) $filePath = $file.FullName $requestPayload = @{ assetType = "Decal" displayName = $fileNameNoExtension description = "bulk uploader in powershell no way" creationContext = @{ creator = @{ userId = $userId } } } | ConvertTo-Json $multipartContent = New-Object System.Net.Http.MultipartFormDataContent # Add JSON request part $jsonContent = New-Object System.Net.Http.StringContent -ArgumentList @($requestPayload, [System.Text.Encoding]::UTF8, "application/json") $multipartContent.Add($jsonContent, "request") # Add file part $fileStream = [System.IO.File]::OpenRead($filePath) $fileContent = New-Object System.Net.Http.StreamContent($fileStream) $fileContent.Headers.ContentType = [System.Net.Http.Headers.MediaTypeHeaderValue]::Parse("image/png") $multipartContent.Add($fileContent, "fileContent", [System.IO.Path]::GetFileName($filePath)) # Prepare the HTTP request $httpClient = New-Object System.Net.Http.HttpClient $httpClient.DefaultRequestHeaders.Add("x-api-key", $apiKey) # Send the POST request $response = $httpClient.PostAsync($url, $multipartContent).Result # Output the response $responseContent = $response.Content.ReadAsStringAsync().Result # Write-Output $responseContent # Parse the response to get the operationId $responseJson = $responseContent | ConvertFrom-Json $operationId = $responseJson.operationId # Wait for 5 seconds Start-Sleep -Seconds 1 # Check the operation status $operationUrl = "$operationUrlBase/$operationId" $operationResponse = $httpClient.GetAsync($operationUrl).Result $operationResponseContent = $operationResponse.Content.ReadAsStringAsync().Result $operationResponseJson = $operationResponseContent | ConvertFrom-Json while ($operationResponseJson.done -ne "True") { $operationResponse = $httpClient.GetAsync($operationUrl).Result $operationResponseContent = $operationResponse.Content.ReadAsStringAsync().Result $operationResponseJson = $operationResponseContent | ConvertFrom-Json Write-Output "Operation $fileNameNoExtension is not completed yet." Start-Sleep -Seconds 1 } # Check if the operation is done if ($operationResponseJson.done -eq $true -or $operationResponseJson.response.assetId -ne $null) { $assetId = $operationResponseJson.response.assetId $convertedAssetId = $httpClient.GetAsync("$decalToImage$assetId").Result.Content.ReadAsStringAsync().Result while ($convertedAssetId -match "error") { $convertedAssetId = $httpClient.GetAsync("$decalToImage$assetId").Result.Content.ReadAsStringAsync().Result Write-Output "decal to image failed so lets try that again" Start-Sleep -Seconds 1 } Write-Output "$fileNameNoExtension -> $convertedAssetId" Add-Content -Path "./asset_ids.txt" -Value "$fileNameNoExtension='rbxassetid://$convertedAssetId'" } # Clean up $fileStream.Dispose() $httpClient.Dispose() $multipartContent.Dispose() } } else { Write-Host "Folder not found: $folderPath" }