protected override void ProcessUpdatedMessage(ChatboxMessage message, bool isPartOfInitialSalvo = false, bool isEdited = false, bool isBanned = false) { if (isEdited) { // find and change! lock (MessageList) { var node = MessageList.Find(m => m.ID == message.ID); if (node == null) { // I guess I don't remember this one anymore return; } node.Value = message; } } else { lock (MessageList) { MessageList.AddFirst(message); while (MessageList.Count > Config.Backlog) { MessageList.RemoveLast(); } } } }
public MessageToDistribute(bool isPartOfInitialSalvo, bool isEdited, bool isBanned, ChatboxMessage message) { IsPartOfInitialSalvo = isPartOfInitialSalvo; IsEdited = isEdited; IsBanned = isBanned; Message = message; }
protected override void ProcessUpdatedMessage(ChatboxMessage message, bool isPartOfInitialSalvo = false, bool isEdited = false, bool isBanned = false) { if (isPartOfInitialSalvo || isEdited || isBanned) { return; } var body = message.BodyBBCode; if (body == "!lastlink") { if (_lastLink == null) { Connector.SendMessage("No last link!"); } else { PostLinkInfo(new [] { _lastLink }); } return; } if (body == "!lasticon") { if (_lastIcon == null) { Connector.SendMessage("No last icon!"); } else { PostLinkInfo(new [] { _lastIcon }); } } // find all the links var dom = message.BodyDom; var links = FindLinks(dom); var icons = FindIcons(dom); // store the new "last link" if (links.Count > 0) { _lastLink = links[links.Count - 1]; } if (icons.Count > 0) { _lastIcon = icons[icons.Count - 1]; } // respond? if (body.StartsWith("!link ")) { PostLinkInfo(links); } else if (body.StartsWith("!icon ")) { PostLinkInfo(icons); } }
protected override void ProcessUpdatedMessage(ChatboxMessage message, bool isPartOfInitialSalvo = false, bool isEdited = false, bool isBanned = false) { if (isPartOfInitialSalvo || isEdited || isBanned) { return; } var body = message.BodyBBCode; if (!IsDownRegex.Match(body).Success) { return; } var client = new WebClient { Encoding = Encoding.UTF8 }; var response = client.DownloadString(_config.ApiUrl); var pieces = response.Split(' '); if (pieces.Length != 3) { Logger.DebugFormat( "unexpected server answer {0} for nickname {1}", Util.LiteralString(response), message.UserName ); Connector.SendMessage(string.Format(PickRandom(_config.UnknownMessages), message.UserName)); return; } var status = pieces[0]; var sinceTimeString = pieces[1]; var lastUpdateTimeString = pieces[2]; var since = FormatDateTime(Util.UnixTimestampStringToLocalDateTime(sinceTimeString)); var lastUpdate = FormatDateTime(Util.UnixTimestampStringToLocalDateTime(lastUpdateTimeString)); IList <string> pickOne = _config.UnknownMessages; if (status == "0") { pickOne = _config.UpMessages; } else if (status == "1") { pickOne = _config.DownMessages; } var outgoing = PickRandom(pickOne); Connector.SendMessage(string.Format( outgoing, message.UserName, since, lastUpdate )); }
protected void PotentialDictSpy(ChatboxMessage message) { var spyDictMatch = SpyDictTrigger.Match(message.BodyBBCode); if (!spyDictMatch.Success) { return; } var userLevel = GetUserLevel(message.UserName); var salutation = userLevel.ToString(); if (userLevel != UserLevel.Spymaster) { SendInsufficientRankMessage(salutation, message.UserName); return; } var wordList = spyDictMatch.Groups[1].Value.Trim(); var origString = spyDictMatch.Groups[2].Value.Trim(); var replString = spyDictMatch.Groups[3].Value.Trim(); if (!_wordLists.ContainsKey(wordList)) { Connector.SendMessage(string.Format( "{0} [noparse]{1}[/noparse]: Unknown word list [noparse]{2}[/noparse].", salutation, message.UserName, Util.ExpungeNoparse(wordList) )); return; } long newDictTriggerID; using (var ctx = GetNewContext()) { var dictTrig = new DictionaryTrigger { OriginalString = origString, ReplacementString = replString, WordList = wordList, SpymasterName = message.UserName }; ctx.DictionaryTriggers.Add(dictTrig); ctx.SaveChanges(); newDictTriggerID = dictTrig.ID; } Connector.SendMessage(string.Format( "{0} [noparse]{1}[/noparse]: Done (#{2}).", salutation, message.UserName, newDictTriggerID )); }
protected void SendRandomMotivatorFromList(IList <string> motivatorList, ChatboxMessage requestMessage) { // pick a motivator var index = _random.Next(motivatorList.Count); var motivator = motivatorList[index]; // personalize motivator = string.Format(motivator, requestMessage.UserName); // send Connector.SendMessage(string.Format("[noparse]{0}[/noparse]: {1}", requestMessage.UserName, motivator)); }
protected override void ProcessUpdatedMessage(ChatboxMessage message, bool isPartOfInitialSalvo = false, bool isEdited = false, bool isBanned = false) { if (isPartOfInitialSalvo || isEdited || isBanned) { return; } var body = message.BodyBBCode.ToLowerInvariant(); foreach (var verbCategories in _config.VerbsCategoriesMotivators) { var verbMeUsing = string.Format("!{0} me using ", verbCategories.Key); if (body == string.Format("!{0} me", verbCategories.Key)) { // unite the motivators from all categories var motivatorList = new List <string>(); foreach (var motivators in verbCategories.Value.Values) { motivatorList.AddRange(motivators); } SendRandomMotivatorFromList(motivatorList, message); return; } else if (body.StartsWith(verbMeUsing)) { var category = body.Substring(verbMeUsing.Length); if (!verbCategories.Value.ContainsKey(category)) { Connector.SendMessage(string.Format( "[noparse]{0}[/noparse]: I don\u2019t know that category.", message.UserName )); return; } var motivatorList = verbCategories.Value[category]; SendRandomMotivatorFromList(motivatorList, message); return; } else if (body == string.Format("!how can you {0} me", verbCategories.Key)) { var categories = verbCategories.Value.Keys.ToList(); categories.Sort(); var categoriesString = string.Join(", ", categories); Connector.SendMessage(string.Format( "[noparse]{0}[/noparse]: I can {1} you using {2}.", message.UserName, verbCategories.Key, categoriesString )); return; } } }
/// <summary> /// Checks whether a new ECHELON trigger is to be added and potentially does so. /// </summary> protected void PotentialSpy(ChatboxMessage message) { var spyMatch = SpyTrigger.Match(message.BodyBBCode); if (!spyMatch.Success) { return; } var userLevel = GetUserLevel(message.UserName); var salutation = userLevel.ToString(); if (userLevel != UserLevel.Spymaster) { SendInsufficientRankMessage(salutation, message.UserName); return; } var username = spyMatch.Groups[1].Success ? spyMatch.Groups[1].Value.Trim().ToLowerInvariant() : null; var regex = spyMatch.Groups[2].Value.Trim(); long newTriggerID; using (var ctx = GetNewContext()) { var trig = new Trigger { TargetNameLower = username, Regex = regex, SpymasterName = message.UserName }; ctx.Triggers.Add(trig); ctx.SaveChanges(); newTriggerID = trig.Id; } Connector.SendMessage(string.Format( "{0} [noparse]{1}[/noparse]: Done (#{2}).", salutation, message.UserName, newTriggerID )); }
protected override void ProcessUpdatedMessage(ChatboxMessage message, bool isPartOfInitialSalvo = false, bool isEdited = false, bool isBanned = false) { if (isPartOfInitialSalvo || isEdited || isBanned) { return; } if (message.UserName == Connector.ForumConfig.Username) { // prevent loops return; } var originalBody = Util.RemoveControlCharactersAndStrip(message.BodyBBCode); var newBody = originalBody; foreach (var repl in _config.Replacements) { // substitute the username in the replacement string var replacementStringWithUser = repl.ReplacementString.Replace("{{{username}}}", message.UserName); newBody = repl.Regex.Replace(newBody, replacementStringWithUser); } if (newBody == originalBody) { return; } var thisProbabilityValue = _random.NextDouble() * 100.0; if (thisProbabilityValue < _config.ProbabilityPercent) { Logger.DebugFormat("{0:F2} < {1:F2}; posting {2}", thisProbabilityValue, _config.ProbabilityPercent, newBody); Connector.SendMessage(newBody); } else { Logger.DebugFormat("{0:F2} >= {1:F2}; not posting {2}", thisProbabilityValue, _config.ProbabilityPercent, newBody); } }
protected void PotentialDeliverRequest(ChatboxMessage message) { var body = message.BodyBBCode; var match = DeliverTrigger.Match(body); if (!match.Success) { return; } // overflow avoidance if (match.Groups[1].Length > 3) { Connector.SendMessage(string.Format( "[noparse]{0}[/noparse]: I am absolutely not delivering that many messages at once.", message.UserName )); return; } var fetchCount = int.Parse(match.Groups[1].Value); var lowerSenderName = message.UserName.ToLowerInvariant(); List <MessageOnRetainer> messages; int messagesLeft; using (var ctx = GetNewContext()) { // get the messages messages = ctx.MessagesOnRetainer .Where(m => m.RecipientFolded == lowerSenderName) .OrderBy(m => m.ID) .Take(fetchCount) .ToList() ; // delete them ctx.MessagesOnRetainer.RemoveRange(messages); ctx.SaveChanges(); // check how many are left messagesLeft = ctx.MessagesOnRetainer .Count(m => m.RecipientFolded == lowerSenderName) ; } // deliver them if (messages.Count > 0) { Connector.SendMessage(string.Format( "Delivering {0} {1} for [noparse]{2}[/noparse]!", messages.Count, messages.Count == 1 ? "message" : "messages", message.UserName )); foreach (var msg in messages) { Logger.DebugFormat( "delivering {0}'s retained message {1} to {2} as part of a chunk", Util.LiteralString(msg.SenderOriginal), Util.LiteralString(msg.Body), Util.LiteralString(message.UserName) ); Connector.SendMessage(string.Format( "{0} <[noparse]{1}[/noparse]> {2}", FormatUtcTimestampFromDatabase(msg.ID, msg.Timestamp), msg.SenderOriginal, msg.Body )); } } // output remaining messages count if (messagesLeft == 0) { if (messages.Count > 0) { Connector.SendMessage(string.Format( "[noparse]{0}[/noparse] has no more messages left to deliver!", message.UserName )); } else { Connector.SendMessage(string.Format( "[noparse]{0}[/noparse] has no messages to deliver!", message.UserName )); } } else { Connector.SendMessage(string.Format( "[noparse]{0}[/noparse] has {1} {2} left to deliver!", message.UserName, messagesLeft, (messagesLeft == 1) ? "message" : "messages" )); } }
protected override void ProcessUpdatedMessage(ChatboxMessage message, bool isPartOfInitialSalvo = false, bool isEdited = false, bool isBanned = false) { if (isEdited || isPartOfInitialSalvo || isBanned) { // do nothing return; } if (message.UserName == Connector.ForumConfig.Username) { // ignore my own messages return; } var body = message.BodyBBCode; if (body == "!stfu") { // check for ban using (var context = GetNewContext()) { var ban = context.Bans.Find(message.UserName); if (ban != null) { if (!ban.Deadline.HasValue) { Logger.DebugFormat("{0} wants to shut me up but they're permabanned", message.UserName); SendSnark(message.UserName); return; } else if (ban.Deadline.Value > DateTime.Now) { Logger.DebugFormat("{0} wants to shut me up but they're banned until {1}", message.UserName, ban.Deadline.Value); SendSnark(message.UserName); return; } } // no ban -- STFU Logger.InfoFormat("{0} shut me up for {1} minutes", message.UserName, _config.Duration / 60); _whoShutMeUpLast = message.UserName; Connector.StfuDeadline = DateTime.Now.AddSeconds(_config.Duration); } } else if (body == "!unstfu") { if (!_config.Admins.Contains(message.UserName)) { Logger.DebugFormat("{0} wants to un-stfu me, but they aren't an admin", message.UserName); return; } Logger.InfoFormat("{0} un-stfu-ed me", message.UserName); Connector.StfuDeadline = null; Connector.SendMessage("I can speak again!"); } else if (body.StartsWith("!stfuban ")) { if (!_config.Admins.Contains(message.UserName)) { Logger.DebugFormat("{0} wants to ban someone but they aren't an admin", message.UserName); SendSnark(message.UserName); return; } var bodyRest = body.Substring(("!stfuban ").Length); var nextSpace = bodyRest.IndexOf(' '); if (nextSpace == -1) { Connector.SendMessage("Usage: !stfuban timespec username"); return; } var timeSpec = bodyRest.Substring(0, nextSpace); var banThisUser = bodyRest.Substring(nextSpace + 1); var seconds = DurationStringToSeconds(timeSpec); DateTime?deadline; if (seconds == 0) { Connector.SendMessage("Invalid timespec!"); return; } else if (seconds == -1) { deadline = null; } else { deadline = DateTime.Now.AddSeconds(seconds); } // insert the ban into the database using (var context = GetNewContext()) { var runningBan = context.Bans.Find(banThisUser); if (runningBan != null) { runningBan.Deadline = deadline; runningBan.Banner = message.UserName; } else { runningBan = new Ban { BannedUser = banThisUser, Deadline = deadline, Banner = message.UserName }; context.Bans.Add(runningBan); } context.SaveChanges(); } if (_whoShutMeUpLast == banThisUser) { // un-STFU immediately Connector.StfuDeadline = null; } Logger.InfoFormat("{0} banned {1} from using !stfu for {2}", message.UserName, banThisUser, timeSpec); if (!deadline.HasValue) { Connector.SendMessage(string.Format("Alright! Banning {0} from using the !stfu function.", banThisUser), bypassStfu: true); } else { Connector.SendMessage(string.Format("Alright! Banning {0} from using the !stfu function until {1}.", banThisUser, deadline.Value), bypassStfu: true); } } else if (body.StartsWith("!stfuunban ")) { if (!_config.Admins.Contains(message.UserName)) { Logger.DebugFormat("{0} wants to unban someone but they aren't an admin", message.UserName); SendSnark(message.UserName); return; } var unbanThisUser = body.Substring(("!stfuunban ").Length); using (var context = GetNewContext()) { var runningBan = context.Bans.Find(unbanThisUser); if (runningBan == null) { Connector.SendMessage(string.Format("{0} isn't even banned...?", unbanThisUser)); } else { context.Bans.Remove(runningBan); context.SaveChanges(); Connector.SendMessage(string.Format("Alright, {0} may use !stfu again.", unbanThisUser)); } } } }
protected override void ProcessUpdatedMessage(ChatboxMessage message, bool isPartOfInitialSalvo = false, bool isEdited = false, bool isBanned = false) { if (isPartOfInitialSalvo || isEdited || isBanned) { return; } var body = message.BodyBBCode; var match = SeenRegex.Match(body); if (!match.Success) { return; } var nicknames = match.Groups[1].Value.Split(';').Select(n => n.Trim().Replace("[/noparse]", "")).Where(n => n.Length > 0).ToList(); if (nicknames.Count == 0) { return; } var nicknamesInfos = new Dictionary <string, SeenInfo>(); foreach (var nickname in nicknames) { var urlEncodedNickname = Util.UrlEncode(nickname, Util.Utf8NoBom, spaceAsPlus: true); var callUrl = new Uri(string.Format(_config.ApiUrlTemplate, urlEncodedNickname)); var client = new WebClient(); if (_config.ApiUsername != null || _config.ApiPassword != null) { client.Credentials = new NetworkCredential(_config.ApiUsername ?? "", _config.ApiPassword ?? ""); } var response = client.DownloadString(callUrl); if (response == "NULL") { nicknamesInfos[nickname] = null; continue; } var pieces = response.Split(' '); if (pieces.Length != 3) { Logger.WarnFormat("unexpected server answer {0} for nickname {1}", Util.LiteralString(response), Util.LiteralString(nickname)); continue; } nicknamesInfos[nickname] = new SeenInfo { Timestamp = Util.UnixTimestampStringToLocalDateTime(pieces[0]), MessageID = Util.MaybeParseLong(pieces[1]), Epoch = Util.MaybeParseLong(pieces[2]) }; } if (nicknames.Count == 1) { // single-user request var nickname = nicknames[0]; var info = nicknamesInfos[nickname]; if (info == null) { Connector.SendMessage(string.Format( "{0}: The great and powerful [i]signanz[/i] doesn't remember seeing [i]{1}[/i].", Connector.EscapeOutogingText(message.UserName), Connector.EscapeOutogingText(nickname) )); } else if (!info.Timestamp.HasValue) { Connector.SendMessage(string.Format( "{0}: The great and powerful [i]signanz[/i]'s answer confused me\u2014sorry!", Connector.EscapeOutogingText(message.UserName) )); } else { var timestampString = FormatDateTime(info.Timestamp.Value); if (_config.ArchiveLinkTemplate != null && info.MessageID.HasValue && info.Epoch.HasValue) { timestampString += string.Format( " ([url={0}]\u2192 archive[/url])", string.Format( _config.ArchiveLinkTemplate, info.MessageID.Value, info.Epoch.Value ) ); } Connector.SendMessage(string.Format( "{0}: The last time the great and powerful [i]signanz[/i] saw [i]{1}[/i] was {2}.", Connector.EscapeOutogingText(message.UserName), Connector.EscapeOutogingText(nickname), timestampString )); } } else { // multi-nick request var responseBits = new List <string>(); foreach (var nickname in nicknames) { string text; var info = nicknamesInfos[nickname]; if (info == null) { text = "never"; } else if (!info.Timestamp.HasValue) { text = "o_O"; } else { text = FormatDateTime(info.Timestamp.Value); if (_config.ArchiveLinkTemplate != null && info.MessageID.HasValue && info.Epoch.HasValue) { text += string.Format( " ([url={0}]\u2192[/url])", string.Format( _config.ArchiveLinkTemplate, info.MessageID.Value, info.Epoch.Value ) ); } } responseBits.Add(string.Format( "[i]{0}[/i]: {1}", Connector.EscapeOutogingText(nickname), text )); } Connector.SendMessage(string.Format( "{0}: The great and powerful [i]signanz[/i] saw: {1}", message.UserName, string.Join(", ", responseBits) )); } }
protected override void ProcessUpdatedMessage(ChatboxMessage message, bool isPartOfInitialSalvo = false, bool isEdited = false, bool isBanned = false) { if (isEdited || isPartOfInitialSalvo || message.UserName == Connector.ForumConfig.Username) { return; } if (!isBanned) { PotentialStats(message); PotentialStatsRank(message); PotentialSpy(message); PotentialModifySpy(message); PotentialDeleteSpy(message); PotentialDictSpy(message); PotentialModifyDictSpy(message); PotentialDeleteDictSpy(message); } // spy on messages from banned users too var lowerSenderName = message.UserName.ToLowerInvariant(); var bodyWords = RemoveNonWord(message.Body).Split(' '); using (var ctx = GetNewContext()) { // standard triggers var relevantTriggers = ctx.Triggers.Where(t => !t.Deactivated && (t.TargetNameLower == null || t.TargetNameLower == lowerSenderName)); foreach (var trigger in relevantTriggers) { var re = trigger.Regex; if (!_regexCache.ContainsKey(re)) { _regexCache[re] = new Regex(re); } if (!_regexCache[re].IsMatch(message.BodyBBCode)) { continue; } // incident! var inc = new Incident { TriggerId = trigger.Id, MessageId = message.ID, Timestamp = DateTime.UtcNow.ToUniversalTimeForDatabase(), PerpetratorName = message.UserName.ToLowerInvariant(), Expunged = false }; ctx.Incidents.Add(inc); } ctx.SaveChanges(); // dictionary triggers var relevantDictTriggers = ctx.DictionaryTriggers.Where(t => !t.Deactivated); foreach (var dictTrigger in relevantDictTriggers) { var wordSet = _wordLists[dictTrigger.WordList]; foreach (var word in bodyWords) { var lowercaseWord = word.ToLower(); // word must contain the "from" substring if (lowercaseWord.IndexOf(dictTrigger.OriginalString) == -1) { // doesn't continue; } // is the word in the dictionary? if (wordSet.Contains(lowercaseWord)) { // it is continue; } // correct the word var corrected = word.Replace(dictTrigger.OriginalString, dictTrigger.ReplacementString); var correctedLower = corrected.ToLower(); // is the corrected word in the dictionary? if (!wordSet.Contains(correctedLower)) { // no continue; } // count it as an incident var dictIncident = new DictionaryIncident { TriggerID = dictTrigger.ID, MessageID = message.ID, Timestamp = DateTime.UtcNow.ToUniversalTimeForDatabase(), PerpetratorName = message.UserName.ToLowerInvariant(), OriginalWord = word, CorrectedWord = corrected, Expunged = false }; ctx.DictionaryIncidents.Add(dictIncident); } } ctx.SaveChanges(); } }
protected override void ProcessUpdatedMessage(ChatboxMessage message, bool isPartOfInitialSalvo = false, bool isEdited = false, bool isBanned = false) { if (isPartOfInitialSalvo || isEdited || isBanned) { return; } if (message.UserName == Connector.ForumConfig.Username) { return; } var body = RemoveNonWord(message.Body); var words = body.Split(' '); var correctedWords = new List <string>(); foreach (var item in _config.Items) { var wordSet = _wordLists[item.WordListFilename]; foreach (var word in words) { var lowercaseWord = word.ToLower(); // word must contain the "from" substring if (lowercaseWord.IndexOf(item.From) == -1) { // doesn't continue; } // is the word in the dictionary? if (wordSet.Contains(lowercaseWord)) { // it is continue; } // correct the word var corrected = word.Replace(item.From, item.To); var correctedLower = corrected.ToLower(); // is the corrected word in the dictionary? if (wordSet.Contains(correctedLower)) { // yes; format and add it to the corrected words list correctedWords.Add(string.Format(_config.CorrectedWordFormat, corrected)); } } } if (correctedWords.Count == 0) { return; } var joined = string.Join(_config.Separator, correctedWords); Connector.SendMessage(joined); }
protected void PotentialModifyDictSpy(ChatboxMessage message) { var modSpyDictMatch = ModifySpyDictTrigger.Match(message.BodyBBCode); if (!modSpyDictMatch.Success) { return; } var userLevel = GetUserLevel(message.UserName); var salutation = userLevel.ToString(); if (userLevel != UserLevel.Spymaster) { SendInsufficientRankMessage(salutation, message.UserName); return; } var dictTriggerID = long.Parse(modSpyDictMatch.Groups[1].Value); var wordList = modSpyDictMatch.Groups[2].Value.Trim(); var origString = modSpyDictMatch.Groups[3].Value.Trim(); var replString = modSpyDictMatch.Groups[4].Value.Trim(); if (!_wordLists.ContainsKey(wordList)) { Connector.SendMessage(string.Format( "{0} [noparse]{1}[/noparse]: Unknown word list [noparse]{2}[/noparse].", salutation, message.UserName, Util.ExpungeNoparse(wordList) )); return; } using (var ctx = GetNewContext()) { var dictTrig = ctx.DictionaryTriggers.FirstOrDefault(t => t.ID == dictTriggerID); if (dictTrig == null) { Connector.SendMessage(string.Format( "{0} [noparse]{1}[/noparse]: The dictionary trigger with this ID does not exist.", salutation, message.UserName )); return; } dictTrig.WordList = wordList; dictTrig.OriginalString = origString; dictTrig.ReplacementString = replString; dictTrig.SpymasterName = message.UserName; ctx.SaveChanges(); } Connector.SendMessage(string.Format( "{0} [noparse]{1}[/noparse]: Updated.", salutation, message.UserName )); }
protected override void ProcessUpdatedMessage(ChatboxMessage message, bool isPartOfInitialSalvo = false, bool isEdited = false, bool isBanned = false) { if (isEdited) { // don't react to edited messages return; } if (message.UserName.Equals(Connector.ForumConfig.Username, StringComparison.InvariantCulture)) { // the bot itself may not throw things into the bin return; } if (isBanned || _config.Banned.Contains(message.UserName)) { return; } var body = message.BodyBBCode; if (!body.StartsWith("!", StringComparison.InvariantCulture)) { // not a bot trigger; process a possible toss HandlePossibleToss(message, body); } else if (isPartOfInitialSalvo) { // don't process commands that are part of the initial salvo } else if (body == "!tonnen") { Logger.DebugFormat("bin overview request from {0}", message.UserName); using (var context = GetNewContext()) { var bins = context.Bins.Select(b => b.BinName).ToList(); if (bins.Count == 0) { Connector.SendMessage("Ich kenne keine Tonnen."); } else if (bins.Count == 1) { Connector.SendMessage("Ich kenne folgende Tonne: '" + bins[0] + "'"); } else { bins.Sort(); var names = string.Join(", ", bins.Select(x => "'" + x + "'")); Connector.SendMessage("Ich kenne folgende Tonnen: " + names); } } } else if (body.StartsWith("!tonneninhalt ")) { var binName = body.Substring(("!tonneninhalt ").Length); Logger.DebugFormat("bin {0} contents request from {1}", binName, message.UserName); using (var context = GetNewContext()) { var bin = context.Bins.FirstOrDefault(b => b.BinName == binName); if (bin == null) { Connector.SendMessage("Diese Tonne kenne ich nicht."); return; } var items = context.BinItems.Where(i => i.Bin.BinName == binName).Select(i => i.Item).ToList(); if (items.Count == 0) { Connector.SendMessage("In dieser Tonne befindet sich nichts."); } else if (items.Count == 1) { Connector.SendMessage("In dieser Tonne befindet sich: " + items[0]); } else { items.Sort(); var itemString = string.Join(", ", items); Connector.SendMessage("In dieser Tonne befinden sich: " + itemString); } } } else if (body.StartsWith("!entleere ")) { var binName = body.Substring(("!entleere ").Length); Logger.DebugFormat("bin {0} emptying request from {1}", binName, message.UserName); using (var context = GetNewContext()) { var bin = context.Bins.FirstOrDefault(b => b.BinName == binName); if (bin == null) { Connector.SendMessage("Diese Tonne kenne ich nicht."); return; } bin.Items.Clear(); context.SaveChanges(); } } else if (body == "!m\u00fcllabfuhr") { Logger.DebugFormat("bin removal request from {0}", message.UserName); using (var context = GetNewContext()) { context.DeleteAll <BinItem>(); context.DeleteAll <Bin>(); context.SaveChanges(); } Connector.SendMessage("Tonnen abgesammelt."); } }
protected override void ProcessUpdatedMessage(ChatboxMessage message, bool isPartOfInitialSalvo = false, bool isEdited = false, bool isBanned = false) { if (isBanned) { return; } var body = message.BodyBBCode; if (body.Length == 0) { return; } // clean out the backlog while (_backlog.Count > _config.BacklogSize) { _backlog.Dequeue(); } if (isEdited) { // find the message in the backlog and modify it var newBacklog = new Queue <BacklogMessage>(); foreach (var backMessage in _backlog) { if (backMessage.MessageID == message.ID) { // store the updated version newBacklog.Enqueue(new BacklogMessage { MessageID = message.ID, Sender = message.UserName, Body = message.BodyBBCode }); } else { newBacklog.Enqueue(backMessage); } } _backlog = newBacklog; } else { // simply append the message _backlog.Enqueue(new BacklogMessage { MessageID = message.ID, Sender = message.UserName, Body = message.BodyBBCode }); } if (isPartOfInitialSalvo) { // don't post anything just yet return; } // perform accounting var messageToSenders = new Dictionary <string, HashSet <string> >(); foreach (var backMessage in _backlog) { if (backMessage.Sender == Connector.ForumConfig.Username) { // this is my message -- start counting from zero, so to speak messageToSenders[backMessage.Body] = new HashSet <string>(); } else { if (!messageToSenders.ContainsKey(backMessage.Body)) { messageToSenders[backMessage.Body] = new HashSet <string>(); } messageToSenders[backMessage.Body].Add(backMessage.Sender); } } foreach (var messageAndSenders in messageToSenders) { var msg = messageAndSenders.Key; var senders = messageAndSenders.Value; if (senders.Count < _config.TriggerCount) { continue; } Logger.DebugFormat( "bowing to the group pressure of ({0}) sending {1}", string.Join(", ", senders.Select(s => Util.LiteralString(s))), Util.LiteralString(msg) ); // submit to group pressure Connector.SendMessage(msg); // fake this message into the backlog to prevent duplicates _backlog.Enqueue(new BacklogMessage { MessageID = -1, Sender = Connector.ForumConfig.Username, Body = msg }); } }
protected void HandlePossibleToss(ChatboxMessage message, string body) { var match = ArrowWasteBinRegex.Match(body); if (!match.Success) { return; } // a waste bin toss has been found var what = match.Groups[1].Value.Trim(); var arrow = match.Groups[2].Value; var where = match.Groups[3].Value.Trim().ToLowerInvariant(); if (ArrowRegex.IsMatch(what) || ArrowRegex.IsMatch(where)) { Logger.DebugFormat( "{0} is trying to trick us by throwing {1} into {2}", message.UserName, Util.LiteralString(what), Util.LiteralString(where) ); return; } var timestamp = DateTime.SpecifyKind(DateTime.UtcNow, DateTimeKind.Unspecified); Logger.DebugFormat( "{0} tossed {1} into {2} using {3}", message.UserName, Util.LiteralString(what), Util.LiteralString(where), Util.LiteralString(arrow) ); using (var context = GetNewContext()) { var bin = context.Bins.Where(x => x.BinName == where).FirstOrDefault(); if (bin == null) { // add the bin bin = new Bin { BinName = where }; context.Bins.Add(bin); context.SaveChanges(); } var item = context.BinItems.Where(x => x.Bin.BinName == where && x.Item == what).FirstOrDefault(); if (item == null) { item = new BinItem { Bin = bin, Thrower = message.UserName, Arrow = arrow, Item = what, Timestamp = timestamp.ToUniversalTimeForDatabase() }; context.BinItems.Add(item); context.SaveChanges(); } } }
protected override void ProcessUpdatedMessage(ChatboxMessage message, bool isPartOfInitialSalvo = false, bool isEdited = false, bool isBanned = false) { if (isPartOfInitialSalvo || isEdited || message.UserName == Connector.ForumConfig.Username) { return; } var lowerNickname = message.UserName.ToLowerInvariant(); if (!isBanned) { PotentialMessageSend(message); PotentialDeliverRequest(message); PotentialIgnoreListRequest(message); PotentialReplayRequest(message); } // even banned users get messages; they just can't respond to them if (Connector.StfuDeadline.HasValue && Connector.StfuDeadline.Value > DateTime.Now) { // don't bother just yet return; } // check if the sender should get any messages List <Message> messages; using (var ctx = GetNewContext()) { messages = ctx.Messages .Where(m => m.RecipientFolded == lowerNickname) .OrderBy(m => m.ID) .ToList() ; var numberMessagesOnRetainer = ctx.MessagesOnRetainer .Count(m => m.RecipientFolded == lowerNickname); var messagesToDisplay = messages .Where(m => message.ID - m.ID < 1 || message.ID - m.ID > 2) .ToList() ; var retainerText = (numberMessagesOnRetainer > 0) ? string.Format(" (and {0} pending !delivermsg)", numberMessagesOnRetainer) : "" ; var moveToReplay = true; if (messagesToDisplay.Count == 0) { // meh // (don't return yet; delete the skipped "responded directly to" messages) } else if (messagesToDisplay.Count == 1) { // one message Logger.DebugFormat( "delivering {0}'s message #{1} {2} to {3}", Util.LiteralString(messagesToDisplay[0].SenderOriginal), messagesToDisplay[0].ID, Util.LiteralString(messagesToDisplay[0].Body), Util.LiteralString(message.UserName) ); Connector.SendMessage(string.Format( "Message for [noparse]{0}[/noparse]{1}! {2} <[noparse]{3}[/noparse]> {4}", message.UserName, retainerText, FormatUtcTimestampFromDatabase(messagesToDisplay[0].ID, messagesToDisplay[0].Timestamp), messagesToDisplay[0].SenderOriginal, messagesToDisplay[0].Body )); } else if (messagesToDisplay.Count >= _config.TooManyMessages) { // use messages instead of messagesToDisplay to put all of them on retainer Logger.DebugFormat( "{0} got {1} messages; putting on retainer", Util.LiteralString(message.UserName), messages.Count ); Connector.SendMessage(string.Format( "{0} new messages for [noparse]{1}[/noparse]{2}! Use \u201c!delivermsg [i]maxnumber[/i]\u201d to get them!", messages.Count, message.UserName, retainerText )); // put messages on retainer ctx.MessagesOnRetainer.AddRange(messages.Select(m => new MessageOnRetainer(m))); // don't replay! moveToReplay = false; // the content of messages will be cleaned out from ctx.Messages below } else { // multiple but not too many messages Connector.SendMessage(string.Format( "{0} new messages for [noparse]{1}[/noparse]{2}!", messagesToDisplay.Count, message.UserName, retainerText )); foreach (var msg in messagesToDisplay) { Logger.DebugFormat( "delivering {0}'s message #{1} {2} to {3} as part of a chunk", Util.LiteralString(msg.SenderOriginal), msg.ID, Util.LiteralString(msg.Body), Util.LiteralString(message.UserName) ); Connector.SendMessage(string.Format( "{0} <[noparse]{1}[/noparse]> {2}", FormatUtcTimestampFromDatabase(msg.ID, msg.Timestamp), msg.SenderOriginal, msg.Body )); } Connector.SendMessage(string.Format( "[noparse]{0}[/noparse]: Have a nice day!", message.UserName )); } if (moveToReplay) { // place the messages on the repeat heap ctx.ReplayableMessages.AddRange(messages.Select( m => new ReplayableMessage(m) { Timestamp = m.Timestamp.ToUniversalTimeForDatabase() } )); } // purge the repeat heap if necessary var currentReplayables = ctx.ReplayableMessages .Where(rm => rm.RecipientFolded == lowerNickname) .OrderBy(rm => rm.ID) .ToList() ; if (currentReplayables.Count > _config.MaxMessagesToReplay) { var deleteCount = currentReplayables.Count - _config.MaxMessagesToReplay; foreach (var oldReplayable in currentReplayables.Take(deleteCount)) { ctx.ReplayableMessages.Remove(oldReplayable); } } // remove the messages from the delivery queue ctx.Messages.RemoveRange(messages); // commit ctx.SaveChanges(); } }
/// <summary> /// Checks whether top-trigger statistics for a user were requested and potentially displays them. /// </summary> protected void PotentialStatsRank(ChatboxMessage message) { var rankStatsMatch = StatsRankTrigger.Match(message.BodyBBCode); if (!rankStatsMatch.Success) { return; } var target = rankStatsMatch.Groups[1].Value; var targetLower = target.ToLowerInvariant(); var userLevel = GetUserLevel(message.UserName); var salutation = userLevel.ToString(); if (userLevel == UserLevel.Terrorist) { Connector.SendMessage(string.Format( "{0} [noparse]{1}[/noparse]: ECHELON does not provide such information to known terrorists.", salutation, message.UserName )); return; } var triggersAndCounts = new List <TriggerAndCount>(); using (var ctx = GetNewContext()) { var triggerCounts = ctx.Incidents .Where(i => !i.Expunged && i.PerpetratorName == targetLower) .GroupBy(i => i.TriggerId) .ToList() .Select(it => new TriggerAndCount { TriggerString = "R " + ctx.Triggers.FirstOrDefault(t => t.Id == it.Key).Regex, Count = it.LongCount() }) .OrderByDescending(tac => tac.Count) .Take(_config.RankCount); var dictTriggerCounts = ctx.DictionaryIncidents .Where(di => !di.Expunged && di.PerpetratorName == targetLower) .GroupBy(di => di.TriggerID) .ToList() .Select(dit => new TriggerAndCount { TriggerString = string.Format( "D {0}->{1}", ctx.DictionaryTriggers.FirstOrDefault(dt => dt.ID == dit.Key).OriginalString, ctx.DictionaryTriggers.FirstOrDefault(dt => dt.ID == dit.Key).ReplacementString ), Count = dit.LongCount() }) .OrderByDescending(tac => tac.Count) .Take(_config.RankCount); triggersAndCounts.AddRange(triggerCounts); triggersAndCounts.AddRange(dictTriggerCounts); } if (triggersAndCounts.Count == 0) { Connector.SendMessage(string.Format( "{0} [noparse]{1}[/noparse]: No known incidents for subject [noparse]{2}[/noparse]!", salutation, message.UserName, target )); return; } triggersAndCounts.Sort(); triggersAndCounts.Reverse(); var statsString = string.Join(" || ", triggersAndCounts.Take(_config.RankCount).Select(tac => string.Format("{0}\u00D7{1}", tac.Count, tac.TriggerString))); Connector.SendMessage(string.Format( "{0} [noparse]{1}[/noparse]: Top \u2264{2} incidents for subject [noparse]{3} || {4}[/noparse]", salutation, message.UserName, _config.RankCount, target, Util.ExpungeNoparse(statsString) )); }
/// <summary> /// Checks whether ECHELON statistics for a user were requested and potentially displays them. /// </summary> protected void PotentialStats(ChatboxMessage message) { var statsMatch = StatsTrigger.Match(message.BodyBBCode); if (!statsMatch.Success) { return; } var target = statsMatch.Groups[1].Value; var targetLower = target.ToLowerInvariant(); var userLevel = GetUserLevel(message.UserName); var salutation = userLevel.ToString(); if (userLevel == UserLevel.Terrorist) { Connector.SendMessage(string.Format( "{0} [noparse]{1}[/noparse]: ECHELON does not provide such information to known terrorists.", salutation, message.UserName )); return; } long incidentCount; using (var ctx = GetNewContext()) { incidentCount = ctx.Incidents.Where(i => !i.Expunged && i.PerpetratorName == targetLower).LongCount(); incidentCount += ctx.DictionaryIncidents.Where(di => !di.Expunged && di.PerpetratorName == targetLower).LongCount(); } if (_config.UsernamesToSpecialCountFormats.ContainsKey(targetLower)) { Connector.SendMessage(string.Format( "{0} [noparse]{1}[/noparse]: {2}", salutation, message.UserName, string.Format( _config.UsernamesToSpecialCountFormats[targetLower], target, incidentCount ) )); } else if (incidentCount == 0) { Connector.SendMessage(string.Format( "{0} [noparse]{1}[/noparse]: Subject [noparse]{2}[/noparse] may or may not have caused any incident.", salutation, message.UserName, target )); } else { Connector.SendMessage(string.Format( "{0} [noparse]{1}[/noparse]: Subject [noparse]{2}[/noparse] may or may not have caused {3} {4}.", salutation, message.UserName, target, incidentCount, incidentCount == 1 ? "incident" : "incidents" )); } }
protected void PotentialReplayRequest(ChatboxMessage message) { var body = message.BodyBBCode; var match = ReplayTrigger.Match(body); if (!match.Success) { return; } if (match.Groups[1].Length > 3) { Connector.SendMessage(string.Format( "[noparse]{0}[/noparse]: I am absolutely not replaying that many messages at once.", message.UserName )); return; } var replayCount = int.Parse(match.Groups[1].Value); if (replayCount > _config.MaxMessagesToReplay) { Connector.SendMessage(string.Format( "[noparse]{0}[/noparse]: I only remember a backlog of up to {1} messages.", message.UserName, _config.MaxMessagesToReplay )); return; } else if (replayCount == 0) { return; } var lowerSenderName = message.UserName.ToLowerInvariant(); List <ReplayableMessage> messages; using (var ctx = GetNewContext()) { // get the messages messages = ctx.ReplayableMessages .Where(m => m.RecipientFolded == lowerSenderName) .OrderByDescending(m => m.ID) .Take(replayCount) .ToList() ; messages.Reverse(); } if (messages.Count == 0) { Connector.SendMessage(string.Format( "[noparse]{0}[/noparse]: You have no messages to replay!", message.UserName )); return; } if (messages.Count == 1) { Logger.DebugFormat("replaying a message for {0}", Util.LiteralString(message.UserName)); Connector.SendMessage(string.Format( "Replaying message for [noparse]{0}[/noparse]! {1} <[noparse]{2}[/noparse]> {3}", message.UserName, FormatUtcTimestampFromDatabase(messages[0].ID, messages[0].Timestamp), messages[0].SenderOriginal, messages[0].Body )); return; } Connector.SendMessage(string.Format( "[noparse]{0}[/noparse]: Replaying {1} messages!", message.UserName, messages.Count )); Logger.DebugFormat( "replaying {0} messages for {1}", messages.Count, Util.LiteralString(message.UserName) ); foreach (var msg in messages) { Connector.SendMessage(string.Format( "{0} <[noparse]{1}[/noparse]> {2}!", FormatUtcTimestampFromDatabase(msg.ID, msg.Timestamp), msg.SenderOriginal, msg.Body )); } Connector.SendMessage(string.Format( "[noparse]{0}[/noparse]: Take care!", message.UserName )); }
/// <summary> /// Checks whether an existing ECHELON trigger is to be deleted or undeleted and potentially does so. /// </summary> protected void PotentialDeleteDictSpy(ChatboxMessage message) { var delDictMatch = DeleteSpyDictTrigger.Match(message.BodyBBCode); if (!delDictMatch.Success) { return; } var userLevel = GetUserLevel(message.UserName); var salutation = userLevel.ToString(); if (userLevel != UserLevel.Spymaster) { SendInsufficientRankMessage(salutation, message.UserName); return; } var undelete = delDictMatch.Groups[1].Success; var dictTriggerID = long.Parse(delDictMatch.Groups[2].Value); using (var ctx = GetNewContext()) { var dictTrig = ctx.DictionaryTriggers.FirstOrDefault(t => t.ID == dictTriggerID); if (dictTrig == null) { Connector.SendMessage(string.Format( "{0} [noparse]{1}[/noparse]: The dictionary trigger with this ID does not exist.", salutation, message.UserName )); return; } if (dictTrig.Deactivated && !undelete) { Connector.SendMessage(string.Format( "{0} [noparse]{1}[/noparse]: The dictionary trigger with this ID is already deleted.", salutation, message.UserName )); return; } else if (!dictTrig.Deactivated && undelete) { Connector.SendMessage(string.Format( "{0} [noparse]{1}[/noparse]: The dictionary trigger with this ID is still active.", salutation, message.UserName )); return; } dictTrig.Deactivated = !undelete; dictTrig.SpymasterName = message.UserName; ctx.SaveChanges(); } Connector.SendMessage(string.Format( "{0} [noparse]{1}[/noparse]: {2}.", salutation, message.UserName, undelete ? "Undeleted" : "Deleted" )); }
protected void PotentialIgnoreListRequest(ChatboxMessage message) { var body = message.BodyBBCode; var match = IgnoreTrigger.Match(body); if (!match.Success) { return; } var command = match.Groups[1].Value; var blockSender = match.Groups[2].Value.Trim(); var blockSenderLower = blockSender.ToLowerInvariant(); var blockRecipientLower = message.UserName.ToLowerInvariant(); bool isIgnored; using (var ctx = GetNewContext()) { isIgnored = ctx.IgnoreList .Any(ie => ie.SenderFolded == blockSenderLower && ie.RecipientFolded == blockRecipientLower); } if (command == "ignore") { if (isIgnored) { Connector.SendMessage(string.Format( "[noparse]{0}[/noparse]: You are already ignoring [i][noparse]{1}[/noparse][/i].", message.UserName, blockSender )); return; } using (var ctx = GetNewContext()) { var entry = new IgnoreEntry { SenderFolded = blockSenderLower, RecipientFolded = blockRecipientLower }; ctx.IgnoreList.Add(entry); ctx.SaveChanges(); } Logger.DebugFormat( "{0} is now ignoring {1}", Util.LiteralString(message.UserName), Util.LiteralString(blockSender) ); Connector.SendMessage(string.Format( "[noparse]{0}[/noparse]: You are now ignoring [i][noparse]{1}[/noparse][/i].", message.UserName, blockSender )); } else if (command == "unignore") { if (!isIgnored) { Connector.SendMessage(string.Format( "[noparse]{0}[/noparse]: You have not been ignoring [i][noparse]{1}[/noparse][/i].", message.UserName, blockSender )); return; } using (var ctx = GetNewContext()) { var entry = ctx.IgnoreList .FirstOrDefault(ie => ie.SenderFolded == blockSenderLower && ie.RecipientFolded == blockRecipientLower); ctx.IgnoreList.Remove(entry); ctx.SaveChanges(); } Logger.DebugFormat( "{0} is not ignoring {1} anymore", Util.LiteralString(message.UserName), Util.LiteralString(blockSender) ); Connector.SendMessage(string.Format( "[noparse]{0}[/noparse]: You are not ignoring [i][noparse]{1}[/noparse][/i] anymore.", message.UserName, blockSender )); } }
protected override void ProcessUpdatedMessage(ChatboxMessage message, bool isPartOfInitialSalvo = false, bool isEdited = false, bool isBanned = false) { if (isBanned || isEdited || isPartOfInitialSalvo) { return; } if (message.UserName == Connector.ForumConfig.Username) { return; } var body = message.BodyBBCode; var thanksMatch = ThankRegex.Match(body); if (thanksMatch.Success) { var nickname = thanksMatch.Groups[1].Value.Trim(); var lowerNickname = nickname.ToLowerInvariant(); if (lowerNickname == message.UserName.ToLowerInvariant()) { Connector.SendMessage(string.Format( "You are so full of yourself, [noparse]{0}[/noparse].", message.UserName )); return; } UserIDAndNickname?userInfo = null; try { userInfo = Connector.UserIDAndNicknameForUncasedName(nickname); } catch (TransferException) { // never mind } if (!userInfo.HasValue) { Connector.SendMessage(string.Format( "I don't know '[noparse]{0}[/noparse]'!", nickname )); return; } Logger.DebugFormat("{0} thanks {1}", message.UserName, nickname); long thankedCount = -1; using (var ctx = GetNewContext()) { var entry = ctx.ThanksEntries.Where(te => te.Thanker == message.UserName && te.ThankeeFolded == lowerNickname).FirstOrDefault(); if (entry == null) { entry = new ThanksEntry { Thanker = message.UserName, ThankeeFolded = lowerNickname, ThankCount = 1 }; ctx.ThanksEntries.Add(entry); } else { ++entry.ThankCount; } ctx.SaveChanges(); thankedCount = ctx.ThanksEntries.Where(te => te.ThankeeFolded == lowerNickname).Sum(te => te.ThankCount); } Connector.SendMessage(string.Format( "[noparse]{0}[/noparse]: Alright! By the way, [noparse]{1}[/noparse] has been thanked {2} until now.", message.UserName, userInfo.Value.Nickname, (thankedCount == 1) ? "once" : (thankedCount + " times") )); } else if (body.StartsWith("!thanked ")) { var nickname = body.Substring(("!thanked ").Length).Trim(); var lowerNickname = nickname.ToLowerInvariant(); UserIDAndNickname?userInfo = null; try { userInfo = Connector.UserIDAndNicknameForUncasedName(nickname); } catch (TransferException) { // never mind } if (!userInfo.HasValue) { Connector.SendMessage(string.Format( "I don't know '[noparse]{0}[/noparse]'!", nickname )); return; } long thankedCount = -1; using (var ctx = GetNewContext()) { thankedCount = ctx.ThanksEntries.Where(te => te.ThankeeFolded == lowerNickname).Sum(te => te.ThankCount); } string countPhrase = null; bool showStats = (thankedCount != 0); if (thankedCount == 0) { countPhrase = "not been thanked"; } else if (thankedCount == 1) { countPhrase = "been thanked once"; } else { countPhrase = string.Format("been thanked {0} times", thankedCount); } var statsString = ""; if (showStats) { List <string> mostGratefulStrings; using (var ctx = GetNewContext()) { mostGratefulStrings = ctx.ThanksEntries .Where(te => te.ThankeeFolded == lowerNickname) .OrderByDescending(te => te.ThankCount) .Take(_config.MostGratefulCount + 1) .ToList() .Select(te => string.Format("[noparse]{0}[/noparse]: {1}\u00D7", te.Thanker, te.ThankCount)) .ToList(); } // mention that the list is truncated if there are more than MostGratefulCount entries var countString = (mostGratefulStrings.Count <= _config.MostGratefulCount) ? "" : (" " + _config.MostGratefulCountText); statsString = string.Format( " (Most grateful{0}: {1})", countString, string.Join(", ", mostGratefulStrings.Take(_config.MostGratefulCount)) ); } Connector.SendMessage(string.Format( "[noparse]{0}: {1}[/noparse] has {2} until now.{3}", message.UserName, userInfo.Value.Nickname, countPhrase, statsString )); } else if (body == "!topthanked") { List <ThankeeAndCount> top; using (var ctx = GetNewContext()) { top = ctx.ThanksEntries .GroupBy(te => te.ThankeeFolded) .Select(teg => new ThankeeAndCount { ThankeeFolded = teg.FirstOrDefault().ThankeeFolded, ThankCount = teg.Sum(te => te.ThankCount) }) .OrderByDescending(teg => teg.ThankCount) .Take(_config.MostThankedCount) .ToList() ; } var topStrings = new List <string>(); foreach (var thankeeAndCount in top) { var actualUsername = thankeeAndCount.ThankeeFolded; try { var info = Connector.UserIDAndNicknameForUncasedName(thankeeAndCount.ThankeeFolded); if (info.HasValue) { actualUsername = info.Value.Nickname; } } catch (TransferException) { } topStrings.Add(string.Format("{0}: {1}", actualUsername, thankeeAndCount.ThankCount)); } Connector.SendMessage(string.Format( "[noparse]{0}[/noparse]: {1}", message.UserName, string.Join(", ", topStrings) )); } }
protected void PotentialMessageSend(ChatboxMessage message) { var body = message.BodyBBCode; var match = MsgTrigger.Match(body); if (!match.Success) { return; } var lowerSenderName = message.UserName.ToLowerInvariant(); var recipientAndMessage = match.Groups[2].Value; RecipientAndMessage ram; try { ram = SplitRecipientAndMessage(recipientAndMessage); } catch (FormatException exc) { Connector.SendMessage(string.Format( "[noparse]{0}[/noparse]: {1}", message.UserName, exc.Message )); return; } var targetName = Util.RemoveControlCharactersAndStrip(ram.Recipient); var lowerTargetName = targetName.ToLowerInvariant(); var sendBody = Util.RemoveControlCharactersAndStrip(ram.Message); //var lowerSenderName = message.UserName.ToLowerInvariant(); if (lowerTargetName.Length == 0) { Connector.SendMessage(string.Format("[noparse]{0}[/noparse]: You must specify a name to deliver to!", message.UserName)); return; } if (sendBody.Length == 0) { Connector.SendMessage(string.Format("[noparse]{0}[/noparse]: You must specify a message to deliver!", message.UserName)); return; } if (lowerTargetName == Connector.ForumConfig.Username.ToLowerInvariant()) { Connector.SendMessage(string.Format("[noparse]{0}[/noparse]: Sorry, I don\u2019t deliver to myself!", message.UserName)); return; } UserIDAndNickname?userInfo; try { userInfo = Connector.UserIDAndNicknameForUncasedName(targetName); } catch (TransferException) { Connector.SendMessage(string.Format( "[noparse]{0}[/noparse]: Sorry, I couldn\u2019t verify if \u201c[noparse]{1}[/noparse] exists because the forum isn\u2019t being cooperative. Please try again later!", message.UserName, targetName )); return; } if (!userInfo.HasValue) { var colonInfo = ""; if (sendBody.Contains(":")) { colonInfo = " (You may escape colons in usernames using a backslash.)"; } else if (targetName.Length > 32) { colonInfo = " (You must place a colon between the username and the message.)"; } Connector.SendMessage(string.Format( "[noparse]{0}[/noparse]: Sorry, I don\u2019t know \u201c[noparse]{1}[/noparse]\u201d.{2}", message.UserName, targetName, colonInfo )); return; } // check ignore list bool isIgnored; using (var ctx = GetNewContext()) { isIgnored = ctx.IgnoreList.Any(il => il.SenderFolded == lowerSenderName && il.RecipientFolded == lowerTargetName); } if (isIgnored) { Logger.DebugFormat( "{0} wants to send message {1} to {2}, but the recipient is ignoring the sender", Util.LiteralString(message.UserName), Util.LiteralString(sendBody), Util.LiteralString(targetName) ); Connector.SendMessage(string.Format( "[noparse]{0}[/noparse]: Can\u2019t send a message to [i][noparse]{1}[/noparse][/i]\u2014they\u2019re ignoring you.", message.UserName, userInfo.Value.Nickname )); return; } Logger.DebugFormat( "{0} sending message {1} to {2}", Util.LiteralString(message.UserName), Util.LiteralString(sendBody), Util.LiteralString(targetName) ); using (var ctx = GetNewContext()) { var msg = new Message { ID = message.ID, Timestamp = message.Timestamp.ToUniversalTimeForDatabase(), SenderOriginal = message.UserName, RecipientFolded = lowerTargetName, Body = sendBody }; ctx.Messages.Add(msg); ctx.SaveChanges(); } if (match.Groups[1].Value == "s") { // silent msg return; } if (lowerTargetName == lowerSenderName) { Connector.SendMessage(string.Format( "[noparse]{0}[/noparse]: Talking to ourselves? Well, no skin off my back. I\u2019ll deliver your message to you right away. ;)", message.UserName )); } else { Connector.SendMessage(string.Format( "[noparse]{0}[/noparse]: Aye-aye! I\u2019ll deliver your message to [i][noparse]{1}[/noparse][/i] next time I see \u2019em!", message.UserName, userInfo.Value.Nickname )); } }
/// <summary> /// Checks whether an existing ECHELON trigger is to be modified and potentially does so. /// </summary> protected void PotentialModifySpy(ChatboxMessage message) { var modMatch = ModifySpyTrigger.Match(message.BodyBBCode); var modMatchAll = ModifySpyAllTrigger.Match(message.BodyBBCode); long triggerID; string triggerUsernameLower; string triggerRegex; if (modMatch.Success) { triggerID = long.Parse(modMatch.Groups[1].Value); triggerUsernameLower = modMatch.Groups[2].Value.Trim().ToLowerInvariant(); triggerRegex = modMatch.Groups[3].Value.Trim(); } else if (modMatchAll.Success) { triggerID = long.Parse(modMatchAll.Groups[1].Value); triggerUsernameLower = null; triggerRegex = modMatchAll.Groups[2].Value.Trim(); } else { return; } var userLevel = GetUserLevel(message.UserName); var salutation = userLevel.ToString(); if (userLevel != UserLevel.Spymaster) { SendInsufficientRankMessage(salutation, message.UserName); return; } using (var ctx = GetNewContext()) { var trig = ctx.Triggers.FirstOrDefault(t => t.Id == triggerID); if (trig == null) { Connector.SendMessage(string.Format( "{0} [noparse]{1}[/noparse]: The trigger with this ID does not exist.", salutation, message.UserName )); return; } trig.TargetNameLower = triggerUsernameLower; trig.Regex = triggerRegex; trig.SpymasterName = message.UserName; ctx.SaveChanges(); } Connector.SendMessage(string.Format( "{0} [noparse]{1}[/noparse]: Updated.", salutation, message.UserName )); }