protected void ProcessStalkChildren(XmlElement element, string flag, ComplexStalk complexStalk) { var foundSearchTree = false; if (element.HasChildNodes) { var childNodeCollection = element.ChildNodes; foreach (XmlNode node in childNodeCollection) { var xmlElement = node as XmlElement; if (xmlElement == null) { continue; } if (xmlElement.Name == "searchtree") { foundSearchTree = true; try { complexStalk.SetStalkTree( this.StalkNodeFactory.NewFromXmlFragment((XmlElement)xmlElement.FirstChild)); } catch (WebException ex) { this.Logger.ErrorFormat( ex, "Error loading stalk {0} in {1} from XML.", complexStalk.Identifier, complexStalk.Channel); complexStalk.IsEnabled = false; complexStalk.Description = complexStalk.Description + "; Disabled automatically on load due to unhandled exception."; } continue; } if (xmlElement.Name == "subscribers") { complexStalk.Subscribers.AddRange( this.PopulateSubscribers(xmlElement.ChildNodes)); continue; } this.Logger.DebugFormat("Unrecognised child {0} of stalk {1}", xmlElement.Name, flag); } if (!foundSearchTree) { this.Logger.InfoFormat("Assuming stalk {0} is legacy", flag); complexStalk.SetStalkTree(this.StalkNodeFactory.NewFromXmlFragment((XmlElement)element.FirstChild)); } } }
public void ShouldSetLastModified() { var stalk = new ComplexStalk("abc"); var span = DateTime.UtcNow - stalk.LastUpdateTime; Assert.True(span.HasValue); Assert.Less(span.Value.TotalSeconds, 5); }
public void ShouldNotBeActive() { var stalk = new ComplexStalk("abc") { IsEnabled = false, ExpiryTime = null }; Assert.IsFalse(stalk.IsActive()); }
public void ShouldNotBeActiveWithExpiry() { var stalk = new ComplexStalk("abc") { IsEnabled = true, ExpiryTime = DateTime.UtcNow.AddMinutes(-1) }; Assert.IsFalse(stalk.IsActive()); }
public void ShouldBeActive() { var stalk = new ComplexStalk("abc") { IsEnabled = true, ExpiryTime = null }; Assert.IsTrue(stalk.IsActive()); }
public dynamic PostNewStalk(dynamic parameters) { var channel = this.channelConfiguration.Items.FirstOrDefault(x => x.Guid == parameters.channel); if (channel == null) { return(new NotFoundResponse()); } if (!this.UserCanConfigureStalks(this.Context, channel)) { return(new NotFoundResponse()); } if (string.IsNullOrWhiteSpace(this.Request.Form.stalkIdentifier)) { var newStalkModel = this.NewStalk(parameters); newStalkModel.Errors.Add("You must set a stalk identifier."); return(newStalkModel); } if (channel.Stalks.ContainsKey(this.Request.Form.stalkIdentifier)) { var newStalkModel = this.NewStalk(parameters); newStalkModel.Errors.Add("This stalk identifier is already in use in this channel."); return(newStalkModel); } IStalk stalk = new ComplexStalk(this.Request.Form.stalkIdentifier) { Channel = channel.Identifier, WatchChannel = this.AppConfiguration.WikimediaChannel }; channel.Stalks.Add(stalk.Identifier, stalk); this.channelConfiguration.Save(); this.FreenodeClient.SendMessage( stalk.Channel, "The stalk " + stalk.Identifier + " was created by " + this.Context.CurrentUser.UserName + " from the web interface."); return(this.Response.AsRedirect(string.Format("/channels/{0}/stalk/{1}/edit", channel.Guid, stalk.Identifier))); }
// ReSharper disable once UnusedMember.Global protected IEnumerable <CommandResponse> AddMode() { var tokenList = this.Arguments; var stalkName = tokenList.First(); var stalk = new ComplexStalk(stalkName) { Channel = this.CommandSource, WatchChannel = this.config.WikimediaChannel }; this.channelConfiguration[this.CommandSource].Stalks.Add(stalk.Identifier, stalk); yield return(new CommandResponse { Message = string.Format("Added disabled stalk {0} with CSL value: {1}", stalkName, stalk.SearchTree) }); this.channelConfiguration.Save(); }
public IStalk NewFromTemplate(string flag, ITemplate template, IList <string> parameters) { var formatParameters = parameters.ToArray <object>(); var templateSearchTree = string.Format(new StalkConfigFormatter(), template.SearchTree, formatParameters); var doc = new XmlDocument(); doc.LoadXml(templateSearchTree); var stalkNode = this.stalkNodeFactory.NewFromXmlFragment(doc.DocumentElement); if (flag == null) { if (template.StalkFlag == null) { throw new Exception("Cannot create stalk without defined flag"); } flag = string.Format(template.StalkFlag, formatParameters); } string description = null; if (template.Description != null) { description = string.Format(template.Description, formatParameters); } var stalk = new ComplexStalk(flag) { Description = description, IsEnabled = template.StalkIsEnabled, ExpiryTime = template.ExpiryDuration.HasValue ? DateTime.UtcNow + template.ExpiryDuration : null, SearchTree = stalkNode, WatchChannel = template.WatchChannel }; return(stalk); }
public void ShouldConstructFlag() { var stalk = new ComplexStalk("abc"); Assert.AreEqual("abc", stalk.Identifier); }
protected override void execute(User source, string destination, string[] tokens) { // =acc id user if (tokens.Length < 2) { EyeInTheSkyBot.IrcFreenode.ircNotice(source.nickname, "More params pls!"); return; } string id = GlobalFunctions.popFromFront(ref tokens); string user = string.Join(" ", tokens); var s = new ComplexStalk( "acc" + id ); OrNode or = new OrNode(); OrNode uor = new OrNode(); UserStalkNode usn = new UserStalkNode(); usn.setMatchExpression(user); PageStalkNode psn = new PageStalkNode(); psn.setMatchExpression(user); uor.LeftChildNode = usn; uor.RightChildNode = psn; OrNode upor = new OrNode(); PageStalkNode upsn = new PageStalkNode(); upsn.setMatchExpression("User:"******"User talk:" + user); upor.LeftChildNode = upsn; upor.RightChildNode = utpsn; SummaryStalkNode ssn = new SummaryStalkNode(); ssn.setMatchExpression(user); OrNode or2 = new OrNode(); or2.LeftChildNode = uor; or2.RightChildNode = upor; or.LeftChildNode = or2; or.RightChildNode = ssn; s.immediatemail = true; s.Description = "ACC " + id + ": " + user; s.mail = false; s.setSearchTree(or, true); s.enabled = true; s.expiryTime = DateTime.Now.AddMonths(3); EyeInTheSkyBot.Config.Stalks.Add("acc" + id, s); EyeInTheSkyBot.Config.save(); EyeInTheSkyBot.IrcFreenode.ircPrivmsg(destination, "Set new stalk " + s.Flag + " with CSL value: " + or); }
public IStalk NewFromXmlElement(XmlElement element) { var flag = element.Attributes["flag"].Value; // Last update time var timeAttribute = element.Attributes["lastupdate"]; DateTime?lastUpdateTime = null; if (timeAttribute != null) { lastUpdateTime = this.ParseDate(flag, timeAttribute.Value, "last update time"); } // Creation time var creationAttribute = element.Attributes["creation"]; var creation = DateTime.MinValue; if (creationAttribute != null) { creation = this.ParseDate(flag, creationAttribute.Value, "creation time"); } // Last trigger time timeAttribute = element.Attributes["lasttrigger"]; DateTime?lastTriggerTime = null; if (timeAttribute != null) { lastTriggerTime = this.ParseDate(flag, timeAttribute.Value, "last trigger time"); // backwards compat if (lastTriggerTime == new DateTime(1970, 1, 1, 0, 0, 0)) { lastTriggerTime = null; } } // Expiry time timeAttribute = element.Attributes["expiry"]; DateTime?expiryTime = null; if (timeAttribute != null) { expiryTime = this.ParseDate(flag, timeAttribute.Value, "expiry time"); // backwards compat if (expiryTime == new DateTime(9999, 12, 31, 23, 59, 59)) { expiryTime = null; } } // Dynamic expiry var dynamicExpiryAttribute = element.GetAttribute("dynamicexpiry"); TimeSpan?dynamicExpiry = null; if (!string.IsNullOrWhiteSpace(dynamicExpiryAttribute)) { dynamicExpiry = XmlConvert.ToTimeSpan(dynamicExpiryAttribute); } // Enabled attribute var enabledText = element.GetAttribute("enabled"); bool enabled; if (!bool.TryParse(enabledText, out enabled)) { this.Logger.WarnFormat( "Unable to parse enabled attribute value '{1}' for stalk {0}. Defaulting to enabled.", flag, enabledText); enabled = true; } var triggercountText = element.GetAttribute("triggercount"); int triggerCount; int.TryParse(triggercountText, out triggerCount); var description = element.GetAttribute("description"); if (string.IsNullOrWhiteSpace(description)) { description = null; } var lastMessageId = element.GetAttribute("lastmessageid"); if (string.IsNullOrWhiteSpace(lastMessageId)) { lastMessageId = null; } var watchChannel = element.GetAttribute("watchchannel"); if (string.IsNullOrWhiteSpace(watchChannel)) { watchChannel = this.appConfig.WikimediaChannel; } var s = new ComplexStalk( flag, lastUpdateTime, lastTriggerTime, description, expiryTime, enabled, triggerCount, lastMessageId, watchChannel, dynamicExpiry, creation); this.ProcessStalkChildren(element, flag, s); return(s); }
// ReSharper disable once UnusedMember.Global protected IEnumerable <CommandResponse> CloneMode() { var tokenList = this.Arguments; var sourceChannel = tokenList[0]; var sourceIdentifier = tokenList[1]; var targetIdentifier = tokenList[2]; var sourceChannelConfig = this.channelConfiguration.ContainsKey(sourceChannel) ? this.channelConfiguration[sourceChannel] : null; if (sourceChannelConfig == null) { throw new CommandErrorException(string.Format("The channel {0} does not exist in configuration", sourceChannel)); } var sourceStalk = sourceChannelConfig.Stalks.ContainsKey(sourceIdentifier) ? sourceChannelConfig.Stalks[sourceIdentifier] : null; if (sourceStalk == null) { throw new CommandErrorException(string.Format("The channel {0} does not exist in configuration", sourceChannel)); } if (this.channelConfiguration[this.CommandSource].Stalks.ContainsKey(targetIdentifier)) { throw new CommandErrorException(string.Format("The identifier {0} already exists in this channel!", targetIdentifier)); } var tree = sourceStalk.SearchTree; // bounce it via XML to ensure its a) different objects and b) saves properly tree = this.stalkNodeFactory.NewFromXmlFragment(this.stalkNodeFactory.ToXml(new XmlDocument(), tree)); var newStalk = new ComplexStalk(targetIdentifier) { Channel = this.CommandSource, Description = string.Format("{0}; based on stalk {1} from {2}", sourceStalk.Description, sourceIdentifier, sourceChannel), ExpiryTime = sourceStalk.ExpiryTime, IsEnabled = sourceStalk.IsEnabled, SearchTree = tree, WatchChannel = sourceStalk.WatchChannel, DynamicExpiry = sourceStalk.DynamicExpiry, LastTriggerTime = sourceStalk.LastTriggerTime }; this.channelConfiguration[this.CommandSource].Stalks.Add(newStalk.Identifier, newStalk); this.channelConfiguration.Save(); yield return(new CommandResponse { Message = string.Format("Created new {1} stalk {0}{2} with CSL {3}", newStalk.Identifier, newStalk.IsEnabled ? "enabled" : "disabled", newStalk.ExpiryTime.HasValue ? newStalk.ExpiryTime < DateTime.UtcNow ? string.Format(" (expired {0:%d}d {0:%h}h {0:%m}m ago)", newStalk.ExpiryTime.Value - DateTime.UtcNow) : string.Format(" (expiring in {0:%d}d {0:%h}h {0:%m}m)", newStalk.ExpiryTime.Value - DateTime.UtcNow) : string.Empty, tree ) }); }
protected override void execute(User source, string destination, string[] tokens) { // =quick token type value if (tokens.Length < 3) { EyeInTheSkyBot.IrcFreenode.ircNotice(source.nickname, "More params pls!"); return; } string name = GlobalFunctions.popFromFront(ref tokens); string type = GlobalFunctions.popFromFront(ref tokens); string regex = string.Join(" ", tokens); var s = new ComplexStalk(name); EyeInTheSkyBot.Config.Stalks.Add(name, s); switch (type) { case "user": UserStalkNode usn = new UserStalkNode(); usn.setMatchExpression(regex); s.setSearchTree(usn, true); EyeInTheSkyBot.IrcFreenode.ircPrivmsg(destination, "Set " + type + " for new stalk " + name + " with CSL value: " + usn); break; case "page": PageStalkNode psn = new PageStalkNode(); psn.setMatchExpression(regex); s.setSearchTree(psn, true); EyeInTheSkyBot.IrcFreenode.ircPrivmsg(destination, "Set " + type + " for new stalk " + name + " with CSL value: " + psn); break; case "summary": SummaryStalkNode ssn = new SummaryStalkNode(); ssn.setMatchExpression(regex); s.setSearchTree(ssn, true); EyeInTheSkyBot.IrcFreenode.ircPrivmsg(destination, "Set " + type + " for new stalk " + name + " with CSL value: " + ssn); break; case "xml": string xmlfragment = string.Join(" ", tokens); try { XmlDocument xd = new XmlDocument(); xd.LoadXml(xmlfragment); StalkNode node = StalkNode.newFromXmlFragment(xd.FirstChild); s.setSearchTree(node, true); EyeInTheSkyBot.IrcFreenode.ircPrivmsg(destination, "Set " + type + " for new stalk " + name + " with CSL value: " + node); } catch (XmlException) { EyeInTheSkyBot.IrcFreenode.ircNotice(source.nickname, "XML Error."); } break; default: EyeInTheSkyBot.IrcFreenode.ircNotice(source.nickname, "Unknown stalk type!"); return; } s.enabled = true; EyeInTheSkyBot.Config.save(); }
protected override void execute(User source, string destination, string[] tokens) { if (tokens.Length < 1) { EyeInTheSkyBot.IrcFreenode.ircNotice(source.nickname, "More params pls!"); return; } string mode = GlobalFunctions.popFromFront(ref tokens); if(mode == "add") #region add { if (tokens.Length < 1) { EyeInTheSkyBot.IrcFreenode.ircNotice(source.nickname, "More params pls!"); return; } var s = new ComplexStalk(tokens[0]); EyeInTheSkyBot.Config.Stalks.Add(tokens[0],s); EyeInTheSkyBot.IrcFreenode.ircPrivmsg(destination, "Added stalk " + tokens[0]); } #endregion if (mode == "del") #region del { if (tokens.Length < 1) { EyeInTheSkyBot.IrcFreenode.ircNotice(source.nickname, "More params pls!"); return; } EyeInTheSkyBot.Config.Stalks.Remove(tokens[0]); EyeInTheSkyBot.IrcFreenode.ircPrivmsg(destination, "Deleted stalk " + tokens[0]); } #endregion if (mode == "set") #region set { if (tokens.Length < 1) { EyeInTheSkyBot.IrcFreenode.ircNotice(source.nickname, "More params pls!"); return; } string stalk = GlobalFunctions.popFromFront(ref tokens); ComplexStalk s = EyeInTheSkyBot.Config.Stalks[stalk]; if (tokens.Length < 1) { EyeInTheSkyBot.IrcFreenode.ircNotice(source.nickname, "More params pls!"); return; } string type = GlobalFunctions.popFromFront(ref tokens); string regex = string.Join(" ", tokens); switch (type) { case "user": var usn = new UserStalkNode(); usn.setMatchExpression(regex); s.setSearchTree(usn, true); EyeInTheSkyBot.IrcFreenode.ircPrivmsg(destination, "Set " + type + " for stalk " + stalk + " with CSL value: " + usn); break; case "page": var psn = new PageStalkNode(); psn.setMatchExpression(regex); s.setSearchTree(psn, true); EyeInTheSkyBot.IrcFreenode.ircPrivmsg(destination, "Set " + type + " for stalk " + stalk + " with CSL value: " + psn); break; case "summary": var ssn = new SummaryStalkNode(); ssn.setMatchExpression(regex); s.setSearchTree(ssn, true); EyeInTheSkyBot.IrcFreenode.ircPrivmsg(destination, "Set " + type + " for stalk " + stalk + " with CSL value: " + ssn); break; case "xml": string xmlfragment = string.Join(" ", tokens); try { var xd = new XmlDocument(); xd.LoadXml(xmlfragment); StalkNode node = StalkNode.newFromXmlFragment(xd.FirstChild); s.setSearchTree(node, true); EyeInTheSkyBot.IrcFreenode.ircPrivmsg(destination, "Set " + type + " for stalk " + stalk + " with CSL value: " + node); } catch (XmlException) { EyeInTheSkyBot.IrcFreenode.ircNotice(source.nickname, "XML Error."); } break; default: EyeInTheSkyBot.IrcFreenode.ircNotice(source.nickname, "Unknown stalk type!"); return; } } #endregion if (mode == "list") #region list { EyeInTheSkyBot.IrcFreenode.ircNotice(source.nickname, "Stalk list:"); foreach (KeyValuePair<string, ComplexStalk> kvp in EyeInTheSkyBot.Config.Stalks) { EyeInTheSkyBot.IrcFreenode.ircNotice(source.nickname, kvp.Value.ToString()); } EyeInTheSkyBot.IrcFreenode.ircNotice(source.nickname, "End of stalk list."); } #endregion if(mode == "mail") #region mail { if (tokens.Length < 2) { EyeInTheSkyBot.IrcFreenode.ircNotice(source.nickname, "More params pls!"); return; } if(tokens[1] == "immediate") { if (tokens.Length < 3 ) { EyeInTheSkyBot.IrcFreenode.ircNotice(source.nickname, "More params pls!"); return; } bool imail = bool.Parse(tokens[2]); EyeInTheSkyBot.Config.Stalks[tokens[0]].immediatemail = imail; EyeInTheSkyBot.IrcFreenode.ircPrivmsg(destination, "Set immediatemail attribute on stalk " + tokens[0] + " to " + imail); } bool mail = bool.Parse(tokens[1]); EyeInTheSkyBot.Config.Stalks[tokens[0]].mail = mail; EyeInTheSkyBot.IrcFreenode.ircPrivmsg(destination, "Set mail attribute on stalk " + tokens[0] + " to " + mail); } #endregion if(mode == "description") #region description { if (tokens.Length < 1) { EyeInTheSkyBot.IrcFreenode.ircNotice(source.nickname, "More params pls!"); return; } string stalk = GlobalFunctions.popFromFront(ref tokens); string descr = string.Join(" ", tokens); EyeInTheSkyBot.Config.Stalks[stalk].Description = descr; EyeInTheSkyBot.IrcFreenode.ircPrivmsg(destination, "Set description attribute on stalk " + stalk + " to " + descr); } #endregion if(mode == "expiry") #region expiry { if (tokens.Length < 2) { EyeInTheSkyBot.IrcFreenode.ircNotice(source.nickname, "More params pls!"); return; } string stalk = GlobalFunctions.popFromFront(ref tokens); string date = string.Join(" ", tokens); DateTime expiryTime = DateTime.Parse(date); EyeInTheSkyBot.Config.Stalks[stalk].expiryTime = expiryTime; EyeInTheSkyBot.IrcFreenode.ircPrivmsg(destination, "Set expiry attribute on stalk " + stalk + " to " + expiryTime); } #endregion if (mode == "enabled") #region enabled { if (tokens.Length < 2) { EyeInTheSkyBot.IrcFreenode.ircNotice(source.nickname, "More params pls!"); return; } bool enabled = bool.Parse(tokens[1]); EyeInTheSkyBot.Config.Stalks[tokens[0]].enabled = enabled; EyeInTheSkyBot.IrcFreenode.ircPrivmsg(destination, "Set enabled attribute on stalk " + tokens[0] + " to " + enabled); } #endregion if (mode == "and") #region and { if (tokens.Length < 1) { EyeInTheSkyBot.IrcFreenode.ircNotice(source.nickname, "More params pls!"); return; } string stalk = GlobalFunctions.popFromFront(ref tokens); ComplexStalk s = EyeInTheSkyBot.Config.Stalks[stalk]; if (tokens.Length < 1) { EyeInTheSkyBot.IrcFreenode.ircNotice(source.nickname, "More params pls!"); return; } string type = GlobalFunctions.popFromFront(ref tokens); string regex = string.Join(" ", tokens); var newroot = new AndNode {LeftChildNode = s.getSearchTree()}; switch (type) { case "user": var usn = new UserStalkNode(); usn.setMatchExpression(regex); newroot.RightChildNode = usn; s.setSearchTree(newroot, true); EyeInTheSkyBot.IrcFreenode.ircPrivmsg(destination, "Set " + type + " for stalk " + stalk + " with CSL value: " + newroot); break; case "page": var psn = new PageStalkNode(); psn.setMatchExpression(regex); newroot.RightChildNode = psn; s.setSearchTree(newroot, true); EyeInTheSkyBot.IrcFreenode.ircPrivmsg(destination, "Set " + type + " for stalk " + stalk + " with CSL value: " + newroot); break; case "summary": var ssn = new SummaryStalkNode(); ssn.setMatchExpression(regex); newroot.RightChildNode = ssn; s.setSearchTree(newroot, true); EyeInTheSkyBot.IrcFreenode.ircPrivmsg(destination, "Set " + type + " for stalk " + stalk + " with CSL value: " + newroot); break; case "xml": string xmlfragment = string.Join(" ", tokens); try { var xd = new XmlDocument(); xd.LoadXml(xmlfragment); StalkNode node = StalkNode.newFromXmlFragment(xd.FirstChild); newroot.RightChildNode = node; s.setSearchTree(newroot, true); EyeInTheSkyBot.IrcFreenode.ircPrivmsg(destination, "Set " + type + " for stalk " + stalk + " with CSL value: " + newroot); } catch (XmlException) { EyeInTheSkyBot.IrcFreenode.ircNotice(source.nickname, "XML Error."); } break; default: EyeInTheSkyBot.IrcFreenode.ircNotice(source.nickname, "Unknown stalk type!"); return; } } #endregion if (mode == "or") #region or { if (tokens.Length < 1) { EyeInTheSkyBot.IrcFreenode.ircNotice(source.nickname, "More params pls!"); return; } string stalk = GlobalFunctions.popFromFront(ref tokens); ComplexStalk s = EyeInTheSkyBot.Config.Stalks[stalk]; if (tokens.Length < 1) { EyeInTheSkyBot.IrcFreenode.ircNotice(source.nickname, "More params pls!"); return; } string type = GlobalFunctions.popFromFront(ref tokens); string regex = string.Join(" ", tokens); var newroot = new OrNode { LeftChildNode = s.getSearchTree() }; switch (type) { case "user": var usn = new UserStalkNode(); usn.setMatchExpression(regex); newroot.RightChildNode = usn; s.setSearchTree(newroot, true); EyeInTheSkyBot.IrcFreenode.ircPrivmsg(destination, "Set " + type + " for stalk " + stalk + " with CSL value: " + newroot); break; case "page": var psn = new PageStalkNode(); psn.setMatchExpression(regex); newroot.RightChildNode = psn; s.setSearchTree(newroot, true); EyeInTheSkyBot.IrcFreenode.ircPrivmsg(destination, "Set " + type + " for stalk " + stalk + " with CSL value: " + newroot); break; case "summary": var ssn = new SummaryStalkNode(); ssn.setMatchExpression(regex); newroot.RightChildNode = ssn; s.setSearchTree(newroot, true); EyeInTheSkyBot.IrcFreenode.ircPrivmsg(destination, "Set " + type + " for stalk " + stalk + " with CSL value: " + newroot); break; case "xml": string xmlfragment = string.Join(" ", tokens); try { var xd = new XmlDocument(); xd.LoadXml(xmlfragment); StalkNode node = StalkNode.newFromXmlFragment(xd.FirstChild); newroot.RightChildNode = node; s.setSearchTree(newroot, true); EyeInTheSkyBot.IrcFreenode.ircPrivmsg(destination, "Set " + type + " for stalk " + stalk + " with CSL value: " + newroot); } catch (XmlException) { EyeInTheSkyBot.IrcFreenode.ircNotice(source.nickname, "XML Error."); } break; default: EyeInTheSkyBot.IrcFreenode.ircNotice(source.nickname, "Unknown stalk type!"); return; } } #endregion EyeInTheSkyBot.Config.save(); }