ruby-mediawiki 0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+