From c6b3827f6b33f68fa1d3ae098c15f95c2791d01f Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Sat, 29 Oct 2011 23:36:54 -0400 Subject: [PATCH] Statistics chart generation from MySQL is ready! --- bot/tasks/afc_statistics.py | 92 +++++++++++++++++++++++++++++++++++++-------- bot/wiki/site.py | 3 +- 2 files changed, 79 insertions(+), 16 deletions(-) diff --git a/bot/tasks/afc_statistics.py b/bot/tasks/afc_statistics.py index ce84baf..a703e37 100644 --- a/bot/tasks/afc_statistics.py +++ b/bot/tasks/afc_statistics.py @@ -1,7 +1,10 @@ # -*- coding: utf-8 -*- import re -from os import path +from os.path import expanduser +from time import strftime, strptime + +import oursql from classes import BaseTask import config @@ -10,22 +13,32 @@ import wiki class Task(BaseTask): """A task to generate statistics for WikiProject Articles for Creation. - Statistics are stored in the file indicated by self.filename, - "statistics.txt" in the bot's root directory being the default. They are - updated live while watching the recent changes IRC feed. - - The bot saves its statistics once an hour, on the hour, to self.pagename. + Statistics are stored in a MySQL database ("u_earwig_afc_statistics") + accessed with oursql. Statistics are updated live while watching the recent + changes IRC feed and saved once an hour, on the hour, to self.pagename. In the live bot, this is "Template:AFC statistics". """ name = "afc_statistics" number = 2 def __init__(self): - self.filename = path.join(config.root_dir, "statistics.txt") self.cfg = config.tasks.get(self.name, {}) + + # Set some wiki-related attributes: self.pagename = cfg.get("page", "Template:AFC statistics") - default = "Updating statistics for [[WP:WPAFC|WikiProject Articles for creation]]." - self.summary = self.make_summary(cfg.get("summary", default)) + default_summary = "Updating statistics for [[WP:WPAFC|WikiProject Articles for creation]]." + self.summary = self.make_summary(cfg.get("summary", default_summary)) + + # Templates used in chart generation: + templates = cfg.get("templates", {}) + self.tl_header = templates.get("header", "AFC statistics/header") + self.tl_row = templates.get("row", "AFC statistics/row") + self.tl_footer = templates.get("footer", "AFC statistics/footer") + + # Establish a connection with our SQL database: + kwargs = cfg.get("sql", {}) + kwargs["read_default_file"] = expanduser("~/.my.cnf") + self.conn = oursql.connect(**kwargs) def run(self, **kwargs): self.site = wiki.get_site() @@ -50,13 +63,12 @@ class Task(BaseTask): method(page) def save(self): + self.check_integrity() + if self.shutoff_enabled(): return - try: - with open(self.filename) as fp: - statistics = fp.read() - except IOError: - pass + + statistics = self.compile_charts() page = self.site.get_page(self.pagename) text = page.get() @@ -68,7 +80,57 @@ class Task(BaseTask): newtext = re.sub("()(.*?)()", "\\1~~~ at ~~~~~\\3", newtext) - page.edit(newtext, self.summary, minor=True) + page.edit(newtext, self.summary, minor=True, bot=True) + + def compile_charts(self): + stats = "" + with self.conn.cursor() as cursor: + cursor.execute("SELECT * FROM chart") + charts = cursor.fetchall() + for chart_info in charts: + stats += self.compile_chart(chart_info) + "\n" + return stats[:-1] # Drop the last newline + + def compile_chart(self, chart_info): + chart_id, chart_title, special_title = chart_info + + if special_title: + chart = "{{{0}|{1}|{2}}}".format(self.tl_header, chart_title, special_title) + else: + chart = "{{{0}|{1}}}".format(self.tl_header, chart_title) + + 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) + for page in cursor: + chart += "\n" + self.compile_chart_row(page) + + chart += "\n{{{0}}}".format(self.tl_footer) + return chart + + def compile_chart_row(self, page): + row = "{{{0}|s={page_status}|t={page_title}|h={page_short}|z={page_size}|" + row += "cr={page_create_user}|cd={page_create_time}|ci={page_create_oldid}|" + row += "mr={page_modify_user}|md={page_modify_time}|mi={page_modify_oldid}|" + + page["page_create_time"] = format_timestamp(page["page_create_time"]) + page["page_modify_time"] = format_timestamp(page["page_modify_time"]) + + if page["page_special_user"]: + row += "sr={page_special_user}|sd={page_special_time}|si={page_special_oldid}|" + page["page_special_time"] = format_timestamp(page["page_special_time"]) + + if page["page_notes"]: + row += "n=1{page_notes}" + + row += "}}" + return row.format(self.tl_row, **page) + + def format_timestamp(self, ts): + return strftime("%H:%M, %d %B %Y", strptime(ts, "%Y-%m-%d %H:%M:%S")) + + def check_integrity(self): + pass def process_edit(self, page): pass diff --git a/bot/wiki/site.py b/bot/wiki/site.py index 032aaf3..55c5b73 100644 --- a/bot/wiki/site.py +++ b/bot/wiki/site.py @@ -3,6 +3,7 @@ from cookielib import CookieJar from gzip import GzipFile from json import loads +from os.path import expanduser from re import escape as re_escape, match as re_match from StringIO import StringIO from time import sleep @@ -446,7 +447,7 @@ class Site(object): args[key] = value if "read_default_file" not in args and "user" not in args and "passwd" not in args: - args["read_default_file"] = "~/.my.cnf" + args["read_default_file"] = expanduser("~/.my.cnf") self._sql_conn = oursql.connect(**args)