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.
This commit is contained in:
parent
1f61958099
commit
10e5fe9f3c
11 changed files with 436 additions and 204 deletions
46
Database.cs
46
Database.cs
|
|
@ -7,7 +7,6 @@ namespace GroupVerify;
|
|||
internal sealed class Database(string connectionString)
|
||||
{
|
||||
private const string MigrationPrefix = "GroupVerify.Migrations.";
|
||||
private const int UpsertBatch = 500;
|
||||
|
||||
// What a reload hands back to the game thread.
|
||||
public sealed record Snapshot(
|
||||
|
|
@ -138,35 +137,28 @@ internal sealed class Database(string connectionString)
|
|||
await command.ExecuteNonQueryAsync();
|
||||
}
|
||||
|
||||
// Saves a fetched group list: upserts a 'group' row for every member (keeping created_at), then
|
||||
// deletes the 'group' rows of anyone no longer in it. One transaction, so a failure keeps the
|
||||
// previous list whole.
|
||||
public async Task SaveGroupAsync(IReadOnlyCollection<ulong> members, DateTime now)
|
||||
// Records one player's group membership from a Steam check: a member gets or refreshes their
|
||||
// 'group' row (keeping created_at, the first time they were seen in it); anyone else loses it.
|
||||
public async Task SetGroupMemberAsync(ulong steamId, bool member, DateTime now)
|
||||
{
|
||||
await using var connection = await OpenAsync();
|
||||
await using var transaction = await connection.BeginTransactionAsync();
|
||||
var sql = member
|
||||
? """
|
||||
INSERT INTO gv_verified (steamid64, source, `override`, expires_at, added_by, created_at, updated_at)
|
||||
VALUES (@steamid, 'group', 0, NULL, 'steam-group', @now, @now)
|
||||
ON DUPLICATE KEY UPDATE updated_at = @now
|
||||
"""
|
||||
: "DELETE FROM gv_verified WHERE steamid64 = @steamid AND source = 'group'";
|
||||
await using var command = Command(connection, sql, ("@steamid", (long)steamId), ("@now", now));
|
||||
await command.ExecuteNonQueryAsync();
|
||||
}
|
||||
|
||||
foreach (var batch in members.Chunk(UpsertBatch))
|
||||
{
|
||||
var rows = string.Join(", ", batch.Select((_, i) => $"(@s{i}, 'group', 0, NULL, 'steam-group', @now, @now)"));
|
||||
var parameters = batch.Select((id, i) => ($"@s{i}", (object?)(long)id)).Append(("@now", now)).ToArray();
|
||||
await using var command = Command(connection, $"""
|
||||
INSERT INTO gv_verified (steamid64, source, `override`, expires_at, added_by, created_at, updated_at)
|
||||
VALUES {rows}
|
||||
ON DUPLICATE KEY UPDATE updated_at = @now
|
||||
""", parameters);
|
||||
command.Transaction = transaction;
|
||||
await command.ExecuteNonQueryAsync();
|
||||
}
|
||||
|
||||
await using (var command = Command(connection,
|
||||
"DELETE FROM gv_verified WHERE source = 'group' AND updated_at < @now", ("@now", now)))
|
||||
{
|
||||
command.Transaction = transaction;
|
||||
await command.ExecuteNonQueryAsync();
|
||||
}
|
||||
|
||||
await transaction.CommitAsync();
|
||||
// Forgets every 'group' row, when the group changes: they belong to the old one.
|
||||
public async Task ClearGroupRowsAsync()
|
||||
{
|
||||
await using var connection = await OpenAsync();
|
||||
await using var command = Command(connection, "DELETE FROM gv_verified WHERE source = 'group'");
|
||||
await command.ExecuteNonQueryAsync();
|
||||
}
|
||||
|
||||
// Whether a player may use css_verify: one of their SimpleAdmin groups has at least minRank's
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue