diff --git a/SharpChat/ChatChannel.cs b/SharpChat/ChatChannel.cs index 3d1b7e9..c27a046 100644 --- a/SharpChat/ChatChannel.cs +++ b/SharpChat/ChatChannel.cs @@ -15,14 +15,14 @@ namespace SharpChat { public ChatChannel( ChatUser owner, string name, - string password = null, + string? password = null, bool isTemporary = false, int rank = 0 ) : this(name, password, isTemporary, rank, owner?.UserId ?? 0) {} public ChatChannel( string name, - string password = null, + string? password = null, bool isTemporary = false, int rank = 0, long ownerId = 0 @@ -34,7 +34,7 @@ namespace SharpChat { OwnerId = ownerId; } - public bool NameEquals(string name) { + public bool NameEquals(string? name) { return string.Equals(name, Name, StringComparison.InvariantCultureIgnoreCase); } diff --git a/SharpChat/ChatColour.cs b/SharpChat/ChatColour.cs index 4856083..75b429a 100644 --- a/SharpChat/ChatColour.cs +++ b/SharpChat/ChatColour.cs @@ -1,6 +1,4 @@ -using System.Diagnostics.CodeAnalysis; - -namespace SharpChat { +namespace SharpChat { public readonly struct ChatColour { public readonly byte Red; public readonly byte Green; @@ -23,7 +21,7 @@ namespace SharpChat { Inherits = false; } - public override bool Equals([NotNullWhen(true)] object obj) { + public override bool Equals(object? obj) { return obj is ChatColour colour && Equals(colour); } diff --git a/SharpChat/ChatConnection.cs b/SharpChat/ChatConnection.cs index 7ea9e3f..aadf074 100644 --- a/SharpChat/ChatConnection.cs +++ b/SharpChat/ChatConnection.cs @@ -17,7 +17,7 @@ namespace SharpChat { public string Id { get; } public bool IsDisposed { get; private set; } public DateTimeOffset LastPing { get; set; } = DateTimeOffset.Now; - public ChatUser User { get; set; } + public ChatUser? User { get; set; } private int CloseCode { get; set; } = 1000; @@ -32,12 +32,12 @@ namespace SharpChat { Socket = sock; Id = RNG.SecureRandomString(ID_LENGTH); - if(!IPAddress.TryParse(sock.ConnectionInfo.ClientIpAddress, out IPAddress addr)) + if(!IPAddress.TryParse(sock.ConnectionInfo.ClientIpAddress, out IPAddress? addr)) throw new Exception("Unable to parse remote address?????"); if(IPAddress.IsLoopback(addr) && sock.ConnectionInfo.Headers.ContainsKey("X-Real-IP") - && IPAddress.TryParse(sock.ConnectionInfo.Headers["X-Real-IP"], out IPAddress realAddr)) + && IPAddress.TryParse(sock.ConnectionInfo.Headers["X-Real-IP"], out IPAddress? realAddr)) addr = realAddr; RemoteAddress = addr; diff --git a/SharpChat/ChatContext.cs b/SharpChat/ChatContext.cs index 9a87a08..eb2852a 100644 --- a/SharpChat/ChatContext.cs +++ b/SharpChat/ChatContext.cs @@ -34,7 +34,7 @@ namespace SharpChat { // e.g. nook sees @Arysil and Arysil sees @nook // this entire routine is garbage, channels should probably in the db - if(!mce.ChannelName.StartsWith("@")) + if(mce.ChannelName?.StartsWith("@") != true) return; IEnumerable uids = mce.ChannelName[1..].Split('-', 3).Select(u => long.TryParse(u, out long up) ? up : -1); @@ -42,7 +42,7 @@ namespace SharpChat { return; IEnumerable users = Users.Where(u => uids.Any(uid => uid == u.UserId)); - ChatUser target = users.FirstOrDefault(u => u.UserId != mce.SenderId); + ChatUser? target = users.FirstOrDefault(u => u.UserId != mce.SenderId); if(target == null) return; @@ -56,15 +56,16 @@ namespace SharpChat { true )); } else { - ChatChannel channel = Channels.FirstOrDefault(c => c.NameEquals(mce.ChannelName)); - SendTo(channel, new ChatMessageAddPacket( - mce.MessageId, - DateTimeOffset.Now, - mce.SenderId, - mce.MessageText, - mce.IsAction, - false - )); + ChatChannel? channel = Channels.FirstOrDefault(c => c.NameEquals(mce.ChannelName)); + if(channel != null) + SendTo(channel, new ChatMessageAddPacket( + mce.MessageId, + DateTimeOffset.Now, + mce.SenderId, + mce.MessageText, + mce.IsAction, + false + )); } Events.AddEvent( @@ -105,8 +106,10 @@ namespace SharpChat { } } - public bool IsInChannel(ChatUser user, ChatChannel channel) { - return ChannelUsers.Contains(new ChannelUserAssoc(user.UserId, channel.Name)); + public bool IsInChannel(ChatUser? user, ChatChannel? channel) { + return user != null + && channel != null + && ChannelUsers.Contains(new ChannelUserAssoc(user.UserId, channel.Name)); } public string[] GetUserChannelNames(ChatUser user) { @@ -129,11 +132,11 @@ namespace SharpChat { public void UpdateUser( ChatUser user, - string userName = null, - string nickName = null, + string? userName = null, + string? nickName = null, ChatColour? colour = null, ChatUserStatus? status = null, - string statusText = null, + string? statusText = null, int? rank = null, ChatUserPermissions? perms = null, bool? isSuper = null, @@ -143,7 +146,7 @@ namespace SharpChat { throw new ArgumentNullException(nameof(user)); bool hasChanged = false; - string previousName = null; + string? previousName = null; if(userName != null && !user.UserName.Equals(userName)) { user.UserName = userName; @@ -275,7 +278,7 @@ namespace SharpChat { } public void SwitchChannel(ChatUser user, ChatChannel chan, string password) { - if(UserLastChannel.TryGetValue(user.UserId, out ChatChannel ulc) && chan == ulc) { + if(UserLastChannel.TryGetValue(user.UserId, out ChatChannel? ulc) && chan == ulc) { ForceChannel(user); return; } @@ -365,7 +368,7 @@ namespace SharpChat { throw new ArgumentNullException(nameof(packet)); IEnumerable chans = Channels.Where(c => IsInChannel(user, c)); - IEnumerable conns = Connections.Where(conn => conn.IsAuthed && ChannelUsers.Any(cu => cu.UserId == conn.User.UserId && chans.Any(chan => chan.NameEquals(cu.ChannelName)))); + IEnumerable 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); } @@ -374,7 +377,7 @@ namespace SharpChat { return Connections.Where(c => c.IsAlive && c.User == user).Select(c => c.RemoteAddress).Distinct().ToArray(); } - public void ForceChannel(ChatUser user, ChatChannel chan = null) { + public void ForceChannel(ChatUser user, ChatChannel? chan = null) { if(user == null) throw new ArgumentNullException(nameof(user)); @@ -384,7 +387,12 @@ namespace SharpChat { SendTo(user, new UserChannelForceJoinPacket(chan.Name)); } - public void UpdateChannel(ChatChannel channel, bool? temporary = null, int? minRank = null, string password = null) { + public void UpdateChannel( + ChatChannel channel, + bool? temporary = null, + int? minRank = null, + string? password = null + ) { if(channel == null) throw new ArgumentNullException(nameof(channel)); if(!Channels.Contains(channel)) @@ -411,7 +419,7 @@ namespace SharpChat { if(channel == null || !Channels.Any()) return; - ChatChannel defaultChannel = Channels.FirstOrDefault(); + ChatChannel? defaultChannel = Channels.FirstOrDefault(); if(defaultChannel == null) return; diff --git a/SharpChat/ChatUser.cs b/SharpChat/ChatUser.cs index 64cc24b..57e7071 100644 --- a/SharpChat/ChatUser.cs +++ b/SharpChat/ChatUser.cs @@ -34,13 +34,13 @@ namespace SharpChat { public ChatUser( long userId, - string userName, + string? userName, ChatColour colour, int rank, ChatUserPermissions perms, - string nickName = null, + string? nickName = null, ChatUserStatus status = ChatUserStatus.Online, - string statusText = null, + string? statusText = null, bool isSuper = false ) { UserId = userId; @@ -59,7 +59,7 @@ namespace SharpChat { return strict ? perms == perm : perms > 0; } - public bool NameEquals(string name) { + public bool NameEquals(string? name) { return string.Equals(name, UserName, StringComparison.InvariantCultureIgnoreCase) || string.Equals(name, NickName, StringComparison.InvariantCultureIgnoreCase) || string.Equals(name, LegacyName, StringComparison.InvariantCultureIgnoreCase) @@ -70,11 +70,11 @@ namespace SharpChat { return UserId.GetHashCode(); } - public override bool Equals(object obj) { + public override bool Equals(object? obj) { return Equals(obj as ChatUser); } - public bool Equals(ChatUser other) { + public bool Equals(ChatUser? other) { return UserId == other?.UserId; } diff --git a/SharpChat/Commands/AFKCommand.cs b/SharpChat/Commands/AFKCommand.cs index a5cce48..a7383fd 100644 --- a/SharpChat/Commands/AFKCommand.cs +++ b/SharpChat/Commands/AFKCommand.cs @@ -11,7 +11,7 @@ namespace SharpChat.Commands { } public void Dispatch(ChatCommandContext ctx) { - string statusText = ctx.Args.FirstOrDefault(); + string? statusText = ctx.Args.FirstOrDefault(); if(string.IsNullOrWhiteSpace(statusText)) statusText = DEFAULT; else { diff --git a/SharpChat/Commands/BanListCommand.cs b/SharpChat/Commands/BanListCommand.cs index 144fba0..a986d2c 100644 --- a/SharpChat/Commands/BanListCommand.cs +++ b/SharpChat/Commands/BanListCommand.cs @@ -25,8 +25,8 @@ namespace SharpChat.Commands { Task.Run(async () => { ctx.Chat.SendTo(ctx.User, new BanListPacket( - (await Misuzu.GetBanListAsync()).Select( - ban => string.IsNullOrEmpty(ban.UserName) ? ban.RemoteAddress : ban.UserName + (await Misuzu.GetBanListAsync() ?? Array.Empty()).Select( + ban => string.IsNullOrEmpty(ban.UserName) ? (string.IsNullOrEmpty(ban.RemoteAddress) ? string.Empty : ban.RemoteAddress) : ban.UserName ).ToArray() )); }).Wait(); diff --git a/SharpChat/Commands/DeleteChannelCommand.cs b/SharpChat/Commands/DeleteChannelCommand.cs index 78f2248..f9e024b 100644 --- a/SharpChat/Commands/DeleteChannelCommand.cs +++ b/SharpChat/Commands/DeleteChannelCommand.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.FirstOrDefault(c => c.NameEquals(delChanName)); if(delChan == null) { ctx.Chat.SendTo(ctx.User, new LegacyCommandResponse(LCR.CHANNEL_NOT_FOUND, true, delChanName)); diff --git a/SharpChat/Commands/DeleteMessageCommand.cs b/SharpChat/Commands/DeleteMessageCommand.cs index 711b758..a85e12f 100644 --- a/SharpChat/Commands/DeleteMessageCommand.cs +++ b/SharpChat/Commands/DeleteMessageCommand.cs @@ -20,16 +20,16 @@ namespace SharpChat.Commands return; } - string firstArg = ctx.Args.FirstOrDefault(); + string? firstArg = ctx.Args.FirstOrDefault(); if(string.IsNullOrWhiteSpace(firstArg) || !firstArg.All(char.IsDigit) || !long.TryParse(firstArg, out long delSeqId)) { ctx.Chat.SendTo(ctx.User, new LegacyCommandResponse(LCR.COMMAND_FORMAT_ERROR)); return; } - StoredEventInfo delMsg = ctx.Chat.Events.GetEvent(delSeqId); + StoredEventInfo? delMsg = ctx.Chat.Events.GetEvent(delSeqId); - if(delMsg == null || delMsg.Sender.Rank > ctx.User.Rank || (!deleteAnyMessage && delMsg.Sender.UserId != ctx.User.UserId)) { + if(delMsg == null || delMsg.Sender?.Rank > ctx.User.Rank || (!deleteAnyMessage && delMsg.Sender?.UserId != ctx.User.UserId)) { ctx.Chat.SendTo(ctx.User, new LegacyCommandResponse(LCR.MESSAGE_DELETE_ERROR)); return; } diff --git a/SharpChat/Commands/JoinChannelCommand.cs b/SharpChat/Commands/JoinChannelCommand.cs index 0e20dfe..8c00c6e 100644 --- a/SharpChat/Commands/JoinChannelCommand.cs +++ b/SharpChat/Commands/JoinChannelCommand.cs @@ -8,11 +8,11 @@ namespace SharpChat.Commands { } public void Dispatch(ChatCommandContext ctx) { - string joinChanStr = ctx.Args.FirstOrDefault(); - ChatChannel joinChan = ctx.Chat.Channels.FirstOrDefault(c => c.NameEquals(joinChanStr)); + string? joinChanStr = ctx.Args.FirstOrDefault(); + ChatChannel? joinChan = ctx.Chat.Channels.FirstOrDefault(c => c.NameEquals(joinChanStr)); if(joinChan == null) { - ctx.Chat.SendTo(ctx.User, new LegacyCommandResponse(LCR.CHANNEL_NOT_FOUND, true, joinChanStr)); + ctx.Chat.SendTo(ctx.User, new LegacyCommandResponse(LCR.CHANNEL_NOT_FOUND, true, joinChanStr ?? string.Empty)); ctx.Chat.ForceChannel(ctx.User); return; } diff --git a/SharpChat/Commands/KickBanCommand.cs b/SharpChat/Commands/KickBanCommand.cs index a307051..acde202 100644 --- a/SharpChat/Commands/KickBanCommand.cs +++ b/SharpChat/Commands/KickBanCommand.cs @@ -25,13 +25,13 @@ namespace SharpChat.Commands { return; } - string banUserTarget = ctx.Args.ElementAtOrDefault(0); - string banDurationStr = ctx.Args.ElementAtOrDefault(1); + string? banUserTarget = ctx.Args.ElementAtOrDefault(0); + string? banDurationStr = ctx.Args.ElementAtOrDefault(1); int banReasonIndex = 1; - ChatUser banUser = null; + ChatUser? banUser = null; if(banUserTarget == null || (banUser = ctx.Chat.Users.FirstOrDefault(u => u.NameEquals(banUserTarget))) == null) { - ctx.Chat.SendTo(ctx.User, new LegacyCommandResponse(LCR.USER_NOT_FOUND, true, banUser == null ? "User" : banUserTarget)); + ctx.Chat.SendTo(ctx.User, new LegacyCommandResponse(LCR.USER_NOT_FOUND, true, banUserTarget ?? string.Empty)); return; } @@ -63,9 +63,9 @@ namespace SharpChat.Commands { string userIp = ctx.Chat.GetRemoteAddresses(banUser).FirstOrDefault()?.ToString() ?? string.Empty; // obviously it makes no sense to only check for one ip address but that's current misuzu limitations - MisuzuBanInfo fbi = await Misuzu.CheckBanAsync(userId, userIp); + MisuzuBanInfo? fbi = await Misuzu.CheckBanAsync(userId, userIp); - if(fbi.IsBanned && !fbi.HasExpired) { + if(fbi != null && fbi.IsBanned && !fbi.HasExpired) { ctx.Chat.SendTo(ctx.User, new LegacyCommandResponse(LCR.KICK_NOT_ALLOWED, true, banUser.LegacyName)); return; } diff --git a/SharpChat/Commands/NickCommand.cs b/SharpChat/Commands/NickCommand.cs index 5cabba7..f9e61bd 100644 --- a/SharpChat/Commands/NickCommand.cs +++ b/SharpChat/Commands/NickCommand.cs @@ -14,7 +14,8 @@ namespace SharpChat.Commands { ctx.Chat.SendTo(ctx.User, new LegacyCommandResponse(LCR.COMMAND_NOT_ALLOWED, true, $"/{ctx.Name}")); return; } - ChatUser targetUser = null; + + ChatUser? targetUser = null; int offset = 0; if(setOthersNick && long.TryParse(ctx.Args.FirstOrDefault(), out long targetUserId) && targetUserId > 0) { @@ -46,7 +47,7 @@ namespace SharpChat.Commands { return; } - string previousName = targetUser == ctx.User ? (targetUser.NickName ?? targetUser.UserName) : null; + string? previousName = targetUser == ctx.User ? (targetUser.NickName ?? targetUser.UserName) : null; ctx.Chat.UpdateUser(targetUser, nickName: nickStr, silent: previousName == null); } } diff --git a/SharpChat/Commands/PardonAddressCommand.cs b/SharpChat/Commands/PardonAddressCommand.cs index 55a8860..4acb5f2 100644 --- a/SharpChat/Commands/PardonAddressCommand.cs +++ b/SharpChat/Commands/PardonAddressCommand.cs @@ -24,8 +24,8 @@ namespace SharpChat.Commands { return; } - string unbanAddrTarget = ctx.Args.FirstOrDefault(); - if(string.IsNullOrWhiteSpace(unbanAddrTarget) || !IPAddress.TryParse(unbanAddrTarget, out IPAddress unbanAddr)) { + string? unbanAddrTarget = ctx.Args.FirstOrDefault(); + if(string.IsNullOrWhiteSpace(unbanAddrTarget) || !IPAddress.TryParse(unbanAddrTarget, out IPAddress? unbanAddr)) { ctx.Chat.SendTo(ctx.User, new LegacyCommandResponse(LCR.COMMAND_FORMAT_ERROR)); return; } @@ -33,9 +33,9 @@ namespace SharpChat.Commands { unbanAddrTarget = unbanAddr.ToString(); Task.Run(async () => { - MisuzuBanInfo banInfo = await Misuzu.CheckBanAsync(ipAddr: unbanAddrTarget); + MisuzuBanInfo? banInfo = await Misuzu.CheckBanAsync(ipAddr: unbanAddrTarget); - if(!banInfo.IsBanned || banInfo.HasExpired) { + if(banInfo?.IsBanned != true || banInfo.HasExpired) { ctx.Chat.SendTo(ctx.User, new LegacyCommandResponse(LCR.USER_NOT_BANNED, true, unbanAddrTarget)); return; } diff --git a/SharpChat/Commands/PardonUserCommand.cs b/SharpChat/Commands/PardonUserCommand.cs index 80ccbfa..3adeaca 100644 --- a/SharpChat/Commands/PardonUserCommand.cs +++ b/SharpChat/Commands/PardonUserCommand.cs @@ -24,13 +24,13 @@ namespace SharpChat.Commands { } bool unbanUserTargetIsName = true; - string unbanUserTarget = ctx.Args.FirstOrDefault(); + string? unbanUserTarget = ctx.Args.FirstOrDefault(); if(string.IsNullOrWhiteSpace(unbanUserTarget)) { ctx.Chat.SendTo(ctx.User, new LegacyCommandResponse(LCR.COMMAND_FORMAT_ERROR)); return; } - ChatUser unbanUser = ctx.Chat.Users.FirstOrDefault(u => u.NameEquals(unbanUserTarget)); + ChatUser? unbanUser = ctx.Chat.Users.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); @@ -40,9 +40,9 @@ namespace SharpChat.Commands { unbanUserTarget = unbanUser.UserId.ToString(); Task.Run(async () => { - MisuzuBanInfo banInfo = await Misuzu.CheckBanAsync(unbanUserTarget, userIdIsName: unbanUserTargetIsName); + MisuzuBanInfo? banInfo = await Misuzu.CheckBanAsync(unbanUserTarget, userIdIsName: unbanUserTargetIsName); - if(!banInfo.IsBanned || banInfo.HasExpired) { + if(banInfo?.IsBanned != true || banInfo.HasExpired) { ctx.Chat.SendTo(ctx.User, new LegacyCommandResponse(LCR.USER_NOT_BANNED, true, unbanUserTarget)); return; } diff --git a/SharpChat/Commands/RemoteAddressCommand.cs b/SharpChat/Commands/RemoteAddressCommand.cs index 1fc4b5a..b579c5b 100644 --- a/SharpChat/Commands/RemoteAddressCommand.cs +++ b/SharpChat/Commands/RemoteAddressCommand.cs @@ -15,11 +15,11 @@ namespace SharpChat.Commands { return; } - string ipUserStr = ctx.Args.FirstOrDefault(); - ChatUser ipUser; + string? ipUserStr = ctx.Args.FirstOrDefault(); + ChatUser? ipUser; if(string.IsNullOrWhiteSpace(ipUserStr) || (ipUser = ctx.Chat.Users.FirstOrDefault(u => u.NameEquals(ipUserStr))) == null) { - ctx.Chat.SendTo(ctx.User, new LegacyCommandResponse(LCR.USER_NOT_FOUND, true, ipUserStr ?? "User")); + ctx.Chat.SendTo(ctx.User, new LegacyCommandResponse(LCR.USER_NOT_FOUND, true, ipUserStr ?? string.Empty)); return; } diff --git a/SharpChat/Commands/WhisperCommand.cs b/SharpChat/Commands/WhisperCommand.cs index 3daa0de..3117e64 100644 --- a/SharpChat/Commands/WhisperCommand.cs +++ b/SharpChat/Commands/WhisperCommand.cs @@ -16,11 +16,11 @@ namespace SharpChat.Commands { return; } - string whisperUserStr = ctx.Args.FirstOrDefault(); - ChatUser whisperUser = ctx.Chat.Users.FirstOrDefault(u => u.NameEquals(whisperUserStr)); + string? whisperUserStr = ctx.Args.FirstOrDefault(); + ChatUser? whisperUser = ctx.Chat.Users.FirstOrDefault(u => u.NameEquals(whisperUserStr)); if(whisperUser == null) { - ctx.Chat.SendTo(ctx.User, new LegacyCommandResponse(LCR.USER_NOT_FOUND, true, whisperUserStr)); + ctx.Chat.SendTo(ctx.User, new LegacyCommandResponse(LCR.USER_NOT_FOUND, true, whisperUserStr ?? string.Empty)); return; } diff --git a/SharpChat/Commands/WhoCommand.cs b/SharpChat/Commands/WhoCommand.cs index 76ab685..3113609 100644 --- a/SharpChat/Commands/WhoCommand.cs +++ b/SharpChat/Commands/WhoCommand.cs @@ -10,7 +10,7 @@ namespace SharpChat.Commands { public void Dispatch(ChatCommandContext ctx) { StringBuilder whoChanSB = new(); - string whoChanStr = ctx.Args.FirstOrDefault(); + string? whoChanStr = ctx.Args.FirstOrDefault(); if(string.IsNullOrEmpty(whoChanStr)) { foreach(ChatUser whoUser in ctx.Chat.Users) { @@ -19,9 +19,7 @@ namespace SharpChat.Commands { if(whoUser == ctx.User) whoChanSB.Append(@" style=""font-weight: bold;"""); - whoChanSB.Append('>'); - whoChanSB.Append(whoUser.LegacyName); - whoChanSB.Append(", "); + whoChanSB.AppendFormat(@">{0}, ", whoUser.LegacyName); } if(whoChanSB.Length > 2) @@ -29,7 +27,7 @@ namespace SharpChat.Commands { ctx.Chat.SendTo(ctx.User, new LegacyCommandResponse(LCR.USERS_LISTING_SERVER, false, whoChanSB)); } else { - ChatChannel whoChan = ctx.Chat.Channels.FirstOrDefault(c => c.NameEquals(whoChanStr)); + ChatChannel? whoChan = ctx.Chat.Channels.FirstOrDefault(c => c.NameEquals(whoChanStr)); if(whoChan == null) { ctx.Chat.SendTo(ctx.User, new LegacyCommandResponse(LCR.CHANNEL_NOT_FOUND, true, whoChanStr)); @@ -47,9 +45,7 @@ namespace SharpChat.Commands { if(whoUser == ctx.User) whoChanSB.Append(@" style=""font-weight: bold;"""); - whoChanSB.Append('>'); - whoChanSB.Append(whoUser.LegacyName); - whoChanSB.Append(", "); + whoChanSB.AppendFormat(@">{0}, ", whoUser.LegacyName); } if(whoChanSB.Length > 2) diff --git a/SharpChat/Config/CachedValue.cs b/SharpChat/Config/CachedValue.cs index 828c4a6..64adc96 100644 --- a/SharpChat/Config/CachedValue.cs +++ b/SharpChat/Config/CachedValue.cs @@ -5,13 +5,13 @@ namespace SharpChat.Config { private IConfig Config { get; } private string Name { get; } private TimeSpan Lifetime { get; } - private T Fallback { get; } + private T? Fallback { get; } private object ConfigAccess { get; } = new(); - private object CurrentValue { get; set; } + private object? CurrentValue { get; set; } private DateTimeOffset LastRead { get; set; } - public T Value { + public T? Value { get { lock(ConfigAccess) { // this lock doesn't really make sense since it doesn't affect other config calls DateTimeOffset now = DateTimeOffset.Now; @@ -21,13 +21,13 @@ namespace SharpChat.Config { Logger.Debug($"Read {Name} ({CurrentValue})"); } } - return (T)CurrentValue; + return (T?)CurrentValue; } } - public static implicit operator T(CachedValue val) => val.Value; + public static implicit operator T?(CachedValue val) => val.Value; - public CachedValue(IConfig config, string name, TimeSpan lifetime, T fallback) { + 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; @@ -41,7 +41,7 @@ namespace SharpChat.Config { } public override string ToString() { - return Value.ToString(); + return Value?.ToString() ?? string.Empty; } } } diff --git a/SharpChat/Config/IConfig.cs b/SharpChat/Config/IConfig.cs index 4c27514..5625389 100644 --- a/SharpChat/Config/IConfig.cs +++ b/SharpChat/Config/IConfig.cs @@ -14,22 +14,22 @@ namespace SharpChat.Config { /// /// Reads a raw (string) value from the config. /// - string ReadValue(string name, string fallback = null); + string? ReadValue(string name, string? fallback = null); /// /// Reads and casts value from the config. /// /// Type conversion failed. - T ReadValue(string name, T fallback = default); + T? ReadValue(string name, T? fallback = default); /// /// Reads and casts a value from the config. Returns fallback when type conversion fails. /// - T SafeReadValue(string name, T fallback); + T? SafeReadValue(string name, T fallback); /// /// Creates an object that caches the read value for a certain amount of time, avoiding disk reads for frequently used non-static values. /// - CachedValue ReadCached(string name, T fallback = default, TimeSpan? lifetime = null); + CachedValue ReadCached(string name, T? fallback = default, TimeSpan? lifetime = null); } } diff --git a/SharpChat/Config/ScopedConfig.cs b/SharpChat/Config/ScopedConfig.cs index 912d074..7cc5a53 100644 --- a/SharpChat/Config/ScopedConfig.cs +++ b/SharpChat/Config/ScopedConfig.cs @@ -18,15 +18,15 @@ namespace SharpChat.Config { return Prefix + name; } - public string ReadValue(string name, string fallback = null) { + public string? ReadValue(string name, string? fallback = null) { return Config.ReadValue(GetName(name), fallback); } - public T ReadValue(string name, T fallback = default) { + public T? ReadValue(string name, T? fallback = default) { return Config.ReadValue(GetName(name), fallback); } - public T SafeReadValue(string name, T fallback) { + public T? SafeReadValue(string name, T fallback) { return Config.SafeReadValue(GetName(name), fallback); } @@ -34,7 +34,7 @@ namespace SharpChat.Config { return Config.ScopeTo(GetName(prefix)); } - public CachedValue ReadCached(string name, T fallback = default, TimeSpan? lifetime = null) { + public CachedValue ReadCached(string name, T? fallback = default, TimeSpan? lifetime = null) { return Config.ReadCached(GetName(name), fallback, lifetime); } diff --git a/SharpChat/Config/StreamConfig.cs b/SharpChat/Config/StreamConfig.cs index 5192def..653f302 100644 --- a/SharpChat/Config/StreamConfig.cs +++ b/SharpChat/Config/StreamConfig.cs @@ -26,14 +26,14 @@ namespace SharpChat.Config { Lock = new Mutex(); } - public string ReadValue(string name, string fallback = null) { + public string? ReadValue(string name, string? fallback = null) { if(!Lock.WaitOne(LOCK_TIMEOUT)) // don't catch this, if this happens something is Very Wrong throw new ConfigLockException(); try { Stream.Seek(0, SeekOrigin.Begin); - string line; + string? line; while((line = StreamReader.ReadLine()) != null) { if(string.IsNullOrWhiteSpace(line)) continue; @@ -55,8 +55,8 @@ namespace SharpChat.Config { return fallback; } - public T ReadValue(string name, T fallback = default) { - object value = ReadValue(name); + public T? ReadValue(string name, T? fallback = default) { + object? value = ReadValue(name); if(value == null) return fallback; @@ -76,7 +76,7 @@ namespace SharpChat.Config { } } - public T SafeReadValue(string name, T fallback) { + public T? SafeReadValue(string name, T fallback) { try { return ReadValue(name, fallback); } catch(ConfigTypeException) { @@ -88,7 +88,7 @@ namespace SharpChat.Config { return new ScopedConfig(this, prefix); } - public CachedValue ReadCached(string name, T fallback = default, TimeSpan? lifetime = null) { + public CachedValue ReadCached(string name, T? fallback = default, TimeSpan? lifetime = null) { return new CachedValue(this, name, lifetime ?? CACHE_LIFETIME, fallback); } diff --git a/SharpChat/EventStorage/IEventStorage.cs b/SharpChat/EventStorage/IEventStorage.cs index 0cac6e2..2f161b1 100644 --- a/SharpChat/EventStorage/IEventStorage.cs +++ b/SharpChat/EventStorage/IEventStorage.cs @@ -5,32 +5,32 @@ namespace SharpChat.EventStorage public interface IEventStorage { void AddEvent( long id, string type, - object data = null, + object? data = null, StoredEventFlags flags = StoredEventFlags.None ); void AddEvent( long id, string type, - string channelName, - object data = null, + string? channelName, + object? data = null, StoredEventFlags flags = StoredEventFlags.None ); void AddEvent( long id, string type, - long senderId, string senderName, ChatColour senderColour, int senderRank, string senderNick, ChatUserPermissions senderPerms, - object data = null, + long senderId, string? senderName, ChatColour senderColour, int senderRank, string? senderNick, ChatUserPermissions senderPerms, + object? data = null, StoredEventFlags flags = StoredEventFlags.None ); void AddEvent( long id, string type, - string channelName, - long senderId, string senderName, ChatColour senderColour, int senderRank, string senderNick, ChatUserPermissions senderPerms, - object data = null, + string? channelName, + long senderId, string? senderName, ChatColour senderColour, int senderRank, string? senderNick, ChatUserPermissions senderPerms, + object? data = null, StoredEventFlags flags = StoredEventFlags.None ); - long AddEvent(string type, ChatUser user, ChatChannel channel, object data = null, StoredEventFlags flags = StoredEventFlags.None); + long AddEvent(string type, ChatUser user, ChatChannel channel, object? data = null, StoredEventFlags flags = StoredEventFlags.None); void RemoveEvent(StoredEventInfo evt); - StoredEventInfo GetEvent(long seqId); + StoredEventInfo? GetEvent(long seqId); IEnumerable GetChannelEventLog(string channelName, int amount = 20, int offset = 0); } } diff --git a/SharpChat/EventStorage/MariaDBEventStorage.cs b/SharpChat/EventStorage/MariaDBEventStorage.cs index 2491595..c0e5bd1 100644 --- a/SharpChat/EventStorage/MariaDBEventStorage.cs +++ b/SharpChat/EventStorage/MariaDBEventStorage.cs @@ -17,7 +17,7 @@ namespace SharpChat.EventStorage public void AddEvent( long id, string type, - object data = null, + object? data = null, StoredEventFlags flags = StoredEventFlags.None ) { AddEvent(id, type, null, 0, null, ChatColour.None, 0, null, 0, data, flags); @@ -25,8 +25,8 @@ namespace SharpChat.EventStorage public void AddEvent( long id, string type, - string channelName, - object data = null, + string? channelName, + object? data = null, StoredEventFlags flags = StoredEventFlags.None ) { AddEvent(id, type, channelName, 0, null, ChatColour.None, 0, null, 0, data, flags); @@ -34,8 +34,8 @@ namespace SharpChat.EventStorage public void AddEvent( long id, string type, - long senderId, string senderName, ChatColour senderColour, int senderRank, string senderNick, ChatUserPermissions senderPerms, - object data = null, + long senderId, string? senderName, ChatColour senderColour, int senderRank, string? senderNick, ChatUserPermissions senderPerms, + object? data = null, StoredEventFlags flags = StoredEventFlags.None ) { AddEvent(id, type, null, senderId, senderName, senderColour, senderRank, senderNick, senderPerms, data, flags); @@ -43,9 +43,9 @@ namespace SharpChat.EventStorage public void AddEvent( long id, string type, - string channelName, - long senderId, string senderName, ChatColour senderColour, int senderRank, string senderNick, ChatUserPermissions senderPerms, - object data = null, + string? channelName, + long senderId, string? senderName, ChatColour senderColour, int senderRank, string? senderNick, ChatUserPermissions senderPerms, + object? data = null, StoredEventFlags flags = StoredEventFlags.None ) { if(type == null) @@ -70,7 +70,7 @@ namespace SharpChat.EventStorage ); } - public long AddEvent(string type, ChatUser user, ChatChannel channel, object data = null, StoredEventFlags flags = StoredEventFlags.None) { + public long AddEvent(string type, ChatUser user, ChatChannel channel, object? data = null, StoredEventFlags flags = StoredEventFlags.None) { if(type == null) throw new ArgumentNullException(nameof(type)); @@ -92,9 +92,9 @@ namespace SharpChat.EventStorage return id; } - public StoredEventInfo GetEvent(long seqId) { + public StoredEventInfo? GetEvent(long seqId) { try { - using MySqlDataReader reader = RunQuery( + using MySqlDataReader? reader = RunQuery( "SELECT `event_id`, `event_type`, `event_flags`, `event_data`, `event_target`" + ", `event_sender`, `event_sender_name`, `event_sender_colour`, `event_sender_rank`, `event_sender_nick`, `event_sender_perms`" + ", UNIX_TIMESTAMP(`event_created`) AS `event_created`" @@ -104,11 +104,12 @@ namespace SharpChat.EventStorage new MySqlParameter("id", seqId) ); - while(reader.Read()) { - StoredEventInfo evt = ReadEvent(reader); - if(evt != null) - return evt; - } + if(reader != null) + while(reader.Read()) { + StoredEventInfo evt = ReadEvent(reader); + if(evt != null) + return evt; + } } catch(MySqlException ex) { Logger.Write(ex); } @@ -140,7 +141,7 @@ namespace SharpChat.EventStorage List events = new(); try { - using MySqlDataReader reader = RunQuery( + using MySqlDataReader? reader = RunQuery( "SELECT `event_id`, `event_type`, `event_flags`, `event_data`, `event_target`" + ", `event_sender`, `event_sender_name`, `event_sender_colour`, `event_sender_rank`, `event_sender_nick`, `event_sender_perms`" + ", UNIX_TIMESTAMP(`event_created`) AS `event_created`" @@ -155,11 +156,12 @@ namespace SharpChat.EventStorage new MySqlParameter("offset", offset) ); - while(reader.Read()) { - StoredEventInfo evt = ReadEvent(reader); - if(evt != null) - events.Add(evt); - } + if(reader != null) + while(reader.Read()) { + StoredEventInfo evt = ReadEvent(reader); + if(evt != null) + events.Add(evt); + } } catch(MySqlException ex) { Logger.Write(ex); } diff --git a/SharpChat/EventStorage/MariaDBEventStorage_Database.cs b/SharpChat/EventStorage/MariaDBEventStorage_Database.cs index 35ded05..b0789bc 100644 --- a/SharpChat/EventStorage/MariaDBEventStorage_Database.cs +++ b/SharpChat/EventStorage/MariaDBEventStorage_Database.cs @@ -5,10 +5,10 @@ namespace SharpChat.EventStorage { public partial class MariaDBEventStorage { public static string BuildConnString(IConfig config) { return BuildConnString( - config.ReadValue("host", "localhost"), - config.ReadValue("user", string.Empty), - config.ReadValue("pass", string.Empty), - config.ReadValue("db", "sharpchat") + config.ReadValue("host", "localhost") ?? string.Empty, + config.ReadValue("user") ?? string.Empty, + config.ReadValue("pass") ?? string.Empty, + config.ReadValue("db", "sharpchat") ?? string.Empty ); } @@ -48,7 +48,7 @@ namespace SharpChat.EventStorage { return 0; } - private MySqlDataReader RunQuery(string command, params MySqlParameter[] parameters) { + private MySqlDataReader? RunQuery(string command, params MySqlParameter[] parameters) { try { MySqlConnection conn = GetConnection(); MySqlCommand cmd = conn.CreateCommand(); @@ -63,7 +63,7 @@ namespace SharpChat.EventStorage { return null; } - private object RunQueryValue(string command, params MySqlParameter[] parameters) { + private object? RunQueryValue(string command, params MySqlParameter[] parameters) { try { using MySqlConnection conn = GetConnection(); using MySqlCommand cmd = conn.CreateCommand(); diff --git a/SharpChat/EventStorage/MariaDBEventStorage_Migrations.cs b/SharpChat/EventStorage/MariaDBEventStorage_Migrations.cs index b5f95bd..f050b3b 100644 --- a/SharpChat/EventStorage/MariaDBEventStorage_Migrations.cs +++ b/SharpChat/EventStorage/MariaDBEventStorage_Migrations.cs @@ -4,7 +4,7 @@ using System; namespace SharpChat.EventStorage { public partial class MariaDBEventStorage { private void DoMigration(string name, Action action) { - bool done = (long)RunQueryValue( + bool done = (long?)RunQueryValue( "SELECT COUNT(*) FROM `sqc_migrations` WHERE `migration_name` = @name", new MySqlParameter("name", name) ) > 0; diff --git a/SharpChat/EventStorage/StoredEventInfo.cs b/SharpChat/EventStorage/StoredEventInfo.cs index f8a1756..966d319 100644 --- a/SharpChat/EventStorage/StoredEventInfo.cs +++ b/SharpChat/EventStorage/StoredEventInfo.cs @@ -5,20 +5,20 @@ namespace SharpChat.EventStorage { public class StoredEventInfo { public long Id { get; set; } public string Type { get; set; } - public ChatUser Sender { get; set; } + public ChatUser? Sender { get; set; } public DateTimeOffset Created { get; set; } public DateTimeOffset? Deleted { get; set; } - public string ChannelName { get; set; } + public string? ChannelName { get; set; } public StoredEventFlags Flags { get; set; } public JsonDocument Data { get; set; } public StoredEventInfo( long id, string type, - ChatUser sender, + ChatUser? sender, DateTimeOffset created, DateTimeOffset? deleted, - string channelName, + string? channelName, JsonDocument data, StoredEventFlags flags ) { diff --git a/SharpChat/EventStorage/VirtualEventStorage.cs b/SharpChat/EventStorage/VirtualEventStorage.cs index 8d312ea..c3b61cd 100644 --- a/SharpChat/EventStorage/VirtualEventStorage.cs +++ b/SharpChat/EventStorage/VirtualEventStorage.cs @@ -9,7 +9,7 @@ namespace SharpChat.EventStorage { public void AddEvent( long id, string type, - object data = null, + object? data = null, StoredEventFlags flags = StoredEventFlags.None ) { AddEvent(id, type, null, 0, null, ChatColour.None, 0, null, 0, data, flags); @@ -17,8 +17,8 @@ namespace SharpChat.EventStorage { public void AddEvent( long id, string type, - string channelName, - object data = null, + string? channelName, + object? data = null, StoredEventFlags flags = StoredEventFlags.None ) { AddEvent(id, type, channelName, 0, null, ChatColour.None, 0, null, 0, data, flags); @@ -26,8 +26,8 @@ namespace SharpChat.EventStorage { public void AddEvent( long id, string type, - long senderId, string senderName, ChatColour senderColour, int senderRank, string senderNick, ChatUserPermissions senderPerms, - object data = null, + long senderId, string? senderName, ChatColour senderColour, int senderRank, string? senderNick, ChatUserPermissions senderPerms, + object? data = null, StoredEventFlags flags = StoredEventFlags.None ) { AddEvent(id, type, null, senderId, senderName, senderColour, senderRank, senderNick, senderPerms, data, flags); @@ -35,9 +35,9 @@ namespace SharpChat.EventStorage { public void AddEvent( long id, string type, - string channelName, - long senderId, string senderName, ChatColour senderColour, int senderRank, string senderNick, ChatUserPermissions senderPerms, - object data = null, + string? channelName, + long senderId, string? senderName, ChatColour senderColour, int senderRank, string? senderNick, ChatUserPermissions senderPerms, + object? data = null, StoredEventFlags flags = StoredEventFlags.None ) { if(type == null) @@ -55,7 +55,7 @@ namespace SharpChat.EventStorage { ), DateTimeOffset.Now, null, channelName, hack, flags)); } - public long AddEvent(string type, ChatUser user, ChatChannel channel, object data = null, StoredEventFlags flags = StoredEventFlags.None) { + public long AddEvent(string type, ChatUser user, ChatChannel channel, object? data = null, StoredEventFlags flags = StoredEventFlags.None) { if(type == null) throw new ArgumentNullException(nameof(type)); @@ -77,13 +77,11 @@ namespace SharpChat.EventStorage { return id; } - public StoredEventInfo GetEvent(long seqId) { - return Events.TryGetValue(seqId, out StoredEventInfo evt) ? evt : null; + public StoredEventInfo? GetEvent(long seqId) { + return Events.TryGetValue(seqId, out StoredEventInfo? evt) ? evt : null; } public void RemoveEvent(StoredEventInfo evt) { - if(evt == null) - throw new ArgumentNullException(nameof(evt)); Events.Remove(evt.Id); } diff --git a/SharpChat/Events/MessageCreateEvent.cs b/SharpChat/Events/MessageCreateEvent.cs index 06fcb4f..6fab2a7 100644 --- a/SharpChat/Events/MessageCreateEvent.cs +++ b/SharpChat/Events/MessageCreateEvent.cs @@ -3,15 +3,14 @@ namespace SharpChat.Events { public class MessageCreateEvent : IChatEvent { public long MessageId { get; } - public string ChannelName { get; } + public string? ChannelName { get; } public long SenderId { get; } - public string SenderName { get; } + public string? SenderName { get; } public ChatColour SenderColour { get; } public int SenderRank { get; } - public string SenderNickName { get; } + public string? SenderNickName { get; } public ChatUserPermissions SenderPerms { get; } public DateTimeOffset MessageCreated { get; } - public string MessageChannel { get; } public string MessageText { get; } public bool IsPrivate { get; } public bool IsAction { get; } @@ -19,12 +18,12 @@ namespace SharpChat.Events { public MessageCreateEvent( long msgId, - string channelName, + string? channelName, long senderId, - string senderName, + string? senderName, ChatColour senderColour, int senderRank, - string senderNickName, + string? senderNickName, ChatUserPermissions senderPerms, DateTimeOffset msgCreated, string msgText, @@ -49,8 +48,8 @@ namespace SharpChat.Events { public MessageCreateEvent( long msgId, - string channelName, - ChatUser sender, + string? channelName, + ChatUser? sender, DateTimeOffset msgCreated, string msgText, bool isPrivate, diff --git a/SharpChat/Misuzu/MisuzuAuthInfo.cs b/SharpChat/Misuzu/MisuzuAuthInfo.cs index f2f0359..6be33f1 100644 --- a/SharpChat/Misuzu/MisuzuAuthInfo.cs +++ b/SharpChat/Misuzu/MisuzuAuthInfo.cs @@ -13,7 +13,7 @@ namespace SharpChat.Misuzu { public long UserId { get; set; } [JsonPropertyName("username")] - public string UserName { get; set; } + public string? UserName { get; set; } [JsonPropertyName("colour_raw")] public int ColourRaw { get; set; } diff --git a/SharpChat/Misuzu/MisuzuBanInfo.cs b/SharpChat/Misuzu/MisuzuBanInfo.cs index 45b2e8a..83dec5e 100644 --- a/SharpChat/Misuzu/MisuzuBanInfo.cs +++ b/SharpChat/Misuzu/MisuzuBanInfo.cs @@ -7,10 +7,10 @@ namespace SharpChat.Misuzu { public bool IsBanned { get; set; } [JsonPropertyName("user_id")] - public string UserId { get; set; } + public string? UserId { get; set; } [JsonPropertyName("ip_addr")] - public string RemoteAddress { get; set; } + public string? RemoteAddress { get; set; } [JsonPropertyName("is_perma")] public bool IsPermanent { get; set; } @@ -20,7 +20,7 @@ namespace SharpChat.Misuzu { // only populated in list request [JsonPropertyName("user_name")] - public string UserName { get; set; } + public string? UserName { get; set; } [JsonPropertyName("user_colour")] public int UserColourRaw { get; set; } diff --git a/SharpChat/Misuzu/MisuzuClient.cs b/SharpChat/Misuzu/MisuzuClient.cs index 8f564cd..5d1584a 100644 --- a/SharpChat/Misuzu/MisuzuClient.cs +++ b/SharpChat/Misuzu/MisuzuClient.cs @@ -47,11 +47,11 @@ namespace SharpChat.Misuzu { } public string CreateBufferSignature(byte[] bytes) { - using HMACSHA256 algo = new(Encoding.UTF8.GetBytes(SecretKey)); + using HMACSHA256 algo = new(Encoding.UTF8.GetBytes(SecretKey.Value ?? string.Empty)); return string.Concat(algo.ComputeHash(bytes).Select(c => c.ToString("x2"))); } - public async Task AuthVerifyAsync(string method, string token, string ipAddr) { + public async Task AuthVerifyAsync(string method, string token, string ipAddr) { method ??= string.Empty; token ??= string.Empty; ipAddr ??= string.Empty; @@ -114,7 +114,11 @@ namespace SharpChat.Misuzu { } } - public async Task CheckBanAsync(string userId = null, string ipAddr = null, bool userIdIsName = false) { + public async Task CheckBanAsync( + string? userId = null, + string? ipAddr = null, + bool userIdIsName = false + ) { userId ??= string.Empty; ipAddr ??= string.Empty; @@ -136,7 +140,7 @@ namespace SharpChat.Misuzu { ); } - public async Task GetBanListAsync() { + public async Task GetBanListAsync() { string now = DateTimeOffset.Now.ToUnixTimeSeconds().ToString(); string url = string.Format(BANS_LIST_URL, BaseURL, Uri.EscapeDataString(now)); string sig = string.Format(BANS_LIST_SIG, now); @@ -170,8 +174,8 @@ namespace SharpChat.Misuzu { }; string target = kind switch { - BanRevokeKind.UserId => banInfo.UserId, - BanRevokeKind.RemoteAddress => banInfo.RemoteAddress, + BanRevokeKind.UserId => banInfo?.UserId ?? string.Empty, + BanRevokeKind.RemoteAddress => banInfo?.RemoteAddress ?? string.Empty, _ => string.Empty, }; diff --git a/SharpChat/Packet/AuthFailPacket.cs b/SharpChat/Packet/AuthFailPacket.cs index 25bb523..b31b988 100644 --- a/SharpChat/Packet/AuthFailPacket.cs +++ b/SharpChat/Packet/AuthFailPacket.cs @@ -5,6 +5,7 @@ namespace SharpChat.Packet { AuthInvalid, MaxSessions, Banned, + Null, } public class AuthFailPacket : ServerPacket { diff --git a/SharpChat/Packet/ContextMessagePacket.cs b/SharpChat/Packet/ContextMessagePacket.cs index 62b6cd9..0dde06e 100644 --- a/SharpChat/Packet/ContextMessagePacket.cs +++ b/SharpChat/Packet/ContextMessagePacket.cs @@ -32,15 +32,15 @@ namespace SharpChat.Packet { } else { sb.AppendFormat( "{0}\t{1}\t{2}\t{3} {4} {5} {6} {7}", - Event.Sender.UserId, - Event.Sender.LegacyNameWithStatus, - Event.Sender.Colour, - Event.Sender.Rank, - Event.Sender.Can(ChatUserPermissions.KickUser) ? 1 : 0, - Event.Sender.Can(ChatUserPermissions.ViewLogs) ? 1 : 0, - Event.Sender.Can(ChatUserPermissions.SetOwnNickname) ? 1 : 0, - Event.Sender.Can(ChatUserPermissions.CreateChannel | ChatUserPermissions.SetChannelPermanent, true) ? 2 : ( - Event.Sender.Can(ChatUserPermissions.CreateChannel) ? 1 : 0 + Event.Sender?.UserId, + Event.Sender?.LegacyNameWithStatus, + Event.Sender?.Colour, + Event.Sender?.Rank, + Event.Sender?.Can(ChatUserPermissions.KickUser) == true ? 1 : 0, + Event.Sender?.Can(ChatUserPermissions.ViewLogs) == true ? 1 : 0, + Event.Sender?.Can(ChatUserPermissions.SetOwnNickname) == true ? 1 : 0, + Event.Sender?.Can(ChatUserPermissions.CreateChannel | ChatUserPermissions.SetChannelPermanent, true) == true ? 2 : ( + Event.Sender?.Can(ChatUserPermissions.CreateChannel) == true ? 1 : 0 ) ); } @@ -50,7 +50,7 @@ namespace SharpChat.Packet { if(isBroadcast) sb.Append("0\fsay\f"); - string body = Event.Data.RootElement.GetProperty("text").GetString().Replace("<", "<").Replace(">", ">").Replace("\n", "
").Replace("\t", " "); + string body = Event.Data.RootElement.GetProperty("text").GetString()?.Replace("<", "<").Replace(">", ">").Replace("\n", "
").Replace("\t", " ") ?? string.Empty; if(isAction) body = string.Format("{0}", body); @@ -59,17 +59,17 @@ namespace SharpChat.Packet { case "user:connect": case "SharpChat.Events.UserConnectEvent": - sb.AppendFormat("{0}\t0\fjoin\f{1}", V1_CHATBOT, Event.Sender.LegacyName); + sb.AppendFormat("{0}\t0\fjoin\f{1}", V1_CHATBOT, Event.Sender?.LegacyName); break; case "chan:join": case "SharpChat.Events.UserChannelJoinEvent": - sb.AppendFormat("{0}\t0\fjchan\f{1}", V1_CHATBOT, Event.Sender.LegacyName); + sb.AppendFormat("{0}\t0\fjchan\f{1}", V1_CHATBOT, Event.Sender?.LegacyName); break; case "chan:leave": case "SharpChat.Events.UserChannelLeaveEvent": - sb.AppendFormat("{0}\t0\flchan\f{1}", V1_CHATBOT, Event.Sender.LegacyName); + sb.AppendFormat("{0}\t0\flchan\f{1}", V1_CHATBOT, Event.Sender?.LegacyName); break; case "user:disconnect": @@ -84,7 +84,7 @@ namespace SharpChat.Packet { UserDisconnectReason.Leave => "leave", _ => "leave", }, - Event.Sender.LegacyName + Event.Sender?.LegacyName ); break; } diff --git a/SharpChat/PacketHandlers/AuthHandler.cs b/SharpChat/PacketHandlers/AuthHandler.cs index 4c3d397..988d22a 100644 --- a/SharpChat/PacketHandlers/AuthHandler.cs +++ b/SharpChat/PacketHandlers/AuthHandler.cs @@ -33,14 +33,14 @@ namespace SharpChat.PacketHandlers { public void Handle(ChatPacketHandlerContext ctx) { string[] args = ctx.SplitText(3); - string authMethod = args.ElementAtOrDefault(1); + string? authMethod = args.ElementAtOrDefault(1); if(string.IsNullOrWhiteSpace(authMethod)) { ctx.Connection.Send(new AuthFailPacket(AuthFailReason.AuthInvalid)); ctx.Connection.Dispose(); return; } - string authToken = args.ElementAtOrDefault(2); + string? authToken = args.ElementAtOrDefault(2); if(string.IsNullOrWhiteSpace(authToken)) { ctx.Connection.Send(new AuthFailPacket(AuthFailReason.AuthInvalid)); ctx.Connection.Dispose(); @@ -54,7 +54,7 @@ namespace SharpChat.PacketHandlers { } Task.Run(async () => { - MisuzuAuthInfo fai; + MisuzuAuthInfo? fai; string ipAddr = ctx.Connection.RemoteAddress.ToString(); try { @@ -70,6 +70,13 @@ namespace SharpChat.PacketHandlers { #endif } + if(fai == null) { + Logger.Debug($"<{ctx.Connection.Id}> Auth fail: "); + ctx.Connection.Send(new AuthFailPacket(AuthFailReason.Null)); + ctx.Connection.Dispose(); + return; + } + if(!fai.Success) { Logger.Debug($"<{ctx.Connection.Id}> Auth fail: {fai.Reason}"); ctx.Connection.Send(new AuthFailPacket(AuthFailReason.AuthInvalid)); @@ -77,7 +84,7 @@ namespace SharpChat.PacketHandlers { return; } - MisuzuBanInfo fbi; + MisuzuBanInfo? fbi; try { fbi = await Misuzu.CheckBanAsync(fai.UserId.ToString(), ipAddr); } catch(Exception ex) { @@ -91,6 +98,13 @@ namespace SharpChat.PacketHandlers { #endif } + if(fbi == null) { + Logger.Debug($"<{ctx.Connection.Id}> Ban check fail: "); + ctx.Connection.Send(new AuthFailPacket(AuthFailReason.Null)); + ctx.Connection.Dispose(); + return; + } + if(fbi.IsBanned && !fbi.HasExpired) { Logger.Write($"<{ctx.Connection.Id}> User is banned."); ctx.Connection.Send(new AuthFailPacket(fbi.ExpiresAt)); @@ -100,7 +114,7 @@ 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.FirstOrDefault(u => u.UserId == fai.UserId); if(user == null) user = new ChatUser( @@ -134,7 +148,7 @@ namespace SharpChat.PacketHandlers { if(File.Exists("welcome.txt")) { IEnumerable lines = File.ReadAllLines("welcome.txt").Where(x => !string.IsNullOrWhiteSpace(x)); - string line = lines.ElementAtOrDefault(RNG.Next(lines.Count())); + string? line = lines.ElementAtOrDefault(RNG.Next(lines.Count())); if(!string.IsNullOrWhiteSpace(line)) ctx.Connection.Send(new LegacyCommandResponse(LCR.WELCOME, false, line)); diff --git a/SharpChat/PacketHandlers/SendMessageHandler.cs b/SharpChat/PacketHandlers/SendMessageHandler.cs index b3b9f82..dc70388 100644 --- a/SharpChat/PacketHandlers/SendMessageHandler.cs +++ b/SharpChat/PacketHandlers/SendMessageHandler.cs @@ -33,10 +33,10 @@ namespace SharpChat.PacketHandlers public void Handle(ChatPacketHandlerContext ctx) { string[] args = ctx.SplitText(3); - ChatUser user = ctx.Connection.User; + ChatUser? user = ctx.Connection.User; // No longer concats everything after index 1 with \t, no previous implementation did that either - string messageText = args.ElementAtOrDefault(2); + string? messageText = args.ElementAtOrDefault(2); if(user == null || !user.Can(ChatUserPermissions.SendMessage) || string.IsNullOrWhiteSpace(messageText)) return; @@ -47,8 +47,8 @@ namespace SharpChat.PacketHandlers ctx.Chat.ContextAccess.Wait(); try { - if(!ctx.Chat.UserLastChannel.TryGetValue(user.UserId, out ChatChannel channel) - && !ctx.Chat.IsInChannel(user, channel)) + if(!ctx.Chat.UserLastChannel.TryGetValue(user.UserId, out ChatChannel? channel) + || !ctx.Chat.IsInChannel(user, channel)) return; if(user.Status != ChatUserStatus.Online) @@ -67,7 +67,7 @@ namespace SharpChat.PacketHandlers if(messageText.StartsWith("/")) { ChatCommandContext context = new(messageText, ctx.Chat, user, ctx.Connection, channel); - IChatCommand command = null; + IChatCommand? command = null; foreach(IChatCommand cmd in Commands) if(cmd.IsMatch(context)) { diff --git a/SharpChat/Program.cs b/SharpChat/Program.cs index 8164187..6f7c1a4 100644 --- a/SharpChat/Program.cs +++ b/SharpChat/Program.cs @@ -29,7 +29,7 @@ namespace SharpChat { using ManualResetEvent mre = new(false); bool hasCancelled = false; - void cancelKeyPressHandler(object sender, ConsoleCancelEventArgs ev) { + void cancelKeyPressHandler(object? sender, ConsoleCancelEventArgs ev) { Console.CancelKeyPress -= cancelKeyPressHandler; hasCancelled = true; ev.Cancel = true; diff --git a/SharpChat/SharpChat.csproj b/SharpChat/SharpChat.csproj index 63d5099..4b3e98d 100644 --- a/SharpChat/SharpChat.csproj +++ b/SharpChat/SharpChat.csproj @@ -3,6 +3,7 @@ Exe net6.0 + enable diff --git a/SharpChat/SharpChatWebSocketServer.cs b/SharpChat/SharpChatWebSocketServer.cs index da986ec..2633344 100644 --- a/SharpChat/SharpChatWebSocketServer.cs +++ b/SharpChat/SharpChatWebSocketServer.cs @@ -1,4 +1,6 @@ -using Fleck; +#nullable disable + +using Fleck; using System; using System.Collections.Generic; using System.IO; diff --git a/SharpChat/SharpInfo.cs b/SharpChat/SharpInfo.cs index aa97fff..fa04f45 100644 --- a/SharpChat/SharpInfo.cs +++ b/SharpChat/SharpInfo.cs @@ -1,6 +1,5 @@ using System.IO; using System.Reflection; -using System.Text; namespace SharpChat { public static class SharpInfo { @@ -19,19 +18,18 @@ namespace SharpChat { #endif try { - using Stream s = Assembly.GetExecutingAssembly().GetManifestResourceStream(@"SharpChat.version.txt"); - using StreamReader sr = new(s); - VersionString = sr.ReadLine().Trim(); + using Stream? s = Assembly.GetExecutingAssembly().GetManifestResourceStream(@"SharpChat.version.txt"); + if(s != null) { + using StreamReader sr = new(s); + VersionString = sr.ReadLine()?.Trim() ?? string.Empty; + } else + VersionString = string.Empty; VersionStringShort = VersionString.Length > 10 ? VersionString[..10] : VersionString; } catch { VersionStringShort = VersionString = UNKNOWN; } - StringBuilder sb = new(); - sb.Append(NAME); - sb.Append('/'); - sb.Append(VersionStringShort); - ProgramName = sb.ToString(); + ProgramName = string.Format(@"{0}/{1}", NAME, VersionStringShort); } } } diff --git a/SharpChat/SockChatServer.cs b/SharpChat/SockChatServer.cs index c5114e4..df5b5cc 100644 --- a/SharpChat/SockChatServer.cs +++ b/SharpChat/SockChatServer.cs @@ -51,24 +51,29 @@ namespace SharpChat { Context = new ChatContext(evtStore); - string[] channelNames = config.ReadValue("channels", new[] { "lounge" }); + string[]? channelNames = config.ReadValue("channels", new[] { "lounge" }); - foreach(string channelName in channelNames) { - IConfig channelCfg = config.ScopeTo($"channels:{channelName}"); + if(channelNames != null) + foreach(string channelName in channelNames) { + IConfig channelCfg = config.ScopeTo($"channels:{channelName}"); - string name = channelCfg.SafeReadValue("name", string.Empty); - if(string.IsNullOrWhiteSpace(name)) - name = channelName; + string? name = channelCfg.SafeReadValue("name", string.Empty); + if(string.IsNullOrWhiteSpace(name)) + name = channelName; - ChatChannel channelInfo = new( - name, - channelCfg.SafeReadValue("password", string.Empty), - rank: channelCfg.SafeReadValue("minRank", 0) - ); + ChatChannel channelInfo = new( + name, + channelCfg.SafeReadValue("password", string.Empty), + rank: channelCfg.SafeReadValue("minRank", 0) + ); - Context.Channels.Add(channelInfo); - DefaultChannel ??= channelInfo; - } + Context.Channels.Add(channelInfo); + DefaultChannel ??= channelInfo; + } + + DefaultChannel ??= new ChatChannel("Default"); + if(!Context.Channels.Any()) + Context.Channels.Add(DefaultChannel); GuestHandlers.Add(new AuthHandler(Misuzu, DefaultChannel, MaxMessageLength, MaxConnections)); @@ -154,13 +159,13 @@ namespace SharpChat { // this doesn't affect non-authed connections????? if(conn.User is not null && conn.User.Rank < FloodKickExemptRank) { - ChatUser banUser = null; + ChatUser? banUser = null; string banAddr = string.Empty; TimeSpan banDuration = TimeSpan.MinValue; Context.ContextAccess.Wait(); try { - if(!Context.UserRateLimiters.TryGetValue(conn.User.UserId, out RateLimiter rateLimiter)) + if(!Context.UserRateLimiters.TryGetValue(conn.User.UserId, out RateLimiter? rateLimiter)) Context.UserRateLimiters.Add(conn.User.UserId, rateLimiter = new RateLimiter( ChatUser.DEFAULT_SIZE, ChatUser.DEFAULT_MINIMUM_DELAY, @@ -200,7 +205,7 @@ namespace SharpChat { } ChatPacketHandlerContext context = new(msg, Context, conn); - IChatPacketHandler handler = conn.User is null + IChatPacketHandler? handler = conn.User is null ? GuestHandlers.FirstOrDefault(h => h.IsMatch(context)) : AuthedHandlers.FirstOrDefault(h => h.IsMatch(context));