Files
L363-Fortbildung-ABC-CBRN-E…/Archive-Babz.ps1
T

197 lines
8.0 KiB
PowerShell

<#
.SYNOPSIS
Full recursive mirror of BABZ Bund ILIAS course content.
Downloads all SCORM modules and PDFs found by the Python crawler.
.NOTES
Requires PHPSESSID in ~/.env
Requires crawl_results.txt generated by the Python crawler.
Run from the C:\GitHub\FW directory.
#>
$EnvFilePath = Join-Path $env:USERPROFILE ".env"
$PHPSESSID = $null
if (Test-Path $EnvFilePath) {
Get-Content $EnvFilePath | Where-Object { $_ -match "^PHPSESSID=(.*)" } | ForEach-Object {
$PHPSESSID = $Matches[1].Trim()
}
}
if ([string]::IsNullOrWhiteSpace($PHPSESSID)) {
Write-Error "PHPSESSID is missing! Please add it to your ~/.env file."
exit 1
}
$BASE_ILIAS = "https://lernplattform-babz-bund.de"
$BASE_DATA = "$BASE_ILIAS/data/BBKILIAS/lm_data"
$OUT_DIR = $PSScriptRoot # C:\GitHub\FW
$Headers = @{ "Cookie" = "PHPSESSID=$PHPSESSID" }
$Modules = [ordered]@{
"Chemische Kampfstoffe_final" = 159348
"WBT Motorola Digitalfunk_final" = 0 # HTLM-Format, wird separat behandelt (kein lm_id)
"Ionenmobilitaetsspektrometer" = 167131
"Photoionisationsdetektor" = 161852
"MGMG Alarme und Sonderzustaende" = 167132
"MGMG Gase und Messprinzipien" = 182052
"MGMG Material" = 167134
"MGMG Menue" = 167135
"MGMG Wartung" = 167136
"CoMo-170 ZS-2 (KNG)" = 167139
"RadEye (DLM)" = 167137
"WBT_ErkW_1_Einfuehrung" = 167175
"WBT_ErkW_2_Aufbau_und_Ueberblick_Bedienoberflaeche" = 167176
"WBT_ErkW_3_Einsatzbereitschaft_herstellen" = 167177
"WBT_ErkW_4_Aufgesessene_Messung" = 167178
"WBT_ErkW_5_Abgesetzte_Messung" = 167179
"WBT_ErkW_6_Administration_erw_Funktionen" = 167180
"Grundlagen_radiologische_Formeln" = 167618
}
$PDFs = [ordered]@{}
function Invoke-FileDownload {
param([string]$Url, [string]$Dest)
$dir = Split-Path $Dest -Parent
if (-not (Test-Path $dir)) { New-Item -ItemType Directory -Path $dir -Force | Out-Null }
try {
$wc = New-Object System.Net.WebClient
$wc.Headers.Add("Cookie", "PHPSESSID=$PHPSESSID")
$wc.DownloadFile($Url, $Dest)
return $true
} catch {
Write-Warning " FAILED: $Url ($_)"
return $false
}
}
Write-Host "`n========================================" -ForegroundColor Cyan
Write-Host " SCORM MODULES ($($Modules.Count) total)" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
$totalFiles = 0
$failedFiles = 0
foreach ($ModuleName in $Modules.Keys) {
$lmId = $Modules[$ModuleName]
$baseUrl = "$BASE_DATA/lm_$lmId"
$destDir = Join-Path $OUT_DIR "Trainings\$ModuleName"
Write-Host "`n[Module] $ModuleName (lm_$lmId)" -ForegroundColor Yellow
# -- Core entry points every Storyline module has --
$CoreFiles = @(
"story.html", "index_lms.html", "analytics-frame.html", "imsmanifest.xml", "meta.xml",
"html5/data/css/output.min.css", "html5/data/js/data.js", "html5/data/js/frame.js",
"html5/data/js/paths.js", "html5/lib/scripts/bootstrapper.min.js",
"html5/lib/scripts/frame.desktop.min.js", "html5/lib/scripts/frame.mobile.min.js",
"html5/lib/scripts/slides.min.js", "story_content/user.js", "story_content/triggers.js",
"story_content/thumbnail.jpg", "mobile/fonts.json"
)
$downloaded = 0
$failed = 0
foreach ($f in $CoreFiles) {
$url = "$baseUrl/$f"
$dest = Join-Path $destDir ($f -replace '/', '\')
$ok = Invoke-FileDownload -Url $url -Dest $dest
if ($ok) { $downloaded++ } else { $failed++ }
}
$manifestPath = Join-Path $destDir "imsmanifest.xml"
if (Test-Path $manifestPath) {
$xmlContent = (Get-Content $manifestPath -Raw -Encoding UTF8) -replace "`x1A", ""
[xml]$manifest = $xmlContent
$ns = @{ ims = "http://www.imsproject.org/xsd/imscp_rootv1p1p2" }
$fileNodes = $manifest.SelectNodes("//file", $null) + $manifest.SelectNodes("//*[local-name()='file']")
$manifestFiles = $fileNodes | ForEach-Object { $_.href } | Where-Object { $_ } | Sort-Object -Unique
foreach ($f in $manifestFiles) {
$f = $f -replace '\\', '/'
$url = "$baseUrl/$f"
$dest = Join-Path $destDir ($f -replace '/', '\')
if (-not (Test-Path $dest)) {
$ok = Invoke-FileDownload -Url $url -Dest $dest
if ($ok) { $downloaded++ } else { $failed++ }
}
}
}
$dataJsPath = Join-Path $destDir "html5\data\js\data.js"
if (Test-Path $dataJsPath) {
$dataContent = Get-Content $dataJsPath -Raw
$chunkRefs = [regex]::Matches($dataContent, '"([A-Za-z0-9_-]{8,15}\.js)"') | ForEach-Object { $_.Groups[1].Value } | Sort-Object -Unique
if ($chunkRefs.Count -gt 0) {
foreach ($chunk in $chunkRefs) {
$url = "$baseUrl/html5/data/js/$chunk"
$dest = Join-Path $destDir "html5\data\js\$chunk"
if (-not (Test-Path $dest)) {
$ok = Invoke-FileDownload -Url $url -Dest $dest
if ($ok) { $downloaded++ } else { $failed++ }
}
}
}
}
$pathsJsPath = Join-Path $destDir "html5\data\js\paths.js"
if (Test-Path $pathsJsPath) {
$pathsContent = Get-Content $pathsJsPath -Raw
$audioRefs = [regex]::Matches($pathsContent, '"([A-Za-z0-9_-]{8,20}_\d+_\d+_\d+\.mp3)"') | ForEach-Object { $_.Groups[1].Value } | Sort-Object -Unique
if ($audioRefs.Count -gt 0) {
foreach ($audio in $audioRefs) {
$url = "$baseUrl/story_content/$audio"
$dest = Join-Path $destDir "story_content\$audio"
if (-not (Test-Path $dest)) {
$ok = Invoke-FileDownload -Url $url -Dest $dest
if ($ok) { $downloaded++ } else { $failed++ }
}
}
}
$pngRefs = [regex]::Matches($pathsContent, '"([A-Za-z0-9_-]{8,20}\.png)"') | ForEach-Object { $_.Groups[1].Value } | Sort-Object -Unique
foreach ($png in $pngRefs) {
$url = "$baseUrl/mobile/$png"
$dest = Join-Path $destDir "mobile\$png"
if (-not (Test-Path $dest)) {
$ok = Invoke-FileDownload -Url $url -Dest $dest
if ($ok) { $downloaded++ } else { $failed++ }
}
}
}
$totalFiles += $downloaded
$failedFiles += $failed
$fc = if ($failed -eq 0) { 'Green' } else { 'Red' }
Write-Host " OK $downloaded new files downloaded, $failed failed" -ForegroundColor $fc
}
Write-Host "`n========================================" -ForegroundColor Cyan
Write-Host " PDF DOCUMENTS ($($PDFs.Count) total)" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
$pdfDir = Join-Path $OUT_DIR "Documents"
if (-not (Test-Path $pdfDir)) { New-Item -ItemType Directory -Path $pdfDir -Force | Out-Null }
foreach ($FileName in $PDFs.Keys) {
$refId = $PDFs[$FileName]
$url = "$BASE_ILIAS/goto.php/file/$refId/download"
$dest = Join-Path $pdfDir $FileName
Write-Host " [PDF] $FileName (ref_id=$refId)" -ForegroundColor Yellow
if ((Invoke-FileDownload -Url $url -Dest $dest) -and (Test-Path $dest)) {
$size = (Get-Item $dest).Length
$header = [System.Text.Encoding]::ASCII.GetString((Get-Content $dest -Encoding Byte -TotalCount 4))
if ($header -ne "%PDF") {
Write-Warning " ! $FileName does not appear to be a valid PDF (size: $size, header: $header)"
$failedFiles++
} else {
Write-Host " OK $([Math]::Round($size/1KB, 1)) KB" -ForegroundColor Green
$totalFiles++
}
}
}
Write-Host "`nDone!" -ForegroundColor Green