void GetNamespaces(bool snamespacesAlreadySet) { if (!snamespacesAlreadySet) { logger.InfoFormat("Fetching namespaces from {0}", rooturl); snamespaces = CVNBotUtils.GetRawDocument(rooturl + "w/api.php?format=xml&action=query&meta=siteinfo&siprop=namespaces"); if (snamespaces == "") { throw new Exception("Can't load list of namespaces from " + rooturl); } } namespaces = new Hashtable(); XmlDocument doc = new XmlDocument(); doc.LoadXml(snamespaces); string namespacesLogline = ""; XmlNode namespacesNode = doc.GetElementsByTagName("namespaces")[0]; for (int i = 0; i < namespacesNode.ChildNodes.Count; i++) { namespaces.Add(namespacesNode.ChildNodes[i].Attributes["id"].Value, namespacesNode.ChildNodes[i].InnerText); namespacesLogline += "id[" + namespacesNode.ChildNodes[i].Attributes["id"].Value + "]=" + namespacesNode.ChildNodes[i].InnerText + "; "; } }
void GetInterfaceMessages(Dictionary <string, MessagesOption> Messages) { string CombinedMessages = string.Join("|", Messages.Keys); string sMwMessages = CVNBotUtils.GetRawDocument( rooturl + "w/api.php?action=query&meta=allmessages&format=xml" + "&ammessages=" + CombinedMessages ); if (sMwMessages == "") { throw new Exception("Can't load list of InterfaceMessages from " + rooturl); } XmlDocument doc = new XmlDocument(); doc.LoadXml(sMwMessages); string mwMessagesLogline = ""; XmlNode allmessagesNode = doc.GetElementsByTagName("allmessages")[0]; for (int i = 0; i < allmessagesNode.ChildNodes.Count; i++) { string elmName = allmessagesNode.ChildNodes[i].Attributes["name"].Value; GenerateRegex( elmName, allmessagesNode.ChildNodes[i].InnerText, Messages[elmName].NumberOfArgs, Messages[elmName].RegexName, Messages[elmName].NonStrictFlag ); mwMessagesLogline += "name[" + elmName + "]=" + allmessagesNode.ChildNodes[i].InnerText + "; "; } }
void GenerateRegex(string mwMessageTitle, int reqCount, ref string destRegex, bool nonStrict) { // Get raw wikitext string mwMessage = CVNBotUtils.GetRawDocument(rooturl + "w/index.php?title=" + mwMessageTitle + "&action=raw&usemsgcache=yes"); // Now gently coax that into a regex foreach (char c in rechars) { mwMessage = mwMessage.Replace(c.ToString(), @"\" + c.ToString()); } mwMessage = mwMessage.Replace("$1", "(?<item1>.+?)"); mwMessage = mwMessage.Replace("$2", "(?<item2>.+?)"); mwMessage = mwMessage.Replace("$3", "(?<item3>.+?)"); mwMessage = mwMessage.Replace("$1", "(?:.+?)"); mwMessage = mwMessage.Replace("$2", "(?:.+?)"); mwMessage = mwMessage.Replace("$3", "(?:.+?)"); mwMessage = mwMessage.Replace("$", @"\$"); mwMessage = "^" + mwMessage + @"(?:: (?<comment>.*?))?$"; // Special:Log comments are preceded by a colon // Dirty code: Block log exceptions! if (mwMessageTitle == "MediaWiki:Blocklogentry") { mwMessage = mwMessage.Replace("(?<item3>.+?)", "\\((?<item3>.+?)\\)"); mwMessage = mwMessage.Replace(@"(?<item2>.+?)(?:: (?<comment>.*?))?$", "(?<item2>.+?)$"); } try { Regex.Match("", mwMessage); } catch (Exception e) { throw new Exception("Failed to test-generate regex " + mwMessage + " for " + mwMessageTitle + "; " + e.Message); } if (reqCount >= 1) { if (!mwMessage.Contains(@"(?<item1>.+?)") && !nonStrict) { throw new Exception("Regex " + mwMessageTitle + " requires one or more items but item1 not found in " + mwMessage); } if (reqCount >= 2) { if (!mwMessage.Contains(@"(?<item2>.+?)") && !nonStrict) { throw new Exception("Regex " + mwMessageTitle + " requires two or more items but item2 not found in " + mwMessage); } } } destRegex = mwMessage; }
/// <summary> /// Downloads a list of admins/bots from wiki and adds them to the database (Run this in a separate thread) /// </summary> void AddGroupToList(object data) { Dictionary <string, string> args = (Dictionary <string, string>)data; string projectName = args["project"]; string getGroup = args["group"]; Thread.CurrentThread.Name = "Get" + getGroup + "@" + projectName; UserType getGroupUT; if (getGroup == "sysop") { getGroupUT = UserType.admin; } else if (getGroup == "bot") { getGroupUT = UserType.bot; } else { throw new Exception("Undefined group: " + getGroup); } logger.InfoFormat("Fetching list of {0} users from {1}", getGroup, projectName); if (!Program.prjlist.ContainsKey(projectName)) { throw new Exception("Undefined project: " + projectName); } Project project = ((Project)Program.prjlist[projectName]); string resp = null; try { resp = CVNBotUtils.GetRawDocument(project.rooturl + "w/api.php?format=xml&action=query&list=allusers&augroup=" + getGroup + "&aulimit=max"); XmlDocument doc = new XmlDocument(); doc.LoadXml(resp); XmlNode list = doc.GetElementsByTagName("allusers")[0]; XmlNodeList nodes = list.ChildNodes; int total = nodes.Count; for (int i = 0; i < total; i++) { string name = nodes[i].Attributes["name"].Value; AddUserToList(name, projectName, getGroupUT, "CVNBot", "Auto-download from wiki", 0); } logger.InfoFormat("Added {0} {1} users from {2}", total, getGroup, projectName); } catch (Exception e) { if (resp != null) { logger.InfoFormat("Preview of failed user list fetch: {0}", resp.Substring(0, 100)); } logger.Error("Unable to get list", e); } }