154 lines
4.9 KiB
C#
154 lines
4.9 KiB
C#
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
|
|
{
|
|
/// <summary>
|
|
/// Trello-Karten-Client für WinForms-Anwendungen (.NET Framework 4.8, C# 7.3)
|
|
/// Erstellt Karten via Trello REST API über HttpClient.
|
|
/// </summary>
|
|
public class TrelloCardClient : IDisposable
|
|
{
|
|
private readonly string _apiKey;
|
|
private readonly string _token;
|
|
private readonly HttpClient _httpClient;
|
|
|
|
/// <summary>
|
|
/// Initialisiert einen neuen TrelloCardClient.
|
|
/// </summary>
|
|
/// <param name="apiKey">Trello API Key</param>
|
|
/// <param name="token">Trello API Token mit write-Recht</param>
|
|
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/")
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// Erstellt eine neue Trello-Karte asynchron und gibt die Roh-JSON-Antwort zurück.
|
|
/// </summary>
|
|
/// <param name="options">Konfiguration der Karte (Name, Liste, Beschreibung, Labels, DueDate, StartDate)</param>
|
|
/// <returns>Antwort-JSON als String (enthaltend die erstellte Karte)</returns>
|
|
public async Task<string> CreateCardAsync(CreateCardOptions options)
|
|
{
|
|
ValidateOptions(options);
|
|
|
|
var values = new Dictionary<string, string>
|
|
{
|
|
["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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Erstellt eine Karte und gibt das Ergebnis als TrelloCard-Objekt zurück.
|
|
/// </summary>
|
|
public async Task<TrelloCard> 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));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt die Ressourcen des Clients frei (empiohlen).
|
|
/// </summary>
|
|
public void Dispose()
|
|
{
|
|
_httpClient?.Dispose();
|
|
}
|
|
}
|
|
}
|