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
data/README
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
Ruby-MediaWiki 0.1
|
2
|
+
------------------
|
3
|
+
------------------
|
4
|
+
|
5
|
+
A library to retrieve and modify content managed by the popular
|
6
|
+
MediaWiki software.
|
7
|
+
|
8
|
+
|
9
|
+
AUTHORS
|
10
|
+
=======
|
11
|
+
|
12
|
+
Sven Klemm
|
13
|
+
Stephan Maka
|
14
|
+
Mike Gerber
|
15
|
+
Michael Witrant
|
16
|
+
|
17
|
+
(patches go to stephan@spaceboyz.net)
|
18
|
+
|
19
|
+
|
20
|
+
LICENSE
|
21
|
+
=======
|
22
|
+
|
23
|
+
Distributed under the GNU General Public License version 3, see the
|
24
|
+
COPYING file.
|
25
|
+
|
26
|
+
|
27
|
+
USAGE
|
28
|
+
=====
|
29
|
+
|
30
|
+
Ruby-MediaWiki relies on a configuration file with URLs, user account
|
31
|
+
details and per-agent settings in YAML. The sample mediawikirc.sample
|
32
|
+
should be rather self-explanatory.
|
33
|
+
|
34
|
+
There are various environment variables for easy usage:
|
35
|
+
|
36
|
+
* MEDIAWIKI_RC - location of the configuration file
|
37
|
+
(default: ~/.mediawikirc)
|
38
|
+
* MEDIAWIKI_WIKI - which section of the configuration file to use
|
39
|
+
(default is the one set in the `default' key)
|
40
|
+
* MEDIAWIKI_DEBUG - if set, set the log level to DEBUG
|
41
|
+
|
42
|
+
Quick start:
|
43
|
+
------------
|
44
|
+
ruby-mediawiki % export RUBYLIB=`pwd`/lib
|
45
|
+
ruby-mediawiki % export MEDIAWIKI_RC=mediawikirc.sample
|
46
|
+
ruby-mediawiki % export MEDIAWIKI_WIKI=wpde
|
47
|
+
ruby-mediawiki % ruby apps/wikicat.rb Arschgeweih
|
48
|
+
|
49
|
+
|
50
|
+
RESOURCES
|
51
|
+
=========
|
52
|
+
|
53
|
+
German description:
|
54
|
+
https://wiki.c3d2.de/Ruby-MediaWiki
|
55
|
+
|
56
|
+
RDoc to Wiki:
|
57
|
+
https://wiki.c3d2.de/Ruby-MediaWiki/Documentation
|
58
|
+
|
59
|
+
SVN repository:
|
60
|
+
svn://svn.c3d2.de/ruby-mediawiki/trunk
|
@@ -0,0 +1,178 @@
|
|
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
|
+
$:.unshift('../lib')
|
21
|
+
require 'postgres'
|
22
|
+
require 'yaml'
|
23
|
+
require 'mediawiki'
|
24
|
+
require 'mediawiki/dotfile'
|
25
|
+
require 'mediawiki/table'
|
26
|
+
|
27
|
+
class SQL_Parser
|
28
|
+
# returns a hash with the tablename as key
|
29
|
+
def self.parse( sql )
|
30
|
+
tables = {}
|
31
|
+
current = nil
|
32
|
+
sql.each_line do | line |
|
33
|
+
line.gsub!(/,$/, '')
|
34
|
+
next if line.match(/^ *$/) or line.match(/BEGIN/) or line.match(/COMMIT/)
|
35
|
+
if match = line.match(/CREATE TABLE ([a-z_]+) *\(/)
|
36
|
+
current = match[1]
|
37
|
+
tables[match[1]] = {:field_names => [], :field => {}}
|
38
|
+
elsif line.match(/\) *(WITHOUT OIDS)?;/)
|
39
|
+
current = nil
|
40
|
+
elsif current
|
41
|
+
if match = line.match(/^ +([a-z_0-9]+) +(.*)$/)
|
42
|
+
tables[current][:field_names].push( match[1] )
|
43
|
+
tables[current][:field][match[1]] = match[2].gsub(/(NOT NULL|UNIQUE|DEFAULT|CHECK).*/, '')
|
44
|
+
elsif match = line.match(/^ *(FOREIGN KEY|PRIMARY KEY|CHECK|UNIQUE)/)
|
45
|
+
else
|
46
|
+
puts "unparsed line: #{line}"
|
47
|
+
end
|
48
|
+
else
|
49
|
+
puts "unrecognized line: #{line.inspect}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
tables
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# reads and writes comment to/from the database
|
57
|
+
class SQL_Comments
|
58
|
+
|
59
|
+
# setup database connection
|
60
|
+
def initialize( config )
|
61
|
+
@connection = PGconn.connect( config['host'], config['port'], nil, nil, config['database'], config['username'], config['password'])
|
62
|
+
end
|
63
|
+
|
64
|
+
def escape( data )
|
65
|
+
data.gsub("\\",'').gsub("'", "''")
|
66
|
+
end
|
67
|
+
|
68
|
+
def escape_ident( data )
|
69
|
+
data.gsub("\\",'').gsub('"', '')
|
70
|
+
end
|
71
|
+
|
72
|
+
def get_table_description( table )
|
73
|
+
@connection.exec("SELECT description
|
74
|
+
FROM pg_description
|
75
|
+
INNER JOIN pg_class ON ( pg_class.oid = pg_description.objoid )
|
76
|
+
WHERE pg_description.objsubid = 0 AND
|
77
|
+
pg_class.relname = '#{escape(table)}';"
|
78
|
+
).entries.flatten[0]
|
79
|
+
end
|
80
|
+
|
81
|
+
def set_table_description( table, text )
|
82
|
+
@connection.exec("COMMENT ON TABLE \"#{escape_ident(table)}\" IS #{text.to_s == "" ? 'NULL' : "'#{escape(text.strip)}'"};")
|
83
|
+
end
|
84
|
+
|
85
|
+
def set_column_description( table, column, text )
|
86
|
+
@connection.exec("COMMENT ON COLUMN \"#{escape_ident(table)}\".\"#{escape_ident(column)}\" IS #{text.to_s == "" ? 'NULL' : "'#{escape(text.strip)}'"};")
|
87
|
+
end
|
88
|
+
|
89
|
+
def get_column_description( table, column )
|
90
|
+
@connection.exec("SELECT description
|
91
|
+
FROM pg_description
|
92
|
+
INNER JOIN pg_class ON ( pg_class.oid = pg_description.objoid )
|
93
|
+
INNER JOIN pg_attribute ON
|
94
|
+
( pg_attribute.attrelid = pg_description.objoid AND
|
95
|
+
pg_description.objsubid = pg_attribute.attnum )
|
96
|
+
WHERE pg_class.relname = '#{escape(table)}' AND
|
97
|
+
pg_attribute.attname = '#{escape(column)}'"
|
98
|
+
).entries.flatten[0]
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
class Comment_Synchronizer
|
105
|
+
|
106
|
+
def initialize( wiki, config, sql)
|
107
|
+
@wiki = MediaWiki.dotfile
|
108
|
+
@sql = SQL_Comments.new(config)
|
109
|
+
@tables = SQL_Parser.parse( sql )
|
110
|
+
end
|
111
|
+
|
112
|
+
# update wiki with content from database
|
113
|
+
def update_wiki
|
114
|
+
# generate index page
|
115
|
+
page = @wiki.article('Database/Tables')
|
116
|
+
page.text = "This is a list of all tables used in pentabarf\n\n"
|
117
|
+
@tables.keys.sort.each do | table |
|
118
|
+
page.text += "*[[Database/Tables/#{table.capitalize}|#{table}]]\n"
|
119
|
+
end
|
120
|
+
page.text += "[[Category:Database]]"
|
121
|
+
page.submit('generating list of tables')
|
122
|
+
|
123
|
+
# create one page for each table
|
124
|
+
@tables.keys.sort.each do | table |
|
125
|
+
page = @wiki.article("Database/Tables/#{table.capitalize}")
|
126
|
+
|
127
|
+
# create wiki page
|
128
|
+
page.text = @sql.get_table_description( table ).to_s + "\n"
|
129
|
+
# table header
|
130
|
+
page.text += "==Columns==\n"
|
131
|
+
page.text += "[[Database/Tables|<< List of Tables]]\n"
|
132
|
+
t = MediaWiki::Table.new
|
133
|
+
t.style = 'border="1" cellspacing="0" cellpadding="3" style="border-collapse: collapse;"'
|
134
|
+
t.header_style = 'bgcolor="lightblue"'
|
135
|
+
t.header = ['field name', 'datatype', 'description']
|
136
|
+
|
137
|
+
@tables[table][:field_names].each do | field_name |
|
138
|
+
t.data.push([field_name, @tables[table][:field][field_name], @sql.get_column_description( table, field_name)])
|
139
|
+
end
|
140
|
+
page.text += t.text
|
141
|
+
page.text += "\n[[Category:Database]]\n"
|
142
|
+
page.submit("updating page for table #{table}")
|
143
|
+
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# write documentation from wiki into database
|
148
|
+
def update_database
|
149
|
+
# fetch content from all wiki pages and put it in the database
|
150
|
+
@tables.keys.sort.each do | table |
|
151
|
+
|
152
|
+
# get the section containing the general description
|
153
|
+
page = @wiki.article("Database/Tables/#{table.capitalize}", 0)
|
154
|
+
@sql.set_table_description( table, page.text )
|
155
|
+
|
156
|
+
# get the section containing the column table
|
157
|
+
page = @wiki.article("Database/Tables/#{table.capitalize}", 1)
|
158
|
+
state = :description
|
159
|
+
column = ''
|
160
|
+
# parse wiki text
|
161
|
+
MediaWiki::Table.parse( page.text ).each do | column |
|
162
|
+
next if column[0] == 'field name' # this is the header column
|
163
|
+
@sql.set_column_description( table, column[0], column[2] )
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
|
169
|
+
end
|
170
|
+
|
171
|
+
db_config = YAML.load_file('db_config.yml')['development']
|
172
|
+
#db_config = {'host' => 'localhost', 'port' => 5432, 'database' => 'pentabarf', 'username' => 'joe', 'password' => 'secret'}
|
173
|
+
sql = `svnlook cat /var/subversion/pentabarf /trunk/sql/tables.sql`
|
174
|
+
|
175
|
+
bot = Comment_Synchronizer.new( :pentabarf, db_config, sql )
|
176
|
+
bot.update_database
|
177
|
+
bot.update_wiki
|
178
|
+
|
@@ -0,0 +1,185 @@
|
|
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
|
+
require 'yaml'
|
21
|
+
$:.unshift('../lib')
|
22
|
+
require 'mediawiki/dotfile'
|
23
|
+
|
24
|
+
include MediaWiki
|
25
|
+
|
26
|
+
class DateUser
|
27
|
+
attr_reader :name
|
28
|
+
|
29
|
+
def initialize(name, hsh)
|
30
|
+
@name = name
|
31
|
+
@hsh = hsh
|
32
|
+
end
|
33
|
+
|
34
|
+
def dates
|
35
|
+
@hsh.keys
|
36
|
+
end
|
37
|
+
|
38
|
+
def day(d)
|
39
|
+
@hsh[d]
|
40
|
+
end
|
41
|
+
|
42
|
+
def day_class(d)
|
43
|
+
if day(d) == nil
|
44
|
+
nil
|
45
|
+
elsif day(d) =~ /^[yj]/i
|
46
|
+
true
|
47
|
+
elsif day(d) =~ /^n/i
|
48
|
+
false
|
49
|
+
else
|
50
|
+
""
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def day_style(d)
|
55
|
+
case day_class(d)
|
56
|
+
when nil then ""
|
57
|
+
when true then 'bgcolor="#7fff7f"'
|
58
|
+
when false then 'bgcolor="#ff7f7f"'
|
59
|
+
else 'bgcolor="#bfbfbf"'
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class DateData
|
65
|
+
def initialize(yaml)
|
66
|
+
@users = []
|
67
|
+
@error = nil
|
68
|
+
begin
|
69
|
+
YAML::load(yaml).each { |user,dates|
|
70
|
+
@users << DateUser.new(user, dates)
|
71
|
+
}
|
72
|
+
rescue Exception => e
|
73
|
+
puts "#{e.class}: #{e}\n#{e.backtrace.join("\n")}"
|
74
|
+
@error = e.to_s
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def table
|
79
|
+
return @error if @error
|
80
|
+
|
81
|
+
s = ''
|
82
|
+
|
83
|
+
##
|
84
|
+
# Collect dates
|
85
|
+
##
|
86
|
+
dates = []
|
87
|
+
dates_yes = {}
|
88
|
+
@users.each { |user| dates += user.dates }
|
89
|
+
|
90
|
+
##
|
91
|
+
# Sort dates
|
92
|
+
##
|
93
|
+
dates.uniq!
|
94
|
+
dates.sort! { |a,b|
|
95
|
+
if a =~ /^(\d+)\.(\d+)\./
|
96
|
+
a_day = $1
|
97
|
+
a_month = $2
|
98
|
+
if b =~ /^(\d+)\.(\d+)\./
|
99
|
+
b_day = $1
|
100
|
+
b_month = $2
|
101
|
+
if a_month.to_i == b_month.to_i
|
102
|
+
a_day.to_i <=> b_day.to_i
|
103
|
+
else
|
104
|
+
a_month.to_i <=> b_month.to_i
|
105
|
+
end
|
106
|
+
else
|
107
|
+
a <=> b
|
108
|
+
end
|
109
|
+
else
|
110
|
+
a <=> b
|
111
|
+
end
|
112
|
+
}
|
113
|
+
|
114
|
+
##
|
115
|
+
# Construct header
|
116
|
+
##
|
117
|
+
s += "{| border=\"1\" cellpadding=\"2\" cellspacing=\"0\" style=\"border-collapse:collapse;\"\n|-\n! \n"
|
118
|
+
dates.each { |date|
|
119
|
+
s += "!#{date}\n"
|
120
|
+
dates_yes[date] = 0
|
121
|
+
}
|
122
|
+
|
123
|
+
##
|
124
|
+
# Construct rows
|
125
|
+
##
|
126
|
+
@users.each { |user|
|
127
|
+
s += "|-\n|[[User:#{user.name}|#{user.name}]]\n"
|
128
|
+
dates.each { |date|
|
129
|
+
s += "| #{user.day_style(date)} | #{user.day(date)}\n"
|
130
|
+
dates_yes[date] += 1 if user.day_class(date) == true
|
131
|
+
}
|
132
|
+
}
|
133
|
+
|
134
|
+
##
|
135
|
+
# Build summary
|
136
|
+
##
|
137
|
+
s += "|-\n|'''sum(ja)'''\n"
|
138
|
+
dates.each { |date|
|
139
|
+
s += "|'''#{dates_yes[date]}'''\n"
|
140
|
+
}
|
141
|
+
s += "|}"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
|
147
|
+
wiki, conf = MediaWiki.dotfile('date determinator')
|
148
|
+
conf['pages'].each { |name|
|
149
|
+
page = wiki.article(name)
|
150
|
+
|
151
|
+
datasets = {}
|
152
|
+
current_data_name = nil
|
153
|
+
current_data_yaml = ''
|
154
|
+
page.text.split(/\n/).each { |line|
|
155
|
+
if line =~ /BEGIN DATA "(.+?)"/
|
156
|
+
current_data_name = $1
|
157
|
+
current_data_yaml = ''
|
158
|
+
elsif line =~ /END DATA/ and current_data_name
|
159
|
+
datasets[current_data_name] = DateData.new(current_data_yaml)
|
160
|
+
current_data_name = nil
|
161
|
+
current_data_yaml = ''
|
162
|
+
elsif current_data_name
|
163
|
+
current_data_yaml += "#{line}\n"
|
164
|
+
end
|
165
|
+
}
|
166
|
+
|
167
|
+
|
168
|
+
text_old = page.text.dup
|
169
|
+
|
170
|
+
signature = /(<!-- BEGIN TABLE ")(.+?)(" -->)(.+?)(<!-- END TABLE -->)/m
|
171
|
+
page.text.gsub!(signature) { |part|
|
172
|
+
begin1,name,begin2,obsolete,end1 = part.match(signature).to_a[1..-1]
|
173
|
+
table = datasets[name] ? datasets[name].table : "DATA #{name} not found!"
|
174
|
+
p table
|
175
|
+
"#{begin1}#{name}#{begin2}\n#{table}\n#{end1}"
|
176
|
+
}
|
177
|
+
puts page.text
|
178
|
+
|
179
|
+
if page.text != text_old
|
180
|
+
puts "submitting"
|
181
|
+
page.submit('Date Determinator run')
|
182
|
+
end
|
183
|
+
|
184
|
+
puts "done"
|
185
|
+
}
|
@@ -0,0 +1,58 @@
|
|
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
|
+
$:.unshift('../lib')
|
21
|
+
|
22
|
+
require 'mediawiki/dotfile'
|
23
|
+
require 'mediawiki/table'
|
24
|
+
require 'momomoto/momomoto'
|
25
|
+
require 'momomoto/tables'
|
26
|
+
require 'momomoto/bot_login'
|
27
|
+
|
28
|
+
ENV['MEDIAWIKI_WIKI'] = 'wikipedia_de'
|
29
|
+
|
30
|
+
db_config = YAML.load_file('db_config.yml')['development']
|
31
|
+
Momomoto::Base.connect(db_config)
|
32
|
+
Momomoto::Bot_login.authorize('ui_tagger')
|
33
|
+
|
34
|
+
wiki = MediaWiki.dotfile
|
35
|
+
page = wiki.article('ISO 639', 3)
|
36
|
+
t = MediaWiki::Table.parse( page.text )
|
37
|
+
|
38
|
+
t.shift
|
39
|
+
|
40
|
+
t.each do | row |
|
41
|
+
row[2].split( '/' ).each do | iso_code |
|
42
|
+
id = Momomoto::Language.find({:iso_639_code=>iso_code})
|
43
|
+
next unless id.length == 1
|
44
|
+
match = row[0].match /\[\[(.*\|)?(.+)\]\]/
|
45
|
+
name = match[2]
|
46
|
+
|
47
|
+
local = Momomoto::Language_localized.find({:language_id=>id.language_id,:translated_id=>144})
|
48
|
+
if local.length == 0 && name != ''
|
49
|
+
local.create
|
50
|
+
local.language_id = id.language_id
|
51
|
+
local.translated_id = 144
|
52
|
+
local.name = name
|
53
|
+
local.write
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|