using System; using System.Collections.Generic; using System.Linq; using HISP.Player; using HISP.Server; namespace HISP.Game.Chat { public class Chat { public struct Correction { public string FilteredWord; public string ReplacedWord; } public struct Reason { public string Name; public string Message; } public struct Filter { public string FilteredWord; public Reason Reason; public bool MatchAll; } public enum ChatChannel { All = 0x14, Ads = 0x1D, Near = 0x15, Buddies = 0x17, Here = 0x18, Isle = 0x1A, Dm = 0x16, Mod = 0x1c, Admin = 0x1b } public static string PrivateMessageSound; public static List FilteredWords = new List(); public static List CorrectedWords = new List(); public static List Reasons = new List(); public static bool ProcessCommand(User user, string message) { if (message.Length < 1) return false; string[] args = message.Split(' ').Skip(1).ToArray(); if (user.Administrator || user.Moderator) { if (message[0] == '%') { if (message.StartsWith("%GIVE")) return Command.Give(message, args, user); if (message.StartsWith("%GOTO")) return Command.Goto(message, args, user); if (message.StartsWith("%KICK")) return Command.Kick(message, args, user); if (message.StartsWith("%NOCLIP")) return Command.NoClip(message, args, user); if (message.StartsWith("%BAN")) return Command.Ban(message, args, user); if (message.StartsWith("%UNBAN")) return Command.UnBan(message, args, user); if (message.StartsWith("%ESCAPE")) return Command.Escape(message, args, user); return false; } } if (message[0] == '!') { // Alias for !MUTE if (message.StartsWith("!MUTEALL")) return Command.Mute(message, new string[] { "ALL" }, user); else if (message.StartsWith("!MUTEADS")) return Command.Mute(message, new string[] { "ADS" }, user); else if (message.StartsWith("!MUTEGLOBAL")) return Command.Mute(message, new string[] { "GLOBAL" }, user); else if (message.StartsWith("!MUTEISLAND")) return Command.Mute(message, new string[] { "ISLAND" }, user); else if (message.StartsWith("!MUTENEAR")) return Command.Mute(message, new string[] { "NEAR" }, user); else if (message.StartsWith("!MUTEHERE")) return Command.Mute(message, new string[] { "HERE" }, user); else if (message.StartsWith("!MUTEBUDDY")) return Command.Mute(message, new string[] { "BUDDY" }, user); else if (message.StartsWith("!MUTEPM")) return Command.Mute(message, new string[] { "PM" }, user); else if (message.StartsWith("!MUTEPM")) return Command.Mute(message, new string[] { "PM" }, user); else if (message.StartsWith("!MUTEBR")) return Command.Mute(message, new string[] { "BR" }, user); else if (message.StartsWith("!MUTESOCIALS")) return Command.Mute(message, new string[] { "SOCIALS" }, user); else if (message.StartsWith("!MUTELOGINS")) return Command.Mute(message, new string[] { "LOGINS" }, user); else if (message.StartsWith("!MUTE")) return Command.Mute(message, args, user); else if (message.StartsWith("!WARP")) return Command.Warp(message, args, user); } return false; } public static Object FilterMessage(string message) // Handles chat filtering and violation stuffs { if (!ConfigReader.BadWords) // Freedom of Speech Mode return null; string[] wordsSaid; if (message.Contains(' ')) wordsSaid = message.Split(' '); else wordsSaid = new string[] { message }; foreach(Filter filter in FilteredWords) { if (!filter.MatchAll) { foreach (string word in wordsSaid) { if (word.ToLower() == filter.FilteredWord.ToLower()) return filter.Reason; } } else { if (message.ToLower().Contains(filter.FilteredWord)) return filter.Reason; } } return null; } public static byte GetSide(ChatChannel channel) { switch (channel) { case ChatChannel.All: case ChatChannel.Ads: case ChatChannel.Isle: return PacketBuilder.CHAT_BOTTOM_LEFT; case ChatChannel.Buddies: case ChatChannel.Here: case ChatChannel.Admin: case ChatChannel.Mod: return PacketBuilder.CHAT_BOTTOM_RIGHT; case ChatChannel.Dm: return PacketBuilder.CHAT_DM_RIGHT; default: Logger.ErrorPrint("unknown channel: " + (byte)channel); return PacketBuilder.CHAT_BOTTOM_LEFT; } } public static string GetDmRecipiant(string message) { if(message.Contains('|')) { string recipiantName = message.Split('|')[0]; return recipiantName; } else { return null; } } public static string GetDmMessage(string message) { if (message.Contains('|')) { string messageStr = message.Split('|')[1]; return messageStr; } else { return message; } } public static GameClient[] GetRecipiants(User user, ChatChannel channel, string to=null) { if (channel == ChatChannel.All) { List recipiants = new List(); foreach (GameClient client in GameServer.ConnectedClients) { if (client.LoggedIn) if (!client.LoggedinUser.MuteGlobal && !client.LoggedinUser.MuteAll) if (client.LoggedinUser.Id != user.Id) recipiants.Add(client); } return recipiants.ToArray(); } if(channel == ChatChannel.Ads) { List recipiants = new List(); foreach (GameClient client in GameServer.ConnectedClients) { if (client.LoggedIn) if (!client.LoggedinUser.MuteAds && !client.LoggedinUser.MuteAll) if (client.LoggedinUser.Id != user.Id) recipiants.Add(client); } return recipiants.ToArray(); } if(channel == ChatChannel.Buddies) { List recipiants = new List(); foreach (GameClient client in GameServer.ConnectedClients) { if (client.LoggedIn) if (!client.LoggedinUser.MuteBuddy && !client.LoggedinUser.MuteAll) if (client.LoggedinUser.Id != user.Id) if (client.LoggedinUser.Friends.List.Contains(user.Id)) recipiants.Add(client); } return recipiants.ToArray(); } if (channel == ChatChannel.Isle) { List recipiants = new List(); if(World.InIsle(user.X,user.Y)) { User[] usersInSile = GameServer.GetUsersInIsle(World.GetIsle(user.X, user.Y), true, false); foreach (User userInIsle in usersInSile) { if (user.Id != userInIsle.Id) if(!user.MuteAll) recipiants.Add(userInIsle.LoggedinClient); } return recipiants.ToArray(); } else { return new GameClient[0]; } } if (channel == ChatChannel.Here) { List recipiants = new List(); User[] usersHere = GameServer.GetUsersAt(user.X, user.Y, true, false); foreach (User userHere in usersHere) { if (user.Id != userHere.Id) if (!user.MuteAll) recipiants.Add(userHere.LoggedinClient); } return recipiants.ToArray(); } if (channel == ChatChannel.Near) { List recipiants = new List(); User[] nearbyUsers = GameServer.GetNearbyUsers(user.X, user.Y, true, false); foreach (User nearbyUser in nearbyUsers) { if (user.Id != nearbyUser.Id) if (!user.MuteAll) recipiants.Add(nearbyUser.LoggedinClient); } return recipiants.ToArray(); } if (channel == ChatChannel.Mod) { if (!user.Moderator || !user.Administrator) // No mod chat for non-mods! { Logger.WarnPrint(user.Username + " attempted to send in MOD chat, without being a MOD."); return new GameClient[0]; } List recipiants = new List(); foreach (GameClient client in GameServer.ConnectedClients) { if (client.LoggedIn) if (client.LoggedinUser.Moderator) if (client.LoggedinUser.Id != user.Id) recipiants.Add(client); } return recipiants.ToArray(); } if(channel == ChatChannel.Admin) { if (!user.Administrator) // No admin chat for non-admins! { Logger.WarnPrint(user.Username + " attempted to send in ADMIN chat, without being an ADMIN."); return new GameClient[0]; } List recipiants = new List(); foreach (GameClient client in GameServer.ConnectedClients) { if (client.LoggedIn) if (client.LoggedinUser.Administrator) if (client.LoggedinUser.Id != user.Id) recipiants.Add(client); } return recipiants.ToArray(); } if(channel == ChatChannel.Dm) { if (to != null) { List recipiants = new List(); foreach (GameClient client in GameServer.ConnectedClients) { if (client.LoggedIn) if (!client.LoggedinUser.MutePrivateMessage && !client.LoggedinUser.MuteAll) if (client.LoggedinUser.Username == to) recipiants.Add(client); } return recipiants.ToArray(); } else { Logger.ErrorPrint("Channel is " + channel + " (DM) BUT no 'to' Paramater was specfied"); return new GameClient[0]; } } Logger.ErrorPrint(user.Username + " Sent message in unknown channel: " + (byte)channel); return new GameClient[0]; // No recipiants } public static string DoCorrections(string message) { if (!ConfigReader.DoCorrections) return message; foreach(Correction correct in CorrectedWords) message = message.Replace(correct.FilteredWord, correct.ReplacedWord); return message.Trim(); } public static string EscapeMessage(string message) { return message.Replace("<", "<"); } public static string FormatChatForOthers(User user, ChatChannel channel, string message) { switch (channel) { case ChatChannel.All: if (user.Moderator || user.Administrator) return Messages.FormatGlobalChatMessageForMod(user.Username, message); else return Messages.FormatGlobalChatMessage(user.Username, message); case ChatChannel.Ads: return Messages.FormatAdsChatMessage(user.Username, message); case ChatChannel.Buddies: return Messages.FormatBuddyChatMessage(user.Username, message); case ChatChannel.Dm: if (user.Moderator || user.Administrator) return Messages.FormatDirectMessageForMod(user.Username, message); else return Messages.FormatDirectMessage(user.Username, message); case ChatChannel.Near: return Messages.FormatNearbyChatMessage(user.Username, message); case ChatChannel.Isle: return Messages.FormatIsleChatMessage(user.Username, message); case ChatChannel.Here: return Messages.FormatHereChatMessage(user.Username, message); case ChatChannel.Mod: if (user.Moderator || user.Administrator) return Messages.FormatModChatMessage(user.Username, message); else { Logger.HackerPrint(user.Username + " Tried to send in mod chat without being a moderator. (Hack/Code Attempt)"); return user.Username + " is a hacker! (Sent in mod channel without being a mod) Maybe ban?"; } case ChatChannel.Admin: if (user.Administrator) return Messages.FormatAdminChatMessage(user.Username, message); else { Logger.HackerPrint(user.Username + " Tried to send in mod chat without being a moderator. (Hack/Code Attempt)"); return user.Username + " is a hacker! (Sent in admin channel without being a admin) Maybe ban?"; } default: Logger.ErrorPrint(user.Username + " is trying to end a message in unknown channel " + channel.ToString("X")); return "not implemented yet :("; } } public static string FormatChatForSender(User user, ChatChannel channel, string message, string dmRecipiant=null) { switch (channel) { case ChatChannel.All: if (user.Moderator || user.Administrator) return Messages.FormatGlobalChatMessageForMod(user.Username, message); else return Messages.FormatGlobalChatMessage(user.Username, message); case ChatChannel.Ads: int numbListening = GameServer.GetNumberOfPlayersListeningToAdsChat(); // vry specific function ik return Messages.FormatAdsChatForSender(numbListening-1, user.Username, message); case ChatChannel.Buddies: return Messages.FormatBuddyChatMessageForSender(user.Friends.Count, user.Username, message); case ChatChannel.Isle: int inIsle = 0; if (World.InIsle(user.X, user.Y)) inIsle = GameServer.GetUsersInIsle(World.GetIsle(user.X, user.Y), false, false).Length -1; return Messages.FormatIsleChatMessageForSender(inIsle, user.Username, message); case ChatChannel.Here: int usersHere = GameServer.GetUsersAt(user.X, user.Y, false, false).Length -1; return Messages.FormatHereChatMessageForSender(usersHere, user.Username, message); case ChatChannel.Near: int nearbyUsers = GameServer.GetNearbyUsers(user.X, user.Y, false, false).Length -1; return Messages.FormatNearChatMessageForSender(nearbyUsers, user.Username, message); case ChatChannel.Mod: int modsOnline = GameServer.GetNumberOfModsOnline() - 1; return Messages.FormatModChatForSender(modsOnline, user.Username, message); case ChatChannel.Admin: int adminsOnline = GameServer.GetNumberOfAdminsOnline() - 1; return Messages.FormatAdminChatForSender(adminsOnline, user.Username, message); case ChatChannel.Dm: return Messages.FormatDirectChatMessageForSender(user.Username, dmRecipiant, message); default: Logger.ErrorPrint(user.Username + " is trying to end a message in unknown channel " + channel.ToString("X")); return "not implemented yet :("; } } public static string NonViolationChecks(User user, string message) { if(ConfigReader.DoNonViolations) return null; // Check if contains password. if (message.ToLower().Contains(user.Password.ToLower())) return Messages.PasswordNotice; // Check if ALL CAPS string[] wordsSaid; if (message.Contains(' ')) wordsSaid = message.Split(' '); else wordsSaid = new string[] { message }; foreach (string word in wordsSaid) { string lettersOnly = ""; foreach(char c in word) { if((byte)c >= (byte)'A' && (byte)c <= (byte)'z') // is letter { lettersOnly += c; } } if (lettersOnly.ToUpper() == lettersOnly && lettersOnly.Length >= 5) return Messages.CapsNotice; } return null; } public static Reason GetReason(string name) { foreach (Reason reason in Reasons) if (reason.Name == name) return reason; throw new KeyNotFoundException("Reason " + name + " not found."); } } }