Switched to file namespace declarations.
This commit is contained in:
parent
6593929827
commit
34e4e9b1a9
93 changed files with 3470 additions and 3471 deletions
.editorconfig
SharpChat.Flashii
FlashiiAuthResult.csFlashiiBanInfo.csFlashiiClient.csFlashiiIPAddressBanInfo.csFlashiiRawBanInfo.csFlashiiUserBanInfo.cs
SharpChat.SockChat
S2CPacket.cs
S2CPackets
AuthFailS2CPacket.csAuthSuccessS2CPacket.csBanListS2CPacket.csChannelCreateS2CPacket.csChannelDeleteS2CPacket.csChannelUpdateS2CPacket.csChatMessageAddS2CPacket.csChatMessageDeleteS2CPacket.csCommandResponseS2CPacket.csContextChannelsS2CPacket.csContextClearS2CPacket.csContextUsersS2CPacket.csForceDisconnectS2CPacket.csPongS2CPacket.csUserChannelForceJoinS2CPacket.csUserChannelJoinS2CPacket.csUserChannelLeaveS2CPacket.csUserConnectS2CPacket.csUserDisconnectS2CPacket.csUserUpdateS2CPacket.cs
SharpChat
C2SPacketHandler.csC2SPacketHandlerContext.cs
C2SPacketHandlers
Channel.csClientCommand.csClientCommandContext.csClientCommands
AFKClientCommand.csActionClientCommand.csBanListClientCommand.csBroadcastClientCommand.csCreateChannelClientCommand.csDeleteChannelClientCommand.csDeleteMessageClientCommand.csJoinChannelClientCommand.csKickBanClientCommand.csNickClientCommand.csPardonAddressClientCommand.csPardonUserClientCommand.csPasswordChannelClientCommand.csRankChannelClientCommand.csRemoteAddressClientCommand.csShutdownRestartClientCommand.csWhisperClientCommand.csWhoClientCommand.cs
Connection.csContext.csEventStorage
EventStorage.csMariaDBEventStorage.csMariaDBEventStorage_Database.csMariaDBEventStorage_Migrations.csStoredEventFlags.csStoredEventInfo.csVirtualEventStorage.cs
Events
Program.csSharpChatWebSocketServer.csSockChat/S2CPackets
SockChatServer.csUser.csUserStatus.csSharpChatCommon
Auth
Bans
ColourInheritable.csColourRgb.csConfiguration
Logger.csRNG.csRateLimiter.csSharpInfo.csSnowflake
UserPermissions.cs
|
@ -15,7 +15,7 @@ csharp_indent_labels = one_less_than_current
|
|||
csharp_using_directive_placement = outside_namespace:silent
|
||||
csharp_prefer_simple_using_statement = true:suggestion
|
||||
csharp_prefer_braces = true:silent
|
||||
csharp_style_namespace_declarations = block_scoped:silent
|
||||
csharp_style_namespace_declarations = file_scoped:silent
|
||||
csharp_style_prefer_method_group_conversion = true:silent
|
||||
csharp_style_prefer_top_level_statements = true:silent
|
||||
csharp_style_prefer_primary_constructors = true:suggestion
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
using SharpChat.Auth;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace SharpChat.Flashii {
|
||||
public class FlashiiAuthResult : AuthResult {
|
||||
namespace SharpChat.Flashii;
|
||||
|
||||
public class FlashiiAuthResult : AuthResult {
|
||||
public string UserId => UserIdRaw.ToString();
|
||||
public string UserName => UserNameRaw ?? string.Empty;
|
||||
public ColourInheritable UserColour => ColourInheritable.FromMisuzu(UserColourRaw);
|
||||
|
@ -27,5 +28,4 @@ namespace SharpChat.Flashii {
|
|||
|
||||
[JsonPropertyName("perms")]
|
||||
public UserPermissions UserPermissions { get; init; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
using SharpChat.Bans;
|
||||
using SharpChat.Bans;
|
||||
|
||||
namespace SharpChat.Flashii {
|
||||
public abstract class FlashiiBanInfo(
|
||||
namespace SharpChat.Flashii;
|
||||
|
||||
public abstract class FlashiiBanInfo(
|
||||
BanKind kind,
|
||||
FlashiiRawBanInfo rawBanInfo
|
||||
) : BanInfo {
|
||||
) : BanInfo {
|
||||
public BanKind Kind { get; } = kind;
|
||||
public bool IsPermanent { get; } = rawBanInfo.IsPermanent;
|
||||
public DateTimeOffset ExpiresAt { get; } = rawBanInfo.ExpiresAt;
|
||||
public abstract override string ToString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,9 @@ using System.Security.Cryptography;
|
|||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace SharpChat.Flashii {
|
||||
public class FlashiiClient(HttpClient httpClient, Config config) : AuthClient, BansClient {
|
||||
namespace SharpChat.Flashii;
|
||||
|
||||
public class FlashiiClient(HttpClient httpClient, Config config) : AuthClient, BansClient {
|
||||
private const string DEFAULT_BASE_URL = "https://flashii.net/_sockchat";
|
||||
private readonly CachedValue<string> BaseURL = config.ReadCached("url", DEFAULT_BASE_URL);
|
||||
|
||||
|
@ -236,5 +237,4 @@ namespace SharpChat.Flashii {
|
|||
? new FlashiiUserBanInfo(b) : new FlashiiIPAddressBanInfo(b));
|
||||
})];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
using SharpChat.Bans;
|
||||
using SharpChat.Bans;
|
||||
using System.Net;
|
||||
|
||||
namespace SharpChat.Flashii {
|
||||
public class FlashiiIPAddressBanInfo(FlashiiRawBanInfo rawBanInfo) : FlashiiBanInfo(BanKind.IPAddress, rawBanInfo), IPAddressBanInfo {
|
||||
namespace SharpChat.Flashii;
|
||||
|
||||
public class FlashiiIPAddressBanInfo(FlashiiRawBanInfo rawBanInfo) : FlashiiBanInfo(BanKind.IPAddress, rawBanInfo), IPAddressBanInfo {
|
||||
public IPAddress Address { get; } = IPAddress.TryParse(rawBanInfo.RemoteAddress, out IPAddress? addr) && addr is not null ? addr : IPAddress.IPv6None;
|
||||
public override string ToString() => Address.ToString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace SharpChat.Flashii {
|
||||
public class FlashiiRawBanInfo {
|
||||
namespace SharpChat.Flashii;
|
||||
|
||||
public class FlashiiRawBanInfo {
|
||||
[JsonPropertyName("is_ban")]
|
||||
public bool IsBanned { get; set; }
|
||||
|
||||
|
@ -25,5 +26,4 @@ namespace SharpChat.Flashii {
|
|||
public DateTimeOffset ExpiresAt { get; set; }
|
||||
|
||||
public bool HasExpired => !IsPermanent && DateTimeOffset.UtcNow >= ExpiresAt;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
using SharpChat.Bans;
|
||||
using SharpChat.Bans;
|
||||
|
||||
namespace SharpChat.Flashii {
|
||||
public class FlashiiUserBanInfo(FlashiiRawBanInfo rawBanInfo) : FlashiiBanInfo(BanKind.User, rawBanInfo), UserBanInfo {
|
||||
namespace SharpChat.Flashii;
|
||||
|
||||
public class FlashiiUserBanInfo(FlashiiRawBanInfo rawBanInfo) : FlashiiBanInfo(BanKind.User, rawBanInfo), UserBanInfo {
|
||||
public string UserId { get; } = rawBanInfo.UserId ?? string.Empty;
|
||||
public string UserName { get; } = rawBanInfo.UserName ?? $"({rawBanInfo.UserId ?? string.Empty})";
|
||||
public ColourInheritable UserColour { get; } = ColourInheritable.FromMisuzu(rawBanInfo.UserColourRaw);
|
||||
public override string ToString() => UserName;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
namespace SharpChat.SockChat {
|
||||
public interface S2CPacket {
|
||||
namespace SharpChat.SockChat;
|
||||
|
||||
public interface S2CPacket {
|
||||
string Pack();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
using System.Text;
|
||||
|
||||
namespace SharpChat.SockChat.S2CPackets {
|
||||
public class AuthFailS2CPacket(
|
||||
namespace SharpChat.SockChat.S2CPackets;
|
||||
|
||||
public class AuthFailS2CPacket(
|
||||
AuthFailS2CPacket.Reason reason,
|
||||
DateTimeOffset? expiresAt = null
|
||||
) : S2CPacket {
|
||||
) : S2CPacket {
|
||||
public enum Reason {
|
||||
AuthInvalid,
|
||||
MaxSessions,
|
||||
|
@ -39,5 +40,4 @@ namespace SharpChat.SockChat.S2CPackets {
|
|||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
using System.Text;
|
||||
|
||||
namespace SharpChat.SockChat.S2CPackets {
|
||||
public class AuthSuccessS2CPacket(
|
||||
namespace SharpChat.SockChat.S2CPackets;
|
||||
|
||||
public class AuthSuccessS2CPacket(
|
||||
string userId,
|
||||
string userName,
|
||||
ColourInheritable userColour,
|
||||
|
@ -9,7 +10,7 @@ namespace SharpChat.SockChat.S2CPackets {
|
|||
UserPermissions userPerms,
|
||||
string channelName,
|
||||
int maxMsgLength
|
||||
) : S2CPacket {
|
||||
) : S2CPacket {
|
||||
public string Pack() {
|
||||
StringBuilder sb = new();
|
||||
|
||||
|
@ -36,5 +37,4 @@ namespace SharpChat.SockChat.S2CPackets {
|
|||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
using SharpChat.Bans;
|
||||
using System.Text;
|
||||
|
||||
namespace SharpChat.SockChat.S2CPackets {
|
||||
public class BanListS2CPacket(
|
||||
namespace SharpChat.SockChat.S2CPackets;
|
||||
|
||||
public class BanListS2CPacket(
|
||||
long msgId,
|
||||
IEnumerable<BanListS2CPacket.Entry> entries
|
||||
) : S2CPacket {
|
||||
) : S2CPacket {
|
||||
public record Entry(BanKind type, string value);
|
||||
|
||||
public string Pack() {
|
||||
|
@ -25,5 +26,4 @@ namespace SharpChat.SockChat.S2CPackets {
|
|||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
using System.Text;
|
||||
|
||||
namespace SharpChat.SockChat.S2CPackets {
|
||||
public class ChannelCreateS2CPacket(
|
||||
namespace SharpChat.SockChat.S2CPackets;
|
||||
|
||||
public class ChannelCreateS2CPacket(
|
||||
string name,
|
||||
bool hasPassword,
|
||||
bool isTemporary
|
||||
) : S2CPacket {
|
||||
) : S2CPacket {
|
||||
public string Pack() {
|
||||
StringBuilder sb = new();
|
||||
|
||||
|
@ -18,5 +19,4 @@ namespace SharpChat.SockChat.S2CPackets {
|
|||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
using System.Text;
|
||||
|
||||
namespace SharpChat.SockChat.S2CPackets {
|
||||
public class ChannelDeleteS2CPacket(
|
||||
namespace SharpChat.SockChat.S2CPackets;
|
||||
|
||||
public class ChannelDeleteS2CPacket(
|
||||
string channelName
|
||||
) : S2CPacket {
|
||||
) : S2CPacket {
|
||||
public string Pack() {
|
||||
StringBuilder sb = new();
|
||||
|
||||
|
@ -12,5 +13,4 @@ namespace SharpChat.SockChat.S2CPackets {
|
|||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
using System.Text;
|
||||
|
||||
namespace SharpChat.SockChat.S2CPackets {
|
||||
public class ChannelUpdateS2CPacket(
|
||||
namespace SharpChat.SockChat.S2CPackets;
|
||||
|
||||
public class ChannelUpdateS2CPacket(
|
||||
string previousName,
|
||||
string newName,
|
||||
bool hasPassword,
|
||||
bool isTemporary
|
||||
) : S2CPacket {
|
||||
) : S2CPacket {
|
||||
public string Pack() {
|
||||
StringBuilder sb = new();
|
||||
|
||||
|
@ -21,5 +22,4 @@ namespace SharpChat.SockChat.S2CPackets {
|
|||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
using System.Text;
|
||||
|
||||
namespace SharpChat.SockChat.S2CPackets {
|
||||
public class ChatMessageAddS2CPacket(
|
||||
namespace SharpChat.SockChat.S2CPackets;
|
||||
|
||||
public class ChatMessageAddS2CPacket(
|
||||
long msgId,
|
||||
DateTimeOffset created,
|
||||
string userId,
|
||||
string text,
|
||||
bool isAction,
|
||||
bool isPrivate
|
||||
) : S2CPacket {
|
||||
) : S2CPacket {
|
||||
public string Pack() {
|
||||
StringBuilder sb = new();
|
||||
|
||||
|
@ -44,5 +45,4 @@ namespace SharpChat.SockChat.S2CPackets {
|
|||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
using System.Text;
|
||||
|
||||
namespace SharpChat.SockChat.S2CPackets {
|
||||
public class ChatMessageDeleteS2CPacket(long eventId) : S2CPacket {
|
||||
namespace SharpChat.SockChat.S2CPackets;
|
||||
|
||||
public class ChatMessageDeleteS2CPacket(long eventId) : S2CPacket {
|
||||
public string Pack() {
|
||||
StringBuilder sb = new();
|
||||
|
||||
|
@ -10,5 +11,4 @@ namespace SharpChat.SockChat.S2CPackets {
|
|||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
using System.Text;
|
||||
|
||||
namespace SharpChat.SockChat.S2CPackets {
|
||||
public class CommandResponseS2CPacket(
|
||||
namespace SharpChat.SockChat.S2CPackets;
|
||||
|
||||
public class CommandResponseS2CPacket(
|
||||
long msgId,
|
||||
string stringId,
|
||||
bool isError = true,
|
||||
params object[] args
|
||||
) : S2CPacket {
|
||||
) : S2CPacket {
|
||||
public string Pack() {
|
||||
StringBuilder sb = new();
|
||||
|
||||
|
@ -48,10 +49,10 @@ namespace SharpChat.SockChat.S2CPackets {
|
|||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Abbreviated class name because otherwise shit gets wide
|
||||
public static class LCR {
|
||||
// Abbreviated class name because otherwise shit gets wide
|
||||
public static class LCR {
|
||||
public const string GENERIC_ERROR = "generr";
|
||||
public const string COMMAND_NOT_FOUND = "nocmd";
|
||||
public const string COMMAND_NOT_ALLOWED = "cmdna";
|
||||
|
@ -81,5 +82,4 @@ namespace SharpChat.SockChat.S2CPackets {
|
|||
public const string USER_UNBANNED = "unban";
|
||||
public const string FLOOD_WARN = "flwarn";
|
||||
public const string NICKNAME_CHANGE = "nick";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
using System.Text;
|
||||
|
||||
namespace SharpChat.SockChat.S2CPackets {
|
||||
public class ContextChannelsS2CPacket(IEnumerable<ContextChannelsS2CPacket.Entry> entries) : S2CPacket {
|
||||
namespace SharpChat.SockChat.S2CPackets;
|
||||
|
||||
public class ContextChannelsS2CPacket(IEnumerable<ContextChannelsS2CPacket.Entry> entries) : S2CPacket {
|
||||
public record Entry(string name, bool hasPassword, bool isTemporary);
|
||||
|
||||
public string Pack() {
|
||||
|
@ -21,5 +22,4 @@ namespace SharpChat.SockChat.S2CPackets {
|
|||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
using System.Text;
|
||||
|
||||
namespace SharpChat.SockChat.S2CPackets {
|
||||
public class ContextClearS2CPacket(ContextClearS2CPacket.Mode mode) : S2CPacket {
|
||||
namespace SharpChat.SockChat.S2CPackets;
|
||||
|
||||
public class ContextClearS2CPacket(ContextClearS2CPacket.Mode mode) : S2CPacket {
|
||||
public enum Mode {
|
||||
Messages = 0,
|
||||
Users = 1,
|
||||
|
@ -18,5 +19,4 @@ namespace SharpChat.SockChat.S2CPackets {
|
|||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
using System.Text;
|
||||
|
||||
namespace SharpChat.SockChat.S2CPackets {
|
||||
public class ContextUsersS2CPacket(IEnumerable<ContextUsersS2CPacket.Entry> entries) : S2CPacket {
|
||||
namespace SharpChat.SockChat.S2CPackets;
|
||||
|
||||
public class ContextUsersS2CPacket(IEnumerable<ContextUsersS2CPacket.Entry> entries) : S2CPacket {
|
||||
public record Entry(string id, string name, ColourInheritable colour, int rank, UserPermissions perms, bool visible);
|
||||
|
||||
public string Pack() {
|
||||
|
@ -33,5 +34,4 @@ namespace SharpChat.SockChat.S2CPackets {
|
|||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
using System.Text;
|
||||
|
||||
namespace SharpChat.SockChat.S2CPackets {
|
||||
public class ForceDisconnectS2CPacket(DateTimeOffset? expires = null) : S2CPacket {
|
||||
namespace SharpChat.SockChat.S2CPackets;
|
||||
|
||||
public class ForceDisconnectS2CPacket(DateTimeOffset? expires = null) : S2CPacket {
|
||||
public string Pack() {
|
||||
StringBuilder sb = new();
|
||||
|
||||
|
@ -18,5 +19,4 @@ namespace SharpChat.SockChat.S2CPackets {
|
|||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
namespace SharpChat.SockChat.S2CPackets {
|
||||
public class PongS2CPacket : S2CPacket {
|
||||
namespace SharpChat.SockChat.S2CPackets;
|
||||
|
||||
public class PongS2CPacket : S2CPacket {
|
||||
public string Pack() {
|
||||
return "0\tpong";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
using System.Text;
|
||||
|
||||
namespace SharpChat.SockChat.S2CPackets {
|
||||
public class UserChannelForceJoinS2CPacket(string channelName) : S2CPacket {
|
||||
namespace SharpChat.SockChat.S2CPackets;
|
||||
|
||||
public class UserChannelForceJoinS2CPacket(string channelName) : S2CPacket {
|
||||
public string Pack() {
|
||||
StringBuilder sb = new();
|
||||
|
||||
|
@ -10,5 +11,4 @@ namespace SharpChat.SockChat.S2CPackets {
|
|||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
using System.Text;
|
||||
|
||||
namespace SharpChat.SockChat.S2CPackets {
|
||||
public class UserChannelJoinS2CPacket(
|
||||
namespace SharpChat.SockChat.S2CPackets;
|
||||
|
||||
public class UserChannelJoinS2CPacket(
|
||||
long msgId,
|
||||
string userId,
|
||||
string userName,
|
||||
ColourInheritable userColour,
|
||||
int userRank,
|
||||
UserPermissions userPerms
|
||||
) : S2CPacket {
|
||||
) : S2CPacket {
|
||||
public string Pack() {
|
||||
StringBuilder sb = new();
|
||||
|
||||
|
@ -33,5 +34,4 @@ namespace SharpChat.SockChat.S2CPackets {
|
|||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
using System.Text;
|
||||
|
||||
namespace SharpChat.SockChat.S2CPackets {
|
||||
public class UserChannelLeaveS2CPacket(long msgId, string userId) : S2CPacket {
|
||||
namespace SharpChat.SockChat.S2CPackets;
|
||||
|
||||
public class UserChannelLeaveS2CPacket(long msgId, string userId) : S2CPacket {
|
||||
public string Pack() {
|
||||
StringBuilder sb = new();
|
||||
|
||||
|
@ -12,5 +13,4 @@ namespace SharpChat.SockChat.S2CPackets {
|
|||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
using System.Text;
|
||||
|
||||
namespace SharpChat.SockChat.S2CPackets {
|
||||
public class UserConnectS2CPacket(
|
||||
namespace SharpChat.SockChat.S2CPackets;
|
||||
|
||||
public class UserConnectS2CPacket(
|
||||
long msgId,
|
||||
DateTimeOffset joined,
|
||||
string userId,
|
||||
|
@ -9,7 +10,7 @@ namespace SharpChat.SockChat.S2CPackets {
|
|||
ColourInheritable userColour,
|
||||
int userRank,
|
||||
UserPermissions userPerms
|
||||
) : S2CPacket {
|
||||
) : S2CPacket {
|
||||
public string Pack() {
|
||||
StringBuilder sb = new();
|
||||
|
||||
|
@ -36,5 +37,4 @@ namespace SharpChat.SockChat.S2CPackets {
|
|||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
using System.Text;
|
||||
|
||||
namespace SharpChat.SockChat.S2CPackets {
|
||||
public class UserDisconnectS2CPacket(
|
||||
namespace SharpChat.SockChat.S2CPackets;
|
||||
|
||||
public class UserDisconnectS2CPacket(
|
||||
long msgId,
|
||||
DateTimeOffset disconnected,
|
||||
string userId,
|
||||
string userName,
|
||||
UserDisconnectS2CPacket.Reason reason
|
||||
) : S2CPacket {
|
||||
) : S2CPacket {
|
||||
public enum Reason {
|
||||
Leave,
|
||||
TimeOut,
|
||||
|
@ -47,5 +48,4 @@ namespace SharpChat.SockChat.S2CPackets {
|
|||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
using System.Text;
|
||||
|
||||
namespace SharpChat.SockChat.S2CPackets {
|
||||
public class UserUpdateS2CPacket(
|
||||
namespace SharpChat.SockChat.S2CPackets;
|
||||
|
||||
public class UserUpdateS2CPacket(
|
||||
string userId,
|
||||
string userName,
|
||||
ColourInheritable userColour,
|
||||
int userRank,
|
||||
UserPermissions userPerms
|
||||
) : S2CPacket {
|
||||
) : S2CPacket {
|
||||
public string Pack() {
|
||||
StringBuilder sb = new();
|
||||
|
||||
|
@ -30,5 +31,4 @@ namespace SharpChat.SockChat.S2CPackets {
|
|||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
namespace SharpChat {
|
||||
public interface C2SPacketHandler {
|
||||
namespace SharpChat;
|
||||
|
||||
public interface C2SPacketHandler {
|
||||
bool IsMatch(C2SPacketHandlerContext ctx);
|
||||
Task Handle(C2SPacketHandlerContext ctx);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
namespace SharpChat {
|
||||
public class C2SPacketHandlerContext(
|
||||
namespace SharpChat;
|
||||
|
||||
public class C2SPacketHandlerContext(
|
||||
string text,
|
||||
Context chat,
|
||||
Connection connection
|
||||
) {
|
||||
) {
|
||||
public string Text { get; } = text ?? throw new ArgumentNullException(nameof(text));
|
||||
public Context Chat { get; } = chat ?? throw new ArgumentNullException(nameof(chat));
|
||||
public Connection Connection { get; } = connection ?? throw new ArgumentNullException(nameof(connection));
|
||||
|
@ -15,5 +16,4 @@
|
|||
public string[] SplitText(int expect) {
|
||||
return Text.Split('\t', expect + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,14 +3,15 @@ using SharpChat.Bans;
|
|||
using SharpChat.Configuration;
|
||||
using SharpChat.SockChat.S2CPackets;
|
||||
|
||||
namespace SharpChat.C2SPacketHandlers {
|
||||
public class AuthC2SPacketHandler(
|
||||
namespace SharpChat.C2SPacketHandlers;
|
||||
|
||||
public class AuthC2SPacketHandler(
|
||||
AuthClient authClient,
|
||||
BansClient bansClient,
|
||||
Channel defaultChannel,
|
||||
CachedValue<int> maxMsgLength,
|
||||
CachedValue<int> maxConns
|
||||
) : C2SPacketHandler {
|
||||
) : C2SPacketHandler {
|
||||
private readonly Channel DefaultChannel = defaultChannel ?? throw new ArgumentNullException(nameof(defaultChannel));
|
||||
private readonly CachedValue<int> MaxMessageLength = maxMsgLength ?? throw new ArgumentNullException(nameof(maxMsgLength));
|
||||
private readonly CachedValue<int> MaxConnections = maxConns ?? throw new ArgumentNullException(nameof(maxConns));
|
||||
|
@ -108,5 +109,4 @@ namespace SharpChat.C2SPacketHandlers {
|
|||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,9 @@ using SharpChat.Auth;
|
|||
using SharpChat.SockChat.S2CPackets;
|
||||
using System.Net;
|
||||
|
||||
namespace SharpChat.C2SPacketHandlers {
|
||||
public class PingC2SPacketHandler(AuthClient authClient) : C2SPacketHandler {
|
||||
namespace SharpChat.C2SPacketHandlers;
|
||||
|
||||
public class PingC2SPacketHandler(AuthClient authClient) : C2SPacketHandler {
|
||||
private readonly TimeSpan BumpInterval = TimeSpan.FromMinutes(1);
|
||||
private DateTimeOffset LastBump = DateTimeOffset.MinValue;
|
||||
|
||||
|
@ -36,5 +37,4 @@ namespace SharpChat.C2SPacketHandlers {
|
|||
ctx.Chat.ContextAccess.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,11 +4,12 @@ using SharpChat.Snowflake;
|
|||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace SharpChat.C2SPacketHandlers {
|
||||
public class SendMessageC2SPacketHandler(
|
||||
namespace SharpChat.C2SPacketHandlers;
|
||||
|
||||
public class SendMessageC2SPacketHandler(
|
||||
RandomSnowflake randomSnowflake,
|
||||
CachedValue<int> maxMsgLength
|
||||
) : C2SPacketHandler {
|
||||
) : C2SPacketHandler {
|
||||
private readonly CachedValue<int> MaxMessageLength = maxMsgLength ?? throw new ArgumentNullException(nameof(maxMsgLength));
|
||||
|
||||
private List<ClientCommand> Commands { get; } = [];
|
||||
|
@ -85,5 +86,4 @@ namespace SharpChat.C2SPacketHandlers {
|
|||
ctx.Chat.ContextAccess.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
namespace SharpChat {
|
||||
public class Channel(
|
||||
namespace SharpChat;
|
||||
|
||||
public class Channel(
|
||||
string name,
|
||||
string password = "",
|
||||
bool isTemporary = false,
|
||||
int rank = 0,
|
||||
string ownerId = ""
|
||||
) {
|
||||
) {
|
||||
public string Name { get; } = name ?? throw new ArgumentNullException(nameof(name));
|
||||
public string Password { get; set; } = password ?? string.Empty;
|
||||
public bool IsTemporary { get; set; } = isTemporary;
|
||||
|
@ -36,5 +37,4 @@ namespace SharpChat {
|
|||
public static bool CheckNameChar(char c) {
|
||||
return char.IsLetter(c) || char.IsNumber(c) || c == '-' || c == '_';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
namespace SharpChat {
|
||||
public interface ClientCommand {
|
||||
namespace SharpChat;
|
||||
|
||||
public interface ClientCommand {
|
||||
bool IsMatch(ClientCommandContext ctx);
|
||||
Task Dispatch(ClientCommandContext ctx);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
namespace SharpChat {
|
||||
public class ClientCommandContext {
|
||||
namespace SharpChat;
|
||||
|
||||
public class ClientCommandContext {
|
||||
public string Name { get; }
|
||||
public string[] Args { get; }
|
||||
public Context Chat { get; }
|
||||
|
@ -45,5 +46,4 @@
|
|||
public bool NameEquals(string name) {
|
||||
return Name.Equals(name, StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace SharpChat.ClientCommands {
|
||||
public class AFKClientCommand : ClientCommand {
|
||||
namespace SharpChat.ClientCommands;
|
||||
|
||||
public class AFKClientCommand : ClientCommand {
|
||||
private const string DEFAULT = "AFK";
|
||||
public const int MAX_GRAPHEMES = 5;
|
||||
public const int MAX_BYTES = MAX_GRAPHEMES * 10;
|
||||
|
@ -30,5 +31,4 @@ namespace SharpChat.ClientCommands {
|
|||
statusText: statusText
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
using SharpChat.Events;
|
||||
|
||||
namespace SharpChat.ClientCommands {
|
||||
public class ActionClientCommand : ClientCommand {
|
||||
namespace SharpChat.ClientCommands;
|
||||
|
||||
public class ActionClientCommand : ClientCommand {
|
||||
public bool IsMatch(ClientCommandContext ctx) {
|
||||
return ctx.NameEquals("action")
|
||||
|| ctx.NameEquals("me");
|
||||
|
@ -29,5 +30,4 @@ namespace SharpChat.ClientCommands {
|
|||
false, true, false
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
using SharpChat.Bans;
|
||||
using SharpChat.SockChat.S2CPackets;
|
||||
|
||||
namespace SharpChat.ClientCommands {
|
||||
public class BanListClientCommand(BansClient bansClient) : ClientCommand {
|
||||
namespace SharpChat.ClientCommands;
|
||||
|
||||
public class BanListClientCommand(BansClient bansClient) : ClientCommand {
|
||||
public bool IsMatch(ClientCommandContext ctx) {
|
||||
return ctx.NameEquals("bans")
|
||||
|| ctx.NameEquals("banned");
|
||||
|
@ -26,5 +27,4 @@ namespace SharpChat.ClientCommands {
|
|||
await ctx.Chat.SendTo(ctx.User, new CommandResponseS2CPacket(msgId, LCR.GENERIC_ERROR, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
using SharpChat.Events;
|
||||
using SharpChat.SockChat.S2CPackets;
|
||||
|
||||
namespace SharpChat.ClientCommands {
|
||||
public class BroadcastClientCommand : ClientCommand {
|
||||
namespace SharpChat.ClientCommands;
|
||||
|
||||
public class BroadcastClientCommand : ClientCommand {
|
||||
public bool IsMatch(ClientCommandContext ctx) {
|
||||
return ctx.NameEquals("say")
|
||||
|| ctx.NameEquals("broadcast");
|
||||
|
@ -30,5 +31,4 @@ namespace SharpChat.ClientCommands {
|
|||
false, false, true
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
using SharpChat.SockChat.S2CPackets;
|
||||
|
||||
namespace SharpChat.ClientCommands {
|
||||
public class CreateChannelClientCommand : ClientCommand {
|
||||
namespace SharpChat.ClientCommands;
|
||||
|
||||
public class CreateChannelClientCommand : ClientCommand {
|
||||
public bool IsMatch(ClientCommandContext ctx) {
|
||||
return ctx.NameEquals("create");
|
||||
}
|
||||
|
@ -58,5 +59,4 @@ namespace SharpChat.ClientCommands {
|
|||
await ctx.Chat.SwitchChannel(ctx.User, createChan, createChan.Password);
|
||||
await ctx.Chat.SendTo(ctx.User, new CommandResponseS2CPacket(msgId, LCR.CHANNEL_CREATED, false, createChan.Name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
using SharpChat.SockChat.S2CPackets;
|
||||
|
||||
namespace SharpChat.ClientCommands {
|
||||
public class DeleteChannelClientCommand : ClientCommand {
|
||||
namespace SharpChat.ClientCommands;
|
||||
|
||||
public class DeleteChannelClientCommand : ClientCommand {
|
||||
public bool IsMatch(ClientCommandContext ctx) {
|
||||
return ctx.NameEquals("delchan") || (
|
||||
ctx.NameEquals("delete")
|
||||
|
@ -33,5 +34,4 @@ namespace SharpChat.ClientCommands {
|
|||
await ctx.Chat.RemoveChannel(delChan);
|
||||
await ctx.Chat.SendTo(ctx.User, new CommandResponseS2CPacket(msgId, LCR.CHANNEL_DELETED, false, delChan.Name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
using SharpChat.EventStorage;
|
||||
using SharpChat.SockChat.S2CPackets;
|
||||
|
||||
namespace SharpChat.ClientCommands
|
||||
{
|
||||
public class DeleteMessageClientCommand : ClientCommand {
|
||||
namespace SharpChat.ClientCommands;
|
||||
|
||||
public class DeleteMessageClientCommand : ClientCommand {
|
||||
public bool IsMatch(ClientCommandContext ctx) {
|
||||
return ctx.NameEquals("delmsg") || (
|
||||
ctx.NameEquals("delete")
|
||||
|
@ -37,5 +37,4 @@ namespace SharpChat.ClientCommands
|
|||
ctx.Chat.Events.RemoveEvent(delMsg);
|
||||
await ctx.Chat.Send(new ChatMessageDeleteS2CPacket(delMsg.Id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
using SharpChat.SockChat.S2CPackets;
|
||||
|
||||
namespace SharpChat.ClientCommands {
|
||||
public class JoinChannelClientCommand : ClientCommand {
|
||||
namespace SharpChat.ClientCommands;
|
||||
|
||||
public class JoinChannelClientCommand : ClientCommand {
|
||||
public bool IsMatch(ClientCommandContext ctx) {
|
||||
return ctx.NameEquals("join");
|
||||
}
|
||||
|
@ -19,5 +20,4 @@ namespace SharpChat.ClientCommands {
|
|||
|
||||
await ctx.Chat.SwitchChannel(ctx.User, joinChan, string.Join(' ', ctx.Args.Skip(1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,9 @@ using SharpChat.Bans;
|
|||
using SharpChat.SockChat.S2CPackets;
|
||||
using System.Net;
|
||||
|
||||
namespace SharpChat.ClientCommands {
|
||||
public class KickBanClientCommand(BansClient bansClient) : ClientCommand {
|
||||
namespace SharpChat.ClientCommands;
|
||||
|
||||
public class KickBanClientCommand(BansClient bansClient) : ClientCommand {
|
||||
public bool IsMatch(ClientCommandContext ctx) {
|
||||
return ctx.NameEquals("kick")
|
||||
|| ctx.NameEquals("ban");
|
||||
|
@ -69,5 +70,4 @@ namespace SharpChat.ClientCommands {
|
|||
|
||||
await ctx.Chat.BanUser(banUser, duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,9 @@ using SharpChat.SockChat.S2CPackets;
|
|||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace SharpChat.ClientCommands {
|
||||
public class NickClientCommand : ClientCommand {
|
||||
namespace SharpChat.ClientCommands;
|
||||
|
||||
public class NickClientCommand : ClientCommand {
|
||||
private const int MAX_GRAPHEMES = 16;
|
||||
private const int MAX_BYTES = MAX_GRAPHEMES * 10;
|
||||
|
||||
|
@ -59,5 +60,4 @@ namespace SharpChat.ClientCommands {
|
|||
string? previousName = targetUser.UserId == ctx.User.UserId ? (targetUser.NickName ?? targetUser.UserName) : null;
|
||||
await ctx.Chat.UpdateUser(targetUser, nickName: nickStr, silent: previousName == null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,9 @@ using SharpChat.Bans;
|
|||
using SharpChat.SockChat.S2CPackets;
|
||||
using System.Net;
|
||||
|
||||
namespace SharpChat.ClientCommands {
|
||||
public class PardonAddressClientCommand(BansClient bansClient) : ClientCommand {
|
||||
namespace SharpChat.ClientCommands;
|
||||
|
||||
public class PardonAddressClientCommand(BansClient bansClient) : ClientCommand {
|
||||
public bool IsMatch(ClientCommandContext ctx) {
|
||||
return ctx.NameEquals("pardonip")
|
||||
|| ctx.NameEquals("unbanip");
|
||||
|
@ -36,5 +37,4 @@ namespace SharpChat.ClientCommands {
|
|||
else
|
||||
await ctx.Chat.SendTo(ctx.User, new CommandResponseS2CPacket(msgId, LCR.USER_NOT_BANNED, true, unbanAddrTarget));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
using SharpChat.Bans;
|
||||
using SharpChat.SockChat.S2CPackets;
|
||||
|
||||
namespace SharpChat.ClientCommands {
|
||||
public class PardonUserClientCommand(BansClient bansClient) : ClientCommand {
|
||||
namespace SharpChat.ClientCommands;
|
||||
|
||||
public class PardonUserClientCommand(BansClient bansClient) : ClientCommand {
|
||||
public bool IsMatch(ClientCommandContext ctx) {
|
||||
return ctx.NameEquals("pardon")
|
||||
|| ctx.NameEquals("unban");
|
||||
|
@ -42,5 +43,4 @@ namespace SharpChat.ClientCommands {
|
|||
else
|
||||
await ctx.Chat.SendTo(ctx.User, new CommandResponseS2CPacket(msgId, LCR.USER_NOT_BANNED, true, unbanUserDisplay));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
using SharpChat.SockChat.S2CPackets;
|
||||
|
||||
namespace SharpChat.ClientCommands {
|
||||
public class PasswordChannelClientCommand : ClientCommand {
|
||||
namespace SharpChat.ClientCommands;
|
||||
|
||||
public class PasswordChannelClientCommand : ClientCommand {
|
||||
public bool IsMatch(ClientCommandContext ctx) {
|
||||
return ctx.NameEquals("pwd")
|
||||
|| ctx.NameEquals("password");
|
||||
|
@ -23,5 +24,4 @@ namespace SharpChat.ClientCommands {
|
|||
await ctx.Chat.UpdateChannel(ctx.Channel, password: chanPass);
|
||||
await ctx.Chat.SendTo(ctx.User, new CommandResponseS2CPacket(msgId, LCR.CHANNEL_PASSWORD_CHANGED, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
using SharpChat.SockChat.S2CPackets;
|
||||
|
||||
namespace SharpChat.ClientCommands {
|
||||
public class RankChannelClientCommand : ClientCommand {
|
||||
namespace SharpChat.ClientCommands;
|
||||
|
||||
public class RankChannelClientCommand : ClientCommand {
|
||||
public bool IsMatch(ClientCommandContext ctx) {
|
||||
return ctx.NameEquals("rank")
|
||||
|| ctx.NameEquals("privilege")
|
||||
|
@ -24,5 +25,4 @@ namespace SharpChat.ClientCommands {
|
|||
await ctx.Chat.UpdateChannel(ctx.Channel, hierarchy: chanHierarchy);
|
||||
await ctx.Chat.SendTo(ctx.User, new CommandResponseS2CPacket(msgId, LCR.CHANNEL_HIERARCHY_CHANGED, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
using SharpChat.SockChat.S2CPackets;
|
||||
using System.Net;
|
||||
|
||||
namespace SharpChat.ClientCommands {
|
||||
public class RemoteAddressClientCommand : ClientCommand {
|
||||
namespace SharpChat.ClientCommands;
|
||||
|
||||
public class RemoteAddressClientCommand : ClientCommand {
|
||||
public bool IsMatch(ClientCommandContext ctx) {
|
||||
return ctx.NameEquals("ip")
|
||||
|| ctx.NameEquals("whois");
|
||||
|
@ -27,5 +28,4 @@ namespace SharpChat.ClientCommands {
|
|||
foreach(IPAddress ip in ctx.Chat.GetRemoteAddresses(ipUser))
|
||||
await ctx.Chat.SendTo(ctx.User, new CommandResponseS2CPacket(msgId, LCR.IP_ADDRESS, false, ipUser.UserName, ip));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
using SharpChat.SockChat.S2CPackets;
|
||||
|
||||
namespace SharpChat.ClientCommands {
|
||||
public class ShutdownRestartClientCommand(ManualResetEvent waitHandle, Func<bool> shutdownCheck) : ClientCommand {
|
||||
namespace SharpChat.ClientCommands;
|
||||
|
||||
public class ShutdownRestartClientCommand(ManualResetEvent waitHandle, Func<bool> shutdownCheck) : ClientCommand {
|
||||
private readonly ManualResetEvent WaitHandle = waitHandle ?? throw new ArgumentNullException(nameof(waitHandle));
|
||||
private readonly Func<bool> ShutdownCheck = shutdownCheck ?? throw new ArgumentNullException(nameof(shutdownCheck));
|
||||
|
||||
|
@ -27,5 +28,4 @@ namespace SharpChat.ClientCommands {
|
|||
await ctx.Chat.Update();
|
||||
WaitHandle?.Set();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
using SharpChat.Events;
|
||||
using SharpChat.SockChat.S2CPackets;
|
||||
|
||||
namespace SharpChat.ClientCommands {
|
||||
public class WhisperClientCommand : ClientCommand {
|
||||
namespace SharpChat.ClientCommands;
|
||||
|
||||
public class WhisperClientCommand : ClientCommand {
|
||||
public bool IsMatch(ClientCommandContext ctx) {
|
||||
return ctx.NameEquals("whisper")
|
||||
|| ctx.NameEquals("msg");
|
||||
|
@ -41,5 +42,4 @@ namespace SharpChat.ClientCommands {
|
|||
true, false, false
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
using SharpChat.SockChat.S2CPackets;
|
||||
using System.Text;
|
||||
|
||||
namespace SharpChat.ClientCommands {
|
||||
public class WhoClientCommand : ClientCommand {
|
||||
namespace SharpChat.ClientCommands;
|
||||
|
||||
public class WhoClientCommand : ClientCommand {
|
||||
public bool IsMatch(ClientCommandContext ctx) {
|
||||
return ctx.NameEquals("who");
|
||||
}
|
||||
|
@ -58,5 +59,4 @@ namespace SharpChat.ClientCommands {
|
|||
await ctx.Chat.SendTo(ctx.User, new CommandResponseS2CPacket(msgId, LCR.USERS_LISTING_CHANNEL, false, whoChan.Name, whoChanSB));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,9 @@ using Fleck;
|
|||
using SharpChat.SockChat;
|
||||
using System.Net;
|
||||
|
||||
namespace SharpChat {
|
||||
public class Connection : IDisposable {
|
||||
namespace SharpChat;
|
||||
|
||||
public class Connection : IDisposable {
|
||||
public const int ID_LENGTH = 20;
|
||||
|
||||
#if DEBUG
|
||||
|
@ -86,5 +87,4 @@ namespace SharpChat {
|
|||
public override int GetHashCode() {
|
||||
return Id.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,9 @@ using SharpChat.SockChat;
|
|||
using SharpChat.SockChat.S2CPackets;
|
||||
using System.Net;
|
||||
|
||||
namespace SharpChat {
|
||||
public class Context {
|
||||
namespace SharpChat;
|
||||
|
||||
public class Context {
|
||||
public record ChannelUserAssoc(string UserId, string ChannelName);
|
||||
|
||||
public readonly SemaphoreSlim ContextAccess = new(1, 1);
|
||||
|
@ -409,5 +410,4 @@ namespace SharpChat {
|
|||
foreach(User user in Users.Where(u => u.Rank >= channel.Rank))
|
||||
await SendTo(user, new ChannelDeleteS2CPacket(channel.Name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
namespace SharpChat.EventStorage {
|
||||
public interface EventStorage {
|
||||
namespace SharpChat.EventStorage;
|
||||
|
||||
public interface EventStorage {
|
||||
void AddEvent(
|
||||
long id,
|
||||
string type,
|
||||
|
@ -16,5 +17,4 @@ namespace SharpChat.EventStorage {
|
|||
void RemoveEvent(StoredEventInfo evt);
|
||||
StoredEventInfo? GetEvent(long seqId);
|
||||
IEnumerable<StoredEventInfo> GetChannelEventLog(string channelName, int amount = 20, int offset = 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,9 @@ using MySqlConnector;
|
|||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace SharpChat.EventStorage {
|
||||
public partial class MariaDBEventStorage(string connString) : EventStorage {
|
||||
namespace SharpChat.EventStorage;
|
||||
|
||||
public partial class MariaDBEventStorage(string connString) : EventStorage {
|
||||
private string ConnectionString { get; } = connString ?? throw new ArgumentNullException(nameof(connString));
|
||||
|
||||
public void AddEvent(
|
||||
|
@ -127,5 +128,4 @@ namespace SharpChat.EventStorage {
|
|||
new MySqlParameter("id", evt.Id)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
using MySqlConnector;
|
||||
using SharpChat.Configuration;
|
||||
|
||||
namespace SharpChat.EventStorage {
|
||||
public partial class MariaDBEventStorage {
|
||||
namespace SharpChat.EventStorage;
|
||||
|
||||
public partial class MariaDBEventStorage {
|
||||
public static string BuildConnString(Configuration.Config config) {
|
||||
return BuildConnString(
|
||||
config.ReadValue("host", "localhost"),
|
||||
|
@ -83,5 +84,4 @@ namespace SharpChat.EventStorage {
|
|||
|
||||
return default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
using MySqlConnector;
|
||||
|
||||
namespace SharpChat.EventStorage {
|
||||
public partial class MariaDBEventStorage {
|
||||
namespace SharpChat.EventStorage;
|
||||
|
||||
public partial class MariaDBEventStorage {
|
||||
private void DoMigration(string name, Action action) {
|
||||
bool done = RunQueryValue<long>(
|
||||
"SELECT COUNT(*) FROM `sqc_migrations` WHERE `migration_name` = @name",
|
||||
|
@ -80,5 +81,4 @@ namespace SharpChat.EventStorage {
|
|||
+ ") COLLATE='utf8mb4_unicode_ci' ENGINE=InnoDB;"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
namespace SharpChat.EventStorage {
|
||||
[Flags]
|
||||
public enum StoredEventFlags {
|
||||
namespace SharpChat.EventStorage;
|
||||
|
||||
[Flags]
|
||||
public enum StoredEventFlags {
|
||||
None = 0,
|
||||
Action = 1,
|
||||
Broadcast = 1 << 1,
|
||||
Log = 1 << 2,
|
||||
Private = 1 << 3,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
using System.Text.Json;
|
||||
|
||||
namespace SharpChat.EventStorage {
|
||||
public class StoredEventInfo(
|
||||
namespace SharpChat.EventStorage;
|
||||
|
||||
public class StoredEventInfo(
|
||||
long id,
|
||||
string type,
|
||||
User? sender,
|
||||
|
@ -10,7 +11,7 @@ namespace SharpChat.EventStorage {
|
|||
string? channelName,
|
||||
JsonDocument data,
|
||||
StoredEventFlags flags
|
||||
) {
|
||||
) {
|
||||
public long Id { get; set; } = id;
|
||||
public string Type { get; set; } = type;
|
||||
public User? Sender { get; set; } = sender;
|
||||
|
@ -19,5 +20,4 @@ namespace SharpChat.EventStorage {
|
|||
public string? ChannelName { get; set; } = channelName;
|
||||
public StoredEventFlags Flags { get; set; } = flags;
|
||||
public JsonDocument Data { get; set; } = data;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
using System.Text.Json;
|
||||
|
||||
namespace SharpChat.EventStorage {
|
||||
public class VirtualEventStorage : EventStorage {
|
||||
namespace SharpChat.EventStorage;
|
||||
|
||||
public class VirtualEventStorage : EventStorage {
|
||||
private readonly Dictionary<long, StoredEventInfo> Events = [];
|
||||
|
||||
public void AddEvent(
|
||||
|
@ -61,5 +62,4 @@ namespace SharpChat.EventStorage {
|
|||
|
||||
return [.. subset.Skip(start).Take(amount)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
namespace SharpChat.Events {
|
||||
public interface ChatEvent {}
|
||||
}
|
||||
namespace SharpChat.Events;
|
||||
|
||||
public interface ChatEvent {}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
namespace SharpChat.Events {
|
||||
public class MessageCreateEvent(
|
||||
namespace SharpChat.Events;
|
||||
|
||||
public class MessageCreateEvent(
|
||||
long msgId,
|
||||
string channelName,
|
||||
string senderId,
|
||||
|
@ -13,7 +14,7 @@ namespace SharpChat.Events {
|
|||
bool isPrivate,
|
||||
bool isAction,
|
||||
bool isBroadcast
|
||||
) : ChatEvent {
|
||||
) : ChatEvent {
|
||||
public long MessageId { get; } = msgId;
|
||||
public string ChannelName { get; } = channelName;
|
||||
public string SenderId { get; } = senderId;
|
||||
|
@ -27,5 +28,4 @@ namespace SharpChat.Events {
|
|||
public bool IsPrivate { get; } = isPrivate;
|
||||
public bool IsAction { get; } = isAction;
|
||||
public bool IsBroadcast { get; } = isBroadcast;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,9 @@ using SharpChat.EventStorage;
|
|||
using SharpChat.Flashii;
|
||||
using System.Text;
|
||||
|
||||
namespace SharpChat {
|
||||
public class Program {
|
||||
namespace SharpChat;
|
||||
|
||||
public class Program {
|
||||
public const string CONFIG = "sharpchat.cfg";
|
||||
|
||||
public static void Main() {
|
||||
|
@ -143,5 +144,4 @@ namespace SharpChat {
|
|||
|
||||
sw.Flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,8 +12,9 @@ using System.Text;
|
|||
// Fleck's Socket wrapper doesn't provide any way to do this with the normally provided APIs
|
||||
// https://github.com/statianzo/Fleck/blob/1.1.0/src/Fleck/WebSocketServer.cs
|
||||
|
||||
namespace SharpChat {
|
||||
public class SharpChatWebSocketServer : IWebSocketServer {
|
||||
namespace SharpChat;
|
||||
|
||||
public class SharpChatWebSocketServer : IWebSocketServer {
|
||||
|
||||
private readonly string _scheme;
|
||||
private readonly IPAddress _locationIP;
|
||||
|
@ -163,5 +164,4 @@ namespace SharpChat {
|
|||
connection.StartReceiving();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
using SharpChat.EventStorage;
|
||||
using System.Text;
|
||||
|
||||
namespace SharpChat.SockChat.S2CPackets {
|
||||
public class ContextMessageS2CPacket(StoredEventInfo evt, bool notify = false) : S2CPacket {
|
||||
namespace SharpChat.SockChat.S2CPackets;
|
||||
|
||||
public class ContextMessageS2CPacket(StoredEventInfo evt, bool notify = false) : S2CPacket {
|
||||
public StoredEventInfo Event { get; private set; } = evt ?? throw new ArgumentNullException(nameof(evt));
|
||||
|
||||
public string Pack() {
|
||||
|
@ -111,5 +112,4 @@ namespace SharpChat.SockChat.S2CPackets {
|
|||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,8 +7,9 @@ using SharpChat.Configuration;
|
|||
using SharpChat.SockChat.S2CPackets;
|
||||
using System.Net;
|
||||
|
||||
namespace SharpChat {
|
||||
public class SockChatServer : IDisposable {
|
||||
namespace SharpChat;
|
||||
|
||||
public class SockChatServer : IDisposable {
|
||||
public const ushort DEFAULT_PORT = 6770;
|
||||
public const int DEFAULT_MSG_LENGTH_MAX = 5000;
|
||||
public const int DEFAULT_MAX_CONNECTIONS = 5;
|
||||
|
@ -236,5 +237,4 @@ namespace SharpChat {
|
|||
|
||||
Server?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,9 @@ using SharpChat.ClientCommands;
|
|||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace SharpChat {
|
||||
public class User(
|
||||
namespace SharpChat;
|
||||
|
||||
public class User(
|
||||
string userId,
|
||||
string userName,
|
||||
ColourInheritable colour,
|
||||
|
@ -12,7 +13,7 @@ namespace SharpChat {
|
|||
string nickName = "",
|
||||
UserStatus status = UserStatus.Online,
|
||||
string statusText = ""
|
||||
) {
|
||||
) {
|
||||
public const int DEFAULT_SIZE = 30;
|
||||
public const int DEFAULT_MINIMUM_DELAY = 10000;
|
||||
public const int DEFAULT_RISKY_OFFSET = 5;
|
||||
|
@ -69,5 +70,4 @@ namespace SharpChat {
|
|||
? $"@{user2.UserId}-{user1.UserId}"
|
||||
: $"@{user1.UserId}-{user2.UserId}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
namespace SharpChat {
|
||||
public enum UserStatus {
|
||||
namespace SharpChat;
|
||||
|
||||
public enum UserStatus {
|
||||
Online,
|
||||
Away,
|
||||
Offline,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
using System.Net;
|
||||
|
||||
namespace SharpChat.Auth {
|
||||
public interface AuthClient {
|
||||
namespace SharpChat.Auth;
|
||||
|
||||
public interface AuthClient {
|
||||
Task<AuthResult> AuthVerifyAsync(IPAddress remoteAddr, string scheme, string token);
|
||||
Task AuthBumpUsersOnlineAsync(IEnumerable<(IPAddress remoteAddr, string userId)> entries);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
namespace SharpChat.Auth {
|
||||
public class AuthFailedException(string message) : Exception(message) {}
|
||||
}
|
||||
namespace SharpChat.Auth;
|
||||
|
||||
public class AuthFailedException(string message) : Exception(message) {}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
namespace SharpChat.Auth {
|
||||
public interface AuthResult {
|
||||
namespace SharpChat.Auth;
|
||||
|
||||
public interface AuthResult {
|
||||
string UserId { get; }
|
||||
string UserName { get; }
|
||||
ColourInheritable UserColour { get; }
|
||||
int UserRank { get; }
|
||||
UserPermissions UserPermissions { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
namespace SharpChat.Bans {
|
||||
public interface BanInfo {
|
||||
namespace SharpChat.Bans;
|
||||
|
||||
public interface BanInfo {
|
||||
BanKind Kind { get; }
|
||||
bool IsPermanent { get; }
|
||||
DateTimeOffset ExpiresAt { get; }
|
||||
public bool HasExpired => !IsPermanent && DateTimeOffset.UtcNow >= ExpiresAt;
|
||||
string ToString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
namespace SharpChat.Bans {
|
||||
public enum BanKind {
|
||||
namespace SharpChat.Bans;
|
||||
|
||||
public enum BanKind {
|
||||
User,
|
||||
IPAddress,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
using System.Net;
|
||||
|
||||
namespace SharpChat.Bans {
|
||||
public interface BansClient {
|
||||
namespace SharpChat.Bans;
|
||||
|
||||
public interface BansClient {
|
||||
Task BanCreateAsync(
|
||||
BanKind kind,
|
||||
TimeSpan duration,
|
||||
|
@ -14,5 +15,4 @@ namespace SharpChat.Bans {
|
|||
Task<bool> BanRevokeAsync(BanInfo info);
|
||||
Task<BanInfo?> BanGetAsync(string? userIdOrName = null, IPAddress? remoteAddr = null);
|
||||
Task<BanInfo[]> BanGetListAsync();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using System.Net;
|
||||
|
||||
namespace SharpChat.Bans {
|
||||
public interface IPAddressBanInfo : BanInfo {
|
||||
namespace SharpChat.Bans;
|
||||
|
||||
public interface IPAddressBanInfo : BanInfo {
|
||||
IPAddress Address { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
namespace SharpChat.Bans {
|
||||
public interface UserBanInfo : BanInfo {
|
||||
namespace SharpChat.Bans;
|
||||
|
||||
public interface UserBanInfo : BanInfo {
|
||||
string UserId { get; }
|
||||
string UserName { get; }
|
||||
ColourInheritable UserColour { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
namespace SharpChat {
|
||||
public readonly record struct ColourInheritable(ColourRgb? rgb) {
|
||||
namespace SharpChat;
|
||||
|
||||
public readonly record struct ColourInheritable(ColourRgb? rgb) {
|
||||
public static readonly ColourInheritable None = new(null);
|
||||
public override string ToString() => rgb.HasValue ? rgb.Value.ToString() : "inherit";
|
||||
|
||||
|
@ -10,5 +11,4 @@ namespace SharpChat {
|
|||
private const int MSZ_INHERIT = 0x40000000;
|
||||
public int ToMisuzu() => rgb.HasValue ? rgb.Value.Raw : MSZ_INHERIT;
|
||||
public static ColourInheritable FromMisuzu(int msz) => (msz & MSZ_INHERIT) > 0 ? None : new(new ColourRgb(msz & 0xFFFFFF));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
namespace SharpChat {
|
||||
public readonly record struct ColourRgb(int Raw) {
|
||||
namespace SharpChat;
|
||||
|
||||
public readonly record struct ColourRgb(int Raw) {
|
||||
public byte Red => (byte)((Raw >> 16) & 0xFF);
|
||||
public byte Green => (byte)((Raw >> 8) & 0xFF);
|
||||
public byte Blue => (byte)(Raw & 0xFF);
|
||||
public override string ToString() => string.Format("#{0:x2}{1:x2}{2:x2}", Red, Green, Blue);
|
||||
public static ColourRgb FromRgb(byte red, byte green, byte blue) => new(red << 16 | green << 8 | blue);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
namespace SharpChat.Configuration {
|
||||
public class CachedValue<T>(Config config, string name, TimeSpan lifetime, T? fallback) {
|
||||
namespace SharpChat.Configuration;
|
||||
|
||||
public class CachedValue<T>(Config config, string name, TimeSpan lifetime, T? fallback) {
|
||||
private Config Config { get; } = config ?? throw new ArgumentNullException(nameof(config));
|
||||
private string Name { get; } = name ?? throw new ArgumentNullException(nameof(name));
|
||||
private object ConfigAccess { get; } = new();
|
||||
|
@ -30,5 +31,4 @@ namespace SharpChat.Configuration {
|
|||
public override string ToString() {
|
||||
return Value?.ToString() ?? string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
namespace SharpChat.Configuration {
|
||||
public interface Config : IDisposable {
|
||||
namespace SharpChat.Configuration;
|
||||
|
||||
public interface Config : IDisposable {
|
||||
/// <summary>
|
||||
/// Creates a proxy object that forces all names to start with the given prefix.
|
||||
/// </summary>
|
||||
|
@ -25,5 +26,4 @@ namespace SharpChat.Configuration {
|
|||
/// Creates an object that caches the read value for a certain amount of time, avoiding disk reads for frequently used non-static values.
|
||||
/// </summary>
|
||||
CachedValue<T> ReadCached<T>(string name, T? fallback = default, TimeSpan? lifetime = null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
namespace SharpChat.Configuration {
|
||||
public abstract class ConfigException : Exception {
|
||||
namespace SharpChat.Configuration;
|
||||
|
||||
public abstract class ConfigException : Exception {
|
||||
public ConfigException(string message) : base(message) { }
|
||||
public ConfigException(string message, Exception ex) : base(message, ex) { }
|
||||
}
|
||||
|
||||
public class ConfigLockException() : ConfigException("Unable to acquire lock for reading configuration.") {}
|
||||
public class ConfigTypeException(Exception ex) : ConfigException("Given type does not match the value in the configuration.", ex) {}
|
||||
}
|
||||
|
||||
public class ConfigLockException() : ConfigException("Unable to acquire lock for reading configuration.") {}
|
||||
public class ConfigTypeException(Exception ex) : ConfigException("Given type does not match the value in the configuration.", ex) {}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
namespace SharpChat.Configuration {
|
||||
public class ScopedConfig(Config config, string prefix) : Config {
|
||||
namespace SharpChat.Configuration;
|
||||
|
||||
public class ScopedConfig(Config config, string prefix) : Config {
|
||||
private Config Config { get; } = config ?? throw new ArgumentNullException(nameof(config));
|
||||
private string Prefix { get; } = prefix ?? throw new ArgumentNullException(nameof(prefix));
|
||||
|
||||
|
@ -30,5 +31,4 @@ namespace SharpChat.Configuration {
|
|||
public void Dispose() {
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
using System.Text;
|
||||
|
||||
namespace SharpChat.Configuration {
|
||||
public class StreamConfig : Config {
|
||||
namespace SharpChat.Configuration;
|
||||
|
||||
public class StreamConfig : Config {
|
||||
private Stream Stream { get; }
|
||||
private StreamReader StreamReader { get; }
|
||||
private Mutex Lock { get; }
|
||||
|
@ -111,5 +112,4 @@ namespace SharpChat.Configuration {
|
|||
Stream.Dispose();
|
||||
Lock.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
using System.Diagnostics;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
namespace SharpChat {
|
||||
public static class Logger {
|
||||
namespace SharpChat;
|
||||
|
||||
public static class Logger {
|
||||
public static void Write(string str) {
|
||||
Console.WriteLine(string.Format("[{1}] {0}", str, DateTime.Now));
|
||||
}
|
||||
|
@ -29,5 +30,4 @@ namespace SharpChat {
|
|||
public static void Debug(object obj) {
|
||||
Write(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
using System.Buffers;
|
||||
using System.Buffers;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace SharpChat {
|
||||
public static class RNG {
|
||||
namespace SharpChat;
|
||||
|
||||
public static class RNG {
|
||||
public const string CHARS = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789";
|
||||
|
||||
private static Random NormalRandom { get; } = new();
|
||||
|
@ -78,5 +79,4 @@ namespace SharpChat {
|
|||
public static string SecureRandomString(int length) {
|
||||
return RandomStringInternal(SecureNext, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
namespace SharpChat {
|
||||
public class RateLimiter {
|
||||
namespace SharpChat;
|
||||
|
||||
public class RateLimiter {
|
||||
private readonly int Size;
|
||||
private readonly int MinimumDelay;
|
||||
private readonly int RiskyOffset;
|
||||
|
@ -31,5 +32,4 @@
|
|||
TimePoints[i - 1] = TimePoints[i];
|
||||
TimePoints[Size - 1] = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace SharpChat {
|
||||
public static class SharpInfo {
|
||||
namespace SharpChat;
|
||||
|
||||
public static class SharpInfo {
|
||||
private const string NAME = @"SharpChat";
|
||||
private const string UNKNOWN = @"XXXXXXXXXX";
|
||||
|
||||
|
@ -32,5 +33,4 @@ namespace SharpChat {
|
|||
sb.Append(VersionStringShort);
|
||||
ProgramName = sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace SharpChat.Snowflake {
|
||||
public class RandomSnowflake(
|
||||
namespace SharpChat.Snowflake;
|
||||
|
||||
public class RandomSnowflake(
|
||||
SnowflakeGenerator? generator = null
|
||||
) {
|
||||
) {
|
||||
public readonly SnowflakeGenerator Generator = generator ?? new SnowflakeGenerator();
|
||||
|
||||
public long Next(DateTimeOffset? at = null) {
|
||||
return Generator.Next(Math.Abs(BitConverter.ToInt64(RandomNumberGenerator.GetBytes(8))), at);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
namespace SharpChat.Snowflake {
|
||||
public class SnowflakeGenerator {
|
||||
namespace SharpChat.Snowflake;
|
||||
|
||||
public class SnowflakeGenerator {
|
||||
public const long MASK = 0x7FFFFFFFFFFFFFFF;
|
||||
// previous default epoch was 1588377600000, but snowflakes are much larger than SharpIds
|
||||
public const long EPOCH = 1356998400000;
|
||||
|
@ -31,5 +32,4 @@
|
|||
public long Next(long sequence, DateTimeOffset? at = null) {
|
||||
return ((Now(at) & TimestampMask) << Shift) | (sequence & SequenceMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
namespace SharpChat {
|
||||
[Flags]
|
||||
public enum UserPermissions : int {
|
||||
namespace SharpChat;
|
||||
|
||||
[Flags]
|
||||
public enum UserPermissions : int {
|
||||
KickUser = 0x00000001,
|
||||
BanUser = 0x00000002,
|
||||
//SilenceUser = 0x00000004,
|
||||
|
@ -20,5 +21,4 @@
|
|||
EditAnyMessage = 0x00004000,
|
||||
SeeIPAddress = 0x00008000,
|
||||
ViewLogs = 0x00040000,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue