using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; using ProxyCore.Messages; using ProxyCore.Scripting; namespace ProxyCore.Output { internal static class TriggerHandler { static TriggerHandler() { } private static SortedDictionary> Triggers = new SortedDictionary>(); internal static Dictionary TriggersName = new Dictionary(); internal static void DisableTriggers(string FromPlugin, int MinPriority, int MaxPriority) { if(FromPlugin == null) return; FromPlugin = FromPlugin.ToLower().Trim(); if(FromPlugin.Length == 0) return; foreach(KeyValuePair> x in Triggers) { if(x.Key < MinPriority) continue; if(x.Key > MaxPriority) break; foreach(TriggerEntry y in x.Value) { if(y.Disabled == null) y.Disabled = new List(); if(!y.Disabled.Contains(FromPlugin)) y.Disabled.Add(FromPlugin); } } } internal static void EnableTriggers(string FromPlugin, int MinPriority, int MaxPriority) { if(FromPlugin == null) return; FromPlugin = FromPlugin.ToLower().Trim(); if(FromPlugin.Length == 0) return; foreach(KeyValuePair> x in Triggers) { if(x.Key < MinPriority) continue; if(x.Key > MaxPriority) break; foreach(TriggerEntry y in x.Value) { if(y.Disabled == null) continue; y.Disabled.Remove(FromPlugin); } } } /// /// Register a new trigger. /// /// Unique identifier for the trigger. /// Regex pattern for the trigger. /// Function that will be called if this trigger fires. internal static void RegisterTrigger(string Name, string Pattern, TriggerFunction Function) { RegisterTrigger(Name, Pattern, Function, TriggerFlags.None); } /// /// Register a new trigger. /// /// Unique identifier for the trigger. /// Regex pattern for the trigger. /// Function that will be called if this trigger fires. /// Options for the trigger. internal static void RegisterTrigger(string Name, string Pattern, TriggerFunction Function, TriggerFlags Flags) { RegisterTrigger(Name, Pattern, Function, Flags, 1000); } /// /// Register a new trigger. /// /// Unique identifier for the trigger. /// Regex pattern for the trigger. /// Function that will be called if this trigger fires. /// Options for the trigger. /// Lower priority triggers get matched first. Default: 1000 internal static void RegisterTrigger(string Name, string Pattern, TriggerFunction Function, TriggerFlags Flags, int Priority) { RegisterTrigger(Name, Pattern, Function, Flags, Priority, 0, "core"); } /// /// Register a new trigger. /// /// Unique identifier for the trigger. /// Regex pattern for the trigger. /// Function that will be called if this trigger fires. /// Options for the trigger. /// Lower priority triggers get matched first. Default: 1000 /// Custom argument to pass to trigger data. /// From which plugin was this registered. internal static void RegisterTrigger(string Name, string Pattern, TriggerFunction Function, TriggerFlags Flags, int Priority, int Arg, string Plugin) { if(string.IsNullOrEmpty(Pattern) || string.IsNullOrEmpty(Name) || Function == null) return; Name = Name.ToLower().Trim(); if(Name.Length == 0) return; Regex p = null; if((Flags & TriggerFlags.NotRegex) == TriggerFlags.None) { try { RegexOptions op = RegexOptions.None; if((Flags & TriggerFlags.RightToLeft) != TriggerFlags.None) op |= RegexOptions.RightToLeft; if((Flags & TriggerFlags.CaseInsensitive) != TriggerFlags.None) op |= RegexOptions.IgnoreCase; p = new Regex(Pattern, op); } catch { return; } } TriggerEntry e = new TriggerEntry(); e.Function = Function; e.Pattern = p; e.PatternStr = Pattern; e.Priority = Priority; e.Name = Name; e.Flags = Flags; e.Arg = Arg; e.Plugin = Plugin; if(TriggersName.ContainsKey(Name)) Triggers[TriggersName[Name].Priority].Remove(TriggersName[Name]); TriggersName[Name] = e; if(!Triggers.ContainsKey(e.Priority)) Triggers[e.Priority] = new List(); Triggers[e.Priority].Add(e); } /// /// Unregister a trigger by name. /// /// Name of the trigger you wish to unregister. internal static void UnregisterTrigger(string Name) { if(Name != null) Name = Name.ToLower().Trim(); if(string.IsNullOrEmpty(Name)) return; if(!TriggersName.ContainsKey(Name)) return; Triggers[TriggersName[Name].Priority].Remove(TriggersName[Name]); TriggersName.Remove(Name); } internal static void HandleText(string Msg, World world) { if(!string.IsNullOrEmpty(lastColorCode)) Msg = lastColorCode + Msg; lastColorCode = Colors.GetLastColorCode(Msg); Msg = Colors.RemoveDuplicateColors(Msg); Message m = new Message(true); m.Msg = Msg; HandleLineRaw(m); if(m.Msg != null) { world._SendMessage(m); world.lastLine.Add(m.Msg); while(world.lastLine.Count > 100) world.lastLine.RemoveAt(0); } } private static string lastColorCode = ""; private static readonly List> gmcpData = new List>(); internal static void HandleGMCP(string Msg) { //string origMsg = Msg; string module; try { int ind = Msg.IndexOf(' '); if(ind == -1) { module = Msg; Msg = ""; } else { module = Msg.Substring(0, ind); Msg = Msg.Substring(ind).Trim(); } } catch { return; } if(string.IsNullOrEmpty(module)) return; if(gmcpData.Count != 0) gmcpData.Clear(); module = module.ToLower(); bool res = JSON.Parse(Msg, module, gmcpData); if(!res) return; if(gmcpData.Count == 0) HandleGMCP(module, null); else { foreach(KeyValuePair i in gmcpData) HandleGMCP(i.Key.ToLower().Trim(), i.Value); } } private static void HandleGMCP(string Module, string Value) { Message m = new Message(true); m.Msg = "$gmcp." + Module + (Value != null ? (" " + Value) : ""); HandleLineRaw(m); } private static void HandleLineRaw(Message Msg) { foreach(KeyValuePair x in PluginMgr.Plugins) { try { x.Value.OnReceivedLineBefore(Msg); } catch(Exception e) { Log.Crash(e, x.Key); } if(Msg.Msg == null) return; } foreach(KeyValuePair> x in Triggers) { foreach(TriggerEntry y in x.Value) { if(y.Disabled != null && y.Disabled.Count != 0) continue; int i = 0; while(Msg.Msg != null) { int o = i; Match m = null; if((y.Flags & TriggerFlags.NotRegex) == TriggerFlags.None) { if((y.Flags & TriggerFlags.RightToLeft) != TriggerFlags.None) m = y.Pattern.Match((y.Flags & TriggerFlags.NonAnsi) == TriggerFlags.None ? Msg.Msg : Msg.MsgNoColor); else m = y.Pattern.Match((y.Flags & TriggerFlags.NonAnsi) == TriggerFlags.None ? Msg.Msg : Msg.MsgNoColor, i); if(!m.Success) break; } else if(y.PatternStr != ((y.Flags & TriggerFlags.NonAnsi) == TriggerFlags.None ? Msg.Msg : Msg.MsgNoColor)) break; TriggerData d = new TriggerData(); d.Match = m; d.Arg = y.Arg; d.Msg = Msg; #if !DEBUG try { #endif if(y.Function(d)) { Msg.Msg = null; return; } #if !DEBUG } catch(Exception e) { Log.Crash(e, y.Plugin); } #endif if((y.Flags & TriggerFlags.NotRegex) != TriggerFlags.None) break; if((y.Flags & TriggerFlags.RightToLeft) != TriggerFlags.None) break; i = m.Groups[0].Index + m.Groups[0].Length; if((y.Flags & TriggerFlags.Repeat) == TriggerFlags.None) break; if(i == o) i++; } } } foreach(KeyValuePair x in PluginMgr.Plugins) { #if !DEBUG try { #endif x.Value.OnReceivedLineAfter(Msg); #if !DEBUG } catch(Exception e) { Log.Crash(e, x.Key); } #endif if(Msg.Msg == null) return; } } } }