rbmediawiki 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/category.rb ADDED
@@ -0,0 +1,42 @@
1
+ require 'deep_merge'
2
+
3
+ require 'api'
4
+ require 'page'
5
+
6
+ #This class represents a category and performs actions dealing with categories.
7
+ #
8
+ class Category
9
+ attr_reader :title
10
+ attr_reader :id
11
+ def initialize(title = nil, site = nil, id = nil)
12
+ @site = site ? site : Api.new()
13
+ @title = title.gsub(" ","_")
14
+ @id = id
15
+ end
16
+
17
+ #get pages in the category as an array of Page elements
18
+ #returns false if there aren't any, and raises NoPage if page doesn't exist
19
+ def get_members(cmlimit = 500)
20
+ cmcontinue = nil
21
+ cms = Hash.new
22
+ loop {
23
+ result = @site.query_list_categorymembers(@title, @title, nil, nil, cmcontinue, cmlimit)
24
+ if result.key?('query-continue')
25
+ cmcontinue = result['query-continue']['categorymembers']['cmcontinue']
26
+ cms.deep_merge!(result['query'])
27
+ else
28
+ cms.deep_merge!(result['query'])
29
+ break
30
+ end
31
+ }
32
+ if cms['pages']['page'].key?('missing')
33
+ raise NoPage.new(), "Page [[#{title}]] does not exist"
34
+ elsif cms.key?('categorymembers')
35
+ members = Array.new
36
+ cms['categorymembers']['cm'].each{|el| members.push(Page.new(el['title']))}
37
+ return members
38
+ else return false
39
+ end
40
+
41
+ end
42
+ end
data/lib/config.yml ADDED
@@ -0,0 +1,4 @@
1
+ default_lang: es
2
+ default_family: wikipedia
3
+ default_user: Chabacano
4
+ user-agent: rbywikipedia
@@ -0,0 +1,56 @@
1
+ require 'page'
2
+ require 'generator'
3
+
4
+ class Misc_generator
5
+ def initialize(site)
6
+ @site = site
7
+ end
8
+
9
+ #returns revisions of a page
10
+ # * titles: the page
11
+ # * rvlimit: how many revisions retrieve by query (default: 50, max: 50)
12
+ # * rvprop: fields to retrieve (default: all)
13
+ # * rvstartid: id of the revision to start
14
+ # * rvendid: id of the revision to end
15
+ # * rvdir: older or newer. Defaulr: older.
16
+ # * rvuser: only get revisions by user.
17
+ # * diffto: Revision ID to diff each revision to. Use "prev", "next" and "cur" for the previous, next and current revision respectively.
18
+
19
+
20
+ def history( titles, rvlimit = 1, rvprop = "ids|timestamp|flags|comment|user|size|content", rvstartid = nil, rvendid = nil, rvdir = "older", rvuser = nil, diffto = "prev")
21
+ g = Generator.new { |g|
22
+ pages = Hash.new
23
+ finish = false
24
+ while !finish
25
+ result = @site.query_prop_revisions(titles, rvprop, rvlimit, rvstartid, rvendid, nil, nil, rvdir, rvuser, nil, nil, nil, nil, nil, nil, diffto )
26
+ result['query']['pages']['page']['revisions'].each {|rv|
27
+ g.yield rv
28
+ }
29
+ if result.key?('query-continue')
30
+ rvstartid = result['query-continue']['revisions']['rvstartid']
31
+ else
32
+ finish = true
33
+ end
34
+ end
35
+ }
36
+ end
37
+
38
+ def history_diff( titles, rvlimit = 50, rvprop = "ids|timestamp|flags|comment|user|size|content", rvstartid = nil, rvendid = nil, rvdir = "older", rvuser= nil)
39
+ g = Generator.new { |g|
40
+ pages = Hash.new
41
+ finish = false
42
+ while !finish
43
+ result = @site.query_prop_revisions(titles, rvprop, rvlimit, rvstartid, rvendid, nil, nil, rvdir, rvuser)
44
+ puts result['query']['pages']['page']['revisions']
45
+ result['query']['pages']['page']['revisions'].each {|rv|
46
+ g.yield rv
47
+ }
48
+ if result.key?('query-continue')
49
+ rvstartid = result['query-continue']['revisions']['rvstartid']
50
+ else
51
+ finish = true
52
+ end
53
+ end
54
+ }
55
+ end
56
+ end
data/lib/page.rb ADDED
@@ -0,0 +1,456 @@
1
+ #TODO: rollback
2
+ #TODO: patrol
3
+ require 'deep_merge'
4
+
5
+ require 'api'
6
+
7
+ #This class represents a page. It gives methods for dealing with single
8
+ #pages: obtainig the content, putting it, appending content, deleting, etc.
9
+ class Page
10
+ attr_reader :title
11
+ def initialize(title = nil, site = nil)
12
+ @site = site ? site : Api.new()
13
+ @title = title
14
+ @normtitle = title.gsub(" ","_")
15
+ end
16
+
17
+ #retrieves the content of the page
18
+ def get()
19
+ result = @site.query_prop_revisions(@normtitle, 'content')
20
+ if result.key?('error')
21
+ raise RbmediawikiError, "#{title}: "+result['error']['code']
22
+ else
23
+ return result['query']['pages']['page']['revisions']['rev']
24
+ end
25
+ end
26
+
27
+ #puts the text of a page.
28
+ # * text: the new content of the page
29
+ # * summary: editting summary
30
+ # * minor: is a minor edit? default->true
31
+ # * bot: is a bot flagged edit?
32
+ def put(text, summary = nil, minor = true, bot = true)
33
+ #require login
34
+ @site.login
35
+ result = @site.query_prop_info(@normtitle, nil, 'edit')
36
+ token = result['query']['pages']['page']['edittoken']
37
+ result = @site.edit(@normtitle, nil, text, token, summary, minor, nil, bot)
38
+ if result.key?('error')
39
+ raise RbmediawikiError, "#{title}: "+result['error']['code']
40
+ else
41
+ return true
42
+ end
43
+ end
44
+
45
+ #appends texto to a page
46
+ #same as #put, but the text is appended and the previous content preserved
47
+ def append(text, summary = nil, minor = true, bot = true)
48
+ #require login
49
+ @site.login
50
+ puts text
51
+ result = @site.query_prop_info(@normtitle, nil, 'edit')
52
+ token = result['query']['pages']['page']['edittoken']
53
+ result = @site.edit(@normtitle, nil, text, token, summary, minor, nil, bot, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, text)
54
+ if result.key?('error')
55
+ raise RbmediawikiError, "#{title}: "+result['error']['code']
56
+ else
57
+ return true
58
+ end
59
+ end
60
+
61
+ #prepends text to a page
62
+ #same as #put, but the text is prepended and the previous content preserved
63
+ def prepend(text, summary = nil, minor = true, bot = true)
64
+ #require login
65
+ @site.login
66
+ result = @site.query_prop_info(@normtitle, nil, 'edit')
67
+ token = result['query']['pages']['page']['edittoken']
68
+ result = @site.edit(@normtitle, nil, text, token, summary, minor, nil, bot, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, text)
69
+ if result.key?('error')
70
+ raise RbmediawikiError, "#{title}: "+result['error']['code']
71
+ else
72
+ return true
73
+ end
74
+ end
75
+
76
+ #adds a section to a page
77
+ #same as #append, but is a section what is appended.
78
+ #title is the title of the new section
79
+ def addsection(text, title, minor = false, bot = true)
80
+ #require login
81
+ @site.login
82
+ result = @site.query_prop_info(@normtitle, nil, 'edit')
83
+ token = result['query']['pages']['page']['edittoken']
84
+ result = @site.edit(@normtitle, section, text, token, title, minor, nil, bot)
85
+ if result.key?('error')
86
+ raise RbmediawikiError, "#{title}: "+result['error']['code']
87
+ else
88
+ return true
89
+ end
90
+ end
91
+
92
+ #moves a page
93
+ # * reason: reason or summary
94
+ # * movetalk: move talk pages too (default->true)
95
+ # * noredirect: don't leave a redirect (default->nil)
96
+ def move(to, reason = nil, movetalk = true, noredirect = nil)
97
+ #require login
98
+ @site.login
99
+ result = @site.query_prop_info(@normtitle, nil, 'move')
100
+ token = result['query']['pages']['page']['movetoken']
101
+ result = @site.move(@normtitle, nil, to, token, reason, movetalk, nil, noredirect)
102
+ if result.key?('error')
103
+ raise RbmediawikiError, "#{title}: "+result['error']['code']
104
+ else
105
+ return true
106
+ end
107
+ end
108
+
109
+ #protects a page.
110
+ #reason is the reason for the protection
111
+ #expiry is a timescamp (default is infinite).
112
+ #protections is the action and group that can perform that action, separated
113
+ #by pipes. Exapmple "edit=sysop|move=autoconfirmed".Default is edit=sysop|move=sysop
114
+ def protect(reason = nil, expiry = 'infinite', protections = 'edit=sysop|move=sysop')
115
+ #require login
116
+ @site.login
117
+ result = @site.query_prop_info(@normtitle, nil, 'protect')
118
+ token = result['query']['pages']['page']['protecttoken']
119
+ result = @site.protect(@normtitle, token, protections, expiry, reason)
120
+ if result.key?('error')
121
+ raise RbmediawikiError, "#{title}: "+result['error']['code']
122
+ else
123
+ return true
124
+ end
125
+ end
126
+
127
+ #semipotects a page.
128
+ #is the same as protect, but default for protections is "edit=autoconfirmed|move=autoconfirmed"
129
+ def semiprotect(reason = nil, expiry = 'infinite')
130
+ protect(reason, expiry, 'edit=autoconfirmed|move=autoconfirmed')
131
+ #possible errors: user doesn't have privileges
132
+ end
133
+
134
+ #delete the page.
135
+ #reason : reason for deleting
136
+ #returns true if success, raises NoPage if page doesn't exist
137
+ def delete(reason="")
138
+ @site.login
139
+ result = @site.query_prop_info(@normtitle, nil, 'delete')
140
+ token = result['query']['pages']['page']['deletetoken']
141
+ result = @site.delete(@normtitle, nil, token, reason)
142
+ if result.key?('error')
143
+ raise RbmediawikiError, "#{@title}: "+result['error']['code']
144
+ else
145
+ return true
146
+ end
147
+ end
148
+
149
+ #undeletes a page.
150
+ #reason: reason for deleting
151
+ #returns true if success, false if there aren't deleted revisions
152
+
153
+ def undelete(reason="")
154
+ @site.login
155
+ result = @site.query_list_deletedrevs(@normtitle, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 'token')
156
+ if result.key?('error')
157
+ raise RbmediawikiError, "#{@title}: "+result['error']['code']
158
+ end
159
+ if !result.has_key?('deletedRevs')
160
+ return false
161
+ end
162
+ token = result['query']['deletedrevs']['page']['token']
163
+ result = @site.undelete(@normtitle, token, reason)
164
+ return true
165
+ end
166
+
167
+ #rollback (revert) editr by user. Summary can be given
168
+ def rollback(user = nil, summary = nil, markbot = nil)
169
+ @site.login
170
+ result = @site.query_prop_revisions(@normtitle, nil, nil, nil, nil, nil, nil, nil, user, nil, nil, nil, nil, 'rollback')
171
+ #Page exists?
172
+ if result['query']['pages']['page'].key?('missing')
173
+ raise NoPage, "Page [[#{@title}]] does not exist"
174
+ end
175
+ #Has user edited this?
176
+ if !result['query']['pages']['page'].key?('revisions')
177
+ raise RbmediawikiError, "#{@title}: No edits by user #{user}"
178
+ end
179
+
180
+ #If the user made more than one contribs, this is an array
181
+ #but the token is the same. We only want the token
182
+ if result['query']['pages']['page']['revisions']['rev'].is_a? Array
183
+ token = result['query']['pages']['page']['revisions']['rev'][0]['rollbacktoken']
184
+ else
185
+ token = result['query']['pages']['page']['revisions']['rev']['rollbacktoken']
186
+ end
187
+ result = @site.rollback(@normtitle, user, token, summary, markbot)
188
+ if result.key?('error')
189
+ raise RbmediawikiError, "#{@title}: "+result['error']['code']
190
+ else
191
+ return true
192
+ end
193
+ end
194
+
195
+ #gets info about the protections of a page. Returns an array as for instance
196
+ #{level => sysop,type => edit,expiry => infinity}
197
+ #{level => sysop,type => move,expiry => infinity}
198
+ def protected?()
199
+ result = @site.query_prop_info(@normtitle, 'protection')
200
+ if result.key?('error')
201
+ raise RbmediawikiError, "#{@title}: "+result['error']['code']
202
+ end
203
+ if result['query']['pages']['page'].key?('missing')
204
+ raise NoPage, "Page [[#{@title}]] does not exist"
205
+
206
+ else
207
+ return result['query']['pages']['page']['protection']['pr']
208
+ end
209
+ end
210
+
211
+
212
+ #get interwiki links
213
+ #min is the minimum number of elements to return, lllimit is the number of
214
+ #elements to request from the API in each iteration. The method will
215
+ #request elements until it has at least min elements.
216
+ #returns false if there aren't any, and raises NoPage if page doesn't exist
217
+ def get_interwikis(min = nil, lllimit = 500)
218
+ llcontinue = nil
219
+ iws = Hash.new
220
+ count = 0
221
+ loop {
222
+ result = @site.query_prop_langlinks(@normtitle, lllimit, llcontinue)
223
+ iws.deep_merge!(result['query'])
224
+ if result.key?('query-continue') && min && count < min
225
+ count += lllimit
226
+ llcontinue = result['query-continue']['langlinks']['llcontinue']
227
+ else
228
+ break
229
+ end
230
+ }
231
+ if iws['pages']['page'].key?('missing')
232
+ raise NoPage.new(), "Page [[#{title}]] does not exist"
233
+ elsif iws['pages']['page'].key?('langlinks')
234
+ return iws['pages']['page']['langlinks']['ll']
235
+ else return false
236
+ end
237
+ end
238
+
239
+ #gets image links of a page
240
+ #min is the minimum number of elements to return, imlimit is the number of
241
+ #elements to request from the API in each iteration. The method will
242
+ #request elements until it has at least min elements.
243
+ #returns false if there aren't any, and raises NoPage if page doesn't exist
244
+ def get_images(min = nil, imlimit = 500)
245
+ imcontinue = nil
246
+ ims = Hash.new
247
+ count = 0
248
+ loop {
249
+ result = @site.query_prop_images(@normtitle, imlimit, imcontinue)
250
+ ims.deep_merge!(result['query'])
251
+ if result.key?('query-continue') && min && count < min
252
+ count += lllimit
253
+ imcontinue = result['query-continue']['images']['imcontinue']
254
+ else
255
+ break
256
+ end
257
+ }
258
+ if ims['pages']['page'].key?('missing')
259
+ raise NoPage.new(), "Page [[#{@title}]] does not exist"
260
+ elsif ims['pages']['page'].key?('images')
261
+ return ims['pages']['page']['images']['im']
262
+ else return false
263
+ end
264
+ end
265
+
266
+ #gets templates used in a page
267
+ #min is the minimum number of elements to return, tllimit is the number of
268
+ #elements to request from the API in each iteration. The method will
269
+ #request elements until it has at least min elements.
270
+ #returns false if there aren't any, and raises NoPage if page doesn't exist
271
+ def get_templates(min = nil, tllimit = 500)
272
+ tlcontinue = nil
273
+ tls = Hash.new
274
+ count = 0
275
+ loop {
276
+ result = @site.query_prop_templates(@normtitle, nil, tllimit, tlcontinue)
277
+ tls.deep_merge!(result['query'])
278
+ if result.key?('query-continue')&& min && count < min
279
+ count += lllimit
280
+ tlcontinue = result['query-continue']['templates']['tlcontinue']
281
+ else
282
+ break
283
+ end
284
+ }
285
+ if tls['pages']['page'].key?('missing')
286
+ raise NoPage.new(), "Page [[#{@title}]] does not exist"
287
+ elsif tls['pages']['page'].key?('templates')
288
+ return tls['pages']['page']['templates']['tl']
289
+ else return false
290
+ end
291
+ end
292
+
293
+ #gets templates used in a page
294
+ #min is the minimum number of elements to return, cllimit is the number of
295
+ #elements to request from the API in each iteration. The method will
296
+ #request elements until it has at least min elements.
297
+ #clshow can be "hidden" or "!hidden". Default shows both
298
+ #if sortkey is true will return the sortkey. Default is true
299
+ def get_categories(min = nil, cllimit = 500, clshow = nil, sortkey = true)
300
+ clcontinue = nil
301
+ cls = Hash.new
302
+ count = 0
303
+
304
+ if sortkey
305
+ clprop = "sortkey"
306
+ end
307
+
308
+ loop {
309
+ result = @site.query_prop_categories(@normtitle, clprop, clshow, cllimit, clcontinue)
310
+ cls.deep_merge!(result['query'])
311
+ if result.key?('query-continue')&& min && count < min
312
+ count += lllimit
313
+ clcontinue = result['query-continue']['categories']['clcontinue']
314
+ else
315
+ break
316
+ end
317
+ }
318
+ if cls['pages']['page'].key?('missing')
319
+ raise NoPage.new(), "Page [[#{@title}]] does not exist"
320
+ elsif cls['pages']['page'].key?('categories')
321
+ return cls['pages']['page']['categories']['cl']
322
+ else return false
323
+ end
324
+ end
325
+
326
+ #gets external links used in a page
327
+ #min is the minimum number of elements to return, ellimit is the number of
328
+ #elements to request from the API in each iteration. The method will
329
+ #request elements until it has at least min elements.
330
+ #returns false if there aren't any, and raises NoPage if page doesn't exist
331
+ def get_external_links(min = nil, ellimit = 500)
332
+ eloffset = nil
333
+ els = Hash.new
334
+ count = 0
335
+ loop {
336
+ result = @site.query_prop_extlinks(@normtitle, ellimit, eloffset)
337
+ els.deep_merge!(result['query'])
338
+ if result.key?('query-continue')&& min && count < min
339
+ count += lllimit
340
+ eloffset = result['query-continue']['extlinks']['elcontinue']
341
+ else
342
+ break
343
+ end
344
+ }
345
+ if els['pages']['page'].key?('missing')
346
+ raise NoPage.new(), "Page [[#{@title}]] does not exist"
347
+ elsif els['pages']['page'].key?('extlinks')
348
+ return els['pages']['page']['extlinks']['el']
349
+ else return false
350
+ end
351
+ end
352
+
353
+ #gets backlinks (what links here) used in a page
354
+ #min is the minimum number of elements to return, bllimit is the number of
355
+ #elements to request from the API in each iteration. The method will
356
+ #request elements until it has at least min elements.
357
+ #returns false if there aren't any, and raises NoPage if page doesn't exist
358
+ def get_backlinks(min = nil, bllimit = 500, blnamespace = nil, blredirect = true)
359
+ blcontinue = nil
360
+ bls = Hash.new
361
+ count = 0
362
+ loop {
363
+ result = @site.query_list_backlinks(@normtitle, @normtitle, blcontinue, blnamespace, nil, bllimit, blredirect)
364
+ bls.deep_merge!(result['query'])
365
+ if result.key?('query-continue')&& min && count < min
366
+ count += lllimit
367
+ blcontinue = result['query-continue']['backlinks']['blcontinue']
368
+ else
369
+ break
370
+ end
371
+ }
372
+ if bls['pages']['page'].key?('missing')
373
+ raise NoPage.new(), "Page [[#{@title}]] does not exist"
374
+ elsif bls['backlinks'].key?('bl')
375
+ return bls['backlinks']['bl']
376
+ else return false
377
+ end
378
+ end
379
+
380
+ #gets deleted revisions of a page
381
+ #min is the minimum number of elements to return, drlimit is the number of
382
+ #elements to request from the API in each iteration. The method will
383
+ #request elements until it has at least min elements.
384
+ #returns false if there aren't any
385
+ def get_deletedrevs(min = nil, drlimit = 500)
386
+ @site.login
387
+ drcontinue = nil
388
+ drs = Hash.new
389
+ count = 0
390
+ loop {
391
+ result = @site.query_list_deletedrevs(@normtitle, nil, nil, nil, nil, nil, nil, drcontinue, nil, nil, nil, nil, drlimit)
392
+ drs.deep_merge!(result['query'])
393
+ if result.key?('query-continue')&& min && count < min
394
+ count += lllimit
395
+ drcontinue = result['query-continue']['deletedrevs']['drstart']
396
+ else
397
+ break
398
+ end
399
+ }
400
+ if drs['deletedrevs'].key?('page')
401
+ return drs['deletedrevs']['page']['revisions']['rev']
402
+ else return false
403
+ end
404
+ end
405
+
406
+ #gets pages in which this page is embedded (or transcluded). Returns a list
407
+ #of Page elements
408
+ #min is the minimum number of elements to return, eilimit is the number of
409
+ #elements to request from the API in each iteration. The method will
410
+ #request elements until it has at least min elements.
411
+ #returns false if there aren't any, and raises NoPage if page doesn't exist
412
+ def get_embeddedin(min = nil, eilimit = 500)
413
+ eicontinue = nil
414
+ eis = Hash.new
415
+ count = 0
416
+ loop {
417
+ result = @site.query_list_embeddedin(@normtitle, @normtitle, eicontinue, nil, nil, eilimit)
418
+ eis.deep_merge!(result['query'])
419
+ if result.key?('query-continue')&& min && count < min
420
+ count += lllimit
421
+ eicontinue = result['query-continue']['embeddedin']['eicontinue']
422
+ else
423
+ break
424
+ end
425
+ }
426
+ if eis['pages']['page'].key?('missing')
427
+ raise NoPage.new(), "Page [[#{@title}]] does not exist"
428
+ elsif eis['embeddedin'].key?('ei')
429
+ members = Array.new
430
+ eis['embeddedin']['ei'].each{|el| members.push(Page.new(el['title']))}
431
+ return members
432
+ else return false
433
+ end
434
+ end
435
+
436
+ #returns the size of the page content in bytes
437
+ #Raises NoPage if the page doesn't exist
438
+ def get_size
439
+ result = @site.query_prop_info(@normtitle)
440
+ if result['query']['pages']['page'].key?('missing')
441
+ raise NoPage.new(), "Page [[#{@normtitle}]] does not exist"
442
+ else
443
+ return result['query']['pages']['page']['length']
444
+ end
445
+ end
446
+
447
+ end
448
+
449
+ class NoPage < RuntimeError
450
+ end
451
+
452
+ class PageExists < RuntimeError
453
+ end
454
+
455
+ class RbmediawikiError < RuntimeError
456
+ end