-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcfd.py
175 lines (160 loc) · 7.1 KB
/
cfd.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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# -*- coding: utf-8 -*-
"""
This script processes the Categories for discussion working page. It parses
out the actions that need to be taken as a result of CFD discussions (as posted
to the working page by an administrator) and performs them.
Syntax: python cfd.py
"""
#
# (C) Ben McIlwain, 2008
# (C) Pywikipedia bot team, 2009-2010
#
# Distributed under the terms of the MIT license.
import wikipedia as pywikibot
import re
import category
# The location of the CFD working page.
cfdPage = 'Wikipedia:Categories for discussion/Working'
# A list of templates that are used on category pages as part of the CFD
# process that contain information such as the link to the per-day discussion page.
cfdTemplates = ['Cfd full', 'Cfr full']
# Regular expression declarations
# See the en-wiki CFD working page at [[Wikipedia:Categories for discussion/Working]]
# to see how these work in context. To get this bot working on other wikis you will
# need to adjust these regular expressions at the very least.
nobots = re.compile(r"NO\s*BOTS", re.IGNORECASE);
example = re.compile(r"\[\[\:Category\:(.)\1\1\1\1\]\]", re.IGNORECASE);
speedymode = re.compile(r"^===*\s*Speedy Moves\s*===*\s*$", re.IGNORECASE);
movemode = re.compile(r"^===*\s*Move\/Merge then delete\s*===*\s*$", re.IGNORECASE);
emptymode = re.compile(r"^===*\s*Empty then delete\s*===*\s*$", re.IGNORECASE)
deletemode = re.compile(r"^===*\s*Ready for deletion\s*===*\s*$", re.IGNORECASE)
maintenance = re.compile(r"^===*\s*Old by month categories with entries\s*===*\s*$", re.IGNORECASE)
dateheader = re.compile(r"(\[\[Wikipedia\:Categories[_ ]for[_ ](?:discussion|deletion)\/Log\/([^\]]*?)\]\])", re.IGNORECASE)
movecat = re.compile(r"\[\[\:Category\:([^\]]*?)\]\][^\]]*?\[\[\:Category\:([^\]]*?)\]\]", re.IGNORECASE)
deletecat = re.compile(r"\[\[\:Category\:([^\]]*?)\]\]", re.IGNORECASE)
findday = re.compile(r"\[\[(Wikipedia\:Categories for (?:discussion|deletion)\/Log\/\d{4} \w+ \d+)#", re.IGNORECASE)
class ReCheck:
def __init__(self):
self.result = None
def check(self, pattern, text):
self.result = pattern.search(text)
return self.result
def main():
pywikibot.handleArgs();
page = pywikibot.Page(pywikibot.getSite(), cfdPage)
# Variable declarations
day = "None"
mode = "None"
src = "None"
dest = "None"
line = ""
summary = ""
robot = None
m = ReCheck()
for line in page.get().split("\n"):
if (nobots.search(line)):
# NO BOTS!!!
pass
elif (example.search(line)):
# Example line
pass
elif (speedymode.search(line)):
mode = "Speedy"
day = "None"
elif (movemode.search(line)):
mode = "Move"
day = "None"
elif (emptymode.search(line)):
mode = "Empty"
day = "None"
elif (deletemode.search(line)):
mode = "Delete"
day = "None"
elif (maintenance.search(line)):
# It's probably best not to try to handle these in an automated fashion.
mode = "None"
day = "None"
elif (m.check(dateheader, line)):
day = m.result.group(1)
pywikibot.output("Found day header: %s" % day)
elif (m.check(movecat, line)):
src = m.result.group(1)
dest = m.result.group(2)
thisDay = findDay(src, day)
if (mode == "Move" and thisDay != "None"):
summary = "Robot - Moving category " + src + " to [[:Category:" + dest + "]] per [[WP:CFD|CFD]] at " + thisDay + "."
elif (mode == "Speedy"):
summary = "Robot - Speedily moving category " + src + " to [[:Category:" + dest + "]] per [[WP:CFDS|CFDS]]."
else:
continue
# If the category is redirect, we do NOT want to move articles to
# it. The safest thing to do here is abort and wait for human
# intervention.
destpage = pywikibot.Page(
pywikibot.getSite(), dest, defaultNamespace=14)
if destpage.isCategoryRedirect():
summary = 'CANCELED. Destination is redirect: ' + summary
pywikibot.output(summary, toStdout=True)
robot = None
else:
robot = category.CategoryMoveRobot(oldCatTitle=src, newCatTitle=dest, batchMode=True,
editSummary=summary, inPlace=True, moveCatPage=True,
deleteEmptySourceCat=True, useSummaryForDeletion=True)
elif (m.check(deletecat, line)):
src = m.result.group(1)
# I currently don't see any reason to handle these two cases separately, though
# if are guaranteed that the category in the "Delete" case is empty, it might be
# easier to call delete.py on it.
thisDay = findDay(src, day)
if ((mode == "Empty" or mode == "Delete") and thisDay != "None"):
summary = "Robot - Removing category " + src + " per [[WP:CFD|CFD]] at " + thisDay + "."
else:
continue
robot = category.CategoryRemoveRobot(catTitle=src, batchMode=True, editSummary=summary,
useSummaryForDeletion=True, inPlace=True)
else:
# This line does not fit any of our regular expressions, so ignore it.
pass
if (summary != "" and robot != None):
pywikibot.output(summary, toStdout=True)
# Run, robot, run!
robot.run()
summary = ""
robot = None
# This function grabs the wiki source of a category page and attempts to
# extract a link to the CFD per-day discussion page from the CFD template.
# If the CFD template is not there, it will return the value of the second
# parameter, which is essentially a fallback that is extracted from the
# per-day subheadings on the working page.
def findDay(pageTitle, oldDay):
page = pywikibot.Page(pywikibot.getSite(), "Category:" + pageTitle)
try:
pageSrc = page.get()
m = findday.search(pageSrc)
except pywikibot.NoPage:
m = None
if (m != None):
return "[[" + m.group(1) + "]]"
else:
# Try to parse day link from CFD template parameters.
templates = page.templatesWithParams()
for template in templates:
if template[0] in cfdTemplates:
params = template[1]
(day, month, year) = [None, None, None]
for param in params:
(paramName, paramVal) = param.split('=', 1)
if (paramName == 'day'):
day = paramVal
elif (paramName == 'month'):
month = paramVal
elif (paramName == 'year'):
year = paramVal
if (day and month and year):
return "[[Wikipedia:Categories for discussion/Log/%s %s %s]]" % (year, month, day)
return oldDay
if __name__ == "__main__":
try:
main()
finally:
pywikibot.stopme()