User:B-bot/source/OTRS Dated Filer

This task will create monthly categories for {{tl|OTRS pending}} and {{tl|OTRS received}}. It will check for templates missing a date and add it to them.

public class OtrsDatedFiler : BBotBase

{

///

/// Gets the name for this job

///

///

public override string GetJobName()

{

return "OTRS dated filer";

}

///

/// Both tasks will do this many. (If you want 50 edits, make this 25.)

///

public int MaximumImagesToProcess = 1000;

///

/// This function creates the requested category if it does not already exist

///

///

///

///

public bool CreateCatIfNeeded(ref Site site, Page pgUserspaceTest, String CategoryName, String StarterTemplate)

{

try

{

// Make sure that this month's and next month's dated categories exist

Page cat = new Page(site, CategoryName);

cat.Load();

SleepApiDelay();

if (!cat.Exists())

{

cat.text = StarterTemplate;

if (UserspaceTest)

{

pgUserspaceTest.text += "|-\r\n| :" + cat.title + " || ~~~~~ ||

" + cat.text.Substring(0, Math.Min(300, cat.text.Length)) + "
\r\n";

pgUserspaceTest.Save("Creating monthly category", false);

}

else

{

cat.Save(cat.text, "Creating monthly category", false);

}

SleepApiDelay();

LogToEventLog(ref site, MessageType.Informational, "Created category :" + CategoryName + " using " + StarterTemplate + ".", null);

}

SleepApiDelay();

return true;

}

catch (Exception ex)

{

LogToEventLog(ref site, MessageType.Informational, "Error creating category :" + CategoryName + " using " + StarterTemplate + ".", ex);

return false;

}

}

///

/// This function will add the date to the requested

///

///

///

///

/// "OTRS Pending", "OTRS received", etc

/// If this is a userspace test, the page on which that is being conducted

/// Format string to be used if we need to create the category

/// Starter template, if we need to create the category

/// True if the tag was modified, false otherwise

public bool DateTag(Site site, Page pg, String strRegex, String strTagName, Page pgUserspaceTest, String strCategoryFormatString, String StarterTemplate)

{

try

{

// If this is a user talk base page, then {{OTRS pending}} has probably been added to the wrong place

if (pg.title.ToLower().StartsWith("user talk:") && !pg.title.Contains("/"))

{

LogToEventLog(ref site, MessageType.Error, "Error: " + pg.title + " has a {{tl|" + strTagName + "}} tag. " +

"This tag should only be placed on file pages or article talk pages (including talk pages of draft articles). " +

"It should not be placed directly on user talk pages.", null);

return false;

}

pg.Load();

// Find the OTRS pending tag

Match match = Regex.Match(pg.text, strRegex, RegexOptions.IgnoreCase);

if (null != match && 0 < match.Length)

{

// Remove the tag from the string

String strNewText = "";

if (0 < match.Index)

{

strNewText = pg.text.Substring(0, match.Index);

}

// This is the tag, without the close

String strTag = pg.text.Substring(match.Index, match.Length).Replace("}}", "");

// If the tag appears to already have a date, then move on

if (strTag.Contains("date") ||

strTag.Contains("year") ||

strTag.Contains("month") ||

strTag.Contains("day"))

{

LogToEventLog(ref site, MessageType.Error, "Wanted to add a date to the " + strTagName + " tag of :" + pg.title + ", but it seems to already have one. Maybe the page has multiple tags?", null);

return false;

}

// Grab the timestamp (it gets blown away once we save)

DateTime dtmTimestamp = pg.timestamp;

// Add the date

strTag += "|year=" + dtmTimestamp.Year.ToString() +

"|month=" + dtmTimestamp.Month.ToString("00") +

"|day=" + dtmTimestamp.Day.ToString("00") + "}}";

strNewText += strTag;

// Add everything after the tag

if (match.Index + match.Length < pg.text.Length - 1)

{

strNewText += pg.text.Substring(match.Index + match.Length);

}

// Trim whitespace

strNewText = strNewText.Trim();

String strEditSummary = "Adding date to " + strTagName + " tag.";

if (UserspaceTest)

{

pgUserspaceTest.text += "|-\r\n| :" + pg.title + " || ~~~~~ ||

" +

pg.text.Substring(0, Math.Min(1500, pg.text.Length)) +

"

||
" + strNewText.Substring(0, Math.Min(1500, strNewText.Length)) + "
\r\n";

pgUserspaceTest.Save(strEditSummary, false);

}

else

{

pg.Save(strNewText, strEditSummary, false);

}

// Now, if that tag is more than a month ago, we need to check the category name to see if it exists

if ((DateTime.Now - dtmTimestamp).TotalDays > 30)

{

CreateCatIfNeeded(ref site, pgUserspaceTest,

String.Format(strCategoryFormatString, dtmTimestamp),

String.Format(StarterTemplate, dtmTimestamp));

}

return true;

}

else

{

LogToEventLog(ref site, MessageType.Error, "Error: though :" + pg.title + " is categorized as having an undated {{tl|" + strTagName + "}} tag, the tag could not be located.", null);

}

}

catch (Exception ex)

{

LogToEventLog(ref site, MessageType.Error, "Error dating " + strTagName + " tag for page :" + pg.title + ".", ex);

}

return false;

}

///

/// This function will perform the task

///

public void PerformTask()

{

// OTRS pending categories

const String csOtrsPendingUnknownDateCategoryName = "Category:Items pending OTRS confirmation of permission as of unknown date";

const String csDatedOtrsPendingCategoryFormatString = "Category:Items pending OTRS confirmation of permission as of {0:MMMM yyyy}";

String strDatedOtrsPendingCategoryThisMonth = String.Format(csDatedOtrsPendingCategoryFormatString, DateTime.Now);

String strDatedOtrsPendingCategoryNextMonth = String.Format(csDatedOtrsPendingCategoryFormatString, DateTime.Now.AddMonths(1));

const String csDatedOtrsPendingCategoryStarterString = "{{{{subst:OTRS pending subcat starter|date={0:yyyy-MM-dd}}}}}";

String strDatedOtrsPendingCategoryStarterThisMonth = String.Format(csDatedOtrsPendingCategoryStarterString, DateTime.Parse(DateTime.Now.AddMonths(1).ToString("MM-01-yyyy")).AddDays(-1));

String strDatedOtrsPendingCategoryStarterNextMonth = String.Format(csDatedOtrsPendingCategoryStarterString, DateTime.Parse(DateTime.Now.AddMonths(2).ToString("MM-01-yyyy")).AddDays(-1));

// OTRS received categories (files)

const String csOtrsReceivedFilesUnknownDateCategoryName = "Category:Wikipedia files with unconfirmed permission received by OTRS as of unknown date";

const String csDatedOtrsReceivedFilesCategoryFormatString = "Category:Wikipedia files with unconfirmed permission received by OTRS as of {0:MMMM yyyy}";

String strDatedOtrsReceivedFilesCategoryThisMonth = String.Format(csDatedOtrsReceivedFilesCategoryFormatString, DateTime.Now);

String strDatedOtrsReceivedFilesCategoryNextMonth = String.Format(csDatedOtrsReceivedFilesCategoryFormatString, DateTime.Now.AddMonths(1));

const String csDatedOtrsReceivedFilesCategoryStarterString = "{{{{subst:OTRS received subcat starter|date={0:yyyy-MM-dd}|type=files}}}}";

String strDatedOtrsReceivedFilesCategoryStarterThisMonth = String.Format(csDatedOtrsReceivedFilesCategoryStarterString, DateTime.Parse(DateTime.Now.AddMonths(1).ToString("MM-01-yyyy")).AddDays(-1));

String strDatedOtrsReceivedFilesCategoryStarterNextMonth = String.Format(csDatedOtrsReceivedFilesCategoryStarterString, DateTime.Parse(DateTime.Now.AddMonths(2).ToString("MM-01-yyyy")).AddDays(-1));

// OTRS received categories (pages)

const String csOtrsReceivedPagesUnknownDateCategoryName = "Category:Wikipedia pages with unconfirmed permission received by OTRS as of unknown date";

const String csDatedOtrsReceivedPagesCategoryFormatString = "Category:Wikipedia pages with unconfirmed permission received by OTRS as of {0:MMMM yyyy}";

String strDatedOtrsReceivedPagesCategoryThisMonth = String.Format(csDatedOtrsReceivedPagesCategoryFormatString, DateTime.Now);

String strDatedOtrsReceivedPagesCategoryNextMonth = String.Format(csDatedOtrsReceivedPagesCategoryFormatString, DateTime.Now.AddMonths(1));

const String csDatedOtrsReceivedPagesCategoryStarterString = "{{{{subst:OTRS received subcat starter|date={0:yyyy-MM-dd}|type=pages}}}}";

String strDatedOtrsReceivedPagesCategoryStarterThisMonth = String.Format(csDatedOtrsReceivedPagesCategoryStarterString, DateTime.Parse(DateTime.Now.AddMonths(1).ToString("MM-01-yyyy")).AddDays(-1));

String strDatedOtrsReceivedPagesCategoryStarterNextMonth = String.Format(csDatedOtrsReceivedPagesCategoryStarterString, DateTime.Parse(DateTime.Now.AddMonths(2).ToString("MM-01-yyyy")).AddDays(-1));

// Connect to Wikipedia

Site site = TryToConnect("https://en.wikipedia.org", Properties.Settings.Default.BotUserName, Properties.Settings.Default.BotPassword);

// Use a separate connection for our API calls - this seems to time out less frequently

Site site2 = TryToConnect("https://en.wikipedia.org", Properties.Settings.Default.BotUserName, Properties.Settings.Default.BotPassword);

// Grab the list of pages in the category

PageList pl = new PageList(site);

pl.FillAllFromCategory(csOtrsPendingUnknownDateCategoryName);

SleepApiDelay();

if (UserspaceTest)

{

LogToEventLog(ref site, MessageType.Start, "B-Bot \"OTRS Dated Filer\" process now commencing IN TEST MODE. This process checks pages from [[:"

+ csOtrsPendingUnknownDateCategoryName + "]] to add the date stamp where it is missing.", null);

}

else

{

LogToEventLog(ref site, MessageType.Start, "B-Bot \"OTRS Dated Filer\" process now commencing. This process checks pages from [[:"

+ csOtrsPendingUnknownDateCategoryName + "]] to add the date stamp where it is missing.", null);

}

int intPagesTagged = 0;

Page pgUserspaceTest = new Page(site, Properties.Settings.Default.UserspaceTestPage);

// Add the userspace test header

if (UserspaceTest)

{

pgUserspaceTest.text = "Now beginning OTRS Dated Filer task on " + DateTime.Now.ToString() + " (local time) ...\r\n\r\n";

pgUserspaceTest.text += "

class=\"wikitable sortable\"\r\n
\r\n! Page !! Timestamp !! Former text !! Proposed text\r\n";

pgUserspaceTest.Save();

}

SleepApiDelay();

// Make sure that this month's and next month's dated categories exist

CreateCatIfNeeded(ref site, pgUserspaceTest, strDatedOtrsPendingCategoryThisMonth, strDatedOtrsPendingCategoryStarterThisMonth);

SleepApiDelay();

CreateCatIfNeeded(ref site, pgUserspaceTest, strDatedOtrsPendingCategoryNextMonth, strDatedOtrsPendingCategoryStarterNextMonth);

SleepApiDelay();

// Loop through each page

foreach (Page pgCurrentImagePage in pl)

{

// Ignore things that are not in a valid namespace

if (pgCurrentImagePage.GetNamespace() != 6 && // file

pgCurrentImagePage.GetNamespace() != 119 && // draft talk

pgCurrentImagePage.GetNamespace() != 118 && // draft

pgCurrentImagePage.GetNamespace() != 3 && // user talk

pgCurrentImagePage.GetNamespace() != 5) // WP: talk

{

continue;

}

// Find the OTRS pending tag

DateTag(site, pgCurrentImagePage, @"\{\{\s*(template\:|)otrs(\s

)pending([^\{^\}]*|)\}\}", "OTRS pending", pgUserspaceTest, csDatedOtrsPendingCategoryFormatString, csDatedOtrsPendingCategoryStarterString);

SleepApiDelay();

if (BotStop(site))

{

LogToEventLog(ref site, MessageType.Error, "I was ordered to abort.", null);

return;

}

intPagesTagged++;

SleepApiDelay();

if (intPagesTagged >= MaximumImagesToProcess)

{

break;

}

}

LogToEventLog(ref site2, MessageType.Informational, "B-Bot finished adding OTRS pending dates. " + intPagesTagged.ToString() + " pages were edited. Will now check category :" + csOtrsReceivedFilesUnknownDateCategoryName + "", null);

// Now, do OTRS received (files)

// Grab the list of pages in the category

pl = new PageList(site);

pl.FillAllFromCategory(csOtrsReceivedFilesUnknownDateCategoryName);

SleepApiDelay();

intPagesTagged = 0;

SleepApiDelay();

// Make sure that this month's and next month's dated categories exist

CreateCatIfNeeded(ref site, pgUserspaceTest, strDatedOtrsReceivedFilesCategoryThisMonth, strDatedOtrsReceivedFilesCategoryStarterThisMonth);

SleepApiDelay();

CreateCatIfNeeded(ref site, pgUserspaceTest, strDatedOtrsReceivedFilesCategoryNextMonth, strDatedOtrsReceivedFilesCategoryStarterNextMonth);

SleepApiDelay();

// Loop through each page

foreach (Page pgCurrentImagePage in pl)

{

// Find the OTRS pending tag

DateTag(site, pgCurrentImagePage, @"\{\{\s*(template\:|)otrs(\s

)(received|insufficient)([^\{^\}]*|)\}\}", "OTRS received", pgUserspaceTest, csDatedOtrsReceivedFilesCategoryFormatString, csDatedOtrsReceivedFilesCategoryStarterString);

SleepApiDelay();

if (BotStop(site))

{

LogToEventLog(ref site, MessageType.Error, "I was ordered to abort.", null);

return;

}

intPagesTagged++;

SleepApiDelay();

if (intPagesTagged >= MaximumImagesToProcess)

{

break;

}

}

LogToEventLog(ref site2, MessageType.Informational, "B-Bot finished adding OTRS received dates to files. " + intPagesTagged.ToString() + " files were edited. Will now check category :" + csOtrsReceivedPagesUnknownDateCategoryName + "", null);

intPagesTagged = 0;

// Now OTRS received pages

// Grab the list of pages in the category

pl = new PageList(site);

pl.FillAllFromCategory(csOtrsReceivedPagesUnknownDateCategoryName);

SleepApiDelay();

// Make sure that this month's and next month's dated categories exist

CreateCatIfNeeded(ref site, pgUserspaceTest, strDatedOtrsReceivedPagesCategoryThisMonth, strDatedOtrsReceivedPagesCategoryStarterThisMonth);

SleepApiDelay();

CreateCatIfNeeded(ref site, pgUserspaceTest, strDatedOtrsReceivedPagesCategoryNextMonth, strDatedOtrsReceivedPagesCategoryStarterNextMonth);

SleepApiDelay();

// Loop through each page

foreach (Page pgCurrentImagePage in pl)

{

// Find the OTRS pending tag

DateTag(site, pgCurrentImagePage, @"\{\{\s*(template\:|)otrs(\s

)(received|insufficient)([^\{^\}]*|)\}\}", "OTRS received", pgUserspaceTest, csDatedOtrsReceivedPagesCategoryFormatString, csDatedOtrsReceivedPagesCategoryStarterString);

SleepApiDelay();

if (BotStop(site))

{

LogToEventLog(ref site, MessageType.Error, "I was ordered to abort.", null);

return;

}

intPagesTagged++;

SleepApiDelay();

if (intPagesTagged >= MaximumImagesToProcess)

{

break;

}

}

LogToEventLog(ref site2, MessageType.Informational, "B-Bot finished adding OTRS received dates to pages. " + intPagesTagged.ToString() + " pages were edited.", null);

LogToEventLog(ref site2, MessageType.Finish, "B-Bot OTRS Dated Filer process completed.", null);

if (UserspaceTest)

{

pgUserspaceTest.text += "

\r\n";

pgUserspaceTest.Save();

}

}