require 'libhttpclient' require 'mountycreds' class Mounty def self.lastinstance @@lastinstance end def self.play @@lastinstance = Mounty.new @@lastinstance.login @@lastinstance end def self.play_noact @@lastinstance = Mounty.new @@lastinstance.login_noact @@lastinstance end attr_reader :http_client def d(*args) puts args if $VERBOSE end SITE_URL = 'http://games.mountyhall.com/' def initialize @http_client = HttpClient.new(SITE_URL) @status = {} @caracs = {} @comps = {} @sorts = {} @caracs_bm = {} @http_ctx = {} end class SessionExpired < RuntimeError ; end def get(url) ret = @http_client.get(url, (rand(8) == 0) ? (1+rand(40)) : (rand(6))) raise SessionExpired if @http_client.cur_url =~ /SessionExpired/i case url when /play_menu.php$/i @shortcuts = ret.parse('a').map { |e| $1.to_i if e['href'] =~ /ToDo=(\d+)&/ }.compact save_ctx :menu when /play_action.php$/i save_ctx :action end hst = @http_client.status_save begin ret.parse('frame').each { |e| @http_client.status_restore hst @http_client.fetch_next_now get e['src'] } rescue ensure @http_client.status_restore hst end ret end def post(url, values) @http_client.post(url, values, (rand(4) == 1) ? (3+rand(15)) : rand(4), (rand(5) == 1) ? (3+rand(25)) : rand(4)) end def save_ctx(c) @http_ctx[c] = @http_client.status_save end def set_ctx(c) if not @http_ctx[c] puts "no ctx #{c} ??", @http_client.history, caller return end @http_client.status_restore @http_ctx[c] end def show(*a) puts get_text(*a), '-' end def get_text(p = nil, onlyform = true, onlystr = true) p ||= @http_client.curpage txt = p.get_text(onlyform, onlystr).reject { |l| l =~ /\[refresh\] \[logout\]|\[contact.*\[heure serveur.*\[page g|- il y a actuellement .* tr.*lls connect/i }.join.chomp if txt == '' and onlyform txt = get_text p, false, onlystr end txt end # cree un tableau de tableaux # chaque tableau represente une ligne d'une # les changements de sont representes par un tableau vide def show_table_content(p=nil, verbose=true) p ||= @http_client.curpage show = showonly = false arr = [] p.parse.each { |e| case e.type when 'table' # separation de tables arr << [] if arr.last and not arr.last.empty? and arr.last != [[]] when 'tr' # nouveau tableau case e['class'] when 'mh_tdpage' arr << [] show = true when 'mh_tdtitre' arr << [] show = showonly = true else if show if showonly s = arr.pop.join ' ' else s = arr.last.join ' ' end puts s if verbose show = showonly = false end end when '/tr' # fin du tableau, affichage if show if showonly s = arr.pop.join ' ' else s = arr.last.join ' ' end puts s if not showonly or not s.include? 'Heure Serveur' if verbose show = showonly = false end when 'td' # nouvel element du tableau : # cree un array ou on entasse les Strings arr.last << [] if show when '/td' # met une chaine dans le tableau du arr.last << arr.last.pop.join(' ') if show when 'String' arr.last.last << e['content'] if show end } arr.pop if arr.last and arr.last.empty? arr end def get_confirm(p = @http_client.curpage) if not pd = @http_client.post_allowed[0] puts 'already used?' elsif pd.method == 'post' post pd.url, pd.vars else get HttpServer.get_form_url(pd.url, pd.vars) end end attr_accessor :curlogin def refresh profil get '/mountyhall/Play.php' show get_confirm profil nz = @http_client.cache['/mountyhall/MH_Play/Play_news.php'] puts get_text(nz, false).grep(/essagerie/) show_table_content nz puts self end def login_noact login false end def activate set_ctx :action get 'Activate_DLA.php' show false get_confirm show false profil self end attr_reader :unreadmsg def login(act = true, resumeonly=false) if not curlogin lg, ps, psr = mountycreds @curlogin = lg end @@lastinstance = self @unreadmsg = 0 @cookiefile = '.mounty.cookie.' << @curlogin if File.exist?(@cookiefile) puts 'reuse cookie' @http_client.loadcookies(@cookiefile) @http_client.get_url_allowed << '/mountyhall/MH_Play/Play.php' begin get '/mountyhall/MH_Play/Play.php' profil return self rescue SessionExpired, SystemCallError puts 'session expired' File.unlink @cookiefile end get '/mountyhall/MH_Play/PlayStart.php' else get '/' if not @http_client.cur_url.to_s.include? '/mountyhall/MH_Play/PlayStart.php' end return if resumeonly d 'logging in' post('/mountyhall/MH_Play/PlayStart.php', {'as_Login' => lg, 'as_Pwd' => ps, 'ai_design' => '20', 'ab_activation' => (act ? '1' : '0'), 'as_Action' => 'Entrer dans le Monde Souterrain'}) @http_client.savecookies(@cookiefile) txt = get_text.to_a.reject { |l| l.chomp.empty? } puts txt if txt =~ /Vous avez .* TU./ puts '', 'OH SHI-', '' logout rescue nil return login(act, resumeonly) end get_confirm or puts("venin kill ?", txt.inspect) profil nz = @http_client.cache['/mountyhall/MH_Play/Play_news.php'] iline = get_text(nz, false).grep(/essagerie/).first puts iline @unreadmsg = iline[/\d+ non lu/].to_i show_table_content nz puts self end def logout d 'logout' profil get '/mountyhall/Logout.php' File.unlink @cookiefile rescue nil end def menu_get(*a) return @http_client.curpage if a.length == 1 and a.first == @http_client.cur_url set_ctx :menu get(*a) end def use_action(n, h=actions(false)) if @shortcuts and @shortcuts.include? n return menu_get("/mountyhall/MH_Play/Play_action.php?ai_ToDo=#{n}&as_Action=ACTION!") end n = n.to_s raise "invalid action #{n} not in #{h.inspect}" unless h[n] set_ctx :action get HttpServer.get_form_url('/mountyhall/MH_Play/Play_action.php', [['x', rand(40)], ['y', rand(20)], ['as_Action', 'ACTION !!'], ['as_SelectName', h[n]], ['as_Action2', ''], ['ai_ToDo', n]]) end def toggle_shortcut(n, h=actions(false)) set_ctx :action h.values.each { |v| v.sub!(/^(  )([^ ])/, '\1 \2') } # fix sort != comp n = n.to_s get HttpServer.get_form_url('/mountyhall/MH_Play/Play_action.php', [['as_Action', 'ACTION !!'],['as_SelectName', h[n]],['as_Action2', 'Shortcuts'],['ai_ToDo', n]]) end def actions(verbose=true) p = @http_client.cache['/mountyhall/MH_Play/Play_action.php'] acts = {} idx = nil p.parse.each { |e| case e.type when 'optgroup' puts '', e['label'] if verbose when 'option' idx = e['value'] unless e['value'].empty? print idx.ljust(4) if idx and verbose when 'String' acts[idx] = e['content'] if idx idx = nil puts e['content'] if verbose end } acts end end