Move channel users into a shared user pool

This makes it so that there are never two user objects for any given
user on the network.
This commit is contained in:
Drew DeVault 2015-07-31 18:42:52 -04:00
parent bf74106ed8
commit 40389177f1
17 changed files with 232 additions and 353 deletions

View File

@ -1,42 +1,30 @@
 
Microsoft Visual Studio Solution File, Format Version 11.00 Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010 # Visual Studio 2010
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestChatSharp", "TestChatSharp\TestChatSharp.csproj", "{BCCCE45F-32D5-4A04-B526-7D5A5673895F}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChatSharp", "ChatSharp\ChatSharp.csproj", "{4033AFFA-BEA3-4BDF-84EA-59A23360FD36}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChatSharp", "ChatSharp\ChatSharp.csproj", "{4033AFFA-BEA3-4BDF-84EA-59A23360FD36}" Global
EndProject GlobalSection(SolutionConfigurationPlatforms) = preSolution
Global Debug|Any CPU = Debug|Any CPU
GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Mixed Platforms = Debug|Mixed Platforms
Debug|Any CPU = Debug|Any CPU Debug|x86 = Debug|x86
Debug|Mixed Platforms = Debug|Mixed Platforms Release|Any CPU = Release|Any CPU
Debug|x86 = Debug|x86 Release|Mixed Platforms = Release|Mixed Platforms
Release|Any CPU = Release|Any CPU Release|x86 = Release|x86
Release|Mixed Platforms = Release|Mixed Platforms EndGlobalSection
Release|x86 = Release|x86 GlobalSection(ProjectConfigurationPlatforms) = postSolution
EndGlobalSection {4033AFFA-BEA3-4BDF-84EA-59A23360FD36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
GlobalSection(ProjectConfigurationPlatforms) = postSolution {4033AFFA-BEA3-4BDF-84EA-59A23360FD36}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4033AFFA-BEA3-4BDF-84EA-59A23360FD36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4033AFFA-BEA3-4BDF-84EA-59A23360FD36}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{4033AFFA-BEA3-4BDF-84EA-59A23360FD36}.Debug|Any CPU.Build.0 = Debug|Any CPU {4033AFFA-BEA3-4BDF-84EA-59A23360FD36}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{4033AFFA-BEA3-4BDF-84EA-59A23360FD36}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU {4033AFFA-BEA3-4BDF-84EA-59A23360FD36}.Debug|x86.ActiveCfg = Debug|Any CPU
{4033AFFA-BEA3-4BDF-84EA-59A23360FD36}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU {4033AFFA-BEA3-4BDF-84EA-59A23360FD36}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4033AFFA-BEA3-4BDF-84EA-59A23360FD36}.Debug|x86.ActiveCfg = Debug|Any CPU {4033AFFA-BEA3-4BDF-84EA-59A23360FD36}.Release|Any CPU.Build.0 = Release|Any CPU
{4033AFFA-BEA3-4BDF-84EA-59A23360FD36}.Release|Any CPU.ActiveCfg = Release|Any CPU {4033AFFA-BEA3-4BDF-84EA-59A23360FD36}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{4033AFFA-BEA3-4BDF-84EA-59A23360FD36}.Release|Any CPU.Build.0 = Release|Any CPU {4033AFFA-BEA3-4BDF-84EA-59A23360FD36}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{4033AFFA-BEA3-4BDF-84EA-59A23360FD36}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {4033AFFA-BEA3-4BDF-84EA-59A23360FD36}.Release|x86.ActiveCfg = Release|Any CPU
{4033AFFA-BEA3-4BDF-84EA-59A23360FD36}.Release|Mixed Platforms.Build.0 = Release|Any CPU EndGlobalSection
{4033AFFA-BEA3-4BDF-84EA-59A23360FD36}.Release|x86.ActiveCfg = Release|Any CPU GlobalSection(SolutionProperties) = preSolution
{BCCCE45F-32D5-4A04-B526-7D5A5673895F}.Debug|Any CPU.ActiveCfg = Debug|x86 HideSolutionNode = FALSE
{BCCCE45F-32D5-4A04-B526-7D5A5673895F}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 EndGlobalSection
{BCCCE45F-32D5-4A04-B526-7D5A5673895F}.Debug|Mixed Platforms.Build.0 = Debug|x86 EndGlobal
{BCCCE45F-32D5-4A04-B526-7D5A5673895F}.Debug|x86.ActiveCfg = Debug|x86
{BCCCE45F-32D5-4A04-B526-7D5A5673895F}.Debug|x86.Build.0 = Debug|x86
{BCCCE45F-32D5-4A04-B526-7D5A5673895F}.Release|Any CPU.ActiveCfg = Release|x86
{BCCCE45F-32D5-4A04-B526-7D5A5673895F}.Release|Mixed Platforms.ActiveCfg = Release|x86
{BCCCE45F-32D5-4A04-B526-7D5A5673895F}.Release|Mixed Platforms.Build.0 = Release|x86
{BCCCE45F-32D5-4A04-B526-7D5A5673895F}.Release|x86.ActiveCfg = Release|x86
{BCCCE45F-32D5-4A04-B526-7D5A5673895F}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -7,9 +7,13 @@ namespace ChatSharp
{ {
public class ChannelCollection : IEnumerable<IrcChannel> public class ChannelCollection : IEnumerable<IrcChannel>
{ {
internal ChannelCollection(IrcClient client) internal ChannelCollection()
{ {
Channels = new List<IrcChannel>(); Channels = new List<IrcChannel>();
}
internal ChannelCollection(IrcClient client) : this()
{
Client = client; Client = client;
} }
@ -30,7 +34,10 @@ namespace ChatSharp
public void Join(string name) public void Join(string name)
{ {
Client.JoinChannel(name); if (Client != null)
Client.JoinChannel(name);
else
throw new InvalidOperationException("Cannot make other users join channels.");
} }
public bool Contains(string name) public bool Contains(string name)
@ -57,6 +64,15 @@ namespace ChatSharp
} }
} }
internal IrcChannel GetOrAdd(string name)
{
if (this.Contains(name))
return this[name];
var channel = new IrcChannel(Client, name);
this.Add(channel);
return channel;
}
public IEnumerator<IrcChannel> GetEnumerator() public IEnumerator<IrcChannel> GetEnumerator()
{ {
return Channels.GetEnumerator(); return Channels.GetEnumerator();

View File

@ -9,6 +9,8 @@
<RootNamespace>ChatSharp</RootNamespace> <RootNamespace>ChatSharp</RootNamespace>
<AssemblyName>ChatSharp</AssemblyName> <AssemblyName>ChatSharp</AssemblyName>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
@ -69,10 +71,12 @@
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RequestManager.cs" /> <Compile Include="RequestManager.cs" />
<Compile Include="ServerInfo.cs" /> <Compile Include="ServerInfo.cs" />
<Compile Include="UserCollection.cs" />
<Compile Include="WhoIs.cs" /> <Compile Include="WhoIs.cs" />
<Compile Include="Events\KickEventArgs.cs" /> <Compile Include="Events\KickEventArgs.cs" />
<Compile Include="Events\NickChangedEventArgs.cs" /> <Compile Include="Events\NickChangedEventArgs.cs" />
<Compile Include="UserPool.cs" />
<Compile Include="UserPoolView.cs" />
<Compile Include="Events\UserEventArgs.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup /> <ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

View File

@ -6,11 +6,13 @@ namespace ChatSharp.Events
{ {
public IrcChannel Channel { get; set; } public IrcChannel Channel { get; set; }
public string Topic { get; set; } public string Topic { get; set; }
public string OldTopic { get; set; }
public ChannelTopicEventArgs(IrcChannel channel, string topic) public ChannelTopicEventArgs(IrcChannel channel, string oldTopic, string topic)
{ {
Channel = channel; Channel = channel;
Topic = topic; Topic = topic;
OldTopic = oldTopic;
} }
} }
} }

View File

@ -0,0 +1,15 @@
using System;
namespace ChatSharp.Events
{
public class UserEventArgs : EventArgs
{
public IrcUser User { get; set; }
public UserEventArgs(IrcUser user)
{
User = user;
}
}
}

View File

@ -10,86 +10,65 @@ namespace ChatSharp.Handlers
{ {
public static void HandleJoin(IrcClient client, IrcMessage message) public static void HandleJoin(IrcClient client, IrcMessage message)
{ {
IrcChannel channel = null; var channel = client.Channels.GetOrAdd(message.Parameters[0]);
if (client.User.Nick == new IrcUser(message.Prefix).Nick) var user = client.Users.GetOrAdd(message.Prefix);
{ user.Channels.Add(channel);
// We've joined this channel
channel = new IrcChannel(client, message.Parameters[0]);
client.Channels.Add(channel);
}
else
{
// Someone has joined a channel we're already in
channel = client.Channels[message.Parameters[0]];
channel.Users.Add(new IrcUser(message.Prefix));
}
if (channel != null) if (channel != null)
client.OnUserJoinedChannel(new ChannelUserEventArgs(channel, new IrcUser(message.Prefix))); client.OnUserJoinedChannel(new ChannelUserEventArgs(channel, new IrcUser(message.Prefix)));
} }
public static void HandleGetTopic(IrcClient client, IrcMessage message) public static void HandleGetTopic(IrcClient client, IrcMessage message)
{ {
IrcChannel channel = null; var channel = client.Channels.GetOrAdd(message.Parameters[1]);
string topic; var old = channel._Topic;
if (client.Channels.Contains(message.Parameters[1])) channel._Topic = message.Parameters[2];
{ client.OnChannelTopicReceived(new ChannelTopicEventArgs(channel, old, channel._Topic));
channel = client.Channels[message.Parameters[1]];
topic = message.Parameters[2];
channel.Topic = topic;
}
else
{
channel = new IrcChannel(client, message.Parameters[1]);
topic = message.Parameters[2];
}
client.OnChannelTopicReceived(new ChannelTopicEventArgs(channel, topic));
} }
public static void HandleGetEmptyTopic(IrcClient client, IrcMessage message) public static void HandleGetEmptyTopic(IrcClient client, IrcMessage message)
{ {
var channel = client.Channels[message.Parameters[1]]; var channel = client.Channels.GetOrAdd(message.Parameters[1]);
var topic = message.Parameters[2]; var old = channel._Topic;
client.OnChannelTopicReceived(new ChannelTopicEventArgs(channel, topic)); channel._Topic = message.Parameters[2];
client.OnChannelTopicReceived(new ChannelTopicEventArgs(channel, old, channel._Topic));
} }
public static void HandlePart(IrcClient client, IrcMessage message) public static void HandlePart(IrcClient client, IrcMessage message)
{ {
if (!client.Channels.Contains(message.Parameters[0])) if (!client.Channels.Contains(message.Parameters[0]))
return; // we already parted the channel, ignore return; // we aren't in this channel, ignore
if (client.User.Match(message.Prefix)) // We've parted this channel var user = client.Users.Get(message.Prefix);
client.Channels.Remove(client.Channels[message.Parameters[0]]); var channel = client.Channels[message.Parameters[0]];
else // Someone has parted a channel we're already in
{ if (user.Channels.Contains(channel))
var user = new IrcUser(message.Prefix).Nick; user.Channels.Remove(channel);
var channel = client.Channels[message.Parameters[0]]; client.OnUserPartedChannel(new ChannelUserEventArgs(client.Channels[message.Parameters[0]],
if (channel.Users.Contains(user)) new IrcUser(message.Prefix)));
channel.Users.Remove(user);
foreach (var mode in channel.UsersByMode)
{
if (mode.Value.Contains(user))
mode.Value.Remove(user);
}
client.OnUserPartedChannel(new ChannelUserEventArgs(client.Channels[message.Parameters[0]], new IrcUser(message.Prefix)));
}
} }
public static void HandleUserListPart(IrcClient client, IrcMessage message) public static void HandleUserListPart(IrcClient client, IrcMessage message)
{ {
var channel = client.Channels[message.Parameters[2]]; var channel = client.Channels[message.Parameters[2]];
var users = message.Parameters[3].Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries); var users = message.Parameters[3].Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var user in users) foreach (var nick in users)
{ {
if (string.IsNullOrWhiteSpace(user)) continue; if (string.IsNullOrWhiteSpace(nick))
var mode = client.ServerInfo.GetModeForPrefix(user[0]); continue;
var mode = client.ServerInfo.GetModeForPrefix(nick[0]);
if (mode == null) if (mode == null)
channel.Users.Add(new IrcUser(user)); {
var user = client.Users.GetOrAdd(nick);
user.Channels.Add(channel);
}
else else
{ {
channel.Users.Add(new IrcUser(user.Substring(1))); var user = client.Users.GetOrAdd(nick.Substring(1));
if (!channel.UsersByMode.ContainsKey(mode.Value)) user.Channels.Add(channel);
// TODO: User modes
/*if (!channel.UsersByMode.ContainsKey(mode.Value))
channel.UsersByMode.Add(mode.Value, new UserCollection()); channel.UsersByMode.Add(mode.Value, new UserCollection());
channel.UsersByMode[mode.Value].Add(new IrcUser(user.Substring(1))); channel.UsersByMode[mode.Value].Add(new IrcUser(nick.Substring(1)));*/
} }
} }
} }
@ -102,9 +81,9 @@ namespace ChatSharp.Handlers
{ {
try try
{ {
client.GetMode(channel.Name, c => Console.WriteLine(c.Mode)); client.GetMode(channel.Name, c => { /* no-op */ });
} }
catch { } catch { /* who cares */ }
} }
if (client.Settings.WhoIsOnJoin) if (client.Settings.WhoIsOnJoin)
{ {
@ -134,12 +113,8 @@ namespace ChatSharp.Handlers
client.Channels.Remove(client.Channels[message.Parameters[0]]); client.Channels.Remove(client.Channels[message.Parameters[0]]);
else else
{ {
if (channel.Users.Contains(message.Parameters[1])) if (kicked.Channels.Contains(channel))
channel.Users.Remove(message.Parameters[1]); kicked.Channels.Remove(channel);
foreach (var mode in channel.UsersByMode.Where(mode => mode.Value.Contains(message.Parameters[1])))
{
mode.Value.Remove(message.Parameters[1]);
}
} }
client.OnUserKicked(new KickEventArgs(channel, new IrcUser(message.Prefix), client.OnUserKicked(new KickEventArgs(channel, new IrcUser(message.Prefix),
kicked, message.Parameters[2])); kicked, message.Parameters[2]));

View File

@ -62,29 +62,13 @@ namespace ChatSharp.Handlers
public static void HandleNick(IrcClient client, IrcMessage message) public static void HandleNick(IrcClient client, IrcMessage message)
{ {
var ircUser = new IrcUser(message.Prefix); var user = client.Users.Get(message.Prefix);
var oldNick = user.Nick;
var oldNick = ircUser.Nick; user.Nick = message.Parameters[0];
var users = client
.Channels
.SelectMany(c => c.Users.Where(u => u.Nick.Equals(ircUser.Nick, StringComparison.OrdinalIgnoreCase)));
foreach (var user in users)
{
if (user != null)
{
user.Nick = message.Parameters[0];
}
}
if (client.User.Nick.Equals(ircUser.Nick, System.StringComparison.OrdinalIgnoreCase))
{
client.User.Nick = message.Parameters[0];
}
client.OnNickChanged(new NickChangedEventArgs client.OnNickChanged(new NickChangedEventArgs
{ {
User = ircUser, User = user,
OldNick = oldNick, OldNick = oldNick,
NewNick = message.Parameters[0] NewNick = message.Parameters[0]
}); });
@ -95,25 +79,8 @@ namespace ChatSharp.Handlers
var user = new IrcUser(message.Prefix); var user = new IrcUser(message.Prefix);
if (client.User.Nick != user.Nick) if (client.User.Nick != user.Nick)
{ {
var channels = client client.Users.Remove(user);
.Channels client.OnUserQuit(new UserEventArgs(user));
.Where(c => c.Users.Any(u => u.Nick.Equals(user.Nick)));
var users = channels
.SelectMany(c=> c.UsersByMode)
.Where(m => m.Value.Contains(user.Nick))
.Select(c => c.Value);
foreach (var userCollection in users)
{
userCollection.Remove(user.Nick);
}
foreach (var channel in channels)
{
channel.Users.Remove(user.Nick);
}
} }
} }
@ -209,6 +176,7 @@ namespace ChatSharp.Handlers
} }
else if (client.ServerInfo.SupportedChannelModes.ChannelUserModes.Contains(c)) else if (client.ServerInfo.SupportedChannelModes.ChannelUserModes.Contains(c))
{ {
/*
if (!channel.UsersByMode.ContainsKey(c)) channel.UsersByMode.Add(c, new UserCollection()); if (!channel.UsersByMode.ContainsKey(c)) channel.UsersByMode.Add(c, new UserCollection());
var user = new IrcUser(message.Parameters[i]); var user = new IrcUser(message.Parameters[i]);
if (add) if (add)
@ -221,6 +189,7 @@ namespace ChatSharp.Handlers
if (channel.UsersByMode[c].Contains(user.Nick)) if (channel.UsersByMode[c].Contains(user.Nick))
channel.UsersByMode[c].Remove(user); channel.UsersByMode[c].Remove(user);
} }
*/
client.OnModeChanged(new ModeChangeEventArgs(channel.Name, new IrcUser(message.Prefix), client.OnModeChanged(new ModeChangeEventArgs(channel.Name, new IrcUser(message.Prefix),
(add ? "+" : "-") + c.ToString() + " " + message.Parameters[i++])); (add ? "+" : "-") + c.ToString() + " " + message.Parameters[i++]));
} }

View File

@ -14,6 +14,14 @@ namespace ChatSharp.Handlers
whois.User.User = message.Parameters[2]; whois.User.User = message.Parameters[2];
whois.User.Hostname = message.Parameters[3]; whois.User.Hostname = message.Parameters[3];
whois.User.RealName = message.Parameters[5]; whois.User.RealName = message.Parameters[5];
if (client.Users.Contains(whois.User.Nick))
{
var user = client.Users[whois.User.Nick];
user.User = whois.User.User;
user.Hostname = whois.User.Hostname;
user.RealName = whois.User.RealName;
whois.User = user;
}
} }
} }
@ -55,9 +63,12 @@ namespace ChatSharp.Handlers
public static void HandleWhoIsEnd(IrcClient client, IrcMessage message) public static void HandleWhoIsEnd(IrcClient client, IrcMessage message)
{ {
var request = client.RequestManager.DequeueOperation("WHOIS " + message.Parameters[1]); var request = client.RequestManager.DequeueOperation("WHOIS " + message.Parameters[1]);
var whois = (WhoIs)request.State;
if (!client.Users.Contains(whois.User.Nick))
client.Users.Add(whois.User);
if (request.Callback != null) if (request.Callback != null)
request.Callback(request); request.Callback(request);
client.OnWhoIsReceived(new Events.WhoIsReceivedEventArgs((WhoIs) request.State)); client.OnWhoIsReceived(new Events.WhoIsReceivedEventArgs(whois));
} }
} }
} }

View File

@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
namespace ChatSharp namespace ChatSharp
{ {
@ -15,21 +16,20 @@ namespace ChatSharp
} }
set set
{ {
Client.SetTopic(Name, value);
_Topic = value; _Topic = value;
} }
} }
public string Name { get; internal set; } public string Name { get; internal set; }
public string Mode { get; internal set; } public string Mode { get; internal set; }
public UserCollection Users { get; set; } public UserPoolView Users { get; private set; }
public Dictionary<char, UserCollection> UsersByMode { get; set; }
internal IrcChannel(IrcClient client, string name) internal IrcChannel(IrcClient client, string name)
{ {
Client = client; Client = client;
Users = new UserCollection();
UsersByMode = new Dictionary<char, UserCollection>();
Name = name; Name = name;
Users = new UserPoolView(client.Users.Where(u => u.Channels.Contains(this)));
} }
public void Invite(string nick) public void Invite(string nick)
@ -54,7 +54,7 @@ namespace ChatSharp
public void Part(string reason) public void Part(string reason)
{ {
Client.PartChannel(Name); Client.PartChannel(Name); // TODO
} }
public void SendMessage(string message) public void SendMessage(string message)
@ -66,11 +66,5 @@ namespace ChatSharp
{ {
Client.ChangeMode(Name, change); Client.ChangeMode(Name, change);
} }
public void SetTopic(string topic)
{
Client.SetTopic(Name, topic);
Topic = topic;
}
} }
} }

View File

@ -74,6 +74,7 @@ namespace ChatSharp
public RequestManager RequestManager { get; set; } public RequestManager RequestManager { get; set; }
public ServerInfo ServerInfo { get; set; } public ServerInfo ServerInfo { get; set; }
public string PrivmsgPrefix { get; set; } public string PrivmsgPrefix { get; set; }
public UserPool Users { get; set; }
public IrcClient(string serverAddress, IrcUser user, bool useSSL = false) public IrcClient(string serverAddress, IrcUser user, bool useSSL = false)
{ {
@ -91,6 +92,8 @@ namespace ChatSharp
UseSSL = useSSL; UseSSL = useSSL;
WriteQueue = new ConcurrentQueue<string>(); WriteQueue = new ConcurrentQueue<string>();
PrivmsgPrefix = ""; PrivmsgPrefix = "";
Users = new UserPool();
Users.Add(User); // Add self to user pool
} }
public void ConnectAsync() public void ConnectAsync()
@ -370,17 +373,20 @@ namespace ChatSharp
{ {
if (UserKicked != null) UserKicked(this, e); if (UserKicked != null) UserKicked(this, e);
} }
public event EventHandler<WhoIsReceivedEventArgs> WhoIsReceived; public event EventHandler<WhoIsReceivedEventArgs> WhoIsReceived;
protected internal virtual void OnWhoIsReceived(WhoIsReceivedEventArgs e) protected internal virtual void OnWhoIsReceived(WhoIsReceivedEventArgs e)
{ {
if (WhoIsReceived != null) WhoIsReceived(this, e); if (WhoIsReceived != null) WhoIsReceived(this, e);
} }
public event EventHandler<NickChangedEventArgs> NickChanged; public event EventHandler<NickChangedEventArgs> NickChanged;
protected internal virtual void OnNickChanged(NickChangedEventArgs e) protected internal virtual void OnNickChanged(NickChangedEventArgs e)
{ {
if (NickChanged != null) NickChanged(this, e); if (NickChanged != null) NickChanged(this, e);
} }
public event EventHandler<UserEventArgs> UserQuit;
protected internal virtual void OnUserQuit(UserEventArgs e)
{
if (UserQuit != null) UserQuit(this, e);
}
} }
} }

View File

@ -7,9 +7,10 @@ namespace ChatSharp
{ {
internal IrcUser() internal IrcUser()
{ {
Channels = new ChannelCollection();
} }
public IrcUser(string host) public IrcUser(string host) : this()
{ {
if (!host.Contains("@") && !host.Contains("!")) if (!host.Contains("@") && !host.Contains("!"))
Nick = host; Nick = host;
@ -29,7 +30,7 @@ namespace ChatSharp
} }
} }
public IrcUser(string nick, string user) public IrcUser(string nick, string user) : this()
{ {
Nick = nick; Nick = nick;
User = user; User = user;
@ -53,6 +54,7 @@ namespace ChatSharp
public string Mode { get; internal set; } public string Mode { get; internal set; }
public string RealName { get; internal set; } public string RealName { get; internal set; }
public string Hostname { get; internal set; } public string Hostname { get; internal set; }
public ChannelCollection Channels { get; set; }
public string Hostmask public string Hostmask
{ {
@ -126,4 +128,10 @@ namespace ChatSharp
return Hostmask; return Hostmask;
} }
} }
internal class UserChannel
{
public string Modes { get; set; }
public IrcChannel Channel { get; set; }
}
} }

View File

@ -1,17 +1,28 @@
using System.Collections; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace ChatSharp namespace ChatSharp
{ {
public class UserCollection : IEnumerable<IrcUser> public class UserPool : IEnumerable<IrcUser>
{ {
internal UserCollection() private List<IrcUser> Users { get; set; }
internal UserPool()
{ {
Users = new List<IrcUser>(); Users = new List<IrcUser>();
} }
private List<IrcUser> Users { get; set; } public IrcUser this[string nick]
{
get
{
var user = Users.FirstOrDefault(u => u.Nick == nick);
if (user == null)
throw new KeyNotFoundException();
return user;
}
}
internal void Add(IrcUser user) internal void Add(IrcUser user)
{ {
@ -46,23 +57,21 @@ namespace ChatSharp
return Users.Any(u => u.Hostmask == user.Hostmask); return Users.Any(u => u.Hostmask == user.Hostmask);
} }
public IrcUser this[int index] internal IrcUser GetOrAdd(string prefix)
{ {
get var user = new IrcUser(prefix);
{ if (Contains(user.Nick))
return Users[index]; return this[user.Nick];
} Add(user);
return user;
} }
public IrcUser this[string nick] internal IrcUser Get(string prefix)
{ {
get var user = new IrcUser(prefix);
{ if (Contains(user.Nick))
var user = Users.FirstOrDefault(u => u.Nick == nick); return this[user.Nick];
if (user == null) throw new KeyNotFoundException();
throw new KeyNotFoundException();
return user;
}
} }
public IEnumerator<IrcUser> GetEnumerator() public IEnumerator<IrcUser> GetEnumerator()
@ -70,9 +79,9 @@ namespace ChatSharp
return Users.GetEnumerator(); return Users.GetEnumerator();
} }
IEnumerator IEnumerable.GetEnumerator() System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{ {
return GetEnumerator(); return GetEnumerator();
} }
} }
} }

52
ChatSharp/UserPoolView.cs Normal file
View File

@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace ChatSharp
{
public class UserPoolView
{
private UserPool Pool { get; set; }
private IEnumerable<IrcUser> Users { get; set; }
internal UserPoolView(IEnumerable<IrcUser> users)
{
Users = users;
}
public IrcUser this[string nick]
{
get
{
var user = Users.FirstOrDefault(u => u.Nick == nick);
if (user == null)
throw new KeyNotFoundException();
return user;
}
}
internal IrcUser this[int index]
{
get
{
return Users.ToList()[index];
}
}
public bool ContainsMask(string mask)
{
return Users.Any(u => u.Match(mask));
}
public bool Contains(string nick)
{
return Users.Any(u => u.Nick == nick);
}
public bool Contains(IrcUser user)
{
return Users.Any(u => u.Hostmask == user.Hostmask);
}
}
}

View File

@ -1,6 +0,0 @@
<?xml version="1.0"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>

View File

@ -1,62 +0,0 @@
using ChatSharp;
using System;
using System.Linq;
namespace TestChatSharp
{
class Program
{
static void Main(string[] args)
{
var client = new IrcClient("irc.freenode.net", new IrcUser("ChatSharp", "ChatSharp"));
client.NetworkError += (s, e) => Console.WriteLine("Error: " + e.SocketError);
client.RawMessageRecieved += (s, e) => Console.WriteLine("<< {0}", e.Message);
client.RawMessageSent += (s, e) => Console.WriteLine(">> {0}", e.Message);
client.UserMessageRecieved += (s, e) =>
{
if (e.PrivateMessage.Message.StartsWith(".join "))
client.Channels.Join(e.PrivateMessage.Message.Substring(6));
else if (e.PrivateMessage.Message.StartsWith(".list "))
{
var channel = client.Channels[e.PrivateMessage.Message.Substring(6)];
var list = channel.Users.Select(u => u.Nick).Aggregate((a, b) => a + "," + b);
client.SendMessage(list, e.PrivateMessage.User.Nick);
}
else if (e.PrivateMessage.Message.StartsWith(".whois "))
client.WhoIs(e.PrivateMessage.Message.Substring(7), null);
else if (e.PrivateMessage.Message.StartsWith(".raw "))
client.SendRawMessage(e.PrivateMessage.Message.Substring(5));
else if (e.PrivateMessage.Message.StartsWith(".mode "))
{
var parts = e.PrivateMessage.Message.Split(' ');
client.ChangeMode(parts[1], parts[2]);
}
else if (e.PrivateMessage.Message.StartsWith(".topic "))
{
string messageArgs = e.PrivateMessage.Message.Substring(7);
if (messageArgs.Contains(" "))
{
string channel = messageArgs.Substring(0, messageArgs.IndexOf(" "));
string topic = messageArgs.Substring(messageArgs.IndexOf(" ") + 1);
client.Channels[channel].SetTopic(topic);
}
else
{
string channel = messageArgs.Substring(messageArgs.IndexOf("#"));
client.GetTopic(channel);
}
}
};
client.ChannelMessageRecieved += (s, e) =>
{
Console.WriteLine("<{0}> {1}", e.PrivateMessage.User.Nick, e.PrivateMessage.Message);
};
client.ChannelTopicReceived += (s, e) =>
{
Console.WriteLine("Received topic for channel {0}: {1}", e.Channel.Name, e.Topic);
};
client.ConnectAsync();
while (true) ;
}
}
}

View File

@ -1,35 +0,0 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("TestChatSharp")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("TestChatSharp")]
[assembly: AssemblyCopyright("Copyright © 2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("4c6f3fb9-9e7b-4d83-bdc4-b810be5aa63f")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -1,67 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{BCCCE45F-32D5-4A04-B526-7D5A5673895F}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>TestChatSharp</RootNamespace>
<AssemblyName>TestChatSharp</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ChatSharp\ChatSharp.csproj">
<Project>{4033AFFA-BEA3-4BDF-84EA-59A23360FD36}</Project>
<Name>ChatSharp</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>