public Task InvokeConnectHandler(MqttClientConnectedEventArgs args, CancellationToken token = default) { Delegate[] invocations = OnConnect?.GetInvocationList(); if (invocations == null) return Task.CompletedTask; Task[] tasks = new Task[invocations.Length]; for (int index = 0; index < invocations.Length; index++) { Delegate invocation = invocations[index]; tasks[index] = (Task)invocation.DynamicInvoke(args, token); } return Task.WhenAll(tasks); }
public IrcClient() { ServerInfo = new ServerInfoType(); Encoding = new System.Text.UTF8Encoding(false); Registered = false; LastMessage = DateTime.Now; Timeout = new TimeSpan(0, 5, 0); Connected = false; #region Register Delegates OnRawMessageReceived += ErrorHandler; // This one looks for ERROR messages OnRawMessageReceived += PingHandler; OnRawMessageReceived += NumericHandler; OnRawMessageReceived += PrivmsgHandler; OnRfcNumeric += (sender, source, numeric, target, other) => { if (numeric == 1 && OnConnect != null) { foreach (var d in OnConnect.GetInvocationList()) { Task.Run(() => d.DynamicInvoke(this)); } } }; OnRfcNumeric += (sender, source, numeric, target, other) => { if (numeric == 353 && OnNamesReply != null) { String[] words = other.Split(' '); String channel = words[1]; foreach (var d in OnNamesReply.GetInvocationList()) { Task.Run(() => d.DynamicInvoke(this, channel, other.Substring(other.IndexOf(':') + 1))); } } }; OnRfcNumeric += (sender, source, numeric, target, other) => { if (numeric == 5 && OnISupport != null) { Dictionary <String, String> parameters = new Dictionary <string, string>(); String[] tokens = other.Split(' '); foreach (String token in tokens) { int equalIndex = token.IndexOf('='); if (equalIndex >= 0) { parameters[token.Substring(0, equalIndex)] = token.Substring(equalIndex + 1); } else { parameters[token] = ""; } } foreach (var d in OnISupport.GetInvocationList()) { Task.Run(() => d.DynamicInvoke(this, parameters)); } } }; OnConnect += (sender) => { lock (channels) { channels.Clear(); } }; OnISupport += (sender, parameters) => { try { sender.ServerInfo.PREFIX = parameters["PREFIX"]; } catch (KeyNotFoundException) { }; try { sender.ServerInfo.CHANMODES = parameters["CHANMODES"]; } catch (KeyNotFoundException) { }; if (parameters.ContainsKey("UHNAMES")) { var task = SendRawMessage("PROTOCTL UHNAMES"); } if (parameters.ContainsKey("NAMESX")) { var task = SendRawMessage("PROTOCTL NAMESX"); } }; OnRawMessageReceived += (source, message) => { String[] tokens = message.Split(' '); if (OnRfcJoin != null && tokens.Length >= 3 && tokens[1].Equals("JOIN")) { foreach (var d in OnRfcJoin.GetInvocationList()) { Task.Run(() => d.DynamicInvoke(this, tokens[0].Replace(":", ""), tokens[2].Replace(":", ""))); } } }; OnRfcJoin += (sender, source, channellist) => { /// If the user joining is me, add it to the channel list. /// If we have a channel already, add the guy to it. foreach (String channelName in channellist.Split(',')) { Channel c = null; lock (channels) { channels.TryGetValue(channelName.ToLower(), out c); if (c == null && ChannelUser.GetNickFromFullAddress(source).Equals(Nick, StringComparison.CurrentCultureIgnoreCase)) { c = new Channel(channelName); channels[channelName.ToLower()] = c; } if (c != null) { ChannelUser u = new ChannelUser(source, c); c.Users[u.Nick.ToLower()] = u; } } } }; OnRawMessageReceived += (sender, message) => { String[] tokens = message.Split(' '); if (tokens.Length >= 5 && tokens[1].Equals("KICK")) { String source = tokens[0].Replace(":", ""), channel = tokens[2], target = tokens[3]; String reason = message.Substring(message.IndexOf(':', 1)); if (OnRfcKick != null) { foreach (var d in OnRfcKick.GetInvocationList()) { Task.Run(() => d.DynamicInvoke(this, source, target, channel, reason)); } } } }; // Catches a part OnRawMessageReceived += (sender, message) => { String[] tokens = message.Split(' '); if (OnRfcPart != null && tokens.Length >= 3 && tokens[1].Equals("PART")) { String reason = tokens.Length >= 4 ? message.Substring(message.IndexOf(':', 1)) : null; foreach (var d in OnRfcPart.GetInvocationList()) { Task.Run(() => d.DynamicInvoke(this, tokens[0].Replace(":", ""), tokens[2], reason)); } } }; OnRawMessageReceived += (sender, message) => { String[] tokens = message.Split(' '); if (tokens.Length >= 4 && tokens[1].Equals("MODE") && OnRfcMode != null) { foreach (var d in OnRfcMode.GetInvocationList()) { Task.Run(() => d.DynamicInvoke(sender, tokens[0].Replace(":", ""), tokens[2], message.Substring(message.IndexOf(tokens[2]) + tokens[2].Length + 1))); } } }; // On part, we should remove the nick from the channel. If it's US parting, we should remove the channel from channels OnRfcPart += (sender, source, channel, reason) => { Channel channelObject = null; lock (channels) { channels.TryGetValue(channel.ToLower(), out channelObject); if (channelObject != null) { if (ChannelUser.GetNickFromFullAddress(source).Equals(Nick, StringComparison.CurrentCultureIgnoreCase)) { channels.Remove(channel.ToLower()); } else { try { channelObject.Users.Remove(ChannelUser.GetNickFromFullAddress(source)); } catch (Exception) { } } } } }; OnRfcKick += (sender, source, target, channel, reason) => { Channel channelObject = null; channels.TryGetValue(channel.ToLower(), out channelObject); if (channelObject != null) { if (Nick.Equals(target, StringComparison.CurrentCultureIgnoreCase)) // If it's us, remove the channel { channels.Remove(channel.ToLower()); } else // else remove the nick from the channel { try { channelObject.Users.Remove(target.ToLower()); } catch (Exception) { } } } }; OnRawMessageReceived += (source, message) => { LastMessage = DateTime.Now; }; OnNamesReply += NamesReplyHandler; // Updates prefix list for users of a channel when modes are changed OnRfcMode += (sender, source, target, modes) => { Channel channel = null; channels.TryGetValue(target.ToLower(), out channel); if (channels == null) { return; } String[] tokens = modes.Split(' '); bool isSet = false; for (int modeIndex = 0, parameterIndex = 1; modeIndex < tokens[0].Length; ++modeIndex) { char mode = tokens[0][modeIndex]; if (mode == '+') { isSet = true; } else if (mode == '-') { isSet = false; } else if (ServerInfo.CHANMODES_parameterNever.Contains(mode)) { continue; } else if (ServerInfo.CHANMODES_paramaterToSet.Contains(mode)) { if (isSet) { ++parameterIndex; } else { continue; } } else { try { // If it's a user access mode if (ServerInfo.PREFIX_modes.Contains(mode)) { ChannelUser user = null; channel.Users.TryGetValue(tokens[parameterIndex].ToLower(), out user); if (user != null) { char prefix = ServerInfo.PREFIX_symbols[ServerInfo.PREFIX_modes.IndexOf(mode)]; if (isSet) { user.InsertPrefix(ServerInfo, target, prefix); } else { user.DeletePrefix(target, prefix); } } } } catch (Exception) { } finally { // These modes always have parameters so we need to always increase the index at the end ++parameterIndex; } } } }; OnRawMessageReceived += (sender, message) => { String[] tokens = message.Split(' '); if (tokens.Length >= 3 && tokens[1].Equals("NICK") && OnRfcNick != null) { foreach (var d in OnRfcNick.GetInvocationList()) { Task.Run(() => d.DynamicInvoke(sender, tokens[0].Replace(":", ""), tokens[2].Replace(":", ""))); } } }; OnRfcNick += (sender, source, newnick) => { String oldnick = ChannelUser.GetNickFromFullAddress(source).ToLower(); ChannelUser user = null; foreach (Channel c in channels.Values) { c.Users.TryGetValue(oldnick, out user); if (user != null) { user.Nick = newnick; c.Users.Remove(oldnick); c.Users[newnick] = user; } } }; OnRawMessageReceived += (sender, message) => { String[] tokens = message.Split(' '); if (tokens.Length >= 3 && OnRfcQuit != null && tokens[1].Equals("QUIT")) { foreach (var d in OnRfcQuit.GetInvocationList()) { Task.Run(() => d.DynamicInvoke(sender, tokens[0].Replace(":", ""), message.Substring(message.IndexOf(":", 1)))); } } }; OnRfcQuit += (sender, source, message) => { String nick = ChannelUser.GetNickFromFullAddress(source); foreach (Channel c in channels.Values) { try { c.Users.Remove(nick.ToLower()); } catch (Exception) { } } }; #endregion Register Delegates }