public MovedPageList(BotConfiguration bc, InputParameters inp) { Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; _botConfiguration = bc; _commonlog = new InterwikiLogger(_botConfiguration.CommonLog, _botConfiguration.CommonLogLevel, inp); _actionlog = new InterwikiLogger(_botConfiguration.ActionLog, _botConfiguration.ActionLogLevel, inp); _conflictlog = new InterwikiLogger(_botConfiguration.ConflictLog, _botConfiguration.ConflictLogLevel, inp); }
public InterwikiLogger(string logFile, int logLevel, InputParameters inp) { _logFile = logFile .Replace("%id", inp.ProcessId) .Replace("%ns", inp.Ns.ToString()) .Replace("%type", inp.Type); _logLevel = logLevel; if (!Path.IsPathRooted(logFile)) { _logFile = Path.GetFullPath(_logFile); } var dir = Path.GetDirectoryName(_logFile); if (dir != null) Directory.CreateDirectory(dir); }
static void Main(string[] args) { InputParameters inputParameters = new InputParameters(); var res = inputParameters.ParseParameters(args); if (!res) return; var botConfiguration = new BotConfiguration(); res = botConfiguration.ReadConfiguration(inputParameters.Botconfig); botConfiguration.ReadNamespaceConformity(); if (!res) { Console.WriteLine("Incorrect configuration file"); return; } try { var mlpl = new MultilingualPageList(botConfiguration, inputParameters); var mopl = new MovedPageList(botConfiguration, inputParameters); if (inputParameters.Type == "new") mlpl.ProcessNewPages(inputParameters); if (inputParameters.Type == "range") mlpl.ProcessRangePages(inputParameters); if (inputParameters.Type == "page") mlpl.ProcessPage(inputParameters); if (inputParameters.Type == "cat" || inputParameters.Type == "category") mlpl.ProcessCategoryPages(inputParameters); if (inputParameters.Type == "user" || inputParameters.Type == "usercontribs") mlpl.ProcessUserContributions(inputParameters); if (inputParameters.Type == "movecat") mopl.FindMovedCategories(inputParameters); if (inputParameters.Type == "movecatrange") mopl.ProcessCategoryRedirectRange2(inputParameters); if (inputParameters.Type == "moverange") mopl.ProcessRedirectRange(inputParameters); if (inputParameters.Type == "move") mopl.ProcessMovedPages(inputParameters); } catch (Exception e) { Console.WriteLine(e); } }
public InterwikiLogger(string logFile, int logLevel, InputParameters inp) { _logFile = logFile .Replace("%id", inp.ProcessId) .Replace("%ns", inp.Ns.ToString()) .Replace("%type", inp.Type); _logLevel = logLevel; if (!Path.IsPathRooted(logFile)) { _logFile = Path.GetFullPath(_logFile); } var dir = Path.GetDirectoryName(_logFile); if (dir != null) { Directory.CreateDirectory(dir); } }
public void ProcessRangePages(InputParameters inp) { LogIn(); var fromStr = inp.Fromstr; var toStr = inp.Tostr; if (string.IsNullOrEmpty(fromStr)) { fromStr = "!"; } if (string.IsNullOrEmpty(toStr)) { toStr = ""; } fromStr = HttpUtility.UrlDecode(fromStr).Replace('_', ' '); toStr = HttpUtility.UrlDecode(toStr).Replace('_', ' '); _wikiCodes = _botConfiguration.GetWikiCodes(inp.Projectcode); _commonlog.LogData("", 5); _commonlog.LogData("Range processing", 4); _commonlog.LogData("Language:", inp.Langcode, 4); _commonlog.LogData("Namespace:", inp.Ns.ToString(), 4); _commonlog.LogData("Starting:", fromStr, 4); if (toStr.Length > 0) { _commonlog.LogData("Ending:", toStr, 4); } if (inp.Fullcheck) { _commonlog.LogData("Full check", 4); } var pages = new List <PageInfo>(); while (true) { pages.Clear(); Dictionary <string, object> queryParams = new Dictionary <string, object> { { "querytype", "allpages" }, { "ns", inp.Ns }, { "limit", inp.Query }, { "offset", fromStr } }; var newFromStr = WikiApiFunctions.FillFromApiQuery(pages, inp.Langcode, inp.Projectcode, queryParams); int portionNumber = (pages.Count - 1) / _bigPortionSize + 1; for (int i = 0; i < portionNumber; i++) { var firstind = i * _bigPortionSize; var num = pages.Count - firstind; if (num > _bigPortionSize) { num = _bigPortionSize; } _commonlog.LogData("", 2); _commonlog.LogData("New portion of pages", 2); _commonlog.LogData("Number of pages:", num.ToString(), 2); TryProcessPortion(inp.Langcode, inp.Projectcode, pages.Skip(firstind).Take(num).Select(p => p.Title).ToList(), inp.Fullcheck, inp.OnlyUpdate); } if (newFromStr.Length == 0) { break; } if (toStr.Length > 0 && newFromStr.CompareTo(toStr) > 0) { break; } fromStr = newFromStr; } }
static void Main(string[] args) { InputParameters inputParameters = new InputParameters(); var res = inputParameters.ParseParameters(args); if (!res) { return; } var botConfiguration = new BotConfiguration(); res = botConfiguration.ReadConfiguration(inputParameters.Botconfig); botConfiguration.ReadNamespaceConformity(); if (!res) { Console.WriteLine("Incorrect configuration file"); return; } try { var mlpl = new MultilingualPageList(botConfiguration, inputParameters); var mopl = new MovedPageList(botConfiguration, inputParameters); if (inputParameters.Type == "new") { mlpl.ProcessNewPages(inputParameters); } if (inputParameters.Type == "range") { mlpl.ProcessRangePages(inputParameters); } if (inputParameters.Type == "page") { mlpl.ProcessPage(inputParameters); } if (inputParameters.Type == "cat" || inputParameters.Type == "category") { mlpl.ProcessCategoryPages(inputParameters); } if (inputParameters.Type == "user" || inputParameters.Type == "usercontribs") { mlpl.ProcessUserContributions(inputParameters); } if (inputParameters.Type == "movecat") { mopl.FindMovedCategories(inputParameters); } if (inputParameters.Type == "movecatrange") { mopl.ProcessCategoryRedirectRange2(inputParameters); } if (inputParameters.Type == "moverange") { mopl.ProcessRedirectRange(inputParameters); } if (inputParameters.Type == "move") { mopl.ProcessMovedPages(inputParameters); } } catch (Exception e) { Console.WriteLine(e); } }
private void ProcessCategoryTalkMovedTemplates(InputParameters inp, List<PageInfo> categories) { var catTalkPages = categories.Select( cat => new PageInfo { Title = _botConfiguration.Namespaces[inp.Langcode][15] + cat.Title.Substring(_botConfiguration.Namespaces[inp.Langcode][14].Length), RedirectTo = cat.Title }) .ToList(); var talkTemplates = GetTemplates(inp.Langcode, inp.Projectcode, catTalkPages.Select(pi => pi.Title).ToList()); var talksWithMoveLabel = talkTemplates .Where(pt => pt.Value.Contains(_categoryTalkMovedTemplate)) .Select(pt => pt.Key) .ToList(); catTalkPages = catTalkPages.Where(pi => talksWithMoveLabel.Contains(pi.Title)).ToList(); var catLinks = GetPageLinks(inp.Langcode, inp.Projectcode, catTalkPages.Select(pi => pi.Title).ToList(), 14); var oldDeletedCategories = GetProperTitles(inp.Langcode, inp.Projectcode, catLinks.Select(cl => cl.Value[0]).ToList()) .Where(pi => pi.IsMissing) .Select(pi => pi.Title) .ToList(); catLinks = catLinks.Where(cl => oldDeletedCategories.Contains(cl.Value[0])) .ToDictionary(cl => cl.Key, cl => cl.Value); var oldWikidataLinks = GetWikidataLinks(inp.Langcode, inp.Projectcode, catLinks.Select(cl => cl.Value[0]).ToList()); catLinks = catLinks.Where(cl => oldWikidataLinks.ContainsKey(cl.Value[0])) .ToDictionary(cl => cl.Key, cl => cl.Value); foreach (var cl in catLinks) { var ctp = catTalkPages.FirstOrDefault(ct => ct.Title == cl.Key); if (ctp == null) continue; var newTitle = ctp.RedirectTo; var oldTitle = cl.Value[0]; var wdId = oldWikidataLinks[oldTitle]; UpdateWikidataLink(inp.Langcode, inp.Projectcode, wdId, oldTitle, newTitle, "mtt"); } }
private void ProcessMovedCategoryTalks(InputParameters inp, List<PageInfo> categories) { var movedCatTalks = new List<PageInfo>(); var movedCategories = new List<PageInfo>(); _commonlog.LogData("Check new category talks moves", 4); Dictionary<string, object> queryParams = new Dictionary<string, object> { {"querytype", "log"}, {"ns", 14}, {"limit", inp.Query}, {"type", "move"}, {"hours", inp.Hours}, {"timefiltration", 1} }; WikiApiFunctions.FillFromApiQuery(movedCatTalks, inp.Langcode, inp.Projectcode, queryParams); movedCatTalks = _botConfiguration.FilterByNamespace(movedCatTalks, inp.Langcode, 15); _commonlog.LogData("Found moved talks:", movedCatTalks.Count.ToString(), 4); foreach (var talkPage in movedCatTalks) { if (_botConfiguration.GetNamespace(inp.Langcode, talkPage.RedirectTo) != 15) continue; var movedCat = new PageInfo { Title = _botConfiguration.Namespaces[inp.Langcode][14] + talkPage.Title.Substring(_botConfiguration.Namespaces[inp.Langcode][15].Length), RedirectTo = _botConfiguration.Namespaces[inp.Langcode][14] + talkPage.RedirectTo.Substring(_botConfiguration.Namespaces[inp.Langcode][15].Length) }; movedCategories.Add(movedCat); } movedCategories = movedCategories .Where(cat => categories.Select(p => p.Title).Contains(cat.RedirectTo)) .ToList(); var catsWithWikidata = GetWikidataLinks(inp.Langcode, inp.Projectcode, movedCategories.Select(pi => pi.RedirectTo).ToList()); movedCategories = movedCategories .Where(cat => !catsWithWikidata.ContainsKey(cat.RedirectTo)) .ToList(); _commonlog.LogData("Categories without Wikidata links:", movedCategories.Count.ToString(), 4); var oldCatsWithWikidata = GetWikidataLinks(inp.Langcode, inp.Projectcode, movedCategories.Select(pi => pi.Title).ToList()); movedCategories = movedCategories .Where(cat => oldCatsWithWikidata.ContainsKey(cat.Title)) .ToList(); _commonlog.LogData("Old categories with Wikidata links:", movedCategories.Count.ToString(), 4); movedCategories = CheckOldAndNewCategoryMatching(inp.Langcode, inp.Projectcode, movedCategories); _commonlog.LogData("Wikidata links to be updated:", movedCategories.Count.ToString(), 4); foreach (var cat in movedCategories) { var wdId = oldCatsWithWikidata[cat.Title]; UpdateWikidataLink(inp.Langcode, inp.Projectcode, wdId, cat.Title, cat.RedirectTo, "tm"); } }
public void FindMovedCategories(InputParameters inp) { var newCats = new List<PageInfo>(); Dictionary<string, object> queryParams = new Dictionary<string, object> { {"querytype", "newpages"}, {"ns", 14}, {"limit", inp.Query}, {"withcomments", 1}, {"hours", inp.Hours} }; WikiApiFunctions.FillFromApiQuery(newCats, inp.Langcode, inp.Projectcode, queryParams); if (newCats.Count == 0) return; LogIn(); _wikiCodes = _botConfiguration.GetWikiCodes(inp.Projectcode); _botConfiguration.GetNamespaces(inp.Langcode, inp.Projectcode); GetCategoryRedirectTemplate(inp.Langcode, inp.Projectcode); if (inp.Mode == "all" || inp.Mode == "talkmove") { ProcessMovedCategoryTalks(inp, newCats); } if (inp.Mode == "all" || inp.Mode == "catredir") { GetCategoryRedirectTemplate(inp.Langcode, inp.Projectcode); if (_categoryRedirectTemplate.Length != 0) { var wikidataLinks = GetWikidataLinks(inp.Langcode, inp.Projectcode, newCats.Select(p => p.Title).ToList()); newCats = newCats.Where(p => !wikidataLinks.ContainsKey(p.Title)).ToList(); ProcessCategoryRedirects(inp, newCats); } } if (inp.Mode == "all" || inp.Mode == "talkmovedtemplate") { GetCategoryTalkMovedTemplate(inp.Langcode, inp.Projectcode); if (_categoryTalkMovedTemplate.Length != 0) { var wikidataLinks = GetWikidataLinks(inp.Langcode, inp.Projectcode, newCats.Select(p => p.Title).ToList()); newCats = newCats.Where(p => !wikidataLinks.ContainsKey(p.Title)).ToList(); ProcessCategoryTalkMovedTemplates(inp, newCats); } } if (inp.Mode == "all" || inp.Mode == "replacedcategory") { var wikidataLinks = GetWikidataLinks(inp.Langcode, inp.Projectcode, newCats.Select(p => p.Title).ToList()); newCats = newCats.Where(p => !wikidataLinks.ContainsKey(p.Title)).ToList(); ProcessReplacedCategories(inp, newCats); } }
private void ProcessCategoryRedirects(InputParameters inp, List<PageInfo> categories) { foreach (var cat in categories) { var linkedCats = new List<PageInfo>(); Dictionary<string, object> queryParams = new Dictionary<string, object> { {"querytype", "linkstopage"}, {"ns", 14}, {"limit", 50}, {"title", cat.Title}, {"withredirects", 1} }; WikiApiFunctions.FillFromApiQuery(linkedCats, inp.Langcode, inp.Projectcode, queryParams); if (linkedCats.Count == 0) continue; var oldCatsWithRedirectTemplates = WikiApiFunctions.GetTemplates(inp.Langcode, inp.Projectcode, linkedCats.Select(p => p.Title).ToArray(), 100) .Where(ts => ts.Value.Contains(_categoryRedirectTemplate)) .Select(ts => ts.Key) .ToList(); if (oldCatsWithRedirectTemplates.Count == 0) continue; var oldCatsWithWikidata = GetWikidataLinks(inp.Langcode, inp.Projectcode, oldCatsWithRedirectTemplates); if (oldCatsWithWikidata.Count != 1) continue; var oldTitle = oldCatsWithWikidata.Keys.First(); var wdId = oldCatsWithWikidata[oldTitle]; UpdateWikidataLink(inp.Langcode, inp.Projectcode, wdId, oldTitle, cat.Title, "cr"); } }
public void ProcessRedirectRange(InputParameters inp) { LogIn(); var fromStr = inp.Fromstr; var toStr = inp.Tostr; if (string.IsNullOrEmpty(fromStr)) fromStr = "!"; if (string.IsNullOrEmpty(toStr)) toStr = ""; // fromStr = HttpUtility.UrlDecode(fromStr).Replace('_', ' '); // toStr = HttpUtility.UrlDecode(toStr).Replace('_', ' '); // fromStr = "B"; _wikiCodes = _botConfiguration.GetWikiCodes(inp.Projectcode); _botConfiguration.GetNamespaces(inp.Langcode, inp.Projectcode); _commonlog.LogData("", 5); _commonlog.LogData("Range processing", 4); _commonlog.LogData("Language:", inp.Langcode, 4); _commonlog.LogData("Namespace:", inp.Ns.ToString(), 4); _commonlog.LogData("Starting:", fromStr, 4); if (toStr.Length > 0) _commonlog.LogData("Ending:", toStr, 4); var pages = new List<PageInfo>(); while (true) { pages.Clear(); Dictionary<string, object> queryParams = new Dictionary<string, object> { {"querytype", "allpages"}, {"ns", inp.Ns}, {"limit", inp.Query}, {"offset", fromStr}, {"redirtype", "redirects"} }; var newFromStr = WikiApiFunctions.FillFromApiQuery(pages, inp.Langcode, inp.Projectcode, queryParams); int portionNumber = (pages.Count - 1) / _bigPortionSize + 1; for (int i = 0; i < portionNumber; i++) { var firstind = i * _bigPortionSize; var num = pages.Count - firstind; if (num > _bigPortionSize) num = _bigPortionSize; _commonlog.LogData("", 2); _commonlog.LogData("New portion of pages", 2); _commonlog.LogData("Number of pages:", num.ToString(), 2); ProcessMovedPortion(inp.Langcode, inp.Projectcode, pages.Skip(firstind).Take(num).ToList()); } if (newFromStr.Length == 0) break; if (toStr.Length > 0 && newFromStr.CompareTo(toStr) > 0) break; fromStr = newFromStr; } }
public void ProcessReplacedCategories(InputParameters inp, List<PageInfo> categories) { var listOfBots = new List<PageInfo>(); var queryParams = new Dictionary<string, object> { {"querytype", "users"}, {"limit", inp.Query}, {"group", "bot"}, {"getall", 1} }; WikiApiFunctions.FillFromApiQuery(listOfBots, inp.Langcode, inp.Projectcode, queryParams); var categoryBotExclusions = _botConfiguration.GetCategoryBotExclusions(inp.Langcode); listOfBots = listOfBots.Where(u => !categoryBotExclusions.Contains(u.Title)).ToList(); if (categories.Count > 0) categories = categories.Where(p => listOfBots.Select(u => u.Title).Contains(p.User)).ToList(); _commonlog.LogData("Found new categories:", categories.Count.ToString(), 4); if (categories.Count <= 0) { _commonlog.LogData("Finishing", 4); return; } foreach (var cat in categories) { TryTrackReplacedCategory(inp.Langcode, inp.Projectcode, cat.Title, cat.User, cat.Timestamp); } }
public void ProcessCategoryPages(InputParameters inp) { LogIn(); var catname = inp.Catname; catname = HttpUtility.UrlDecode(catname).Replace('_', ' '); _wikiCodes = _botConfiguration.GetWikiCodes(inp.Projectcode); _commonlog.LogData("", 5); _commonlog.LogData("Category processing", 4); _commonlog.LogData("Language:", inp.Langcode, 4); _commonlog.LogData("Namespace:", inp.Ns.ToString(), 4); _commonlog.LogData("Category:", catname, 4); _commonlog.LogData("Depth:", inp.Depth.ToString(), 4); if (inp.Fullcheck) _commonlog.LogData("Full check", 4); var pages = new List<PageInfo>(); pages.Clear(); Dictionary<string, object> queryParams = new Dictionary<string, object> { {"querytype", "categorytree"}, {"ns", inp.Ns}, {"limit", inp.Query}, {"categoryname", catname}, {"depth", inp.Depth} }; WikiApiFunctions.FillFromApiQuery(pages, inp.Langcode, inp.Projectcode, queryParams); int portionNumber = (pages.Count - 1) / _bigPortionSize + 1; for (int i = 0; i < portionNumber; i++) { var firstind = i * _bigPortionSize; var num = pages.Count - firstind; if (num > _bigPortionSize) num = _bigPortionSize; _commonlog.LogData("", 2); _commonlog.LogData("New portion of pages", 2); _commonlog.LogData("Number of pages:", num.ToString(), 2); TryProcessPortion(inp.Langcode, inp.Projectcode, pages.Skip(firstind).Take(num).Select(p => p.Title).ToList(), inp.Fullcheck, inp.OnlyUpdate); } }
public void ProcessMovedPages(InputParameters inp) { _commonlog.LogData("", 5); _commonlog.LogData("move page processing", 4); _commonlog.LogData("Language:", inp.Langcode, 4); _commonlog.LogData("Namespace:", inp.Ns.ToString(), 4); _commonlog.LogData("Hours:", inp.Hours.ToString(), 4); _commonlog.LogData("Query size:", inp.Query.ToString(), 4); var pages = new List<PageInfo>(); var timeBorder = DateTime.UtcNow.AddMinutes(-_botConfiguration.MoveWaitMin); Dictionary<string, object> queryParams = new Dictionary<string, object> { {"querytype", "log"}, {"ns", 14}, {"limit", inp.Query}, {"type", "move"}, {"hours", inp.Hours}, {"timefiltration", 1} }; WikiApiFunctions.FillFromApiQuery(pages, inp.Langcode, inp.Projectcode, queryParams); _botConfiguration.GetNamespaces(inp.Langcode, inp.Projectcode); pages = pages.Where(pi => pi.Timestamp.CompareTo(timeBorder) <= 0).ToList(); pages = _botConfiguration.FilterByNamespace(pages, inp.Langcode, -100); _commonlog.LogData("Found new page(s):", pages.Count.ToString(), 4); if (pages.Count <= 0) { _commonlog.LogData("Finishing", 4); return; } LogIn(); _wikiCodes = _botConfiguration.GetWikiCodes(inp.Projectcode); int portionNumber = (pages.Count - 1) / 500 + 1; for (int i = 0; i < portionNumber; i++) { var firstind = i * 500; var num = pages.Count - firstind; if (num > 500) num = 500; _commonlog.LogData("", 2); _commonlog.LogData("New portion of pages", 2); _commonlog.LogData("Number of pages:", num.ToString(), 2); ProcessMovedPortion(inp.Langcode, inp.Projectcode, pages.Skip(firstind).Take(num).ToList()); } }
public void ProcessCategoryRedirectRange2(InputParameters inp) { _wikiCodes = _botConfiguration.GetWikiCodes(inp.Projectcode); GetCategoryRedirectTemplate(inp.Langcode, inp.Projectcode); _commonlog.LogData("", 5); _commonlog.LogData("Range processing", 4); _commonlog.LogData("Language:", inp.Langcode, 4); _commonlog.LogData("Namespace:", inp.Ns.ToString(), 4); if (_categoryRedirectTemplate.Length == 0) { _commonlog.LogData("There is no category redirect template. Finishing", 4); return; } var pages = new List<PageInfo>(); Dictionary<string, object> queryParams = new Dictionary<string, object> { {"querytype", "transclusions"}, {"ns", 14}, {"limit", inp.Query}, {"title", _categoryRedirectTemplate}, {"getall", 1} }; WikiApiFunctions.FillFromApiQuery(pages, inp.Langcode, inp.Projectcode, queryParams); LogIn(); int portionNumber = (pages.Count - 1) / 500 + 1; for (int i = 0; i < portionNumber; i++) { var firstind = i * 500; var num = pages.Count - firstind; if (num > 500) num = 500; _commonlog.LogData("", 2); _commonlog.LogData("New portion of pages", 2); _commonlog.LogData("Number of pages:", num.ToString(), 2); ProcessCategoryRedirects(inp.Langcode, inp.Projectcode, pages.Skip(firstind).Take(num).Select(p => p.Title).ToList()); } }
public void ProcessPage(InputParameters inp) { var title = inp.Fromstr; if (string.IsNullOrEmpty(title)) { _commonlog.LogData("Incorrect page title. Finishing.", 5); return; } LogIn(); title = HttpUtility.UrlDecode(title).Replace('_', ' '); _wikiCodes = _botConfiguration.GetWikiCodes(inp.Projectcode); _commonlog.LogData("", 5); _commonlog.LogData("One page processing", 4); _commonlog.LogData("Language:", inp.Langcode, 4); _commonlog.LogData("Namespace:", inp.Ns.ToString(), 4); if (inp.Fullcheck) _commonlog.LogData("Full check", 4); TryProcessPortion(inp.Langcode, inp.Projectcode, new List<string> { title }, inp.Fullcheck, inp.OnlyUpdate); }
public void ProcessUserContributions(InputParameters inp) { _commonlog.LogData("", 5); _commonlog.LogData("User contribution processing", 4); _commonlog.LogData("Language:", inp.Langcode, 4); _commonlog.LogData("User:"******"Namespace:", inp.Ns.ToString(), 4); _commonlog.LogData("Hours:", inp.Hours.ToString(), 4); _commonlog.LogData("Query size:", inp.Query.ToString(), 4); if (inp.Fullcheck) _commonlog.LogData("Full check", 4); var pages = new List<PageInfo>(); Dictionary<string, object> queryParams = new Dictionary<string, object> { {"querytype", "usercontributions"}, {"ns", inp.Ns}, {"limit", inp.Query}, {"timefiltration", 1} }; WikiApiFunctions.FillFromApiQuery(pages, inp.Langcode, inp.Projectcode, queryParams); _commonlog.LogData("Found new page(s):", pages.Count.ToString(), 4); if (pages.Count <= 0) { _commonlog.LogData("Finishing", 4); return; } LogIn(); _wikiCodes = _botConfiguration.GetWikiCodes(inp.Projectcode); int portionNumber = (pages.Count - 1) / 500 + 1; for (int i = 0; i < portionNumber; i++) { var firstind = i * 500; var num = pages.Count - firstind; if (num > 500) num = 500; _commonlog.LogData("", 2); _commonlog.LogData("New portion of pages", 2); _commonlog.LogData("Number of pages:", num.ToString(), 2); TryProcessPortion(inp.Langcode, inp.Projectcode, pages.Skip(firstind).Take(num).Select(p => p.Title).ToList(), inp.Fullcheck, inp.OnlyUpdate); } }