GroupVerify/GroupVerifyApi/IGroupVerifyApi.cs
Astra 10e5fe9f3c GroupVerify 0.3.0: check players with the Steam Web API as they join, clan tag for other plugins
Steam rate-limits its community member lists by IP (429), so the whole-list download is gone.
Each player is checked as they join with ISteamUser/GetUserGroupList: a member's 'group' row is
added or refreshed, a non-member's deleted, and when Steam won't say (private profile, bad key,
outage) the database stands. A player is asked about at most once per
min_forced_refresh_seconds; css_verify rechecks its targets, offline SteamIDs too. Changing the
group clears the old group's rows. refresh_minutes is gone.

The Web API key goes in configs/plugins/GroupVerify/GroupVerify.json (SteamWebApiKey); every
other setting stays in the database.

New clan_tag setting and css_gv_clantag <tag|-> (@css/root): the scoreboard tag for verified
players without a rank, applied by CS2-Tags. The API gains ClanTag and OnClanTagChanged, so
shared/GroupVerifyApi changes: needs a server restart.
2026-10-02 18:42:41 +01:00

69 lines
3.1 KiB
C#

using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Core.Capabilities;
namespace GroupVerifyApi;
/// <summary>
/// Whether players are verified by GroupVerify: in the configured Steam group, or given a manual
/// override on the web panel. Get it in <c>OnAllPluginsLoaded</c> with
/// <c>IGroupVerifyApi.Capability.Get()</c>. Use it on the game thread only.
/// </summary>
/// <remarks>
/// The object stays valid when GroupVerify is hot-reloaded, and event subscriptions stay attached.
/// While GroupVerify is unloaded, disabled or has no group set, <see cref="IsActive"/> is false and
/// nobody is verified.
/// </remarks>
public interface IGroupVerifyApi
{
/// <summary>The capability GroupVerify registers.</summary>
public static readonly PluginCapability<IGroupVerifyApi> Capability = new("groupverify:api");
/// <summary>
/// True when GroupVerify is loaded, enabled, has a Steam group set and has read its database.
/// When false, every check returns not verified.
/// </summary>
bool IsActive { get; }
/// <summary>
/// Whether the player is verified. False for bots and players Steam hasn't authorized yet.
/// </summary>
bool IsVerified(CCSPlayerController player);
/// <summary>Whether a SteamID64 is verified, online or not.</summary>
bool IsVerified(ulong steamId64);
/// <summary>Why a SteamID64 is or isn't verified, online or not.</summary>
VerifyStatus GetStatus(ulong steamId64);
/// <summary>
/// Fired on the game thread when an online player's verified status changes: true when they
/// become verified (including right after connecting), false when they stop being verified
/// (they left the group, their override ran out, or GroupVerify was disabled). Not fired on
/// disconnect. After GroupVerify is hot-reloaded it fires true again for everyone verified,
/// so handlers should be idempotent.
/// </summary>
event Action<CCSPlayerController, VerifyStatus>? OnVerifiedChanged;
/// <summary>
/// The scoreboard clan tag for verified players who have no rank tag of their own (gv_settings
/// clan_tag, set with css_gv_clantag or the web panel), up to 12 characters, without brackets.
/// Empty when none is set, and while <see cref="IsActive"/> is false.
/// </summary>
string ClanTag { get; }
/// <summary>
/// Fired on the game thread when <see cref="ClanTag"/> changes, including to or from empty as
/// GroupVerify is turned on or off, loaded or unloaded. Re-tag everyone when it fires.
/// </summary>
event Action? OnClanTagChanged;
}
/// <summary>A player's verification, and why.</summary>
/// <param name="InGroup">In the Steam group's member list.</param>
/// <param name="HasOverride">Has an unexpired manual override.</param>
/// <param name="OverrideExpires">When the override ends, in GroupVerify's database time zone; null if it never does (or there's none).</param>
public readonly record struct VerifyStatus(bool InGroup, bool HasOverride, DateTime? OverrideExpires)
{
/// <summary>In the group, or has an override.</summary>
public bool Verified => InGroup || HasOverride;
}