Преглед на файлове

Implementing more code for dealing with the volunteer list.

tags/v0.1^2
Ben Kurtovic преди 12 години
родител
ревизия
d2b82b60d9
променени са 2 файла, в които са добавени 113 реда и са изтрити 61 реда
  1. +103
    -61
      earwigbot/tasks/drn_clerkbot.py
  2. +10
    -0
      earwigbot/tasks/schema/drn_clerkbot.sql

+ 103
- 61
earwigbot/tasks/drn_clerkbot.py Целия файл

@@ -53,6 +53,7 @@ class DRNClerkBot(Task):
# Set some wiki-related attributes:
self.title = cfg.get("title", "Wikipedia:Dispute resolution noticeboard")
self.talk = cfg.get("talk", "Wikipedia talk:Dispute resolution noticeboard")
self.volunteer_title = cfg.get("volunteers", "Wikipedia:Dispute resolution noticeboard/Volunteering")
default_summary = "Updating $3 cases for the [[WP:DRN|dispute resolution noticeboard]]."
self.summary = self.make_summary(cfg.get("summary", default_summary))

@@ -76,70 +77,47 @@ class DRNClerkBot(Task):
if not self.db_access_lock.acquire(False): # Non-blocking
self.logger.info("A job is already ongoing; aborting")
return

with self.db_access_lock:
self.logger.info(u"Starting update to [[{0}]]".format(self.title))
action = kwargs.get("action", "all")
try:
start = time()
conn = oursql.connect(**self.conn_data)
cases = self.read_database(conn)
site = self.bot.wiki.get_site()
page = site.get_page(self.title)
text = page.get()
self.read_page(conn, cases, text)
noticies = self.clerk(cases)
self.save(page, cases)
self.send_notices(site, notices)

def save(self, page, cases):
"""Save any changes to the noticeboard."""
newtext = text = page.get()
counter = 0
for case in cases:
if case.old != case.body:
newtext = newtext.replace(case.old, case.body)
counter += 1
if newtext == text:
self.logger.info(u"Nothing to edit on [[{0}]]".format(page.title))
return

worktime = time() - start
if worktime < 60:
sleep(60 - worktime)
page.reload()
if page.get() != text:
log = "Someone has edited the page while we were working; restarting"
self.logger.warn(log)
return self.run()
summary = self.summary.replace("$3", str(counter))
page.edit(text, summary, minor=True, bot=True)
self.logger.info(u"Saved page [[{0}]]".format(page.title))

def send_notices(self, site, notices):
"""Send out any templated notices to users or pages."""
if not notices:
self.logger.info("No notices to send; finishing")
return
for notice in notices:
target, template = notice.target, notice.template
log = u"Notifying [[{0}]] with {1}".format(target, template)
self.logger.info(log)
page = site.get_page(target)
try:
text = page.get()
except exceptions.PageNotFoundError:
text = ""
if notice.too_late in text:
log = u"Skipping [[{0}]]; was already notified".format(target)
if action in ["all", "update_volunteers"]:
self.update_volunteers(conn, site)
if action in ["all", "clerk"]:
log = u"Starting update to [[{0}]]".format(self.title)
self.logger.info(log)
text += ("\n" if text else "") + template
try:
page.edit(text, summary, minor=False, bot=True)
except exceptions.EditError as error:
name, msg = type(error).name, error.message
log = u"Couldn't leave notice on {0} because of {1}: {2}"
self.logger.error(log.format(page.title, name, msg))
cases = self.read_database(conn)
page = site.get_page(self.title)
text = page.get()
self.read_page(conn, cases, text)
noticies = self.clerk(conn, cases)
self.save(page, cases, kwargs)
self.send_notices(site, notices)
finally:
self.db_access_lock.release()

self.logger.info("Done sending notices")
def update_volunteers(self, conn, site):
"""Updates and stores the list of dispute resolution volunteers."""
log = u"Updating volunteer list from [[{0}]]"
self.logger.info(log.format(self.volunteer_title))
page = site.get_page(self.volunteer_title)
try:
text = page.get()
except exceptions.PageNotFoundError:
text = ""
marker = "<!-- please don't remove this comment (used by EarwigBot) -->"
if marker not in text:
log = u"The marker ({0}) wasn't found in the volunteer list at [[{1}]]!"
self.logger.error(log.format(marker, page.title))
text = text.split(marker)[1]
users = set()
for line in text.splitlines():
user = re.search("\# \{\{User\|(.*?)\}\}", line)
if user:
users.add(user.group(1))

# SYNCHRONIZE USERS WITH DATABASE

def read_database(self, conn):
"""Return a list of _Cases from the database."""
@@ -148,7 +126,8 @@ class DRNClerkBot(Task):
with conn.cursor() as cursor:
cursor.execute(query)
for id_, name, status in cursor:
cases.append(_Case(id_, title, status))
case = _Case(id_, title, status)
cases.append(case)
return cases

def read_page(self, conn, cases, text):
@@ -181,6 +160,7 @@ class DRNClerkBot(Task):
self.update_case_title(conn, id_, title)
case.title = title
case.body, case.old = body, old
case.apparent_status = status

def select_next_id(self, conn):
"""Return the next incremental ID for a case."""
@@ -218,11 +198,72 @@ class DRNClerkBot(Task):
with conn.cursor() as cursor:
cursor.execute(query, (title, id_))

def clerk(self):
def clerk(self, conn, cases):
"""Actually go through cases and modify those to be updated."""
query = "SELECT volunteer_username FROM volunteer"
with conn.cursor() as cursor:
cursor.execute(query)
volunteers = [name for (name,) in cursor.fetchall()]
notices = []
for case in cases:
notices += self.clerk_case(conn, case, volunteers)
return notices

def clerk_case(self, conn, case, volunteers):
"""Clerk a particular case and return a list of any notices to send."""
case # TODO

def save(self, page, cases, kwargs):
"""Save any changes to the noticeboard."""
newtext = text = page.get()
counter = 0
for case in cases:
if case.old != case.body:
newtext = newtext.replace(case.old, case.body)
counter += 1
if newtext == text:
self.logger.info(u"Nothing to edit on [[{0}]]".format(page.title))
return

worktime = time() - start
if worktime < 60:
sleep(60 - worktime)
page.reload()
if page.get() != text:
log = "Someone has edited the page while we were working; restarting"
self.logger.warn(log)
return self.run(**kwargs)
summary = self.summary.replace("$3", str(counter))
page.edit(text, summary, minor=True, bot=True)
self.logger.info(u"Saved page [[{0}]]".format(page.title))

def send_notices(self, site, notices):
"""Send out any templated notices to users or pages."""
if not notices:
self.logger.info("No notices to send; finishing")
return
for notice in notices:
target, template = notice.target, notice.template
log = u"Notifying [[{0}]] with {1}".format(target, template)
self.logger.info(log)
page = site.get_page(target)
try:
text = page.get()
except exceptions.PageNotFoundError:
text = ""
if notice.too_late in text:
log = u"Skipping [[{0}]]; was already notified".format(target)
self.logger.info(log)
text += ("\n" if text else "") + template
try:
page.edit(text, summary, minor=False, bot=True)
except exceptions.EditError as error:
name, msg = type(error).name, error.message
log = u"Couldn't leave notice on {0} because of {1}: {2}"
self.logger.error(log.format(page.title, name, msg))

self.logger.info("Done sending notices")


class _Case(object):
"""A object representing a dispute resolution case."""
@@ -233,6 +274,7 @@ class _Case(object):

self.body = None
self.old = None
self.apparent_status = None


class _Notice(object):


+ 10
- 0
earwigbot/tasks/schema/drn_clerkbot.sql Целия файл

@@ -20,4 +20,14 @@ CREATE TABLE `case` (
PRIMARY KEY (`case_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

--
-- Table structure for table `volunteer`
--

DROP TABLE IF EXISTS `volunteer`;
CREATE TABLE `volunteer` (
`volunteer_username` varchar(512) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`volunteer_username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

-- Dump completed on 2012-07-27 00:00:00

Зареждане…
Отказ
Запис