Xmotoctl
xmotoctl.rb
Dient dem Anzeigen und Validieren aller pending Highscores in einem Privaten Raum. Benötigt Ruby-MediaWiki.
#!/usr/bin/env ruby $: << 'ruby-mediawiki/lib/' require 'mediawiki/minibrowser' require 'htree' require 'rexml/document' class REXML::Element def first_element(s) each_element(s) { |e| return e } nil end end class HTTPDocument def initialize(url, browser=MediaWiki::MiniBrowser.new(URI::parse(url))) @url = url @browser = browser end def perform_request puts "Performing GET request" @body = @browser.get_content(@url) end def body perform_request unless @body @body end def html @html = HTree(body).to_rexml unless @html @html end end class HTTPPostDocument < HTTPDocument def initialize(url, params) @params = params super(url) end def perform_request puts "Performing POST request" @body = @browser.post_content(@url, @params) end end class Login < HTTPPostDocument def initialize(id, username, password) super("http://xmoto.free.fr/index.php", {:page=>:rooms, :action=>:change, :id_room=>id, :login=>username, :password=>password}) error = nil html.each_element('//div[@class=\'message_erreur\']') { |div| error = div.text } raise error if error end def highscoresvalidation HighscoresValidation.new(@browser) end end class HighscoresValidation < HTTPDocument def initialize(browser) super("http://xmoto.free.fr/index.php?page=highscoresvalidation", browser) end def table html.first_element('//table[@class=\'admin_data\']') end def get_columns res = [] table.each_element('tr[1]/th') { |th| res << th.text } res end def columns @columns = get_columns unless @columns @columns end def get_highscores res = [] table.each_element('tr[starts-with(@class, \'admin_data_line\')]') { |tr| i = 0 row = {} tr.each_element('td[@class=\'admin_data_multiple\']') { |td| row[columns[i]] = td.text.strip if td.text i += 1 } res << row } res end def highscores @highscores = get_highscores unless @highscores @highscores end def dump_highscores column_widths = {} columns.each do |column| width = column.size highscores.each { |h| width = h[column].size if (h[column]||'').size > width } column_widths[column] = width end puts columns.collect { |c| c.center(column_widths[c]) }.join('|') puts columns.collect { |c| '-' * column_widths[c] }.join('+') highscores.each do |h| puts columns.collect { |c| value = h[c] || '' value.ljust(column_widths[c]) }.join('|') end end def highscore_actions(id) res = nil # TODO: Replace contains() table.each_element('tr[starts-with(@class, \'admin_data_line\') and contains(td[1], '+id+')]') { |tr| res = {} tr.each_element('td[@class=\'admin_data_multiple\']/ul[@class=\'admin_submenu_actions\']/li/a') { |a| res[a.attributes['title']] = a.attributes['href'] } } res end def validate(id) actions = highscore_actions(id) if actions['validate'] @browser.get_content('/' + actions['validate']) else raise 'No validate action available' end end end if ARGV.size < 3 puts "Usage: #{$0} <room id> <username> <password> [validateall]" exit! end room_id, username, password = ARGV.shift, ARGV.shift, ARGV.shift l = Login.new(room_id, username, password) h = l.highscoresvalidation h.dump_highscores if ARGV.first == 'validateall' h.highscores.each { |h1| id = h1['Id'] puts "Validating #{id}..." begin h.validate(id) rescue Exception => e puts "Error: #{e}" end } end