using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace TrelloIntegration
{
///
/// Trello-Karten-Client für WinForms-Anwendungen (.NET Framework 4.8, C# 7.3)
/// Erstellt Karten via Trello REST API über HttpClient.
///
public class TrelloCardClient : IDisposable
{
private readonly string _apiKey;
private readonly string _token;
private readonly HttpClient _httpClient;
///
/// Initialisiert einen neuen TrelloCardClient.
///
/// Trello API Key
/// Trello API Token mit write-Recht
public TrelloCardClient(string apiKey, string token)
{
_apiKey = apiKey ?? throw new ArgumentNullException(nameof(apiKey));
_token = token ?? throw new ArgumentNullException(nameof(token));
_httpClient = new HttpClient
{
BaseAddress = new Uri("https://api.trello.com/1/")
};
}
///
/// Erstellt eine neue Trello-Karte asynchron und gibt die Roh-JSON-Antwort zurück.
///
/// Konfiguration der Karte (Name, Liste, Beschreibung, Labels, DueDate, StartDate)
/// Antwort-JSON als String (enthaltend die erstellte Karte)
public async Task CreateCardAsync(CreateCardOptions options)
{
ValidateOptions(options);
var values = new Dictionary
{
["key"] = _apiKey,
["token"] = _token,
["idList"] = options.IdList,
["name"] = options.Name
};
if (!string.IsNullOrWhiteSpace(options.Desc))
values["desc"] = options.Desc;
if (!string.IsNullOrWhiteSpace(options.Pos))
values["pos"] = options.Pos;
if (options.IdLabels != null && options.IdLabels.Count > 0)
values["idLabels"] = string.Join(",", options.IdLabels);
if (options.DueDate.HasValue)
values["due"] = options.DueDate.Value.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm");
if (options.StartDate.HasValue)
values["start"] = options.StartDate.Value.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm");
var content = new FormUrlEncodedContent(values);
var response = await _httpClient.PostAsync("cards", content);
var responseBody = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
throw new HttpRequestException(
$"Trello API Fehler {response.StatusCode}: {responseBody}");
}
return responseBody;
}
///
/// Erstellt eine Karte und gibt das Ergebnis als TrelloCard-Objekt zurück.
///
public async Task CreateCardAndParseAsync(CreateCardOptions options)
{
var json = await CreateCardAsync(options);
return ParseTrelloCard(json);
}
private static TrelloCard ParseTrelloCard(string json)
{
// Minimaler Parser ohne System.Text.Json (für .NET Framework 4.8)
// Extrahiert die wichtigsten Felder aus der JSON-Antwort
var card = new TrelloCard();
card.Id = ExtractJsonValue(json, "id");
card.Name = ExtractJsonValue(json, "name");
card.Desc = ExtractJsonValue(json, "desc");
card.IdList = ExtractJsonValue(json, "idList");
card.ShortUrl = ExtractJsonValue(json, "shortUrl");
var due = ExtractJsonValue(json, "due");
if (!string.IsNullOrWhiteSpace(due))
if (DateTime.TryParse(due, out var dtDue)) card.DueDate = dtDue;
else card.DueDate = null;
var start = ExtractJsonValue(json, "start");
if (!string.IsNullOrWhiteSpace(start))
if (DateTime.TryParse(start, out var dtStart)) card.StartDate = dtStart;
else card.StartDate = null;
return card;
}
private static string ExtractJsonValue(string json, string key)
{
// Einfacher JSON-String-Extractor für "key": "value"
var pattern = "\"" + key + "\"\\s*:\\s*\"";
var startIndex = json.IndexOf(pattern, StringComparison.Ordinal);
if (startIndex < 0)
return null;
startIndex += pattern.Length;
var endIndex = json.IndexOf("\"", startIndex);
if (endIndex < 0)
return null;
return json.Substring(startIndex, endIndex - startIndex);
}
private void ValidateOptions(CreateCardOptions options)
{
if (options == null)
throw new ArgumentNullException(nameof(options));
if (string.IsNullOrWhiteSpace(options.Name))
throw new ArgumentException("Name ist erforderlich.", nameof(options.Name));
if (string.IsNullOrWhiteSpace(options.IdList))
throw new ArgumentException("IdList ist erforderlich.", nameof(options.IdList));
}
///
/// Gibt die Ressourcen des Clients frei (empiohlen).
///
public void Dispose()
{
_httpClient?.Dispose();
}
}
}