This repository has been archived by the owner on Apr 5, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
cfd.py
153 lines (139 loc) · 6.04 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
# -*- 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
import re
import category
# The locateion of the CFD working page.
cfdPage = 'Wikipedia:Categories for discussion/Working'
# 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():
wikipedia.handleArgs();
page = wikipedia.Page(wikipedia.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)
elif (m.check(movecat, line)):
src = m.result.group(1)
dest = m.result.group(2)
if (mode == "Move" and day != "None"):
summary = "Robot - Moving category " + src + " to " + dest + " per [[WP:CFD|CFD]] at " + findDay(src, day) + "."
elif (mode == "Speedy"):
summary = "Robot - Speedily moving category " + src + " to " + dest + " per [[WP:CFD|CFD]]."
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 = wikipedia.Page(
wikipedia.getSite(), dest, defaultNamespace=14)
if destpage.isCategoryRedirect():
summary = 'CANCELED. Destination is redirect: ' + summary
wikipedia.output(summary, toStdout=True)
robot = None
else:
robot = category.CategoryMoveRobot(oldCatTitle=src, newCatTitle=dest, batchMode=True,
editSummary=summary, inPlace=True, moveCatPage=True,
deleteEmptySourceCat=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.
if ((mode == "Empty" or mode == "Delete") and day != "None"):
summary = "Robot - Removing category " + src + " per [[WP:CFD|CFD]] at " + findDay(src, day) + "."
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):
wikipedia.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 = wikipedia.Page(wikipedia.getSite(), "Category:" + pageTitle)
try:
pageSrc = page.get()
m = findday.search(pageSrc)
except wikipedia.NoPage:
m = None
if (m != None):
return "[[" + m.group(1) + "]]"
else:
wikipedia.output("Could not find CFD day link on Category:" + pageTitle + "\n", toStdout=True)
return oldDay
if __name__ == "__main__":
try:
main()
finally:
wikipedia.stopme()