nurjns icon

Snapchat Snap Map Geotagger

nurjns | PRO | 01/15/26 01:46:02 PM UTC (Edited) | 0 ⭐ | 6195 👁️ | Never ⏰ | []
PowerShell |

7.05 KB

|

None

|

0 👍

/

0 👎

<#
Version 1.0 - 11.07.2025 - @nurjns
 
1. Snapchat Daten-Export: JSON-Datei "json/snap_map_places_history.json" und der Ordner "memories" mit den Snaps werden benötigt.
2. ExifTool wird benötigt: https://exiftool.org/
3. Ausführung in PowerShell:
    cd X:\Pfad\zum\Projektordner
    Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
    .\geotag.ps1
 
Komplette Ordnerstruktur:
 
📁 Projektordner/
├── 📁 exiftool_files/
├── 📁 memories/
│   ├── 2024-04-06_abc123-main.jpg
│   └── ...
├── 📁 json/
│   └── snap_map_places_history.json
├── 📄 exiftool.exe
├── 📄 geotag.ps1
#>
 
# Pfade
$sourceFolder = 'memories'
$targetFolder = 'memories_geotagged'
$jsonFile = 'json\snap_map_places_history.json'
$exiftool = '.\exiftool.exe'
 
# Ordner erstellen, falls nicht vorhanden
if (-not (Test-Path $targetFolder)) {
    New-Item -ItemType Directory -Path $targetFolder | Out-Null
    Write-Host "📁 Zielordner wurde erstellt: $targetFolder"
}
 
# Funktion für Umlaut-Konvertierung
function ConvertUmlautsAndUrlEncode {
    param([string]$str)
    
    # Komma entfernen
    $str = $str -replace ',', ''
 
    # Umlaute ersetzen
    $str = $str -replace 'ü', 'ue'
    $str = $str -replace 'Ü', 'Ue'
    $str = $str -replace 'ä', 'ae'
    $str = $str -replace 'Ä', 'Ae'
    $str = $str -replace 'ö', 'oe'
    $str = $str -replace 'Ö', 'Oe'
    $str = $str -replace 'ß', 'ss'
 
    # Leerzeichen zu %20 (keine weitere URL-Kodierung)
    return $str -replace ' ', '%20'
}
 
# JSON laden mit UTF8-Encoding
$jsonRaw = Get-Content $jsonFile -Raw -Encoding utf8
$json = $jsonRaw | ConvertFrom-Json
$history = $json.'Snap Map Places History'
 
# Alle JPG- und PNG-Dateien laden (ohne -overlay)
$files = Get-ChildItem -Path $sourceFolder | Where-Object {
    $_.Extension -match '^\.(jpg|png)$' -and $_.BaseName -notmatch '-overlay'
}
 
# Startpunkt-Abfrage (Dateiname oder Datum)
$startInput = Read-Host '🔁 Falls du ab einer bestimmten Datei oder einem Datum (YYYY-MM-DD) weitermachen willst, gib es ein (oder Enter für Start ab Anfang)'
$startFound = [string]::IsNullOrWhiteSpace($startInput)
$startAtFile = ''
 
if (-not $startFound) {
    if ($startInput -match '^\d{4}-\d{2}-\d{2}$') {
        # Start per Datum
        $match = $files | Where-Object { $_.BaseName -like "$startInput*" } | Select-Object -First 1
        if ($match) {
            $startAtFile = $match.Name
            Write-Host '📆 Beginne ab erster Datei mit Datum' $startInput ':' $startAtFile
        } else {
            Write-Host '❗️Keine Datei mit Datum' $startInput 'gefunden. Starte trotzdem ganz normal.'
            $startFound = $true
        }
    } else {
        # Start per Dateiname
        if ($files.Name -contains $startInput) {
            $startAtFile = $startInput
        } else {
            Write-Host "❗️Datei '$startInput' wurde im Quellordner nicht gefunden. Starte trotzdem ganz normal."
            $startFound = $true
        }
    }
}
 
# Verarbeitung starten
foreach ($file in $files) {
    if (-not $startFound) {
        if ($file.Name -eq $startAtFile) {
            $startFound = $true
        } else {
            continue
        }
    }
 
    Write-Host "`n➡️ Verarbeite Datei: $($file.Name)"
 
    # Ziel-Datei prüfen
    $targetFile = Join-Path $targetFolder ($file.BaseName + '_geotagged.jpg')
    if (Test-Path $targetFile) {
        Write-Host "⚠️  $($file.Name) wurde bereits verarbeitet. Überspringe."
        continue
    }
 
    # Datum aus Dateiname extrahieren
    $datePart = $file.BaseName -split '_' | Select-Object -First 1
    if (-not ($datePart -match '^\d{4}-\d{2}-\d{2}$')) {
        Write-Host "❌ Ungültiges Datumsformat im Dateinamen: $($file.Name)"
        continue
    }
 
    # Einträge für Datum filtern
    $matchingEntries = $history | Where-Object { ($_.Date -split ' ')[0] -eq $datePart }
    if ($matchingEntries.Count -eq 0) {
        Write-Host "❌ Keine Einträge für $($file.Name) gefunden."
        continue
    }
 
    # Foto öffnen (Standardprogramm)
    $photoProcess = Start-Process -FilePath $file.FullName -PassThru
 
    if ($matchingEntries.Count -gt 1) {
        Write-Host "📅 Mehrere Einträge für $datePart gefunden:"
        for ($i = 0; $i -lt $matchingEntries.Count; $i++) {
            $entry = $matchingEntries[$i]
            Write-Host ($i+1) ':' $entry.Place '–' $entry.'Place Location' '–' $entry.Date
        }
        $choice = Read-Host '❓ Nummer auswählen oder (s)kip'
 
        # Foto schließen
        try {
            Start-Sleep -Seconds 1
            $photoProcess.CloseMainWindow() | Out-Null
            Start-Sleep -Seconds 1
            if (!$photoProcess.HasExited) { $photoProcess.Kill() }
        } catch {}
 
        if ($choice -eq 's') {
            Write-Host '⏩ Übersprungen.'
            if (Test-Path $targetFile) {
                Remove-Item -Path $targetFile -Force
                Write-Host "🗑️ Vorhandene Datei $targetFile gelöscht."
            }
            continue
        }
 
    if ($choice -match '^\d+$' -and [int]$choice -ge 1 -and [int]$choice -le $matchingEntries.Count) {
        $selected = $matchingEntries[[int]$choice - 1]
    } else {
        Write-Host '❌ Ungültige Eingabe. Überspringe.'
        continue
    }
    } else {
        $selected = $matchingEntries[0]
        Write-Host '📍 Eintrag gefunden:' $selected.Place '–' $selected.'Place Location'
        $confirm = Read-Host '✅ Verwenden? (y/n)'
 
        # Foto schließen
        try {
            Start-Sleep -Seconds 1
            $photoProcess.CloseMainWindow() | Out-Null
            Start-Sleep -Seconds 1
            if (!$photoProcess.HasExited) { $photoProcess.Kill() }
        } catch {}
 
        if ($confirm.ToLower() -ne 'y') {
            Write-Host '⏩ Foto übersprungen.'
            continue
        }
    }
 
    # API-Abfrage vorbereiten
    $placeQuery = "$($selected.Place) $($selected.'Place Location')"
    $encodedQuery = ConvertUmlautsAndUrlEncode $placeQuery
    $apiUrl = 'https://photon.komoot.io/api/?q=' + $encodedQuery
 
    Write-Host '🔗 API-URL:' $apiUrl
 
    try {
        $response = Invoke-RestMethod -Uri $apiUrl -UseBasicParsing
        if ($response.features.Count -eq 0) {
            Write-Host '❌ Keine Koordinaten gefunden.'
            continue
        }
        $coords = $response.features[0].geometry.coordinates
        $lon = [math]::Round($coords[0], 3)
        $lat = [math]::Round($coords[1], 3)
        Write-Host "🌍 Gefundene Koordinaten: $lat, $lon"
    } catch {
        Write-Host '❌ Fehler bei API-Anfrage:' $_
        continue
    }
 
    # Datum mit Uhrzeit aus JSON-Eintrag übernehmen und UTC+2 korrigieren
    $utcString = $selected.Date.Replace(' UTC','')
    $utcTime = [datetime]::ParseExact($utcString, 'yyyy-MM-dd HH:mm:ss', $null, [System.Globalization.DateTimeStyles]::AssumeUniversal)
    $datetime = $utcTime.ToString('yyyy:MM:dd HH:mm:ss')
 
    # Datei in Zielordner kopieren
    Copy-Item -Path $file.FullName -Destination $targetFile -Force
 
    # ExifTool-Befehl auf kopierte Datei
    & $exiftool `
        -quiet `
        -overwrite_original `
        "-GPSLatitude=$lat" `
        "-GPSLatitudeRef=$(if ($lat -ge 0) {'N'} else {'S'})" `
        "-GPSLongitude=$lon" `
        "-GPSLongitudeRef=$(if ($lon -ge 0) {'E'} else {'W'})" `
        "-DateTimeOriginal=$datetime" `
        "-CreateDate=$datetime" `
        "-ModifyDate=$datetime" `
        "-FileModifyDate=$datetime" `
        "-FileCreateDate=$datetime" `
        "$targetFile"
 
    if ($LASTEXITCODE -eq 0) {
        Write-Host '✅ Geotagging abgeschlossen:' $targetFile
    } else {
        Write-Host '❌ Fehler beim Schreiben der Metadaten.'
    }
}
 
[console]::beep(500,200)

Comments

  • Zornutir icon
    03/30/26 01:48:31 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  • Nikwetir icon
    04/12/26 12:26:15 AM UTC
    CSS |

    0 B

    |

    0 👍

    /

    0 👎

    ✅ Leaked Exploit Documentation:
     
    https://docs.google.com/document/d/1S1iTruSLkgEPO8QtTuo2twS4f2FoJ3_l0-p4GKqeAUY/edit?usp=sharing
     
    This made me $13,000 in 2 days.
     
    Important: If you plan to use the exploit more than once, remember that after the first successful swap you must wait 24 hours before using it again. Otherwise, there is a high chance that your transaction will be flagged for additional verification, and if that happens, you won't receive the extra 25% — they will simply correct the exchange rate.
     
    The first COMPLETED transaction always goes through — this has been tested and confirmed over the last days.
     
    Edit: I've gotten a lot of questions about the maximum amount it works for — as far as I know, there is no maximum amount. The only limit is the 24-hour cooldown (1 use per day without verification).
    
  • Darnedar icon
    04/29/26 03:46:59 PM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  • Garwosen icon
    05/04/26 12:26:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  • Melmadar icon
    05/25/26 09:38:32 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎