diff --git a/tasks/afc_statistics.py b/tasks/afc_statistics.py index 9bf33fa..9c75f94 100644 --- a/tasks/afc_statistics.py +++ b/tasks/afc_statistics.py @@ -20,6 +20,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +from collections import OrderedDict from datetime import datetime import re from os.path import expanduser @@ -33,13 +34,27 @@ from earwigbot import exceptions from earwigbot import wiki from earwigbot.tasks import Task +_DEFAULT_PAGE_TEXT = """ +{{NOINDEX}} + +Last updated by \ +{{#ifeq:{{REVISIONUSER:Template:AFC statistics}}|EarwigBot|\ +|{{User|{{REVISIONUSER:Template:AFC statistics}}}} at \ +{{#time:H:i, j F Y "(UTC)"|{{REVISIONTIMESTAMP:Template:AFC statistics}}}}}}\ + +{{Documentation}} +""" + class AFCStatistics(Task): """A task to generate statistics for WikiProject Articles for Creation. Statistics are stored in a MySQL database ("u_earwig_afc_statistics") accessed with oursql. Statistics are synchronied with the live database - every four minutes and saved once an hour, on the hour, to self.pagename. - In the live bot, this is "Template:AFC statistics". + every four minutes and saved once an hour, on the hour, to subpages of + self.pageroot. In the live bot, this is "Template:AFC statistics". """ name = "afc_statistics" number = 2 @@ -58,7 +73,7 @@ class AFCStatistics(Task): self.revision_cache = {} # Set some wiki-related attributes: - self.pagename = cfg.get("page", "Template:AFC statistics") + self.pageroot = cfg.get("page", "Template:AFC statistics") self.pending_cat = cfg.get("pending", "Pending AfC submissions") self.ignore_list = cfg.get("ignoreList", []) default_summary = "Updating statistics for [[WP:WPAFC|WikiProject Articles for creation]]." @@ -112,8 +127,8 @@ class AFCStatistics(Task): """Save our local statistics to the wiki. After checking for emergency shutoff, the statistics chart is compiled, - and then saved to self.pagename using self.summary iff it has changed - since last save. + and then saved to subpages of self.pageroot using self.summary iff it + has changed since last save. """ self.logger.info("Saving chart") if kwargs.get("fromIRC"): @@ -124,43 +139,50 @@ class AFCStatistics(Task): summary = self.summary statistics = self._compile_charts() + for name, chart in statistics.iteritems(): + self._save_page(name, chart) + + def _save_page(self, name, chart): + """Save a statistics chart to a single page.""" + page = self.site.get_page(u"{}/{}".format(self.pageroot, name)) + try: + text = page.get() + except exceptions.PageNotFoundError: + text = _DEFAULT_PAGE_TEXT - page = self.site.get_page(self.pagename) - text = page.get() newtext = re.sub(u"(.*?)", - "\n" + statistics + "\n", + "\n" + chart + "\n", text, flags=re.DOTALL) if newtext == text: - self.logger.info("Chart unchanged; not saving") - return # Don't edit the page if we're not adding anything + self.logger.info(u"Chart for {} unchanged; not saving".format(name)) + return newtext = re.sub("(.*?)", "~~~ at ~~~~~", newtext) page.edit(newtext, summary, minor=True, bot=True) - self.logger.info(u"Chart saved to [[{0}]]".format(page.title)) + self.logger.info(u"Chart for {} saved to [[{}]]".format(name, page.title)) def _compile_charts(self): """Compile and return all statistics information from our local db.""" - stats = "" - with self.conn.cursor() as cursor: + stats = OrderedDict() + with self.conn.cursor(oursql.DictCursor) as cursor: cursor.execute("SELECT * FROM chart") for chart in cursor: - stats += self._compile_chart(chart) + "\n" - return stats[:-1] # Drop the last newline + name = chart['chart_name'] + stats[name] = self._compile_chart(chart) + return stats def _compile_chart(self, chart_info): """Compile and return a single statistics chart.""" - chart_id, chart_title, special_title = chart_info - - chart = self.tl_header + "|" + chart_title - if special_title: - chart += "|" + special_title + chart = self.tl_header + "|" + chart_info['chart_title'] + if chart_info['chart_special_title']: + chart += "|" + chart_info['chart_special_title'] chart = "{{" + chart + "}}" query = "SELECT * FROM page JOIN row ON page_id = row_id WHERE row_chart = ?" with self.conn.cursor(oursql.DictCursor) as cursor: - cursor.execute(query, (chart_id,)) + cursor.execute(query, (chart_info['chart_id'],)) for page in cursor.fetchall(): chart += "\n" + self._compile_chart_row(page) diff --git a/tasks/schema/afc_statistics.sql b/tasks/schema/afc_statistics.sql index eaf0e95..8e3ba8b 100644 --- a/tasks/schema/afc_statistics.sql +++ b/tasks/schema/afc_statistics.sql @@ -15,6 +15,7 @@ CREATE DATABASE `u_earwig_afc_statistics` DROP TABLE IF EXISTS `chart`; CREATE TABLE `chart` ( `chart_id` tinyint(3) unsigned NOT NULL AUTO_INCREMENT, + `chart_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL, `chart_title` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, `chart_special_title` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, PRIMARY KEY (`chart_id`) @@ -26,11 +27,11 @@ CREATE TABLE `chart` ( LOCK TABLES `chart` WRITE; INSERT INTO `chart` VALUES -(1,'Pending submissions','Submitted'), -(3,'Being reviewed','Reviewer'), -(4,'Recently accepted','Accepted'), -(5,'Recently declined','Declined'), -(6,'Misplaced submissions','Created'); +(1,'pending','Pending submissions','Submitted'), +(3,'reviewing','Being reviewed','Reviewer'), +(4,'accepted','Recently accepted','Accepted'), +(5,'declined','Recently declined','Declined'), +(6,'created','Misplaced submissions','Created'); UNLOCK TABLES; --