using System.IO.Compression; using System.Text.Json; using System.Text.Json.Serialization; namespace wp2ghost { // ============================================================================= // GhostExporter — Ghost ZIP erstellen // ============================================================================= static class GhostExporter { private static string BaseDir = ""; private static string MarkdownDir = ""; public static int PostCount => PostFetcher.PostCount; public static void Init(string baseDir) { BaseDir = baseDir; MarkdownDir = Path.Combine(baseDir, "markdown"); } public static async Task CreateZipAsync() { Console.WriteLine(); Console.WriteLine("Erstelle Ghost ZIP-Datei..."); var posts = PostFetcher.Posts; if (posts.Count == 0) { Console.WriteLine("Keine Beiträge geladen. Bitte zuerst Option 1 ausführen."); return; } string outputPath = Path.Combine(BaseDir, Importer.OutputZipPath); try { //PostFetcher.SaveAllMarkdownFiles(); // Links zwischen den eigenen Beiträgen auf Ghost umschreiben (Kopie, Original bleibt unverändert) int internalLinks = 0; var exportPosts = posts.Select(p => { var rewritten = InternalLinkManager.Rewrite(p.Html ?? "", Importer.WpBaseUrl, "__GHOST_URL__"); internalLinks += rewritten.Replaced; return new GhostPost { Id = p.Id, Title = p.Title, Slug = p.Slug, Html = rewritten.Html, Markdown = p.Markdown, FeatureImage = p.FeatureImage, Status = p.Status, CreatedAt = p.CreatedAt, PublishedAt = p.PublishedAt }; }).ToList(); if (internalLinks > 0) Console.WriteLine($" {internalLinks} interne(r) Link(s) auf Ghost umgeschrieben"); string jsonString = JsonSerializer.Serialize(new GhostRoot { Db = new List { new GhostDb { Data = new GhostData { Posts = exportPosts } } } }, new JsonSerializerOptions { WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }); string outputDir = Path.GetDirectoryName(outputPath) ?? BaseDir; if (!Directory.Exists(outputDir)) Directory.CreateDirectory(outputDir); using (var zipStream = new FileStream(outputPath, FileMode.Create)) using (var archive = new ZipArchive(zipStream, ZipArchiveMode.Create, true)) { var jsonEntry = archive.CreateEntry("import.json"); using (var writer = new StreamWriter(jsonEntry.Open())) { await writer.WriteAsync(jsonString); } if (Directory.Exists(MarkdownDir)) { foreach (string mdFile in Directory.GetFiles(MarkdownDir, "*.md", SearchOption.AllDirectories)) { string relativeMdPath = Path.GetFileName(mdFile); var mdEntry = archive.CreateEntry($"content/{relativeMdPath}"); using (var entryStream = mdEntry.Open()) using (var fileStream = File.OpenRead(mdFile)) { await fileStream.CopyToAsync(entryStream); } } } foreach (var file in ImageManager.CachedFiles) { string fullLocalPath = Path.Combine(Path.Combine(BaseDir, "images"), file.RelativePath); if (File.Exists(fullLocalPath)) { var fileEntry = archive.CreateEntry($"content/images/{file.RelativePath}"); using (var entryStream = fileEntry.Open()) using (var fileStream = File.OpenRead(fullLocalPath)) { await fileStream.CopyToAsync(entryStream); } } } // Videos unkomprimiert ablegen (MP4 lässt sich nicht weiter packen) foreach (var file in MediaManager.CachedFiles) { if (File.Exists(file.LocalPath)) { var fileEntry = archive.CreateEntry($"content/media/{file.RelativePath}", CompressionLevel.NoCompression); using (var entryStream = fileEntry.Open()) using (var fileStream = File.OpenRead(file.LocalPath)) { await fileStream.CopyToAsync(entryStream); } } } } Console.WriteLine(); Console.WriteLine("========================================="); Console.WriteLine($" Ghost ZIP erstellt!"); Console.WriteLine($" Beiträge: {posts.Count}"); Console.WriteLine($" Bilder: {ImageManager.CachedFiles.Count} Dateien"); Console.WriteLine($" Videos: {MediaManager.CachedFiles.Count} Dateien"); Console.WriteLine($" Ausgabe: {outputPath}"); Console.WriteLine("========================================="); } catch (Exception ex) { Console.WriteLine($"\nFehler beim Erstellen der ZIP-Datei: {ex.Message}"); Console.WriteLine($"Stack Trace: {ex.StackTrace}"); } } } }