require 'libhttpclient' require 'libdemcreds' if File.exists?('libdemcreds.rb') class CasePers attr_accessor :mat, :name, :mdj, :race def initialize(mat, name, mdj, race) @mat, @name, @mdj, @race = mat, name, mdj, race end def inspect "#{mat}: #{name} (#{race}) \"#{mdj}\"" end end class Case attr_accessor :x, :y, :mv, :pers def initialize(x, y, mv=1) @x, @y, @mv = x, y, mv end def inspect "(#@x, #@y), #@mv mv, #{@pers.inspect}" end end class Vue attr_reader :ys, :xmin, :xmax, :ymin, :ymax def initialize @ys = Array.new @xmin, @xmax = 800, 0 @ymin, @ymax = 600, 0 end def [](x, y) t = @ys[y] t[x] if t end def add(c) @ymin = c.y if c.y < @ymin @ymax = c.y if c.y > @ymax @xmin = c.x if c.x < @xmin @xmax = c.x if c.x > @xmax (@ys[c.y] ||= [])[c.x] = c end end class Perso attr_reader :idx attr_accessor :name, :race, :lvl, :px, :pi, :pv, :pvmax, :mv, :mvmax attr_accessor :pp, :ppmax, :natq, :natqmax, :deg, :datq, :ddef attr_accessor :dcanchg, :x, :y, :plan, :nextturn, :pvregen, :armnat attr_accessor :ppregen, :dvar, :maldef, :maldefregen, :nbal, :mat, :cibles attr_accessor :dead attr_reader :mdj attr_reader :lastdef, :lastatq, :lastdeg, :lastxp alias dla nextturn # garde le hash global pour vue, pour gerer les changements de plans def initialize(d, v, i) @d, @vue, @idx = d, v, i @cibles = Array.new @dead = false end def events(nr = nil) @d.events @mat, nr end def incarnation(zoneidx) return puts("not dead") if not @dead allowed = dead_sync(false) return puts("not in allowed list !") if not allowed.include?(zoneidx.to_s) p = @d.get('/perso_incarnation.php?id_zone='+zoneidx.to_s+'&index_perso='+@idx.to_s) p.parse.map { |e| next if e.type != 'String' if e.attr['content'] =~ /position.*invalide/ puts "Incarnation échouée: position invalide" return false end } @dead = false sync end def dead_sync(verbose = true) inform = false fstr = false zones = Array.new p = nil if @d.http_client.cur_url == '/perso_incarnation.php?index_perso='+@idx.to_s p = @d.http_client.curpage else p = @d.get('/jouer.php?index_perso='+@idx.to_s) end p.parse.each { |e| case e.type when 'String' if inform and fstr print e.attr['content'].rjust(25)+': ' if verbose fstr = false end when 'input' if inform and e.attr['onclick'] =~ /document.activ.id_zone.value='(.*)';/ zones << $1 puts $1 if verbose fstr = true end when 'form' inform = true fstr = true when '/form' inform = false end } zones end def sync(fast = false) # @d.domain_goto :idx if @domain != :pidx return dead_sync if @dead getarg = ['/jouer.php?index_perso='+@idx.to_s] getarg = ['/jouer.php'] if @d.http_client.cur_url == '/jouer.php' and @d.curpersoidx == @idx @d.curpersoidx = @idx getarg << 2*rand if fast scan_idx @d.get(*getarg) true end def scan_idx(page) state = 0 cases = Array.new form = nil formselect = nil @dcanchg = false @cibles.clear @mdj = '' s, t, e = nil page.each_table { |t, e| if t.empty? if e.type == 'img' and s = e.attr['onmouseover'] s = s.split(';', 2) next unless s[0] =~ /X = (\d+) \/ Y = (\d+) .*cement: ([0-9.]+)/ cases << Case.new($1.to_i, $2.to_i, $3.to_f) next unless s[1] =~ /Show_perso \('(\d+)', '(.+)', '(.+)', '(.*)'/ cases.last.pers = CasePers.new($1.to_i, $2, $4, $3) # mat name mdj race elsif e.type == 'String' and e.attr['content'] =~ /^(\d+)-(\d+) (\d+):(\d+):(\d+)/ @d.now = Time.mktime(Time.now.year, $2, $1, $3, $4, $5) end next end case e.type when 'String' s = e.attr['content'] case state when 1 ; @name = s when 2 ; @race, @lvl = $1, $2.to_i if s =~ /^(.*) Niv. (\d+)/ when 4 ; @px = $1.to_i if s =~ /^(\d+)$/ when 6 ; @pi = $1.to_i if s =~ /^(\d+)$/ when 8 ; @pv = $1.to_i if s =~ /^(\d+)$/ when 9 ; @pvmax = $1.to_i if s =~ /^\/ (\d+)$/ when 11 ; @mv, @mvmax = $1.to_f, $2.to_i if s =~ /^([0-9.]+) \/ (\d+)/ when 13 ; @pp, @ppmax = $1.to_f, $2.to_i if s =~ /^([0-9.]+) \/ (\d+)/ when 14 ; @mdj = s # /textarea when 19 ; @natq, @natqmax = $1.to_i, $2.to_i if s =~ /^(\d+) \/ (\d+)/ when 21 ; @deg = $1.to_i if s =~ /^(\d+)/ # variation des dés # carte # cibles when 27 ; @x, @y = $1.to_i, $2.to_i if s =~ /^Votre position: X=(\d+), Y=(\d+)/ # mouvs when 32 if s =~ /(\d+)-(\d+) (\d+):(\d+):(\d+)/ @nextturn = Time.mktime(Time.now.year, $2, $1, $3, $4, $5) if @nextturn < Time.now - 48*3600 @nextturn = Time.mktime(Time.now.year+1, $2, $1, $3, $4, $5) end elsif s =~ /activer/i @nextturn = Time.now - 3600 end when 35 ; @pvregen = $1.to_i if s =~ /^(\d+) pv/ when 37 ; @armnat = $1.to_i if s =~ /^(\d+)$/ when 39 ; @ppregen = $1.to_i if s =~ /^(\d+) pp/ when 42 ; @dvar = $1.to_i if s =~ /^(\d+) \/ tour/ when 44 ; @maldef = $1.to_i if s =~ /^(\d+)/ when 46 ; @maldefregen = $1.to_i if s =~ /^(\d+) \/ tour/ when 50 ; @nbal = $1.to_i if s =~ /Consulter.*\((\d+)\)/ end state += 1 if state > 0 and not form when 'form' form = e.attr['name'] when '/form', 'hr' # site bug form = nil state += 1 when 'select' formselect = e.attr['name'] when '/select' formselect = nil state += 1 if state == 0 # start scan (apres selection du perso) when 'option' if formselect == 'id_perso_ataq' mat = e.attr['value'].to_i @cibles << mat if mat >= 0 end when 'input' if form == 'maj_combat' case e.attr['name'] when 'atq' @datq = e.attr['value'].to_i when 'def' @ddef = e.attr['value'].to_i when nil @dcanchg = true if e.attr['type'] == 'button' and e.attr['onclick'] == 'maj_des();' end end when 'a' if state == 24 and e.attr['href'] =~ /^cartes_view.php\?id_plan=(\d+)/ @plan = $1.to_i state += 1 elsif e.attr['href'] =~ /^perso_events_view.php\?id_perso=(\d+)/ @mat = $1.to_i state += 1 if state != 52 puts "BUG parse error: link to events at state #{state} != 52, page follows:", page.parse @dead = true end end end } cases.each { |c| @vue[@plan].add c } end private :scan_idx def amelioration(what = nil) p = @d.get('perso_upgrade.php?index_perso='+@idx.to_s) if what match = false p.parse.each { |e| case e.type when 'String' match = true if e.attr['content'] == what when 'input' next if not match if e.attr['value'] == ' + ' # "window.open ('?index_perso=6&upgrade=1&var=0.11506500 1118662210','_self');" if e.attr['onclick'] =~ /window.open.*'(\?index_perso.*)','_self/ @d.get('perso_upgrade.php' + $1.gsub(' ', '%20')) end elsif e.attr['value'] == ' / ' puts "Pas assez de PI pour augmenter #{what}" end break end } what = match end if not what show = false p.parse.each { |e| case e.type when '/select' show = true when 'Comment' show = false end next unless show case e.type when 'String' print e.attr['content'] + ' ' when 'input' puts e.attr['value'] end } end sync end def randvar "&var=#{rand*100}#{rand(10) if rand(10) != 3}" end private :randvar def move(newx, newy) return if @dead return false unless @mv >= @vue[@plan][newx, newy].mv if @vue[@plan] and @vue[@plan][newx, newy] sync true return false unless @mv >= @vue[@plan][newx, newy].mv return false if @vue[@plan][newx, newy].pers case [newx - x, newy - y] when [-1, 1] ; idx = 1 when [ 0, 1] ; idx = 2 when [ 1, 1] ; idx = 3 when [-1, 0] ; idx = 8 when [ 1, 0] ; idx = 4 when [-1, -1] ; idx = 7 when [ 0, -1] ; idx = 6 when [ 1, -1] ; idx = 5 else return false end # function mouvement (i) { # var alea = Math.random() * 100; # document.location.href = 'perso_move.php?move='+ i +'&var='+ alea; # } @d.http_client.get_url_allowed << '/perso_move.php' p = @d.get('/perso_move.php?move=' + idx.to_s + randvar, 1) sync true end def attaque(mat, deg=nil) return :invalide if @dead return :invalide if @natq == 0 sync true return :invalide unless @cibles.include?(mat) deg = @deg if not deg # function attaque () { # var alea = Math.random() * 100; # document.location.href = 'perso_attaque.php?id_perso='+ document.attak.id_perso_ataq.value+'°at_actu='+document.attak.degat_actu.value+'&var='+alea; # } @d.http_client.get_url_allowed << '/perso_attaque.php' p = @d.get('/perso_attaque.php?id_perso=' + mat.to_s + '°at_actu=' + deg.to_s + randvar, 1) hit = :inconnu p.parse.map!{|e| e.attr['content'] if e.type == 'String'}.compact!.each { |e| case e when /Erreur/ raise 'bug!' if hit == :inconnu when /^Vous avez tué (.*) !/ puts "#@name vient de tuer #$1 !!" hit = :meurtre when /^Vous avez touché (.*) !/ puts "#@name vs #$1: Touché !" hit = :touche when /(.*) a esquivé votre attaque/ puts "#@name vs #$1: Manqué !" hit = :manque when /^Votre score d'attaque.* (-?\d+)/ @lastatq = $1.to_i puts "Attaque : #@lastatq" when /^Son score de défense.* (-?\d+)/ @lastdef = $1.to_i puts "Défense : #@lastdef" when /^Vous infligez (\d+) dégat/, /^Dégat\(s\) infligé\(s\) : (\d+)/ @lastdeg = $1.to_i puts "Dégats : #@lastdeg" when /^Vous (?:avez )?gagn..? (\d+)/ @lastxp = $1.to_i puts "Gain xp : #@lastxp" when /^Vous venez de passer au niveau (\d+)/ puts "Passage au niveau #$1" when /^Démange II - Jeu|^Retourner à votre page/, /^body / else puts "unhandled attaque string #{e.inspect}" end } @d.http_client.get_url_allowed << '/jouer.php' sync true hit end def mdj=(newmdj) return if @dead sync @d.http_client.get_url_allowed << '/perso_msg_maj.php' puts @d.get_new('/perso_msg_maj.php?msg='+@d.http_client.urlenc(newmdj)).parse.map{ |e| e.attr['content'] if e.type == 'String' and e.attr['content'] !~ /^body |^D.mange/ }.compact end def setdes(newatq, newdef) return if @dead sync true unless @pvregen if newatq <= 0 newdef -= 1-newatq newatq = 1 end if newdef <= 0 newatq -= 1-newdef newdef = 1 end return nil if newatq == @datq return false unless @dcanchg sync true return false unless @dcanchg # function maj_des() { # var alea = Math.random() * 100; # window.open ("perso_combat_maj.php?atq="+ eval(document.maj_combat.atq.value) +"&def="+ eval(document.maj_combat.def.value) +"&var="+ alea, "_blank", "top=190, left=300, width=500, height=200"); # } @d.http_client.get_url_allowed << '/perso_combat_maj.php' x = @d.get_new('/perso_combat_maj.php?atq=' + newatq.to_s + '&def=' + newdef.to_s + randvar, 1) if x.parse.map{ |e| e.attr['content'] if e.type == 'String' }.compact.grep(/ mis .* jour avec succ/) @datq, @ddef, @dcanchg = newatq, newdef, false true else puts x.parse false end end end class EventItem attr_accessor :categorie attr_reader :evenement, :date, :p1, :p2 def initialize @evenement = String.new end def date=(s) @date = Time.mktime($3, $2, $1, $4, $5, $6) if s =~ /^(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)/ end def p1=(s) @p1 = s.to_i @p1 = nil if @p1 == 0 end def p2=(s) @p2 = s.to_i @p2 = nil if @p2 == 0 end def to_s "#{@date.strftime('%d/%m %H:%M:%S')}: #@categorie #@evenement (#@p1#{ ' - ' << p2.to_s if p2 })" end end class Events # arrivee = date de creation du perso attr_accessor :name, :mat, :race, :etat, :xp, :sexe attr_reader :list, :factions, :arrivee def initialize @list = Array.new @factions = Array.new end def arrivee=(s) @date = Time.mktime($3, $2, $1) if s =~ /^(\d+)-(\d+)-(\d+)/ end def to_s "#@name (#@mat) - #@race #@sexe #@etat - #@xp xp (factions: #{@factions.join(', ')})\n" + list.map{ |e| "\n" << e.to_s }.join end end class Demange attr_reader :http_client, :persos, :vue, :nbal, :resumed attr_accessor :now, :fast_mode, :curpersoidx def initialize proxyh, proxyp = nil, nil @http_client = HttpClient.new('www.demange-le-jeu.com', 600, proxyh, proxyp) @http_client.bogus_site = true @login_savefile = nil @persos = Array.new @vue = Hash.new @nbal = 0 @fast_mode = false @tried_abonnement = nil end def login(savefile=nil) @http_client.cache['/img/pubs/tickets_surf_banniere.gif'] = HttpResp.new if @http_client.cur_url !~ /joueur_connexion.php/ if @http_client.cur_url get('/index.php', 1) else get('/', 1) end p = get('/joueur_accueil.php') unless @http_client.post_allowed[0] and @http_client.post_allowed[0].url == '/joueur_connexion.php' raise "Site error : no login link in\n#{p.content}" end end h = @http_client.post_allowed[0].vars.clone h['joueur_email'] = @@mail h['code'] = @@pass p = post('/joueur_connexion.php', h, rand(3), 6+rand(8)) if @http_client.cur_url =~ /abonnement/ raise 'Abonnement à refaire !' if @tried_abonnement @tried_abonnement = true puts 'Resouscription à l\'abonnement gratuit...' get('abo_souscription.php?id_abo=2') get('abo_souscription.php?id_abo=2&duree_abo=1') get('abo_souscription.php?id_abo=2&valide=1&duree_abo=1') return login(savefile) end savefile = '.demange.cookies' if savefile == nil # set savefile = false to disable cookie file creation if savefile and File.exists?(savefile) i = 0 i += 1 while File.exists?(savefile+'.'+i.to_s) savefile = savefile + '.' +i.to_s puts "Using #{savefile} as savefile" end @login_savefile = savefile File.open(@login_savefile, 'w') { |fd| @http_client.cookie.each { |k, v| fd.puts "#{k} = #{v}" } } if @login_savefile @persos = Array.new parse_idx(p) @resumed = false true end def login_resume(savefile = '.demange.cookies') @login_savefile = savefile i = 0 loop do raise 'No session file !' unless File.exists?(savefile) raise 'Stale login' if i > 10 break if File.size(savefile) > 0 sleep 2 i += 1 end File.open(savefile).each_line { |l| @http_client.cookie[$1] = $2 if l =~ /^\s*([^= ]*)\s*=\s*(.*)$/ } p = get('/joueur_accueil.php', 1) u = @http_client.cur_url if u != '/joueur_accueil.php' File.unlink(savefile) if File.exists?(savefile) raise "Login resume error : not on accueil, but on #{u} :\n#{p.content}" end @vue = Hash.new @persos = Array.new parse_idx(p) puts "resumed" @resumed = true end def logout x = get('/session_stop.php', 0) u = nil x.parse.each { |l| next if l.type != 'Script' u = $1 if l.attr['content'] =~ />.*?location.*?=.*?['"](.*?)['"].*? 1 when 4 if l > 1 case c when 1 ev.list << EventItem.new ev.list.last.date = s when 2 ; ev.list.last.categorie = s when 3 ; ev.list.last.evenement << s + ' ' when 4 ; ev.list.last.p1 = s when 5 ; ev.list.last.p2 = s end end end } ev end def parse_idx(page) @nbal = 0 curpers = nil t2 = nil state = nil page.each_table { |t, e| if t.empty? and e.type == 'String' and e.attr['content'] =~ /^(..)-(..)-(....) (..):(..):(..)/ @now = Time.mktime($3, $2, $1, $4, $5, $6) end if t[0] == [3, 1, 2] and e.type == 'String' and e.attr['content'] =~ /^Bo.*te Aux Lettres \((-?\d+)\)/ @nbal = $1.to_i end if t[2] != t2 if curpers if state != 18 p = @persos[curpers] puts "Invalid state for perso #{p.name} in index ! (final state = #{state})" p.dead = true end curpers = nil end t2 = t[2].dup if t[2] end next unless t.length == 4 and t[0] == [3, 1, 2] and t[1] == [1, 1, 2] case e.type when 'a' s = e.attr['href'] if not curpers and s =~ /^jouer.php\?index_perso=(\d+)/ idx = $1.to_i curpers = @persos.length @persos.each_index { |i| curpers = i if @persos[i].idx == idx } @persos[curpers] = Perso.new(self, @vue, idx) if not @persos[curpers] state = 0 elsif curpers and s =~ /cartes_view.php\?id_plan=(\d+)/ plan = $1.to_i @persos[curpers].plan = plan @vue[plan] ||= Vue.new end when 'String' next if not curpers s = e.attr['content'] p = @persos[curpers] case state when 0 ; p.name = s when 1 ; p.race, p.lvl, p.px = $1, $2.to_i, $3.to_i if s =~ /^(.*) Niv. (\d+) ~ (\d+) xp/ when 3 ; p.mat = s.to_i when 4 if s =~ /incarnation/i p.dead = true state += 2 else p.dead = false end when 6 ; p.x, p.y = $1.to_i, $2.to_i if s =~ /X = (\d+) .* Y = (\d+)/ when 8 ; p.pv, p.pvmax = $1.to_i, $2.to_i if s =~ /(\d+) \/ (\d+)/ when 10 ; p.natq, p.natqmax = $1.to_i, $2.to_i if s =~ /(\d+) \/ (\d+)/ when 12 ; p.mv, p.mvmax = $1.to_f, $2.to_i if s =~ /([0-9.]+) \/ (\d+)/ when 14 ; p.pp, p.ppmax = $1.to_f, $2.to_i if s =~ /([0-9.]+) \/ (\d+)/ when 16 if s =~ /(\d+)-(\d+) (\d+):(\d+):(\d+)/ p.nextturn = Time.mktime(Time.now.year, $2, $1, $3, $4, $5) if p.nextturn < Time.now - 48*3600 p.nextturn = Time.mktime(Time.now.year+1, $2, $1, $3, $4, $5) end elsif s =~ /activer/i p.nextturn = Time.now - 3600 else puts "unknown next turn: #{s.inspect}" p.nextturn = Time.now + 3600 end end state += 1 end } @persos.compact! end private :parse_idx # TODO rewrite a la events def ballist(oldstoo=false) state, bstate = 0, 0 pers = nil bidx, from, bnew, subj, date = nil, nil, false, nil, nil ret = Array.new get('/bal_view.php').parse.each { |e| case state when 0 state += 1 if e.type == 'Comment' and e.attr['content'] =~ /FIN BOUTON/ when 1 state += 1 if e.type == 'form' when 2 if e.type == 'String' # nombre total de bals puts e.attr['content'] state += 1 end when 3 if e.type == 'String' # nom de la case pers = e.attr['content'] state += 1 end else # bals case e.type when '/table' state = 3 when 'tr' state += 1 bstate = 0 when 'td' bstate += 1 when '/tr' next if not bidx if bnew or oldstoo if pers puts ' - ' + pers pers = nil end puts "#{'*' if bnew}#{bidx}\tle #{date} de #{from}: #{subj}" ret << bidx end bidx, from, bnew, subj, date = nil, nil, false, nil, nil end next if state < 7 case bstate when 2 from = e.attr['content'] if e.type == 'String' when 3 bidx = $1 if e.attr['href'] =~ /bal_msg_view.php\?id_bmr=(.*)/ bnew = true if e.type == 'span' and e.attr['class'] == 'error' # TODO subj = e.attr['content'] if e.type == 'String' when 4 date = e.attr['content'] if e.type == 'String' end end } ret end def balview(bidx) get('/bal_view.php') if not @http_client.get_url_allowed.include?('/bal_msg_view.php') state = 0 get_new("/bal_msg_view.php?id_bmr=#{bidx}").parse.each { |e| case e.type when 'table' ; state += 1 when 'tr' ; state += 1 if state >= 2 when 'String' ; puts e.attr['content'] if state == 3 or state == 5 when 'br' ; print "\n" if state == 5 end } nil end # tolist = '29032-2343-23423', from=arg to self[] def balsend(tolist, sujet, msg, from=0) get('/bal_view.php') if not @http_client.get_url_allowed.include?('/bal_send.php') puts post_new('bal_send.php', { 'msg' => msg, 'sujet' => sujet, 'index_perso'=>self[from].idx.to_s, 'header'=>'1', 'footer'=>'1', 'liste_dests'=>tolist.to_s }).content end def baldel(bidx) get('/bal_view.php').parse.map{ |e| e.attr['href'] if e.type == 'a' }.compact.each { |a| if a =~ /bal_msg_del.php\?id_bmr=#{bidx}&/ get(a) return true end } false end def [](idx) if idx.class == Fixnum p = @persos.each{ |p| return p if p.mat == idx or p.idx == idx } return nil end re = Regexp.new(idx, Regexp::IGNORECASE) @persos.each { |p| return p if p.name =~ re } raise "Invalid perso index: #{idx.inspect}" end # quasiment pas testé def inscription(camp, login, mail, pass) raise 'Un fichier de login existe déjà !' if File.exists?('credentials.rb') return 'mauvais args' unless pass and mail File.open('credentials.rb', 'w') { |fd| fd.puts 'class Demange' fd.puts "\t@@pass = #{pass.inspect}" fd.puts "\t@@mail = #{mail.inspect}" fd.puts 'end' } @@pass = pass @@mail = mail camp = {'ange'=>'9', 'demon'=>'10', 'humain'=>'11'}[camp] return 'mauvais camp' unless camp return 'mauvais args' unless login sexe = '1' sexe = '2' if rand(4) == 1 get('/') get('/joueur_inscription_1.php') post('/joueur_inscription_2.php', {'id_race'=>camp, 'pseudo'=>login, 'sexe'=>sexe, 'email'=>@@mail, 'code'=>@@pass}) post('/joueur_inscription_3.php', {'nom'=>'', 'prenom'=>'', 'jj'=>'1', 'mm'=>'1', 'aaaa'=>'1924', 'adresse'=>'', 'cp'=>'', 'ville'=>'', 'id_pays'=>'1'}) puts "Maintenant vérifier sur #@mail et invoquer inscription_confirm(code)" end def inscription_confirm(code) puts get('/joueur_activation.php?email='+@@mail+'&code='+code.to_s).parse.map{ |e| e.attr['content'] if e.type == 'String' }.compact end def creation_perso(race, name, sexe=nil) race = { 'hero humain' => 11, 'humain' => 12 }[race] return "race invalide" if not race unless sexe sexe = '1' sexe = '2' if rand(4) == 1 end get('/joueur_perso_create.php') get('/joueur_perso_create.php?action=Create&id_race=' + race.to_s) get('/joueur_perso_create.php?action=Create&id_race=' + race.to_s + '&pseudo=' + name + '&sexe=' + sexe) get('/joueur_perso_create.php?action=Create&id_race=' + race.to_s + '&pseudo=' + name + '&sexe=' + sexe + '&confirm=1') end def get_carte(plan = 1) s = @http_client.status_save @http_client.get("/cartes_view.php?id_plan=#{plan}", 0) @http_client.get("/img/plans/calques/plan_persos_#{plan}.png", 0, true) @http_client.get("/img/plans/calques/plan_geo_#{plan}.png", 0, true) @http_client.status_restore s if @fast_mode sleep 1+rand(3) else sleep 4+rand(22) end end def get(page, timeout=4+rand(22)) timeout = 1+rand(3) if @fast_mode and timeout > 3 @http_client.get(page, timeout) end def get_new(page, timeout = 4+rand(22)) timeout = 1+rand(3) if @fast_mode and timeout > 3 s = @http_client.status_save r = @http_client.get(page, timeout) @http_client.status_restore s r end def post(page, vars, timeout=2+rand(12), pretimeout=6+rand(14)) timeout = pretimeout = 1+rand(3) if @fast_mode @http_client.post(page, vars, timeout, pretimeout) end def post_new(*args) s = @http_client.status_save r = post(*args) @http_client.status_restore(s) r end end