-
Notifications
You must be signed in to change notification settings - Fork 0
/
read.py
117 lines (97 loc) · 4.46 KB
/
read.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
"""Reads my notifications and writes new reminders to the database."""
import datetime
import json
import mwparserfromhell
import pytimeparse
import pytz
import pywikibot
import re
import sys
BOT_NAME = "RemindMeBot"
SIGNATURE_TIMESTAMP_FORMAT = "%H:%M, %-d %B %Y"
INITIAL_INDENTATION = re.compile("^[*: ]+")
BEFORE_PING = re.compile(r".+ ([[(User:)?{0}(|.*)?]]|\{{\{{\w+\|{0}\}}\}})".format(BOT_NAME))
SIGNATURE_REGEX = r"\[\[User.*?:{}.+\(UTC\)"
LEAD_TRAIL_PUNCT = re.compile(r"^[^\w\d]*(.+?)[^\w\d]*$")
TIME_RESOLUTION = datetime.timedelta(minutes=30)
REMINDERS_FILE = "reminders.json"
def parse_duration(input_string):
"""Wrapper around pytimeparse to parse a time duration and return a
regular timedelta"""
return datetime.timedelta(seconds=pytimeparse.parse(input_string))
def parse_line(line, username):
"""
Parses a line with a comment (given the username of the user who made it)
and returns a time duration and a note.
"""
line = INITIAL_INDENTATION.sub("", line)
# Remove everything before and including the ping
line = BEFORE_PING.sub("", line)
# Remove the signature and everything after it
line = re.sub(SIGNATURE_REGEX.format(username), "", line)
# Remove leading and trailing punctuation
line = LEAD_TRAIL_PUNCT.sub(r"\1", line)
time_duration, _, note = line.partition(",")
return (time_duration, note.strip())
class SectionIdentifier:
"""Identifies which section a line came from."""
def __init__(self, page_content):
wikicode = mwparserfromhell.parse(page_content)
self.sections = []
for each_section in wikicode.get_sections()[1:]:
first_heading = each_section.filter_headings()[0]
title = first_heading.title.strip()
each_section.remove(first_heading)
text = unicode(each_section).strip()
self.sections.append((title, text))
def lookup(self, text):
try:
return next(x[0] for x in self.sections if text in x[1])
except StopIteration:
return None
def save_reminders(new_reminders):
current_reminders = []
with open(REMINDERS_FILE, "r") as reminders_file_read:
current_reminders = json.load(reminders_file_read)
with open(REMINDERS_FILE, "w") as reminders_file_write:
json.dump(current_reminders + new_reminders, reminders_file_write)
print("Dumped reminders to {}.".format(REMINDERS_FILE))
def main():
print("Starting {}-read at {}".format(BOT_NAME,
datetime.datetime.utcnow().isoformat()))
site = pywikibot.Site("en", "wikipedia")
site.login()
current_user = site.user()
if current_user != BOT_NAME:
print("Error! Logged in as {} instead of {}.".format(current_user, BOT_NAME))
sys.exit(1)
else:
print("Logged in as {}.".format(current_user))
# Read through my notifications and get a list of new reminders to send
new_reminders = []
for notification in site.notifications():
if notification.type != "mention": continue
username = notification.agent.username
page_content = notification.page.getOldVersion(notification.revid)
section_identifier = SectionIdentifier(page_content)
line_parts = [current_user, username,
notification.timestamp.strftime(SIGNATURE_TIMESTAMP_FORMAT)]
has_line_parts = lambda line: all(x in line for x in line_parts)
for each_line in filter(has_line_parts, page_content.splitlines()):
time_duration, note = parse_line(each_line, username)
time_duration = parse_duration(time_duration)
reminder_time = notification.timestamp + time_duration
reminder_time = TIME_RESOLUTION + reminder_time
reminder_time = reminder_time.replace(second=0, minute=0)
# We can't send reminders in the past
if reminder_time < datetime.datetime.utcnow(): continue
location = u"%s#%s" % (notification.page.title(withNamespace=True),
section_identifier.lookup(each_line))
# Strip timezone information from notification timestamp
notification_timestamp = datetime.timedelta(minutes=0) + notification.timestamp
reminder = (username, location, notification_timestamp.isoformat(),
reminder_time.isoformat(), note)
new_reminders.append(reminder)
save_reminders(new_reminders)
if __name__ == "__main__":
main()