Add complete support for server-time cap

This commit is contained in:
Alexandre Oliveira 2017-09-08 14:27:05 -03:00
parent 838a33e99a
commit e653691cf9
4 changed files with 143 additions and 1 deletions

View File

@ -164,7 +164,7 @@ namespace ChatSharp
Users.Add(User); // Add self to user pool
Capabilities = new CapabilityPool();
// List of supported capabilities
Capabilities.AddRange(new string[] { "server-time", "multi-prefix", "cap-notify" });
Capabilities.AddRange(new string[] { "server-time", "multi-prefix", "cap-notify", "znc.in/server-time", "znc.in/server-time-iso" });
IsNegotiatingCapabilities = false;
}

View File

@ -29,6 +29,10 @@ namespace ChatSharp
/// The message tags.
/// </summary>
public KeyValuePair<string, string>[] Tags { get; private set; }
/// <summary>
/// The message timestamp in ISO 8601 format.
/// </summary>
public Timestamp Timestamp { get; private set; }
/// <summary>
/// Initializes and decodes an IRC message, given the raw message from the server.
@ -98,6 +102,22 @@ namespace ChatSharp
Command = rawMessage;
Parameters = new string[0];
}
// Parse server-time message tag.
// Fallback to server-info if both znc.in/server-info and the former exists.
//
// znc.in/server-time tag
if (Tags.Any(tag => tag.Key == "t"))
{
var tag = Tags.SingleOrDefault(x => x.Key == "t");
Timestamp = new Timestamp(tag.Value, true);
}
// server-time tag
else if (Tags.Any(tag => tag.Key == "time"))
{
var tag = Tags.SingleOrDefault(x => x.Key == "time");
Timestamp = new Timestamp(tag.Value);
}
}
}
}

82
ChatSharp/Timestamp.cs Normal file
View File

@ -0,0 +1,82 @@
using System;
using System.Globalization;
namespace ChatSharp
{
/// <summary>
/// Represents a message timestamp received from a server.
/// </summary>
public class Timestamp
{
/// <summary>
/// A date representation of the timestamp.
/// </summary>
public DateTime Date { get; internal set; }
/// <summary>
/// A unix epoch representation of the timestamp.
/// </summary>
public double UnixTimestamp { get; internal set; }
/// <summary>
/// Initializes and parses the timestamp received from the server.
/// </summary>
/// <param name="date"></param>
/// <param name="compatibility">Enable pre-ZNC 1.0 compatibility. In previous versions of the tag,
/// servers sent a unix timestamp instead of a ISO 8601 string.</param>
internal Timestamp(string date, bool compatibility = false)
{
if (!compatibility)
{
DateTime parsedDate;
if (!DateTime.TryParseExact(date, @"yyyy-MM-dd\THH:mm:ss.fff\Z", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out parsedDate))
throw new ArgumentException("The date string was provided in an invalid format.", date);
Date = parsedDate;
UnixTimestamp = Date.Subtract(new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds;
}
else
{
double parsedTimestamp;
if (!double.TryParse(date, out parsedTimestamp))
throw new ArgumentException("The timestamp string was provided in an invalid format.", date);
UnixTimestamp = parsedTimestamp;
Date = (new DateTime(1970, 1, 1, 0, 0, 0).AddSeconds(UnixTimestamp));
}
}
/// <summary>
/// True if this timestamp is equal to another (compares unix timestamps).
/// </summary>
public bool Equals(Timestamp other)
{
return other.UnixTimestamp == UnixTimestamp;
}
/// <summary>
/// True if this timestamp is equal to another (compares unix timestamps).
/// </summary>
public override bool Equals(object obj)
{
if (obj is Timestamp)
return Equals((Timestamp)obj);
return false;
}
/// <summary>
/// Returns a ISO 8601 string representation of the timestamp.
/// </summary>
public string ToISOString()
{
return Date.ToString(@"yyyy-MM-dd\THH:mm:ss.fff\Z");
}
/// <summary>
/// Returns the hash code of the unix timestamp.
/// </summary>
public override int GetHashCode()
{
return UnixTimestamp.GetHashCode();
}
}
}

View File

@ -81,5 +81,45 @@ namespace ChatSharp.Tests
};
CollectionAssert.AreEqual(fromMessage.Tags, compareTags);
}
[TestMethod]
public void Timestamp_CompareISOString()
{
IrcMessage[] messages = {
new IrcMessage("@time=2011-10-19T16:40:51.620Z :Angel!angel@example.org PRIVMSG Wiz :Hello"),
new IrcMessage("@time=2012-06-30T23:59:59.419Z :John!~john@1.2.3.4 JOIN #chan")
};
string[] timestamps = {
"2011-10-19T16:40:51.620Z",
"2012-06-30T23:59:59.419Z"
};
Assert.AreEqual(messages[0].Timestamp.ToISOString(), timestamps[0]);
Assert.AreEqual(messages[1].Timestamp.ToISOString(), timestamps[1]);
}
[TestMethod]
public void Timestamp_FromTimestamp()
{
IrcMessage[] messages = {
new IrcMessage("@t=1504923966 :Angel!angel@example.org PRIVMSG Wiz :Hello"),
new IrcMessage("@t=1504923972 :John!~john@1.2.3.4 JOIN #chan")
};
string[] timestamps = {
"2017-09-09T02:26:06.000Z",
"2017-09-09T02:26:12.000Z"
};
Assert.AreEqual(messages[0].Timestamp.ToISOString(), timestamps[0]);
Assert.AreEqual(messages[1].Timestamp.ToISOString(), timestamps[1]);
}
[TestMethod]
public void Timestamp_FailOnLeap()
{
Assert.ThrowsException<ArgumentException>(() => new IrcMessage("@time=2012-06-30T23:59:60.419Z :John!~john@1.2.3.4 JOIN #chan"));
}
}
}