183 lines
6.7 KiB
C#
183 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();
|
|
}
|
|
}
|
|
}
|