diff --git a/Chaskis/ChaskisCore/Handlers/AnyChaskisEvent/AnyChaskisEventHandler.cs b/Chaskis/ChaskisCore/Handlers/AnyChaskisEvent/AnyChaskisEventHandler.cs
new file mode 100644
index 00000000..cc321ac7
--- /dev/null
+++ b/Chaskis/ChaskisCore/Handlers/AnyChaskisEvent/AnyChaskisEventHandler.cs
@@ -0,0 +1,97 @@
+//
+// Copyright Seth Hendrick 2016-2020.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+using System.Text.RegularExpressions;
+using SethCS.Exceptions;
+
+namespace Chaskis.Core
+{
+ public delegate void AnyChaskisEventHandlerAction( AnyChaskisEventHandlerArgs args );
+
+ ///
+ /// This class will fire for ALL chaskis events that are triggered.
+ ///
+ /// Note, this should really only be used when you want to get ALL output
+ /// from the chaskis event without any filtering. Really only meant to be used for debugging.
+ ///
+ public sealed class AnyChaskisEventHandler : IIrcHandler
+ {
+ // ---------------- Fields ----------------
+
+ private readonly AnyChaskisEventHandlerConfig config;
+
+ private static readonly Regex chaskisEventRegex = new Regex(
+ @"^
+ /// The action to take when ANY message appears from IRC (JOIN, PART, PRIVMSG, PING, etc).
+ /// As far as the passed in IrcResponse to the action goes, the channel and remote user
+ /// will be String.Empty, since this class does no parsing of the IRC message.
+ /// It just grabs the line from the IRC channel and passes it into the AllAction
+ /// with no parsing. It is up to the AllAction to parse the channel and user
+ /// name if they so desire.
+ ///
+ public AnyChaskisEventHandlerAction LineAction
+ {
+ get
+ {
+ return this.config.LineAction;
+ }
+ }
+
+ ///
+ /// Whether or not the handler should keep handling or not.
+ /// Set to true to keep handling the event when it appears in the chat.
+ /// Set to false so when the current IRC message is finished processing being,
+ /// it leaves the event queue and never
+ /// happens again. Useful for events that only need to happen once.
+ ///
+ /// This is a public get/set. Either classes outside of the handler can
+ /// tell the handler to cancel the event, or it can cancel itself.
+ ///
+ /// Note: when this is set to false, there must be one more IRC message that appears
+ /// before it is removed from the queue.
+ ///
+ /// Defaulted to true.
+ ///
+ public bool KeepHandling { get; set; }
+
+ // ---------------- Functions ----------------
+
+ ///
+ /// Handles the event.
+ ///
+ public void HandleEvent( HandlerArgs args )
+ {
+ ArgumentChecker.IsNotNull( args, nameof( args ) );
+
+ if( chaskisEventRegex.IsMatch( args.Line ) == false )
+ {
+ return;
+ }
+
+ AnyChaskisEventHandlerArgs allArgs = new AnyChaskisEventHandlerArgs( args.IrcWriter, args.Line );
+ this.LineAction( allArgs );
+ }
+ }
+}
\ No newline at end of file
diff --git a/Chaskis/ChaskisCore/Handlers/AnyChaskisEvent/AnyChaskisEventHandlerArgs.cs b/Chaskis/ChaskisCore/Handlers/AnyChaskisEvent/AnyChaskisEventHandlerArgs.cs
new file mode 100644
index 00000000..c4b46aac
--- /dev/null
+++ b/Chaskis/ChaskisCore/Handlers/AnyChaskisEvent/AnyChaskisEventHandlerArgs.cs
@@ -0,0 +1,35 @@
+//
+// Copyright Seth Hendrick 2020.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+namespace Chaskis.Core
+{
+ ///
+ /// Arguments that are passed in when is triggered.
+ ///
+ public class AnyChaskisEventHandlerArgs
+ {
+ // ---------------- Constructor ----------------
+
+ public AnyChaskisEventHandlerArgs( IIrcWriter writer, string line )
+ {
+ this.Writer = writer;
+ this.Line = line;
+ }
+
+ // ---------------- Properties ----------------
+
+ ///
+ /// The Writer to use so we can respond to the chaskis event.
+ ///
+ public IIrcWriter Writer { get; private set; }
+
+ ///
+ /// The raw line that was read from the server.
+ ///
+ public string Line { get; private set; }
+ }
+}
diff --git a/Chaskis/ChaskisCore/Handlers/AnyChaskisEvent/AnyChaskisEventHandlerConfig.cs b/Chaskis/ChaskisCore/Handlers/AnyChaskisEvent/AnyChaskisEventHandlerConfig.cs
new file mode 100644
index 00000000..97da8e5a
--- /dev/null
+++ b/Chaskis/ChaskisCore/Handlers/AnyChaskisEvent/AnyChaskisEventHandlerConfig.cs
@@ -0,0 +1,57 @@
+//
+// Copyright Seth Hendrick 2018.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+using System.Text;
+using SethCS.Exceptions;
+
+namespace Chaskis.Core
+{
+ ///
+ /// Configuration used for
+ ///
+ public class AnyChaskisEventHandlerConfig
+ {
+ // ---------------- Constructor ----------------
+
+ public AnyChaskisEventHandlerConfig()
+ {
+ }
+
+ // ---------------- Properties ----------------
+
+ ///
+ /// The action to take when ANY chaskis event. It is up to this action to
+ /// actually parse the string.
+ ///
+ public AnyChaskisEventHandlerAction LineAction { get; set; }
+
+ // ---------------- Functions ----------------
+
+ public void Validate()
+ {
+ bool success = true;
+ StringBuilder errorString = new StringBuilder();
+ errorString.AppendLine( "Errors when validating " + nameof( AnyChaskisEventHandlerConfig ) );
+
+ if( this.LineAction == null )
+ {
+ success = false;
+ errorString.AppendLine( "\t- " + nameof( this.LineAction ) + " can not be null" );
+ }
+
+ if( success == false )
+ {
+ throw new ValidationException( errorString.ToString() );
+ }
+ }
+
+ public AnyChaskisEventHandlerConfig Clone()
+ {
+ return (AnyChaskisEventHandlerConfig)this.MemberwiseClone();
+ }
+ }
+}
diff --git a/Chaskis/ChaskisCore/Handlers/Receive/ReceiveHandler.cs b/Chaskis/ChaskisCore/Handlers/Receive/ReceiveHandler.cs
index 045c2a2d..a1d8c051 100644
--- a/Chaskis/ChaskisCore/Handlers/Receive/ReceiveHandler.cs
+++ b/Chaskis/ChaskisCore/Handlers/Receive/ReceiveHandler.cs
@@ -5,6 +5,7 @@
// http://www.boost.org/LICENSE_1_0.txt)
//
+using System.Text.RegularExpressions;
using SethCS.Exceptions;
namespace Chaskis.Core
@@ -26,6 +27,11 @@ public sealed class ReceiveHandler : IIrcHandler
private readonly ReceiveHandlerConfig config;
+ private static readonly Regex chaskisEventRegex = new Regex(
+ @"^
+ /// So chaskis events show up in the logs.
+ ///
+ private void PrintChaskisEvent( AnyChaskisEventHandlerArgs args )
+ {
+ Console.WriteLine( args.Line );
+ }
}
}
diff --git a/Chaskis/UnitTests/CoreTests/Handlers/AnyChaskisEvent/AnyChaskisEventHandlerArgsTests.cs b/Chaskis/UnitTests/CoreTests/Handlers/AnyChaskisEvent/AnyChaskisEventHandlerArgsTests.cs
new file mode 100644
index 00000000..f22d52f8
--- /dev/null
+++ b/Chaskis/UnitTests/CoreTests/Handlers/AnyChaskisEvent/AnyChaskisEventHandlerArgsTests.cs
@@ -0,0 +1,37 @@
+//
+// Copyright Seth Hendrick 2020.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+using Chaskis.Core;
+using Moq;
+using NUnit.Framework;
+
+namespace Chaskis.UnitTests.CoreTests.Handlers.AnyChaskisEvent
+{
+ [TestFixture]
+ public class AnyChaskisEventHandlerArgsTests
+ {
+ // ---------------- Tests ----------------
+
+ ///
+ /// Ensures the properties get set correctly during construction.
+ ///
+ [Test]
+ public void ConstructorTest()
+ {
+ Mock writer = new Mock( MockBehavior.Strict );
+ const string line = "line";
+
+ AnyChaskisEventHandlerArgs uut = new AnyChaskisEventHandlerArgs(
+ writer.Object,
+ line
+ );
+
+ Assert.AreSame( writer.Object, uut.Writer );
+ Assert.AreEqual( line, uut.Line );
+ }
+ }
+}
diff --git a/Chaskis/UnitTests/CoreTests/Handlers/AnyChaskisEvent/AnyChaskisEventHandlerConfigTests.cs b/Chaskis/UnitTests/CoreTests/Handlers/AnyChaskisEvent/AnyChaskisEventHandlerConfigTests.cs
new file mode 100644
index 00000000..417f92a4
--- /dev/null
+++ b/Chaskis/UnitTests/CoreTests/Handlers/AnyChaskisEvent/AnyChaskisEventHandlerConfigTests.cs
@@ -0,0 +1,46 @@
+//
+// Copyright Seth Hendrick 2020.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+using Chaskis.Core;
+using NUnit.Framework;
+using SethCS.Exceptions;
+
+namespace Chaskis.UnitTests.CoreTests.Handlers.AnyChaskisEvent
+{
+ [TestFixture]
+ public class AnyChaskisEventHandlerConfigTests
+ {
+ // ---------------- Tests ----------------
+
+ ///
+ /// Ensures the Validate() function works as expected.
+ ///
+ [Test]
+ public void ValidateTest()
+ {
+ AnyChaskisEventHandlerConfig config = new AnyChaskisEventHandlerConfig();
+
+ config.LineAction = null;
+ Assert.Throws( () => config.Validate() );
+
+ config.LineAction = delegate ( AnyChaskisEventHandlerArgs args )
+ {
+ };
+
+ Assert.DoesNotThrow( () => config.Validate() );
+ }
+
+ [Test]
+ public void CloneTest()
+ {
+ AnyChaskisEventHandlerConfig config1 = new AnyChaskisEventHandlerConfig();
+ AnyChaskisEventHandlerConfig clone = config1.Clone();
+
+ Assert.AreNotSame( config1, clone );
+ }
+ }
+}
diff --git a/Chaskis/UnitTests/CoreTests/Handlers/AnyChaskisEvent/AnyChaskisEventHandlerTest.cs b/Chaskis/UnitTests/CoreTests/Handlers/AnyChaskisEvent/AnyChaskisEventHandlerTest.cs
new file mode 100644
index 00000000..771c61c7
--- /dev/null
+++ b/Chaskis/UnitTests/CoreTests/Handlers/AnyChaskisEvent/AnyChaskisEventHandlerTest.cs
@@ -0,0 +1,236 @@
+//
+// Copyright Seth Hendrick 2020.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+using System;
+using Chaskis.UnitTests.Common;
+using Chaskis.Core;
+using Moq;
+using NUnit.Framework;
+using SethCS.Exceptions;
+
+namespace Chaskis.UnitTests.CoreTests.Handlers.AnyChaskisEvent
+{
+ [TestFixture]
+ public class AnyChaskisEventHandlerTest
+ {
+ // -------- Fields --------
+
+ ///
+ /// Unit Under Test.
+ ///
+ private AnyChaskisEventHandler uut;
+
+ ///
+ /// Irc Config to use.
+ ///
+ private IrcConfig ircConfig;
+
+ ///
+ /// Mock IRC writer to use.
+ ///
+ private Mock ircWriter;
+
+ ///
+ /// The response AnyChaskisEventd from the event handler (if any).
+ ///
+ private AnyChaskisEventHandlerArgs responseReceived;
+
+ ///
+ /// A user.
+ ///
+ private const string remoteUser = "remoteuser";
+
+ // -------- Setup / Teardown --------
+
+ [SetUp]
+ public void TestSetup()
+ {
+ this.ircConfig = TestHelpers.GetTestIrcConfig();
+ this.ircWriter = new Mock( MockBehavior.Strict );
+ this.responseReceived = null;
+
+ AnyChaskisEventHandlerConfig allHandlerConfig = new AnyChaskisEventHandlerConfig
+ {
+ LineAction = this.AllFunction
+ };
+ this.uut = new AnyChaskisEventHandler( allHandlerConfig );
+ }
+
+ // -------- Tests --------
+
+ ///
+ /// Ensures that if a bad config is passed in, we throw an exception.
+ ///
+ [Test]
+ public void InvalidConfigTest()
+ {
+ Assert.Throws(
+ () => new AnyChaskisEventHandler( new AnyChaskisEventHandlerConfig() )
+ );
+ }
+
+ ///
+ /// Ensures that the class is created correctly.
+ ///
+ [Test]
+ public void ConstructionTest()
+ {
+ // Keep Handling should be true by default.
+ Assert.IsTrue( this.uut.KeepHandling );
+ }
+
+ ///
+ /// Ensurs everything that needs to throw argument null
+ /// exceptions does.
+ ///
+ [Test]
+ public void ArgumentNullTest()
+ {
+ Assert.Throws( () =>
+ new AnyChaskisEventHandler( null )
+ );
+
+ Assert.Throws( () =>
+ this.uut.HandleEvent( null )
+ );
+
+ Assert.IsNull( this.responseReceived ); // Ensure handler didn't get called.
+ }
+
+ ///
+ /// Ensures that if the bot parts, the event is not fired.
+ ///
+ [Test]
+ public void BotParts()
+ {
+ string ircString = TestHelpers.ConstructIrcString(
+ this.ircConfig.Nick,
+ PartHandler.IrcCommand,
+ this.ircConfig.Channels[0],
+ string.Empty
+ );
+
+ this.uut.HandleEvent( this.ConstructArgs( ircString ) );
+ Assert.IsNull( this.responseReceived );
+ }
+
+ ///
+ /// Ensures that if a PRIMSG appears, the event is not fired.
+ ///
+ [Test]
+ public void MessageCommandAppears()
+ {
+ string ircString = TestHelpers.ConstructIrcString(
+ remoteUser,
+ PrivateMessageHelper.IrcCommand,
+ this.ircConfig.Channels[0],
+ "A message"
+ );
+
+ this.uut.HandleEvent( this.ConstructArgs( ircString ) );
+ Assert.IsNull( this.responseReceived );
+ }
+
+ ///
+ /// Ensures that if a JOIN appears, the event is not fired.
+ ///
+ [Test]
+ public void JoinCommandAppears()
+ {
+ string ircString = TestHelpers.ConstructIrcString(
+ remoteUser,
+ JoinHandler.IrcCommand,
+ this.ircConfig.Channels[0],
+ string.Empty
+ );
+
+ this.uut.HandleEvent( this.ConstructArgs( ircString ) );
+ Assert.IsNull( this.responseReceived );
+ }
+
+ ///
+ /// Ensures that if a PING appears, the event is not fired.
+ ///
+ [Test]
+ public void PingAppears()
+ {
+ string ircString = TestHelpers.ConstructPingString( "12345" );
+ this.uut.HandleEvent( this.ConstructArgs( ircString ) );
+ Assert.IsNull( this.responseReceived );
+ }
+
+ [Test]
+ public void SendNoticeAppears()
+ {
+ SendNoticeEventArgs e = new SendNoticeEventArgs
+ {
+ Protocol = ChaskisEventProtocol.IRC,
+ Server = "irc.somewhere.net",
+ Writer = this.ircWriter.Object,
+
+ ChannelOrUser = "#channel",
+ Message = "A message"
+ };
+
+ string eventString = e.ToXml();
+ this.uut.HandleEvent( this.ConstructArgs( eventString ) );
+ this.CheckResponse( eventString );
+ }
+
+ [Test]
+ public void SendJoinAppears()
+ {
+ SendJoinEventArgs e = new SendJoinEventArgs
+ {
+ Protocol = ChaskisEventProtocol.IRC,
+ Server = "irc.somewhere.net",
+ Writer = this.ircWriter.Object
+ };
+
+ string eventString = e.ToXml();
+ this.uut.HandleEvent( this.ConstructArgs( eventString ) );
+ this.CheckResponse( eventString );
+ }
+
+ // -------- Test Helpers --------
+
+ ///
+ /// The function that is called
+ ///
+ /// The writer that can be written to.
+ /// The response from the server.
+ private void AllFunction( AnyChaskisEventHandlerArgs args )
+ {
+ Assert.AreSame( this.ircWriter.Object, args.Writer );
+ this.responseReceived = args;
+ }
+
+ ///
+ /// Ensures the bot responds accordingly.
+ ///
+ /// The raw string we expect.
+ private void CheckResponse( string rawString )
+ {
+ Assert.IsNotNull( this.responseReceived );
+
+ // Ensure its the raw string.
+ Assert.AreEqual( rawString, this.responseReceived.Line );
+ }
+
+ private HandlerArgs ConstructArgs( string line )
+ {
+ HandlerArgs args = new HandlerArgs
+ {
+ Line = line,
+ IrcWriter = this.ircWriter.Object,
+ IrcConfig = this.ircConfig
+ };
+
+ return args;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Chaskis/UnitTests/CoreTests/Handlers/Receive/ReceiveHandlerTest.cs b/Chaskis/UnitTests/CoreTests/Handlers/Receive/ReceiveHandlerTest.cs
index 438eaf24..7a503348 100644
--- a/Chaskis/UnitTests/CoreTests/Handlers/Receive/ReceiveHandlerTest.cs
+++ b/Chaskis/UnitTests/CoreTests/Handlers/Receive/ReceiveHandlerTest.cs
@@ -91,7 +91,7 @@ public void ConstructionTest()
public void ArgumentNullTest()
{
Assert.Throws( () =>
- new PartHandler( null )
+ new ReceiveHandler( null )
);
Assert.Throws( () =>
@@ -163,6 +163,25 @@ public void PingAppears()
this.CheckResponse( ircString );
}
+ [Test]
+ public void ChaskisEventAppears()
+ {
+ SendNoticeEventArgs e = new SendNoticeEventArgs
+ {
+ Protocol = ChaskisEventProtocol.IRC,
+ Server = "irc.somewhere.net",
+ Writer = this.ircWriter.Object,
+
+ ChannelOrUser = "#channel",
+ Message = "A message"
+ };
+
+ string eventString = e.ToXml();
+
+ this.uut.HandleEvent( this.ConstructArgs( eventString ) );
+ Assert.IsNull( this.responseReceived );
+ }
+
// -------- Test Helpers --------
///