Merge pull request #81 from RockyTV/channel-issues

Fix channel issues
This commit is contained in:
Drew DeVault 2017-08-25 21:08:21 -05:00 committed by GitHub
commit 7a3fa55e6d
10 changed files with 171 additions and 38 deletions

View File

@ -10,15 +10,15 @@ namespace ChatSharp.Handlers
{
public static void HandleJoin(IrcClient client, IrcMessage message)
{
var channel = client.Channels.GetOrAdd(message.Parameters[0]);
var user = client.Users.GetOrAdd(message.Prefix);
var channel = client.Channels.GetOrAdd(message.Parameters[0]);
if (channel != null)
{
if (!user.Channels.Contains(channel))
user.Channels.Add(channel);
client.OnUserJoinedChannel(new ChannelUserEventArgs(channel, new IrcUser(message.Prefix)));
client.OnUserJoinedChannel(new ChannelUserEventArgs(channel, user));
}
}
@ -48,39 +48,35 @@ namespace ChatSharp.Handlers
if (user.Channels.Contains(channel))
user.Channels.Remove(channel);
client.OnUserPartedChannel(new ChannelUserEventArgs(client.Channels[message.Parameters[0]],
new IrcUser(message.Prefix)));
if (user.ChannelModes.ContainsKey(channel))
user.ChannelModes.Remove(channel);
client.OnUserPartedChannel(new ChannelUserEventArgs(channel, user));
}
public static void HandleUserListPart(IrcClient client, IrcMessage message)
{
var channel = client.Channels[message.Parameters[2]];
var users = message.Parameters[3].Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var nick in users)
foreach (var rawNick in users)
{
if (string.IsNullOrWhiteSpace(nick))
if (string.IsNullOrWhiteSpace(rawNick))
continue;
var mode = client.ServerInfo.GetModeForPrefix(nick[0]);
if (mode == null)
{
var user = client.Users.GetOrAdd(nick);
if (!user.Channels.Contains(channel))
user.Channels.Add(channel);
if (!user.ChannelModes.ContainsKey(channel))
user.ChannelModes.Add(channel, null);
else
user.ChannelModes[channel] = null;
}
var nick = rawNick;
var modes = client.ServerInfo.GetModesForNick(nick);
if (modes.Count > 0)
nick = rawNick.Remove(0, modes.Count);
var user = client.Users.GetOrAdd(nick);
if (!user.Channels.Contains(channel))
user.Channels.Add(channel);
if (!user.ChannelModes.ContainsKey(channel))
user.ChannelModes.Add(channel, modes);
else
{
var user = client.Users.GetOrAdd(nick.Substring(1));
if (!user.Channels.Contains(channel))
user.Channels.Add(channel);
if (!user.ChannelModes.ContainsKey(channel))
user.ChannelModes.Add(channel, mode.Value);
else
user.ChannelModes[channel] = mode.Value;
}
user.ChannelModes[channel] = modes;
}
}

View File

@ -1,5 +1,6 @@
using ChatSharp.Events;
using System.Linq;
using System.Collections.Generic;
using System;
namespace ChatSharp.Handlers
@ -182,15 +183,16 @@ namespace ChatSharp.Handlers
new UserPoolView(channel.Users.Where(u =>
{
if (!u.ChannelModes.ContainsKey(channel))
u.ChannelModes.Add(channel, null);
return u.ChannelModes[channel] == c;
u.ChannelModes.Add(channel, new List<char?>());
return u.ChannelModes[channel].Contains(c);
})));
}
var user = new IrcUser(message.Parameters[i]);
if (add)
{
if (!channel.UsersByMode[c].Contains(user.Nick))
user.ChannelModes[channel] = c;
if (!user.ChannelModes[channel].Contains(c))
user.ChannelModes[channel].Add(c);
}
else
{

View File

@ -107,5 +107,34 @@ namespace ChatSharp
{
Client.ChangeMode(Name, change);
}
/// <summary>
/// True if this channel is equal to another (compares names).
/// </summary>
/// <returns></returns>
public bool Equals(IrcChannel other)
{
return other.Name == Name;
}
/// <summary>
/// True if this channel is equal to another (compares names).
/// </summary>
/// <returns></returns>
public override bool Equals(object obj)
{
if (obj is IrcChannel)
return Equals((IrcChannel)obj);
return false;
}
/// <summary>
/// Returns the hash code of the channel's name.
/// </summary>
/// <returns></returns>
public override int GetHashCode()
{
return Name.GetHashCode();
}
}
}

View File

@ -58,7 +58,6 @@ namespace ChatSharp
if (!Channels.Contains(channel))
throw new InvalidOperationException("Client is not present in channel.");
SendRawMessage("PART {0}", channel);
Channels.Remove(Channels[channel]);
}
/// <summary>
@ -69,7 +68,6 @@ namespace ChatSharp
if (!Channels.Contains(channel))
throw new InvalidOperationException("Client is not present in channel.");
SendRawMessage("PART {0} :{1}", channel, reason);
Channels.Remove(Channels[channel]);
}
/// <summary>

View File

@ -146,7 +146,6 @@ namespace ChatSharp
User = user;
ServerAddress = serverAddress;
Encoding = Encoding.UTF8;
Channels = new ChannelCollection(this);
Settings = new ClientSettings();
Handlers = new Dictionary<string, MessageHandler>();
MessageHandlers.RegisterDefaultHandlers(this);
@ -155,10 +154,11 @@ namespace ChatSharp
WriteQueue = new ConcurrentQueue<string>();
ServerInfo = new ServerInfo();
PrivmsgPrefix = "";
Channels = User.Channels = new ChannelCollection(this);
Users = new UserPool();
Users.Add(User); // Add self to user pool
Capabilities = new CapabilityPool();
Capabilities.AddRange(new string[] { "server-time" }); // List of supported capabilities
Capabilities.AddRange(new string[] { "server-time", "multi-prefix" }); // List of supported capabilities
}
/// <summary>

View File

@ -12,7 +12,7 @@ namespace ChatSharp
internal IrcUser()
{
Channels = new ChannelCollection();
ChannelModes = new Dictionary<IrcChannel, char?>();
ChannelModes = new Dictionary<IrcChannel, List<char?>>();
}
/// <summary>
@ -98,7 +98,7 @@ namespace ChatSharp
/// <value>The channels.</value>
public ChannelCollection Channels { get; set; }
internal Dictionary<IrcChannel, char?> ChannelModes { get; set; }
internal Dictionary<IrcChannel, List<char?>> ChannelModes { get; set; }
/// <summary>
/// This user's hostmask (nick!user@host).

View File

@ -1,3 +1,6 @@
using System.Collections.Generic;
using System.Linq;
namespace ChatSharp
{
/// <summary>
@ -8,7 +11,7 @@ namespace ChatSharp
internal ServerInfo()
{
// Guess for some defaults
Prefixes = new[] { "ov", "@+" };
Prefixes = new[] { "ovhaq", "@+%&~" };
SupportedChannelModes = new ChannelModes();
IsGuess = true;
}
@ -23,6 +26,35 @@ namespace ChatSharp
return Prefixes[0][Prefixes[1].IndexOf(prefix)];
}
/// <summary>
/// Gets the channel modes for a given user nick.
/// Returns an empty array if user has no modes.
/// </summary>
/// <returns></returns>
public List<char?> GetModesForNick(string nick)
{
var supportedPrefixes = Prefixes[1];
List<char?> modeList = new List<char?>();
List<char> nickPrefixes = new List<char>();
foreach (char prefix in supportedPrefixes)
{
if (nick.Contains(prefix))
{
nick.Remove(nick.IndexOf(prefix));
if (!nickPrefixes.Contains(prefix))
{
nickPrefixes.Add(prefix);
var mode = GetModeForPrefix(prefix);
if (!modeList.Contains(mode))
modeList.Add(mode);
}
}
}
return modeList;
}
/// <summary>
/// ChatSharp makes some assumptions about what the server supports in order to function properly.
/// If it has not recieved a 005 message giving it accurate information, this value will be true.
@ -97,7 +129,7 @@ namespace ChatSharp
ParameterizedSettings = "k";
OptionallyParameterizedSettings = "flj";
Settings = string.Empty;
ChannelUserModes = "vo"; // I have no idea what I'm doing here
ChannelUserModes = "vhoaq"; // I have no idea what I'm doing here
}
/// <summary>

View File

@ -9,7 +9,6 @@ namespace ChatSharp
/// </summary>
public class UserPoolView : IEnumerable<IrcUser>
{
private UserPool Pool { get; set; }
private IEnumerable<IrcUser> Users { get; set; }
internal UserPoolView(IEnumerable<IrcUser> users)

View File

@ -49,6 +49,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="IrcMessageTests.cs" />
<Compile Include="IrcUserTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>

View File

@ -0,0 +1,76 @@
using System;
using ChatSharp;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace ChatSharp.Tests
{
[TestClass]
public class IrcUserTests
{
[TestMethod]
public void GetUserModes_NotNull_FiveModes()
{
IrcUser user = new IrcUser("~&@%+aji", "user");
IrcClient client = new IrcClient("irc.address", user);
var userModes = client.ServerInfo.GetModesForNick(user.Nick);
Assert.IsTrue(userModes.Count == 5);
}
[TestMethod]
public void GetUserModes_NotNull_FourModes()
{
IrcUser user = new IrcUser("&@%+aji", "user");
IrcClient client = new IrcClient("irc.address", user);
var userModes = client.ServerInfo.GetModesForNick(user.Nick);
Assert.IsTrue(userModes.Count == 4);
}
[TestMethod]
public void GetUserModes_NotNull_ThreeModes()
{
IrcUser user = new IrcUser("@%+aji", "user");
IrcClient client = new IrcClient("irc.address", user);
var userModes = client.ServerInfo.GetModesForNick(user.Nick);
Assert.IsTrue(userModes.Count == 3);
}
[TestMethod]
public void GetUserModes_NotNull_TwoModes()
{
IrcUser user = new IrcUser("%+aji", "user");
IrcClient client = new IrcClient("irc.address", user);
var userModes = client.ServerInfo.GetModesForNick(user.Nick);
Assert.IsTrue(userModes.Count == 2);
}
[TestMethod]
public void GetUserModes_NotNull_OneMode()
{
IrcUser user = new IrcUser("+aji", "user");
IrcClient client = new IrcClient("irc.address", user);
var userModes = client.ServerInfo.GetModesForNick(user.Nick);
Assert.IsTrue(userModes.Count == 1);
}
[TestMethod]
public void GetUserModes_IsNull()
{
IrcUser user = new IrcUser("aji", "user");
IrcClient client = new IrcClient("irc.address", user);
var userModes = client.ServerInfo.GetModesForNick(user.Nick);
Assert.IsTrue(userModes.Count == 0);
}
}
}