/// <summary> /// Tries to parse a string to get an IRC identity. /// /// IRC identities are formatted as nickname!username@hostname. /// </summary> /// <param name="string">The string to parse.</param> /// <param name="identity">The identity, or <c>null</c> if parsing fails.</param> /// <returns><c>true</c> if parsing completed successfully.</returns> public static bool TryParse(IrcString @string, out IrcIdentity identity) { IrcString[] parts; identity = null; if (@string == null) { goto invalid; } identity = new IrcIdentity(); parts = @string.Split((byte)'@'); if (parts.Length >= 2) { identity.Hostname = parts[1]; @string = parts[0]; } parts = @string.Split((byte)'!'); if (parts.Length >= 2) { identity.Username = parts[1]; @string = parts[0]; } identity.Nickname = @string; string errorMessage; if (!IrcValidation.ValidateIdentity(identity, out errorMessage)) { goto invalid; } return(true); invalid: identity = null; return(false); }
static IrcString CtcpEncode(IrcString command, IrcString[] parameters, bool escapeParameters) { return("\x1" + command + IrcString.Join("", parameters.Select(p => " " + (escapeParameters ? CtcpEscapeParameter(p) : p)).ToArray()) + "\x1"); }
/// <summary> /// Replies to a CTCP command from a user or channel. /// </summary> /// <param name="recipient">The user or channel to send the reply to.</param> /// <param name="command">The CTCP command.</param> /// <param name="parameters">The CTCP command reply parameters.</param> /// <param name="escapeParameters"> /// <c>true</c> to quote parameters with spaces in them, and escape backslashes and quotation marks. /// </param> public void CtcpReply(IrcString recipient, IrcString command, IrcString[] parameters, bool escapeParameters = true) { Throw.If.Null(recipient, "recipient").Null(command, "command").NullElements(parameters, "parameters"); Notice(recipient, CtcpEncode(command, parameters, escapeParameters)); }
/// <summary> /// Joins the specified channel. /// </summary> /// <param name="channel">The channel to join.</param> /// <param name="key">The channel key, or <c>null</c> if a key is unnecessary.</param> public void Join(IrcString channel, IrcString key = null) { Throw.If.Null(channel, "channel"); IrcCommand("JOIN", key != null ? new IrcString[2] { channel, key } : new IrcString[1] { channel }); }
/// <summary> /// Kicks the specified user from the channel. Channel operator access may be required. /// </summary> /// <param name="user">The user to kick.</param> /// <param name="channel">The channel to kick the user from.</param> /// <param name="reason">The reason the user was kicked, or <c>null</c> to give no reason.</param> public void Kick(IrcString user, IrcString channel, IrcString reason) { Throw.If.Null(user, "user").Null(channel, "channel"); IrcCommand("KICK", reason != null ? new IrcString[3] { channel, user, reason } : new IrcString[2] { channel, user }); }
/// <summary> /// Logs in to the server. /// </summary> /// <param name="username">A username. If you aren't using a password, this can be anything you want.</param> /// <param name="realname">Your real name, or some made up name.</param> /// <param name="nickname">The IRC nickname to use.</param> /// <param name="hostname">The hostname to send, or <c>null</c> to send a default value.</param> /// <param name="servername">The servername to send, or <c>null</c> to send a default value.</param> /// <param name="password">The connection password, or <c>null</c> to not use one.</param> public void LogIn(IrcString username, IrcString realname, IrcString nickname, IrcString hostname = null, IrcString servername = null, IrcString password = null) { Throw.If.Null(username, "username").Null(realname, "realname").Null(nickname, "nickname"); lock (SyncRoot) { if (password != null) { IrcCommand("PASS", password); } IrcCommand("NICK", nickname); IrcCommand("USER", username, hostname ?? "0", servername ?? "*", realname); } }
protected virtual void OnCtcpReplyReceived(IrcIdentity sender, IrcString recipient, IrcString command, IrcString[] parameters, IrcString rawParameter) { switch ((string)command) { case "PING": if (parameters.Length >= 1) { int timestamp; if (int.TryParse(parameters[0], out timestamp)) { int delay = CtcpPingGetTimeDifference(timestamp, CtcpPingGetTimestamp()); OnGotPingReply(new PingReplyEventArgs(sender, delay)); } } break; } }
static IrcString CtcpEscapeParameter(IrcString parameter) { parameter = new IrcString(parameter.SelectMany(@byte => { if (@byte == 0 || @byte == 1 || @byte == 13 || @byte == 10) { return(new byte[0]); } if (@byte == (byte)'\\' || @byte == (byte)'\"') { return(new[] { (byte)'\\', @byte }); } return(new[] { @byte }); }).ToArray()); return(parameter.Contains((byte)' ') ? "\"" + parameter + "\"" : parameter); }
protected virtual void OnCtcpCommandReceived(IrcIdentity sender, IrcString recipient, IrcString command, IrcString[] parameters, IrcString rawParameter) { switch ((string)command) { case "ACTION": OnGotChatAction(new ChatMessageEventArgs(sender, recipient, rawParameter)); break; case "DCC": if (parameters.Length >= 1) { OnDccCommandReceived(sender, recipient, parameters[0], parameters.Skip(1).ToArray()); } break; case "PING": if (parameters.Length >= 1 && !IrcValidation.IsChannelName(recipient)) { CtcpReply(sender.Nickname, "PING", new IrcString[] { parameters[0] }); } break; case "TIME": if (!IrcValidation.IsChannelName(recipient)) { CtcpReply(sender.Nickname, "TIME", new IrcString[] { CtcpTimeGetNow().ToString ("ddd MMM dd HH:mm:ss yyyy", DateTimeFormatInfo.InvariantInfo) }); } break; case "VERSION": if (!IrcValidation.IsChannelName(recipient)) { CtcpReply(sender.Nickname, "VERSION", new[] { ClientVersion }); } break; } }
/// <summary> /// Leaves the specified channel. /// </summary> /// <param name="channel">The channel to leave.</param> public void Leave(IrcString channel) { Throw.If.Null(channel, "channel"); IrcCommand("PART", channel); }
/// <summary> /// Changes the client's nickname. /// </summary> /// <param name="newName">The nickname to change to.</param> public void ChangeName(IrcString newName) { Throw.If.Null(newName, "newName"); IrcCommand("NICK", newName); }
/// <summary> /// Sends an action message to the specified user or channel. /// </summary> /// <param name="recipient">The user or channel to send the action message to.</param> /// <param name="message">The message to send.</param> public void ChatAction(IrcString recipient, IrcString message) { Throw.If.Null(recipient, "recipient").Null(message, "message"); CtcpCommand(recipient, "ACTION", new[] { message }, false); }
/// <summary> /// Sends a DCC command to the specified user or channel. /// </summary> /// <param name="recipient">The user or channel to send the command to.</param> /// <param name="command">The DCC command.</param> /// <param name="parameters">The DCC command parameters.</param> public void DccCommand(IrcString recipient, IrcString command, params IrcString[] parameters) { Throw.If.Null(recipient, "recipient").Null(command, "command").NullElements(parameters, "parameters"); CtcpCommand(recipient, "DCC", new[] { command }.Concat(parameters).ToArray()); }
/// <summary> /// Changes the channel topic. /// </summary> /// <param name="channel">The channel whose topic to change.</param> /// <param name="newTopic">The new channel topic.</param> public void ChangeChannelTopic(IrcString channel, IrcString newTopic) { Throw.If.Null(channel, "channel").Null(newTopic, "newTopic"); IrcCommand("TOPIC", channel, newTopic); }
/// <summary> /// Sends a notice to the specified user. /// </summary> /// <param name="recipient">The user to send the notice to.</param> /// <param name="message">The message to send.</param> public void Notice(IrcString recipient, string message) { Throw.If.Null(recipient, "recipient").Null(message, "message"); IrcCommand("NOTICE", recipient, message); }
/// <summary> /// Pings the specified user. /// </summary> /// <param name="userToPing">The user to ping.</param> public void Ping(IrcString userToPing) { Throw.If.Null(userToPing, "userToPing"); CtcpCommand(userToPing, "PING", new IrcString[] { CtcpPingGetTimestamp().ToString() }); }
/// <summary> /// Changes a channel or user's mode. /// </summary> /// <param name="target">The channel or user to change the mode of.</param> /// <param name="command">The mode change, for example +o or +v.</param> /// <param name="parameters">The mode change parameters.</param> public void Mode(IrcString target, IrcString command, params IrcString[] parameters) { Throw.If.Null(target, "target").Null(command, "command").NullElements(parameters, "parameters"); IrcCommand("MODE", new[] { target, command }.Concat(parameters).ToArray()); }
/// <summary> /// Sends a message to the specified user or channel. /// </summary> /// <param name="recipient">The user or channel to send the message to.</param> /// <param name="message">The message to send.</param> public void Message(IrcString recipient, IrcString message) { Throw.If.Null(recipient, "recipient").Null(message, "message"); IrcCommand("PRIVMSG", recipient, message); }
/// <summary> /// Constructs and sends an IRC command to the server. /// </summary> /// <param name="command">The command to send.</param> /// <param name="parameters">The command's parameters.</param> /// <returns><c>true</c> if the command was sent successfully.</returns> public bool IrcCommand(IrcString command, params IrcString[] parameters) { Throw.If.Null(command, "command").Null(parameters, "parameters"); return(IrcCommand(new IrcStatement(null, command, parameters))); }
static bool TryCtcpDecode(IrcString message, out IrcString command, out IrcString[] parameters, out IrcString rawParameter) { command = null; rawParameter = null; parameters = null; if (message.Length >= 2 && message[0] == 1 && message[message.Length - 1] == 1) { var args = message.Substring(1, message.Length - 2).Split((byte)' ', 2); command = args[0]; rawParameter = args.Length >= 2 ? args[1] : IrcString.Empty; var paramBytes = new List <List <byte> >(); int index = 0; bool escaped = false, quoted = false; for (int i = 0; i < rawParameter.Length; i++) { var @byte = rawParameter[i]; if (@byte == 0 || @byte == 1 || @byte == 13 || @byte == 10) { continue; } byte?value = null; if (escaped) { value = @byte; escaped = false; } else if (@byte == (byte)'\\') { escaped = true; } else if (@byte == (byte)'\"') { quoted = !quoted; } else if (@byte == (byte)' ') { if (quoted) { value = @byte; } else { index++; } } else { value = @byte; } if (value != null) { while (paramBytes.Count <= index) { paramBytes.Add(new List <byte>()); } paramBytes[index].Add((byte)value); } } parameters = paramBytes.Select(paramByte => new IrcString(paramByte.ToArray())).ToArray(); return(true); } return(false); }
/// <summary> /// Invites the specified user to the channel. Channel operator access /// may be required. /// </summary> /// <param name="user">The user to invite.</param> /// <param name="channel">The channel to invite the user to.</param> public void Invite(IrcString user, IrcString channel) { Throw.If.Null(user, "user").Null(channel, "channel"); IrcCommand("INVITE", user, channel); }
protected virtual void OnDccCommandReceived(IrcIdentity sender, IrcString recipient, IrcString command, IrcString[] parameters) { }
/// <summary> /// This command is used to query information about particular user. /// </summary> /// <param name="recipient">The user to query.</param> public void Whois(IrcString recipient) { Throw.If.Null(recipient, "recipient"); IrcCommand("WHOIS", recipient); }