diff --git a/SharpChat/ChatChannel.cs b/SharpChat/ChatChannel.cs index c27a046..762936e 100644 --- a/SharpChat/ChatChannel.cs +++ b/SharpChat/ChatChannel.cs @@ -12,14 +12,6 @@ namespace SharpChat { public bool HasPassword => !string.IsNullOrWhiteSpace(Password); - public ChatChannel( - ChatUser owner, - string name, - string? password = null, - bool isTemporary = false, - int rank = 0 - ) : this(name, password, isTemporary, rank, owner?.UserId ?? 0) {} - public ChatChannel( string name, string? password = null, @@ -44,10 +36,6 @@ namespace SharpChat { && OwnerId == user.UserId; } - public override int GetHashCode() { - return Name.GetHashCode(); - } - public static bool CheckName(string name) { return !string.IsNullOrWhiteSpace(name) && name.All(CheckNameChar); } diff --git a/SharpChat/ChatColour.cs b/SharpChat/ChatColour.cs index 75b429a..aad0fb4 100644 --- a/SharpChat/ChatColour.cs +++ b/SharpChat/ChatColour.cs @@ -21,19 +21,11 @@ Inherits = false; } - public override bool Equals(object? obj) { - return obj is ChatColour colour && Equals(colour); - } - public bool Equals(ChatColour other) { - return Red == other.Red + return Inherits == other.Inherits + && Red == other.Red && Green == other.Green - && Blue == other.Blue - && Inherits == other.Inherits; - } - - public override int GetHashCode() { - return ToMisuzu(); + && Blue == other.Blue; } public override string ToString() { @@ -65,13 +57,5 @@ ? None : FromRawRGB(raw); } - - public static bool operator ==(ChatColour left, ChatColour right) { - return left.Equals(right); - } - - public static bool operator !=(ChatColour left, ChatColour right) { - return !(left == right); - } } } diff --git a/SharpChat/ChatCommandContext.cs b/SharpChat/ChatCommandContext.cs index 2ac1c37..1a8cefe 100644 --- a/SharpChat/ChatCommandContext.cs +++ b/SharpChat/ChatCommandContext.cs @@ -17,35 +17,16 @@ namespace SharpChat { ChatConnection connection, ChatChannel channel ) { - if(text == null) - throw new ArgumentNullException(nameof(text)); - - Chat = chat ?? throw new ArgumentNullException(nameof(chat)); - User = user ?? throw new ArgumentNullException(nameof(user)); - Connection = connection ?? throw new ArgumentNullException(nameof(connection)); - Channel = channel ?? throw new ArgumentNullException(nameof(channel)); + Chat = chat; + User = user; + Connection = connection; + Channel = channel; string[] parts = text[1..].Split(' '); Name = parts.First().Replace(".", string.Empty); Args = parts.Skip(1).ToArray(); } - public ChatCommandContext( - string name, - string[] args, - ChatContext chat, - ChatUser user, - ChatConnection connection, - ChatChannel channel - ) { - Name = name ?? throw new ArgumentNullException(nameof(name)); - Args = args ?? throw new ArgumentNullException(nameof(args)); - Chat = chat ?? throw new ArgumentNullException(nameof(chat)); - User = user ?? throw new ArgumentNullException(nameof(user)); - Connection = connection ?? throw new ArgumentNullException(nameof(connection)); - Channel = channel ?? throw new ArgumentNullException(nameof(channel)); - } - public bool NameEquals(string name) { return Name.Equals(name, StringComparison.InvariantCultureIgnoreCase); } diff --git a/SharpChat/ChatConnection.cs b/SharpChat/ChatConnection.cs index aadf074..f1a9b1b 100644 --- a/SharpChat/ChatConnection.cs +++ b/SharpChat/ChatConnection.cs @@ -84,9 +84,5 @@ namespace SharpChat { public override string ToString() { return Id; } - - public override int GetHashCode() { - return Id.GetHashCode(); - } } } diff --git a/SharpChat/ChatContext.cs b/SharpChat/ChatContext.cs index 09b4ec6..d5d93d7 100644 --- a/SharpChat/ChatContext.cs +++ b/SharpChat/ChatContext.cs @@ -13,16 +13,16 @@ namespace SharpChat { public readonly SemaphoreSlim ContextAccess = new(1, 1); - public HashSet<ChatChannel> Channels { get; } = new(); - public HashSet<ChatConnection> Connections { get; } = new(); - public HashSet<ChatUser> Users { get; } = new(); + public Dictionary<string, ChatChannel> Channels { get; } = new(); + public List<ChatConnection> Connections { get; } = new(); + public Dictionary<long, ChatUser> Users { get; } = new(); public IEventStorage Events { get; } public HashSet<ChannelUserAssoc> ChannelUsers { get; } = new(); public Dictionary<long, RateLimiter> UserRateLimiters { get; } = new(); public Dictionary<long, ChatChannel> UserLastChannel { get; } = new(); public ChatContext(IEventStorage evtStore) { - Events = evtStore ?? throw new ArgumentNullException(nameof(evtStore)); + Events = evtStore; } public void DispatchEvent(IChatEvent eventInfo) { @@ -37,11 +37,11 @@ namespace SharpChat { if(mce.ChannelName?.StartsWith("@") != true) return; - IEnumerable<long> uids = mce.ChannelName[1..].Split('-', 3).Select(u => long.TryParse(u, out long up) ? up : -1); - if(uids.Count() != 2) + long[] targetIds = mce.ChannelName[1..].Split('-', 3).Select(u => long.TryParse(u, out long up) ? up : -1).ToArray(); + if(targetIds.Length != 2) return; - IEnumerable<ChatUser> users = Users.Where(u => uids.Any(uid => uid == u.UserId)); + ChatUser[] users = Users.Where(kvp => targetIds.Contains(kvp.Key)).Select(kvp => kvp.Value).ToArray(); ChatUser? target = users.FirstOrDefault(u => u.UserId != mce.SenderId); if(target == null) return; @@ -56,7 +56,7 @@ namespace SharpChat { true )); } else { - ChatChannel? channel = Channels.FirstOrDefault(c => c.NameEquals(mce.ChannelName)); + ChatChannel? channel = Channels.Values.FirstOrDefault(c => c.NameEquals(mce.ChannelName)); if(channel != null) SendTo(channel, new MessageAddPacket( mce.MessageId, @@ -88,9 +88,11 @@ namespace SharpChat { Logger.Write($"Nuked connection {conn.Id} associated with {conn.User}."); } - Connections.RemoveWhere(conn => conn.IsDisposed); + int removed = Connections.RemoveAll(conn => conn.IsDisposed); + if(removed > 0) + Logger.Write($"Removed {removed} nuked connections from the list."); - foreach(ChatUser user in Users) + foreach(ChatUser user in Users.Values) if(!Connections.Any(conn => conn.User == user)) { HandleDisconnect(user, ChatUserDisconnectReason.TimeOut); Logger.Write($"Timed out {user} (no more connections)."); @@ -118,7 +120,7 @@ namespace SharpChat { public ChatChannel[] GetUserChannels(ChatUser user) { string[] names = GetUserChannelNames(user); - return Channels.Where(c => names.Any(n => c.NameEquals(n))).ToArray(); + return Channels.Values.Where(c => names.Any(n => c.NameEquals(n))).ToArray(); } public long[] GetChannelUserIds(ChatChannel channel) { @@ -126,8 +128,8 @@ namespace SharpChat { } public ChatUser[] GetChannelUsers(ChatChannel channel) { - long[] ids = GetChannelUserIds(channel); - return Users.Where(u => ids.Contains(u.UserId)).ToArray(); + long[] targetIds = GetChannelUserIds(channel); + return Users.Values.Where(u => targetIds.Contains(u.UserId)).ToArray(); } public void UpdateUser( @@ -142,9 +144,6 @@ namespace SharpChat { bool? isSuper = null, bool silent = false ) { - if(user == null) - throw new ArgumentNullException(nameof(user)); - bool hasChanged = false; string? previousName = null; @@ -161,7 +160,7 @@ namespace SharpChat { hasChanged = true; } - if(colour.HasValue && user.Colour != colour.Value) { + if(colour.HasValue && user.Colour.Equals(colour.Value)) { user.Colour = colour.Value; hasChanged = true; } @@ -215,7 +214,7 @@ namespace SharpChat { foreach(ChatConnection conn in Connections) if(conn.User == user) conn.Dispose(); - Connections.RemoveWhere(conn => conn.IsDisposed); + Connections.RemoveAll(conn => conn.IsDisposed); HandleDisconnect(user, reason); } @@ -261,11 +260,11 @@ namespace SharpChat { HandleChannelEventLog(chan.Name, p => conn.Send(p)); - conn.Send(new ChannelsPopulatePacket(Channels.Where(c => c.Rank <= user.Rank).Select( + conn.Send(new ChannelsPopulatePacket(Channels.Values.Where(c => c.Rank <= user.Rank).Select( channel => new ChannelsPopulatePacket.ListEntry(channel.Name, channel.HasPassword, channel.IsTemporary) ).ToArray())); - Users.Add(user); + Users.Add(user.UserId, user); ChannelUsers.Add(new ChannelUserAssoc(user.UserId, chan.Name)); UserLastChannel[user.UserId] = chan; @@ -273,7 +272,7 @@ namespace SharpChat { public void HandleDisconnect(ChatUser user, ChatUserDisconnectReason reason = ChatUserDisconnectReason.Leave) { UpdateUser(user, status: ChatUserStatus.Offline); - Users.Remove(user); + Users.Remove(user.UserId); UserLastChannel.Remove(user.UserId); ChatChannel[] channels = GetUserChannels(user); @@ -313,7 +312,7 @@ namespace SharpChat { } public void ForceChannelSwitch(ChatUser user, ChatChannel chan) { - if(!Channels.Contains(chan)) + if(!Channels.ContainsValue(chan)) return; ChatChannel oldChan = UserLastChannel[user.UserId]; @@ -340,31 +339,18 @@ namespace SharpChat { } public void Send(IServerPacket packet) { - if(packet == null) - throw new ArgumentNullException(nameof(packet)); - foreach(ChatConnection conn in Connections) if(conn.IsAuthed) conn.Send(packet); } public void SendTo(ChatUser user, IServerPacket packet) { - if(user == null) - throw new ArgumentNullException(nameof(user)); - if(packet == null) - throw new ArgumentNullException(nameof(packet)); - foreach(ChatConnection conn in Connections) if(conn.IsAlive && conn.User == user) conn.Send(packet); } public void SendTo(ChatChannel channel, IServerPacket packet) { - if(channel == null) - throw new ArgumentNullException(nameof(channel)); - if(packet == null) - throw new ArgumentNullException(nameof(packet)); - // might be faster to grab the users first and then cascade into that SendTo IEnumerable<ChatConnection> conns = Connections.Where(c => c.IsAuthed && IsInChannel(c.User, channel)); foreach(ChatConnection conn in conns) @@ -372,12 +358,7 @@ namespace SharpChat { } public void SendToUserChannels(ChatUser user, IServerPacket packet) { - if(user == null) - throw new ArgumentNullException(nameof(user)); - if(packet == null) - throw new ArgumentNullException(nameof(packet)); - - IEnumerable<ChatChannel> chans = Channels.Where(c => IsInChannel(user, c)); + IEnumerable<ChatChannel> chans = Channels.Values.Where(c => IsInChannel(user, c)); IEnumerable<ChatConnection> conns = Connections.Where(conn => conn.IsAuthed && ChannelUsers.Any(cu => cu.UserId == conn.User?.UserId && chans.Any(chan => chan.NameEquals(cu.ChannelName)))); foreach(ChatConnection conn in conns) conn.Send(packet); @@ -388,9 +369,6 @@ namespace SharpChat { } public void ForceChannel(ChatUser user, ChatChannel? chan = null) { - if(user == null) - throw new ArgumentNullException(nameof(user)); - if(chan == null && !UserLastChannel.TryGetValue(user.UserId, out chan)) throw new ArgumentException("no channel???"); @@ -403,9 +381,7 @@ namespace SharpChat { int? minRank = null, string? password = null ) { - if(channel == null) - throw new ArgumentNullException(nameof(channel)); - if(!Channels.Contains(channel)) + if(!Channels.ContainsValue(channel)) throw new ArgumentException("Provided channel is not registered with this manager.", nameof(channel)); string prevName = channel.Name; @@ -420,7 +396,7 @@ namespace SharpChat { channel.Password = password; // TODO: Users that no longer have access to the channel/gained access to the channel by the rank change should receive delete and create packets respectively - foreach(ChatUser user in Users.Where(u => u.Rank >= channel.Rank)) { + foreach(ChatUser user in Users.Values.Where(u => u.Rank >= channel.Rank)) { SendTo(user, new ChannelUpdatePacket(prevName, channel.Name, channel.HasPassword, channel.IsTemporary)); } } @@ -429,12 +405,12 @@ namespace SharpChat { if(channel == null || !Channels.Any()) return; - ChatChannel? defaultChannel = Channels.FirstOrDefault(); + ChatChannel? defaultChannel = Channels.Values.FirstOrDefault(); if(defaultChannel == null) return; // Remove channel from the listing - Channels.Remove(channel); + Channels.Remove(channel.Name); // Move all users back to the main channel // TODO: Replace this with a kick. SCv2 supports being in 0 channels, SCv1 should force the user back to DefaultChannel. @@ -442,7 +418,7 @@ namespace SharpChat { SwitchChannel(user, defaultChannel, string.Empty); // Broadcast deletion of channel - foreach(ChatUser user in Users.Where(u => u.Rank >= channel.Rank)) + foreach(ChatUser user in Users.Values.Where(u => u.Rank >= channel.Rank)) SendTo(user, new ChannelDeletePacket(channel.Name)); } } diff --git a/SharpChat/ChatPacketHandlerContext.cs b/SharpChat/ChatPacketHandlerContext.cs index eb8eda3..321fb2f 100644 --- a/SharpChat/ChatPacketHandlerContext.cs +++ b/SharpChat/ChatPacketHandlerContext.cs @@ -11,9 +11,9 @@ namespace SharpChat { ChatContext chat, ChatConnection connection ) { - Text = text ?? throw new ArgumentNullException(nameof(text)); - Chat = chat ?? throw new ArgumentNullException(nameof(chat)); - Connection = connection ?? throw new ArgumentNullException(nameof(connection)); + Text = text; + Chat = chat; + Connection = connection; } public bool CheckPacketId(string packetId) { diff --git a/SharpChat/ChatUser.cs b/SharpChat/ChatUser.cs index d8c0983..7151825 100644 --- a/SharpChat/ChatUser.cs +++ b/SharpChat/ChatUser.cs @@ -2,7 +2,7 @@ using System.Text; namespace SharpChat { - public class ChatUser : IEquatable<ChatUser> { + public class ChatUser { public const int DEFAULT_SIZE = 30; public const int DEFAULT_MINIMUM_DELAY = 10000; public const int DEFAULT_RISKY_OFFSET = 5; @@ -34,7 +34,7 @@ namespace SharpChat { public ChatUser( long userId, - string? userName, + string userName, ChatColour colour, int rank, ChatUserPermissions perms, @@ -44,7 +44,7 @@ namespace SharpChat { bool isSuper = false ) { UserId = userId; - UserName = userName ?? throw new ArgumentNullException(nameof(userName)); + UserName = userName; Colour = colour; Rank = rank; Permissions = perms; @@ -61,18 +61,6 @@ namespace SharpChat { || string.Equals(name, LegacyNameWithStatus, StringComparison.InvariantCultureIgnoreCase); } - public override int GetHashCode() { - return UserId.GetHashCode(); - } - - public override bool Equals(object? obj) { - return Equals(obj as ChatUser); - } - - public bool Equals(ChatUser? other) { - return UserId == other?.UserId; - } - public static string GetDMChannelName(ChatUser user1, ChatUser user2) { return user1.UserId < user2.UserId ? $"@{user1.UserId}-{user2.UserId}" diff --git a/SharpChat/Commands/BanListCommand.cs b/SharpChat/Commands/BanListCommand.cs index 38ea8cd..66327f3 100644 --- a/SharpChat/Commands/BanListCommand.cs +++ b/SharpChat/Commands/BanListCommand.cs @@ -9,7 +9,7 @@ namespace SharpChat.Commands { private readonly MisuzuClient Misuzu; public BanListCommand(MisuzuClient msz) { - Misuzu = msz ?? throw new ArgumentNullException(nameof(msz)); + Misuzu = msz; } public bool IsMatch(ChatCommandContext ctx) { diff --git a/SharpChat/Commands/ChannelCreateCommand.cs b/SharpChat/Commands/ChannelCreateCommand.cs index 1cded6d..369a448 100644 --- a/SharpChat/Commands/ChannelCreateCommand.cs +++ b/SharpChat/Commands/ChannelCreateCommand.cs @@ -38,19 +38,20 @@ namespace SharpChat.Commands { return; } - if(ctx.Chat.Channels.Any(c => c.NameEquals(createChanName))) { + if(ctx.Chat.Channels.Values.Any(c => c.NameEquals(createChanName))) { ctx.Chat.SendTo(ctx.User, new ChannelNameInUseErrorPacket(createChanName)); return; } ChatChannel createChan = new( - ctx.User, createChanName, + createChanName, isTemporary: !ctx.User.Permissions.HasFlag(ChatUserPermissions.SetChannelPermanent), - rank: createChanHierarchy + rank: createChanHierarchy, + ownerId: ctx.User.UserId ); - ctx.Chat.Channels.Add(createChan); - foreach(ChatUser ccu in ctx.Chat.Users.Where(u => u.Rank >= ctx.Channel.Rank)) + ctx.Chat.Channels.Add(createChan.Name, createChan); + foreach(ChatUser ccu in ctx.Chat.Users.Values.Where(u => u.Rank >= ctx.Channel.Rank)) ctx.Chat.SendTo(ccu, new ChannelCreatePacket( ctx.Channel.Name, ctx.Channel.HasPassword, diff --git a/SharpChat/Commands/ChannelDeleteCommand.cs b/SharpChat/Commands/ChannelDeleteCommand.cs index f1094bc..09da53d 100644 --- a/SharpChat/Commands/ChannelDeleteCommand.cs +++ b/SharpChat/Commands/ChannelDeleteCommand.cs @@ -17,7 +17,7 @@ namespace SharpChat.Commands { } string delChanName = string.Join('_', ctx.Args); - ChatChannel? delChan = ctx.Chat.Channels.FirstOrDefault(c => c.NameEquals(delChanName)); + ChatChannel? delChan = ctx.Chat.Channels.Values.FirstOrDefault(c => c.NameEquals(delChanName)); if(delChan == null) { ctx.Chat.SendTo(ctx.User, new ChannelNotFoundErrorPacket(delChanName)); diff --git a/SharpChat/Commands/ChannelJoinCommand.cs b/SharpChat/Commands/ChannelJoinCommand.cs index b7e1277..8c2a948 100644 --- a/SharpChat/Commands/ChannelJoinCommand.cs +++ b/SharpChat/Commands/ChannelJoinCommand.cs @@ -9,7 +9,7 @@ namespace SharpChat.Commands { public void Dispatch(ChatCommandContext ctx) { string joinChanStr = ctx.Args.FirstOrDefault() ?? string.Empty; - ChatChannel? joinChan = ctx.Chat.Channels.FirstOrDefault(c => c.NameEquals(joinChanStr)); + ChatChannel? joinChan = ctx.Chat.Channels.Values.FirstOrDefault(c => c.NameEquals(joinChanStr)); if(joinChan == null) { ctx.Chat.SendTo(ctx.User, new ChannelNotFoundErrorPacket(joinChanStr)); diff --git a/SharpChat/Commands/KickBanCommand.cs b/SharpChat/Commands/KickBanCommand.cs index 60e887b..b670299 100644 --- a/SharpChat/Commands/KickBanCommand.cs +++ b/SharpChat/Commands/KickBanCommand.cs @@ -9,7 +9,7 @@ namespace SharpChat.Commands { private readonly MisuzuClient Misuzu; public KickBanCommand(MisuzuClient msz) { - Misuzu = msz ?? throw new ArgumentNullException(nameof(msz)); + Misuzu = msz; } public bool IsMatch(ChatCommandContext ctx) { @@ -30,7 +30,7 @@ namespace SharpChat.Commands { int banReasonIndex = 1; ChatUser? banUser = null; - if(string.IsNullOrEmpty(banUserTarget) || (banUser = ctx.Chat.Users.FirstOrDefault(u => u.NameEquals(banUserTarget))) == null) { + if(string.IsNullOrEmpty(banUserTarget) || (banUser = ctx.Chat.Users.Values.FirstOrDefault(u => u.NameEquals(banUserTarget))) == null) { ctx.Chat.SendTo(ctx.User, new UserNotFoundErrorPacket(banUserTarget)); return; } diff --git a/SharpChat/Commands/MessageWhisperCommand.cs b/SharpChat/Commands/MessageWhisperCommand.cs index d1e657a..86c3b2e 100644 --- a/SharpChat/Commands/MessageWhisperCommand.cs +++ b/SharpChat/Commands/MessageWhisperCommand.cs @@ -17,7 +17,7 @@ namespace SharpChat.Commands { } string whisperUserStr = ctx.Args.FirstOrDefault() ?? string.Empty; - ChatUser? whisperUser = ctx.Chat.Users.FirstOrDefault(u => u.NameEquals(whisperUserStr)); + ChatUser? whisperUser = ctx.Chat.Users.Values.FirstOrDefault(u => u.NameEquals(whisperUserStr)); if(whisperUser == null) { ctx.Chat.SendTo(ctx.User, new UserNotFoundErrorPacket(whisperUserStr)); diff --git a/SharpChat/Commands/PardonAddressCommand.cs b/SharpChat/Commands/PardonAddressCommand.cs index fb4e87d..8e069f3 100644 --- a/SharpChat/Commands/PardonAddressCommand.cs +++ b/SharpChat/Commands/PardonAddressCommand.cs @@ -10,7 +10,7 @@ namespace SharpChat.Commands { private readonly MisuzuClient Misuzu; public PardonAddressCommand(MisuzuClient msz) { - Misuzu = msz ?? throw new ArgumentNullException(nameof(msz)); + Misuzu = msz; } public bool IsMatch(ChatCommandContext ctx) { diff --git a/SharpChat/Commands/PardonUserCommand.cs b/SharpChat/Commands/PardonUserCommand.cs index ed861ff..b98b971 100644 --- a/SharpChat/Commands/PardonUserCommand.cs +++ b/SharpChat/Commands/PardonUserCommand.cs @@ -9,7 +9,7 @@ namespace SharpChat.Commands { private readonly MisuzuClient Misuzu; public PardonUserCommand(MisuzuClient msz) { - Misuzu = msz ?? throw new ArgumentNullException(nameof(msz)); + Misuzu = msz; } public bool IsMatch(ChatCommandContext ctx) { @@ -31,10 +31,10 @@ namespace SharpChat.Commands { return; } - ChatUser? unbanUser = ctx.Chat.Users.FirstOrDefault(u => u.NameEquals(unbanUserTarget)); + ChatUser? unbanUser = ctx.Chat.Users.Values.FirstOrDefault(u => u.NameEquals(unbanUserTarget)); if(unbanUser == null && long.TryParse(unbanUserTarget, out long unbanUserId)) { unbanUserTargetIsName = false; - unbanUser = ctx.Chat.Users.FirstOrDefault(u => u.UserId == unbanUserId); + unbanUser = ctx.Chat.Users.Values.FirstOrDefault(u => u.UserId == unbanUserId); } if(unbanUser != null) diff --git a/SharpChat/Commands/ShutdownRestartCommand.cs b/SharpChat/Commands/ShutdownRestartCommand.cs index f2746aa..b7bf413 100644 --- a/SharpChat/Commands/ShutdownRestartCommand.cs +++ b/SharpChat/Commands/ShutdownRestartCommand.cs @@ -8,8 +8,8 @@ namespace SharpChat.Commands { private readonly Func<bool> ShutdownCheck; public ShutdownRestartCommand(ManualResetEvent waitHandle, Func<bool> shutdownCheck) { - WaitHandle = waitHandle ?? throw new ArgumentNullException(nameof(waitHandle)); - ShutdownCheck = shutdownCheck ?? throw new ArgumentNullException(nameof(shutdownCheck)); + WaitHandle = waitHandle; + ShutdownCheck = shutdownCheck; } public bool IsMatch(ChatCommandContext ctx) { diff --git a/SharpChat/Commands/UserNickCommand.cs b/SharpChat/Commands/UserNickCommand.cs index adab7c1..f8de6b5 100644 --- a/SharpChat/Commands/UserNickCommand.cs +++ b/SharpChat/Commands/UserNickCommand.cs @@ -19,7 +19,7 @@ namespace SharpChat.Commands { int offset = 0; if(setOthersNick && long.TryParse(ctx.Args.FirstOrDefault(), out long targetUserId) && targetUserId > 0) { - targetUser = ctx.Chat.Users.FirstOrDefault(u => u.UserId == targetUserId); + targetUser = ctx.Chat.Users.Values.FirstOrDefault(u => u.UserId == targetUserId); ++offset; } @@ -42,7 +42,7 @@ namespace SharpChat.Commands { else if(string.IsNullOrEmpty(nickStr)) nickStr = string.Empty; - if(!string.IsNullOrWhiteSpace(nickStr) && ctx.Chat.Users.Any(u => u.NameEquals(nickStr))) { + if(!string.IsNullOrWhiteSpace(nickStr) && ctx.Chat.Users.Values.Any(u => u.NameEquals(nickStr))) { ctx.Chat.SendTo(ctx.User, new UserNameInUseErrorPacket(nickStr)); return; } diff --git a/SharpChat/Commands/WhoCommand.cs b/SharpChat/Commands/WhoCommand.cs index b184e1a..6ee4ab0 100644 --- a/SharpChat/Commands/WhoCommand.cs +++ b/SharpChat/Commands/WhoCommand.cs @@ -12,13 +12,13 @@ namespace SharpChat.Commands { if(string.IsNullOrEmpty(channelName)) { ctx.Chat.SendTo(ctx.User, new WhoServerResponsePacket( - ctx.Chat.Users.Select(u => u.LegacyName).ToArray(), + ctx.Chat.Users.Values.Select(u => u.LegacyName).ToArray(), ctx.User.LegacyName )); return; } - ChatChannel? channel = ctx.Chat.Channels.FirstOrDefault(c => c.NameEquals(channelName)); + ChatChannel? channel = ctx.Chat.Channels.Values.FirstOrDefault(c => c.NameEquals(channelName)); if(channel == null) { ctx.Chat.SendTo(ctx.User, new ChannelNotFoundErrorPacket(channelName)); diff --git a/SharpChat/Commands/WhoisCommand.cs b/SharpChat/Commands/WhoisCommand.cs index 2c6a144..f97db47 100644 --- a/SharpChat/Commands/WhoisCommand.cs +++ b/SharpChat/Commands/WhoisCommand.cs @@ -18,7 +18,7 @@ namespace SharpChat.Commands { string ipUserStr = ctx.Args.FirstOrDefault() ?? string.Empty; ChatUser? ipUser; - if(string.IsNullOrWhiteSpace(ipUserStr) || (ipUser = ctx.Chat.Users.FirstOrDefault(u => u.NameEquals(ipUserStr))) == null) { + if(string.IsNullOrWhiteSpace(ipUserStr) || (ipUser = ctx.Chat.Users.Values.FirstOrDefault(u => u.NameEquals(ipUserStr))) == null) { ctx.Chat.SendTo(ctx.User, new UserNotFoundErrorPacket(ipUserStr)); return; } diff --git a/SharpChat/Config/CachedValue.cs b/SharpChat/Config/CachedValue.cs index 64adc96..b33a0d5 100644 --- a/SharpChat/Config/CachedValue.cs +++ b/SharpChat/Config/CachedValue.cs @@ -28,12 +28,13 @@ namespace SharpChat.Config { public static implicit operator T?(CachedValue<T> val) => val.Value; public CachedValue(IConfig config, string name, TimeSpan lifetime, T? fallback) { - Config = config ?? throw new ArgumentNullException(nameof(config)); - Name = name ?? throw new ArgumentNullException(nameof(name)); - Lifetime = lifetime; - Fallback = fallback; if(string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Name cannot be empty.", nameof(name)); + + Config = config; + Name = name; + Lifetime = lifetime; + Fallback = fallback; } public void Refresh() { diff --git a/SharpChat/Config/ScopedConfig.cs b/SharpChat/Config/ScopedConfig.cs index 7cc5a53..3350e17 100644 --- a/SharpChat/Config/ScopedConfig.cs +++ b/SharpChat/Config/ScopedConfig.cs @@ -6,10 +6,12 @@ namespace SharpChat.Config { private string Prefix { get; } public ScopedConfig(IConfig config, string prefix) { - Config = config ?? throw new ArgumentNullException(nameof(config)); - Prefix = prefix ?? throw new ArgumentNullException(nameof(prefix)); if(string.IsNullOrWhiteSpace(prefix)) throw new ArgumentException("Prefix must exist.", nameof(prefix)); + + Config = config; + Prefix = prefix; + if(Prefix[^1] != ':') Prefix += ':'; } diff --git a/SharpChat/Config/StreamConfig.cs b/SharpChat/Config/StreamConfig.cs index 653f302..702e661 100644 --- a/SharpChat/Config/StreamConfig.cs +++ b/SharpChat/Config/StreamConfig.cs @@ -17,7 +17,7 @@ namespace SharpChat.Config { : this(new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Read, FileShare.ReadWrite)) { } public StreamConfig(Stream stream) { - Stream = stream ?? throw new ArgumentNullException(nameof(stream)); + Stream = stream; if(!Stream.CanRead) throw new ArgumentException("Provided stream must be readable.", nameof(stream)); if(!Stream.CanSeek) diff --git a/SharpChat/EventStorage/MariaDBEventStorage.cs b/SharpChat/EventStorage/MariaDBEventStorage.cs index c0e5bd1..7ce4b97 100644 --- a/SharpChat/EventStorage/MariaDBEventStorage.cs +++ b/SharpChat/EventStorage/MariaDBEventStorage.cs @@ -1,18 +1,15 @@ using MySqlConnector; using System; using System.Collections.Generic; -using System.Dynamic; using System.Text; using System.Text.Json; -using System.Threading.Channels; -namespace SharpChat.EventStorage -{ +namespace SharpChat.EventStorage { public partial class MariaDBEventStorage : IEventStorage { private string ConnectionString { get; } public MariaDBEventStorage(string connString) { - ConnectionString = connString ?? throw new ArgumentNullException(nameof(connString)); + ConnectionString = connString; } public void AddEvent( @@ -48,9 +45,6 @@ namespace SharpChat.EventStorage object? data = null, StoredEventFlags flags = StoredEventFlags.None ) { - if(type == null) - throw new ArgumentNullException(nameof(type)); - RunCommand( "INSERT INTO `sqc_events` (`event_id`, `event_created`, `event_type`, `event_target`, `event_flags`, `event_data`" + ", `event_sender`, `event_sender_name`, `event_sender_colour`, `event_sender_rank`, `event_sender_nick`, `event_sender_perms`)" @@ -71,9 +65,6 @@ namespace SharpChat.EventStorage } public long AddEvent(string type, ChatUser user, ChatChannel channel, object? data = null, StoredEventFlags flags = StoredEventFlags.None) { - if(type == null) - throw new ArgumentNullException(nameof(type)); - long id = SharpId.Next(); AddEvent( @@ -172,8 +163,6 @@ namespace SharpChat.EventStorage } public void RemoveEvent(StoredEventInfo evt) { - if(evt == null) - throw new ArgumentNullException(nameof(evt)); RunCommand( "UPDATE IGNORE `sqc_events` SET `event_deleted` = NOW() WHERE `event_id` = @id AND `event_deleted` IS NULL", new MySqlParameter("id", evt.Id) diff --git a/SharpChat/EventStorage/VirtualEventStorage.cs b/SharpChat/EventStorage/VirtualEventStorage.cs index c3b61cd..13c9295 100644 --- a/SharpChat/EventStorage/VirtualEventStorage.cs +++ b/SharpChat/EventStorage/VirtualEventStorage.cs @@ -40,14 +40,11 @@ namespace SharpChat.EventStorage { object? data = null, StoredEventFlags flags = StoredEventFlags.None ) { - if(type == null) - throw new ArgumentNullException(nameof(type)); - // VES is meant as an emergency fallback but this is something else JsonDocument hack = JsonDocument.Parse(data == null ? "{}" : JsonSerializer.Serialize(data)); Events.Add(id, new(id, type, senderId < 1 ? null : new ChatUser( senderId, - senderName, + senderName ?? string.Empty, senderColour, senderRank, senderPerms, @@ -56,9 +53,6 @@ namespace SharpChat.EventStorage { } public long AddEvent(string type, ChatUser user, ChatChannel channel, object? data = null, StoredEventFlags flags = StoredEventFlags.None) { - if(type == null) - throw new ArgumentNullException(nameof(type)); - long id = SharpId.Next(); AddEvent( diff --git a/SharpChat/Misuzu/MisuzuClient.cs b/SharpChat/Misuzu/MisuzuClient.cs index 5d1584a..4c50a84 100644 --- a/SharpChat/Misuzu/MisuzuClient.cs +++ b/SharpChat/Misuzu/MisuzuClient.cs @@ -34,9 +34,7 @@ namespace SharpChat.Misuzu { private CachedValue<string> SecretKey { get; } public MisuzuClient(HttpClient httpClient, IConfig config) { - if(config == null) - throw new ArgumentNullException(nameof(config)); - HttpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient)); + HttpClient = httpClient; BaseURL = config.ReadCached("url", DEFAULT_BASE_URL); SecretKey = config.ReadCached("secret", DEFAULT_SECRET_KEY); @@ -77,8 +75,6 @@ namespace SharpChat.Misuzu { } public async Task BumpUsersOnlineAsync(IEnumerable<(string userId, string ipAddr)> list) { - if(list == null) - throw new ArgumentNullException(nameof(list)); if(!list.Any()) return; @@ -164,9 +160,6 @@ namespace SharpChat.Misuzu { } public async Task<bool> RevokeBanAsync(MisuzuBanInfo banInfo, BanRevokeKind kind) { - if(banInfo == null) - throw new ArgumentNullException(nameof(banInfo)); - string type = kind switch { BanRevokeKind.UserId => "user", BanRevokeKind.RemoteAddress => "addr", @@ -208,9 +201,9 @@ namespace SharpChat.Misuzu { string reason ) { if(string.IsNullOrWhiteSpace(targetAddr)) - throw new ArgumentNullException(nameof(targetAddr)); + throw new ArgumentException("targetAddr may not be empty", nameof(targetAddr)); if(string.IsNullOrWhiteSpace(modAddr)) - throw new ArgumentNullException(nameof(modAddr)); + throw new ArgumentException("modAddr may not be empty", nameof(modAddr)); if(duration <= TimeSpan.Zero) return; diff --git a/SharpChat/Packet/MessagePopulatePacket.cs b/SharpChat/Packet/MessagePopulatePacket.cs index 28e6897..e455d72 100644 --- a/SharpChat/Packet/MessagePopulatePacket.cs +++ b/SharpChat/Packet/MessagePopulatePacket.cs @@ -9,7 +9,7 @@ namespace SharpChat.Packet { private readonly bool Notify; public MessagePopulatePacket(StoredEventInfo evt, bool notify = false) { - Event = evt ?? throw new ArgumentNullException(nameof(evt)); + Event = evt; Notify = notify; } diff --git a/SharpChat/Packet/UserChannelForceJoinPacket.cs b/SharpChat/Packet/UserChannelForceJoinPacket.cs index d280d14..766186d 100644 --- a/SharpChat/Packet/UserChannelForceJoinPacket.cs +++ b/SharpChat/Packet/UserChannelForceJoinPacket.cs @@ -5,7 +5,7 @@ namespace SharpChat.Packet { private readonly string ChannelName; public UserChannelForceJoinPacket(string channelName) { - ChannelName = channelName ?? throw new ArgumentNullException(nameof(channelName)); + ChannelName = channelName; } public override string Pack() { diff --git a/SharpChat/Packet/UserChannelJoinPacket.cs b/SharpChat/Packet/UserChannelJoinPacket.cs index df126ab..c7e6c09 100644 --- a/SharpChat/Packet/UserChannelJoinPacket.cs +++ b/SharpChat/Packet/UserChannelJoinPacket.cs @@ -16,7 +16,7 @@ namespace SharpChat.Packet { ChatUserPermissions userPerms ) { UserId = userId; - UserName = userName ?? throw new ArgumentNullException(nameof(userName)); + UserName = userName; UserColour = userColour; UserRank = userRank; UserPerms = userPerms; diff --git a/SharpChat/Packet/UserUpdateNotificationPacket.cs b/SharpChat/Packet/UserUpdateNotificationPacket.cs index 7c01f7b..2275ddc 100644 --- a/SharpChat/Packet/UserUpdateNotificationPacket.cs +++ b/SharpChat/Packet/UserUpdateNotificationPacket.cs @@ -7,8 +7,8 @@ namespace SharpChat.Packet { private readonly long Timestamp; public UserUpdateNotificationPacket(string previousName, string newName) { - PreviousName = previousName ?? throw new ArgumentNullException(nameof(previousName)); - NewName = newName ?? throw new ArgumentNullException(nameof(newName)); + PreviousName = previousName; + NewName = newName; Timestamp = DateTimeOffset.Now.ToUnixTimeSeconds(); } diff --git a/SharpChat/Packet/UserUpdatePacket.cs b/SharpChat/Packet/UserUpdatePacket.cs index f6a8226..ddd2936 100644 --- a/SharpChat/Packet/UserUpdatePacket.cs +++ b/SharpChat/Packet/UserUpdatePacket.cs @@ -16,7 +16,7 @@ namespace SharpChat.Packet { ChatUserPermissions userPerms ) { UserId = userId; - UserName = userName ?? throw new ArgumentNullException(nameof(userName)); + UserName = userName; UserColour = userColour; UserRank = userRank; UserPerms = userPerms; diff --git a/SharpChat/Packet/UsersPopulatePacket.cs b/SharpChat/Packet/UsersPopulatePacket.cs index 5c0b1a9..57d1af9 100644 --- a/SharpChat/Packet/UsersPopulatePacket.cs +++ b/SharpChat/Packet/UsersPopulatePacket.cs @@ -8,7 +8,7 @@ namespace SharpChat.Packet { private readonly ListEntry[] Entries; public UsersPopulatePacket(ListEntry[] entries) { - Entries = entries ?? throw new ArgumentNullException(nameof(entries)); + Entries = entries; } public override string Pack() { diff --git a/SharpChat/PacketHandlers/AuthHandler.cs b/SharpChat/PacketHandlers/AuthHandler.cs index e6e5016..999c307 100644 --- a/SharpChat/PacketHandlers/AuthHandler.cs +++ b/SharpChat/PacketHandlers/AuthHandler.cs @@ -20,10 +20,10 @@ namespace SharpChat.PacketHandlers { CachedValue<int> maxMsgLength, CachedValue<int> maxConns ) { - Misuzu = msz ?? throw new ArgumentNullException(nameof(msz)); - DefaultChannel = defaultChannel ?? throw new ArgumentNullException(nameof(defaultChannel)); - MaxMessageLength = maxMsgLength ?? throw new ArgumentNullException(nameof(maxMsgLength)); - MaxConnections = maxConns ?? throw new ArgumentNullException(nameof(maxConns)); + Misuzu = msz; + DefaultChannel = defaultChannel; + MaxMessageLength = maxMsgLength; + MaxConnections = maxConns; } public bool IsMatch(ChatPacketHandlerContext ctx) { @@ -114,12 +114,12 @@ namespace SharpChat.PacketHandlers { await ctx.Chat.ContextAccess.WaitAsync(); try { - ChatUser? user = ctx.Chat.Users.FirstOrDefault(u => u.UserId == fai.UserId); + ChatUser? user = ctx.Chat.Users.Values.FirstOrDefault(u => u.UserId == fai.UserId); if(user == null) user = new ChatUser( fai.UserId, - fai.UserName, + fai.UserName ?? string.Empty, fai.Colour, fai.Rank, fai.Permissions, diff --git a/SharpChat/PacketHandlers/PingHandler.cs b/SharpChat/PacketHandlers/PingHandler.cs index 87d04c9..a33bf8b 100644 --- a/SharpChat/PacketHandlers/PingHandler.cs +++ b/SharpChat/PacketHandlers/PingHandler.cs @@ -12,7 +12,7 @@ namespace SharpChat.PacketHandlers { private DateTimeOffset LastBump = DateTimeOffset.MinValue; public PingHandler(MisuzuClient msz) { - Misuzu = msz ?? throw new ArgumentNullException(nameof(msz)); + Misuzu = msz; } public bool IsMatch(ChatPacketHandlerContext ctx) { @@ -31,7 +31,7 @@ namespace SharpChat.PacketHandlers { ctx.Chat.ContextAccess.Wait(); try { if(LastBump < DateTimeOffset.UtcNow - BumpInterval) { - (string, string)[] bumpList = ctx.Chat.Users + (string, string)[] bumpList = ctx.Chat.Users.Values .Where(u => u.Status == ChatUserStatus.Online && ctx.Chat.Connections.Any(c => c.User == u)) .Select(u => (u.UserId.ToString(), ctx.Chat.GetRemoteAddresses(u).FirstOrDefault()?.ToString() ?? string.Empty)) .ToArray(); diff --git a/SharpChat/PacketHandlers/SendMessageHandler.cs b/SharpChat/PacketHandlers/SendMessageHandler.cs index 785e2fc..90668e0 100644 --- a/SharpChat/PacketHandlers/SendMessageHandler.cs +++ b/SharpChat/PacketHandlers/SendMessageHandler.cs @@ -15,15 +15,15 @@ namespace SharpChat.PacketHandlers private List<IChatCommand> Commands { get; } = new(); public SendMessageHandler(CachedValue<int> maxMsgLength) { - MaxMessageLength = maxMsgLength ?? throw new ArgumentNullException(nameof(maxMsgLength)); + MaxMessageLength = maxMsgLength; } public void AddCommand(IChatCommand command) { - Commands.Add(command ?? throw new ArgumentNullException(nameof(command))); + Commands.Add(command); } public void AddCommands(IEnumerable<IChatCommand> commands) { - Commands.AddRange(commands ?? throw new ArgumentNullException(nameof(commands))); + Commands.AddRange(commands); } public bool IsMatch(ChatPacketHandlerContext ctx) { diff --git a/SharpChat/SockChatServer.cs b/SharpChat/SockChatServer.cs index bbf640e..24e5709 100644 --- a/SharpChat/SockChatServer.cs +++ b/SharpChat/SockChatServer.cs @@ -41,8 +41,8 @@ namespace SharpChat { public SockChatServer(HttpClient httpClient, MisuzuClient msz, IEventStorage evtStore, IConfig config) { Logger.Write("Initialising Sock Chat server..."); - HttpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient)); - Misuzu = msz ?? throw new ArgumentNullException(nameof(msz)); + HttpClient = httpClient; + Misuzu = msz; MaxMessageLength = config.ReadCached("msgMaxLength", DEFAULT_MSG_LENGTH_MAX); MaxConnections = config.ReadCached("connMaxCount", DEFAULT_MAX_CONNECTIONS); @@ -67,13 +67,13 @@ namespace SharpChat { rank: channelCfg.SafeReadValue("minRank", 0) ); - Context.Channels.Add(channelInfo); + Context.Channels.Add(channelInfo.Name, channelInfo); DefaultChannel ??= channelInfo; } DefaultChannel ??= new ChatChannel("Default"); - if(!Context.Channels.Any()) - Context.Channels.Add(DefaultChannel); + if(Context.Channels.Count < 1) + Context.Channels.Add(DefaultChannel.Name, DefaultChannel); GuestHandlers.Add(new AuthHandler(Misuzu, DefaultChannel, MaxMessageLength, MaxConnections));