Skip to content

Instantly share code, notes, and snippets.

@MadeBaruna
Last active July 26, 2024 16:00
Show Gist options
  • Save MadeBaruna/3c92e3dc8e7aff5d2a3f5bfa4e0833f9 to your computer and use it in GitHub Desktop.
Save MadeBaruna/3c92e3dc8e7aff5d2a3f5bfa4e0833f9 to your computer and use it in GitHub Desktop.
Export ZZZ FM history to CSV

Open FM history on ZZZ first, then copy & paste this command to powershell, the CSV will be saved on Documents folder

iex ((New-Object System.Net.WebClient).DownloadString('https://gist.githubusercontent.com/MadeBaruna/3c92e3dc8e7aff5d2a3f5bfa4e0833f9/raw/zzz_import.ps1'))

Banners
1 = Standard Banner - Star-Studded Cast
2 = Character Banner
3 = Weapon Banner
5 = Bangboo Banner - An Outstanding Partner

Add-Type -AssemblyName System.Web
$logLocation = "%userprofile%\AppData\LocalLow\miHoYo\ZenlessZoneZero\Player.log";
$reg = $args[0]
$apiHost = "api-os-takumi.mihoyo.com"
$tmps = $env:TEMP + '\pm.ps1';
if ([System.IO.File]::Exists($tmps)) {
ri $tmps
}
$path = [System.Environment]::ExpandEnvironmentVariables($logLocation);
if (-Not [System.IO.File]::Exists($path)) {
Write-Host "Cannot find the log file! Make sure to open the FM history first!" -ForegroundColor Red
if (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
Write-Host "Do you want to try to run the script as Administrator? Press [ENTER] to continue, or any key to cancel."
$keyInput = [Console]::ReadKey($true).Key
if ($keyInput -ne "13") {
return
}
$myinvocation.mycommand.definition > $tmps
Start-Process powershell -Verb runAs -ArgumentList "-noexit", $tmps, $reg
break
}
return
}
$logs = Get-Content -Path $path
$m = $logs -match "(?m).:/.+ZenlessZoneZero_Data"
$m[0] -match "(.:/.+ZenlessZoneZero_Data)" >$null
if ($matches.Length -eq 0) {
Write-Host "Cannot find the FM history url! Make sure to open the FM history first!" -ForegroundColor Red
return
}
$gamedir = $matches[1]
$webcachePath = Resolve-Path "$gamedir/webCaches"
$cacheVerPath = Get-Item (Get-ChildItem -Path $webcachePath | Sort-Object LastWriteTime -Descending | Select-Object -First 1).FullName
$cachefile = Resolve-Path "$cacheVerPath/Cache/Cache_Data/data_2"
$tmpfile = "$env:TEMP/ch_data_2"
Copy-Item $cachefile -Destination $tmpfile
function testUrl($url) {
$ProgressPreference = 'SilentlyContinue'
$response = Invoke-WebRequest -Uri $url -ContentType "application/json" -UseBasicParsing -TimeoutSec 10 | ConvertFrom-Json
Write-Host $apiUrl
$testResult = $response.retcode -eq 0
return $testResult
}
$content = Get-Content -Encoding UTF8 -Raw $tmpfile
$splitted = $content -split "1/0/"
$found = $splitted -match "/getGachaLog"
$link = $false
$linkFound = $false
for ($i = $found.Length - 1; $i -ge 0; $i -= 1) {
$t = $found[$i] -match "(https.+?end_id=)"
$link = $matches[0]
Write-Host "`rChecking Link $i" -NoNewline
$testResult = testUrl $link
if ($testResult -eq $true) {
$linkFound = $true
break
}
Sleep 1
}
Remove-Item $tmpfile
Write-Host ""
if (-Not $linkFound) {
Write-Host "Cannot find the FM history url! Make sure to open the FM history first!" -ForegroundColor Red
return
}
function fetch($url) {
$ProgressPreference = 'SilentlyContinue'
$retrycount = 0
$completed = $false
$response = $null
while (-Not $completed) {
try {
$response = Invoke-WebRequest -Uri $url -ContentType "application/json" -UseBasicParsing -TimeoutSec 30
$completed = $true
}
catch {
if ($retrycount -ge 3) {
throw
}
else {
$retrycount++
}
}
}
return $response
}
$banners = [ordered]@{
1 = "Standard Banner - Star-Studded Cast";
2 = "Character Banner";
3 = "Weapon Banner";
5 = "Bangboo Banner - An Outstanding Partner";
}
$uri = [System.UriBuilder]::New($link)
$params = [System.Web.HttpUtility]::ParseQueryString($uri.Query)
$wishes = [System.Collections.ArrayList]@()
function GetBannerLog($code, $type) {
$total = 0
$params = [System.Web.HttpUtility]::ParseQueryString($uri.Query)
$params.Remove("gacha_type")
$params.Set("lang", "en");
$params.Set("real_gacha_type", $code);
$params.Set("size", 20);
$page = 1
$lastList = [System.Collections.ArrayList]@()
$lastId = 0
do {
$params.Set("page", $page)
$params.Set("end_id", $lastId);
$uri.Query = $params.ToString()
$apiUrl = $uri.Uri.AbsoluteUri
Write-Host "`rProcessing $type Banner - Page $page - x$total" -NoNewline
try {
$response = fetch $apiUrl
$result = $response | ConvertFrom-Json
if ($result.retcode -ne 0) {
if ($result.message -eq "authkey timeout") {
Write-Host "Authkey expired, please re-open the Wish History page" -ForegroundColor Red
exit
}
Write-Host "Error code returned from MiHoYo API! Try again later" -ForegroundColor Red
exit
}
$lastList = $result.data.list
foreach ($wish in $result.data.list) {
[void]$wishes.Add(@($wish.id, $wish.uid, $wish.gacha_type, $wish.item_id, $wish.time, $wish.item_type, $wish.rank_type, $wish.name))
}
$total = $total + $result.data.list.Count;
$page++;
if ($result.data.list.Count -gt 0) {
$lastId = $result.data.list[$result.data.list.Count - 1].id
}
else {
$lastId = 0
}
}
catch {
Write-Host "Error when connecting to MiHoYo API! (Check your internet connection)" -ForegroundColor Red
exit
}
Write-Host "`rProcessing $type Banner - Page $page - x$total" -NoNewline
Start-Sleep -Seconds 1
} while ($lastList.Count -ne 0)
}
foreach ($banner in $banners.GetEnumerator()) {
Write-Host ""
GetBannerLog $banner.Name $banner.Value
}
$generated = "id,uid,gacha_type,item_id,time,item_type,rank_type,name`n"
foreach ($w in $wishes) {
$str = $w -join ","
$generated += "$str`n"
}
Write-Host ""
$documentpath = [Environment]::GetFolderPath("MyDocuments")
$time = Get-Date -Format "yyyyMMddHHmm"
$generated | Out-File -FilePath "$documentpath\zzz-import-$time.csv"
Write-Host "CSV saved on $documentpath\zzz-import-$time.csv" -ForegroundColor Green
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment