public Enumerate ( ParameterCollection parameters, bool getAll ) : |
||
parameters | ParameterCollection | |
getAll | bool | |
Résultat |
public void Analyse(Wiki wiki) { Directory.CreateDirectory(_cacheDir); Regex wikiLinkRE = new Regex(@"\[{2}(.+?)(\|.+?)?]{2}"); ParameterCollection parameters = new ParameterCollection(); parameters.Add("generator", "categorymembers"); parameters.Add("gcmtitle", _l10i.Category); parameters.Add("gcmlimit", "max"); parameters.Add("gcmnamespace", "4"); parameters.Add("prop", "info"); XmlDocument doc = wiki.Enumerate(parameters, true); XmlNodeList pages = doc.SelectNodes("//page"); List<Day> days = new List<Day>(); foreach (XmlNode page in pages) { string prefix = _l10i.MainPage + "/"; string pageName = page.Attributes["title"].Value; if (pageName.Length < prefix.Length) { continue; } string date = pageName.Substring(prefix.Length); Day day = new Day(); if (!DateTime.TryParse(date, CultureInfo.CreateSpecificCulture(_l10i.Culture), DateTimeStyles.AssumeUniversal, out day.Date)) { continue; } string fileName = _cacheDir + date + ".bin"; string text = ""; if (File.Exists(fileName)) { using (FileStream fs = new FileStream(fileName, FileMode.Open)) using (GZipStream gs = new GZipStream(fs, CompressionMode.Decompress)) using (TextReader sr = new StreamReader(gs)) { string revid = sr.ReadLine(); if (revid == page.Attributes["lastrevid"].Value) { Console.Out.WriteLine("Loading " + pageName + "..."); text = sr.ReadToEnd(); } } } if (string.IsNullOrEmpty(text)) { Console.Out.WriteLine("Downloading " + pageName + "..."); text = wiki.LoadText(pageName); using (FileStream fs = new FileStream(fileName, FileMode.Create)) using (GZipStream gs = new GZipStream(fs, CompressionMode.Compress)) using (StreamWriter sw = new StreamWriter(gs)) { sw.WriteLine(page.Attributes["lastrevid"].Value); sw.Write(text); } } day.Page = WikiPage.Parse(pageName, text); days.Add(day); } days.Sort(CompareDays); using (StreamWriter sw = new StreamWriter(_cacheDir + "Main.txt")) { sw.WriteLine("{{" + _l10i.TopTemplate + "}}\n"); foreach (Day day in days) { sw.Write("{{" + _l10i.Template + "|" + day.Date.ToString("yyyy-M-d") + "|"); List<string> titles = new List<string>(); foreach (WikiPageSection section in day.Page.Sections) { ReplaceEmptyResults(section); RemoveStrikeOut(section); StrikeOutSection(section); string result = section.Reduce("", SubsectionsList); if (result.Length > 0) { result = " • <small>" + result.Substring(3) + "</small>"; } string title; if (_l10i.Processor != null) { title = _l10i.Processor(section).Trim(); } else { title = section.Title.Trim(); } titles.Add(title + result); } sw.Write(string.Join(" • ", titles.ConvertAll(c => c).ToArray())); sw.Write("}}\n\n"); } sw.WriteLine("{{" + _l10i.BottomTemplate + "}}"); } List<string> dates = new List<string>(); DateTime today = DateTime.Today; DateTime currentMonth = new DateTime(today.Year, today.Month, 1); for (int i = 0; i < 2; ++i) { DateTime start = currentMonth.AddMonths(-i); DateTime end = start.AddMonths(1); while (start < end) { string date = start.ToString("d MMMM yyyy", CultureInfo.CreateSpecificCulture(_l10i.Culture)); string prefix = _l10i.MainPage + "/"; string pageName = prefix + date; dates.Add(pageName); start = start.AddDays(1); } } parameters.Clear(); parameters.Add("prop", "info"); XmlDocument xml = wiki.Query(QueryBy.Titles, parameters, dates); days.Clear(); foreach (string pageName in dates) { string prefix = _l10i.MainPage + "/"; string date = pageName.Substring(prefix.Length); string fileName = _cacheDir + date + ".bin"; bool archived = doc.SelectSingleNode("//page[@title=\"" + pageName + "\"]") == null; XmlNode page = xml.SelectSingleNode("//page[@title=\"" + pageName + "\"]"); Day day = new Day(); day.Archived = archived; if (!DateTime.TryParse(date, CultureInfo.CreateSpecificCulture(_l10i.Culture), DateTimeStyles.AssumeUniversal, out day.Date)) { continue; } if (page.Attributes["missing"] != null) { day.Exists = false; days.Add(day); continue; } string text = ""; if (File.Exists(fileName)) { using (FileStream fs = new FileStream(fileName, FileMode.Open)) using (GZipStream gs = new GZipStream(fs, CompressionMode.Decompress)) using (TextReader sr = new StreamReader(gs)) { string revid = sr.ReadLine(); if (revid == page.Attributes["lastrevid"].Value) { Console.Out.WriteLine("Loading " + pageName + "..."); text = sr.ReadToEnd(); } } } if (string.IsNullOrEmpty(text)) { Console.Out.WriteLine("Downloading " + pageName + "..."); text = wiki.LoadText(pageName); using (FileStream fs = new FileStream(fileName, FileMode.Create)) using (GZipStream gs = new GZipStream(fs, CompressionMode.Compress)) using (StreamWriter sw = new StreamWriter(gs)) { sw.WriteLine(page.Attributes["lastrevid"].Value); sw.Write(text); } } day.Exists = true; day.Page = WikiPage.Parse(pageName, text); days.Add(day); } days.Sort(CompareDays); for (int i = 0; i < 2; ++i) { DateTime start = currentMonth.AddMonths(-i); DateTime end = start.AddMonths(1); string archiveDate = start.ToString("yyyy-MM"); IEnumerable<Day> daysInMonth = days.Where(d => d.Date >= start && d.Date < end); using (StreamWriter sw = new StreamWriter(_cacheDir + "Archive-" + archiveDate + ".txt")) { sw.WriteLine(_l10i.ArchiveHeader); StringBuilder sb = new StringBuilder(); foreach (Day day in daysInMonth) { sb.Append("{{" + _l10i.Template + "|" + day.Date.ToString("yyyy-M-d") + "|"); if (!day.Exists) { sb.Append("''" + _l10i.EmptyArchive + "''}}\n\n"); continue; } List<string> titles = new List<string>(); foreach (WikiPageSection section in day.Page.Sections) { string result = section.Reduce("", SubsectionsList); if (result.Length > 0) { result = " • <small>" + result.Substring(3) + "</small>"; } string title; if (_l10i.Processor != null) { title = _l10i.Processor(section).Trim(); } else { title = section.Title.Trim(); } titles.Add(title + result); } sb.Append(string.Join(" • ", titles.ConvertAll(c => c).ToArray())); sb.Append("}}\n\n"); } sb.Replace("<s>", ""); sb.Replace("</s>", ""); sb.Replace("<strike>", ""); sb.Replace("</strike>", ""); sw.Write(sb.ToString()); sw.WriteLine(_l10i.ArchiveFooter); } } }
public override Dictionary<string, string> Process(Wiki wiki, WikiPage page, ref int diffSize, ref int topicsArchived) { List<WikiPageSection> archivedSections = new List<WikiPageSection>(); foreach (WikiPageSection section in page.Sections) { WikiPageSection result = section.Subsections.FirstOrDefault(ss => ss.Title.Trim().ToLower() == "итог"); bool forceArchivation = LookForLines.Any(s => section.Text.ToLower().Contains(s.ToLower())); if (!OnHold.Any(s => section.Text.ToLower().Contains(s.ToLower())) && ((result != null && !string.IsNullOrEmpty(result.SectionText.Trim())) || forceArchivation || !CheckForResult)) { MatchCollection ms = timeRE.Matches(FilterQuotes(section.Text)); DateTime published = DateTime.Today; DateTime lastReply = DateTime.MinValue; foreach (Match match in ms) { string value = match.Groups[1].Value; DateTime time = DateTime.Parse(value, L10i.Culture, DateTimeStyles.AssumeUniversal); if (time < published) { published = time; } if (time > lastReply) { lastReply = time; } } if (lastReply != DateTime.MinValue && ((forceArchivation && (DateTime.Today - lastReply).TotalHours >= ForcedArchivationDelay) || (DateTime.Today - lastReply).TotalHours >= Delay)) { archivedSections.Add(section); } } if (IsMovedSection(section)) { section.SectionText = section.SectionText.Trim(new char[] { ' ', '\t', '\n' }) + "\n~~~~\n"; archivedSections.Add(section); } } Dictionary<string, string> archiveTexts = new Dictionary<string, string>(); if (archivedSections.Count == 0) { diffSize = 0; return archiveTexts; } var parameters = new ParameterCollection() { { "prop", "info" }, }; XmlDocument xml = wiki.Query(QueryBy.Titles, parameters, MainPage); int ns = int.Parse(xml.SelectSingleNode("//page").Attributes["ns"].Value); string prefix = wiki.GetNamespace(ns) + ":"; parameters = new ParameterCollection() { { "list", "allpages" }, { "apprefix", MainPage.Substring(prefix.Length) }, { "apnamespace", ns.ToString() } }; xml = wiki.Enumerate(parameters, true); int maxNumber = 1; foreach (XmlNode p in xml.SelectNodes("//p")) { string title = p.Attributes["title"].Value; string format = Format.Replace("{0}", ""); if (title.StartsWith(format)) { int number; if (int.TryParse(title.Substring(format.Length), out number)) { if (number > maxNumber) { maxNumber = number; } } } } int index = 0; string pageName = string.Format(Format, maxNumber); parameters.Clear(); parameters.Add("prop", "info"); xml = wiki.Query(QueryBy.Titles, parameters, new string[] { pageName }); XmlNode node = xml.SelectSingleNode("//page"); if (node.Attributes["missing"] == null) { string pageFileName = _cacheDir + Cache.GenerateCachePath(pageName); string text = Cache.LoadPageFromCache(pageFileName, node.Attributes["lastrevid"].Value, pageName); if (string.IsNullOrEmpty(text)) { Console.Out.WriteLine("Downloading " + pageName + "..."); text = wiki.LoadText(pageName); Cache.CachePage(pageName, _cacheDir, node.Attributes["lastrevid"].Value, text); } WikiPage archivePage = WikiPage.Parse(pageName, text); if (archivePage.Sections.Count < Topics) { int topics = Topics - archivePage.Sections.Count; for (int i = 0; i < topics && index < archivedSections.Count; ++i, ++index) { WikiPageSection section = archivedSections[index]; section.Title = ProcessSectionTitle(section.Title); archivePage.Sections.Add(section); } if (NewSectionsDown) { archivePage.Sections.Sort(SectionsDown); } else { archivePage.Sections.Sort(SectionsUp); } if (!string.IsNullOrEmpty(RemoveFromText)) { archivePage.Text = archivePage.Text.Replace(RemoveFromText, ""); } archiveTexts.Add(pageName, archivePage.Text); } } if (index < archivedSections.Count) { string text = Header; pageName = string.Format(Format, maxNumber + 1); WikiPage archivePage = WikiPage.Parse(pageName, text); for (; index < archivedSections.Count; ++index) { WikiPageSection section = archivedSections[index]; section.Title = ProcessSectionTitle(section.Title); archivePage.Sections.Add(section); } archivePage.Sections.Sort(SectionsUp); if (!string.IsNullOrEmpty(RemoveFromText)) { archivePage.Text = archivePage.Text.Replace(RemoveFromText, ""); } archiveTexts.Add(pageName, archivePage.Text); } topicsArchived = 0; diffSize = 0; foreach (var section in archivedSections) { diffSize += Encoding.UTF8.GetByteCount(section.Text); ++topicsArchived; page.Sections.Remove(section); } return archiveTexts; }
internal void AddNavigationTemplate(Wiki wiki) { ParameterCollection parameters = new ParameterCollection(); parameters.Add("list", "embeddedin"); parameters.Add("eititle", "Template:ВПКОБ-Навигация"); parameters.Add("eilimit", "max"); parameters.Add("einamespace", "4"); parameters.Add("eifilterredir", "nonredirects"); XmlDocument doc = wiki.Enumerate(parameters, true); List<string> titles = new List<string>(); DateTime end = DateTime.Today; DateTime start = end.AddDays(-7); while (start <= end) { string pageDate = start.ToString("d MMMM yyyy", CultureInfo.CreateSpecificCulture("ru-RU")); string prefix = "Википедия:К объединению/"; string pageName = prefix + pageDate; if (doc.SelectSingleNode("//ei[@title='" + pageName + "']") == null) { titles.Add(pageName); } start = start.AddDays(1); } parameters.Clear(); parameters.Add("prop", "info"); XmlDocument xml = wiki.Query(QueryBy.Titles, parameters, titles); foreach (XmlNode node in xml.SelectNodes("//page")) { if (node.Attributes["missing"] == null) { Console.Out.WriteLine("Updating " + node.Attributes["title"].Value + "..."); wiki.Prepend(node.Attributes["title"].Value, "{{ВПКОБ-Навигация}}\n", "добавление навигационного шаблона"); } } }
public void UpdateArchivePages(Wiki wiki) { ParameterCollection parameters = new ParameterCollection(); parameters.Add("generator", "categorymembers"); parameters.Add("gcmtitle", _l10i.Category); parameters.Add("gcmlimit", "max"); parameters.Add("gcmnamespace", "4"); parameters.Add("prop", "info"); XmlDocument doc = wiki.Enumerate(parameters, true); XmlNodeList pages = doc.SelectNodes("//page"); DateTime minDate = DateTime.Now; foreach (XmlNode page in pages) { string prefix = _l10i.MainPage + "/"; string pageName = page.Attributes["title"].Value; string date = pageName.Substring(prefix.Length); DateTime day; if (DateTime.TryParse(date, _l10i.Culture, DateTimeStyles.AssumeUniversal, out day)) { if (day < minDate) { minDate = day; } } else { continue; } } List<string> titles = new List<string>(); minDate = new DateTime(minDate.Year, minDate.Month, 1); DateTime currentMonth = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1); DateTime start = minDate; while (start <= currentMonth) { string date = start.ToString("yyyy-MM"); string pageName = _l10i.ArchivePage + date; titles.Add(pageName); start = start.AddMonths(1); } parameters.Clear(); parameters.Add("prop", "info"); XmlDocument archivesDoc = wiki.Query(QueryBy.Titles, parameters, titles); pages = archivesDoc.SelectNodes("//page"); foreach (XmlNode archivePage in pages) { string archiveName = archivePage.Attributes["title"].Value; string date = archiveName.Substring(_l10i.ArchivePage.Length); DateTime archiveDate; if (!DateTime.TryParse(date, _l10i.Culture, DateTimeStyles.AssumeUniversal, out archiveDate)) { continue; } string fileName = _cacheDir + "Archive-" + date + ".txt"; start = archiveDate; DateTime end = start.AddMonths(1); titles.Clear(); while (start < end) { string pageDate = start.ToString("d MMMM yyyy", _l10i.Culture); string prefix = _l10i.MainPage + "/"; string pageName = prefix + pageDate; titles.Add(pageName); start = start.AddDays(1); } parameters.Clear(); parameters.Add("prop", "info"); List<Day> days = new List<Day>(); XmlDocument xml = wiki.Query(QueryBy.Titles, parameters, titles); XmlNodeList archives = xml.SelectNodes("//page"); foreach (XmlNode page in archives) { string prefix = _l10i.MainPage + "/"; string pageName = page.Attributes["title"].Value; string dateString = pageName.Substring(prefix.Length); string pageFileName = _cacheDir + dateString + ".bin"; Day day = new Day(); day.Archived = doc.SelectSingleNode("//page[@title=\"" + pageName + "\"]") == null; if (!DateTime.TryParse(dateString, _l10i.Culture, DateTimeStyles.AssumeUniversal, out day.Date)) { continue; } if (page.Attributes["missing"] != null) { day.Exists = false; days.Add(day); continue; } string text = LoadPageFromCache(pageFileName, page.Attributes["lastrevid"].Value, pageName); if (string.IsNullOrEmpty(text)) { Console.Out.WriteLine("Downloading " + pageName + "..."); text = wiki.LoadText(pageName); CachePage(pageFileName, page.Attributes["lastrevid"].Value, text); } day.Exists = true; day.Page = WikiPage.Parse(pageName, text); days.Add(day); } days.Sort(CompareDays); StringBuilder textBuilder = new StringBuilder(); textBuilder.AppendLine(_l10i.ArchiveHeader); StringBuilder sb = new StringBuilder(); foreach (Day day in days) { sb.Append("{{" + _l10i.Template + "|" + day.Date.ToString("yyyy-M-d") + "|\n"); if (!day.Exists) { sb.Append("''" + _l10i.EmptyArchive + "''}}\n\n"); continue; } List<string> sectionTitles = new List<string>(); foreach (WikiPageSection section in day.Page.Sections) { string result = section.Reduce("", SubsectionsList); if (result.Length > 0) { result = " • <small>" + result.Substring(3) + "</small>"; } string title; if (_l10i.Processor != null) { title = _l10i.Processor(section).Trim(); } else { title = section.Title.Trim(); } sectionTitles.Add(title + result); } sb.Append(string.Join(" • ", sectionTitles.ConvertAll(c => c).ToArray())); sb.Append("}}\n\n"); } sb.Replace("<s>", ""); sb.Replace("</s>", ""); sb.Replace("<strike>", ""); sb.Replace("</strike>", ""); textBuilder.Append(sb.ToString()); textBuilder.AppendLine(_l10i.ArchiveFooter); if (File.Exists(fileName)) { using (TextReader sr = new StreamReader(fileName)) { string text = sr.ReadToEnd(); if (text == textBuilder.ToString()) { continue; } } } Console.Out.WriteLine("Updating " + archiveName + "..."); wiki.Save(archiveName, textBuilder.ToString(), _l10i.MainPageUpdateComment); using (StreamWriter sw = new StreamWriter(fileName)) { sw.Write(textBuilder.ToString()); } } }
private static bool MovedTo(Wiki wiki, string title, DateTime start, out string movedTo, out string movedBy, out DateTime movedAt) { ParameterCollection parameters = new ParameterCollection(); parameters.Add("list", "logevents"); parameters.Add("letitle", title); parameters.Add("letype", "move"); parameters.Add("lestart", start.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")); parameters.Add("ledir", "newer"); parameters.Add("lelimit", "max"); XmlDocument doc = wiki.Enumerate(parameters, true); XmlNodeList moved = doc.SelectNodes("//move"); List<Revision> revs = new List<Revision>(); foreach (XmlNode revision in moved) { revs.Add(new Revision(revision.Attributes["new_title"].Value, revision.ParentNode.Attributes["comment"].Value, revision.ParentNode.Attributes["timestamp"].Value, revision.ParentNode.Attributes["user"].Value)); } revs.Sort(CompareRevisions); if (revs.Count > 0) { bool result = MovedTo(wiki, revs[0].MovedTo, revs[0].Time, out movedTo, out movedBy, out movedAt); if (result) { return movedTo != title; } else { movedTo = revs[0].MovedTo; movedBy = revs[0].User; movedAt = revs[0].Time; return movedTo != title; } } movedTo = ""; movedBy = ""; movedAt = new DateTime(); return false; }
public void UpdateArchivePages(Wiki wiki) { ParameterCollection parameters = new ParameterCollection(); parameters.Add("generator", "categorymembers"); parameters.Add("gcmtitle", "Категория:Википедия:Незакрытые обсуждения объединения страниц"); parameters.Add("gcmlimit", "max"); parameters.Add("gcmnamespace", "4"); parameters.Add("prop", "info"); XmlDocument doc = wiki.Enumerate(parameters, true); XmlNodeList pages = doc.SelectNodes("//page"); DateTime minDate = DateTime.Now; foreach (XmlNode page in pages) { string pageName = page.Attributes["title"].Value; string date = pageName.Substring("Википедия:К объединению/".Length); try { DateTime day = DateTime.Parse(date, CultureInfo.CreateSpecificCulture("ru-RU"), DateTimeStyles.AssumeUniversal); if (day < minDate) { minDate = day; } } catch (FormatException) { continue; } } List<string> titles = new List<string>(); minDate = new DateTime(minDate.Year, minDate.Month, 1); DateTime currentMonth = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1); DateTime start = minDate; while (start <= currentMonth) { string date = start.ToString("yyyy-MM"); string pageName = "Википедия:Архив запросов на объединение/" + date; titles.Add(pageName); start = start.AddMonths(1); } parameters.Clear(); parameters.Add("prop", "info"); XmlDocument archivesDoc = wiki.Query(QueryBy.Titles, parameters, titles); pages = archivesDoc.SelectNodes("//page"); foreach (XmlNode archivePage in pages) { string archiveName = archivePage.Attributes["title"].Value; string date = archiveName.Substring("Википедия:Архив запросов на объединение/".Length); DateTime archiveDate; try { archiveDate = DateTime.Parse(date, CultureInfo.CreateSpecificCulture("ru-RU"), DateTimeStyles.AssumeUniversal); } catch (FormatException) { continue; } string fileName = _cacheDir + "Archive-" + date + ".txt"; start = archiveDate; DateTime end = start.AddMonths(1); titles.Clear(); while (start < end) { string pageDate = start.ToString("d MMMM yyyy", CultureInfo.CreateSpecificCulture("ru-RU")); string prefix = "Википедия:К объединению/"; string pageName = prefix + pageDate; titles.Add(pageName); start = start.AddDays(1); } parameters.Clear(); parameters.Add("prop", "info"); List<Day> days = new List<Day>(); XmlDocument xml = wiki.Query(QueryBy.Titles, parameters, titles); XmlNodeList archives = xml.SelectNodes("//page"); foreach (XmlNode page in archives) { string pageName = page.Attributes["title"].Value; string dateString = pageName.Substring("Википедия:К объединению/".Length); string pageFileName = _cacheDir + dateString + ".bin"; Day day = new Day(); day.Archived = doc.SelectSingleNode("//page[@title=\"" + pageName + "\"]") == null; try { day.Date = DateTime.Parse(dateString, CultureInfo.CreateSpecificCulture("ru-RU"), DateTimeStyles.AssumeUniversal); } catch (FormatException) { continue; } if (page.Attributes["missing"] != null) { day.Exists = false; days.Add(day); continue; } string text = LoadPageFromCache(pageFileName, page.Attributes["lastrevid"].Value, pageName); if (string.IsNullOrEmpty(text)) { Console.Out.WriteLine("Downloading " + pageName + "..."); text = wiki.LoadText(pageName); CachePage(pageFileName, page.Attributes["lastrevid"].Value, text); } day.Exists = true; day.Page = WikiPage.Parse(pageName, text); days.Add(day); } days.Sort(CompareDays); StringBuilder textBuilder = new StringBuilder(); textBuilder.AppendLine("{{Навигация по архиву КОБ}}\n{{Объединение статей/Начало}}"); StringBuilder sb = new StringBuilder(); foreach (Day day in days) { sb.Append("{{Объединение статей/День|" + day.Date.ToString("yyyy-M-d") + "|\n"); if (!day.Archived && day.Exists) { sb.Append("''обсуждение не завершено''}}\n\n"); continue; } if (!day.Exists) { sb.Append("''нет обсуждений''}}\n\n"); continue; } List<string> sectionTitles = new List<string>(); foreach (WikiPageSection section in day.Page.Sections) { string filler = ""; for (int i = 0; i < section.Level - 1; ++i) { filler += "*"; } sectionTitles.Add(filler + " " + section.Title.Trim()); List<WikiPageSection> sections = new List<WikiPageSection>(); section.Reduce(sections, SubsectionsList); foreach (WikiPageSection subsection in sections) { filler = ""; for (int i = 0; i < subsection.Level - 1; ++i) { filler += "*"; } sectionTitles.Add(filler + " " + subsection.Title.Trim()); } } if (sectionTitles.Count(s => s.Contains("=")) > 0) { titles[0] = "2=<li>" + titles[0].Substring(2) + "</li>"; } sb.Append(string.Join("\n", sectionTitles.ConvertAll(c => c).ToArray())); sb.Append("}}\n\n"); } sb.Replace("<s>", ""); sb.Replace("</s>", ""); sb.Replace("<strike>", ""); sb.Replace("</strike>", ""); textBuilder.Append(sb.ToString()); textBuilder.AppendLine("{{Объединение статей/Конец}}"); if (File.Exists(fileName)) { using (TextReader sr = new StreamReader(fileName)) { string text = sr.ReadToEnd(); if (text == textBuilder.ToString()) { continue; } } } Console.Out.WriteLine("Updating " + archiveName + "..."); wiki.Save(archiveName, textBuilder.ToString(), "обновление"); using (StreamWriter sw = new StreamWriter(fileName)) { sw.Write(textBuilder.ToString()); } } }
internal void UpdatePages(Wiki wiki) { ParameterCollection parameters = new ParameterCollection(); parameters.Add("generator", "categorymembers"); parameters.Add("gcmtitle", "Категория:Википедия:Незакрытые обсуждения восстановления страниц"); parameters.Add("gcmlimit", "max"); parameters.Add("gcmnamespace", "4"); parameters.Add("prop", "info|revisions"); parameters.Add("intoken", "edit"); XmlDocument doc = wiki.Enumerate(parameters, true); string queryTimestamp = DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ"); XmlNodeList pages = doc.SelectNodes("//page"); foreach (XmlNode page in pages) { string starttimestamp = queryTimestamp; int results = 0; string prefix = "Википедия:К восстановлению/"; string pageName = page.Attributes["title"].Value; string basetimestamp = page.FirstChild.FirstChild.Attributes["timestamp"].Value; string editToken = page.Attributes["edittoken"].Value; string date = pageName.Substring(prefix.Length); Day day = new Day(); if (!DateTime.TryParse(date, CultureInfo.CreateSpecificCulture("ru-RU"), DateTimeStyles.AssumeUniversal, out day.Date)) { continue; } string text = ""; string fileName = _cacheDir + date + ".bin"; if (File.Exists(fileName)) { using (FileStream fs = new FileStream(fileName, FileMode.Open)) using (GZipStream gs = new GZipStream(fs, CompressionMode.Decompress)) using (TextReader sr = new StreamReader(gs)) { string revid = sr.ReadLine(); if (revid == page.Attributes["lastrevid"].Value) { Console.Out.WriteLine("Loading " + pageName + "..."); text = sr.ReadToEnd(); } } } if (string.IsNullOrEmpty(text)) { try { Console.Out.WriteLine("Downloading " + pageName + "..."); text = wiki.LoadText(pageName); starttimestamp = DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ"); } catch (WikiPageNotFound) { continue; } using (FileStream fs = new FileStream(fileName, FileMode.Create)) using (GZipStream gs = new GZipStream(fs, CompressionMode.Compress)) using (StreamWriter sw = new StreamWriter(gs)) { sw.WriteLine(page.Attributes["lastrevid"].Value); sw.Write(text); } } Dictionary<string, List<WikiPageSection>> titles = new Dictionary<string, List<WikiPageSection>>(); day.Page = WikiPage.Parse(pageName, text); foreach (WikiPageSection section in day.Page.Sections) { RemoveStrikeOut(section); StrikeOutSection(section); if (section.Subsections.Count(s => _results.Any(r => r.ToLower() == s.Title.Trim().ToLower())) == 0) { Match m = _wikiLinkRE.Match(section.Title); if (m.Success) { string title = m.Groups[1].Value.Trim(); if (titles.ContainsKey(title)) { titles[title].Add(section); } else { titles.Add(title, new List<WikiPageSection>()); titles[title].Add(section); } } } { List<WikiPageSection> sections = new List<WikiPageSection>(); section.Reduce(sections, SubsectionsList); foreach (WikiPageSection subsection in sections) { Match m = _wikiLinkRE.Match(subsection.Title); if (m.Success && !subsection.Title.Contains("<s>") && subsection.Subsections.Count(s => _results.Any(r => r.ToLower() == s.Title.Trim().ToLower())) == 0) { string title = m.Groups[1].Value.Trim(); if (titles.ContainsKey(title)) { titles[title].Add(subsection); } else { titles.Add(title, new List<WikiPageSection>()); titles[title].Add(subsection); } } } } } parameters.Clear(); parameters.Add("prop", "info"); Dictionary<string, string> normalizedTitles = new Dictionary<string, string>(); XmlDocument xml = wiki.Query(QueryBy.Titles, parameters, titles.Keys); foreach (XmlNode node in xml.SelectNodes("//n")) { normalizedTitles.Add(node.Attributes["to"].Value, node.Attributes["from"].Value); } List<string> notificationList = new List<string>(); XmlNodeList missingTitles = xml.SelectNodes("//page"); foreach (XmlNode node in missingTitles) { string title = node.Attributes["title"].Value; IEnumerable<WikiPageSection> sections; if (titles.ContainsKey(title)) { sections = titles[title]; } else { sections = titles[normalizedTitles[title]]; } if (node.Attributes["missing"] == null) { DateTime start = day.Date; parameters.Clear(); parameters.Add("list", "logevents"); parameters.Add("letype", "delete"); parameters.Add("lemlimit", "max"); parameters.Add("lestart", start.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")); parameters.Add("ledir", "newer"); parameters.Add("letitle", title); parameters.Add("leprop", "comment|type|user|timestamp"); XmlDocument log = wiki.Enumerate(parameters, true); XmlNodeList items = log.SelectNodes("//item"); List<DeleteLogEvent> events = new List<DeleteLogEvent>(); foreach (XmlNode item in items) { DeleteLogEvent ev = new DeleteLogEvent(); ev.Comment = item.Attributes["comment"].Value; ev.Restored = item.Attributes["action"].Value == "restore"; ev.Deleted = item.Attributes["action"].Value == "delete"; ev.User = item.Attributes["user"].Value; ev.Timestamp = DateTime.Parse(item.Attributes["timestamp"].Value, null, DateTimeStyles.AssumeUniversal); events.Add(ev); } events.Sort(CompareDeleteLogEvents); if (events.Count > 0 && events[0].Restored && (DateTime.Now - events[0].Timestamp).TotalHours > 2) { Regex commentRE = new Regex(@" восстановлено: (.+)"); Match m = commentRE.Match(events[0].Comment); string comment; if (m.Success) { comment = m.Groups[1].Value; } else { comment = "<nowiki>" + events[0].Comment + "</nowiki>"; } string message = string.Format("Страница была восстановлена {1} администратором [[User:{0}|]]. Была указана следующая причина: «{2}». Данное сообщение было автоматически сгенерировано ботом ~~~~.\n", events[0].User, events[0].Timestamp.ToUniversalTime().ToString("d MMMM yyyy в HH:mm (UTC)"), comment); if (!titles.ContainsKey(title)) { continue; } foreach (WikiPageSection section in titles[title]) { WikiPageSection verdict = new WikiPageSection(" Автоматический итог ", section.Level + 1, message); section.AddSubsection(verdict); StrikeOutSection(section); ++results; } } else if (events.Count > 0 && events[0].Deleted) { parameters.Clear(); parameters.Add("prop", "revisions"); parameters.Add("rvprop", "timestamp|user"); parameters.Add("rvdir", "newer"); parameters.Add("rvlimit", "1"); parameters.Add("redirects"); log = wiki.Query(QueryBy.Titles, parameters, new string[] { title }); XmlNode revision = log.SelectSingleNode("//rev"); if (revision != null) { string user = revision.Attributes["user"].Value; string timestamp = revision.Attributes["timestamp"].Value; DateTime time = DateTime.Parse(timestamp, null, DateTimeStyles.AssumeUniversal); string message = string.Format("Страница была создана заново {1} участником [[User:{0}|]]. Данное сообщение было автоматически сгенерировано ботом ~~~~.\n", user, time.ToUniversalTime().ToString("d MMMM yyyy в HH:mm (UTC)")); if (!titles.ContainsKey(title)) { continue; } foreach (WikiPageSection section in titles[title]) { WikiPageSection verdict = new WikiPageSection(" Автоматический итог ", section.Level + 1, message); section.AddSubsection(verdict); StrikeOutSection(section); ++results; } } } } } string newText = day.Page.Text; if (newText.Trim() == text.Trim()) { continue; } try { Console.Out.WriteLine("Updating " + pageName + "..."); string revid = wiki.Save(pageName, "", newText, "зачёркивание заголовков" + (results > 0 ? " и подведение итогов" : ""), MinorFlags.Minor, CreateFlags.NoCreate, WatchFlags.None, SaveFlags.Replace, true, basetimestamp, "", editToken); using (FileStream fs = new FileStream(fileName, FileMode.Create)) using (GZipStream gs = new GZipStream(fs, CompressionMode.Compress)) using (StreamWriter sw = new StreamWriter(gs)) { sw.WriteLine(revid); sw.Write(newText); } } catch (WikiException) { } } }
public void Analyze(Wiki wiki) { ParameterCollection parameters = new ParameterCollection(); parameters.Add("generator", "categorymembers"); parameters.Add("gcmtitle", "Категория:Википедия:Незакрытые обсуждения переименования страниц"); parameters.Add("gcmlimit", "max"); parameters.Add("gcmnamespace", "4"); parameters.Add("prop", "info|revisions"); parameters.Add("rvprop", "timestamp"); XmlDocument doc = wiki.Enumerate(parameters, true); XmlNodeList pages = doc.SelectNodes("//page"); List<Day> days = new List<Day>(); DateTime start = DateTime.Today; Regex closedRE = new Regex(@"(\{{2}ВПКПМ-Навигация\}{2}\s*\{{2}(Закрыто|Closed|закрыто|closed)\}{2})|(\{{2}(Закрыто|Closed|закрыто|closed)\}{2}\s*\{{2}ВПКПМ-Навигация\}{2})"); wiki.SleepBetweenEdits = 10; wiki.SleepBetweenQueries = 2; DateTime cutOffDate = new DateTime(2009, 3, 21); foreach (XmlNode page in pages) { string pageName = page.Attributes["title"].Value; string date = pageName.Substring("Википедия:К переименованию/".Length); Day day = new Day(); try { day.Date = DateTime.Parse(date, CultureInfo.CreateSpecificCulture("ru-RU"), DateTimeStyles.AssumeUniversal); } catch (FormatException) { continue; } string fileName = _cacheDir + date + ".bin"; string text = ""; if (File.Exists(fileName)) { using (FileStream fs = new FileStream(fileName, FileMode.Open)) using (GZipStream gs = new GZipStream(fs, CompressionMode.Decompress)) using (TextReader sr = new StreamReader(gs)) { string revid = sr.ReadLine(); if (revid == page.Attributes["lastrevid"].Value) { Console.Out.WriteLine("Loading " + pageName + "..."); text = sr.ReadToEnd(); } } } if (string.IsNullOrEmpty(text)) { Console.Out.WriteLine("Downloading " + pageName + "..."); text = wiki.LoadText(pageName); using (FileStream fs = new FileStream(fileName, FileMode.Create)) using (GZipStream gs = new GZipStream(fs, CompressionMode.Compress)) using (StreamWriter sw = new StreamWriter(gs)) { sw.WriteLine(page.Attributes["lastrevid"].Value); sw.Write(text); } } DateTime lastEdit = DateTime.Parse(page.FirstChild.FirstChild.Attributes["timestamp"].Value, null, DateTimeStyles.AssumeUniversal); Match m = closedRE.Match(text); if ((DateTime.Now - lastEdit).TotalDays > 2 && m.Success) { text = text.Replace("{{ВПКПМ-Навигация}}", "{{ВПКПМ-Навигация|nocat=1}}"); try { string revid = wiki.Save(pageName, text, "обсуждение закрыто"); using (FileStream fs = new FileStream(fileName, FileMode.Create)) using (GZipStream gs = new GZipStream(fs, CompressionMode.Compress)) using (StreamWriter sw = new StreamWriter(gs)) { sw.WriteLine(revid); sw.Write(text); } } catch (WikiException) { } continue; } day.Page = WikiPage.Parse(pageName, text); days.Add(day); } days.Sort(CompareDays); using (StreamWriter sw = new StreamWriter(_cacheDir + "MainPage.txt")) { sw.WriteLine("{{/Шапка}}\n"); sw.WriteLine("{{Переименование статей/Статьи, вынесенные на переименование}}\n"); Regex wikiLinkRE = new Regex(@"\[{2}(.+?)(\|.+?)?]{2}"); foreach (Day day in days) { Console.Out.WriteLine("Analyzing " + day.Date.ToString("d MMMM yyyy") + "..."); sw.Write("{{Переименование статей/День|" + day.Date.ToString("yyyy-M-d") + "|\n"); List<string> titles = new List<string>(); foreach (WikiPageSection section in day.Page.Sections) { string filler = ""; string result = ""; RemoveStrikeOut(section); StrikeOutSection(section); if (section.SectionText.ToLower().Contains("{{mark out}}")) { section.Title = "{{mark out|" + section.Title.Trim() + "}}"; } bool hasVerdict = section.Subsections.Count(s => s.Title.ToLower().Trim() == "итог") > 0; bool hasAutoVerdict = section.Subsections.Count(s => s.Title.Trim() == "Автоматический итог") > 0; if (hasVerdict || hasAutoVerdict || section.Title.Contains("<s>")) { Match m = wikiLinkRE.Match(section.Title); if (m.Success && !m.Groups[1].Value.StartsWith(":Категория:")) { string link = m.Groups[1].Value; string movedTo; bool moved = MovedTo(wiki, link, day.Date, out movedTo); if (moved && string.IsNullOrEmpty(movedTo)) { result = " ''(переименовано)''"; } else if (moved) { result = string.Format(" ''({1}переименовано в «[[{0}]]»)''", movedTo.StartsWith("Файл:") ? ":" + movedTo : movedTo, hasAutoVerdict ? "де-факто " : ""); } else { result = " ''(не переименовано)''"; } } } for (int i = 0; i < section.Level - 1; ++i) { filler += "*"; } titles.Add(filler + " " + section.Title.Trim() + result); List<WikiPageSection> sections = new List<WikiPageSection>(); section.Reduce(sections, SubsectionsList); foreach (WikiPageSection subsection in sections) { if (subsection.SectionText.ToLower().Contains("{{mark out}}")) { subsection.Title = "{{mark out|" + subsection.Title.Trim() + "}}"; } result = ""; hasVerdict = subsection.Subsections.Count(s => s.Title.ToLower().Trim() == "итог") > 0; hasAutoVerdict = subsection.Subsections.Count(s => s.Title.Trim() == "Автоматический итог") > 0; if (hasVerdict || hasAutoVerdict || subsection.Title.Contains("<s>")) { Match m = wikiLinkRE.Match(subsection.Title); if (m.Success && !m.Groups[1].Value.StartsWith(":Категория:")) { string link = m.Groups[1].Value; string movedTo; bool moved = MovedTo(wiki, link, day.Date, out movedTo); if (moved && string.IsNullOrEmpty(movedTo)) { result = " ''(переименовано)''"; } else if (moved) { result = string.Format(" ''({1}переименовано в «[[{0}]]»)''", movedTo.StartsWith("Файл:") ? ":" + movedTo : movedTo, hasAutoVerdict ? "де-факто " : ""); } else { result = " ''(не переименовано)''"; } } } filler = ""; for (int i = 0; i < subsection.Level - 1; ++i) { filler += "*"; } titles.Add(filler + " " + subsection.Title.Trim() + result); } } if (titles.Count(s => s.Contains("=")) > 0) { titles[0] = "2=<li>" + titles[0].Substring(2) + "</li>"; } sw.Write(string.Join("\n", titles.ConvertAll(c => c).ToArray())); sw.Write("}}\n\n"); } sw.WriteLine("|}\n"); sw.WriteLine("{{/Окончание}}"); } }
static int Main(string[] args) { Wiki wiki = new Wiki("http://ru.wikipedia.org/w/"); wiki.SleepBetweenQueries = 2; if (string.IsNullOrEmpty(Settings.Default.Login) || string.IsNullOrEmpty(Settings.Default.Password)) { Console.Out.WriteLine("Please add login and password to the configuration file."); return 0; } Console.Out.WriteLine("Logging in as " + Settings.Default.Login + "..."); try { WikiCache.Login(wiki, Settings.Default.Login, Settings.Default.Password); } catch (WikiException e) { Console.Out.WriteLine(e.Message); return 0; } Console.Out.WriteLine("Logged in as " + Settings.Default.Login + "."); string listText; try { listText = wiki.LoadText("Шаблон:Список подводящих итоги"); } catch (WikiException e) { Console.Out.WriteLine(e.Message); return -1; } StringReader reader = new StringReader(listText); HashSet<string> users = new HashSet<string>(); Regex userRE = new Regex(@"^\*\s*\[\[(User|Участник):(.+)\|.+\]\]\s*$", RegexOptions.IgnoreCase); string line; while ((line = reader.ReadLine()) != null) { Match m = userRE.Match(line); if (m.Success) { users.Add(m.Groups[2].Value.ToLower()); } } ParameterCollection parameters = new ParameterCollection { { "generator", "embeddedin" }, { "geititle", "Template:Db-discussion" }, { "geilimit", "max"}, { "prop", "info" }, { "intoken", "delete" }, { "inprop", "talkid" } }; Regex templateRE = new Regex(@"\{\{db-discussion\|(\d+)\|(дата|причина)\s*=\s*(.+?)\}\}", RegexOptions.IgnoreCase); XmlDocument doc; try { doc = wiki.Enumerate(parameters, true); } catch (WikiException e) { Console.Out.WriteLine(e.Message); return -1; } bool failed = false; foreach (XmlNode page in doc.SelectNodes("//page")) { string title = page.Attributes["title"].Value; parameters = new ParameterCollection { { "prop", "revisions" }, { "rvprop", "content" }, { "rvlimit", "1" } }; XmlDocument xml; try { xml = wiki.Query(QueryBy.Titles, parameters, title); } catch (WikiException e) { Console.Out.WriteLine(e.Message); failed = true; continue; } XmlNode node = xml.SelectSingleNode("//rev"); if (node == null || node.FirstChild == null) { failed = true; continue; } string content = node.FirstChild.Value; Match m = templateRE.Match(content); if (m.Success) { string timestamp = m.Groups[1].Value; parameters = new ParameterCollection { { "prop", "revisions" }, { "rvprop", "timestamp|user|content" }, { "rvlimit", "1" }, { "rvstart", timestamp }, { "rvdir", "newer" }, }; try { xml = wiki.Query(QueryBy.Titles, parameters, new string[] { title }, 500, false); } catch (WikiException e) { Console.Out.WriteLine(e.Message); failed = true; continue; } node = xml.SelectSingleNode("//rev"); if (node != null && users.Contains(node.Attributes["user"].Value.ToLower())) { content = node.FirstChild.Value; m = templateRE.Match(content); if (m.Success && m.Groups[1].Value == timestamp) { string comment; if (m.Groups[2].Value.ToLower() == "причина") { comment = m.Groups[3].Value; } else { DateTime talkDate; if (DateTime.TryParse(m.Groups[3].Value, null, System.Globalization.DateTimeStyles.AssumeUniversal, out talkDate)) { comment = string.Format("согласно итогу обсуждения [[ВП:К удалению/{0}#{1}]]", talkDate.ToUniversalTime().ToString("d MMMM yyyy"), title); } else { continue; } } string reason = string.Format("удалил [[User:{0}|{0}]]: {1}", node.Attributes["user"].Value, comment); string token = page.Attributes["deletetoken"].Value; try { wiki.Delete(title, reason, token); } catch (WikiException e) { Console.Out.WriteLine(e.Message); failed = true; continue; } parameters = new ParameterCollection { { "list", "backlinks" }, { "blfilterredir", "redirects" }, { "bllimit", "max" }, { "bltitle", title }, }; try { xml = wiki.Enumerate(parameters, true); } catch (WikiException e) { Console.Out.WriteLine(e.Message); failed = true; continue; } foreach (XmlNode backlink in xml.SelectNodes("//bl")) { try { wiki.Delete(backlink.Attributes["title"].Value, "[[ВП:КБУ#П1|П1]]: перенаправление в никуда", wiki.Token); } catch (WikiException e) { Console.Out.WriteLine(e.Message); failed = true; continue; } } } } } } return failed ? -1 : 0; }
public void Analyze(Wiki wiki) { ParameterCollection parameters = new ParameterCollection(); parameters.Add("generator", "categorymembers"); parameters.Add("gcmtitle", "Категория:Википедия:Незакрытые обсуждения восстановления страниц"); parameters.Add("gcmlimit", "max"); parameters.Add("gcmnamespace", "4"); parameters.Add("prop", "info|revisions"); parameters.Add("rvprop", "timestamp"); XmlDocument doc = wiki.Enumerate(parameters, true); XmlNodeList pages = doc.SelectNodes("//page"); List<Day> days = new List<Day>(); DateTime start = DateTime.Today; Regex closedRE = new Regex(@"({{ВПВУС-Навигация}}\s*{{(Закрыто|Closed|закрыто|closed)}})|({{(Закрыто|Closed|закрыто|closed)}}\s*{{ВПВУС-Навигация}})"); foreach (XmlNode page in pages) { string pageName = page.Attributes["title"].Value; string date = pageName.Substring("Википедия:К восстановлению/".Length); DateTime cutOffDate = new DateTime(2008, 11, 13); Day day = new Day(); if (!DateTime.TryParse(date, CultureInfo.CreateSpecificCulture("ru-RU"), DateTimeStyles.AssumeUniversal, out day.Date)) { continue; } string fileName = _cacheDir + date + ".bin"; string text = ""; if (File.Exists(fileName)) { using (FileStream fs = new FileStream(fileName, FileMode.Open)) using (GZipStream gs = new GZipStream(fs, CompressionMode.Decompress)) using (TextReader sr = new StreamReader(gs)) { string revid = sr.ReadLine(); if (revid == page.Attributes["lastrevid"].Value) { Console.Out.WriteLine("Loading " + pageName + "..."); text = sr.ReadToEnd(); } } } if (string.IsNullOrEmpty(text)) { Console.Out.WriteLine("Downloading " + pageName + "..."); text = wiki.LoadText(pageName); using (FileStream fs = new FileStream(fileName, FileMode.Create)) using (GZipStream gs = new GZipStream(fs, CompressionMode.Compress)) using (StreamWriter sw = new StreamWriter(gs)) { sw.WriteLine(page.Attributes["lastrevid"].Value); sw.Write(text); } } DateTime lastEdit = DateTime.Parse(page.FirstChild.FirstChild.Attributes["timestamp"].Value, null, DateTimeStyles.AssumeUniversal); Match m = closedRE.Match(text); if ((DateTime.Now - lastEdit).TotalDays > 2 && (m.Success || day.Date < cutOffDate)) { Console.Out.WriteLine("Closing " + pageName + "..."); text = text.Replace("{{ВПВУС-Навигация}}", "{{ВПВУС-Навигация|nocat=1}}"); wiki.Save(pageName, text, "обсуждение закрыто"); continue; } day.Page = WikiPage.Parse(pageName, text); days.Add(day); } days.Sort(CompareDays); Regex wikiLinkRE = new Regex(@"\[{2}(.+?)(\|.+?)?]{2}"); List<string> sectionTitles = new List<string>(); foreach (Day day in days) { foreach (WikiPageSection section in day.Page.Sections) { RemoveStrikeOut(section); StrikeOutSection(section); if (section.Title.Contains("<s>")) { Match m = wikiLinkRE.Match(section.Title); if (m.Success) { sectionTitles.Add(m.Groups[1].Value); } } List<WikiPageSection> sections = new List<WikiPageSection>(); section.Reduce(sections, SubsectionsList); foreach (WikiPageSection subsection in sections) { if (subsection.Title.Contains("<s>")) { Match m = wikiLinkRE.Match(subsection.Title); if (m.Success) { sectionTitles.Add(m.Groups[1].Value); } } } } } parameters.Clear(); parameters.Add("prop", "info"); XmlDocument xml = wiki.Query(QueryBy.Titles, parameters, sectionTitles); using (StreamWriter sw = new StreamWriter(_cacheDir + "MainPage.txt")) { sw.WriteLine("== Текущие обсуждения ==\n"); sw.WriteLine("{{Восстановление статей/Статьи, вынесенные на обсуждение восстановления}}\n"); foreach (Day day in days) { sw.Write("{{Восстановление статей/День|" + day.Date.ToString("yyyy-M-d") + "|\n"); List<string> titles = new List<string>(); foreach (WikiPageSection section in day.Page.Sections) { string result = ""; string filler = ""; RemoveStrikeOut(section); StrikeOutSection(section); if (section.Title.Contains("<s>")) { Match m = wikiLinkRE.Match(section.Title); if (m.Success) { string link = m.Groups[1].Value; XmlNode node = xml.SelectSingleNode("//page[@title='" + link.Replace("'", @"'") + "']"); if (node != null) { if (node.Attributes["missing"] == null) { WikiPageSection autoresult = section.Subsections.FirstOrDefault(s => s.Title.Trim() == "Автоматический итог"); if (autoresult != null && autoresult.SectionText.Contains("Страница была создана заново")) { result = " ''(создана заново)''"; } else { result = " ''(восстановлена)''"; } } else { result = " ''(не восстановлена)''"; } } } } for (int i = 0; i < section.Level - 1; ++i) { filler += "*"; } titles.Add(filler + " " + section.Title.Trim() + result); List<WikiPageSection> sections = new List<WikiPageSection>(); section.Reduce(sections, SubsectionsList); foreach (WikiPageSection subsection in sections) { result = ""; if (subsection.Title.Contains("<s>")) { Match m = wikiLinkRE.Match(subsection.Title); if (m.Success) { string link = m.Groups[1].Value; XmlNode node = xml.SelectSingleNode("//page[@title='" + link + "']"); if (node != null) { if (node.Attributes["missing"] == null) { WikiPageSection autoresult = subsection.Subsections.FirstOrDefault(s => s.Title.Trim() == "Автоматический итог"); if (autoresult != null && autoresult.SectionText.Contains("Страница была создана заново")) { result = " ''(создана заново)''"; } else { result = " ''(восстановлена)''"; } } else { result = " ''(не восстановлена)''"; } } } } filler = ""; for (int i = 0; i < subsection.Level - 1; ++i) { filler += "*"; } titles.Add(filler + " " + subsection.Title.Trim()); } } if (titles.Count(s => s.Contains("=")) > 0) { titles[0] = "2=<div>" + titles[0].Substring(2); } sw.Write(string.Join("\n", titles.ConvertAll(c => c).ToArray())); if (titles.Count(s => s.Contains("=")) > 0) { sw.Write("</div>"); } sw.Write("}}\n\n"); } sw.WriteLine("{{/Подвал}}"); } }
private void SwitchToLanguage(string language) { string path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); path += @"\WikiLive\" + language; Directory.CreateDirectory(path); _baseName = path + @"\WikiLive.db"; if (!File.Exists(_baseName)) { SQLiteConnection.CreateFile(_baseName); } if (_connection != null && _connection.State != ConnectionState.Closed) { _connection.Close(); } SQLiteFactory factory = (SQLiteFactory)DbProviderFactories.GetFactory("System.Data.SQLite"); _connection = (SQLiteConnection)factory.CreateConnection(); _connection.ConnectionString = "Data Source = " + _baseName; _connection.Open(); using (SQLiteCommand command = new SQLiteCommand(_connection)) { command.CommandText = @"CREATE TABLE IF NOT EXISTS [edits] ( [id] integer PRIMARY KEY NOT NULL, [timestamp] TEXT NOT NULL, [user] TEXT NOT NULL, [page] TEXT NOT NULL, [namespace] INTEGER NOT NULL, [flags] INTEGER NOT NULL, [oldid] INTEGER NOT NULL, [size] INTEGER NOT NULL, [summary] TEXT NOT NULL );"; command.CommandType = CommandType.Text; command.ExecuteNonQuery(); } using (SQLiteCommand command = new SQLiteCommand(_connection)) { command.CommandText = @"CREATE TABLE IF NOT EXISTS [watched_pages] ( [id] integer PRIMARY KEY AUTOINCREMENT NOT NULL, [page] TEXT NOT NULL, [namespace] INTEGER NOT NULL );"; command.CommandType = CommandType.Text; command.ExecuteNonQuery(); } if (!File.Exists(path + @"\namespaces.dat")) { Wiki wiki = new Wiki("http://" + language + ".wikipedia.org"); ParameterCollection parameters = new ParameterCollection(); parameters.Add("meta", "siteinfo"); parameters.Add("siprop", "namespaces"); XmlDocument xml = wiki.Enumerate(parameters, true); XmlNodeList nodes = xml.SelectNodes("//ns[@id > 0]"); Serializer serializer = new Serializer(); serializer.Put(nodes.Count); foreach (XmlNode node in nodes) { serializer.Put(node.Attributes["id"].Value); serializer.Put(node.FirstChild.Value); } using (FileStream fs = new FileStream(path + @"\namespaces.dat", FileMode.CreateNew)) using (BinaryWriter streamWriter = new BinaryWriter(fs)) { streamWriter.Write(serializer.ToArray()); } } }
public void Analyze(Wiki wiki) { ParameterCollection parameters = new ParameterCollection(); parameters.Add("generator", "categorymembers"); parameters.Add("gcmtitle", _l10i.Category); parameters.Add("gcmlimit", "max"); parameters.Add("gcmnamespace", "4"); parameters.Add("prop", "info"); XmlDocument doc = wiki.Enumerate(parameters, true); XmlNodeList pages = doc.SelectNodes("//page"); List<Day> days = new List<Day>(); foreach (XmlNode page in pages) { string prefix = _l10i.MainPage + "/"; string pageName = page.Attributes["title"].Value; string date = pageName.Substring(prefix.Length); Day day = new Day(); try { day.Date = DateTime.Parse(date, _l10i.Culture, DateTimeStyles.AssumeUniversal); } catch (FormatException) { continue; } string fileName = _cacheDir + date + ".bin"; string text = ""; if (File.Exists(fileName)) { using (FileStream fs = new FileStream(fileName, FileMode.Open)) using (GZipStream gs = new GZipStream(fs, CompressionMode.Decompress)) using (TextReader sr = new StreamReader(gs)) { string revid = sr.ReadLine(); if (revid == page.Attributes["lastrevid"].Value) { Console.Out.WriteLine("Loading " + pageName + "..."); text = sr.ReadToEnd(); } } } if (string.IsNullOrEmpty(text)) { Console.Out.WriteLine("Downloading " + pageName + "..."); text = wiki.LoadText(pageName); using (FileStream fs = new FileStream(fileName, FileMode.Create)) using (GZipStream gs = new GZipStream(fs, CompressionMode.Compress)) using (StreamWriter sw = new StreamWriter(gs)) { sw.WriteLine(page.Attributes["lastrevid"].Value); sw.Write(text); } } Match m = _l10i.closedRE.Match(text); if (m.Success) { Console.Out.WriteLine("Closing " + pageName + "..."); text = _l10i.ClosePage(text); wiki.Save(pageName, text, _l10i.CloseComment); continue; } day.Page = WikiPage.Parse(pageName, text); days.Add(day); } days.Sort(CompareDays); using (StreamWriter sw = new StreamWriter(_cacheDir + "MainPage.txt")) { if (!string.IsNullOrEmpty(_l10i.SectionTitle)) { sw.WriteLine("== " + _l10i.SectionTitle + " ==\n"); } sw.WriteLine("{{" + _l10i.TopTemplate + "}}\n"); foreach (Day day in days) { sw.Write("{{" + _l10i.Template + "|" + day.Date.ToString("yyyy-M-d") + "|"); List<string> titles = new List<string>(); foreach (WikiPageSection section in day.Page.Sections) { RemoveStrikeOut(section); StrikeOutSection(section); string result = section.Reduce("", SubsectionsList); if (result.Length > 0) { result = " • <small>" + result.Substring(3) + "</small>"; } string title; if (_l10i.Processor != null) { title = _l10i.Processor(section).Trim(); } else { title = section.Title.Trim(); } titles.Add(title + result); } sw.Write(string.Join(" • ", titles.ConvertAll(c => c).ToArray())); sw.Write("}}\n\n"); } sw.WriteLine("{{" + _l10i.BottomTemplate + "}}"); } }
internal void AddNavigationTemplate(Wiki wiki) { ParameterCollection parameters = new ParameterCollection(); parameters.Add("list", "embeddedin"); parameters.Add("eititle", "Template:" + _l10i.NavigationTemplate); parameters.Add("eilimit", "max"); parameters.Add("einamespace", "4"); parameters.Add("eifilterredir", "nonredirects"); XmlDocument doc = wiki.Enumerate(parameters, true); List<string> titles = new List<string>(); DateTime end = DateTime.Today; DateTime start = end.AddDays(-7); while (start <= end) { string pageDate = start.ToString("d MMMM yyyy", _l10i.Culture); string prefix = _l10i.MainPage + "/"; string pageName = prefix + pageDate; if (doc.SelectSingleNode("//ei[@title='" + pageName + "']") == null) { titles.Add(pageName); } start = start.AddDays(1); } parameters.Clear(); parameters.Add("prop", "info"); XmlDocument xml = wiki.Query(QueryBy.Titles, parameters, titles); foreach (XmlNode node in xml.SelectNodes("//page")) { if (node.Attributes["missing"] == null) { Console.Out.WriteLine("Updating " + node.Attributes["title"].Value + "..."); wiki.Prepend(node.Attributes["title"].Value, "{{" + _l10i.NavigationTemplate + "}}\n", _l10i.MainPageUpdateComment); } } }
static int Main(string[] args) { if (args.Length < 2) { Console.Out.WriteLine("NewPagesWikiBot <language> <update comment>"); return 0; } string path = @"Cache\" + args[0] + @"\"; Directory.CreateDirectory(@"Cache\" + args[0]); Wiki wiki = new Wiki(string.Format("http://{0}.wikipedia.org/w/", args[0])); wiki.SleepBetweenQueries = 5; if (string.IsNullOrEmpty(Settings.Default.Login) || string.IsNullOrEmpty(Settings.Default.Password)) { Console.Out.WriteLine("Please add login and password to the configuration file."); return 0; } Console.Out.WriteLine("Logging in as " + Settings.Default.Login + " to " + wiki.Uri + "..."); try { string cookieFile = @"Cache\" + args[0] + @"\cookie.jar"; WikiCache.Login(wiki, Settings.Default.Login, Settings.Default.Password, cookieFile); string namespacesFile = @"Cache\" + args[0] + @"\namespaces.dat"; if (!WikiCache.LoadNamespaces(wiki, namespacesFile)) { wiki.GetNamespaces(); WikiCache.CacheNamespaces(wiki, namespacesFile); } } catch (WikiException e) { Console.Out.WriteLine(e.Message); return 0; } Console.Out.WriteLine("Logged in as " + wiki.User + "."); PortalModule portal = new PortalModule(args[0], args[1]); Directory.CreateDirectory("Cache\\" + args[0] + "\\NewPages\\"); Directory.CreateDirectory("Cache\\" + args[0] + "\\PagesInCategory\\"); Directory.CreateDirectory("Cache\\" + args[0] + "\\PagesInCategoryWithTemplates\\"); Cache.PurgeCache(args[0]); if (!File.Exists("Cache\\" + args[0] + "\\processed.txt")) { FileStream stream = File.Create("Cache\\" + args[0] + "\\processed.txt"); stream.Close(); } HashSet<string> processedPages = new HashSet<string>(); using (StreamReader sr = new StreamReader("Cache\\" + args[0] + "\\processed.txt")) { String line; while ((line = sr.ReadLine()) != null) { processedPages.Add(line); } } ParameterCollection parameters = new ParameterCollection() { { "generator", "embeddedin" }, { "geititle", "User:ClaymoreBot/Новые статьи" }, { "geilimit", "max" }, { "prop", "info" }, { "intoken", "edit" }, { "redirects", "1" } }; List<string> pages = new List<string>(); XmlDocument doc = wiki.Enumerate(parameters, true); foreach (XmlNode node in doc.SelectNodes("//page")) { string title = node.Attributes["title"].Value; pages.Add(title); } pages.Sort(); for (int i = 0; i < pages.Count; ++i) { try { if (processedPages.Contains(pages[i])) { continue; } WikiPage page = Cache.Load(wiki, pages[i], path); IPortalModule module; if (TryParse(page, path, portal, out module)) { module.Update(wiki); using (StreamWriter sw = new StreamWriter("Cache\\" + args[0] + "\\processed.txt", true)) { sw.WriteLine(pages[i]); } } } catch (WikiException) { return -1; } catch (System.Net.WebException) { return -1; } } File.Delete("Cache\\" + args[0] + "\\processed.txt"); Console.Out.WriteLine("Done."); return 0; }
static int Main(string[] args) { Wiki wiki = new Wiki("http://ru.wikipedia.org/w/"); wiki.SleepBetweenQueries = 2; if (string.IsNullOrEmpty(Settings.Default.Login) || string.IsNullOrEmpty(Settings.Default.Password)) { Console.Out.WriteLine("Please add login and password to the configuration file."); return 0; } Console.Out.WriteLine("Logging in as " + Settings.Default.Login + "..."); try { WikiCache.Login(wiki, Settings.Default.Login, Settings.Default.Password); } catch (WikiException e) { Console.Out.WriteLine(e.Message); return 0; } Console.Out.WriteLine("Logged in as " + wiki.User + "."); ParameterCollection parameters = new ParameterCollection { { "list", "embeddedin" }, { "eititle", "Шаблон:Редактирую" }, { "eilimit", "max"}, { "einamespace", "0" }, }; XmlDocument doc; try { doc = wiki.Enumerate(parameters, true); } catch (WikiException e) { Console.Out.WriteLine(e.Message); return -1; } Regex templateRE = new Regex(@"\{\{(Редактирую|Перерабатываю|Inuse-by|Пишу|Inuse|Правлю|Перевожу|In-use|Processing|Process|Редактирую раздел)\|1=(.+?)\|2=.+?}}\s?", RegexOptions.IgnoreCase); Regex templateRE2 = new Regex(@"\{\{(Редактирую|Перерабатываю|Inuse-by|Пишу|Inuse|Правлю|Перевожу|In-use|Processing|Process|Редактирую раздел)\|(.*?\[\[.+?]].*?)(\|.+?)?}}\s?", RegexOptions.IgnoreCase); Regex templateRE3 = new Regex(@"\{\{(Редактирую|Перерабатываю|Inuse-by|Пишу|Inuse|Правлю|Перевожу|In-use|Processing|Process|Редактирую раздел)}}\s?", RegexOptions.IgnoreCase); Regex userRE = new Regex(@"\[\[(User:|Участник:|special:contributions/|Служебная:contributions/)(.+?)(\|.+?)*?\]\]", RegexOptions.IgnoreCase); bool failed = false; foreach (XmlNode page in doc.SelectNodes("//ei")) { string title = page.Attributes["title"].Value; parameters = new ParameterCollection { { "prop", "revisions" }, { "rvprop", "timestamp|content" }, { "rvlimit", "1" } }; XmlDocument xml; try { xml = wiki.Query(QueryBy.Titles, parameters, new string[] { title }, 500, false); } catch (WikiException e) { Console.Out.WriteLine(e.Message); failed = true; continue; } XmlNode node = xml.SelectSingleNode("//rev"); if (node == null || node.FirstChild == null) { failed = true; continue; } string content = node.FirstChild.Value; DateTime timestamp = DateTime.Parse(node.Attributes["timestamp"].Value, null, System.Globalization.DateTimeStyles.AssumeUniversal); if ((DateTime.Now - timestamp).TotalDays >= 3) { Match m = templateRE.Match(content); string text = content; string user = ""; if (m.Success) { text = templateRE.Replace(content, ""); user = m.Groups[2].Value; } else { m = templateRE2.Match(content); if (m.Success) { text = templateRE2.Replace(content, ""); user = m.Groups[2].Value; } else { m = templateRE3.Match(content); if (m.Success) { text = templateRE3.Replace(content, ""); } } } if (text == content) { continue; } try { Console.WriteLine("Updating " + title + "..."); wiki.Save(title, text, "автоматическое удаление просроченного шаблона [[Шаблон:Редактирую|редактирую]]"); } catch (WikiException e) { Console.Out.WriteLine(e.Message); failed = true; continue; } Match um = userRE.Match(user); if (um.Success) { string notification = "\n== Уведомление ==\nЗдравствуйте! Пожалуйста, обратите внимание, что в статье [[" + title + "]] был автоматически удалён установленный вами шаблон {{tl|Редактирую}}. ~~~~"; string userTalk = "Обсуждение участника:" + um.Groups[2].Value; try { Console.WriteLine("Creating a topic on " + userTalk + "..."); wiki.Append(userTalk, notification, "/* Уведомление */ новая тема: автоматическое удаление просроченного шаблона", MinorFlags.NotMinor, false); } catch (WikiException e) { Console.Out.WriteLine(e.Message); failed = true; } } } } return failed ? -1 : 0; }
static void Main(string[] args) { Wiki wiki = new Wiki("http://ru.wikipedia.org/w/"); wiki.SleepBetweenQueries = 2; if (string.IsNullOrEmpty(Settings.Default.Login) || string.IsNullOrEmpty(Settings.Default.Password)) { Console.Out.WriteLine("Please add login and password to the configuration file."); return; } Console.Out.WriteLine("Logging in as " + Settings.Default.Login + "..."); try { WikiCache.Login(wiki, Settings.Default.Login, Settings.Default.Password); } catch (WikiException e) { Console.Out.WriteLine(e.Message); return; } Console.Out.WriteLine("Logged in as " + wiki.User + "."); var parameters = new ParameterCollection { {"list", "recentchanges"}, {"rcnamespace", "0"}, {"rcprop", "user"}, {"rcshow", "patrolled|!bot|!anon|!redirect"}, {"rclimit", "2500"}, {"rctype", "edit|new"}, }; if (!File.Exists("DoNotCheck.txt")) { FileStream fs = File.Create("DoNotCheck.txt"); fs.Close(); } HashSet<string> checkedUsers = new HashSet<string>(); using (StreamReader sr = new StreamReader("DoNotCheck.txt")) { string line; while ((line = sr.ReadLine()) != null) { checkedUsers.Add(line); } } HashSet<string> users = new HashSet<string>(); XmlDocument doc = wiki.Enumerate(parameters, false); foreach (XmlNode edit in doc.SelectNodes("//rc")) { string userName = edit.Attributes["user"].Value; if (!checkedUsers.Contains(userName) && !users.Contains(userName)) { users.Add(userName); } } parameters = new ParameterCollection { {"list", "users"}, {"usprop", "groups|editcount|registration"}, }; Dictionary<string, UserInfo> candidates = new Dictionary<string, UserInfo>(); int limit = 500; StringBuilder usersString = new StringBuilder(); int index = 0; foreach (string user in users) { if (index < limit) { usersString.Append("|" + user); ++index; } else { usersString.Remove(0, 1); ParameterCollection localParameters = new ParameterCollection(parameters); localParameters.Add("ususers", usersString.ToString()); doc = wiki.Enumerate(localParameters, true); using (StreamWriter sw = new StreamWriter("DoNotCheck.txt", true)) { FillInCandidates(candidates, doc.SelectNodes("//user"), sw); } index = 1; usersString = new StringBuilder("|" + user); } } if (index > 0) { usersString.Remove(0, 1); ParameterCollection localParameters = new ParameterCollection(parameters); localParameters.Add("ususers", usersString.ToString()); doc = wiki.Enumerate(localParameters, true); using (StreamWriter sw = new StreamWriter("DoNotCheck.txt", true)) { FillInCandidates(candidates, doc.SelectNodes("//user"), sw); } } StringBuilder sb = new StringBuilder("== Список ==\n"); using (StreamWriter sw = new StreamWriter("DoNotCheck.txt", true)) { foreach (var candidate in candidates) { parameters = new ParameterCollection { {"list", "logevents"}, {"leprop", "timestamp"}, {"letype", "block"}, {"letitle", "User:"******"//item") != null; if (wasBlocked) { sw.WriteLine(candidate.Key); continue; } parameters = new ParameterCollection { {"list", "usercontribs"}, {"uclimit", "500"}, {"ucnamespace", "0"}, {"ucprop", "patrolled"}, {"ucuser", candidate.Key}, }; doc = wiki.Enumerate(parameters, false); int totalEdits = doc.SelectNodes("//item").Count; int patrolledEdits = doc.SelectNodes("//item[@patrolled]").Count; Console.Out.WriteLine("{0}: {1} from {2} (was blocked? {3})", candidate.Key, patrolledEdits, totalEdits, wasBlocked ? "Yes" : "No"); if (patrolledEdits > 5 && totalEdits == 500) { sb.AppendFormat("* {{{{userlinks|{0}}}}}, всего правок: {1}, дата регистрации — {2}, отпатрулировано правок: {3}\n", candidate.Key, candidate.Value.Edits, candidate.Value.Registration == DateTime.MinValue ? "— дата неизвестна" : candidate.Value.Registration.ToUniversalTime().ToLongDateString(), patrolledEdits); } } } Console.Out.WriteLine("Википедия:Заявки на статус автопатрулируемого/Кандидаты..."); wiki.SaveSection("Википедия:Заявки на статус автопатрулируемого/Кандидаты", "1", sb.ToString(), "обновление"); }
static int Main(string[] args) { if (args.Length < 3) { Console.Out.WriteLine("ArchiveWikiBot <language> <culture> <update comment>"); return 0; } if (string.IsNullOrEmpty(Settings.Default.Login) || string.IsNullOrEmpty(Settings.Default.Password)) { Console.Out.WriteLine("Please add login and password to the configuration file."); return 0; } string path = @"Cache\" + args[0] + @"\"; Directory.CreateDirectory(@"Cache\" + args[0]); Wiki wiki = new Wiki(string.Format("http://{0}.wikipedia.org/w/", args[0])); wiki.SleepBetweenQueries = 2; Console.Out.WriteLine("Logging in as " + Settings.Default.Login + " to " + wiki.Uri + "..."); try { string cookieFile = @"Cache\" + args[0] + @"\cookie.jar"; WikiCache.Login(wiki, Settings.Default.Login, Settings.Default.Password, cookieFile); string namespacesFile = @"Cache\" + args[0] + @"\namespaces.dat"; if (!WikiCache.LoadNamespaces(wiki, namespacesFile)) { wiki.GetNamespaces(); WikiCache.CacheNamespaces(wiki, namespacesFile); } } catch (WikiException e) { Console.Out.WriteLine(e.Message); return 0; } Console.Out.WriteLine("Logged in as " + wiki.User + "."); L10i l10i = new L10i(args[0], args[1], args[2]); WikiPage listPage = new WikiPage("User:ClaymoreBot/Архивация/Список"); listPage.Load(wiki); StringReader reader = new StringReader(listPage.Text); HashSet<string> pages = new HashSet<string>(); Regex pageRE = new Regex(@"^\*\s*(.+)\s*$"); string line; while ((line = reader.ReadLine()) != null) { Match m = pageRE.Match(line); if (m.Success) { pages.Add(m.Groups[1].Value); } } ParameterCollection parameters = new ParameterCollection(); parameters.Add("generator", "embeddedin"); parameters.Add("geititle", "User:ClaymoreBot/Архивация"); parameters.Add("geilimit", "max"); parameters.Add("prop", "info"); parameters.Add("intoken", "edit"); parameters.Add("redirects"); XmlDocument doc = wiki.Enumerate(parameters, true); foreach (XmlNode node in doc.SelectNodes("//page")) { string title = node.Attributes["title"].Value; WikiPage page = Cache.Load(wiki, title, path); IArchive archive; try { if (TryParse(page, path, pages.Contains(page.Title), l10i, out archive)) { archive.Archivate(wiki); } } catch (WikiException) { } catch (Exception) { } } return 0; }
public void UpdatePages(Wiki wiki) { Regex closedRE = new Regex(@"(\{{2}ВПКПМ-Навигация\}{2}\s*\{{2}(Закрыто|Closed|закрыто|closed)\}{2})|(\{{2}(Закрыто|Closed|закрыто|closed)\}{2}\s*\{{2}ВПКПМ-Навигация\}{2})"); Regex wikiLinkRE = new Regex(@"\[{2}(.+?)(\|.+?)?]{2}"); Regex timeRE = new Regex(@"(\d{2}:\d{2}\, \d\d? [а-я]+ \d{4}) \(UTC\)"); ParameterCollection parameters = new ParameterCollection(); parameters.Add("generator", "categorymembers"); parameters.Add("gcmtitle", "Категория:Википедия:Незакрытые обсуждения переименования страниц"); parameters.Add("gcmlimit", "max"); parameters.Add("gcmnamespace", "4"); parameters.Add("prop", "info|revisions"); parameters.Add("intoken", "edit"); XmlDocument doc = wiki.Enumerate(parameters, true); string queryTimestamp = DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ"); XmlNodeList pages = doc.SelectNodes("//page"); foreach (XmlNode page in pages) { int results = 0; string pageName = page.Attributes["title"].Value; string date = pageName.Substring("Википедия:К переименованию/".Length); string basetimestamp = page.FirstChild.FirstChild.Attributes["timestamp"].Value; string editToken = page.Attributes["edittoken"].Value; Day day = new Day(); if (!DateTime.TryParse(date, CultureInfo.CreateSpecificCulture("ru-RU"), DateTimeStyles.AssumeUniversal, out day.Date)) { continue; } string fileName = _cacheDir + date + ".bin"; string text = ""; if (File.Exists(fileName)) { using (FileStream fs = new FileStream(fileName, FileMode.Open)) using (GZipStream gs = new GZipStream(fs, CompressionMode.Decompress)) using (TextReader sr = new StreamReader(gs)) { string revid = sr.ReadLine(); if (revid == page.Attributes["lastrevid"].Value) { Console.Out.WriteLine("Loading " + pageName + "..."); text = sr.ReadToEnd(); } } } if (string.IsNullOrEmpty(text)) { Console.Out.WriteLine("Downloading " + pageName + "..."); text = wiki.LoadText(pageName); using (FileStream fs = new FileStream(fileName, FileMode.Create)) using (GZipStream gs = new GZipStream(fs, CompressionMode.Compress)) using (StreamWriter sw = new StreamWriter(gs)) { sw.WriteLine(page.Attributes["lastrevid"].Value); sw.Write(text); } } day.Page = WikiPage.Parse(pageName, text); List<string> titlesWithResults = new List<string>(); foreach (WikiPageSection section in day.Page.Sections) { RemoveStrikeOut(section); StrikeOutSection(section); Match m = wikiLinkRE.Match(section.Title); if (m.Success && !m.Groups[1].Value.StartsWith(":Категория:")) { string link = m.Groups[1].Value; string movedTo; string movedBy; DateTime movedAt; DateTime start = day.Date; m = timeRE.Match(section.SectionText); if (m.Success) { start = DateTime.Parse(m.Groups[1].Value, CultureInfo.CreateSpecificCulture("ru-RU"), DateTimeStyles.AssumeUniversal); } bool moved = MovedTo(wiki, link, start, out movedTo, out movedBy, out movedAt); WikiPageSection autoVerdictSection = section.Subsections.FirstOrDefault(s => s.Title.Trim() == "Автоматический итог"); if (autoVerdictSection != null && !moved) { autoVerdictSection.Title = " Оспоренный итог "; RemoveStrikeOut(section); StrikeOutSection(section); } if (section.Subsections.Count(s => s.Title.Trim() == "Оспоренный итог") == 0 && section.Subsections.Count(s => s.Title.ToLower().Trim() == "итог") == 0 && section.Subsections.Count(s => s.Title.Trim() == "Автоматический итог") == 0 && moved && !string.IsNullOrEmpty(movedTo)) { string message = string.Format("Страница была переименована {2} в «[[{0}]]» участником [[User:{1}|]]. Данное сообщение было автоматически сгенерировано ботом ~~~~.\n", movedTo, movedBy, movedAt.ToUniversalTime().ToString("d MMMM yyyy в HH:mm (UTC)")); WikiPageSection verdict = new WikiPageSection(" Автоматический итог ", section.Level + 1, message); section.AddSubsection(verdict); StrikeOutSection(section); ++results; } } m = wikiLinkRE.Match(section.Title); if (m.Success && section.Title.Contains("<s>")) { titlesWithResults.Add(m.Groups[1].Value); } List<WikiPageSection> sections = new List<WikiPageSection>(); section.Reduce(sections, SubsectionsList); foreach (WikiPageSection subsection in sections) { m = wikiLinkRE.Match(subsection.Title); if (m.Success && subsection.Title.Contains("<s>")) { titlesWithResults.Add(m.Groups[1].Value.Trim()); } if (m.Success && !subsection.Title.Contains("<s>") && !m.Groups[1].Value.StartsWith(":Категория:")) { string link = m.Groups[1].Value; string movedTo; string movedBy; DateTime movedAt; DateTime start = day.Date; m = timeRE.Match(subsection.SectionText); if (m.Success) { start = DateTime.Parse(m.Groups[1].Value, CultureInfo.CreateSpecificCulture("ru-RU"), DateTimeStyles.AssumeUniversal); } bool moved = MovedTo(wiki, link, start, out movedTo, out movedBy, out movedAt); WikiPageSection verdictSection = subsection.Subsections.FirstOrDefault(s => s.Title.Trim() == "Автоматический итог"); if (verdictSection != null && !moved) { verdictSection.Title = " Оспоренный итог "; RemoveStrikeOut(subsection); StrikeOutSection(subsection); } if (subsection.Subsections.Count(s => s.Title.Trim() == "Оспоренный итог") == 0 && subsection.Subsections.Count(s => s.Title.ToLower().Trim() == "итог") == 0 && subsection.Subsections.Count(s => s.Title.Trim() == "Автоматический итог") == 0 && moved && !string.IsNullOrEmpty(movedTo)) { string message = string.Format("Страница была переименована {2} в «[[{0}]]» участником [[User:{1}|]]. Данное сообщение было автоматически сгенерировано ботом ~~~~.\n", movedTo, movedBy, movedAt.ToUniversalTime().ToString("d MMMM yyyy в HH:mm (UTC)")); WikiPageSection verdict = new WikiPageSection(" Автоматический итог ", subsection.Level + 1, message); subsection.AddSubsection(verdict); StrikeOutSection(subsection); ++results; } } } } Match matchClosed = closedRE.Match(text); if (matchClosed.Success) { List<TalkResult> talkResults = new List<TalkResult>(); foreach (string name in titlesWithResults) { if (wiki.PageNamespace(name) > 0) { continue; } string movedTo; string movedBy; DateTime movedAt; bool moved = MovedTo(wiki, name, day.Date, out movedTo, out movedBy, out movedAt); talkResults.Add(new TalkResult(name, movedTo, moved)); } parameters.Clear(); parameters.Add("prop", "info"); XmlDocument xml = wiki.Query(QueryBy.Titles, parameters, talkResults.ConvertAll(r => r.Moved ? r.MovedTo : r.Title)); List<string> notificationList = new List<string>(); foreach (XmlNode node in xml.SelectNodes("//page")) { if (node.Attributes["missing"] == null && node.Attributes["ns"].Value == "0") { notificationList.Add(node.Attributes["title"].Value); } } if (notificationList.Count > 0) { parameters.Clear(); parameters.Add("list", "backlinks"); parameters.Add("bltitle", pageName); parameters.Add("blfilterredir", "nonredirects"); parameters.Add("blnamespace", "1"); parameters.Add("bllimit", "max"); XmlDocument backlinks = wiki.Enumerate(parameters, true); foreach (string title in notificationList) { if (backlinks.SelectSingleNode("//bl[@title=\"Обсуждение:" + title + "\"]") == null) { TalkResult tr = talkResults.Find(r => r.Moved ? r.MovedTo == title : r.Title == title); PutNotification(wiki, tr, day.Date); } } } } string newText = day.Page.Text; if (newText.Trim() == text.Trim()) { continue; } try { Console.Out.WriteLine("Updating " + pageName + "..."); string revid = wiki.Save(pageName, "", newText, "зачёркивание заголовков" + (results > 0 ? ", сообщение об итогах" : ""), MinorFlags.Minor, CreateFlags.NoCreate, WatchFlags.None, SaveFlags.Replace, true, basetimestamp, "", editToken); using (FileStream fs = new FileStream(fileName, FileMode.Create)) using (GZipStream gs = new GZipStream(fs, CompressionMode.Compress)) using (StreamWriter sw = new StreamWriter(gs)) { sw.WriteLine(revid); sw.Write(newText); } } catch (WikiException) { } } }
static void Main(string[] args) { Wiki wiki = new Wiki("http://ru.wikipedia.org/w/"); wiki.SleepBetweenQueries = 2; if (string.IsNullOrEmpty(Settings.Default.Login) || string.IsNullOrEmpty(Settings.Default.Password)) { Console.Out.WriteLine("Please add login and password to the configuration file."); return; } Console.Out.WriteLine("Logging in as " + Settings.Default.Login + "..."); try { WikiCache.Login(wiki, Settings.Default.Login, Settings.Default.Password); } catch (WikiException e) { Console.Out.WriteLine(e.Message); return; } Console.Out.WriteLine("Logged in as " + wiki.User + "."); Dictionary<string, int> requestNumbers = new Dictionary<string, int>(); string text = wiki.LoadText("Википедия:Заявки на арбитраж/Все страницы"); StringReader reader = new StringReader(text); Regex re = new Regex(@" \[\[ВП:(\d+)\]\] — \[\[(.+?)\|"); string line; while ((line = reader.ReadLine()) != null) { Match m = re.Match(line); if (m.Success) { int number = int.Parse(m.Groups[1].Value); string page = m.Groups[2].Value; requestNumbers.Add(page, number); } } var parameters = new ParameterCollection { {"list" , "categorymembers"}, {"cmtitle", "Категория:Википедия:Заявки в Арбитражный комитет"}, {"cmlimit", "max"}, }; List<ArbComEntry> entries = new List<ArbComEntry>(); var doc = wiki.Enumerate(parameters, true); foreach (XmlNode page in doc.SelectNodes("//cm")) { parameters = new ParameterCollection { {"list" , "backlinks"}, {"bltitle", page.Attributes["title"].Value}, {"bllimit", "max"}, {"blfilterredir", "redirects"}, }; int number = int.MinValue; if (requestNumbers.ContainsKey(page.Attributes["title"].Value)) { number = requestNumbers[page.Attributes["title"].Value]; } else { XmlDocument xml = wiki.Enumerate(parameters, true); foreach (XmlNode link in xml.SelectNodes("//bl")) { if (link.Attributes["title"].Value.StartsWith("Википедия:")) { if (int.TryParse(link.Attributes["title"].Value.Replace("Википедия:", ""), out number)) { break; } else { number = int.MinValue; } } } } ArbComEntry entry = new ArbComEntry(); entry.Number = number; entry.Page = page.Attributes["title"].Value; entries.Add(entry); } string prefix = "Википедия:Заявки на арбитраж/"; StringBuilder sb = new StringBuilder("== Заявки ==\n"); entries.Sort(CompareEntries); foreach (ArbComEntry entry in entries) { string requestNumber = ""; if (entry.Number != int.MinValue) { requestNumber = string.Format("[[ВП:{0}]] — ", entry.Number); } string title = entry.Page.Substring(prefix.Length); sb.AppendFormat("* {2}[[{1}{0}|{0}]] [[Обсуждение Википедии:Заявки на арбитраж/{0}|±]] ([[{1}{0}/Дискуссия арбитров|д]])\n", title, prefix, requestNumber); } text = sb.ToString(); wiki.SaveSection("Википедия:Заявки на арбитраж/Все страницы", "1", text, "/* Заявки */ обновление"); }
private void UpdateArchives(Wiki wiki) { var parameters = new ParameterCollection() { {"generator", "categorymembers"}, {"gcmtitle", "Категория:Википедия:Незакрытые обсуждения переименования страниц"}, {"gcmlimit", "max"}, {"gcmnamespace", "4"}, {"prop", "info"}, }; XmlDocument doc = wiki.Enumerate(parameters, true); XmlNodeList pages = doc.SelectNodes("//page"); DateTime startDate = DateTime.Today; foreach (XmlNode page in pages) { string pageName = page.Attributes["title"].Value; string dateString = pageName.Substring("Википедия:К переименованию/".Length); DateTime date; if (!DateTime.TryParse(dateString, CultureInfo.CreateSpecificCulture("ru-RU"), DateTimeStyles.AssumeUniversal, out date)) { continue; } if (date < startDate) { startDate = new DateTime(date.Year, date.Month, 1); } } DateTime month = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1); do { UpdateArchivePages(wiki, month.Year, month.Month); month = month.AddMonths(-1); } while (month != startDate); }
public void Run(Wiki wiki) { Directory.CreateDirectory(_cacheDir); Console.Out.WriteLine("Updating " + _page); Regex wikiLinkRE = new Regex(@"\[{2}(.+?)(\|.+?)?]{2}"); Regex timeRE = new Regex(@"(\d{2}:\d{2}\, \d\d? [а-я]+ \d{4}) \(UTC\)"); ParameterCollection parameters = new ParameterCollection(); parameters.Add("prop", "info|revisions"); parameters.Add("intoken", "edit"); XmlDocument doc = wiki.Query(QueryBy.Titles, parameters, _page); XmlNode page = doc.SelectSingleNode("//page"); string queryTimestamp = DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ"); string pageName = page.Attributes["title"].Value; string basetimestamp = page.FirstChild.FirstChild.Attributes["timestamp"].Value; string editToken = page.Attributes["edittoken"].Value; string starttimestamp = queryTimestamp; string text = ""; string fileName = _cacheDir + WikiCache.EscapePath(_page); if (File.Exists(fileName)) { using (FileStream fs = new FileStream(fileName, FileMode.Open)) using (GZipStream gs = new GZipStream(fs, CompressionMode.Decompress)) using (TextReader sr = new StreamReader(gs)) { string revid = sr.ReadLine(); if (revid == page.Attributes["lastrevid"].Value) { Console.Out.WriteLine("Loading " + pageName + "..."); text = sr.ReadToEnd(); } } } if (string.IsNullOrEmpty(text)) { Console.Out.WriteLine("Downloading " + pageName + "..."); text = wiki.LoadText(pageName); starttimestamp = DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ"); using (FileStream fs = new FileStream(fileName, FileMode.Create)) using (GZipStream gs = new GZipStream(fs, CompressionMode.Compress)) using (StreamWriter sw = new StreamWriter(gs)) { sw.WriteLine(page.Attributes["lastrevid"].Value); sw.Write(text); } } Dictionary<string, List<WikiPageSection>> titles = new Dictionary<string, List<WikiPageSection>>(); WikiPage wikiPage = WikiPage.Parse(pageName, text); foreach (WikiPageSection section in wikiPage.Sections) { if (section.Subsections.Count(s => s.Title.ToLower(CultureInfo.CreateSpecificCulture("ru-RU")).Trim() == "итог") == 0) { Match m = wikiLinkRE.Match(section.Title); if (m.Success) { string title = m.Groups[1].Value.Trim(); if (titles.ContainsKey(title)) { titles[title].Add(section); } else { titles.Add(title, new List<WikiPageSection>()); titles[title].Add(section); } } } } parameters.Clear(); parameters.Add("prop", "info"); Dictionary<string, string> normalizedTitles = new Dictionary<string, string>(); XmlDocument xml = wiki.Query(QueryBy.Titles, parameters, titles.Keys); foreach (XmlNode node in xml.SelectNodes("//n")) { normalizedTitles.Add(node.Attributes["to"].Value, node.Attributes["from"].Value); } List<string> notificationList = new List<string>(); XmlNodeList missingTitles = xml.SelectNodes("//page"); foreach (XmlNode node in missingTitles) { string title = node.Attributes["title"].Value; IEnumerable<WikiPageSection> sections; if (titles.ContainsKey(title)) { sections = titles[title]; } else { sections = titles[normalizedTitles[title]]; } if (node.Attributes["missing"] != null) { parameters.Clear(); parameters.Add("list", "logevents"); parameters.Add("letype", "delete"); parameters.Add("lemlimit", "max"); parameters.Add("ledir", "newer"); parameters.Add("letitle", title); parameters.Add("leprop", "comment|type|user|timestamp"); XmlDocument log = wiki.Enumerate(parameters, true); XmlNodeList items = log.SelectNodes("//item"); List<DeleteLogEvent> events = new List<DeleteLogEvent>(); foreach (XmlNode item in items) { DeleteLogEvent ev = new DeleteLogEvent(); ev.Comment = item.Attributes["comment"].Value; ev.Deleted = item.Attributes["action"].Value == "delete"; ev.User = item.Attributes["user"].Value; ev.Timestamp = DateTime.Parse(item.Attributes["timestamp"].Value, null, DateTimeStyles.AssumeUniversal); events.Add(ev); } events.Sort(CompareDeleteLogEvents); if (events.Count > 0 && events[0].Deleted) { string comment = FilterWikiMarkup(events[0].Comment); string message = string.Format("Страница была удалена {1} администратором [[User:{0}|]]. Была указана следующая причина: «{2}». Данное сообщение было автоматически сгенерировано ботом ~~~~.\n", events[0].User, events[0].Timestamp.ToUniversalTime().ToString("d MMMM yyyy в HH:mm (UTC)", CultureInfo.CreateSpecificCulture("ru-RU")), comment); var pageSections = titles.ContainsKey(title) ? titles[title] : titles[normalizedTitles[title]]; foreach (WikiPageSection section in pageSections) { WikiPageSection verdict = new WikiPageSection(" Итог ", section.Level + 1, message); section.AddSubsection(verdict); } } } } string newText = wikiPage.Text; if (newText.Trim() == text.Trim()) { return; } Console.Out.WriteLine("Updating " + pageName + "..."); string id = wiki.Save(pageName, "", newText, "автоматическое подведение итогов", MinorFlags.Minor, CreateFlags.NoCreate, WatchFlags.None, SaveFlags.Replace, true, basetimestamp, "", editToken); using (FileStream fs = new FileStream(fileName, FileMode.Create)) using (GZipStream gs = new GZipStream(fs, CompressionMode.Compress)) using (StreamWriter sw = new StreamWriter(gs)) { sw.WriteLine(id); sw.Write(newText); } }
public void UpdatePages(Wiki wiki) { ParameterCollection parameters = new ParameterCollection(); parameters.Add("generator", "categorymembers"); parameters.Add("gcmtitle", "Категория:Википедия:Незакрытые обсуждения объединения страниц"); parameters.Add("gcmlimit", "max"); parameters.Add("gcmnamespace", "4"); parameters.Add("prop", "info"); XmlDocument doc = wiki.Enumerate(parameters, true); XmlNodeList pages = doc.SelectNodes("//page"); foreach (XmlNode page in pages) { string pageName = page.Attributes["title"].Value; string date = pageName.Substring("Википедия:К объединению/".Length); Day day = new Day(); try { day.Date = DateTime.Parse(date, CultureInfo.CreateSpecificCulture("ru-RU"), DateTimeStyles.AssumeUniversal); } catch (FormatException) { continue; } string fileName = _cacheDir + date + ".bin"; string text = LoadPageFromCache(fileName, page.Attributes["lastrevid"].Value, pageName); if (string.IsNullOrEmpty(text)) { Console.Out.WriteLine("Downloading " + pageName + "..."); text = wiki.LoadText(pageName); CachePage(fileName, page.Attributes["lastrevid"].Value, text); } day.Page = WikiPage.Parse(pageName, text); foreach (WikiPageSection section in day.Page.Sections) { RemoveStrikeOut(section); StrikeOutSection(section); } string newText = day.Page.Text; if (newText.Trim() == text.Trim()) { continue; } try { string revid = wiki.Save(pageName, newText, "зачёркивание заголовков"); CachePage(fileName, revid, newText); } catch (WikiException) { } } }
public void UpdatePages(Wiki wiki) { Console.Out.WriteLine("Updating articles for deletion..."); Regex wikiLinkRE = new Regex(@"\[{2}(.+?)(\|.+?)?]{2}"); Regex timeRE = new Regex(@"(\d{2}:\d{2}\, \d\d? [а-я]+ \d{4}) \(UTC\)"); ParameterCollection parameters = new ParameterCollection(); parameters.Add("generator", "categorymembers"); parameters.Add("gcmtitle", _l10i.Category); parameters.Add("gcmlimit", "max"); parameters.Add("gcmnamespace", "4"); parameters.Add("prop", "info|revisions"); parameters.Add("intoken", "edit"); XmlDocument doc = wiki.Enumerate(parameters, true); string queryTimestamp = DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ"); XmlNodeList pages = doc.SelectNodes("//page"); foreach (XmlNode page in pages) { string starttimestamp = queryTimestamp; int results = 0; string prefix = _l10i.MainPage + "/"; string pageName = page.Attributes["title"].Value; string basetimestamp = page.FirstChild.FirstChild.Attributes["timestamp"].Value; string editToken = page.Attributes["edittoken"].Value; if (pageName.Length < prefix.Length) { continue; } string date = pageName.Substring(prefix.Length); Day day = new Day(); if (!DateTime.TryParse(date, CultureInfo.CreateSpecificCulture(_l10i.Culture), DateTimeStyles.AssumeUniversal, out day.Date)) { continue; } string text = ""; string fileName = _cacheDir + date + ".bin"; if (File.Exists(fileName)) { using (FileStream fs = new FileStream(fileName, FileMode.Open)) using (GZipStream gs = new GZipStream(fs, CompressionMode.Decompress)) using (TextReader sr = new StreamReader(gs)) { string revid = sr.ReadLine(); if (revid == page.Attributes["lastrevid"].Value) { Console.Out.WriteLine("Loading " + pageName + "..."); text = sr.ReadToEnd(); } } } if (string.IsNullOrEmpty(text)) { try { Console.Out.WriteLine("Downloading " + pageName + "..."); text = wiki.LoadText(pageName); starttimestamp = DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ"); } catch (WikiPageNotFound) { continue; } using (FileStream fs = new FileStream(fileName, FileMode.Create)) using (GZipStream gs = new GZipStream(fs, CompressionMode.Compress)) using (StreamWriter sw = new StreamWriter(gs)) { sw.WriteLine(page.Attributes["lastrevid"].Value); sw.Write(text); } } List<string> titlesWithResults = new List<string>(); Dictionary<string, List<WikiPageSection>> titles = new Dictionary<string, List<WikiPageSection>>(); day.Page = WikiPage.Parse(pageName, text); foreach (WikiPageSection section in day.Page.Sections) { ReplaceEmptyResults(section); RemoveStrikeOut(section); StrikeOutSection(section); if (section.Subsections.Count(s => _l10i.Processor != null ? _l10i.Results.Any(r => r == _l10i.Processor(s).Trim()) : _l10i.Results.Any(r => r == s.Title.Trim())) == 0 && section.Subsections.Count(s => s.Title.Trim() == _l10i.ChallengedResult) == 0) { Match m = wikiLinkRE.Match(section.Title); if (m.Success) { string title = m.Groups[1].Value.Trim(); if (titles.ContainsKey(title)) { titles[title].Add(section); } else { titles.Add(title, new List<WikiPageSection>()); titles[title].Add(section); } } } { Match m = wikiLinkRE.Match(section.Title); if (m.Success && section.Title.Contains("<s>")) { titlesWithResults.Add(m.Groups[1].Value.Trim()); } List<WikiPageSection> sections = new List<WikiPageSection>(); section.Reduce(sections, SubsectionsList); foreach (WikiPageSection subsection in sections) { m = wikiLinkRE.Match(subsection.Title); if (m.Success && subsection.Title.Contains("<s>")) { titlesWithResults.Add(m.Groups[1].Value.Trim()); } if (m.Success && !subsection.Title.Contains("<s>") && subsection.Subsections.Count(s => s.Title.Trim() == _l10i.ChallengedResult) == 0 && subsection.Subsections.Count(s => _l10i.Processor != null ? _l10i.Results.Any(r => r == _l10i.Processor(s).Trim()) : _l10i.Results.Any(r => r == s.Title.Trim())) == 0) { string title = m.Groups[1].Value.Trim(); if (titles.ContainsKey(title)) { titles[title].Add(subsection); } else { titles.Add(title, new List<WikiPageSection>()); titles[title].Add(subsection); } } } } } parameters.Clear(); parameters.Add("prop", "info"); Dictionary<string, string> normalizedTitles = new Dictionary<string, string>(); XmlDocument xml = wiki.Query(QueryBy.Titles, parameters, titles.Keys); foreach (XmlNode node in xml.SelectNodes("//n")) { normalizedTitles.Add(node.Attributes["to"].Value, node.Attributes["from"].Value); } List<string> notificationList = new List<string>(); XmlNodeList missingTitles = xml.SelectNodes("//page"); foreach (XmlNode node in missingTitles) { string title = node.Attributes["title"].Value; IEnumerable<WikiPageSection> sections; if (titles.ContainsKey(title)) { sections = titles[title]; } else { sections = titles[normalizedTitles[title]]; } if (node.Attributes["missing"] != null) { DateTime start = day.Date; //foreach (WikiPageSection section in sections) //{ // Match m = timeRE.Match(section.Text); // if (m.Success) // { // start = DateTime.Parse(m.Groups[1].Value, // CultureInfo.CreateSpecificCulture(_l10i.Culture), // DateTimeStyles.AssumeUniversal); // } //} parameters.Clear(); parameters.Add("list", "logevents"); parameters.Add("letype", "delete"); parameters.Add("lemlimit", "max"); parameters.Add("lestart", start.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")); parameters.Add("ledir", "newer"); parameters.Add("letitle", title); parameters.Add("leprop", "comment|type|user|timestamp"); XmlDocument log = wiki.Enumerate(parameters, true); XmlNodeList items = log.SelectNodes("//item"); List<DeleteLogEvent> events = new List<DeleteLogEvent>(); foreach (XmlNode item in items) { DeleteLogEvent ev = new DeleteLogEvent(); ev.Comment = item.Attributes["comment"].Value; ev.Deleted = item.Attributes["action"].Value == "delete"; ev.User = item.Attributes["user"].Value; ev.Timestamp = DateTime.Parse(item.Attributes["timestamp"].Value, null, DateTimeStyles.AssumeUniversal); events.Add(ev); } events.Sort(CompareDeleteLogEvents); if (events.Count > 0 && events[0].Deleted && (DateTime.Now - events[0].Timestamp).TotalHours > 2) { string comment = FilterWikiMarkup(events[0].Comment); string message = string.Format(_l10i.AutoResultMessage, events[0].User, events[0].Timestamp.ToUniversalTime().ToString(_l10i.DateFormat, CultureInfo.CreateSpecificCulture(_l10i.Culture)), comment); var pageSections = titles.ContainsKey(title) ? titles[title] : titles[normalizedTitles[title]]; foreach (WikiPageSection section in pageSections) { WikiPageSection verdict = new WikiPageSection(" " + _l10i.AutoResultSection + " ", section.Level + 1, message); section.AddSubsection(verdict); StrikeOutSection(section); ++results; } } } } if (_l10i.Culture != "ru-RU") { parameters.Clear(); parameters.Add("prop", "info"); xml = wiki.Query(QueryBy.Titles, parameters, titlesWithResults); foreach (XmlNode node in xml.SelectNodes("//page")) { if (node.Attributes["missing"] == null && node.Attributes["redirect"] == null && node.Attributes["ns"].Value == "0") { notificationList.Add(node.Attributes["title"].Value); } } if (notificationList.Count > 0) { parameters.Clear(); parameters.Add("list", "backlinks"); parameters.Add("bltitle", pageName); parameters.Add("blfilterredir", "nonredirects"); parameters.Add("blnamespace", "1"); parameters.Add("bllimit", "max"); XmlDocument backlinks = wiki.Enumerate(parameters, true); foreach (string title in notificationList) { string talkPage = wiki.GetNamespace(1) + ":" + title; if (backlinks.SelectSingleNode("//bl[@title=" + GenerateConcatForXPath(talkPage) + "]") == null) { PutNotification(wiki, title, date); } } } } string newText = day.Page.Text; if (newText.Trim() == text.Trim()) { continue; } try { Console.Out.WriteLine("Updating " + pageName + "..."); string revid = wiki.Save(pageName, "", newText, _l10i.StrikeOutComment + (results > 0 ? _l10i.AutoResultComment : ""), MinorFlags.Minor, CreateFlags.NoCreate, WatchFlags.None, SaveFlags.Replace, true, basetimestamp, "", editToken); using (FileStream fs = new FileStream(fileName, FileMode.Create)) using (GZipStream gs = new GZipStream(fs, CompressionMode.Compress)) using (StreamWriter sw = new StreamWriter(gs)) { sw.WriteLine(revid); sw.Write(newText); } } catch (WikiException) { } } }
public void Analyze(Wiki wiki) { ParameterCollection parameters = new ParameterCollection(); parameters.Add("generator", "categorymembers"); parameters.Add("gcmtitle", "Категория:Википедия:Незакрытые обсуждения объединения страниц"); parameters.Add("gcmlimit", "max"); parameters.Add("gcmnamespace", "4"); parameters.Add("prop", "info"); XmlDocument doc = wiki.Enumerate(parameters, true); XmlNodeList pages = doc.SelectNodes("//page"); List<Day> days = new List<Day>(); DateTime start = DateTime.Today; foreach (XmlNode page in pages) { string pageName = page.Attributes["title"].Value; string date = pageName.Substring("Википедия:К объединению/".Length); Day day = new Day(); try { day.Date = DateTime.Parse(date, CultureInfo.CreateSpecificCulture("ru-RU"), DateTimeStyles.AssumeUniversal); } catch (FormatException) { continue; } string fileName = _cacheDir + date + ".bin"; string text = LoadPageFromCache(fileName, page.Attributes["lastrevid"].Value, pageName); if (string.IsNullOrEmpty(text)) { Console.Out.WriteLine("Downloading " + pageName + "..."); text = wiki.LoadText(pageName); CachePage(fileName, page.Attributes["lastrevid"].Value, text); } Match m = _closedRE.Match(text); if (m.Success) { Console.Out.WriteLine("Closing " + pageName + "..."); text = text.Replace("{{ВПКОБ-Навигация}}", "{{ВПКОБ-Навигация|nocat=1}}"); wiki.Save(pageName, text, "обсуждение закрыто"); continue; } day.Page = WikiPage.Parse(pageName, text); days.Add(day); } days.Sort(CompareDays); using (StreamWriter sw = new StreamWriter(_cacheDir + "MainPage.txt")) { sw.WriteLine("== Текущие обсуждения ==\n"); sw.WriteLine("{{Объединение статей/Статьи, вынесенные для объединения}}\n"); foreach (Day day in days) { sw.Write("{{Объединение статей/День|" + day.Date.ToString("yyyy-M-d") + "|\n"); List<string> titles = new List<string>(); foreach (WikiPageSection section in day.Page.Sections) { string filler = ""; RemoveStrikeOut(section); StrikeOutSection(section); for (int i = 0; i < section.Level - 1; ++i) { filler += "*"; } titles.Add(filler + " " + section.Title.Trim()); List<WikiPageSection> sections = new List<WikiPageSection>(); section.Reduce(sections, SubsectionsList); foreach (WikiPageSection subsection in sections) { filler = ""; for (int i = 0; i < subsection.Level - 1; ++i) { filler += "*"; } titles.Add(filler + " " + subsection.Title.Trim()); } } if (titles.Count(s => s.Contains("=")) > 0) { titles[0] = "2=<li>" + titles[0].Substring(2) + "</li>"; } sw.Write(string.Join("\n", titles.ConvertAll(c => c).ToArray())); sw.Write("}}\n\n"); } sw.WriteLine("{{/Подвал}}"); } }
public void UpdateArchivePages(Wiki wiki) { ParameterCollection parameters = new ParameterCollection(); parameters.Add("generator", "categorymembers"); parameters.Add("gcmtitle", "Категория:Википедия:Незакрытые обсуждения категорий"); parameters.Add("gcmlimit", "max"); parameters.Add("gcmnamespace", "4"); parameters.Add("prop", "info"); XmlDocument doc = wiki.Enumerate(parameters, true); XmlNodeList pages = doc.SelectNodes("//page"); DateTime minDate = DateTime.Now; foreach (XmlNode page in pages) { string pageName = page.Attributes["title"].Value; string date = pageName.Substring("Википедия:Обсуждение категорий/".Length); DateTime day; if (DateTime.TryParse(date, CultureInfo.CreateSpecificCulture("ru-RU"), DateTimeStyles.AssumeUniversal, out day)) { if (day < minDate) { minDate = day; } } else { continue; } } List<string> titles = new List<string>(); minDate = new DateTime(minDate.Year, minDate.Month, 1); DateTime currentMonth = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1); DateTime start = new DateTime(minDate.Year, 1, 1); while (start <= currentMonth) { string date = start.ToString("yyyy"); string pageName = "Википедия:Обсуждение категорий/Архив/" + date; titles.Add(pageName); start = start.AddYears(1); } parameters.Clear(); parameters.Add("prop", "info"); XmlDocument archivesDoc = wiki.Query(QueryBy.Titles, parameters, titles); pages = archivesDoc.SelectNodes("//page"); foreach (XmlNode archivePage in pages) { string archiveName = archivePage.Attributes["title"].Value; string date = archiveName.Substring("Википедия:Обсуждение категорий/Архив/".Length); int year; if (!int.TryParse(date, out year)) { continue; } DateTime archiveDate = new DateTime(year, 1, 1); string fileName = _cacheDir + "Archive-" + date + ".txt"; start = archiveDate; DateTime end = start.AddYears(1); titles.Clear(); while (start < end) { string pageDate = start.ToString("MMMM yyyy", CultureInfo.CreateSpecificCulture("ru-RU")); string prefix = "Википедия:Обсуждение категорий/"; string pageName = prefix + pageDate; titles.Add(pageName); start = start.AddMonths(1); } parameters.Clear(); parameters.Add("prop", "info"); List<Day> days = new List<Day>(); XmlDocument xml = wiki.Query(QueryBy.Titles, parameters, titles); XmlNodeList archives = xml.SelectNodes("//page"); foreach (XmlNode page in archives) { string pageName = page.Attributes["title"].Value; string dateString = pageName.Substring("Википедия:Обсуждение категорий/".Length); string pageFileName = _cacheDir + dateString + ".bin"; Day day = new Day(); if (!DateTime.TryParse(dateString, CultureInfo.CreateSpecificCulture("ru-RU"), DateTimeStyles.AssumeUniversal, out day.Date)) { continue; } if (page.Attributes["missing"] != null) { continue; } string text = LoadPageFromCache(pageFileName, page.Attributes["lastrevid"].Value, pageName); if (string.IsNullOrEmpty(text)) { Console.Out.WriteLine("Downloading " + pageName + "..."); text = wiki.LoadText(pageName); CachePage(pageFileName, page.Attributes["lastrevid"].Value, text); } day.Page = WikiPage.Parse(pageName, text); days.Add(day); } days.Sort(CompareDays); StringBuilder sb = new StringBuilder(); sb.AppendLine("{{Википедия:Обсуждение категорий/Обсуждаемые категории}}\n"); foreach (Day day in days) { sb.Append("{{Википедия:Обсуждение категорий/Месяц|" + day.Date.ToString("yyyy-M") + "|\n"); List<string> sectionTitles = new List<string>(); foreach (WikiPageSection section in day.Page.Sections) { string filler = ""; for (int i = 0; i < section.Level - 1; ++i) { filler += "*"; } sectionTitles.Add(filler + " " + section.Title.Trim()); List<WikiPageSection> sections = new List<WikiPageSection>(); section.Reduce(sections, SubsectionsList); foreach (WikiPageSection subsection in sections) { filler = ""; for (int i = 0; i < subsection.Level - 1; ++i) { filler += "*"; } sectionTitles.Add(filler + " " + subsection.Title.Trim()); } } if (sectionTitles.Count(s => s.Contains("=")) > 0) { sectionTitles[0] = "2=<div>" + sectionTitles[0].Substring(2); } sb.Append(string.Join("\n", sectionTitles.ConvertAll(c => c).ToArray())); if (sectionTitles.Count(s => s.Contains("=")) > 0) { sb.Append("</div>"); } sb.Append("}}\n\n"); } sb.Append("|}"); sb.Replace("<s>", ""); sb.Replace("</s>", ""); sb.Replace("<strike>", ""); sb.Replace("</strike>", ""); if (File.Exists(fileName)) { using (TextReader sr = new StreamReader(fileName)) { string txt = sr.ReadToEnd(); if (txt == sb.ToString()) { continue; } } } Console.Out.WriteLine("Updating " + archiveName + "..."); wiki.Save(archiveName, sb.ToString(), "обновление"); using (StreamWriter sw = new StreamWriter(fileName)) { sw.Write(sb.ToString()); } } }