|
@@ -46,6 +46,16 @@ class DRNClerkBot(Task): |
|
|
STATUS_CLOSED = 7 |
|
|
STATUS_CLOSED = 7 |
|
|
STATUS_ARCHIVE = 8 |
|
|
STATUS_ARCHIVE = 8 |
|
|
|
|
|
|
|
|
|
|
|
ALIASES = { |
|
|
|
|
|
STATUS_NEW: ("",), |
|
|
|
|
|
STATUS_OPEN: ("open", "active", "inprogress"), |
|
|
|
|
|
STATUS_STALE: ("stale",), |
|
|
|
|
|
STATUS_NEEDASSIST: ("needassist", "relist", "relisted"), |
|
|
|
|
|
STATUS_REVIEW: ("review",), |
|
|
|
|
|
STATUS_RESOLVED: ("resolved", "resolve"), |
|
|
|
|
|
STATUS_CLOSED: ("closed", "close"), |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
def setup(self): |
|
|
def setup(self): |
|
|
"""Hook called immediately after the task is loaded.""" |
|
|
"""Hook called immediately after the task is loaded.""" |
|
|
cfg = self.config.tasks.get(self.name, {}) |
|
|
cfg = self.config.tasks.get(self.name, {}) |
|
@@ -167,7 +177,8 @@ class DRNClerkBot(Task): |
|
|
re_id2 += "(.*?)\}\})(<!-- Bot Case ID \(please don't modify\): .*? -->)?" |
|
|
re_id2 += "(.*?)\}\})(<!-- Bot Case ID \(please don't modify\): .*? -->)?" |
|
|
repl = ur"\1 <!-- Bot Case ID (please don't modify): {0} -->" |
|
|
repl = ur"\1 <!-- Bot Case ID (please don't modify): {0} -->" |
|
|
body = re.sub(re_id2, repl.format(id_), body) |
|
|
body = re.sub(re_id2, repl.format(id_), body) |
|
|
case = _Case(id_, title, status, time()) |
|
|
|
|
|
|
|
|
case = _Case(id_, title, status, self.STATUS_UNKNOWN, time(), |
|
|
|
|
|
time(), False, False) |
|
|
cases.append(case) |
|
|
cases.append(case) |
|
|
else: |
|
|
else: |
|
|
case.status = status |
|
|
case.status = status |
|
@@ -188,20 +199,11 @@ class DRNClerkBot(Task): |
|
|
|
|
|
|
|
|
def read_status(self, body): |
|
|
def read_status(self, body): |
|
|
"""Parse the current status from a case body.""" |
|
|
"""Parse the current status from a case body.""" |
|
|
aliases = { |
|
|
|
|
|
self.STATUS_NEW: ("",), |
|
|
|
|
|
self.STATUS_OPEN: ("open", "active", "inprogress"), |
|
|
|
|
|
self.STATUS_STALE: ("stale",), |
|
|
|
|
|
self.STATUS_NEEDASSIST: ("needassist", "relist", "relisted"), |
|
|
|
|
|
self.STATUS_REVIEW: ("review",), |
|
|
|
|
|
self.STATUS_RESOLVED: ("resolved", "resolve"), |
|
|
|
|
|
self.STATUS_CLOSED: ("closed", "close"), |
|
|
|
|
|
} |
|
|
|
|
|
templ = re.escape(self.tl_status) |
|
|
templ = re.escape(self.tl_status) |
|
|
status = re.search("\{\{" + templ + "\|?(.*?)\}\}", body, re.S|re.U) |
|
|
status = re.search("\{\{" + templ + "\|?(.*?)\}\}", body, re.S|re.U) |
|
|
if not status: |
|
|
if not status: |
|
|
return self.STATUS_UNKNOWN |
|
|
return self.STATUS_UNKNOWN |
|
|
for option, names in aliases.iteritems(): |
|
|
|
|
|
|
|
|
for option, names in self.ALIASES.iteritems(): |
|
|
if status.group(1).lower() in names: |
|
|
if status.group(1).lower() in names: |
|
|
return option |
|
|
return option |
|
|
return self.STATUS_UNKNOWN |
|
|
return self.STATUS_UNKNOWN |
|
@@ -226,35 +228,30 @@ class DRNClerkBot(Task): |
|
|
def clerk_case(self, conn, case, volunteers): |
|
|
def clerk_case(self, conn, case, volunteers): |
|
|
"""Clerk a particular case and return a list of any notices to send.""" |
|
|
"""Clerk a particular case and return a list of any notices to send.""" |
|
|
notices = [] |
|
|
notices = [] |
|
|
|
|
|
signatures = self.read_signatures(case.body) |
|
|
if case.status == self.STATUS_NEW: |
|
|
if case.status == self.STATUS_NEW: |
|
|
notices = self.clerk_new_case(case, volunteers) |
|
|
|
|
|
|
|
|
notices = self.clerk_new_case(case, volunteers, signatures) |
|
|
elif case.status == self.STATUS_OPEN: |
|
|
elif case.status == self.STATUS_OPEN: |
|
|
notices = self.clerk_open_case(case) |
|
|
notices = self.clerk_open_case(case) |
|
|
elif case.status == self.STATUS_NEEDASSIST: |
|
|
elif case.status == self.STATUS_NEEDASSIST: |
|
|
notices = self.clerk_needassist_case(case, volunteers) |
|
|
|
|
|
|
|
|
notices = self.clerk_needassist_case(case, volunteers, signatures) |
|
|
elif case.status == self.STATUS_STALE: |
|
|
elif case.status == self.STATUS_STALE: |
|
|
notices = self.clerk_stale_case(case) |
|
|
|
|
|
|
|
|
notices = self.clerk_stale_case(case, signatures) |
|
|
elif case.status == self.STATUS_REVIEW: |
|
|
elif case.status == self.STATUS_REVIEW: |
|
|
notices = self.clerk_review_case(case) |
|
|
notices = self.clerk_review_case(case) |
|
|
elif case.status in [self.STATUS_RESOLVED, self.STATUS_CLOSED]: |
|
|
elif case.status in [self.STATUS_RESOLVED, self.STATUS_CLOSED]: |
|
|
self.clerk_closed_case(conn) |
|
|
self.clerk_closed_case(conn) |
|
|
else: |
|
|
else: |
|
|
LOG NOT SURE HOW TO DEAL WITH CASE |
|
|
|
|
|
|
|
|
log = u"Unsure of how to deal with case {0} (title: {1})" |
|
|
|
|
|
self.logger.error(log.format(case.id, case.title)) |
|
|
return notices |
|
|
return notices |
|
|
|
|
|
|
|
|
# STORE UPDATES IN DATABASE |
|
|
|
|
|
# APPLY STATUS UPDATES TO CASE BODY |
|
|
|
|
|
|
|
|
STORE UPDATES IN DATABASE |
|
|
|
|
|
APPLY STATUS UPDATES TO CASE BODY |
|
|
return notices |
|
|
return notices |
|
|
|
|
|
|
|
|
def check_for_review(self, case): |
|
|
|
|
|
if time() - case.file_time > 60 * 60 * 24 * 4: |
|
|
|
|
|
if case.last_action != self.STATUS_REVIEW: |
|
|
|
|
|
case.status = self.STATUS_REVIEW |
|
|
|
|
|
return SEND_MESSAGE_TO_WT:DRN |
|
|
|
|
|
|
|
|
|
|
|
def clerk_new_case(self, case, volunteers): |
|
|
|
|
|
|
|
|
def clerk_new_case(self, case, volunteers, signatures): |
|
|
notices = self.notify_parties(case) |
|
|
notices = self.notify_parties(case) |
|
|
signatures = self.read_signatures(case.body) |
|
|
|
|
|
if any([editor in volunteers for (editor, time) in signatures]): |
|
|
if any([editor in volunteers for (editor, time) in signatures]): |
|
|
if case.last_action != self.STATUS_OPEN: |
|
|
if case.last_action != self.STATUS_OPEN: |
|
|
case.status = self.STATUS_OPEN |
|
|
case.status = self.STATUS_OPEN |
|
@@ -268,32 +265,30 @@ class DRNClerkBot(Task): |
|
|
if len(case.body) - SIZE_WHEN_LAST_VOLUNTEER_EDIT > 15000: |
|
|
if len(case.body) - SIZE_WHEN_LAST_VOLUNTEER_EDIT > 15000: |
|
|
if case.last_action != self.STATUS_NEEDASSIST: |
|
|
if case.last_action != self.STATUS_NEEDASSIST: |
|
|
case.status = self.STATUS_NEEDASSIST |
|
|
case.status = self.STATUS_NEEDASSIST |
|
|
return SEND_MESSAGE_TO_WT:DRN |
|
|
|
|
|
|
|
|
return self.build_talk_notice(self.STATUS_NEEDASSIST) |
|
|
|
|
|
|
|
|
if time() - LAST_EDIT > 60 * 60 * 24 * 2: |
|
|
|
|
|
|
|
|
if time() - case.modify_time > 60 * 60 * 24 * 2: |
|
|
if case.last_action != self.STATUS_STALE: |
|
|
if case.last_action != self.STATUS_STALE: |
|
|
case.status = self.STATUS_STALE |
|
|
case.status = self.STATUS_STALE |
|
|
return SEND_MESSAGE_TO_WT:DRN |
|
|
|
|
|
|
|
|
return self.build_talk_notice(self.STATUS_STALE) |
|
|
return [] |
|
|
return [] |
|
|
|
|
|
|
|
|
def clerk_needassist_case(self, case, volunteers): |
|
|
|
|
|
|
|
|
def clerk_needassist_case(self, case, volunteers, signatures): |
|
|
flagged = self.check_for_review(case): |
|
|
flagged = self.check_for_review(case): |
|
|
if flagged: |
|
|
if flagged: |
|
|
return flagged |
|
|
return flagged |
|
|
|
|
|
|
|
|
signatures = self.read_signatures(case.body) |
|
|
|
|
|
newsigs = signatures - SIGNATURES_FROM_DATABASE |
|
|
newsigs = signatures - SIGNATURES_FROM_DATABASE |
|
|
if any([editor in volunteers for (editor, time) in newsigs]): |
|
|
if any([editor in volunteers for (editor, time) in newsigs]): |
|
|
if case.last_action != self.STATUS_OPEN: |
|
|
if case.last_action != self.STATUS_OPEN: |
|
|
case.status = self.STATUS_OPEN |
|
|
case.status = self.STATUS_OPEN |
|
|
return [] |
|
|
return [] |
|
|
|
|
|
|
|
|
def clerk_stale_case(self, case): |
|
|
|
|
|
|
|
|
def clerk_stale_case(self, case, signatures): |
|
|
flagged = self.check_for_review(case): |
|
|
flagged = self.check_for_review(case): |
|
|
if flagged: |
|
|
if flagged: |
|
|
return flagged |
|
|
return flagged |
|
|
|
|
|
|
|
|
signatures = self.read_signatures(case.body) |
|
|
|
|
|
if signatures - SIGNATURES_FROM_DATABASE: |
|
|
if signatures - SIGNATURES_FROM_DATABASE: |
|
|
if case.last_action != self.STATUS_OPEN: |
|
|
if case.last_action != self.STATUS_OPEN: |
|
|
case.status = self.STATUS_OPEN |
|
|
case.status = self.STATUS_OPEN |
|
@@ -306,18 +301,29 @@ class DRNClerkBot(Task): |
|
|
return [] |
|
|
return [] |
|
|
|
|
|
|
|
|
def clerk_closed_case(self, case): |
|
|
def clerk_closed_case(self, case): |
|
|
if time() - TIME_STATUS_SET AND LAST_EDIT > 60 * 60 * 24: |
|
|
|
|
|
|
|
|
if time() - TIME_STATUS_SET > 60 * 60 * 24 and time() - case.modify_time > 60 * 60 * 24: |
|
|
case.status = self.STATUS_ARCHIVE |
|
|
case.status = self.STATUS_ARCHIVE |
|
|
ADD_ARCHIVE_TEMPLATE |
|
|
ADD_ARCHIVE_TEMPLATE |
|
|
REMOVE_NOARCHIVE |
|
|
REMOVE_NOARCHIVE |
|
|
|
|
|
|
|
|
|
|
|
def check_for_review(self, case): |
|
|
|
|
|
if time() - case.file_time > 60 * 60 * 24 * 4: |
|
|
|
|
|
if case.last_action != self.STATUS_REVIEW: |
|
|
|
|
|
case.status = self.STATUS_REVIEW |
|
|
|
|
|
return self.build_talk_notice(self.STATUS_REVIEW) |
|
|
|
|
|
|
|
|
def read_signatures(self, text): |
|
|
def read_signatures(self, text): |
|
|
raise NotImplementedError() |
|
|
|
|
|
|
|
|
raise NotImplementedError() # TODO |
|
|
|
|
|
|
|
|
|
|
|
def build_talk_notice(self, status): |
|
|
|
|
|
param = self.ALIASES[status][0] |
|
|
|
|
|
template = "{{subst:" + self.tl_notify_stale + "|" + param + "}} ~~~~" |
|
|
|
|
|
return _Notice(self.talk, template) |
|
|
|
|
|
|
|
|
def notify_parties(self, case): |
|
|
def notify_parties(self, case): |
|
|
if case.parties_notified: |
|
|
if case.parties_notified: |
|
|
return |
|
|
return |
|
|
raise NotImplementedError() |
|
|
|
|
|
|
|
|
raise NotImplementedError() # TODO |
|
|
case.parties_notified = True |
|
|
case.parties_notified = True |
|
|
|
|
|
|
|
|
def save(self, page, cases, kwargs): |
|
|
def save(self, page, cases, kwargs): |
|
@@ -358,7 +364,7 @@ class DRNClerkBot(Task): |
|
|
text = page.get() |
|
|
text = page.get() |
|
|
except exceptions.PageNotFoundError: |
|
|
except exceptions.PageNotFoundError: |
|
|
text = "" |
|
|
text = "" |
|
|
if notice.too_late in text: |
|
|
|
|
|
|
|
|
if notice.too_late and notice.too_late in text: |
|
|
log = u"Skipping [[{0}]]; was already notified".format(target) |
|
|
log = u"Skipping [[{0}]]; was already notified".format(target) |
|
|
self.logger.info(log) |
|
|
self.logger.info(log) |
|
|
text += ("\n" if text else "") + template |
|
|
text += ("\n" if text else "") + template |
|
@@ -374,13 +380,14 @@ class DRNClerkBot(Task): |
|
|
|
|
|
|
|
|
class _Case(object): |
|
|
class _Case(object): |
|
|
"""A object representing a dispute resolution case.""" |
|
|
"""A object representing a dispute resolution case.""" |
|
|
def __init__(self, id_, title, status, last_action, file_time, |
|
|
|
|
|
|
|
|
def __init__(self, id_, title, status, last_action, file_time, modify_time, |
|
|
parties_notified, very_old_notified): |
|
|
parties_notified, very_old_notified): |
|
|
self.id = id_ |
|
|
self.id = id_ |
|
|
self.title = title |
|
|
self.title = title |
|
|
self.status = status |
|
|
self.status = status |
|
|
self.last_action = last_action |
|
|
self.last_action = last_action |
|
|
self.file_time = file_time |
|
|
self.file_time = file_time |
|
|
|
|
|
self.modify_time = modify_time |
|
|
self.parties_notified = parties_notified |
|
|
self.parties_notified = parties_notified |
|
|
self.very_old_notified = very_old_notified |
|
|
self.very_old_notified = very_old_notified |
|
|
|
|
|
|
|
@@ -391,7 +398,7 @@ class _Case(object): |
|
|
|
|
|
|
|
|
class _Notice(object): |
|
|
class _Notice(object): |
|
|
"""An object representing a notice to be sent to a user or a page.""" |
|
|
"""An object representing a notice to be sent to a user or a page.""" |
|
|
def __init__(self, target, template, too_late): |
|
|
|
|
|
|
|
|
def __init__(self, target, template, too_late=None): |
|
|
self.target = target |
|
|
self.target = target |
|
|
self.template = template |
|
|
self.template = template |
|
|
self.too_late = too_late |
|
|
self.too_late = too_late |