Wp2ghost/GhostImageManager/Services/GhostApiService.cs
2026-09-24 19:23:54 +02:00

169 lines
6.4 KiB
C#

using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using GhostImageManager.Models;
using HtmlAgilityPack;
namespace GhostImageManager.Services;
public class GhostApiService
{
private readonly HttpClient _httpClient;
public GhostApiService(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<List<GhostPost>> GetPostsAsync(GhostInstance instance, string filter = "", int limit = 100)
{
var request = CreateRequest(HttpMethod.Get, instance, $"posts/?limit={limit}&filter={Uri.EscapeDataString(filter)}&fields=id,title,slug,feature_image,html,created_at,updated_at,status");
var response = await _httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
var doc = JsonDocument.Parse(json);
var posts = new List<GhostPost>();
if (doc.RootElement.TryGetProperty("posts", out var postsElement))
{
foreach (var post in postsElement.EnumerateArray())
{
posts.Add(new GhostPost
{
Id = GetString(post, "id"),
Title = GetString(post, "title"),
Slug = GetString(post, "slug"),
Html = GetString(post, "html"),
FeatureImage = GetString(post, "feature_image"),
CreatedAt = GetDateTime(post, "created_at"),
UpdatedAt = GetDateTime(post, "updated_at"),
Status = GetString(post, "status")
});
}
}
return posts;
}
public async Task<GhostPost?> GetPostAsync(GhostInstance instance, string postId)
{
var request = CreateRequest(HttpMethod.Get, instance, $"posts/{postId}/?fields=id,title,slug,feature_image,html,created_at,updated_at,status");
var response = await _httpClient.SendAsync(request);
if (!response.IsSuccessStatusCode) return null;
var json = await response.Content.ReadAsStringAsync();
var doc = JsonDocument.Parse(json);
if (doc.RootElement.TryGetProperty("posts", out var posts) && posts.GetArrayLength() > 0)
{
var post = posts[0];
return new GhostPost
{
Id = GetString(post, "id"),
Title = GetString(post, "title"),
Slug = GetString(post, "slug"),
Html = GetString(post, "html"),
FeatureImage = GetString(post, "feature_image"),
CreatedAt = GetDateTime(post, "created_at"),
UpdatedAt = GetDateTime(post, "updated_at"),
Status = GetString(post, "status")
};
}
return null;
}
public async Task<bool> UpdatePostAsync(GhostInstance instance, GhostPost post)
{
var request = CreateRequest(HttpMethod.Put, instance, $"posts/{post.Id}/?source=html");
var body = new
{
posts = new[]
{
new
{
id = post.Id,
title = post.Title,
html = post.Html,
status = post.Status,
feature_image = post.FeatureImage,
updated_at = post.UpdatedAt?.ToString("o")
}
}
};
request.Content = new StringContent(JsonSerializer.Serialize(body), Encoding.UTF8, "application/json");
var response = await _httpClient.SendAsync(request);
return response.IsSuccessStatusCode;
}
public async Task<string?> UploadImageAsync(GhostInstance instance, Stream fileStream, string fileName, string? reference = null)
{
var token = JwtTokenService.GenerateToken(instance.AdminApiKey);
var request = new HttpRequestMessage(HttpMethod.Post, $"{instance.Url.TrimEnd('/')}/ghost/api/admin/images/upload/");
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Ghost", token);
request.Headers.Add("Accept-Version", "v5.0");
var content = new MultipartFormDataContent();
var streamContent = new StreamContent(fileStream);
var ext = Path.GetExtension(fileName).ToLowerInvariant();
var mimeType = ext switch
{
".jpg" or ".jpeg" => "image/jpeg",
".png" => "image/png",
".gif" => "image/gif",
".webp" => "image/webp",
".svg" => "image/svg+xml",
_ => "application/octet-stream"
};
streamContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(mimeType);
content.Add(streamContent, "file", fileName);
if (!string.IsNullOrEmpty(reference))
content.Add(new StringContent(reference), "ref");
request.Content = content;
var response = await _httpClient.SendAsync(request);
if (!response.IsSuccessStatusCode) return null;
var json = await response.Content.ReadAsStringAsync();
var doc = JsonDocument.Parse(json);
if (doc.RootElement.TryGetProperty("images", out var images) && images.GetArrayLength() > 0)
{
return GetString(images[0], "url");
}
return null;
}
private HttpRequestMessage CreateRequest(HttpMethod method, GhostInstance instance, string endpoint)
{
var token = JwtTokenService.GenerateToken(instance.AdminApiKey);
var request = new HttpRequestMessage(method, $"{instance.Url.TrimEnd('/')}/ghost/api/admin/{endpoint}");
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Ghost", token);
request.Headers.Add("Accept-Version", "v5.0");
return request;
}
private static string GetString(JsonElement element, string property)
{
if (element.TryGetProperty(property, out var prop) && prop.ValueKind != JsonValueKind.Null)
return prop.GetString() ?? "";
return "";
}
private static DateTime? GetDateTime(JsonElement element, string property)
{
if (element.TryGetProperty(property, out var prop) && prop.ValueKind != JsonValueKind.Null)
if (DateTime.TryParse(prop.GetString(), out var dt))
return dt;
return null;
}
}
public class GhostImageReference
{
[JsonPropertyName("url")] public string Url { get; set; } = "";
[JsonPropertyName("ref")] public string? Ref { get; set; }
}