/// <summary> /// Constructor /// </summary> /// <param name="config">The configuration to use.</param> public IrcConnection(IIrcConfig config, INonDisposableStringParsingQueue parsingQueue, IIrcMac macLayer) { ArgumentChecker.IsNotNull(config, nameof(config)); ArgumentChecker.IsNotNull(parsingQueue, nameof(parsingQueue)); ArgumentChecker.IsNotNull(macLayer, nameof(macLayer)); this.inited = false; this.Config = new ReadOnlyIrcConfig(config); this.IsConnected = false; this.connection = macLayer; this.keepReadingObject = new object(); this.KeepReading = false; this.writerQueue = new EventExecutor(config.Server + " IRC Writer Queue"); this.writerQueue.OnError += this.WriterQueue_OnError; this.ircWriterLock = new object(); this.reconnectAbortEvent = new ManualResetEvent(false); this.eventScheduler = new EventScheduler(); this.parsingQueue = parsingQueue; this.watchDog = new IrcWatchdog( StaticLogger.Log, () => this.SendPing(watchdogStr), this.Watchdog_OnFailure, 60 * 1000 ); }
// -------- Functions -------- /// <summary> /// Handles the event and sends the responses to the channel if desired. /// </summary> /// <param name="line">The RAW line from IRC to check.</param> /// <param name="ircConfig">The irc config to use when parsing this line.</param> /// <param name="ircWriter">The way to write to the irc channel.</param> public void HandleEvent(string line, IIrcConfig ircConfig, IIrcWriter ircWriter) { ArgumentChecker.StringIsNotNullOrEmpty(line, nameof(line)); ArgumentChecker.IsNotNull(ircConfig, nameof(ircConfig)); ArgumentChecker.IsNotNull(ircWriter, nameof(ircWriter)); Match match = pattern.Match(line); if (match.Success) { string remoteUser = match.Groups["nick"].Value; // Don't fire if we were the ones to trigger the event. if (remoteUser.ToUpper() == ircConfig.Nick.ToUpper()) { return; } IrcResponse response = new IrcResponse( remoteUser, match.Groups["channel"].Value, string.Empty ); this.PartAction(ircWriter, response); } }
// -------- Functions -------- /// <summary> /// Inits this plugin. /// </summary> /// <param name="pluginPath">Path to the plugin DLL</param> /// <param name="ircConfig">The IRC config being used.</param> public void Init(string pluginPath, IIrcConfig ircConfig) { MessageHandler weatherHandler = new MessageHandler( weatherCommand, HandleWeatherCommand, cooldown ); MessageHandler helpHandler = new MessageHandler( @"!weather\s+help", HandleHelpCommand, cooldown ); MessageHandler aboutHandler = new MessageHandler( @"!weather\s+about", HandleAboutCommand, cooldown ); MessageHandler sourceCodeHandler = new MessageHandler( @"!weather\s+sourcecode", HandleSourceCodeCommand, cooldown ); this.handlers.Add(weatherHandler); this.handlers.Add(helpHandler); this.handlers.Add(aboutHandler); this.handlers.Add(sourceCodeHandler); }
// ---------------- Functions ---------------- /// <summary> /// Initializes the plugin. /// </summary> /// <param name="pluginInit">The class that has information required for initing the plugin.</param> public void Init(PluginInitor initor) { this.ircConfig = initor.IrcConfig; { MessageHandlerConfig config = new MessageHandlerConfig { LineRegex = @"^!broadcast\s+(?<bcastmsg>.+)", LineAction = this.BroadcastHandler }; MessageHandler bcastHandler = new MessageHandler( config ); this.handlers.Add(bcastHandler); } { MessageHandlerConfig config = new MessageHandlerConfig { LineRegex = @"^!cc\s+\<(?<channel>\S+)\>\s+(?<ccmessage>.+)", LineAction = this.CCHandler }; MessageHandler ccHandler = new MessageHandler( config ); this.handlers.Add(ccHandler); } }
/// <summary> /// Generates the handler for the MessageHandler based on the user's command /// and our expected response. /// </summary> /// <param name="command">The command our bot is listening for.</param> /// <param name="response">The response our bot will generate.</param> public static MessageHandlerAction GetMessageHandler(string response, IIrcConfig ircConfig) { ArgumentChecker.StringIsNotNullOrEmpty(response, nameof(response)); string innerResponse = response; return(delegate(MessageHandlerArgs args) { StringBuilder responseToSend = new StringBuilder( Parsing.LiquefyStringWithIrcConfig(innerResponse, args.User, ircConfig.Nick, args.Channel) ); foreach (string group in args.Regex.GetGroupNames()) { responseToSend.Replace( "{%" + group + "%}", args.Match.Groups[group].Value ); } args.Writer.SendMessage( responseToSend.ToString(), args.Channel ); }); }
// -------- Functions -------- /// <summary> /// Initializes the plugin. /// </summary> /// <param name="pluginPath">The absolute path to the plugin dll.</param> /// <param name="ircConfig">The IRC config we are using.</param> public void Init(string pluginPath, IIrcConfig ircConfig) { string pluginDir = Path.GetDirectoryName(pluginPath); IrcLoggerConfig config = XmlLoader.LoadIrcLoggerConfig( Path.Combine(pluginDir, "IrcLoggerConfig.xml") ); if (string.IsNullOrEmpty(config.LogFileLocation)) { config.LogFileLocation = Path.Combine(pluginDir, "Logs"); } if (string.IsNullOrEmpty(config.LogName)) { config.LogName = "irclog"; } this.logManager = new LogManager(config); AllHandler handler = new AllHandler( this.HandleLogEvent ); this.handlers.Add(handler); }
public void TestValidXmlWithPassword() { IIrcConfig config = XmlLoader.ParseIrcConfig( Path.Combine(testXmlFiles, "ValidIrcConfigWithPassword.xml") ); Assert.AreEqual(this.ircConfig, config); }
// -------- Functions -------- /// <summary> /// Initializes the plugin. This includes loading any configuration files, /// starting services, etc. Allowed to throw Exceptions. /// /// This function should be used to validates that the environment is good for the plugin. /// For example, it has all dependencies installed, config files are in the correct spot, etc. /// It should also load GetHandlers() with the handlers. /// </summary> /// <param name="pluginPath"> /// The absolute path to the plugin, including the file name. To just get /// the path to the plugin, call Path.GetDirectoryName on this argument. /// </param> /// <param name="ircConfig">The IRC config we are using.</param> public void Init(string pluginPath, IIrcConfig ircConfig) { MessageHandler handler = new MessageHandler( ".+", this.HandleMessage ); this.handlers.Add(handler); }
// ---------------- Functions ---------------- /// <summary> /// Loads the IRC config from the chaskis root. /// </summary> /// <param name="xmlFilePath">The path to the IRC config XML.</param> public void InitState1_LoadIrcConfig() { string ircConfigFile = Path.Combine(this.chaskisRoot, "IrcConfig.xml"); StaticLogger.Log.WriteLine("Using IRC config file '{0}'", ircConfigFile); this.ircConfig = XmlLoader.ParseIrcConfig(ircConfigFile); this.ircBot = new IrcBot(this.ircConfig, this.parsingQueue); }
// -------- Functions -------- /// <summary> /// Initializes the plugin. This includes loading any configuration files, /// starting services, etc. /// </summary> /// <param name="pluginPath">Path to the plugin.</param> /// <param name="ircConfig">The IRC config to use.</param> public void Init(string pluginPath, IIrcConfig ircConfig) { if (this.isLoaded == false) { this.handlers.Add(new JoinHandler(JoinMessage)); this.handlers.Add(new PartHandler(PartMessage)); this.isLoaded = true; } }
// -------- Functions -------- /// <summary> /// Initializes the plugin. /// </summary> /// <param name="pluginPath">The absolute path to the plugin dll.</param> /// <param name="ircConfig">The IRC config we are using.</param> public void Init(string pluginPath, IIrcConfig ircConfig) { MessageHandler handler = new MessageHandler( handlerRegex, MathHandler ); this.handlers.Add(handler); }
// ---------------- Functions ---------------- public void Init(PluginInitor initor) { this.chaskisEventCreator = initor.ChaskisEventCreator; this.eventSender = initor.ChaskisEventSender; this.ircConfig = initor.IrcConfig; this.logger = initor.Log; this.pluginDir = Path.Combine( initor.ChaskisConfigPluginRoot, "NewVersionNotifier" ); string configPath = Path.Combine( this.pluginDir, "NewVersionNotifierConfig.xml" ); this.config = XmlLoader.LoadConfig(configPath); this.cachedFilePath = Path.Combine( this.pluginDir, cacheFileName ); if (File.Exists(this.cachedFilePath) == false) { this.cachedVersion = string.Empty; } else { string[] lines = File.ReadAllLines(this.cachedFilePath); if (lines.Length == 0) { this.cachedVersion = string.Empty; } else { this.cachedVersion = lines[0].Trim(); } } ChaskisEventHandler eventHandler = this.chaskisEventCreator.CreatePluginEventHandler( "chaskis", this.HandleChaskisEvent ); this.ircHandlers.Add(eventHandler); JoinHandlerConfig joinHandlerConfig = new JoinHandlerConfig { JoinAction = this.OnJoinChannel, RespondToSelf = true }; JoinHandler joinHandler = new JoinHandler(joinHandlerConfig); this.ircHandlers.Add(joinHandler); }
public void TestValidXmlWithRateLimit() { this.ircConfig.RateLimit = 0; IIrcConfig config = XmlLoader.ParseIrcConfig( Path.Combine(testXmlFiles, "ValidIrcConfigWithNoRateLimit.xml") ); Assert.AreEqual(this.ircConfig, config); }
// -------- Constructor -------- /// <summary> /// Constructor. /// </summary> /// <param name="config">The config to wrap.</param> public ReadOnlyIrcConfig(IIrcConfig config) { ArgumentChecker.IsNotNull(config, nameof(config)); this.wrappedConfig = config; this.Channels = new List <string>(config.Channels).AsReadOnly(); this.BridgeBots = new ReadOnlyDictionary <string, string>(config.BridgeBots); this.Admins = new List <string>(config.Admins).AsReadOnly(); }
public void TestValidXmlWithNoPassword() { this.ircConfig.NickServPassword = string.Empty; IIrcConfig config = XmlLoader.ParseIrcConfig( Path.Combine(testXmlFiles, "ValidIrcConfigWithNoPassword.xml") ); Assert.AreEqual(this.ircConfig, config); }
/// <summary> /// Ensures the given IRCConfig is not valid. /// </summary> /// <param name="config">The config to check.</param> private void CheckNotValid( IrcConfig config ) { Assert.Throws<ValidationException>( () => config.Validate() ); ReadOnlyIrcConfig roConfig = new ReadOnlyIrcConfig( config.Clone() ); Assert.Throws<ValidationException>( () => roConfig.Validate() ); IIrcConfig iircConfig = config; Assert.Throws<ValidationException>( () => iircConfig.Validate() ); }
// -------- Functions -------- /// <summary> /// Loads the given list of plugins. /// Any errors are logged to the passed in logger. /// </summary> /// <param name="ircConfig">The irc config we are using.</param> /// <param name="errorLog">Where to log the errors. Default to Console.Out.</param> /// <param name="logFunction"> /// Action to take when we want to log something. /// Argument to action is the string to log. /// </param> public bool LoadPlugins( IList <AssemblyConfig> pluginList, IIrcConfig ircConfig, Action <string> infoLogFunction = null, Action <string> errorLogFunction = null ) { bool success = true; foreach (AssemblyConfig pluginConfig in pluginList) { try { Assembly dll = Assembly.LoadFrom(pluginConfig.AssemblyPath); Type type = dll.GetType(pluginConfig.ClassName); MethodInfo initFunction = type.GetMethod("Init"); // Make instance object instance = Activator.CreateInstance(type); initFunction.Invoke(instance, new object[] { pluginConfig.AssemblyPath, ircConfig }); IPlugin plugin = (IPlugin)instance; // Use string.split, there's less bugs and edge-cases when trying to parse it out. string[] splitString = pluginConfig.ClassName.Split('.'); string name = splitString[splitString.Length - 1].ToLower(); this.plugins.Add(name, plugin); infoLogFunction?.Invoke("Successfully loaded plugin: " + pluginConfig.ClassName); } catch (Exception e) { errorLogFunction?.Invoke("*************"); errorLogFunction?.Invoke("Warning! Error when loading assembly " + pluginConfig.ClassName + ":"); errorLogFunction?.Invoke(e.Message); errorLogFunction?.Invoke(string.Empty); errorLogFunction?.Invoke(e.StackTrace); errorLogFunction?.Invoke(string.Empty); if (e.InnerException != null) { errorLogFunction?.Invoke("Inner Exception:"); errorLogFunction?.Invoke(e.InnerException.Message); errorLogFunction?.Invoke(e.InnerException.StackTrace); } errorLogFunction?.Invoke("*************"); success = false; } } return(success); }
public void TestValidXmlWithThreeChannelsAndPassword() { this.ircConfig.Channels.Add("#mychannel"); this.ircConfig.Channels.Add("#chaskis"); IIrcConfig config = XmlLoader.ParseIrcConfig( Path.Combine(testXmlFiles, "ValidIrcConfigWithThreeChannels.xml") ); Assert.AreEqual(this.ircConfig, config); }
public void TestValidXmlWithPasswordAndBridgeBots() { this.ircConfig.BridgeBots.Add("telegrambot", @"^(?<bridgeUser>\w+):\s+(?<bridgeMessage>.+)"); this.ircConfig.BridgeBots.Add("slackbot", @"^(?<bridgeUser>\w+)--(?<bridgeMessage>.+)"); IIrcConfig config = XmlLoader.ParseIrcConfig( Path.Combine(testXmlFiles, "ValidIrcConfigWithBridgeBots.xml") ); Assert.AreEqual(this.ircConfig, config); }
/// <summary> /// Checks to see if the given IIrcConfig object is the same /// as the given object. /// </summary> /// <param name="config1">The IIrcConfig object to check.</param> /// <param name="obj">The object to check.</param> /// <returns>True if the given object is equal to this one, else false.</returns> internal static bool Equals(IIrcConfig config1, object config2) { IIrcConfig other = config2 as IIrcConfig; if (other == null) { return(false); } return(Equals(config1, other)); }
// -------- Functions -------- /// <summary> /// Initializes the plugin. /// </summary> /// <param name="pluginPath">The absolute path to the plugin dll.</param> /// <param name="ircConfig">The IRC config we are using.</param> public void Init(string pluginPath, IIrcConfig ircConfig) { AllHandler handler = new AllHandler( delegate(IIrcWriter writer, IrcResponse response) { Console.WriteLine(response.Message); Console.Out.Flush(); } ); this.handlers.Add(handler); }
// -------- Functions -------- /// <summary> /// Inits this plugin. /// </summary> /// <param name="pluginPath">Path to the plugin DLL</param> /// <param name="ircConfig">The IRC config being used.</param> public void Init(string pluginPath, IIrcConfig ircConfig) { ArgumentChecker.StringIsNotNullOrEmpty(pluginPath, nameof(pluginPath)); ArgumentChecker.IsNotNull(ircConfig, nameof(ircConfig)); string configPath = Path.Combine( Path.GetDirectoryName(pluginPath), "ServerDiagnosticsConfig.xml" ); ServerDiagnosticsConfig config = XmlLoader.LoadConfig(configPath); if (string.IsNullOrEmpty(config.UpTimeCmd) == false) { MessageHandler utimeHandler = new MessageHandler( config.UpTimeCmd.Replace("{%nick%}", ircConfig.Nick), HandleUpTimeCmd, coolDown ); this.handlerList.Add(utimeHandler); } if (string.IsNullOrEmpty(config.OsVersionCmd) == false) { MessageHandler osHandler = new MessageHandler( config.OsVersionCmd.Replace("{%nick%}", ircConfig.Nick), HandleOsVersionCmd, coolDown ); this.handlerList.Add(osHandler); } if (string.IsNullOrEmpty(config.ProcessorCountCmd) == false) { MessageHandler procCoundHandler = new MessageHandler( config.ProcessorCountCmd.Replace("{%nick%}", ircConfig.Nick), HandleProcessorCountCmd, coolDown ); this.handlerList.Add(procCoundHandler); } if (string.IsNullOrEmpty(config.TimeCmd) == false) { MessageHandler timeHandler = new MessageHandler( config.TimeCmd.Replace("{%nick%}", ircConfig.Nick), HandleTimeCmd, coolDown ); this.handlerList.Add(timeHandler); } }
// -------- Functions -------- /// <summary> /// Handles the event and the pong back to the server. /// </summary> /// <param name="line">The RAW line from IRC to check.</param> /// <param name="ircConfig">The irc config to use when parsing this line.</param> /// <param name="ircWriter">The way to write to the irc channel.</param> public void HandleEvent(string line, IIrcConfig ircConfig, IIrcWriter ircWriter) { ArgumentChecker.StringIsNotNullOrEmpty(line, nameof(line)); ArgumentChecker.IsNotNull(ircConfig, nameof(ircConfig)); ArgumentChecker.IsNotNull(ircWriter, nameof(ircWriter)); Match match = pattern.Match(line); if (match.Success) { ircWriter.SendPong(match.Groups["response"].Value); } }
/// <summary> /// Gets the hash code of the IRC config object. /// </summary> /// <param name="config">The config to get the hash code of.</param> /// <returns>The hash code of the IRC config object.</returns> internal static int GetHashCode(IIrcConfig config) { return (config.Server.GetHashCode() + config.Channel.GetHashCode() + config.Port.GetHashCode() + config.UserName.GetHashCode() + config.Nick.GetHashCode() + config.RealName.GetHashCode() + config.Password.GetHashCode() + config.QuitMessage.GetHashCode() + config.BridgeBots.GetHashCode()); }
public void TestValidXmlWithAdmins() { this.ircConfig.Admins.Add("person1"); this.ircConfig.Admins.Add("person2"); this.ircConfig.UseSsl = true; IIrcConfig config = XmlLoader.ParseIrcConfig( Path.Combine(testXmlFiles, "ValidIrcConfigWithAdmins.xml") ); Assert.AreEqual(this.ircConfig, config); }
// -------- Functions -------- /// <summary> /// Handles the event. /// </summary> /// <param name="line">The RAW line from IRC to check.</param> /// <param name="ircConfig">The irc config to use when parsing this line.</param> /// <param name="ircWriter">The way to write to the irc channel.</param> public void HandleEvent(string line, IIrcConfig ircConfig, IIrcWriter ircWriter) { ArgumentChecker.StringIsNotNullOrEmpty(line, nameof(line)); ArgumentChecker.IsNotNull(ircConfig, nameof(ircConfig)); ArgumentChecker.IsNotNull(ircWriter, nameof(ircWriter)); IrcResponse response = new IrcResponse( string.Empty, string.Empty, line ); this.AllAction(ircWriter, response); }
// -------- Constructor -------- /// <summary> /// Constructor. /// </summary> /// <param name="ircConfig">The irc config object to use. This will be cloned after being passed in.</param> /// <param name="parsingQueue">The global parsing queue we are using.</param> public IrcBot(IIrcConfig ircConfig, INonDisposableStringParsingQueue parsingQueue) { ArgumentChecker.IsNotNull(ircConfig, nameof(ircConfig)); ArgumentChecker.IsNotNull(parsingQueue, nameof(parsingQueue)); this.ircConfig = ircConfig.Clone(); this.IrcConfig = new ReadOnlyIrcConfig(this.ircConfig); IrcConnection connection = new IrcConnection(ircConfig, parsingQueue); this.ircConnection = connection; this.parsingQueue = parsingQueue; }
public void TestValidXmlWithJustChannelAndServer() { // Our expected behavior is everything but channel and server to be defaults. IrcConfig expectedConfig = new IrcConfig(); expectedConfig.Server = this.ircConfig.Server; expectedConfig.Channel = this.ircConfig.Channel; IIrcConfig config = XmlLoader.ParseIrcConfig( Path.Combine(testXmlFiles, "ValidIrcConfigJustChannelServer.xml") ); Assert.AreEqual(expectedConfig, config); }
/// <summary> /// Converts an XML file to a list of handlers. /// </summary> /// <param name="rng"> /// Leave this null to use the default RNG, otherwise pass this in if you want to use your own (e.g. with a different seed) /// </param> public static IList <IIrcHandler> LoadXmlBotConfig(string file, IIrcConfig ircConfig, Random rng = null) { ArgumentChecker.IsNotNull(ircConfig, nameof(ircConfig)); if (File.Exists(file) == false) { throw new FileNotFoundException("Could not find XmlBotConfig file '" + file + '"'); } List <IIrcHandler> handlers = new List <IIrcHandler>(); XmlDocument doc = new XmlDocument(); doc.Load(file); XmlNode rootNode = doc.DocumentElement; if (rootNode.Name != rootXmlElementName) { throw new XmlException( "Root XML node should be named \"" + rootXmlElementName + "\". Got: " + rootNode.Name ); } foreach (XmlNode messageNode in rootNode.ChildNodes) { IIrcHandler handler = null; if (messageNode.Name.EqualsIgnoreCase("message")) { MessageHandlerConfig config = new MessageHandlerConfig(); config.Deserialize(messageNode, ircConfig, rng); handler = new MessageHandler(config); } else if (messageNode.Name.EqualsIgnoreCase("action")) { ActionHandlerConfig config = new ActionHandlerConfig(); config.Deserialze(messageNode, ircConfig, rng); handler = new ActionHandler(config); } if (handler != null) { handlers.Add(handler); } } return(handlers); }
/// <summary> /// Converts an XML node to a config object. /// </summary> /// <param name="rng"> /// Leave this null to use the default RNG, otherwise pass this in if you want to use your own (e.g. with a different seed) /// </param> public static void Deserialze( this ActionHandlerConfig actionConfig, XmlNode handlerNode, IIrcConfig ircConfig, Random rng = null ) { IReadOnlyList <string> responses = DeserializeBase(actionConfig, handlerNode); // I can not for the life of me figure out how to make this generic between this // and message... maybe we can't? ActionHandlerAction action = delegate(ActionHandlerArgs args) { HandleResponse(args, responses, ircConfig, rng); }; actionConfig.LineAction = action; }