Limited
2
0
Files
bmc.maui/BuyMeCofee.Maui/Services/BmcSupporterService.cs

94 lines
3.0 KiB
C#
Raw Normal View History

using System.Net.Http.Headers;
using System.Text.Json;
namespace BuyMeCofee.Maui.Services;
/// <summary>
/// Checks the Buy Me a Coffee API to determine whether a given email
/// belongs to a supporter (one-time or member). Results are cached.
/// </summary>
public class BmcSupporterService
{
private const string ApiBase = "https://developers.buymeacoffee.com/api/v1/";
private readonly HttpClient _http;
private readonly TimeSpan _cacheDuration;
private HashSet<string>? _cachedEmails;
private DateTime _cacheExpiry;
public BmcSupporterService(string accessToken, TimeSpan cacheDuration)
{
_cacheDuration = cacheDuration;
_http = new HttpClient { BaseAddress = new Uri(ApiBase) };
_http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", accessToken);
}
/// <summary>
/// Returns true if the given email matches any one-time supporter
/// or active/inactive member on the creator's BMC account.
/// </summary>
public async Task<bool> IsSupporterAsync(string email)
{
if (string.IsNullOrWhiteSpace(email)) return false;
var emails = await GetAllSupporterEmailsAsync();
return emails.Contains(email.Trim());
}
private async Task<HashSet<string>> GetAllSupporterEmailsAsync()
{
if (_cachedEmails != null && DateTime.UtcNow < _cacheExpiry)
return _cachedEmails;
var emails = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
await FetchEmailsFromEndpoint("supporters", emails);
await FetchEmailsFromEndpoint("subscriptions", emails);
_cachedEmails = emails;
_cacheExpiry = DateTime.UtcNow + _cacheDuration;
return emails;
}
private async Task FetchEmailsFromEndpoint(string endpoint, HashSet<string> emails)
{
try
{
var page = 1;
while (true)
{
var response = await _http.GetAsync($"{endpoint}?page={page}");
if (!response.IsSuccessStatusCode) break;
var json = await response.Content.ReadAsStringAsync();
using var doc = JsonDocument.Parse(json);
var root = doc.RootElement;
if (root.TryGetProperty("data", out var data))
{
foreach (var item in data.EnumerateArray())
{
if (item.TryGetProperty("payer_email", out var emailProp))
{
var email = emailProp.GetString();
if (!string.IsNullOrWhiteSpace(email))
emails.Add(email);
}
}
}
if (!root.TryGetProperty("next_page_url", out var nextPage) ||
nextPage.ValueKind == JsonValueKind.Null)
break;
page++;
}
}
catch
{
// Silently fail — don't block the app if BMC API is unreachable
}
}
}