|
@@ -1,7 +1,10 @@ |
|
|
# -*- coding: utf-8 -*- |
|
|
# -*- coding: utf-8 -*- |
|
|
|
|
|
|
|
|
import re |
|
|
import re |
|
|
from os import path |
|
|
|
|
|
|
|
|
from os.path import expanduser |
|
|
|
|
|
from time import strftime, strptime |
|
|
|
|
|
|
|
|
|
|
|
import oursql |
|
|
|
|
|
|
|
|
from classes import BaseTask |
|
|
from classes import BaseTask |
|
|
import config |
|
|
import config |
|
@@ -10,22 +13,32 @@ import wiki |
|
|
class Task(BaseTask): |
|
|
class Task(BaseTask): |
|
|
"""A task to generate statistics for WikiProject Articles for Creation. |
|
|
"""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". |
|
|
In the live bot, this is "Template:AFC statistics". |
|
|
""" |
|
|
""" |
|
|
name = "afc_statistics" |
|
|
name = "afc_statistics" |
|
|
number = 2 |
|
|
number = 2 |
|
|
|
|
|
|
|
|
def __init__(self): |
|
|
def __init__(self): |
|
|
self.filename = path.join(config.root_dir, "statistics.txt") |
|
|
|
|
|
self.cfg = config.tasks.get(self.name, {}) |
|
|
self.cfg = config.tasks.get(self.name, {}) |
|
|
|
|
|
|
|
|
|
|
|
# Set some wiki-related attributes: |
|
|
self.pagename = cfg.get("page", "Template:AFC statistics") |
|
|
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): |
|
|
def run(self, **kwargs): |
|
|
self.site = wiki.get_site() |
|
|
self.site = wiki.get_site() |
|
@@ -50,13 +63,12 @@ class Task(BaseTask): |
|
|
method(page) |
|
|
method(page) |
|
|
|
|
|
|
|
|
def save(self): |
|
|
def save(self): |
|
|
|
|
|
self.check_integrity() |
|
|
|
|
|
|
|
|
if self.shutoff_enabled(): |
|
|
if self.shutoff_enabled(): |
|
|
return |
|
|
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) |
|
|
page = self.site.get_page(self.pagename) |
|
|
text = page.get() |
|
|
text = page.get() |
|
@@ -68,7 +80,57 @@ class Task(BaseTask): |
|
|
|
|
|
|
|
|
newtext = re.sub("(<!-- sig begin -->)(.*?)(<!-- sig end -->)", |
|
|
newtext = re.sub("(<!-- sig begin -->)(.*?)(<!-- sig end -->)", |
|
|
"\\1~~~ at ~~~~~\\3", newtext) |
|
|
"\\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): |
|
|
def process_edit(self, page): |
|
|
pass |
|
|
pass |
|
|