Skip to content

Commit

Permalink
Issue: #57
Browse files Browse the repository at this point in the history
Added SendPart events, which is fired when we part from a channel.
  • Loading branch information
xforever1313 committed Nov 1, 2020
1 parent 63f4acb commit 7deef00
Show file tree
Hide file tree
Showing 8 changed files with 482 additions and 23 deletions.
4 changes: 4 additions & 0 deletions Chaskis/ChaskisCore/Chaskis.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
<PackageReference Condition="$(NoDotNet)!=''" Include="NETStandard.Library" Version="2.0.3" />
</ItemGroup>

<ItemGroup>
<Folder Include="Handlers\SendPart\" />
</ItemGroup>

<PropertyGroup>
<PackageId>ChaskisCore</PackageId>
<Version>0.20.0</Version>
Expand Down
98 changes: 98 additions & 0 deletions Chaskis/ChaskisCore/Handlers/SendPart/SendPartEventArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
//
// 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.Collections.Generic;
using System.Xml.Linq;
using SethCS.Exceptions;
using SethCS.Extensions;

namespace Chaskis.Core
{
/// <summary>
/// Args that are passed into <see cref="SendPartEventHandler"/> when
/// the bot leaves a channel.
/// </summary>
public sealed class SendPartEventArgs : BaseCoreEventArgs
{
// ---------------- Fields ----------------

internal const string XmlRootName = "chaskis_SendPart_event";

// ---------------- Constructor ----------------

internal SendPartEventArgs() :
base()
{
this.Channel = null;
this.PartReason = null;
}

// ---------------- Properties ----------------

public IIrcWriter Writer { get; internal set; }

/// <summary>
/// The channel the bot left.
/// </summary>
public string Channel { get; internal set; }

/// <summary>
/// The reason they bot left the channel.
/// Set to <see cref="string."/> if there was no reason.
/// </summary>
public string PartReason { get; internal set; }

protected override string XmlElementName => XmlRootName;

protected override IEnumerable<XElement> ChildToXml()
{
return new List<XElement>
{
new XElement( "channel", this.Channel ),
new XElement( "reason", this.PartReason )
};
}
}

/// <summary>
/// Extensions to <see cref="SendPartEventArgs"/>
/// </summary>
internal static class SendPartEventArgsExtensions
{
public static SendPartEventArgs FromXml( string xmlString, IIrcWriter writer )
{
SendPartEventArgs args = new SendPartEventArgs
{
Writer = writer
};

XElement root = BaseCoreEventArgs.ParseXml( args, xmlString );
BaseCoreEventArgs.ParseBaseXml( args, root );

foreach( XElement child in root.Elements() )
{
if( "channel".EqualsIgnoreCase( child.Name.LocalName ) )
{
args.Channel = child.Value;
}
else if( "reason".EqualsIgnoreCase( child.Name.LocalName ) )
{
args.PartReason = child.Value;
}
}

if( ( args.Channel == null ) || ( args.PartReason == null ) )
{
throw new ValidationException(
$"Could not find all required properties when creating {nameof( SendPartEventArgs )}"
);
}

return args;
}
}
}
37 changes: 37 additions & 0 deletions Chaskis/ChaskisCore/Handlers/SendPart/SendPartEventConfig.cs
Original file line number Diff line number Diff line change
@@ -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 System.Collections.Generic;

namespace Chaskis.Core
{
/// <summary>
/// Event to configure <see cref="SendPartEventHandler"/>
/// </summary>
public sealed class SendPartEventConfig :
BaseCoreEvent<SendPartEventConfig, SendPartHandlerAction, SendPartEventArgs>
{
// ---------------- Constructor ----------------

public SendPartEventConfig()
{
}

// ---------------- Functions ----------------

public override SendPartEventConfig Clone()
{
return (SendPartEventConfig)this.MemberwiseClone();
}

protected override IEnumerable<string> ValidateChild()
{
// Nothing to validate.
return null;
}
}
}
41 changes: 41 additions & 0 deletions Chaskis/ChaskisCore/Handlers/SendPart/SendPartEventHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//
// 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.Text.RegularExpressions;

namespace Chaskis.Core
{
public delegate void SendPartHandlerAction( SendPartEventArgs args );

/// <summary>
/// Event that gets fired when the bot joins a server.
/// </summary>
public sealed class SendPartEventHandler : BaseCoreEventHandler<SendPartEventConfig>
{
// ---------------- Fields ----------------

private static readonly Regex regex = new Regex(
$@"^<{SendPartEventArgs.XmlRootName}>.+</{SendPartEventArgs.XmlRootName}>",
RegexOptions.ExplicitCapture | RegexOptions.Compiled | RegexOptions.IgnoreCase
);

// ---------------- Constructor ----------------

public SendPartEventHandler( SendPartEventConfig config ) :
base( config, regex )
{
}

// ---------------- Functions ----------------

protected override void HandleEventInternal( HandlerArgs args, Match match )
{
SendPartEventArgs connectionArgs = SendPartEventArgsExtensions.FromXml( args.Line, args.IrcWriter );
this.config.LineAction( connectionArgs );
}
}
}
40 changes: 17 additions & 23 deletions Chaskis/ChaskisCore/IrcConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
//

using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Sockets;
using System.Threading;
Expand Down Expand Up @@ -294,7 +293,7 @@ public void Connect()
Thread.Sleep( this.Config.RateLimit );
}

this.ReadEvent(
this.OnReadLine(
new FinishedJoiningChannelsEventArgs
{
Protocol = ChaskisEventProtocol.IRC,
Expand Down Expand Up @@ -488,7 +487,20 @@ public void SendPong( string response )
public void SendPart( string reason, string channel )
{
// TODO: Make reason string more smart if not specified.
string partString = string.Format( "PART {0} :{1}", channel, reason ?? this.Config.QuitMessage );
reason = reason ?? this.Config.QuitMessage;

this.OnReadLine(
new SendPartEventArgs
{
Channel = channel,
PartReason = reason,
Protocol = ChaskisEventProtocol.IRC,
Server = this.Config.Server,
Writer = this
}.ToXml()
);

string partString = string.Format( "PART {0} :{1}", channel, reason );
this.SendRawCmd( partString );
}

Expand Down Expand Up @@ -719,24 +731,6 @@ public void SendChaskisEvent( ChaskisEvent e )
this.OnReadLine( s );
}

private void AddCoreEvent( string eventStr )
{
ChaskisEvent e = new ChaskisEvent(
ChaskisEventSource.CORE,
ChaskisEventProtocol.IRC.ToString(),
string.Empty, // For BCAST
new Dictionary<string, string>()
{
["event_id"] = eventStr,
["server"] = this.Config.Server,
["nick"] = this.Config.Nick
},
null
);

this.SendChaskisEvent( e );
}

private void OnReadLine( string s )
{
this.ReadEvent?.Invoke( s );
Expand Down Expand Up @@ -844,7 +838,7 @@ private void AttemptReconnect()
timeoutMinutes++;
}

this.ReadEvent(
this.OnReadLine(
new ReconnectingEventArgs
{
Protocol = ChaskisEventProtocol.IRC,
Expand Down Expand Up @@ -919,7 +913,7 @@ private void WriterQueue_OnError( Exception err )

private void Watchdog_OnFailure()
{
this.ReadEvent(
this.OnReadLine(
new WatchdogFailedEventArgs
{
Protocol = ChaskisEventProtocol.IRC,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
//
// 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.Core;
using Moq;
using NUnit.Framework;
using SethCS.Exceptions;

namespace Chaskis.UnitTests.CoreTests.Handlers.SendPart
{
[TestFixture]
public class SendPartEventArgsTests
{
// ---------------- Fields ----------------

private const string channel = "#somechannel";
private const string reason = "Some Reason";
private const string server = "irc.somewhere.net";
private const ChaskisEventProtocol protocol = ChaskisEventProtocol.IRC;

private Mock<IIrcWriter> mockWriter;

// ---------------- Setup / Teardown ----------------

[SetUp]
public void TestSetup()
{
this.mockWriter = new Mock<IIrcWriter>( MockBehavior.Strict );
}

[TearDown]
public void TestTeardown()
{
this.mockWriter = null;
}

// ---------------- Tests ----------------

[Test]
public void XmlRoundTripTest()
{
SendPartEventArgs uut = new SendPartEventArgs
{
Protocol = protocol,
Server = server,
Writer = mockWriter.Object,

Channel = channel,
PartReason = reason
};
string xmlString = uut.ToXml();
SendPartEventArgs postXml = SendPartEventArgsExtensions.FromXml( xmlString, mockWriter.Object );

Console.WriteLine( xmlString );

Assert.AreEqual( uut.Server, postXml.Server );
Assert.AreEqual( uut.Protocol, postXml.Protocol );
Assert.AreSame( uut.Writer, postXml.Writer );
}

[Test]
public void InvalidXmlRootName()
{
string xmlString = $"<lol><server>{server}</server><protocol>{protocol}</protocol><channel>{channel}</channel><reason>{reason}</reason></lol>";

Assert.Throws<ValidationException>(
() => SendPartEventArgsExtensions.FromXml( xmlString, mockWriter.Object )
);
}

[Test]
public void MissingServerDuringXmlParsing()
{
string xmlString = $"<chaskis_sendpart_event><protocol>{protocol}</protocol><channel>{channel}</channel><reason>{reason}</reason></chaskis_sendpart_event>";

Assert.Throws<ValidationException>(
() => SendPartEventArgsExtensions.FromXml( xmlString, mockWriter.Object )
);
}

[Test]
public void MissingProtocolDuringXmlParsing()
{
string xmlString = $"<chaskis_sendpart_event><server>{server}</server><channel>{channel}</channel><reason>{reason}</reason></chaskis_sendpart_event>";

Assert.Throws<ValidationException>(
() => SendPartEventArgsExtensions.FromXml( xmlString, mockWriter.Object )
);
}

[Test]
public void MissingChannelDuringXmlParsing()
{
string xmlString = $"<chaskis_sendpart_event><server>{server}</server><protocol>{protocol}</protocol><reason>{reason}</reason></chaskis_sendpart_event>";

Assert.Throws<ValidationException>(
() => SendPartEventArgsExtensions.FromXml( xmlString, mockWriter.Object )
);
}

[Test]
public void MissingReasonDuringXmlParsing()
{
string xmlString = $"<chaskis_sendpart_event><server>{server}</server><protocol>{protocol}</protocol><channel>{channel}</channel></chaskis_sendpart_event>";

Assert.Throws<ValidationException>(
() => SendPartEventArgsExtensions.FromXml( xmlString, mockWriter.Object )
);
}
}
}
Loading

0 comments on commit 7deef00

Please sign in to comment.