ruby-mediawiki 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +674 -0
- data/README +60 -0
- data/apps/comment_sync.rb +178 -0
- data/apps/date_determinator.rb +185 -0
- data/apps/iso_639_leecher.rb +58 -0
- data/apps/localization_sync.rb +143 -0
- data/apps/rdoc_to_wiki.rb +126 -0
- data/apps/speed_metal_bot.rb +79 -0
- data/apps/wikicat.rb +30 -0
- data/apps/wikipost.rb +32 -0
- data/lib/mediawiki.rb +170 -0
- data/lib/mediawiki/article.rb +259 -0
- data/lib/mediawiki/category.rb +54 -0
- data/lib/mediawiki/dotfile.rb +51 -0
- data/lib/mediawiki/minibrowser.rb +140 -0
- data/lib/mediawiki/specialpage.rb +39 -0
- data/lib/mediawiki/table.rb +95 -0
- data/mediawikirc.sample +25 -0
- data/mkrdoc.sh +3 -0
- metadata +62 -0
@@ -0,0 +1,143 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
=begin
|
3
|
+
This file is part of Ruby-MediaWiki.
|
4
|
+
|
5
|
+
Ruby-MediaWiki is free software: you can redistribute it and/or
|
6
|
+
modify it under the terms of the GNU General Public License as
|
7
|
+
published by the Free Software Foundation, either version 3 of the
|
8
|
+
License, or (at your option) any later version.
|
9
|
+
|
10
|
+
Ruby-MediaWiki is distributed in the hope that it will be useful,
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
+
General Public License for more details.
|
14
|
+
|
15
|
+
You should have received a copy of the GNU General Public License
|
16
|
+
along with Ruby-MediaWiki. If not, see
|
17
|
+
<http://www.gnu.org/licenses/>.
|
18
|
+
=end
|
19
|
+
|
20
|
+
|
21
|
+
# this bot expects a fully functional local pentabarf installation
|
22
|
+
|
23
|
+
$:.unshift('../lib')
|
24
|
+
|
25
|
+
require 'mediawiki/dotfile'
|
26
|
+
require 'mediawiki/table'
|
27
|
+
require 'momomoto/momomoto'
|
28
|
+
require 'momomoto/tables'
|
29
|
+
require 'momomoto/bot_login'
|
30
|
+
|
31
|
+
class Localization_Sync
|
32
|
+
|
33
|
+
def initialize
|
34
|
+
@wiki = MediaWiki.dotfile
|
35
|
+
|
36
|
+
db_config = YAML.load_file('db_config.yml')['development']
|
37
|
+
Momomoto::Base.connect(db_config)
|
38
|
+
Momomoto::Bot_login.authorize('ui_tagger')
|
39
|
+
|
40
|
+
@lang = {}
|
41
|
+
Momomoto::Language.find({:f_localized=>'t'},nil,"lower(tag)").each do | l | @lang[l.tag] = l.language_id end
|
42
|
+
|
43
|
+
@@syncable = [
|
44
|
+
['Attachment_type', :attachment_type_id, :tag, Momomoto::Attachment_type, Momomoto::Attachment_type_localized],
|
45
|
+
['Conference_phase', :conference_phase_id, :tag, Momomoto::Conference_phase, Momomoto::Conference_phase_localized],
|
46
|
+
['Conflict', :conflict_id, :tag, Momomoto::Conflict, Momomoto::Conflict_localized],
|
47
|
+
['Conflict_level', :conflict_level_id, :tag, Momomoto::Conflict_level, Momomoto::Conflict_level_localized],
|
48
|
+
['Country', :country_id, :iso_3166_code, Momomoto::Country, Momomoto::Country_localized],
|
49
|
+
['Currency', :currency_id, :iso_4217_code, Momomoto::Currency, Momomoto::Currency_localized],
|
50
|
+
['Event_origin', :event_origin_id, :tag, Momomoto::Event_origin, Momomoto::Event_origin_localized],
|
51
|
+
['Event_role', :event_role_id, :tag, Momomoto::Event_role, Momomoto::Event_role_localized],
|
52
|
+
['Event_state', :event_state_id, :tag, Momomoto::Event_state, Momomoto::Event_state_localized],
|
53
|
+
['Event_type', :event_type_id, :tag, Momomoto::Event_type, Momomoto::Event_type_localized],
|
54
|
+
['Im_type', :im_type_id, :tag, Momomoto::Im_type, Momomoto::Im_type_localized],
|
55
|
+
['Language', :language_id, :iso_639_code, Momomoto::Language, Momomoto::Language_localized, :translated_id],
|
56
|
+
['Mime_type', :mime_type_id, :mime_type, Momomoto::Mime_type, Momomoto::Mime_type_localized],
|
57
|
+
['Phone_type', :phone_type_id, :tag, Momomoto::Phone_type, Momomoto::Phone_type_localized],
|
58
|
+
['Role', :role_id, :tag, Momomoto::Role, Momomoto::Role_localized],
|
59
|
+
['Transport', :transport_id, :tag, Momomoto::Transport, Momomoto::Transport_localized],
|
60
|
+
['Ui_message', :ui_message_id, :tag, Momomoto::Ui_message, Momomoto::Ui_message_localized]
|
61
|
+
]
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
# creates wiki pages from the data in the database
|
66
|
+
def update_wiki
|
67
|
+
@@syncable.each do | row |
|
68
|
+
make_table( *row )
|
69
|
+
end
|
70
|
+
page = @wiki.article('Localization', 1)
|
71
|
+
page.text = "=Localizable Tables=\n"
|
72
|
+
@@syncable.each do | row |
|
73
|
+
page.text += "*[[Localization/#{row[0]}|#{row[0]}]]\n"
|
74
|
+
end
|
75
|
+
page.submit('updating localization page')
|
76
|
+
end
|
77
|
+
|
78
|
+
# reads wiki pages and updates the database according to the data in the wiki
|
79
|
+
def update_database
|
80
|
+
@@syncable.each do | row |
|
81
|
+
read_table( *row )
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def read_table(table, tag_id, tag_name, tag_class, local_class, lang_id = :language_id)
|
86
|
+
page = @wiki.article("Localization/#{table}")
|
87
|
+
return if page.text == ''
|
88
|
+
t = MediaWiki::Table.parse( page.text )
|
89
|
+
header = t.shift
|
90
|
+
header.shift
|
91
|
+
|
92
|
+
local_class.new.begin
|
93
|
+
|
94
|
+
t.each do | row |
|
95
|
+
header.each_with_index do | lang_tag, index |
|
96
|
+
cur_tag = tag_class.find({tag_name=>row[0]})
|
97
|
+
next unless cur_tag.length == 1
|
98
|
+
cur_loc = local_class.find({lang_id=>@lang[header[index]],tag_id=>cur_tag[tag_id]})
|
99
|
+
next if row[index + 1] == ''
|
100
|
+
unless cur_loc.length == 1
|
101
|
+
cur_loc.create
|
102
|
+
cur_loc[lang_id] = @lang[header[index]]
|
103
|
+
cur_loc[tag_id] = cur_tag[tag_id]
|
104
|
+
end
|
105
|
+
cur_loc[:name] = row[index + 1].strip
|
106
|
+
cur_loc.write
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
local_class.new.commit
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
def make_table(table, tag_id, tag_name, tag_class, local_class, lang_id = :language_id)
|
115
|
+
tags = {}
|
116
|
+
tag_class.find().each do | tc | tags[tc[tag_name]] = tc[tag_id] end
|
117
|
+
local = local_class.find({lang_id=>@lang.values})
|
118
|
+
|
119
|
+
page = @wiki.article("Localization/#{table}")
|
120
|
+
|
121
|
+
t = MediaWiki::Table.new
|
122
|
+
t.style = 'border="1" cellspacing="0" cellpadding="3" style="border-collapse: collapse;"'
|
123
|
+
t.header_style = 'bgcolor="lightblue"'
|
124
|
+
t.header = ['']
|
125
|
+
@lang.each do | tag, id | t.header.push( tag ) end
|
126
|
+
tags.keys.sort.each do | tag |
|
127
|
+
row = [tag]
|
128
|
+
@lang.each do | key, language_id |
|
129
|
+
row.push(local.find_by_value({tag_id=>tags[tag],lang_id=>language_id}) ? local.name : '')
|
130
|
+
end
|
131
|
+
t.data.push( row )
|
132
|
+
end
|
133
|
+
|
134
|
+
page.text = "[[Localization|<< Localization]]\n" + t.text + "\n[[Category:Localization]]"
|
135
|
+
page.submit("updating localization pages")
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
s = Localization_Sync.new
|
141
|
+
s.update_database
|
142
|
+
s.update_wiki
|
143
|
+
|
@@ -0,0 +1,126 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
=begin
|
3
|
+
This file is part of Ruby-MediaWiki.
|
4
|
+
|
5
|
+
Ruby-MediaWiki is free software: you can redistribute it and/or
|
6
|
+
modify it under the terms of the GNU General Public License as
|
7
|
+
published by the Free Software Foundation, either version 3 of the
|
8
|
+
License, or (at your option) any later version.
|
9
|
+
|
10
|
+
Ruby-MediaWiki is distributed in the hope that it will be useful,
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
+
General Public License for more details.
|
14
|
+
|
15
|
+
You should have received a copy of the GNU General Public License
|
16
|
+
along with Ruby-MediaWiki. If not, see
|
17
|
+
<http://www.gnu.org/licenses/>.
|
18
|
+
=end
|
19
|
+
|
20
|
+
|
21
|
+
require 'yaml'
|
22
|
+
require 'rdoc/ri/ri_reader'
|
23
|
+
|
24
|
+
$:.unshift('../lib')
|
25
|
+
require 'mediawiki/dotfile'
|
26
|
+
|
27
|
+
|
28
|
+
def find(dir, &block)
|
29
|
+
Dir.foreach(dir) { |file|
|
30
|
+
next if file =~ /^\./
|
31
|
+
|
32
|
+
path = "#{dir}/#{file}"
|
33
|
+
if File.directory?(path)
|
34
|
+
find(path) { |f| yield f }
|
35
|
+
else
|
36
|
+
yield path
|
37
|
+
end
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
def wiki_format(flow)
|
42
|
+
s = ''
|
43
|
+
case flow
|
44
|
+
when Array
|
45
|
+
flow.each { |subflow|
|
46
|
+
s += wiki_format(subflow)
|
47
|
+
}
|
48
|
+
when SM::Flow::LIST
|
49
|
+
flow.contents.each { |subflow|
|
50
|
+
s += wiki_format(subflow)
|
51
|
+
}
|
52
|
+
s += "\n"
|
53
|
+
when SM::Flow::LI
|
54
|
+
if flow.label =~ /:$/
|
55
|
+
s += "; #{flow.label}\n: #{flow.body}\n"
|
56
|
+
elsif flow.label =~ /^[ \*]$/
|
57
|
+
s += "#{flow.label} #{flow.body}\n"
|
58
|
+
else
|
59
|
+
s += "* '''#{flow.label}:''' #{flow.body}\n"
|
60
|
+
end
|
61
|
+
when SM::Flow::P
|
62
|
+
s += "#{flow.body}\n\n"
|
63
|
+
else
|
64
|
+
puts "Unknown Flow: #{flow.inspect}"
|
65
|
+
end
|
66
|
+
s.gsub!(/"/, '"')
|
67
|
+
s.gsub!(/<b>(.+?)<\/b>/, '\'\'\'\1\'\'\'')
|
68
|
+
s.gsub!(/<i>(.+?)<\/i>/, '\'\'\1\'\'')
|
69
|
+
s.gsub!(/<tt>(.+?)<\/tt>/, '<em>\1</em>')
|
70
|
+
s
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
classes = []
|
75
|
+
methods = {}
|
76
|
+
|
77
|
+
find("../rdoc-ri") { |file|
|
78
|
+
next unless file =~ /\.yaml$/
|
79
|
+
ri = YAML::load(File.new(file))
|
80
|
+
case ri
|
81
|
+
when RI::ClassDescription
|
82
|
+
classes << ri
|
83
|
+
when RI::MethodDescription
|
84
|
+
methods[ri.full_name] = ri
|
85
|
+
else
|
86
|
+
puts "Unknown Description: #{ri.inspect}"
|
87
|
+
end
|
88
|
+
}
|
89
|
+
|
90
|
+
classes.sort! { |a,b|
|
91
|
+
a.full_name <=> b.full_name
|
92
|
+
}
|
93
|
+
|
94
|
+
text = ''
|
95
|
+
classes.each { |klass|
|
96
|
+
text += "==#{klass.full_name}==\n\n"
|
97
|
+
text += "Inherited from '''#{klass.superclass}'''\n\n" if klass.superclass
|
98
|
+
text += wiki_format(klass.comment || [])
|
99
|
+
klass.attributes.each { |attribute|
|
100
|
+
text += "===#{klass.full_name}##{attribute.name} (#{attribute.rw})===\n\n"
|
101
|
+
text += wiki_format(attribute.comment || [])
|
102
|
+
text += "\n"
|
103
|
+
}
|
104
|
+
klass.class_methods.each { |methodname|
|
105
|
+
method = methods["#{klass.full_name}::#{methodname.name}"]
|
106
|
+
text += "===#{method.full_name}#{method.params}===\n\n"
|
107
|
+
text += wiki_format(method.comment || [])
|
108
|
+
text += "\n"
|
109
|
+
}
|
110
|
+
klass.instance_methods.each { |methodname|
|
111
|
+
method = methods["#{klass.full_name}##{methodname.name}"]
|
112
|
+
text += "===#{method.full_name}#{method.params}===\n\n"
|
113
|
+
text += wiki_format(method.comment || [])
|
114
|
+
text += "\n"
|
115
|
+
}
|
116
|
+
}
|
117
|
+
|
118
|
+
if false # Dry run?
|
119
|
+
puts text
|
120
|
+
exit
|
121
|
+
end
|
122
|
+
|
123
|
+
wiki, conf = MediaWiki.dotfile('rdoc to wiki')
|
124
|
+
article = wiki.article(conf['page'])
|
125
|
+
article.text = "=#{conf['title']}=\n\n" + text
|
126
|
+
article.submit("I can even document myself :-)")
|
@@ -0,0 +1,79 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
=begin
|
3
|
+
This file is part of Ruby-MediaWiki.
|
4
|
+
|
5
|
+
Ruby-MediaWiki is free software: you can redistribute it and/or
|
6
|
+
modify it under the terms of the GNU General Public License as
|
7
|
+
published by the Free Software Foundation, either version 3 of the
|
8
|
+
License, or (at your option) any later version.
|
9
|
+
|
10
|
+
Ruby-MediaWiki is distributed in the hope that it will be useful,
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
+
General Public License for more details.
|
14
|
+
|
15
|
+
You should have received a copy of the GNU General Public License
|
16
|
+
along with Ruby-MediaWiki. If not, see
|
17
|
+
<http://www.gnu.org/licenses/>.
|
18
|
+
=end
|
19
|
+
|
20
|
+
|
21
|
+
$:.unshift('../lib')
|
22
|
+
require 'mediawiki/dotfile'
|
23
|
+
|
24
|
+
wiki, conf = MediaWiki.dotfile('speed metal bot')
|
25
|
+
category_name = conf['category']
|
26
|
+
user_prefix = conf['user prefix']
|
27
|
+
template_name = conf['template']
|
28
|
+
|
29
|
+
category = wiki.category(category_name)
|
30
|
+
template = wiki.article("Template:#{template_name}")
|
31
|
+
|
32
|
+
puts "Category #{category_name}: #{category.articles.inspect}"
|
33
|
+
|
34
|
+
users = []
|
35
|
+
projects = []
|
36
|
+
category.articles.each { |name|
|
37
|
+
if name.index(user_prefix) and name.index('/').nil?
|
38
|
+
prefix, name = name.split(/:/, 2)
|
39
|
+
users << name
|
40
|
+
else
|
41
|
+
projects << name
|
42
|
+
end
|
43
|
+
}
|
44
|
+
|
45
|
+
### Construct template ###
|
46
|
+
newtemplate = "<div align=\"center\" style=\"border: 1px solid black; clear: right;\">\n" +
|
47
|
+
"<div style=\"float: left; width: 64px; height: 64px;>[[Bild:Speed metal coding 64x64.jpg|left]]</div>\n" +
|
48
|
+
"<div style=\"margin-left: 70px; background-color: #e64200; font-size: large; height: 1.5em;\">'''Rübÿ Spëëd Mëtäl Cödïng'''</div>\n" +
|
49
|
+
"<div style=\"margin-left: 70px;\">'''Coders:''' "
|
50
|
+
users.each_with_index { |user,i|
|
51
|
+
newtemplate += " | " if i > 0
|
52
|
+
newtemplate += "[[User:#{user}|#{user}]]"
|
53
|
+
}
|
54
|
+
|
55
|
+
newtemplate += "</div>\n" +
|
56
|
+
"<div style=\"margin-left: 70px;\">'''Projects:''' "
|
57
|
+
projects.each_with_index { |project,i|
|
58
|
+
newtemplate += " | " if i > 0
|
59
|
+
newtemplate += "[[#{project}]]"
|
60
|
+
}
|
61
|
+
newtemplate += "<br/></div>\n" +
|
62
|
+
"</div>\n"
|
63
|
+
|
64
|
+
### Submit template ###
|
65
|
+
if template.text != newtemplate
|
66
|
+
template.text = newtemplate
|
67
|
+
template.submit("Speed metal bot run", true)
|
68
|
+
end
|
69
|
+
|
70
|
+
### Let template be used by all in category ###
|
71
|
+
category.articles.each { |name|
|
72
|
+
article = wiki.article(name)
|
73
|
+
unless article.text.index("{{#{template_name}}}")
|
74
|
+
puts "#{article.name} is in category but doesn't use template"
|
75
|
+
article.text.gsub!(/\n+$/, '')
|
76
|
+
article.text += "\n\n\n\n{{#{template_name}}}"
|
77
|
+
article.submit("This page must use the #{template_name} template!!!111")
|
78
|
+
end
|
79
|
+
}
|
data/apps/wikicat.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
=begin
|
3
|
+
This file is part of Ruby-MediaWiki.
|
4
|
+
|
5
|
+
Ruby-MediaWiki is free software: you can redistribute it and/or
|
6
|
+
modify it under the terms of the GNU General Public License as
|
7
|
+
published by the Free Software Foundation, either version 3 of the
|
8
|
+
License, or (at your option) any later version.
|
9
|
+
|
10
|
+
Ruby-MediaWiki is distributed in the hope that it will be useful,
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
+
General Public License for more details.
|
14
|
+
|
15
|
+
You should have received a copy of the GNU General Public License
|
16
|
+
along with Ruby-MediaWiki. If not, see
|
17
|
+
<http://www.gnu.org/licenses/>.
|
18
|
+
=end
|
19
|
+
|
20
|
+
|
21
|
+
$:.unshift('../lib')
|
22
|
+
require 'mediawiki/dotfile'
|
23
|
+
|
24
|
+
if ARGV.size != 1
|
25
|
+
puts "Usage: #{$0} <Article name>"
|
26
|
+
exit
|
27
|
+
end
|
28
|
+
|
29
|
+
wiki = MediaWiki.dotfile
|
30
|
+
puts wiki.article(ARGV[0]).text
|
data/apps/wikipost.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
=begin
|
3
|
+
This file is part of Ruby-MediaWiki.
|
4
|
+
|
5
|
+
Ruby-MediaWiki is free software: you can redistribute it and/or
|
6
|
+
modify it under the terms of the GNU General Public License as
|
7
|
+
published by the Free Software Foundation, either version 3 of the
|
8
|
+
License, or (at your option) any later version.
|
9
|
+
|
10
|
+
Ruby-MediaWiki is distributed in the hope that it will be useful,
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
+
General Public License for more details.
|
14
|
+
|
15
|
+
You should have received a copy of the GNU General Public License
|
16
|
+
along with Ruby-MediaWiki. If not, see
|
17
|
+
<http://www.gnu.org/licenses/>.
|
18
|
+
=end
|
19
|
+
|
20
|
+
|
21
|
+
$:.unshift('../lib')
|
22
|
+
require 'mediawiki/dotfile'
|
23
|
+
|
24
|
+
if ARGV.size != 3
|
25
|
+
puts "Usage: #{$0} <Article name> <file> <comment>"
|
26
|
+
exit
|
27
|
+
end
|
28
|
+
|
29
|
+
wiki = MediaWiki.dotfile
|
30
|
+
a = wiki.article(ARGV[0])
|
31
|
+
a.text = File.new(ARGV[1]).readlines.to_s
|
32
|
+
a.submit(ARGV[2])
|
data/lib/mediawiki.rb
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
=begin
|
2
|
+
This file is part of Ruby-MediaWiki.
|
3
|
+
|
4
|
+
Ruby-MediaWiki is free software: you can redistribute it and/or
|
5
|
+
modify it under the terms of the GNU General Public License as
|
6
|
+
published by the Free Software Foundation, either version 3 of the
|
7
|
+
License, or (at your option) any later version.
|
8
|
+
|
9
|
+
Ruby-MediaWiki is distributed in the hope that it will be useful,
|
10
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
+
General Public License for more details.
|
13
|
+
|
14
|
+
You should have received a copy of the GNU General Public License
|
15
|
+
along with Ruby-MediaWiki. If not, see
|
16
|
+
<http://www.gnu.org/licenses/>.
|
17
|
+
=end
|
18
|
+
|
19
|
+
|
20
|
+
require 'uri'
|
21
|
+
require 'logger'
|
22
|
+
|
23
|
+
|
24
|
+
# Logger is required by article.rb
|
25
|
+
module MediaWiki
|
26
|
+
def self.logger
|
27
|
+
if defined? @@logger
|
28
|
+
@@logger
|
29
|
+
else
|
30
|
+
@@logger = Logger.new(STDERR)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
require 'mediawiki/article'
|
36
|
+
require 'mediawiki/specialpage'
|
37
|
+
require 'mediawiki/category'
|
38
|
+
require 'mediawiki/minibrowser'
|
39
|
+
|
40
|
+
##
|
41
|
+
# =Ruby-MediaWiki - manipulate MediaWiki pages from Ruby.
|
42
|
+
#
|
43
|
+
# Please note that documents spit out by MediaWiki *must* be valid
|
44
|
+
# XHTML (or XML)!
|
45
|
+
#
|
46
|
+
# You may not want to use MediaWiki::Wiki directly but let MediaWiki.dotfile
|
47
|
+
# create your instance. This gives you the power of the dotfile
|
48
|
+
# infrastructure. See sample apps and <tt>mediawikirc.sample</tt>.
|
49
|
+
module MediaWiki
|
50
|
+
##
|
51
|
+
# There's no need for any language attribute, the "Special:" prefix
|
52
|
+
# works in any MediaWiki, regardless of localization settings.
|
53
|
+
class Wiki
|
54
|
+
##
|
55
|
+
# The MiniBrowser instance used by this Wiki.
|
56
|
+
# This must be readable as it's used by Article and Category
|
57
|
+
# to fetch themselves.
|
58
|
+
attr_reader :browser
|
59
|
+
|
60
|
+
##
|
61
|
+
# The URL-Path to index.php (without index.php) as given
|
62
|
+
# to Wiki#initialize
|
63
|
+
attr_reader :url
|
64
|
+
|
65
|
+
##
|
66
|
+
# Initialize a new Wiki instance.
|
67
|
+
# url:: [String] URL-Path to index.php (without index.php), may containt <tt>user:password</tt> combination.
|
68
|
+
# user:: [String] If not nil, log in with that MediaWiki username (see Wiki#login)
|
69
|
+
# password:: [String] If not nil, log in with that MediaWiki password (see Wiki#login)
|
70
|
+
# loglevel:: [Integer] Loglevel, default is to log all messages >= Logger::WARN = 2
|
71
|
+
def initialize(url, user = nil, password = nil, loglevel = Logger::WARN)
|
72
|
+
if ENV['MEDIAWIKI_DEBUG']
|
73
|
+
MediaWiki::logger.level = Logger::DEBUG
|
74
|
+
else
|
75
|
+
MediaWiki::logger.level = loglevel
|
76
|
+
end
|
77
|
+
|
78
|
+
@url = URI.parse( url.match(/\/$/) ? url : url + '/' )
|
79
|
+
@browser = MiniBrowser.new(@url)
|
80
|
+
|
81
|
+
login( user, password ) if user and password
|
82
|
+
end
|
83
|
+
|
84
|
+
##
|
85
|
+
# Log in into MediaWiki
|
86
|
+
#
|
87
|
+
# This is *not* HTTP authentication
|
88
|
+
# (put HTTP-Auth into [url] of Wiki#initialize!)
|
89
|
+
# user:: [String] MediaWiki username
|
90
|
+
# password:: [String] MediaWiki password
|
91
|
+
#
|
92
|
+
# May raise an exception if cannot authenticate
|
93
|
+
def login( username, password )
|
94
|
+
data = {'wpName' => username, 'wpPassword' => password, 'wpLoginattempt' => 'Log in'}
|
95
|
+
data = @browser.post_content( @url.path + 'index.php?title=Special:Userlogin&action=submitlogin', data )
|
96
|
+
if data =~ /<p class='error'>/
|
97
|
+
raise "Unable to authenticate as #{username}"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
##
|
102
|
+
# Return a new Category instance with given name,
|
103
|
+
# will be constructed with [self] (for MiniBrowser usage)
|
104
|
+
# name:: [String] Category name (to be prepended with "Category:")
|
105
|
+
def category(name)
|
106
|
+
Category.new(self, name)
|
107
|
+
end
|
108
|
+
|
109
|
+
##
|
110
|
+
# Return a new Article instance with given name,
|
111
|
+
# will be constructed with [self] (for MiniBrowser usage)
|
112
|
+
# name:: [String] Article name
|
113
|
+
# section:: [Fixnum] Optional section number
|
114
|
+
def article(name, section = nil)
|
115
|
+
Article.new(self, name, section)
|
116
|
+
end
|
117
|
+
|
118
|
+
##
|
119
|
+
# Retrieve all namespaces and their IDs, which could be used for Wiki#allpages
|
120
|
+
# result:: [Hash] String => Fixnum
|
121
|
+
def namespace_ids
|
122
|
+
ids = {}
|
123
|
+
SpecialPage.new( self, 'Special:Allpages', nil, false ).xhtml.each_element('//select[@name=\'namespace\']/option') do | o |
|
124
|
+
ids[o.text] = o.attributes['value'].to_i
|
125
|
+
end
|
126
|
+
ids
|
127
|
+
end
|
128
|
+
|
129
|
+
##
|
130
|
+
# Returns the pages listed on "Special:Allpages"
|
131
|
+
#
|
132
|
+
# TODO: Handle big wikis with chunked Special:Allpages
|
133
|
+
# namespace_id:: Optional namespace for article index (see Wiki#namespace_ids to retrieve id)
|
134
|
+
# result:: [Array] of [String] Articlenames
|
135
|
+
def allpages(namespace_id=nil)
|
136
|
+
# Dirty, but works
|
137
|
+
article_name = 'Special:Allpages'
|
138
|
+
article_name += "&namespace=#{namespace_id}" if namespace_id
|
139
|
+
|
140
|
+
pages = []
|
141
|
+
SpecialPage.new( self, article_name, nil, false ).xhtml.each_element('table[2]/tr/td/a') do | a |
|
142
|
+
pages.push( a.text )
|
143
|
+
end
|
144
|
+
pages
|
145
|
+
end
|
146
|
+
|
147
|
+
##
|
148
|
+
# Construct the URL to a specific article
|
149
|
+
#
|
150
|
+
# Uses the [url] the Wiki instance was constructed with,
|
151
|
+
# appends "index.php", the name parameter and, optionally,
|
152
|
+
# the section.
|
153
|
+
#
|
154
|
+
# Often called by Article, Category, ...
|
155
|
+
# name:: [String] Article name
|
156
|
+
# section:: [Fixnum] Optional section number
|
157
|
+
def article_url(name, section = nil)
|
158
|
+
"#{@url.path}index.php?title=#{CGI::escape(name.gsub(' ', '_'))}#{section ? "§ion=#{CGI::escape(section.to_s)}" : ''}"
|
159
|
+
end
|
160
|
+
|
161
|
+
def full_article_url(name, section=nil)
|
162
|
+
uri = @url.dup
|
163
|
+
uri.path, uri.query = article_url(name, section).split(/\?/, 2)
|
164
|
+
uri.to_s
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
|