class Queryserver < ActiveRecord::Base FIELDS = [:numplayers, :gamestate, :language, :ping, :difficulty, :gamever, :gametype, :gamemode, :mission, :mapname, :country, :platform, :sv_battleye, :verifysignatures, :password, :dedicated, :players] FIELDS2 = [:mod, :signatures] # [:maxplayers, :equalModRequired, :numteams, :timelimit, :param1, :param2, :currentVersion, :requiredVersion, :gamename] SYS_MODS = ["CA"] serialize :mod, Array serialize :players, Array serialize :signatures, Array has_and_belongs_to_many :mods def address [self.ip, self.port].join(":") end def mods_fetch if self.mod.size > 0 self.mod.reject {|m| SYS_MODS.include? m }.map do |m| mods = Mod.find(:all, :conditions => "name LIKE '#{m}'") # needed for case insensitivity :S mod = nil mods.each do |mo| if mo.name.downcase == m.downcase mod = mo break else mod = nil end end unless mod # TODO: Filter for mods that are not installed, but actually requires an appsetting! mod = Mod.new mod.name = m mod.skip = true end mod end.reject {|m| m.nil? } else [] end end def mods_fetch2 if self.mod.size > 0 self.mod.reject {|m| SYS_MODS.include? m }.map do |m| mods = Mod.find(:all, :conditions => "name LIKE '#{m}'") # needed for case insensitivity :S mod = nil mods.each do |mo| if mo.name.downcase == m.downcase mod = mo break else mod = nil end end mod end.reject {|m| m.nil? } else [] end end def convert(data) data.each_pair do |k, v| if !k.is_a? String logger.info "Key that is no string: #{k} #{v}!" #STDIN.gets else if k.empty? logger.info "Key that is empty: #{k} #{v}!" next end self[k] = v if FIELDS.include?(k.to_sym) self[k] = v.split(";").reject{|e| e.empty?} if FIELDS2.include?(k.to_sym) end end end def dynamic_server s = Server.new s.name = self.name s.address = self.ip s.port = self.port s.password = self.saved_password s.mods = self.mods_fetch s end def exec2 "" end def latest #unless self.updated_at < Time.now - 1.minutes n = get_latest if n self.convert(n) self.mods = self.mods_fetch2 if self.mod end end def get_latest # TODO: Also query with gslist, to get ping/country update? g = Six::Query::Gamespy.new(self.ip, self.port) begin g.sync rescue Six::Query::Base::TimeoutError logger.info "Timeout while accessing #{self.address}" nil end end def self.clean ar = [] self.find(:all, :conditions => ["numplayers > 0 AND updated_at < ?", 20.minutes.ago]).each do |r| r.mission = "" r.players = [] r.numplayers = 0 r.save ar << r end ar end def self.prune ar = [] self.find(:all, :conditions => ["updated_at < ?", 7.days.ago]).each do |r| r.delete unless r.favorite # Don't prune favorites end ar end def self.purge self.delete_all end def self.import(e) s = self.find_by_ip_and_port(e[:ip], e[:port]) if e[:gamedata] unless s s = self.new s.ip = e[:ip] s.port = e[:port] end #oldmod = s.mod ? s.mod.clone : nil s.name = e[:gamedata]["hostname"].split(",").join(", ") if e[:gamedata]["hostname"] #s.content = e[:gamedata] s.convert(e[:gamedata]) if s.mod # TODO: Can't use the unless condition this until we can measure if there are any new Mod records too s.mods = s.mods_fetch2 # unless s.mod == oldmod end s.save else if s s.failures = 0 unless s.failures s.failures += 1 s.save end # TODO: If more than 5 subsequent failures, only try em once an hour? end s end end