snapshot from Gobby
[backwash] / backwash.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 # http://pywikipediabot.sourceforge.net/
5 # svn co http://svn.wikimedia.org/svnroot/pywikipedia/trunk/pywikipedia pywikipedia
6
7
8 import sys
9 import re
10 import iso8601
11 from simplemediawiki import MediaWiki
12 import interwiki
13
14 # TODO:
15 # - any space names in page names need to be turned into '_'s 
16 # - we need to de-interwikify any interwiki links given to Wiki:
17 # - normalize messages for non-unix linebreaks
18
19 class Wiki:
20     def __init__(self, url):
21         self.url = url
22         self.wiki = MediaWiki(self.url + 'api.php')
23
24     def get_revid_for_date(self, page, date):
25         wc = self.wiki.call({
26             'action': 'query',
27             'prop': 'revisions',
28             'titles': page,
29             'rvlimit': 1,
30             'redirects': 'true',
31             'rvstart': date,
32             'rvdir' : 'newer',
33             'rvprop' : 'timestamp|ids'})
34         pages = wc['query']['pages']
35         return pages[pages.keys()[0]]['revisions'][0]['revid']
36
37     def get_edit_token(self, page):
38         wc = self.wiki.call({
39             'action' : 'query',
40             'prop': 'info|revisions',
41             'titles': page,
42             'intoken' : 'edit'})
43         pages = wc['query']['pages']
44         import pprint
45         print 'edit token result:' + pprint.pformat(wc)
46         page = pages[pages.keys()[0]]
47         return page['edittoken']
48
49     def normalize_title(self, page):
50         wc = self.wiki.call({
51             'action': 'query',
52             'prop': 'info',
53             'titles': page,
54             'redirects': 'true'})
55         pages = wc['query']['pages']
56         page = pages[pages.keys()[0]]
57         return page['title']
58         
59     def get_talk_page(self, page):
60        normalized = self.normalize_title(page)
61        
62        if ':' in normalized:
63           (namespace, rest) = normalized.split(':', 1)
64           return '%s_talk:%s' % (namespace, rest)
65        else:
66           return 'Talk:%s' % page
67
68     def get_page_text(self, page):
69         wc = self.wiki.call({
70             'action': 'query',
71             'prop': 'revisions',
72             'titles': page,
73             'redirects': 'true',
74             'rvprop' : 'content'})
75         pages = wc['query']['pages']
76         # something here
77         page = pages[pages.keys()[0]]
78         return page['revisions'][0]['*']
79         
80     def append_to_talk_page(self, page, text):
81         talk_page = self.get_talk_page(page)
82         print 'talk page: %r' % talk_page
83         edit_token = self.get_edit_token(talk_page)
84         print edit_token, "\n"
85
86         wc = self.wiki.call({
87             'action' : 'edit',
88             'title': talk_page,
89 #            'bot' : 'true',
90             'token' : edit_token,
91             'not_minor': 'true',
92             'section' : 'new',
93             'summary': 'Suggestion from an offline user',
94             'text': text })
95
96         #import pprint
97         #print 'edit result:' + pprint.pformat(wc)        
98
99 def make_link(wiki, page, revision):
100     return '%sindex.php?title=%s&oldid=%s' % (wiki, page.replace(' ', '_'), revision)
101
102 class WikiEdit:
103     fields = ['page', 'date', 'e-mail', 'export-date', 'redirect', 'page-revision', 'user-agent', 'username', 'wiki']
104     datefields = ['date', 'export-date']
105
106     def __init__(self, headers={}, body='', normalize=True):
107         self.headers = headers
108         self.body = body
109
110         if normalize:
111             self.normalize_headers()
112
113     def normalize_headers(self):
114         self.headers.setdefault('wiki', 'http://en.wikipedia.org/wiki/')
115         if self.headers['wiki'] in interwiki.mapping.keys():
116             self.headers['wiki'] = interwiki.mapping[self.headers['wiki']]
117
118     def to_comment(self):
119         assembly = [('date', ' on %s,'),
120                     ('username', ' [[User:%s]]', ' an anonymous user'),
121                     ('e-mail', ' (e-mail: %s)'),
122                     (' made a comment',),
123                     ('page-revision', 
124         lambda x: ' on [' + make_link(self.headers['wiki'], self.headers['page'], self.headers['page-revision']) + 'this revision]'),
125                     ('user-agent', ' (using %s)')
126                     ]
127
128         comment = ""
129         for stage in assembly:
130             if len(stage) == 1:
131                 comment += stage[0]
132             elif self.headers.has_key(stage[0]):
133                 if isinstance(stage[1], str):
134                     comment += stage[1] % (self.headers[stage[0]])
135                 else:
136                     comment += stage[1](stage[0])
137             elif len(stage) == 3:
138                 comment += stage[2]
139
140         return ': ' + comment.strip().capitalize() + ":\n\n" + self.body
141
142     @classmethod
143     def from_string(cls, s):
144         body_index = s.index('\n\n')
145         # headers = dict([(X[:X.index(':')], X[X.index(':')+1:].strip()) for X in s[:body_index].split('\n')])
146         kvs = [re.split(': *', key_value, 1) for key_value in s[:body_index].splitlines()]
147         headers = dict([(key.lower(), value) for (key, value) in kvs])
148         body = s[body_index+2:]
149         return cls(headers, body)
150
151
152     
153
154 def parse_edits(lines):
155     edits = []
156     acc = ""
157     for line in lines:
158         if '\n\n' in acc and line.startswith('Page:'):
159             we = WikiEdit.from_string(acc)
160             edits.append(we)
161             print we, we.headers, we.body
162             acc = ""
163         acc += line
164     
165     if acc != '':
166         we = WikiEdit.from_string(acc)
167         edits.append(we)
168         print (we, we.headers, we.body)
169
170     return edits
171
172 if __name__ =='__main__':
173     # parse the .wpe file on standard
174     edits = parse_edits(sys.stdin)
175
176     for edit in edits:
177         # if there is an export date but no revision, lets go to wiki an
178         # find out what the revision id is
179         # if edit.headers.has_key("export-date") and \
180         #         not edit.headers.has_key("page-revision"):
181         #     wiki = Wiki(edit.headers['wiki'])
182         #     revid = wiki.get_revid_for_date(edit.headers["page"], edit.headers["export-date"])
183         # else:
184         #     revid = edit.headers['page-revision']
185
186         # print revid
187         # # rvdir=newer&rvprop=timestamp|ids
188
189         # edit_msg = edit.to_comment()
190         # print edit_msg
191
192         wiki = Wiki(edit.headers['wiki'])
193         #print wiki.get_page_text(edit.headers['page'])
194         wiki.append_to_talk_page(edit.headers['page'], edit.to_comment())
195
196                      
197 # iso8601.parse_date("2007-06-20T12:34:40+03:00")

Benjamin Mako Hill || Want to submit a patch?