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