public IRC() { RefreshList(); Client = new IrcClient(); Client.Encoding = new System.Text.UTF8Encoding(false); Client.OutgoingPolicies = OutgoingMessagePolicy.NoDuplicates; Client.Timeout = TimeSpan.FromSeconds(30); }
private void NamesReplyHandler(IrcClient sender, String channel, String names) { Channel channelObject = null; lock (_channels) { _channels.TryGetValue(channel.ToLower(), out channelObject); if (channelObject == null) channelObject = new Channel(channel); String[] namesArray = names.Split(' '); foreach (String name in namesArray) { if (String.IsNullOrEmpty(name)) continue; int nameStart = 0; for (nameStart = 0; sender.ServerInfo.PREFIX_symbols.Contains(name[nameStart]); ++nameStart) ; String justName = name.Substring(nameStart); ChannelUser user = null; channelObject.Users.TryGetValue(ChannelUser.GetNickFromFullAddress(justName), out user); if (user == null) { user = new ChannelUser(justName, channelObject); channelObject.Users[user.Nick.ToLower()] = user; /// If we are in the list, we need to be smart enough to add the channel to our list if it isnt there if (user.Nick.Equals(Nick, StringComparison.CurrentCultureIgnoreCase)) _channels[channelObject.Name.ToLower()] = channelObject; } for (int i = 0; i < nameStart; ++i) user.InsertPrefix(sender.ServerInfo, channel, name[i]); } } }
private void PrivmsgHandler(IrcClient sender, String message) { String[] words = message.Split(' '); if (words.Length >= 4 && OnRfcPrivmsg != null && words[1].Equals("PRIVMSG", StringComparison.CurrentCultureIgnoreCase)) { OnRfcPrivmsg(this, words[0], words[2], message.Substring(message.IndexOf(":", 1) + 1)); } }
/// <summary> /// Creates a new IRCEventThread. Only makes sense to do this once for each IRC instance /// </summary> /// <param name="client"></param> public IRCEventThread(IrcClient client) { Debug.Assert(client != null); Client = client; new Thread(ThreadStart).Start(); }
/// <summary> /// Inserts a prefix (mode symbol) into this client's prefix list for the given channel and svrInfo class (must have PREFIX_symbols set by server) /// </summary> /// <param name="svrInfo"></param> /// <param name="channelName"></param> /// <param name="prefix"></param> internal void InsertPrefix(IrcClient.ServerInfoType svrInfo, String channelName, char prefix) { String currentList; lock (prefixes) { if (prefixes.ToString().Contains(prefix)) return; else if (prefixes.Length == 0) prefixes.Append(prefix); else { if (svrInfo.PREFIX_symbols == null) throw new Exception("Internal IRCClient error: PREFIX_symbols is NULL"); if (!svrInfo.PREFIX_symbols.Contains(prefix)) throw new Exception("Internal IRCClient error: PREFIX_symbols does not contain prefix which was inserted: " + prefix); /// Find the first prefix in the current list (newList) whose value is less than this new prefix, and insert at that position /// Or append it to the end if we never find one for (int i = 0; i < prefixes.Length; ++i) { if (svrInfo.PREFIX_symbols.IndexOf(prefix) < svrInfo.PREFIX_symbols.IndexOf(prefixes[i])) { prefixes.Insert(i, prefix); break; } else if (i + 1 == prefixes.Length) // If we've reached the end and still haven't found one of lower value, then this one belongs at the end { prefixes.Append(prefix); return; } } } } }
/// <summary> /// Checks to see if the user has at least the given prefix SYMBOL (true if his highest prefix is higher or equal to this prefix) /// </summary> /// <param name="svr"></param> /// <param name="prefix"></param> /// <returns></returns> public bool AtLeast(IrcClient.ServerInfoType svr, char prefix) { int targetPosition = svr.PREFIX_symbols.IndexOf(prefix); if (targetPosition <= 0 || Prefixes.Length == 0) return false; int myPosition = svr.PREFIX_symbols.IndexOf(Prefixes[0]); if (myPosition < 0) return false; return myPosition <= targetPosition; }
private void OnConnect(IrcClient sender) { if (Config.OnConnectAction != null) { sender.SendRawMessage(Config.OnConnectAction).Wait(); } foreach (String channel in Config.IRCChannels) { sender.SendRawMessage("JOIN {0}", channel).Wait(); } }
private void OnRawMessageSent(IrcClient sender, String message) { Console.WriteLine("{0} --> {1}", DateTime.Now - startTime, message); }
private void OnRawMessageReceived(IrcClient sender, String message) { Console.WriteLine("{0} <-- {1}",DateTime.Now - startTime, message); }
private async void OnPrivmsg(IrcClient sender, String source, String target, String message) { // If its to me (the bot), then respond to source. Otherwise, respond to target (channel) String responseTarget = target.Equals(Client.Nick, StringComparison.CurrentCultureIgnoreCase) ? source.Substring(source.IndexOf(":") + 1, source.IndexOf("!") - (source.IndexOf(":") + 1)) : target; String lowerMessage = message.ToLower(); if (lowerMessage.StartsWith("!debug ") && message.Length > "!debug ".Length) { double m; Card c = LookupCard(lowerMessage.Substring("!debug ".Length).ToLower(), out m); if (c == null) { Message(responseTarget, "Card not found."); return; } Console.WriteLine("Source: {0}", c.XmlSource); Console.WriteLine(c.XmlData); // Message(e.Targets[0].Name, "See terminal for debug data."); String pasteUrl = await DebugPaster.PasteCard(c); if (pasteUrl == null) Message(target, "Paste failed."); else Message(target, "Debug data posted: {0}", pasteUrl); return; } else if (lowerMessage.StartsWith("!card ") && message.Length > "!card ".Length && message.Length <= (Config.MaxCardNameLength + "!card ".Length)) { // If the lookup request is longer than Config.MaxCardNameLength (default: 30) characters, // it's probably too long to be a card. LookupCardNameFor(responseTarget, message.Substring("!card ".Length).ToLower()); } // The check for manually triggered cards Match match = regex.Match(lowerMessage); for (int i = 0; i < Config.MaxCardsPerLine && match.Success; ++i, match = match.NextMatch()) { if (match.Groups[1].Length >= Config.MaxCardNameLength) { --i; continue; } LookupCardNameFor(responseTarget, match.Groups[1].Value); } // Auto trigger check double atThreshold = Config.AutoTriggerMatchRequirement / 100.0; if (atThreshold > 0) { string[] lowerWords = lowerMessage.Split(' '); Dictionary<Card, double> matches = new Dictionary<Card, double>(); for (int i = 0; i < lowerWords.Length; ++i) { double matchPct; StringBuilder runningString = new StringBuilder(lowerWords[i]); LookupCard(runningString.ToString(), out matchPct, 0.0 /* boost */); int backward = i - 1, forward = i + 1; while (true) { double matchPct2; double matchPctLastLoop = matchPct; if (backward >= 0) { LookupCard(lowerWords[backward] + " " + runningString.ToString(), out matchPct2, 0.0 /* boost */); if (matchPct2 > matchPct) { matchPct = matchPct2; runningString = new StringBuilder(lowerWords[backward] + " " + runningString.ToString()); --backward; } } if (forward < lowerWords.Length) { LookupCard(runningString.ToString() + " " + lowerWords[forward], out matchPct2, 0.0); if (matchPct2 > matchPct) { matchPct = matchPct2; runningString.Append(" "); runningString.Append(lowerWords[forward]); forward++; } } if (matchPct == matchPctLastLoop) break; matchPctLastLoop = matchPct; } if (matchPct >= atThreshold) { try { matches.Add(LookupCard(runningString.ToString(), out matchPct, 0.0), matchPct); } catch (ArgumentException) { // Caught when there already exists a card in the dictionary. We're OK with that :) } } } matches.OrderByDescending<KeyValuePair<Card, double>, double>((kvp) => kvp.Value); for (int i = 0; i < Config.MaxCardsPerLine && matches.Count > 0; ++i) { KeyValuePair<Card, double> max = matches.First(); matches.Remove(max.Key); LookupCardNameFor(responseTarget, max.Key.Name); } } }