chatsharp/ChatSharp/IrcClient.cs

641 lines
22 KiB
C#
Raw Permalink Normal View History

2015-07-07 19:16:52 +00:00
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Net.Security;
using System.Net.Sockets;
using System.Text;
2013-04-09 21:19:48 +00:00
using System.Timers;
2022-04-12 20:14:48 +00:00
using ChatSharp.Events;
using ChatSharp.Handlers;
using ErrorEventArgs = ChatSharp.Events.ErrorEventArgs;
2013-04-09 21:19:48 +00:00
namespace ChatSharp
{
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// An IRC client.
2015-08-01 01:06:22 +00:00
/// </summary>
public sealed partial class IrcClient
2013-04-09 21:19:48 +00:00
{
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// A raw IRC message handler.
2015-08-01 01:06:22 +00:00
/// </summary>
2013-04-09 21:19:48 +00:00
public delegate void MessageHandler(IrcClient client, IrcMessage message);
2022-04-12 20:14:48 +00:00
private const int ReadBufferLength = 1024;
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Creates a new IRC client, but will not connect until ConnectAsync is called.
2015-08-01 01:06:22 +00:00
/// </summary>
2022-04-12 20:14:48 +00:00
/// <param name="serverAddress">Server address including port in the form of "hostname:port".</param>
/// <param name="user">The IRC user to connect as.</param>
/// <param name="useSSL">Connect with SSL if true.</param>
public IrcClient(string serverAddress, IrcUser user, bool useSSL = false)
2013-04-09 21:19:48 +00:00
{
2022-04-12 20:14:48 +00:00
User = user ?? throw new ArgumentNullException(nameof(user));
ServerAddress = serverAddress ?? throw new ArgumentNullException(nameof(serverAddress));
Encoding = Encoding.UTF8;
2024-04-19 04:24:48 +00:00
Settings = new ClientSettings();
Handlers = new Dictionary<string, MessageHandler>();
2022-04-12 20:14:48 +00:00
MessageHandlers.RegisterDefaultHandlers(this);
2024-04-19 04:24:48 +00:00
RequestManager = new RequestManager();
2022-04-12 20:14:48 +00:00
UseSSL = useSSL;
2024-04-19 04:24:48 +00:00
WriteQueue = new ConcurrentQueue<string>();
ServerInfo = new ServerInfo();
2022-04-12 20:14:48 +00:00
PrivmsgPrefix = "";
2024-04-19 04:24:48 +00:00
Channels = User.Channels = new ChannelCollection(this);
2022-04-12 20:14:48 +00:00
// Add self to user pool
2024-04-19 04:24:48 +00:00
Users = new UserPool { User };
Capabilities = new CapabilityPool();
2013-04-09 21:19:48 +00:00
2022-04-12 20:14:48 +00:00
// List of supported capabilities
Capabilities.AddRange(new[]
{
"server-time", "multi-prefix", "cap-notify", "znc.in/server-time", "znc.in/server-time-iso",
"account-notify", "chghost", "userhost-in-names", "sasl"
});
IsNegotiatingCapabilities = false;
IsAuthenticatingSasl = false;
2024-04-19 04:24:48 +00:00
RandomNumber = new Random();
}
2022-04-12 20:14:48 +00:00
private Dictionary<string, MessageHandler> Handlers { get; }
2017-10-03 19:58:29 +00:00
2022-04-12 20:14:48 +00:00
internal static Random RandomNumber { get; private set; }
2013-04-09 21:19:48 +00:00
private byte[] ReadBuffer { get; set; }
private int ReadBufferIndex { get; set; }
private string ServerHostname { get; set; }
private int ServerPort { get; set; }
private Timer PingTimer { get; set; }
2014-09-19 17:24:21 +00:00
private Socket Socket { get; set; }
2022-04-12 20:14:48 +00:00
private ConcurrentQueue<string> WriteQueue { get; }
2014-09-19 17:24:21 +00:00
private bool IsWriting { get; set; }
2013-04-09 21:19:48 +00:00
2015-08-01 01:06:22 +00:00
internal RequestManager RequestManager { get; set; }
internal string ServerNameFromPing { get; set; }
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// The address this client is connected to, or will connect to. Setting this
/// after the client is connected will not cause a reconnect.
2015-08-01 01:06:22 +00:00
/// </summary>
2013-04-09 21:19:48 +00:00
public string ServerAddress
{
2024-04-19 19:06:28 +00:00
get => $"{ServerHostname}:{ServerPort}";
2013-04-09 21:19:48 +00:00
internal set
{
2022-04-12 20:14:48 +00:00
var parts = value.Split(':');
2013-04-09 21:19:48 +00:00
if (parts.Length > 2 || parts.Length == 0)
throw new FormatException("Server address is not in correct format ('hostname:port')");
ServerHostname = parts[0];
2024-04-19 18:52:01 +00:00
ServerPort = parts.Length > 1 ? int.Parse(parts[1]) : 6667;
2013-04-09 21:19:48 +00:00
}
}
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// The low level TCP stream for this client.
2015-08-01 01:06:22 +00:00
/// </summary>
2014-09-19 17:24:21 +00:00
public Stream NetworkStream { get; set; }
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// If true, SSL will be used to connect.
2015-08-01 01:06:22 +00:00
/// </summary>
2022-04-12 20:14:48 +00:00
public bool UseSSL { get; }
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// If true, invalid SSL certificates are ignored.
2015-08-01 01:06:22 +00:00
/// </summary>
2015-01-05 12:53:39 +00:00
public bool IgnoreInvalidSSL { get; set; }
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// The character encoding to use for the connection. Defaults to UTF-8.
2015-08-01 01:06:22 +00:00
/// </summary>
/// <value>The encoding.</value>
2013-04-09 21:19:48 +00:00
public Encoding Encoding { get; set; }
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// The user this client is logged in as.
2015-08-01 01:06:22 +00:00
/// </summary>
/// <value>The user.</value>
2013-04-09 21:19:48 +00:00
public IrcUser User { get; set; }
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// The channels this user is joined to.
2015-08-01 01:06:22 +00:00
/// </summary>
2022-04-12 20:14:48 +00:00
public ChannelCollection Channels { get; }
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Settings that control the behavior of ChatSharp.
2015-08-01 01:06:22 +00:00
/// </summary>
2013-04-10 17:26:20 +00:00
public ClientSettings Settings { get; set; }
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Information about the server we are connected to. Servers may not send us this information,
/// but it's required for ChatSharp to function, so by default this is a guess. Handle
/// IrcClient.ServerInfoReceived if you'd like to know when it's populated with real information.
2015-08-01 01:06:22 +00:00
/// </summary>
2015-07-07 19:16:52 +00:00
public ServerInfo ServerInfo { get; set; }
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// A string to prepend to all PRIVMSGs sent. Many IRC bots prefix their messages with \u200B, to
/// indicate to other bots that you are a bot.
2015-08-01 01:06:22 +00:00
/// </summary>
2015-03-18 16:01:19 +00:00
public string PrivmsgPrefix { get; set; }
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// A list of users on this network that we are aware of.
2015-08-01 01:06:22 +00:00
/// </summary>
public UserPool Users { get; set; }
2022-04-12 20:14:48 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// A list of capabilities supported by the library, along with enabled and disabled capabilities
/// after negotiating with the server.
/// </summary>
public CapabilityPool Capabilities { get; set; }
2022-04-12 20:14:48 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Set to true when the client is negotiating IRC capabilities with the server.
/// If set to False, capability negotiation is finished.
/// </summary>
public bool IsNegotiatingCapabilities { get; internal set; }
2022-04-12 20:14:48 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Set to True when the client is authenticating with SASL.
/// If set to False, SASL authentication is finished.
/// </summary>
public bool IsAuthenticatingSasl { get; internal set; }
2013-04-09 21:19:48 +00:00
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Sets a custom handler for an IRC message. This applies to the low level IRC protocol,
/// not for private messages.
2015-08-01 01:06:22 +00:00
/// </summary>
2022-04-12 20:14:48 +00:00
public void SetHandler(string message, MessageHandler handler)
2013-04-09 21:19:48 +00:00
{
2022-04-12 20:14:48 +00:00
#if DEBUG
// This is the default behavior if 3rd parties want to handle certain messages themselves
// However, if it happens from our own code, we probably did something wrong
if (Handlers.ContainsKey(message.ToUpper()))
Console.WriteLine("Warning: {0} handler has been overwritten", message);
#endif
2024-04-19 19:06:28 +00:00
message = message.ToUpperInvariant();
2022-04-12 20:14:48 +00:00
Handlers[message] = handler;
}
2017-10-03 19:58:29 +00:00
2022-04-12 20:14:48 +00:00
internal static DateTime DateTimeFromIrcTime(int time)
{
return new DateTime(1970, 1, 1).AddSeconds(time);
2013-04-09 21:19:48 +00:00
}
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Connects to the IRC server.
2015-08-01 01:06:22 +00:00
/// </summary>
2013-04-09 21:19:48 +00:00
public void ConnectAsync()
{
2024-04-19 18:52:01 +00:00
if (Socket is { Connected: true })
2022-04-12 20:14:48 +00:00
throw new InvalidOperationException("Socket is already connected to server.");
2024-04-19 04:24:48 +00:00
Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
2013-04-09 21:19:48 +00:00
ReadBuffer = new byte[ReadBufferLength];
ReadBufferIndex = 0;
2024-04-19 04:24:48 +00:00
PingTimer = new Timer(30000);
PingTimer.Elapsed += (x, y) =>
{
if (!string.IsNullOrEmpty(ServerNameFromPing))
SendRawMessage("PING :{0}", ServerNameFromPing);
};
2015-01-11 01:44:51 +00:00
var checkQueue = new Timer(1000);
2024-04-19 04:24:48 +00:00
checkQueue.Elapsed += (x, y) =>
2015-01-11 01:44:51 +00:00
{
2021-09-17 20:24:13 +00:00
if (!WriteQueue.IsEmpty)
2015-01-11 01:44:51 +00:00
{
2022-04-12 20:14:48 +00:00
string nextMessage;
while (!WriteQueue.TryDequeue(out nextMessage))
{
}
2015-01-11 01:44:51 +00:00
SendRawMessage(nextMessage);
}
};
2015-07-07 19:16:52 +00:00
checkQueue.Start();
2015-05-10 02:11:38 +00:00
Socket.BeginConnect(ServerHostname, ServerPort, ConnectComplete, null);
2013-04-09 21:19:48 +00:00
}
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Send a QUIT message with a reason and disconnect.
2015-08-01 01:06:22 +00:00
/// </summary>
2024-04-19 19:06:28 +00:00
public void Quit(string reason = null)
2013-09-26 01:35:10 +00:00
{
if (reason == null)
SendRawMessage("QUIT");
else
SendRawMessage("QUIT :{0}", reason);
2014-09-19 17:24:21 +00:00
Socket.BeginDisconnect(false, ar =>
{
Socket.EndDisconnect(ar);
NetworkStream.Dispose();
NetworkStream = null;
}, null);
2013-09-26 01:35:10 +00:00
PingTimer.Dispose();
}
2013-06-02 22:55:53 +00:00
2013-04-09 21:19:48 +00:00
private void ConnectComplete(IAsyncResult result)
{
try
{
Socket.EndConnect(result);
NetworkStream = new NetworkStream(Socket);
if (UseSSL)
{
2024-04-19 18:52:01 +00:00
NetworkStream = IgnoreInvalidSSL
? new SslStream(NetworkStream, false, (a, b, c, d) => true)
: new SslStream(NetworkStream);
((SslStream)NetworkStream).AuthenticateAsClient(ServerHostname);
}
2014-09-19 17:24:21 +00:00
2019-02-05 22:56:52 +00:00
NetworkStream.BeginRead(ReadBuffer, ReadBufferIndex, ReadBuffer.Length, DataReceived, null);
// Begin capability negotiation
SendRawMessage("CAP LS 302");
// Write login info
if (!string.IsNullOrEmpty(User.Password))
SendRawMessage("PASS {0}", User.Password);
SendRawMessage("NICK {0}", User.Nick);
// hostname, servername are ignored by most IRC servers
SendRawMessage("USER {0} hostname servername :{1}", User.User, User.RealName);
PingTimer.Start();
}
catch (SocketException e)
2014-09-19 17:24:21 +00:00
{
2024-04-19 04:24:48 +00:00
OnNetworkError(new SocketErrorEventArgs(e.SocketErrorCode));
}
catch (Exception e)
{
2024-04-19 04:24:48 +00:00
OnError(new ErrorEventArgs(e));
2014-09-19 17:24:21 +00:00
}
2013-04-09 21:19:48 +00:00
}
2019-02-05 22:56:52 +00:00
private void DataReceived(IAsyncResult result)
2013-04-09 21:19:48 +00:00
{
2014-09-19 17:24:21 +00:00
if (NetworkStream == null)
{
2024-04-19 04:24:48 +00:00
OnNetworkError(new SocketErrorEventArgs(SocketError.NotConnected));
2014-09-19 17:24:21 +00:00
return;
}
int length;
try
2013-04-09 21:19:48 +00:00
{
2014-09-19 17:24:21 +00:00
length = NetworkStream.EndRead(result) + ReadBufferIndex;
}
catch (IOException e)
{
2021-09-17 20:24:13 +00:00
if (e.InnerException is SocketException socketException)
2024-04-19 04:24:48 +00:00
OnNetworkError(new SocketErrorEventArgs(socketException.SocketErrorCode));
2014-09-19 17:24:21 +00:00
else
throw;
2013-04-09 21:19:48 +00:00
return;
}
2014-09-19 17:24:21 +00:00
2013-04-09 21:19:48 +00:00
ReadBufferIndex = 0;
while (length > 0)
{
2022-04-12 20:14:48 +00:00
var messageLength = Array.IndexOf(ReadBuffer, (byte)'\n', 0, length);
2013-04-09 21:19:48 +00:00
if (messageLength == -1) // Incomplete message
{
ReadBufferIndex = length;
break;
}
2022-04-12 20:14:48 +00:00
2013-04-09 21:19:48 +00:00
messageLength++;
var message = Encoding.GetString(ReadBuffer, 0, messageLength - 2); // -2 to remove \r\n
HandleMessage(message);
Array.Copy(ReadBuffer, messageLength, ReadBuffer, 0, length - messageLength);
length -= messageLength;
}
2022-04-12 20:14:48 +00:00
NetworkStream.BeginRead(ReadBuffer, ReadBufferIndex, ReadBuffer.Length - ReadBufferIndex, DataReceived,
null);
2013-04-09 21:19:48 +00:00
}
private void HandleMessage(string rawMessage)
{
2024-04-19 04:24:48 +00:00
OnRawMessageReceived(new RawMessageEventArgs(rawMessage, false));
2013-04-09 21:19:48 +00:00
var message = new IrcMessage(rawMessage);
2024-04-19 19:08:19 +00:00
if (Handlers.TryGetValue(message.Command, out var handler)) handler(this, message);
2013-04-09 21:19:48 +00:00
}
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Send a raw IRC message. Behaves like /quote in most IRC clients.
2015-08-01 01:06:22 +00:00
/// </summary>
2013-04-09 21:19:48 +00:00
public void SendRawMessage(string message, params object[] format)
{
2014-09-19 17:24:21 +00:00
if (NetworkStream == null)
{
2024-04-19 04:24:48 +00:00
OnNetworkError(new SocketErrorEventArgs(SocketError.NotConnected));
2014-09-19 17:24:21 +00:00
return;
}
2013-04-09 21:19:48 +00:00
message = string.Format(message, format);
2024-04-19 19:06:28 +00:00
var data = Encoding.GetBytes($"{message}\r\n");
2014-09-19 17:24:21 +00:00
if (!IsWriting)
{
IsWriting = true;
2015-01-11 01:44:51 +00:00
NetworkStream.BeginWrite(data, 0, data.Length, MessageSent, message);
2014-09-19 17:24:21 +00:00
}
else
2015-01-11 01:44:51 +00:00
{
2014-09-19 17:24:21 +00:00
WriteQueue.Enqueue(message);
2015-01-11 01:44:51 +00:00
}
2013-04-09 21:19:48 +00:00
}
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Send a raw IRC message. Behaves like /quote in most IRC clients.
2015-08-01 01:06:22 +00:00
/// </summary>
2013-04-09 23:31:06 +00:00
public void SendIrcMessage(IrcMessage message)
2013-04-09 21:19:48 +00:00
{
2024-04-19 18:52:01 +00:00
SendRawMessage(message.Format());
2013-04-09 21:19:48 +00:00
}
private void MessageSent(IAsyncResult result)
{
2014-09-19 17:24:21 +00:00
if (NetworkStream == null)
{
2024-04-19 04:24:48 +00:00
OnNetworkError(new SocketErrorEventArgs(SocketError.NotConnected));
2015-01-11 01:44:51 +00:00
IsWriting = false;
2014-09-19 17:24:21 +00:00
return;
}
try
{
NetworkStream.EndWrite(result);
}
catch (IOException e)
{
2021-09-17 20:24:13 +00:00
if (e.InnerException is SocketException socketException)
2024-04-19 04:24:48 +00:00
OnNetworkError(new SocketErrorEventArgs(socketException.SocketErrorCode));
2014-09-19 17:24:21 +00:00
else
throw;
return;
}
2015-01-11 01:44:51 +00:00
finally
{
IsWriting = false;
}
2014-09-19 17:24:21 +00:00
2024-04-19 04:24:48 +00:00
OnRawMessageSent(new RawMessageEventArgs((string)result.AsyncState, true));
2014-09-19 17:24:21 +00:00
2021-09-17 20:24:13 +00:00
if (!WriteQueue.IsEmpty)
2015-01-11 01:44:51 +00:00
{
2024-04-19 19:06:28 +00:00
string nextMessage;
2022-04-12 20:14:48 +00:00
while (!WriteQueue.TryDequeue(out nextMessage))
{
}
2015-01-11 01:44:51 +00:00
SendRawMessage(nextMessage);
}
2013-04-09 21:19:48 +00:00
}
/// <summary>
2022-04-12 20:14:48 +00:00
/// IRC Error Replies. rfc1459 6.1.
/// </summary>
2022-04-12 20:14:48 +00:00
public event EventHandler<ErrorReplyEventArgs> ErrorReply;
internal void OnErrorReply(ErrorReplyEventArgs e)
{
2021-09-17 20:24:13 +00:00
ErrorReply?.Invoke(this, e);
}
2022-04-12 20:14:48 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Raised for errors.
/// </summary>
2022-04-12 20:14:48 +00:00
public event EventHandler<ErrorEventArgs> Error;
internal void OnError(ErrorEventArgs e)
{
2021-09-17 20:24:13 +00:00
Error?.Invoke(this, e);
}
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Raised for socket errors. ChatSharp does not automatically reconnect.
2015-08-01 01:06:22 +00:00
/// </summary>
2013-04-09 21:19:48 +00:00
public event EventHandler<SocketErrorEventArgs> NetworkError;
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
internal void OnNetworkError(SocketErrorEventArgs e)
2013-04-09 21:19:48 +00:00
{
2021-09-17 20:24:13 +00:00
NetworkError?.Invoke(this, e);
2013-04-09 21:19:48 +00:00
}
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Occurs when a raw message is sent.
2015-08-01 01:06:22 +00:00
/// </summary>
2013-04-09 21:19:48 +00:00
public event EventHandler<RawMessageEventArgs> RawMessageSent;
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
internal void OnRawMessageSent(RawMessageEventArgs e)
2013-04-09 21:19:48 +00:00
{
2021-09-17 20:24:13 +00:00
RawMessageSent?.Invoke(this, e);
2013-04-09 21:19:48 +00:00
}
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Occurs when a raw message received.
2015-08-01 01:06:22 +00:00
/// </summary>
2019-02-05 22:56:52 +00:00
public event EventHandler<RawMessageEventArgs> RawMessageReceived;
2022-04-12 20:14:48 +00:00
2019-02-05 22:56:52 +00:00
internal void OnRawMessageReceived(RawMessageEventArgs e)
2013-04-09 21:19:48 +00:00
{
2021-09-17 20:24:13 +00:00
RawMessageReceived?.Invoke(this, e);
2013-04-09 21:19:48 +00:00
}
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Occurs when a notice received.
2015-08-01 01:06:22 +00:00
/// </summary>
2019-02-05 22:56:52 +00:00
public event EventHandler<IrcNoticeEventArgs> NoticeReceived;
2022-04-12 20:14:48 +00:00
2019-02-05 22:56:52 +00:00
internal void OnNoticeReceived(IrcNoticeEventArgs e)
2013-04-09 23:24:50 +00:00
{
2021-09-17 20:24:13 +00:00
NoticeReceived?.Invoke(this, e);
2013-04-09 23:24:50 +00:00
}
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Occurs when the server has sent us part of the MOTD.
2015-08-01 01:06:22 +00:00
/// </summary>
2019-02-05 22:56:52 +00:00
public event EventHandler<ServerMOTDEventArgs> MOTDPartReceived;
2022-04-12 20:14:48 +00:00
2019-02-05 22:56:52 +00:00
internal void OnMOTDPartReceived(ServerMOTDEventArgs e)
2013-04-09 23:24:50 +00:00
{
2021-09-17 20:24:13 +00:00
MOTDPartReceived?.Invoke(this, e);
2013-04-09 23:24:50 +00:00
}
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Occurs when the entire server MOTD has been received.
2015-08-01 01:06:22 +00:00
/// </summary>
2019-02-05 22:56:52 +00:00
public event EventHandler<ServerMOTDEventArgs> MOTDReceived;
2022-04-12 20:14:48 +00:00
2019-02-05 22:56:52 +00:00
internal void OnMOTDReceived(ServerMOTDEventArgs e)
2013-04-09 23:24:50 +00:00
{
2021-09-17 20:24:13 +00:00
MOTDReceived?.Invoke(this, e);
2013-04-09 23:24:50 +00:00
}
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Occurs when a private message received. This can be a channel OR a user message.
2015-08-01 01:06:22 +00:00
/// </summary>
2019-02-05 22:56:52 +00:00
public event EventHandler<PrivateMessageEventArgs> PrivateMessageReceived;
2022-04-12 20:14:48 +00:00
2019-02-05 22:56:52 +00:00
internal void OnPrivateMessageReceived(PrivateMessageEventArgs e)
2013-04-09 23:24:50 +00:00
{
2021-09-17 20:24:13 +00:00
PrivateMessageReceived?.Invoke(this, e);
2013-04-09 23:24:50 +00:00
}
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Occurs when a message is received in an IRC channel.
2015-08-01 01:06:22 +00:00
/// </summary>
2019-02-05 22:56:52 +00:00
public event EventHandler<PrivateMessageEventArgs> ChannelMessageReceived;
2022-04-12 20:14:48 +00:00
2019-02-05 22:56:52 +00:00
internal void OnChannelMessageReceived(PrivateMessageEventArgs e)
2013-04-09 23:24:50 +00:00
{
2021-09-17 20:24:13 +00:00
ChannelMessageReceived?.Invoke(this, e);
2013-04-09 23:24:50 +00:00
}
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Occurs when a message is received from a user.
2015-08-01 01:06:22 +00:00
/// </summary>
2019-02-05 22:56:52 +00:00
public event EventHandler<PrivateMessageEventArgs> UserMessageReceived;
2022-04-12 20:14:48 +00:00
2019-02-05 22:56:52 +00:00
internal void OnUserMessageReceived(PrivateMessageEventArgs e)
2013-04-09 23:24:50 +00:00
{
2021-09-17 20:24:13 +00:00
UserMessageReceived?.Invoke(this, e);
2013-04-09 23:24:50 +00:00
}
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Raised if the nick you've chosen is in use. By default, ChatSharp will pick a
2024-04-19 19:06:28 +00:00
/// random nick to use instead. Set ErroneousNickEventArgs.DoNotHandle to prevent this.
2015-08-01 01:06:22 +00:00
/// </summary>
2022-04-12 20:14:48 +00:00
public event EventHandler<ErroneousNickEventArgs> NickInUse;
internal void OnNickInUse(ErroneousNickEventArgs e)
2013-04-09 23:24:50 +00:00
{
2021-09-17 20:24:13 +00:00
NickInUse?.Invoke(this, e);
2013-04-09 23:24:50 +00:00
}
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Occurs when a user or channel mode is changed.
2015-08-01 01:06:22 +00:00
/// </summary>
public event EventHandler<ModeChangeEventArgs> ModeChanged;
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
internal void OnModeChanged(ModeChangeEventArgs e)
{
2021-09-17 20:24:13 +00:00
ModeChanged?.Invoke(this, e);
}
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Occurs when a user joins a channel.
2015-08-01 01:06:22 +00:00
/// </summary>
public event EventHandler<ChannelUserEventArgs> UserJoinedChannel;
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
internal void OnUserJoinedChannel(ChannelUserEventArgs e)
{
2021-09-17 20:24:13 +00:00
UserJoinedChannel?.Invoke(this, e);
}
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Occurs when a user parts a channel.
2015-08-01 01:06:22 +00:00
/// </summary>
public event EventHandler<ChannelUserEventArgs> UserPartedChannel;
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
internal void OnUserPartedChannel(ChannelUserEventArgs e)
{
2021-09-17 20:24:13 +00:00
UserPartedChannel?.Invoke(this, e);
}
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Occurs when we have received the list of users present in a channel.
2015-08-01 01:06:22 +00:00
/// </summary>
2019-02-05 22:56:52 +00:00
public event EventHandler<ChannelEventArgs> ChannelListReceived;
2022-04-12 20:14:48 +00:00
2019-02-05 22:56:52 +00:00
internal void OnChannelListReceived(ChannelEventArgs e)
{
2021-09-17 20:24:13 +00:00
ChannelListReceived?.Invoke(this, e);
2015-07-07 19:16:52 +00:00
}
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Occurs when we have received the topic of a channel.
2015-08-01 01:06:22 +00:00
/// </summary>
2015-04-06 22:10:06 +00:00
public event EventHandler<ChannelTopicEventArgs> ChannelTopicReceived;
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
internal void OnChannelTopicReceived(ChannelTopicEventArgs e)
2015-07-07 19:16:52 +00:00
{
2021-09-17 20:24:13 +00:00
ChannelTopicReceived?.Invoke(this, e);
}
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Occurs when the IRC connection is established and it is safe to begin interacting with the server.
2015-08-01 01:06:22 +00:00
/// </summary>
public event EventHandler<EventArgs> ConnectionComplete;
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
internal void OnConnectionComplete(EventArgs e)
{
2021-09-17 20:24:13 +00:00
ConnectionComplete?.Invoke(this, e);
}
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Occurs when we receive server info (such as max nick length).
2015-08-01 01:06:22 +00:00
/// </summary>
2019-02-05 22:56:52 +00:00
public event EventHandler<SupportsEventArgs> ServerInfoReceived;
2022-04-12 20:14:48 +00:00
2019-02-05 22:56:52 +00:00
internal void OnServerInfoReceived(SupportsEventArgs e)
{
2021-09-17 20:24:13 +00:00
ServerInfoReceived?.Invoke(this, e);
}
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Occurs when a user is kicked.
2015-08-01 01:06:22 +00:00
/// </summary>
2013-06-01 22:38:57 +00:00
public event EventHandler<KickEventArgs> UserKicked;
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
internal void OnUserKicked(KickEventArgs e)
2013-06-01 22:38:57 +00:00
{
2021-09-17 20:24:13 +00:00
UserKicked?.Invoke(this, e);
2015-07-07 19:16:52 +00:00
}
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Occurs when a WHOIS response is received.
2015-08-01 01:06:22 +00:00
/// </summary>
2015-07-07 19:16:52 +00:00
public event EventHandler<WhoIsReceivedEventArgs> WhoIsReceived;
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
internal void OnWhoIsReceived(WhoIsReceivedEventArgs e)
2015-07-07 19:16:52 +00:00
{
2021-09-17 20:24:13 +00:00
WhoIsReceived?.Invoke(this, e);
2015-07-07 19:16:52 +00:00
}
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Occurs when a user has changed their nick.
2015-08-01 01:06:22 +00:00
/// </summary>
2015-07-07 19:16:52 +00:00
public event EventHandler<NickChangedEventArgs> NickChanged;
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
internal void OnNickChanged(NickChangedEventArgs e)
2015-07-07 19:16:52 +00:00
{
2021-09-17 20:24:13 +00:00
NickChanged?.Invoke(this, e);
2013-06-01 22:38:57 +00:00
}
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Occurs when a user has quit.
2015-08-01 01:06:22 +00:00
/// </summary>
public event EventHandler<UserEventArgs> UserQuit;
2022-04-12 20:14:48 +00:00
2015-08-01 01:06:22 +00:00
internal void OnUserQuit(UserEventArgs e)
{
2021-09-17 20:24:13 +00:00
UserQuit?.Invoke(this, e);
}
2022-04-12 20:14:48 +00:00
2017-10-03 19:58:29 +00:00
/// <summary>
2022-04-12 20:14:48 +00:00
/// Occurs when a WHO (WHOX protocol) is received.
2017-10-03 19:58:29 +00:00
/// </summary>
public event EventHandler<WhoxReceivedEventArgs> WhoxReceived;
2022-04-12 20:14:48 +00:00
2017-10-03 19:58:29 +00:00
internal void OnWhoxReceived(WhoxReceivedEventArgs e)
{
WhoxReceived?.Invoke(this, e);
}
2013-04-09 21:19:48 +00:00
}
2022-04-12 20:14:48 +00:00
}