From 27c28aafcda0724a2fffe7031edfae535bb08004 Mon Sep 17 00:00:00 2001 From: flashwave Date: Wed, 8 Feb 2023 01:01:55 +0100 Subject: [PATCH] Don't use a stinky Timer for user bumps and exclude AFK. --- SharpChat/ChatContext.cs | 16 +--------- SharpChat/Flashii/FlashiiBump.cs | 47 ------------------------------ SharpChat/Flashii/FlashiiUrls.cs | 50 ++++++++++++++++++++++++++++++-- SharpChat/Program.cs | 4 ++- SharpChat/SockChatServer.cs | 22 +++++++++++++- SharpChat/UserManager.cs | 4 +++ 6 files changed, 77 insertions(+), 66 deletions(-) delete mode 100644 SharpChat/Flashii/FlashiiBump.cs diff --git a/SharpChat/ChatContext.cs b/SharpChat/ChatContext.cs index 1632fd9..13e589a 100644 --- a/SharpChat/ChatContext.cs +++ b/SharpChat/ChatContext.cs @@ -1,35 +1,22 @@ using SharpChat.Events; -using SharpChat.Flashii; using SharpChat.Packet; using System; using System.Collections.Generic; -using System.Net; -using System.Net.Http; -using System.Threading; namespace SharpChat { public class ChatContext : IDisposable, IPacketTarget { public bool IsDisposed { get; private set; } - private readonly HttpClient HttpClient; - - public SockChatServer Server { get; } - public Timer BumpTimer { get; } - public ChannelManager Channels { get; } public UserManager Users { get; } public ChatEventManager Events { get; } public string TargetName => @"@broadcast"; - public ChatContext(HttpClient httpClient, SockChatServer server) { - HttpClient = httpClient; - Server = server; + public ChatContext() { Users = new(this); Channels = new(this); Events = new(this); - - BumpTimer = new Timer(e => FlashiiBump.SubmitAsync(HttpClient, Users.WithActiveConnections()).Wait(), null, TimeSpan.Zero, TimeSpan.FromMinutes(1)); } public void Update() { @@ -173,7 +160,6 @@ namespace SharpChat { return; IsDisposed = true; - BumpTimer?.Dispose(); Events?.Dispose(); Channels?.Dispose(); Users?.Dispose(); diff --git a/SharpChat/Flashii/FlashiiBump.cs b/SharpChat/Flashii/FlashiiBump.cs deleted file mode 100644 index 54809e9..0000000 --- a/SharpChat/Flashii/FlashiiBump.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Text.Json; -using System.Text.Json.Serialization; -using System.Threading.Tasks; - -namespace SharpChat.Flashii { - public class FlashiiBump { - [JsonPropertyName(@"id")] - public long UserId { get; set; } - - [JsonPropertyName(@"ip")] - public string UserIP { get; set; } - - public static async Task SubmitAsync(HttpClient httpClient, IEnumerable users) { - FlashiiBump[] bups = users.Where(u => u.HasSessions).Select(x => new FlashiiBump { - UserId = x.UserId, - UserIP = x.RemoteAddresses.First().ToString() - }).ToArray(); - - if(bups.Any()) - await SubmitAsync(httpClient, bups); - } - - public static async Task SubmitAsync(HttpClient httpClient, IEnumerable users) { - if(httpClient == null) - throw new ArgumentNullException(nameof(httpClient)); - if(users == null) - throw new ArgumentNullException(nameof(users)); - if(!users.Any()) - return; - - byte[] data = JsonSerializer.SerializeToUtf8Bytes(users); - - HttpRequestMessage request = new(HttpMethod.Post, FlashiiUrls.BumpURL) { - Content = new ByteArrayContent(data), - Headers = { - { @"X-SharpChat-Signature", data.GetSignedHash() }, - } - }; - - await httpClient.SendAsync(request); - } - } -} diff --git a/SharpChat/Flashii/FlashiiUrls.cs b/SharpChat/Flashii/FlashiiUrls.cs index 1b1302b..041d858 100644 --- a/SharpChat/Flashii/FlashiiUrls.cs +++ b/SharpChat/Flashii/FlashiiUrls.cs @@ -1,12 +1,18 @@ -using System.IO; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; namespace SharpChat.Flashii { public static class FlashiiUrls { private const string BASE_URL_FILE = "msz_url.txt"; private const string BASE_URL_FALLBACK = "https://flashii.net"; - private const string VERIFY = "/_sockchat/verify"; private const string BUMP = "/_sockchat/bump"; + private const string VERIFY = "/_sockchat/verify"; private const string BANS_CHECK = "/_sockchat/bans/check?u={0}&a={1}&x={2}&n={3}"; private const string BANS_CREATE = "/_sockchat/bans/create"; @@ -42,5 +48,45 @@ namespace SharpChat.Flashii { public static string GetURL(string path) { return GetBaseURL() + path; } + + public static async Task BumpUsersOnlineAsync(HttpClient client, IEnumerable<(string userId, string ipAddr)> list) { + if(client == null) + throw new ArgumentNullException(nameof(client)); + if(list == null) + throw new ArgumentNullException(nameof(list)); + if(!list.Any()) + return; + + string now = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(); + StringBuilder sb = new(); + sb.AppendFormat("bump#{0}", now); + + Dictionary formData = new() { + { "t", now } + }; + + foreach(var (userId, ipAddr) in list) { + sb.AppendFormat("#{0}:{1}", userId, ipAddr); + formData.Add(string.Format("u[{0}]", userId), ipAddr); + } + + HttpRequestMessage req = new(HttpMethod.Post, BumpURL) { + Headers = { + { "X-SharpChat-Signature", sb.ToString().GetSignedHash() } + }, + Content = new FormUrlEncodedContent(formData), + }; + + using HttpResponseMessage res = await client.SendAsync(req); + + try { + res.EnsureSuccessStatusCode(); + } catch(HttpRequestException) { + Logger.Debug(await res.Content.ReadAsStringAsync()); +#if DEBUG + throw; +#endif + } + } } } diff --git a/SharpChat/Program.cs b/SharpChat/Program.cs index d6bdad4..2d170c4 100644 --- a/SharpChat/Program.cs +++ b/SharpChat/Program.cs @@ -32,7 +32,9 @@ namespace SharpChat { if(hasCancelled) return; - using HttpClient httpClient = new(); + using HttpClient httpClient = new(new HttpClientHandler() { + UseProxy = false, // we will never and the initial resolving takes forever on linux + }); httpClient.DefaultRequestHeaders.Add(@"User-Agent", @"SharpChat/20230206"); if(hasCancelled) return; diff --git a/SharpChat/SockChatServer.cs b/SharpChat/SockChatServer.cs index e00718e..b65cc71 100644 --- a/SharpChat/SockChatServer.cs +++ b/SharpChat/SockChatServer.cs @@ -59,7 +59,7 @@ namespace SharpChat { HttpClient = httpClient; - Context = new ChatContext(HttpClient, this); + Context = new ChatContext(); Context.Channels.Add(new ChatChannel(@"Lounge")); #if DEBUG @@ -129,6 +129,10 @@ namespace SharpChat { Context.Update(); } + private readonly object BumpAccess = new(); + private readonly TimeSpan BumpInterval = TimeSpan.FromMinutes(1); + private DateTimeOffset LastBump = DateTimeOffset.MinValue; + private void OnMessage(IWebSocketConnection conn, string msg) { Context.Update(); @@ -172,6 +176,22 @@ namespace SharpChat { sess.BumpPing(); sess.Send(new PongPacket(sess.LastPing)); + + lock(BumpAccess) { + if(LastBump < DateTimeOffset.UtcNow - BumpInterval) { + (string, string)[] bumpList = Context.Users + .Where(u => u.HasSessions && u.Status == ChatUserStatus.Online) + .Select(u => (u.UserId.ToString(), u.RemoteAddresses.FirstOrDefault()?.ToString() ?? string.Empty)) + .ToArray(); + + if(bumpList.Any()) + Task.Run(async () => { + await FlashiiUrls.BumpUsersOnlineAsync(HttpClient, bumpList); + }).Wait(); + + LastBump = DateTimeOffset.UtcNow; + } + } break; case "1": diff --git a/SharpChat/UserManager.cs b/SharpChat/UserManager.cs index b78f36b..a086ac3 100644 --- a/SharpChat/UserManager.cs +++ b/SharpChat/UserManager.cs @@ -54,6 +54,10 @@ namespace SharpChat { || (includeNickName && x.Nickname?.ToLowerInvariant() == username) || (includeDisplayName && x.DisplayName.ToLowerInvariant() == username)); } + + public IEnumerable Where(Func selector) { + return Users.Where(selector); + } public IEnumerable OfHierarchy(int hierarchy) { lock(Users)