From 4fc8f0f1bb0e65b26457778a29f630f629676090 Mon Sep 17 00:00:00 2001 From: Brett Date: Thu, 30 Jan 2025 23:13:43 -0400 Subject: [PATCH] new tg era patch (REAL) (OFFICIAL) --- CentCom.Server/BanSources/TgBanParser.cs | 20 ++- CentCom.Server/External/Raw/TgRawBan.cs | 164 ++++++++++++----------- CentCom.Server/External/TgApiResponse.cs | 24 +++- CentCom.Server/Services/TgBanService.cs | 54 +++----- 4 files changed, 137 insertions(+), 125 deletions(-) diff --git a/CentCom.Server/BanSources/TgBanParser.cs b/CentCom.Server/BanSources/TgBanParser.cs index 1383efa..c7bab4c 100644 --- a/CentCom.Server/BanSources/TgBanParser.cs +++ b/CentCom.Server/BanSources/TgBanParser.cs @@ -47,6 +47,24 @@ public override async Task> FetchNewBansAsync() .Include(x => x.JobBans) .Include(x => x.SourceNavigation) .ToListAsync(); - return await _banService.GetBansBatchedAsync(searchFor: recent.Select(x => x.Id)); + + var foundBans = new List(); + var page = 1; + while (true) + { + var bans = await _banService.GetBansAsync(page); + if (bans.Count == 0) + break; + + foundBans.AddRange(bans.Select(x => x.AsBan(Sources["tgstation"]))); + + // Check for existing bans + if (foundBans.Any(x => recent.Any(y => y.BanID == x.BanID))) + break; + + page++; + } + + return foundBans.DistinctBy(x => x.BanID); } } \ No newline at end of file diff --git a/CentCom.Server/External/Raw/TgRawBan.cs b/CentCom.Server/External/Raw/TgRawBan.cs index 7f13049..a6eee0e 100644 --- a/CentCom.Server/External/Raw/TgRawBan.cs +++ b/CentCom.Server/External/Raw/TgRawBan.cs @@ -1,106 +1,112 @@ -using System; -using System.Globalization; +using System; +using System.Collections.Generic; +using System.Linq; using System.Text.Json.Serialization; using CentCom.Common.Extensions; using CentCom.Common.Models; namespace CentCom.Server.External.Raw; -public class TgRawBan : IRawBan +public class TgUser { - private string _bannedAt; - private string _expirationTime; - private string _unbannedAt; - - [JsonPropertyName("id")] - public int Id { get; set; } - - [JsonPropertyName("expiration_time")] - public string ExpirationTimeRaw - { - get => _expirationTime; set - { - _expirationTime = value; - ExpirationTime = ParseTgDateTime(value); - } - } - - public DateTime? ExpirationTime { get; private set; } - - [JsonPropertyName("role")] - public string Role { get; set; } - [JsonPropertyName("ckey")] public string CKey { get; set; } + + [JsonPropertyName("userIdentifier")] + public string UserIdentifier { get; set; } +} - [JsonPropertyName("a_ckey")] - public string AdminCKey { get; set; } +public class TgServer +{ + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("identifier")] + public string Identifier { get; set; } + + [JsonPropertyName("port")] + public int Port { get; set; } + + [JsonPropertyName("address")] + public string Address { get; set; } + + [JsonPropertyName("url")] + public string Url { get; set; } + + [JsonPropertyName("publicLogs")] + public string PublicLogsUrl { get; set; } + + [JsonPropertyName("rawLogs")] + public string RawLogsUrl { get; set; } + + [JsonPropertyName("round")] + public int Round { get; set; } +} +public class TgRawBan : IRawBan +{ + [JsonPropertyName("id")] + public int Id { get; set; } + + [JsonPropertyName("admin")] + public TgUser Admin { get; set; } + + [JsonPropertyName("target")] + public TgUser Target { get; set; } + + [JsonPropertyName("unbanner")] + public TgUser? Unbanner { get; set; } + + [JsonPropertyName("roles")] + public List Roles { get; set; } + + [JsonPropertyName("bantime")] + public DateTimeOffset BanTime { get; set; } + + [JsonPropertyName("unbannedTime")] + public DateTimeOffset? UnbannedTime { get; set; } + + [JsonPropertyName("round")] + public int Round { get; set; } + + [JsonPropertyName("status")] + public string Status { get; set; } + [JsonPropertyName("reason")] public string Reason { get; set; } - - [JsonPropertyName("bantime")] - public string BannedAtRaw - { - get => _bannedAt; set - { - _bannedAt = value; - BannedAt = ParseTgDateTime(value).Value; - } - } - - public DateTime BannedAt { get; private set; } - - [JsonPropertyName("unbanned_datetime")] - public string UnbannedAtRaw - { - get => _unbannedAt; set - { - _unbannedAt = value; - UnbannedAt = ParseTgDateTime(value); - } - } - - public DateTime? UnbannedAt { get; private set; } - - [JsonPropertyName("unbanned_Ckey")] - public string UnbannedBy { get; set; } - - public BanType GetBanType() => Role.ToLower() == "server" ? BanType.Server : BanType.Job; + + [JsonPropertyName("server")] + public TgServer Server { get; set; } + + [JsonPropertyName("expiration")] + public DateTimeOffset? Expiration { get; set; } + + [JsonPropertyName("banIds")] + public List BanIds { get; set; } + + public BanType GetBanType() => Roles.Count == 1 && Roles[0] == "Server" ? BanType.Server : BanType.Job; public Ban AsBan(BanSource source) { var toReturn = new Ban { - BanID = Id.ToString(), - BannedBy = AdminCKey, - BannedOn = BannedAt, + SourceNavigation = source, BanType = GetBanType(), - CKey = CKey, - UnbannedBy = UnbannedBy, + CKey = Target.CKey, + BannedOn = BanTime.UtcDateTime, + BannedBy = Admin.CKey, Reason = Reason, - Expires = UnbannedAt ?? ExpirationTime, - SourceNavigation = source + Expires = Expiration?.UtcDateTime, + UnbannedBy = Unbanner?.CKey, + BanID = string.Join(";", BanIds), + JobBans = null, + BanAttributes = (BanAttribute)0 }; + // Add job bans if relevant if (toReturn.BanType == BanType.Job) - { - toReturn.AddJob(Role); - } + toReturn.AddJobRange(Roles); return toReturn; } - - private static DateTime? ParseTgDateTime(string value) - { - if (DateTime.TryParse(value, - CultureInfo.InvariantCulture.DateTimeFormat, - DateTimeStyles.AllowWhiteSpaces, - out var expiration)) - { - return expiration; - } - - return null; - } } \ No newline at end of file diff --git a/CentCom.Server/External/TgApiResponse.cs b/CentCom.Server/External/TgApiResponse.cs index ef0179a..105ed4a 100644 --- a/CentCom.Server/External/TgApiResponse.cs +++ b/CentCom.Server/External/TgApiResponse.cs @@ -1,14 +1,26 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Text.Json.Serialization; using CentCom.Server.External.Raw; namespace CentCom.Server.External; -public class TgApiResponse +public class TgApiPagination { - [JsonPropertyName("beforeid")] - public int BeforeId { get; set; } + [JsonPropertyName("items")] + public int Items { get; set; } + + [JsonPropertyName("page")] + public int Page { get; set; } + + [JsonPropertyName("per_page")] + public int PerPage { get; set; } +} - [JsonPropertyName("bans")] - public IEnumerable Bans { get; set; } +public class TgApiResponse +{ + [JsonPropertyName("data")] + public IEnumerable Data { get; set; } + + [JsonPropertyName("pagination")] + public TgApiPagination Pagination { get; set; } } \ No newline at end of file diff --git a/CentCom.Server/Services/TgBanService.cs b/CentCom.Server/Services/TgBanService.cs index 62fcb8d..07a1994 100644 --- a/CentCom.Server/Services/TgBanService.cs +++ b/CentCom.Server/Services/TgBanService.cs @@ -4,7 +4,6 @@ using System.Text.Json; using System.Text.Json.Serialization; using System.Threading.Tasks; -using CentCom.Common.Extensions; using CentCom.Common.Models; using CentCom.Server.External; using CentCom.Server.External.Raw; @@ -28,57 +27,34 @@ public TgBanService(ILogger logger) : base(logger) })); } - protected override string BaseUrl => "https://tgstation13.org/"; + protected override string BaseUrl => "https://statbus.space/"; - private async Task> GetBansAsync(int? startingId = null) + public async Task> GetBansAsync(int? page = null) { - var request = new RestRequest("tgdb/publicbans.php") - .AddQueryParameter("format", "json"); - if (startingId.HasValue) - request.AddQueryParameter("beforeid", startingId.ToString()); + var request = new RestRequest($"bans/public/v1/{page}") + .AddQueryParameter("json", "true"); var response = await Client.ExecuteAsync(request); if (response.StatusCode != HttpStatusCode.OK) FailedRequest(response); - return response.Data.Bans.ToList(); + return response.Data.Data.ToList(); } - public async Task> GetBansBatchedAsync(int? startingId = null, IEnumerable searchFor = null) + public async Task> GetBansBatchedAsync() { - // Get bans, must use a sequential approach here due to the last ban - // ID only being available once we finish a page - var dirtyBans = new List(); - var lastRequested = startingId; - List lastResponse; - do + var allBans = new List(); + var page = 1; + while (true) { - lastResponse = await GetBansAsync(lastRequested); - if (!lastResponse.Any()) + var bans = await GetBansAsync(page); + if (bans.Count == 0) break; - - // If the last ban on the page is a job ban, get the next page to ensure we have the full ban - if (lastResponse[^1].GetBanType() == BanType.Job) - { - var nextPage = await GetBansAsync(lastResponse[^1].Id); - lastResponse.AddRange(nextPage.Where(x => x.CKey == lastResponse[^1].CKey && x.BannedAt == lastResponse[^1].BannedAt)); - } - - lastRequested = lastResponse.Min(x => x.Id); - dirtyBans.AddRange(lastResponse); - } - while (lastResponse.Any() && (searchFor == null || lastResponse.Any(x => searchFor.Contains(x.Id)))); - - // Flatten any jobbans - var intermediateBans = dirtyBans.Select(x => x.AsBan(BanSource)); - var cleanBans = intermediateBans.Where(x => x.BanType == BanType.Server).ToList(); - foreach (var group in intermediateBans.Where(x => x.BanType == BanType.Job).GroupBy(x => new { x.CKey, x.BannedOn })) - { - var firstBan = group.OrderBy(x => x.BanID).First(); - firstBan.AddJobRange(group.SelectMany(x => x.JobBans).Select(x => x.Job)); - cleanBans.Add(firstBan); + + allBans.AddRange(bans); + page++; } - return cleanBans; + return allBans.Select(x => x.AsBan(BanSource)).DistinctBy(x => x.BanID); } } \ No newline at end of file