using SharpChat.Config; using SharpChat.Events; using SharpChat.SockChat.Commands; using System.Collections.Generic; using System.Linq; namespace SharpChat.SockChat.PacketsC2S { public class SendMessageC2SPacketHandler : IC2SPacketHandler { private readonly CachedValue MaxMessageLength; private List Commands { get; } = new(); public SendMessageC2SPacketHandler(CachedValue maxMsgLength) { MaxMessageLength = maxMsgLength; } public void AddCommand(ISockChatClientCommand command) { Commands.Add(command); } public void AddCommands(IEnumerable commands) { Commands.AddRange(commands); } public bool IsMatch(C2SPacketHandlerContext ctx) { return ctx.CheckPacketId("2"); } public void Handle(C2SPacketHandlerContext ctx) { string[] args = ctx.SplitText(3); UserInfo? user = ctx.Chat.Users.Get(ctx.Connection.UserId); // No longer concats everything after index 1 with \t, no previous implementation did that either string? messageText = args.ElementAtOrDefault(2); if(user == null || !user.Permissions.HasFlag(UserPermissions.SendMessage) || string.IsNullOrWhiteSpace(messageText)) return; // Extra validation step, not necessary at all but enforces proper formatting in SCv1. if(!long.TryParse(args[1], out long mUserId) || user.UserId != mUserId) return; ctx.Chat.ContextAccess.Wait(); try { ChannelInfo? channelInfo = ctx.Chat.Channels.Get( ctx.Chat.ChannelsUsers.GetUserLastChannel(user) ); if(channelInfo == null) return; if(ctx.Chat.UserStatuses.GetStatus(user) != UserStatus.Online) ctx.Chat.Events.Dispatch( "user:status", user, new UserStatusUpdateEventData(UserStatus.Online) ); int maxMsgLength = MaxMessageLength; if(messageText.Length > maxMsgLength) messageText = messageText[..maxMsgLength]; messageText = messageText.Trim(); #if DEBUG Logger.Write($"<{user.UserId} {user.UserName}> {messageText}"); #endif if(messageText.StartsWith("/")) { SockChatClientCommandContext context = new(messageText, ctx.Chat, user, ctx.Connection, channelInfo); ISockChatClientCommand? command = null; foreach(ISockChatClientCommand cmd in Commands) if(cmd.IsMatch(context)) { command = cmd; break; } if(command != null) { command.Dispatch(context); return; } } ctx.Chat.Events.Dispatch("msg:add", channelInfo, user, new MessageAddEventData(messageText)); } finally { ctx.Chat.ContextAccess.Release(); } } } }