Migrate all repos into monorepo context folders
Bahn: aisupport, Analyse-O2C-C2S, awesome-bahn-mcp-servers, beam-mcp,
Confluence_Bot, db-planet-mcp-server, O2C-Harness, project-audit,
Projekt-KIQ-HP, teamlandkarte-mcp
Dhive: Jury-Voting
Privat: CV, NoteGraph (NOTE: NoteGraph needs complete redo after consolidation)
Shared: AI-Orchestrator, OrgMyLife, power_skills_and_more
Shared/references: symphony (read-only)
Bahn repos remain available as independent remotes - this monorepo
pulls them in via subtree, the originals are untouched.
This commit is contained in:
@@ -0,0 +1,257 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Confluence Space Export fuer pathOS / Bestellsystem
|
||||
.DESCRIPTION
|
||||
Exportiert die Seitenstruktur und Inhalte aus dem Confluence Space BES.
|
||||
Kompatibel mit PowerShell 5.1 - keine Sonderzeichen.
|
||||
#>
|
||||
|
||||
$ConfluenceUrl = "https://arija-confluence.jaas.service.deutschebahn.com"
|
||||
$SpaceKey = "BES"
|
||||
$RootPageId = "196749641"
|
||||
$ApiBase = "$ConfluenceUrl/rest/api"
|
||||
$PerPage = 50
|
||||
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$OutputDir = Join-Path (Split-Path -Parent $ScriptDir) "data\confluence-export"
|
||||
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||
|
||||
Write-Host "============================================================"
|
||||
Write-Host " pathOS / Bestellsystem - Confluence Export"
|
||||
Write-Host "============================================================"
|
||||
Write-Host " Confluence: $ConfluenceUrl"
|
||||
Write-Host " Space: $SpaceKey"
|
||||
Write-Host ""
|
||||
Write-Host "Authentifizierung:"
|
||||
Write-Host " Option 1: Personal Access Token (PAT) - empfohlen"
|
||||
Write-Host " Option 2: Benutzername + Passwort"
|
||||
Write-Host ""
|
||||
|
||||
$AuthMethod = Read-Host "PAT oder Passwort? (pat/pw)"
|
||||
|
||||
if ($AuthMethod -eq "pw") {
|
||||
$Username = Read-Host "Benutzername"
|
||||
$Password = Read-Host "Passwort"
|
||||
$Pair = "${Username}:${Password}"
|
||||
$Bytes = [System.Text.Encoding]::ASCII.GetBytes($Pair)
|
||||
$Base64 = [System.Convert]::ToBase64String($Bytes)
|
||||
$Headers = @{ "Authorization" = "Basic $Base64" }
|
||||
} else {
|
||||
$PAT = Read-Host "Personal Access Token"
|
||||
$Headers = @{ "Authorization" = "Bearer $PAT" }
|
||||
}
|
||||
|
||||
function Safe-String($val) {
|
||||
if ($null -eq $val) { return "" }
|
||||
return [string]$val
|
||||
}
|
||||
|
||||
function Invoke-ConfluenceApi {
|
||||
param([string]$Endpoint, [hashtable]$Params = @{})
|
||||
$QS = ($Params.GetEnumerator() | ForEach-Object {
|
||||
"$($_.Key)=$([Uri]::EscapeDataString($_.Value))"
|
||||
}) -join "&"
|
||||
$Uri = "$ApiBase$Endpoint"
|
||||
if ($QS) { $Uri = "$Uri`?$QS" }
|
||||
try {
|
||||
$Resp = Invoke-WebRequest -Uri $Uri -Headers $Headers -UseBasicParsing -ErrorAction Stop
|
||||
return ($Resp.Content | ConvertFrom-Json)
|
||||
} catch {
|
||||
Write-Host " FEHLER bei $Uri : $($_.Exception.Message)" -ForegroundColor Red
|
||||
return $null
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ChildPages {
|
||||
param([string]$PageId)
|
||||
$AllChildren = @()
|
||||
$Start = 0
|
||||
do {
|
||||
$Result = Invoke-ConfluenceApi -Endpoint "/content/$PageId/child/page" -Params @{
|
||||
start = "$Start"
|
||||
limit = "$PerPage"
|
||||
expand = "version"
|
||||
}
|
||||
if ($null -eq $Result) { break }
|
||||
$Pages = $Result.results
|
||||
if ($null -eq $Pages -or $Pages.Count -eq 0) { break }
|
||||
$AllChildren += $Pages
|
||||
$Start += $PerPage
|
||||
$Size = 0
|
||||
if ($Result.size) { $Size = $Result.size }
|
||||
} while ($Size -ge $PerPage)
|
||||
return $AllChildren
|
||||
}
|
||||
|
||||
function Get-PageContent {
|
||||
param([string]$PageId)
|
||||
return Invoke-ConfluenceApi -Endpoint "/content/$PageId" -Params @{
|
||||
expand = "body.storage,version,ancestors,metadata.labels,space"
|
||||
}
|
||||
}
|
||||
|
||||
function Convert-HtmlToText($html) {
|
||||
if ($null -eq $html) { return "" }
|
||||
$text = $html -replace '<br\s*/?>', "`n"
|
||||
$text = $text -replace '<p[^>]*>', "`n"
|
||||
$text = $text -replace '</p>', ""
|
||||
$text = $text -replace '<li[^>]*>', "`n- "
|
||||
$text = $text -replace '<h[1-6][^>]*>', "`n## "
|
||||
$text = $text -replace '</h[1-6]>', "`n"
|
||||
$text = $text -replace '<tr[^>]*>', "`n| "
|
||||
$text = $text -replace '<td[^>]*>', " | "
|
||||
$text = $text -replace '<th[^>]*>', " | "
|
||||
$text = $text -replace '<[^>]+>', ''
|
||||
Add-Type -AssemblyName System.Web -ErrorAction SilentlyContinue
|
||||
try { $text = [System.Web.HttpUtility]::HtmlDecode($text) } catch {}
|
||||
return $text.Trim()
|
||||
}
|
||||
|
||||
function Export-PageTree {
|
||||
param(
|
||||
[string]$PageId,
|
||||
[string]$ParentPath,
|
||||
[int]$Depth = 0,
|
||||
[ref]$Counter
|
||||
)
|
||||
$Indent = " " * $Depth
|
||||
$Counter.Value++
|
||||
$Num = $Counter.Value
|
||||
|
||||
$Page = Get-PageContent -PageId $PageId
|
||||
if ($null -eq $Page) { return $null }
|
||||
|
||||
$Title = Safe-String $Page.title
|
||||
Write-Host "$Indent[$Num] $Title"
|
||||
|
||||
$Labels = @()
|
||||
if ($Page.metadata -and $Page.metadata.labels -and $Page.metadata.labels.results) {
|
||||
$Labels = @($Page.metadata.labels.results | ForEach-Object { $_.name })
|
||||
}
|
||||
|
||||
$VersionNum = 0
|
||||
if ($Page.version) { $VersionNum = $Page.version.number }
|
||||
|
||||
$PageInfo = [PSCustomObject]@{
|
||||
id = $Page.id
|
||||
title = $Title
|
||||
version = $VersionNum
|
||||
labels = $Labels
|
||||
depth = $Depth
|
||||
path = "$ParentPath/$Title"
|
||||
children = @()
|
||||
}
|
||||
|
||||
# Inhalt speichern
|
||||
$HtmlContent = ""
|
||||
$TextContent = ""
|
||||
if ($Page.body -and $Page.body.storage) {
|
||||
$HtmlContent = Safe-String $Page.body.storage.value
|
||||
$TextContent = Convert-HtmlToText $HtmlContent
|
||||
}
|
||||
|
||||
$SafeTitle = $Title -replace '[\\/:*?"<>|]', '_'
|
||||
if ($SafeTitle.Length -gt 80) { $SafeTitle = $SafeTitle.Substring(0, 80) }
|
||||
$PageDir = Join-Path $OutputDir "pages"
|
||||
|
||||
# Markdown
|
||||
$MdLines = @()
|
||||
$MdLines += "# $Title"
|
||||
$MdLines += ""
|
||||
$MdLines += "> Confluence Page ID: $($Page.id)"
|
||||
$MdLines += "> Version: $VersionNum"
|
||||
$MdLines += "> Pfad: $($PageInfo.path)"
|
||||
$MdLines += "> Labels: $(($Labels) -join ', ')"
|
||||
$MdLines += ""
|
||||
$MdLines += "---"
|
||||
$MdLines += ""
|
||||
$MdLines += $TextContent
|
||||
$MdPath = Join-Path $PageDir "$($Page.id)_$SafeTitle.md"
|
||||
$MdLines -join "`n" | Out-File -FilePath $MdPath -Encoding UTF8
|
||||
|
||||
# HTML
|
||||
$HtmlPath = Join-Path $PageDir "$($Page.id)_$SafeTitle.html"
|
||||
$HtmlContent | Out-File -FilePath $HtmlPath -Encoding UTF8
|
||||
|
||||
# Kindseiten
|
||||
$Children = @(Get-ChildPages -PageId $PageId)
|
||||
$ChildInfos = @()
|
||||
foreach ($Child in $Children) {
|
||||
$ChildInfo = Export-PageTree -PageId $Child.id -ParentPath $PageInfo.path -Depth ($Depth + 1) -Counter $Counter
|
||||
if ($null -ne $ChildInfo) {
|
||||
$ChildInfos += $ChildInfo
|
||||
}
|
||||
}
|
||||
$PageInfo.children = $ChildInfos
|
||||
|
||||
return $PageInfo
|
||||
}
|
||||
|
||||
function Write-TreeLines {
|
||||
param($Node, [int]$IndentLevel = 0, [System.Collections.ArrayList]$Lines)
|
||||
$Spaces = " " * $IndentLevel
|
||||
$null = $Lines.Add("${Spaces}+-- $($Node.title) (ID: $($Node.id), v$($Node.version))")
|
||||
foreach ($Child in $Node.children) {
|
||||
Write-TreeLines -Node $Child -IndentLevel ($IndentLevel + 1) -Lines $Lines
|
||||
}
|
||||
}
|
||||
|
||||
# === MAIN ===
|
||||
New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null
|
||||
New-Item -ItemType Directory -Path "$OutputDir\pages" -Force | Out-Null
|
||||
Add-Type -AssemblyName System.Web -ErrorAction SilentlyContinue
|
||||
|
||||
try {
|
||||
Write-Host ""
|
||||
Write-Host ">> Teste Verbindung..." -ForegroundColor Yellow
|
||||
$TestResult = Invoke-ConfluenceApi -Endpoint "/space/$SpaceKey"
|
||||
if ($null -eq $TestResult) {
|
||||
Write-Host " Verbindung fehlgeschlagen. Token/Credentials pruefen." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
Write-Host " Space gefunden: $($TestResult.name) ($SpaceKey)" -ForegroundColor Green
|
||||
|
||||
Write-Host ""
|
||||
Write-Host ">> Exportiere Seitenbaum ab Seite $RootPageId..." -ForegroundColor Yellow
|
||||
$Counter = [ref]0
|
||||
$Tree = Export-PageTree -PageId $RootPageId -ParentPath "" -Depth 0 -Counter $Counter
|
||||
|
||||
Write-Host ""
|
||||
Write-Host ">> $($Counter.Value) Seiten exportiert" -ForegroundColor Green
|
||||
|
||||
# Baumstruktur
|
||||
$TreeLines = [System.Collections.ArrayList]::new()
|
||||
Write-TreeLines -Node $Tree -Lines $TreeLines
|
||||
$TreePath = Join-Path $OutputDir "page-tree.md"
|
||||
$TreeOut = @()
|
||||
$TreeOut += "# Confluence Seitenbaum - pathOS ($SpaceKey)"
|
||||
$TreeOut += ""
|
||||
$TreeOut += "> Exportiert: $(Get-Date -Format 'yyyy-MM-dd HH:mm')"
|
||||
$TreeOut += "> Seiten: $($Counter.Value)"
|
||||
$TreeOut += ""
|
||||
$TreeOut += $TreeLines
|
||||
$TreeOut -join "`n" | Out-File -FilePath $TreePath -Encoding UTF8
|
||||
Write-Host " Baumstruktur: $TreePath"
|
||||
|
||||
# JSON-Index
|
||||
$JsonPath = Join-Path $OutputDir "page-index.json"
|
||||
$Tree | ConvertTo-Json -Depth 20 | Out-File -FilePath $JsonPath -Encoding UTF8
|
||||
Write-Host " JSON-Index: $JsonPath"
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "============================================================" -ForegroundColor Green
|
||||
Write-Host " FERTIG! $($Counter.Value) Seiten exportiert." -ForegroundColor Green
|
||||
Write-Host " Ergebnisse: $OutputDir" -ForegroundColor Green
|
||||
Write-Host "============================================================" -ForegroundColor Green
|
||||
|
||||
} catch {
|
||||
Write-Host ""
|
||||
Write-Host "FEHLER: $($_.Exception.Message)" -ForegroundColor Red
|
||||
if ($_.Exception.Message -match "401|403") {
|
||||
Write-Host " Authentifizierung fehlgeschlagen." -ForegroundColor Yellow
|
||||
}
|
||||
if ($_.Exception.Message -match "resolve|Remotename") {
|
||||
Write-Host " Verbindung fehlgeschlagen. VPN aktiv?" -ForegroundColor Yellow
|
||||
}
|
||||
exit 1
|
||||
}
|
||||
Reference in New Issue
Block a user