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.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();
|
||||
|
|
|
@ -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 {
|
||||
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<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;
|
||||
|
||||
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;
|
||||
|
|
|
@ -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":
|
||||
|
|
|
@ -54,6 +54,10 @@ namespace SharpChat {
|
|||
|| (includeNickName && x.Nickname?.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) {
|
||||
lock(Users)
|
||||
|
|
Loading…
Reference in a new issue