ruby-mediawiki 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/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
|
+
|