Docker Compose bot + Google Api
Build App / Build (push) Failing after 3s

This commit is contained in:
2026-08-06 16:23:50 +02:00
parent c9a3c252e1
commit 937b8554dd
44 changed files with 3360 additions and 74 deletions
@@ -0,0 +1,42 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using LaDOSE.Entity;
namespace LaDOSE.Business.Interface
{
public interface ISheetsExportService
{
/// <summary>What the export panel needs to render. Never includes a secret.</summary>
SheetsConfig GetConfig();
/// <summary>
/// Resolves the target spreadsheet from configuration, validates the tables, sanitises
/// and de-duplicates the tab titles, then hands off to the configured
/// <see cref="ISheetsWriter"/>. Throws <see cref="SheetsExportException"/> for anything
/// the caller can act on.
/// </summary>
Task<SheetExportResult> ExportAsync(SheetExportRequest request, CancellationToken ct = default);
}
/// <summary>
/// A failure with a message meant for the person who pressed the button, plus the status
/// the API should answer with. The API has no exception middleware, so anything that escapes
/// reaches the browser as an HTML developer page the client can only report as a bare status
/// — hence every foreseeable failure is raised as one of these instead.
/// </summary>
public class SheetsExportException : Exception
{
public SheetsExportException(int statusCode, string message) : base(message)
{
StatusCode = statusCode;
}
public SheetsExportException(int statusCode, string message, Exception inner) : base(message, inner)
{
StatusCode = statusCode;
}
public int StatusCode { get; }
}
}
@@ -0,0 +1,26 @@
using System.Threading;
using System.Threading.Tasks;
using LaDOSE.Entity;
namespace LaDOSE.Business.Interface
{
/// <summary>
/// Writes tabular data into a Google Spreadsheet. Startup picks one implementation from
/// GoogleSheets:Writer, so nothing above this interface knows how Google is reached.
///
/// Implementations must be idempotent: writing the same request twice leaves the same
/// spreadsheet. They must also leave tabs they were not asked about completely alone —
/// the spreadsheet holds hand-made summaries and charts, and deletion is irreversible
/// through the API.
/// </summary>
public interface ISheetsWriter
{
/// <summary>Reported to the UI so the panel can say what it is talking to.</summary>
string Name { get; }
/// <summary>False when credentials are missing, so the API can answer 503 with a message.</summary>
bool IsConfigured { get; }
Task<SheetExportResult> WriteTablesAsync(SheetExportRequest request, CancellationToken ct = default);
}
}
@@ -12,5 +12,19 @@ namespace LaDOSE.Business.Interface
/// A null or empty id list yields a well-formed, zeroed <see cref="MatchStats"/>.
/// </summary>
Task<MatchStats> GetMatchStats(List<int> eventIds);
/// <summary>
/// The players a versus lookup can say something about: those with at least one
/// set in a bracket whose game is known, by display name.
/// </summary>
Task<List<PlayerOption>> GetVersusPlayers();
/// <summary>
/// Every recorded meeting between two players, all events, broken down per game.
/// Sets whose bracket has no game are excluded and only counted in
/// <see cref="PlayerVersus.UnknownGameSets"/>.
/// Missing, equal or unknown ids yield a well-formed empty <see cref="PlayerVersus"/>.
/// </summary>
Task<PlayerVersus> GetVersus(int playerAId, int playerBId);
}
}