2026-09-20 08:31:23 +02:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
using System.Text.Json.Serialization;
|
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
|
|
|
|
|
|
namespace wp2ghost
|
|
|
|
|
|
{
|
|
|
|
|
|
public class IdsResponse
|
|
|
|
|
|
{
|
|
|
|
|
|
[JsonPropertyName("count")] public int Count { get; set; }
|
|
|
|
|
|
[JsonPropertyName("post_type")] public string? PostType { get; set; }
|
|
|
|
|
|
[JsonPropertyName("ids")] public List<int>? Ids { get; set; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public class WpPostResponse
|
|
|
|
|
|
{
|
|
|
|
|
|
[JsonPropertyName("id")] public int Id { get; set; }
|
|
|
|
|
|
[JsonPropertyName("title")] public string? Title { get; set; }
|
|
|
|
|
|
[JsonPropertyName("slug")] public string? Slug { get; set; }
|
2026-10-14 19:12:29 +02:00
|
|
|
|
// Veröffentlichungsdatum in der Ortszeit des Blogs (ohne Zeitzone)
|
2026-09-20 08:31:23 +02:00
|
|
|
|
[JsonPropertyName("date")] public string? Date { get; set; }
|
2026-10-14 19:12:29 +02:00
|
|
|
|
// Dasselbe in UTC — ab Plugin-Version mit date_gmt
|
|
|
|
|
|
[JsonPropertyName("date_gmt")] public string? DateGmt { get; set; }
|
2026-09-20 08:31:23 +02:00
|
|
|
|
[JsonPropertyName("content")] public string? Content { get; set; }
|
|
|
|
|
|
[JsonPropertyName("excerpt")] public string? Excerpt { get; set; }
|
|
|
|
|
|
[JsonPropertyName("featured_image")] public string? FeaturedImage { get; set; }
|
|
|
|
|
|
[JsonPropertyName("categories")] public List<WpCategory>? Categories { get; set; } = new();
|
2026-09-22 08:08:51 +02:00
|
|
|
|
[JsonPropertyName("tags")] public List<WpCategory>? Tags { get; set; } = new();
|
2026-09-20 08:31:23 +02:00
|
|
|
|
[JsonPropertyName("keywords")] public string? Keywords { get; set; }
|
|
|
|
|
|
[JsonPropertyName("comments")] public List<WpComment>? Comments { get; set; } = new();
|
|
|
|
|
|
[JsonPropertyName("media_files")] public List<string>? MediaFiles { get; set; } = new();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public class WpCategory
|
|
|
|
|
|
{
|
|
|
|
|
|
[JsonPropertyName("id")] public int Id { get; set; }
|
|
|
|
|
|
[JsonPropertyName("name")] public string? Name { get; set; }
|
|
|
|
|
|
[JsonPropertyName("slug")] public string? Slug { get; set; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-10-14 19:12:29 +02:00
|
|
|
|
// Datumsangaben für Ghost: immer UTC im Format 2022-11-19T09:30:00.000Z
|
|
|
|
|
|
public static class DateHelper
|
|
|
|
|
|
{
|
|
|
|
|
|
private const string GhostFormat = "yyyy-MM-dd'T'HH:mm:ss.000'Z'";
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Wandelt ein Datum in UTC um. Ein Datum ohne Zeitzone (so liefert es WordPress) wird
|
|
|
|
|
|
/// als Ortszeit dieses Rechners gedeutet. Liefert null, wenn es nicht lesbar ist.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static string? ToGhostUtc(string? date) => Convert(date, System.Globalization.DateTimeStyles.AssumeLocal);
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>Wie ToGhostUtc, aber ein Datum ohne Zeitzone gilt als UTC (WordPress "date_gmt").</summary>
|
|
|
|
|
|
public static string? FromGmt(string? date) => Convert(date, System.Globalization.DateTimeStyles.AssumeUniversal);
|
|
|
|
|
|
|
|
|
|
|
|
private static string? Convert(string? date, System.Globalization.DateTimeStyles assume)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(date)) return null;
|
|
|
|
|
|
if (!DateTimeOffset.TryParse(date, System.Globalization.CultureInfo.InvariantCulture, assume, out var parsed)) return null;
|
|
|
|
|
|
if (parsed.Year < 1990) return null; // WordPress-Platzhalter 0000-00-00
|
|
|
|
|
|
return parsed.UtcDateTime.ToString(GhostFormat, System.Globalization.CultureInfo.InvariantCulture);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Kategorien, die nie nach Ghost übernommen werden
|
|
|
|
|
|
public static class CategoryRules
|
|
|
|
|
|
{
|
|
|
|
|
|
private static readonly string[] IgnoredNames = { "Allgemein" };
|
|
|
|
|
|
|
|
|
|
|
|
public static bool IsIgnored(string? name) =>
|
|
|
|
|
|
IgnoredNames.Contains(System.Net.WebUtility.HtmlDecode(name ?? "").Trim(), StringComparer.OrdinalIgnoreCase);
|
|
|
|
|
|
|
|
|
|
|
|
public static bool IsIgnored(WpCategory category) => IsIgnored(category.Name) || IsIgnored(category.Slug);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-20 08:31:23 +02:00
|
|
|
|
public class WpComment
|
|
|
|
|
|
{
|
|
|
|
|
|
[JsonPropertyName("id")] public int Id { get; set; }
|
|
|
|
|
|
[JsonPropertyName("author_name")] public string? AuthorName { get; set; }
|
|
|
|
|
|
[JsonPropertyName("author_email")] public string? AuthorEmail { get; set; }
|
|
|
|
|
|
[JsonPropertyName("author_url")] public string? AuthorUrl { get; set; }
|
|
|
|
|
|
[JsonPropertyName("content")] public string? Content { get; set; }
|
|
|
|
|
|
[JsonPropertyName("date")] public string? Date { get; set; }
|
2026-10-14 19:12:29 +02:00
|
|
|
|
// Ab Plugin-Version mit Kommentar-Typ: "comment", "pingback", "like", "repost" ...
|
|
|
|
|
|
[JsonPropertyName("type")] public string? Type { get; set; }
|
|
|
|
|
|
[JsonPropertyName("parent")] public int Parent { get; set; }
|
2026-09-20 08:31:23 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|