Admin/AdminClient.cs

Data models and API wrappers for the in-game staff administration menu. Holds cached log, player file and player-search responses in AdminClient, and posts the serverStaff* actions (logs, file, search, ban, unban, money, rename) through Backend.Post.

namespace HorizonRP;

/// <summary>
/// Côté staff : ce que l'hôte a lu dans l'API pour le menu d'administration
/// (journal, fiche d'un joueur, recherche de joueurs). Rien n'est gardé d'une partie à l'autre.
/// </summary>
public static class AdminClient
{
	/// <summary>Le journal demandé ; null tant qu'il n'est pas arrivé ou si l'API ne répond pas.</summary>
	public static List<Backend.StaffLog> Logs { get; set; }

	/// <summary>Le joueur dont c'est le journal ; 0 pour le journal général.</summary>
	public static ulong LogsFor { get; set; }

	/// <summary>Ce que la base sait du joueur choisi, connecté ou non (serverStaffPlayer).</summary>
	public static Backend.StaffFileResponse File { get; set; }
	public static ulong FileFor { get; set; }

	/// <summary>La recherche de joueurs en base (serverStaffPlayers) ; null tant qu'elle n'est pas arrivée.</summary>
	public static Backend.StaffPlayersResponse Found { get; set; }

	/// <summary>Change à chaque réponse : l'interface se redessine.</summary>
	public static int Version { get; set; }
}

/// <summary>
/// Les appels de l'API propres au menu d'administration en jeu, rangés ici avec ce qu'ils
/// rapportent (actions serverStaff* d'api.php, clé du serveur, signées du nom du staff).
/// </summary>
public static partial class Backend
{
	/// <summary>Un joueur tel que la base le connaît (playerOut d'api.php), connecté ou non.</summary>
	public sealed class StaffPlayerRow
	{
		public string SteamId { get; set; }
		public string DisplayName { get; set; }
		public string RpName { get; set; }
		public int Wallet { get; set; }
		public int Bank { get; set; }
		public string Job { get; set; }
		public bool Online { get; set; }
		public int Playtime { get; set; }
		public string FirstSeen { get; set; }
		public string LastSeen { get; set; }
		public bool Banned { get; set; }
		public string BanReason { get; set; }
		public string BannedUntil { get; set; }
		public string BannedBy { get; set; }
		public string Phone { get; set; }

		public ulong Id => ulong.TryParse( SteamId, out var id ) ? id : 0;
		public string Name => string.IsNullOrWhiteSpace( RpName ) ? DisplayName : RpName;
	}

	public sealed class StaffPlayersResponse
	{
		public bool Ok { get; set; }
		public string Error { get; set; }
		public int Total { get; set; }
		public int Page { get; set; }
		public int Pages { get; set; }
		public List<StaffPlayerRow> Players { get; set; }
	}

	/// <summary>La fiche : ce que le panneau sait d'un joueur et que le jeu n'a pas (ou plus, s'il est parti).</summary>
	public sealed class StaffFileResponse
	{
		public bool Ok { get; set; }
		public string Error { get; set; }
		public StaffPlayerRow Player { get; set; }
		public string Notes { get; set; }
		public string FirstSeen { get; set; }
		public int Playtime { get; set; }
		public List<StaffVehicle> Vehicles { get; set; }
		public int Captures { get; set; }
		public List<StaffLog> Logs { get; set; }
	}

	/// <summary>Une écriture du menu : réussie ou non, et la phrase à montrer au staff.</summary>
	public sealed class StaffAnswer
	{
		public bool Ok { get; set; }
		public string Error { get; set; }
		public string Message { get; set; }
	}

	/// <summary>Le journal, filtré aussi par source : « jeu », « admin » (le panneau web) ou "" pour tout.</summary>
	public static Task<StaffLogsResponse> StaffLogs( string q, ulong steamId, int limit, string source )
		=> Post<StaffLogsResponse>( "serverStaffLogs", new { q, steamId = steamId == 0 ? "" : steamId.ToString(), limit, source } );

	public static Task<StaffFileResponse> StaffFile( ulong steamId )
		=> Post<StaffFileResponse>( "serverStaffPlayer", new { steamId = steamId.ToString() } );

	/// <summary>Nom RP, pseudo ou SteamID ; filtre « tous », « enligne », « horsligne » ou « bannis ».</summary>
	public static Task<StaffPlayersResponse> StaffPlayers( string q, string filter, int page )
		=> Post<StaffPlayersResponse>( "serverStaffPlayers", new { q, filter, page } );

	public static Task<StaffAnswer> StaffBanOffline( ulong steamId, int hours, string reason, string by )
		=> Post<StaffAnswer>( "serverStaffBan", new { steamId = steamId.ToString(), hours, reason, by } );

	public static Task<StaffAnswer> StaffUnban( ulong steamId, string by )
		=> Post<StaffAnswer>( "serverStaffUnban", new { steamId = steamId.ToString(), by } );

	/// <summary>Hors ligne : « portefeuille » ou « banque » fixé à <paramref name="value"/>.</summary>
	public static Task<StaffAnswer> StaffMoney( ulong steamId, string type, int value, string by )
		=> Post<StaffAnswer>( "serverStaffMoney", new { steamId = steamId.ToString(), type, value, by } );

	/// <summary>Hors ligne : « Prénom|Nom ».</summary>
	public static Task<StaffAnswer> StaffRename( ulong steamId, string text, string by )
		=> Post<StaffAnswer>( "serverStaffRename", new { steamId = steamId.ToString(), text, by } );
}