sharp-chat/SharpChat/Flashii/FlashiiBanInfo.cs

184 lines
6.7 KiB
C#

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace SharpChat.Flashii {
public class FlashiiBanInfo {
[JsonPropertyName("is_ban")]
public bool IsBanned { get; set; }
[JsonPropertyName("user_id")]
public string UserId { get; set; }
[JsonPropertyName("ip_addr")]
public string RemoteAddress { get; set; }
[JsonPropertyName("is_perma")]
public bool IsPermanent { get; set; }
[JsonPropertyName("expires")]
public DateTimeOffset ExpiresAt { get; set; }
// only populated in list request
[JsonPropertyName("user_name")]
public string UserName { get; set; }
[JsonPropertyName(@"user_colour")]
public int UserColourRaw { get; set; }
public bool HasExpired => !IsPermanent && DateTimeOffset.UtcNow >= ExpiresAt;
public ChatColour UserColour => ChatColour.FromMisuzu(UserColourRaw);
private const string CHECK_SIG_FMT = "check#{0}#{1}#{2}#{3}";
private const string REVOKE_SIG_FMT = "revoke#{0}#{1}#{2}";
private const string CREATE_SIG_FMT = "create#{0}#{1}#{2}#{3}#{4}#{5}#{6}#{7}";
private const string LIST_SIG_FMT = "list#{0}";
public static async Task<FlashiiBanInfo> CheckAsync(HttpClient client, string userId = null, string ipAddr = null, bool userIdIsName = false) {
if(client == null)
throw new ArgumentNullException(nameof(client));
userId ??= string.Empty;
ipAddr ??= string.Empty;
string userIdIsNameStr = userIdIsName ? "1" : "0";
string now = DateTimeOffset.Now.ToUnixTimeSeconds().ToString();
string url = string.Format(FlashiiUrls.BansCheckURL, Uri.EscapeDataString(userId), Uri.EscapeDataString(ipAddr), Uri.EscapeDataString(now), Uri.EscapeDataString(userIdIsNameStr));
string sig = string.Format(CHECK_SIG_FMT, now, userId, ipAddr, userIdIsNameStr);
HttpRequestMessage req = new(HttpMethod.Get, url) {
Headers = {
{ "X-SharpChat-Signature", sig.GetSignedHash() },
},
};
using HttpResponseMessage res = await client.SendAsync(req);
return JsonSerializer.Deserialize<FlashiiBanInfo>(
await res.Content.ReadAsByteArrayAsync()
);
}
public static async Task<FlashiiBanInfo[]> GetListAsync(HttpClient client) {
if(client == null)
throw new ArgumentNullException(nameof(client));
string now = DateTimeOffset.Now.ToUnixTimeSeconds().ToString();
string url = string.Format(FlashiiUrls.BansListURL, Uri.EscapeDataString(now));
string sig = string.Format(LIST_SIG_FMT, now);
HttpRequestMessage req = new(HttpMethod.Get, url) {
Headers = {
{ "X-SharpChat-Signature", sig.GetSignedHash() },
},
};
using HttpResponseMessage res = await client.SendAsync(req);
return JsonSerializer.Deserialize<FlashiiBanInfo[]>(
await res.Content.ReadAsByteArrayAsync()
);
}
public enum RevokeKind {
UserId,
RemoteAddress,
}
public async Task<bool> RevokeAsync(HttpClient client, RevokeKind kind) {
if(client == null)
throw new ArgumentNullException(nameof(client));
string type = kind switch {
RevokeKind.UserId => "user",
RevokeKind.RemoteAddress => "addr",
_ => throw new ArgumentException("Invalid kind specified.", nameof(kind)),
};
string target = kind switch {
RevokeKind.UserId => UserId,
RevokeKind.RemoteAddress => RemoteAddress,
_ => string.Empty,
};
string now = DateTimeOffset.Now.ToUnixTimeSeconds().ToString();
string url = string.Format(FlashiiUrls.BansRevokeURL, Uri.EscapeDataString(type), Uri.EscapeDataString(target), Uri.EscapeDataString(now));
string sig = string.Format(REVOKE_SIG_FMT, now, type, target);
HttpRequestMessage req = new(HttpMethod.Delete, url) {
Headers = {
{ "X-SharpChat-Signature", sig.GetSignedHash() },
},
};
using HttpResponseMessage res = await client.SendAsync(req);
if(res.StatusCode == HttpStatusCode.NotFound)
return false;
res.EnsureSuccessStatusCode();
return res.StatusCode == HttpStatusCode.NoContent;
}
public static async Task CreateAsync(
HttpClient client,
string targetId,
string targetAddr,
string modId,
string modAddr,
TimeSpan duration,
string reason
) {
if(client == null)
throw new ArgumentNullException(nameof(client));
if(string.IsNullOrWhiteSpace(targetAddr))
throw new ArgumentNullException(nameof(targetAddr));
if(string.IsNullOrWhiteSpace(modAddr))
throw new ArgumentNullException(nameof(modAddr));
if(duration <= TimeSpan.Zero)
return;
modId ??= string.Empty;
targetId ??= string.Empty;
reason ??= string.Empty;
string isPerma = duration == TimeSpan.MaxValue ? "1" : "0";
string durationStr = duration == TimeSpan.MaxValue ? "-1" : duration.TotalSeconds.ToString();
string now = DateTimeOffset.Now.ToUnixTimeSeconds().ToString();
string sig = string.Format(
CREATE_SIG_FMT,
now, targetId, targetAddr,
modId, modAddr,
durationStr, isPerma, reason
);
HttpRequestMessage req = new(HttpMethod.Post, FlashiiUrls.BansCreateURL) {
Headers = {
{ "X-SharpChat-Signature", sig.GetSignedHash() },
},
Content = new FormUrlEncodedContent(new Dictionary<string, string> {
{ "t", now },
{ "ui", targetId },
{ "ua", targetAddr },
{ "mi", modId },
{ "ma", modAddr },
{ "d", durationStr },
{ "p", isPerma },
{ "r", reason },
}),
};
using HttpResponseMessage res = await client.SendAsync(req);
res.EnsureSuccessStatusCode();
}
}
}