Files
ChronoCCG/Chrono/Web/Services/CardNotesGraphQLService.cs
6d486f49 ffaab59585 ...
2026-09-09 17:19:03 -04:00

195 lines
6.2 KiB
C#

using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text.Json.Serialization;
using Model;
namespace Web.Services;
public class CardNotesGraphQLService
{
private readonly AuthService _authService;
private readonly string _graphqlEndpoint;
private readonly HttpClient _http;
private readonly NetworkStatusService _networkStatus;
public CardNotesGraphQLService(HttpClient http, NetworkStatusService networkStatus, AuthService authService)
{
_http = http;
_networkStatus = networkStatus;
_authService = authService;
_graphqlEndpoint = http.BaseAddress != null && http.BaseAddress.Port == 7266
? "/graphql"
: "https://localhost:7266/graphql";
}
public async Task<bool> IsApiOnlineAsync()
{
if (!_networkStatus.IsOnline) return false;
try
{
var request = new GraphQLRequest
{
Query = "query { __typename }"
};
var response = await SendGraphQLAsync<object>(request);
return response != null;
}
catch
{
return false;
}
}
public async Task<string> GetNoteAsync(string cardName)
{
if (!_networkStatus.IsOnline || !_authService.IsLoggedIn) return string.Empty;
try
{
var request = new GraphQLRequest
{
Query = @"query GetCardNote($cardName: String!) {
note(cardName: $cardName) {
username
cardName
note
}
}",
Variables = new Dictionary<string, object>
{
["cardName"] = cardName
}
};
var response = await SendGraphQLAsync<GetNoteData>(request);
return response?.Data?.Note?.Note ?? string.Empty;
}
catch (Exception ex)
{
Console.WriteLine($"[WARNING] Failed to fetch note for {cardName}: {ex.Message}");
return string.Empty;
}
}
public async Task<bool> SaveNoteAsync(string cardName, string note)
{
if (!_networkStatus.IsOnline || !_authService.IsLoggedIn) return false;
try
{
var request = new GraphQLRequest
{
Query = @"mutation SaveCardNote($cardName: String!, $note: String!) {
saveNote(cardName: $cardName, note: $note) {
username
cardName
note
}
}",
Variables = new Dictionary<string, object>
{
["cardName"] = cardName,
["note"] = note
}
};
var response = await SendGraphQLAsync<SaveNoteData>(request);
return response?.Data?.SaveNote != null;
}
catch (Exception ex)
{
Console.WriteLine($"[WARNING] Failed to save note for {cardName}: {ex.Message}");
return false;
}
}
private async Task<GraphQLResponse<T>?> SendGraphQLAsync<T>(GraphQLRequest request)
{
async Task<HttpResponseMessage> SendToUrlAsync(string url)
{
var httpRequest = new HttpRequestMessage(HttpMethod.Post, url)
{
Content = JsonContent.Create(request)
};
if (!string.IsNullOrEmpty(_authService.AuthToken))
httpRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _authService.AuthToken);
return await _http.SendAsync(httpRequest);
}
try
{
var httpResponse = await SendToUrlAsync(_graphqlEndpoint);
if (httpResponse.IsSuccessStatusCode)
return await httpResponse.Content.ReadFromJsonAsync<GraphQLResponse<T>>();
if (_graphqlEndpoint == "/graphql" || _graphqlEndpoint.StartsWith("https://"))
{
var fallbackUrl = _graphqlEndpoint == "/graphql"
? "https://localhost:7266/graphql"
: "http://localhost:7266/graphql";
var fallbackResponse = await SendToUrlAsync(fallbackUrl);
if (fallbackResponse.IsSuccessStatusCode)
return await fallbackResponse.Content.ReadFromJsonAsync<GraphQLResponse<T>>();
}
}
catch
{
try
{
var fallbackUrl = _graphqlEndpoint.StartsWith("http://")
? "https://localhost:7266/graphql"
: "http://localhost:7266/graphql";
var fallbackResponse = await SendToUrlAsync(fallbackUrl);
if (fallbackResponse.IsSuccessStatusCode)
return await fallbackResponse.Content.ReadFromJsonAsync<GraphQLResponse<T>>();
}
catch
{
if (_graphqlEndpoint == "/graphql")
{
try
{
var fallbackHttp = await SendToUrlAsync("http://localhost:7266/graphql");
if (fallbackHttp.IsSuccessStatusCode)
return await fallbackHttp.Content.ReadFromJsonAsync<GraphQLResponse<T>>();
}
catch
{
}
}
}
}
return null;
}
public class GraphQLRequest
{
[JsonPropertyName("query")] public string Query { get; set; } = string.Empty;
[JsonPropertyName("variables")] public Dictionary<string, object>? Variables { get; set; }
}
public class GraphQLResponse<T>
{
[JsonPropertyName("data")] public T? Data { get; set; }
[JsonPropertyName("errors")] public List<GraphQLError>? Errors { get; set; }
}
public class GraphQLError
{
[JsonPropertyName("message")] public string Message { get; set; } = string.Empty;
}
public class GetNoteData
{
[JsonPropertyName("note")] public CardNote? Note { get; set; }
}
public class SaveNoteData
{
[JsonPropertyName("saveNote")] public CardNote? SaveNote { get; set; }
}
}