Don't use a stinky Timer for user bumps and exclude AFK.
This commit is contained in:
parent
36f3ff6385
commit
27c28aafcd
6 changed files with 77 additions and 66 deletions
|
@ -1,35 +1,22 @@
|
||||||
using SharpChat.Events;
|
using SharpChat.Events;
|
||||||
using SharpChat.Flashii;
|
|
||||||
using SharpChat.Packet;
|
using SharpChat.Packet;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace SharpChat {
|
namespace SharpChat {
|
||||||
public class ChatContext : IDisposable, IPacketTarget {
|
public class ChatContext : IDisposable, IPacketTarget {
|
||||||
public bool IsDisposed { get; private set; }
|
public bool IsDisposed { get; private set; }
|
||||||
|
|
||||||
private readonly HttpClient HttpClient;
|
|
||||||
|
|
||||||
public SockChatServer Server { get; }
|
|
||||||
public Timer BumpTimer { get; }
|
|
||||||
|
|
||||||
public ChannelManager Channels { get; }
|
public ChannelManager Channels { get; }
|
||||||
public UserManager Users { get; }
|
public UserManager Users { get; }
|
||||||
public ChatEventManager Events { get; }
|
public ChatEventManager Events { get; }
|
||||||
|
|
||||||
public string TargetName => @"@broadcast";
|
public string TargetName => @"@broadcast";
|
||||||
|
|
||||||
public ChatContext(HttpClient httpClient, SockChatServer server) {
|
public ChatContext() {
|
||||||
HttpClient = httpClient;
|
|
||||||
Server = server;
|
|
||||||
Users = new(this);
|
Users = new(this);
|
||||||
Channels = new(this);
|
Channels = new(this);
|
||||||
Events = new(this);
|
Events = new(this);
|
||||||
|
|
||||||
BumpTimer = new Timer(e => FlashiiBump.SubmitAsync(HttpClient, Users.WithActiveConnections()).Wait(), null, TimeSpan.Zero, TimeSpan.FromMinutes(1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update() {
|
public void Update() {
|
||||||
|
@ -173,7 +160,6 @@ namespace SharpChat {
|
||||||
return;
|
return;
|
||||||
IsDisposed = true;
|
IsDisposed = true;
|
||||||
|
|
||||||
BumpTimer?.Dispose();
|
|
||||||
Events?.Dispose();
|
Events?.Dispose();
|
||||||
Channels?.Dispose();
|
Channels?.Dispose();
|
||||||
Users?.Dispose();
|
Users?.Dispose();
|
||||||
|
|
|
@ -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<ChatUser> 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<FlashiiBump> 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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 {
|
namespace SharpChat.Flashii {
|
||||||
public static class FlashiiUrls {
|
public static class FlashiiUrls {
|
||||||
private const string BASE_URL_FILE = "msz_url.txt";
|
private const string BASE_URL_FILE = "msz_url.txt";
|
||||||
private const string BASE_URL_FALLBACK = "https://flashii.net";
|
private const string BASE_URL_FALLBACK = "https://flashii.net";
|
||||||
|
|
||||||
private const string VERIFY = "/_sockchat/verify";
|
|
||||||
private const string BUMP = "/_sockchat/bump";
|
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_CHECK = "/_sockchat/bans/check?u={0}&a={1}&x={2}&n={3}";
|
||||||
private const string BANS_CREATE = "/_sockchat/bans/create";
|
private const string BANS_CREATE = "/_sockchat/bans/create";
|
||||||
|
@ -42,5 +48,45 @@ namespace SharpChat.Flashii {
|
||||||
public static string GetURL(string path) {
|
public static string GetURL(string path) {
|
||||||
return GetBaseURL() + 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<string, string> 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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,9 @@ namespace SharpChat {
|
||||||
|
|
||||||
if(hasCancelled) return;
|
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");
|
httpClient.DefaultRequestHeaders.Add(@"User-Agent", @"SharpChat/20230206");
|
||||||
|
|
||||||
if(hasCancelled) return;
|
if(hasCancelled) return;
|
||||||
|
|
|
@ -59,7 +59,7 @@ namespace SharpChat {
|
||||||
|
|
||||||
HttpClient = httpClient;
|
HttpClient = httpClient;
|
||||||
|
|
||||||
Context = new ChatContext(HttpClient, this);
|
Context = new ChatContext();
|
||||||
|
|
||||||
Context.Channels.Add(new ChatChannel(@"Lounge"));
|
Context.Channels.Add(new ChatChannel(@"Lounge"));
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
@ -129,6 +129,10 @@ namespace SharpChat {
|
||||||
Context.Update();
|
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) {
|
private void OnMessage(IWebSocketConnection conn, string msg) {
|
||||||
Context.Update();
|
Context.Update();
|
||||||
|
|
||||||
|
@ -172,6 +176,22 @@ namespace SharpChat {
|
||||||
|
|
||||||
sess.BumpPing();
|
sess.BumpPing();
|
||||||
sess.Send(new PongPacket(sess.LastPing));
|
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;
|
break;
|
||||||
|
|
||||||
case "1":
|
case "1":
|
||||||
|
|
|
@ -54,6 +54,10 @@ namespace SharpChat {
|
||||||
|| (includeNickName && x.Nickname?.ToLowerInvariant() == username)
|
|| (includeNickName && x.Nickname?.ToLowerInvariant() == username)
|
||||||
|| (includeDisplayName && x.DisplayName.ToLowerInvariant() == username));
|
|| (includeDisplayName && x.DisplayName.ToLowerInvariant() == username));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerable<ChatUser> Where(Func<ChatUser, bool> selector) {
|
||||||
|
return Users.Where(selector);
|
||||||
|
}
|
||||||
|
|
||||||
public IEnumerable<ChatUser> OfHierarchy(int hierarchy) {
|
public IEnumerable<ChatUser> OfHierarchy(int hierarchy) {
|
||||||
lock(Users)
|
lock(Users)
|
||||||
|
|
Loading…
Reference in a new issue