|  | @@ -13,7 +13,7 @@ require 'timeout'
 | 
	
		
			
				|  |  |  # .. allowed commands .. ROLES = CAPABILITIES
 | 
	
		
			
				|  |  |  # normal users have ROLE broadcast. Roles are defined on a per-user basis .. in a config.
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -$version = "0.4em_cooldns_classes_for_caching"
 | 
	
		
			
				|  |  | +$version = "0.6em_specservers_dupe_election"
 | 
	
		
			
				|  |  |  $debug = 0
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  $role_commands = Hash[
 | 
	
	
		
			
				|  | @@ -23,8 +23,8 @@ $role_commands = Hash[
 | 
	
		
			
				|  |  |    'broadcast_admin' => %w(BC_ID BC BC_ENDCOUNT),
 | 
	
		
			
				|  |  |    'broadcast' => %w(REQ_BC BC_RE),
 | 
	
		
			
				|  |  |  	
 | 
	
		
			
				|  |  | -	'specbot_admin' => %w(REQ_ASSIGN REQ_UNASSIGN REQ_PING REQ_ASSIGNMENTS),
 | 
	
		
			
				|  |  | -	'specbot' => %w(ASSIGN_RE UNASSIGN_RE PING_RE ASSIGNMENTS_RE REQ_DNS),
 | 
	
		
			
				|  |  | +	'specbot_admin' => %w(REQ_ASSIGN REQ_UNASSIGN REQ_PING REQ_ASSIGNMENTS REQ_MAXSERVERS DUPECHECK ELECTION),
 | 
	
		
			
				|  |  | +	'specbot' => %w(ASSIGN_RE UNASSIGN_RE PING_RE ASSIGNMENTS_RE REQ_DNS MAXSERVERS_RE),
 | 
	
		
			
				|  |  |  ]
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  $default_role = "everyone"
 | 
	
	
		
			
				|  | @@ -44,7 +44,7 @@ $role_dialogs = Hash[
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  $user_roles = Hash[
 | 
	
		
			
				|  |  |    #noinspection RubyStringKeysInHashInspection
 | 
	
		
			
				|  |  | -  'paul_tester' => %w(everyone broadcast specbot specbot_admin),
 | 
	
		
			
				|  |  | +  'paul_tester' => %w(everyone broadcast specbot_admin),
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	'paul_dev_eggdrop' => %w(everyone broadcast),
 | 
	
		
			
				|  |  |  	'paul_eggdrop' => %w(everyone broadcast),
 | 
	
	
		
			
				|  | @@ -54,8 +54,9 @@ $user_roles = Hash[
 | 
	
		
			
				|  |  |  	
 | 
	
		
			
				|  |  |  	'qw.nu' => %w(everyone broadcast),
 | 
	
		
			
				|  |  |  	'qw.nu_poster' => %w(everyone broadcast),
 | 
	
		
			
				|  |  | -	
 | 
	
		
			
				|  |  | -	'mihawk_dev_specbot' => %w(everyone broadcast specbot),
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  'mihawk_devA_specbot' => %w(everyone broadcast specbot),
 | 
	
		
			
				|  |  | +  'mihawk_devB_specbot' => %w(everyone broadcast specbot),
 | 
	
		
			
				|  |  |  	'mihawk_specbot' => %w(everyone broadcast specbot),
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    'armitage_specbot' => %w(everyone broadcast specbot),
 | 
	
	
		
			
				|  | @@ -351,6 +352,12 @@ $qw_list = [
 | 
	
		
			
				|  |  |          "210.50.4.11:27504",
 | 
	
		
			
				|  |  |          ]
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +# for local dev usage ;)
 | 
	
		
			
				|  |  | +$qw_list = [
 | 
	
		
			
				|  |  | +    "89.104.194.146:27501",
 | 
	
		
			
				|  |  | +    "210.50.4.11:27504",
 | 
	
		
			
				|  |  | +    "122.99.118.2:28001",
 | 
	
		
			
				|  |  | +]
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  class GameServers
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -443,7 +450,7 @@ class GameServers
 | 
	
		
			
				|  |  |        scanserver(gserver, type)
 | 
	
		
			
				|  |  |      end
 | 
	
		
			
				|  |  |      put_log "End of scanning."
 | 
	
		
			
				|  |  | -    put_log "foppa: #{@gameservers.fetch("89.104.194.146:27503")} "
 | 
	
		
			
				|  |  | +    #put_log "foppa: #{@gameservers.fetch("89.104.194.146:27501")} "
 | 
	
		
			
				|  |  |    end # of scanserverlist()
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    def get_cool_dns(iphost, ipport)
 | 
	
	
		
			
				|  | @@ -659,19 +666,127 @@ module CentralProtocolHandler
 | 
	
		
			
				|  |  |    # default method that is being run on connection!
 | 
	
		
			
				|  |  |  	def post_init # connection of someone starts here...
 | 
	
		
			
				|  |  |  		@username = nil
 | 
	
		
			
				|  |  | -	end
 | 
	
		
			
				|  |  | +    @my_servers = Hash.new
 | 
	
		
			
				|  |  | +    @my_servers.default = {
 | 
	
		
			
				|  |  | +      "active" => 0,
 | 
	
		
			
				|  |  | +      "s-p" => "false",
 | 
	
		
			
				|  |  | +      "ping" => 8888,
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +  ### setters
 | 
	
		
			
				|  |  | +  def set_my_servers(server, key, value)
 | 
	
		
			
				|  |  | +    current = Hash.new
 | 
	
		
			
				|  |  | +    current.store(key, value)
 | 
	
		
			
				|  |  | +    @my_servers[server] = @my_servers[server].merge(current)
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  def specbot_set_sp(username, server, value)
 | 
	
		
			
				|  |  | +    @@connected_clients.each {|c|
 | 
	
		
			
				|  |  | +      if c.username == username
 | 
	
		
			
				|  |  | +        c.set_my_servers(server, "s-p", value)
 | 
	
		
			
				|  |  | +      end
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	### getters
 | 
	
		
			
				|  |  | +  ### getters
 | 
	
		
			
				|  |  |  	def entered_username?
 | 
	
		
			
				|  |  |  		!@username.nil? && !@username.empty? # then it's true
 | 
	
		
			
				|  |  |  	end
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	def username
 | 
	
		
			
				|  |  |  		@username
 | 
	
		
			
				|  |  | -	end
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  def my_active_servers(active = true)
 | 
	
		
			
				|  |  | +    unless @my_servers.nil? || @my_servers.empty?
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      if active
 | 
	
		
			
				|  |  | +        rethash = Hash.new
 | 
	
		
			
				|  |  | +        @my_servers.each_pair{|k, v|
 | 
	
		
			
				|  |  | +          if v["active"] == 1
 | 
	
		
			
				|  |  | +            rethash[k] = @my_servers[k]
 | 
	
		
			
				|  |  | +          end
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        rethash
 | 
	
		
			
				|  |  | +      else
 | 
	
		
			
				|  |  | +        @my_servers
 | 
	
		
			
				|  |  | +      end
 | 
	
		
			
				|  |  | +    end
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  def specbot_servers(flat = true)
 | 
	
		
			
				|  |  | +    the_servers = Hash.new
 | 
	
		
			
				|  |  | +    @@connected_clients.each {|c|
 | 
	
		
			
				|  |  | +      if flat
 | 
	
		
			
				|  |  | +        unless c.my_active_servers.nil? || c.my_active_servers.empty?
 | 
	
		
			
				|  |  | +          the_servers = the_servers.merge(c.my_active_servers)
 | 
	
		
			
				|  |  | +        end
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      else
 | 
	
		
			
				|  |  | +        unless c.my_active_servers.nil? || c.my_active_servers.empty?
 | 
	
		
			
				|  |  | +          the_servers[c.username] = c.my_active_servers
 | 
	
		
			
				|  |  | +        end
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      end
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    the_servers
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  def specbot_ping(server)
 | 
	
		
			
				|  |  | +    ms = my_active_servers(false)
 | 
	
		
			
				|  |  | +    unless ms.nil?
 | 
	
		
			
				|  |  | +      si = ms[server]
 | 
	
		
			
				|  |  | +      p1 = si.fetch("ping").to_s.to_i
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      return p1
 | 
	
		
			
				|  |  | +    else
 | 
	
		
			
				|  |  | +      return 8888
 | 
	
		
			
				|  |  | +    end
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  def specbot_active?(server)
 | 
	
		
			
				|  |  | +    ms = my_active_servers(false)
 | 
	
		
			
				|  |  | +    unless ms.nil?
 | 
	
		
			
				|  |  | +      si = ms[server]
 | 
	
		
			
				|  |  | +      a1 = si.fetch("active")
 | 
	
		
			
				|  |  | +    else
 | 
	
		
			
				|  |  | +      a1 = 0
 | 
	
		
			
				|  |  | +    end
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if a1 == 1
 | 
	
		
			
				|  |  | +      return 1
 | 
	
		
			
				|  |  | +    else
 | 
	
		
			
				|  |  | +      return 0
 | 
	
		
			
				|  |  | +    end
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  def specbot_sp?(server)
 | 
	
		
			
				|  |  | +    ms = my_active_servers(false)
 | 
	
		
			
				|  |  | +    unless ms.nil?
 | 
	
		
			
				|  |  | +      si = ms[server]
 | 
	
		
			
				|  |  | +      a1 = si.fetch("s-p")
 | 
	
		
			
				|  |  | +    else
 | 
	
		
			
				|  |  | +      a1 = "false"
 | 
	
		
			
				|  |  | +    end
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	def my_roles
 | 
	
		
			
				|  |  | +    if a1 == "true"
 | 
	
		
			
				|  |  | +      return true
 | 
	
		
			
				|  |  | +    else
 | 
	
		
			
				|  |  | +      return false
 | 
	
		
			
				|  |  | +    end
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  def my_maxservers
 | 
	
		
			
				|  |  | +    if @my_maxservers.nil? || @my_maxservers.empty?
 | 
	
		
			
				|  |  | +      nil
 | 
	
		
			
				|  |  | +    else
 | 
	
		
			
				|  |  | +      @my_maxservers
 | 
	
		
			
				|  |  | +    end
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  def my_roles
 | 
	
		
			
				|  |  |  		$user_roles[@username]
 | 
	
		
			
				|  |  |  	end
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -685,7 +800,29 @@ module CentralProtocolHandler
 | 
	
		
			
				|  |  |  		@@connected_clients.each {|c| users.push(c.username)}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  		users
 | 
	
		
			
				|  |  | -	end # of ousers
 | 
	
		
			
				|  |  | +  end # of ousers
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  # returns online users by searching through saved connections that have the specified role
 | 
	
		
			
				|  |  | +  def ousers_by_role(role)
 | 
	
		
			
				|  |  | +    users = Array.new
 | 
	
		
			
				|  |  | +    @@connected_clients.each {|c|
 | 
	
		
			
				|  |  | +      if c.my_roles.include?(role)
 | 
	
		
			
				|  |  | +        users.push(c.username)
 | 
	
		
			
				|  |  | +      end
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    users
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  # returns connections by searching through saved connections that have the specified role
 | 
	
		
			
				|  |  | +  def connections_by_role(role)
 | 
	
		
			
				|  |  | +    conns = Array.new
 | 
	
		
			
				|  |  | +    @@connected_clients.each {|c|
 | 
	
		
			
				|  |  | +      if c.my_roles.include?(role)
 | 
	
		
			
				|  |  | +        conns.push(c)
 | 
	
		
			
				|  |  | +      end
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    conns
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	### checkers
 | 
	
		
			
				|  |  |  	def allowed_cmd(inputmessage)
 | 
	
	
		
			
				|  | @@ -710,6 +847,58 @@ module CentralProtocolHandler
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	### actions
 | 
	
		
			
				|  |  | +  def specbot_dupecheck()
 | 
	
		
			
				|  |  | +    put_log "specbot_dupecheck drin"
 | 
	
		
			
				|  |  | +    conns = connections_by_role("specbot")
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    # if this connection has a same key than another connection
 | 
	
		
			
				|  |  | +    # then fight .. which connection should have that server unassigned. REQ_PING
 | 
	
		
			
				|  |  | +    # the one with the better ping will win and the one with the worse ping will get a new free server slot ;)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    # we have at least 2 bots... > 1
 | 
	
		
			
				|  |  | +    conns.repeated_combination(2){|c|
 | 
	
		
			
				|  |  | +      c1 = c[0]
 | 
	
		
			
				|  |  | +      c2 = c[1]
 | 
	
		
			
				|  |  | +      unless c1 == c2
 | 
	
		
			
				|  |  | +        unless c1.my_active_servers.nil? || c2.my_active_servers.nil?
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          dupes = c1.my_active_servers.keys & c2.my_active_servers.keys
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          if dupes.size > 0
 | 
	
		
			
				|  |  | +            # damn, there's dupes.
 | 
	
		
			
				|  |  | +            put_log "the dupes are: #{dupes.join(", ")} on #{c1.username} and #{c2.username}"
 | 
	
		
			
				|  |  | +            dupes.each{|d|
 | 
	
		
			
				|  |  | +              write_user("REQ_PING #{d}", c1.username)
 | 
	
		
			
				|  |  | +              write_user("REQ_PING #{d}", c2.username)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +              EventMachine.add_timer 2, proc {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                p1 = c1.specbot_ping(d)
 | 
	
		
			
				|  |  | +                p2 = c2.specbot_ping(d)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                a1 = c1.specbot_active?(d)
 | 
	
		
			
				|  |  | +                a2 = c2.specbot_active?(d)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                if p1 <= p2
 | 
	
		
			
				|  |  | +                  unless a2 == 0
 | 
	
		
			
				|  |  | +                    write_user("REQ_UNASSIGN #{d}", c2.username)
 | 
	
		
			
				|  |  | +                  end
 | 
	
		
			
				|  |  | +                else
 | 
	
		
			
				|  |  | +                  unless a1 == 0
 | 
	
		
			
				|  |  | +                    write_user("REQ_UNASSIGN #{d}", c1.username)
 | 
	
		
			
				|  |  | +                  end
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                end
 | 
	
		
			
				|  |  | +              }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +          end
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        end
 | 
	
		
			
				|  |  | +      end
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  end # of specbot_dupecheck
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	# searches through our hash of saved connections and writes them a messages.
 | 
	
		
			
				|  |  |  	def	write_user(input, username = nil)
 | 
	
		
			
				|  |  |  		if username.nil? || username.empty?
 | 
	
	
		
			
				|  | @@ -792,7 +981,7 @@ module CentralProtocolHandler
 | 
	
		
			
				|  |  |  				write_role($default_role, "PARTED User '#{@username}' leaves the party.", @username)
 | 
	
		
			
				|  |  |  				return "bye"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -			###now for the good stuff, broadcasting
 | 
	
		
			
				|  |  | +			### now for the good stuff, broadcasting role
 | 
	
		
			
				|  |  |  			elsif cmd == "REQ_BC"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  				# help with format .. but send the raw payload
 | 
	
	
		
			
				|  | @@ -878,24 +1067,7 @@ module CentralProtocolHandler
 | 
	
		
			
				|  |  |  				end
 | 
	
		
			
				|  |  |    		#end of REQ_BC here..
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -      elsif cmd == "REQ_DNS"
 | 
	
		
			
				|  |  | -        # help with format .. but send the raw payload
 | 
	
		
			
				|  |  | -        if payload =~ /^(\d+\.\d+\.\d+\.\d+):(\d{1,5})/
 | 
	
		
			
				|  |  | -          iphost = $1
 | 
	
		
			
				|  |  | -          ipport = $2
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -          targetname = $gs.get_cool_dns(iphost, ipport)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -          write_user("DNS_RE #{iphost}:#{ipport} #{targetname}") # write back to asking user.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        else # of payload has format
 | 
	
		
			
				|  |  | -          write_user("SYS Command format is REQ_DNS <serverip>:<serverport>")
 | 
	
		
			
				|  |  | -          error = 1
 | 
	
		
			
				|  |  | -        end # of if payload has format
 | 
	
		
			
				|  |  | -      #end of REQ_DNS here..
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        elsif cmd == "BC_RE"
 | 
	
		
			
				|  |  | +      elsif cmd == "BC_RE"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  				if payload =~ /^(.+) (.+)=(\d+),(.+)=(\d+)$/
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -920,9 +1092,235 @@ module CentralProtocolHandler
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  				else # of bc_re format check
 | 
	
		
			
				|  |  |  					put_log "SYS Format is BC_RE <bcid> <userstring>=<usercount>,<itemstring>=<itemcount>"
 | 
	
		
			
				|  |  | -				end
 | 
	
		
			
				|  |  | +        end
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -			end
 | 
	
		
			
				|  |  | +      ### the specbot-admin ROLE does ...
 | 
	
		
			
				|  |  | +      elsif cmd == "REQ_ASSIGN"
 | 
	
		
			
				|  |  | +        if payload =~ /^([a-zA-Z_\.]+) (\d+\.\d+\.\d+\.\d+:\d{1,5})[,]?(true|false)?/
 | 
	
		
			
				|  |  | +          specbot = $1
 | 
	
		
			
				|  |  | +          hostport = $2
 | 
	
		
			
				|  |  | +          sp = $3
 | 
	
		
			
				|  |  | +          if sp == "true"
 | 
	
		
			
				|  |  | +            specbot_set_sp(specbot, hostport, sp)
 | 
	
		
			
				|  |  | +            write_user("REQ_ASSIGN #{hostport},#{sp}", specbot)
 | 
	
		
			
				|  |  | +          else
 | 
	
		
			
				|  |  | +            write_user("REQ_ASSIGN #{hostport}", specbot)
 | 
	
		
			
				|  |  | +          end
 | 
	
		
			
				|  |  | +        else # of format check
 | 
	
		
			
				|  |  | +          write_user("SYS Format is REQ_ASSIGN <specbot> <ip:port>[,<s-p;true or false>]")
 | 
	
		
			
				|  |  | +        end
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      elsif cmd == "REQ_UNASSIGN"
 | 
	
		
			
				|  |  | +        if payload =~ /^([a-zA-Z_\.]+) (\d+\.\d+\.\d+\.\d+:\d{1,5})/
 | 
	
		
			
				|  |  | +          specbot = $1
 | 
	
		
			
				|  |  | +          hostport = $2
 | 
	
		
			
				|  |  | +          write_user("REQ_UNASSIGN #{hostport}", specbot)
 | 
	
		
			
				|  |  | +        else # of format check
 | 
	
		
			
				|  |  | +          write_user("SYS Format is REQ_UNASSIGN <specbot> <ip:port>")
 | 
	
		
			
				|  |  | +        end
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      elsif cmd == "REQ_PING"
 | 
	
		
			
				|  |  | +        if payload =~ /^([a-zA-Z_\.]+) (\d+\.\d+\.\d+\.\d+:\d{1,5})/
 | 
	
		
			
				|  |  | +          specbot = $1
 | 
	
		
			
				|  |  | +          hostport = $2
 | 
	
		
			
				|  |  | +          write_user("REQ_PING #{hostport}", specbot)
 | 
	
		
			
				|  |  | +        else # of format check
 | 
	
		
			
				|  |  | +          write_user("SYS Format is REQ_PING <specbot> <ip:port>")
 | 
	
		
			
				|  |  | +        end
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      elsif cmd == "REQ_ASSIGNMENTS"
 | 
	
		
			
				|  |  | +        if payload =~ /^([a-zA-Z_\.]+)/
 | 
	
		
			
				|  |  | +          specbot = $1
 | 
	
		
			
				|  |  | +          write_user("REQ_ASSIGNMENTS give me your assignments", specbot)
 | 
	
		
			
				|  |  | +        else # of format check
 | 
	
		
			
				|  |  | +          write_user("SYS Format is REQ_ASSIGNMENTS <specbot>")
 | 
	
		
			
				|  |  | +        end
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      elsif cmd == "REQ_MAXSERVERS"
 | 
	
		
			
				|  |  | +        if payload =~ /^([a-zA-Z_\.]+)/
 | 
	
		
			
				|  |  | +          specbot = $1
 | 
	
		
			
				|  |  | +          write_user("REQ_MAXSERVERS how many do you do?", specbot)
 | 
	
		
			
				|  |  | +        else # of format check
 | 
	
		
			
				|  |  | +          write_user("SYS Format is REQ_MAXSERVERS <specbot>")
 | 
	
		
			
				|  |  | +        end
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      elsif cmd == "DUPECHECK"
 | 
	
		
			
				|  |  | +        write_user("SYS specbot server monitoring dupecheck started")
 | 
	
		
			
				|  |  | +        # start the central function for dupechecking:
 | 
	
		
			
				|  |  | +        specbot_dupecheck()
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      elsif cmd == "ELECTION"
 | 
	
		
			
				|  |  | +        write_user("SYS specbot server ping election on global server list started")
 | 
	
		
			
				|  |  | +        # start the central function for server election:
 | 
	
		
			
				|  |  | +        all_servers = specbot_servers()
 | 
	
		
			
				|  |  | +        put_log("#{all_servers}")
 | 
	
		
			
				|  |  | +        write_user("SYS active unique server count: #{all_servers.size}")
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        conns = connections_by_role("specbot")
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        #für jeden server, jeden ping der einzelnen bots vergleichen..
 | 
	
		
			
				|  |  | +        #falls ping info noch nicht vorhanden (>5000), dann einfordern
 | 
	
		
			
				|  |  | +        all_servers.each_key{|k|
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          put_log("SYS bots race for #{k} now..")
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          conns.each{|c|
 | 
	
		
			
				|  |  | +            ping = c.specbot_ping(k)
 | 
	
		
			
				|  |  | +            if ping > 5000
 | 
	
		
			
				|  |  | +              write_user("REQ_PING #{k}", c.username)
 | 
	
		
			
				|  |  | +            end
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          EventMachine.add_timer 5, proc {
 | 
	
		
			
				|  |  | +            lastbest = 5000
 | 
	
		
			
				|  |  | +            winner = ""
 | 
	
		
			
				|  |  | +            conns.each{|c|
 | 
	
		
			
				|  |  | +              ping = c.specbot_ping(k)
 | 
	
		
			
				|  |  | +              put_log("SYS #{ping} of #{c.username} to #{k}")
 | 
	
		
			
				|  |  | +              if ping < lastbest
 | 
	
		
			
				|  |  | +                lastbest = ping
 | 
	
		
			
				|  |  | +                winner = c
 | 
	
		
			
				|  |  | +                put_log("SYS - current best bot for #{k} is #{c.username}")
 | 
	
		
			
				|  |  | +              end
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            put_log("SYS --> best bot for #{k} is #{winner.username}")
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            conns.each{|c|
 | 
	
		
			
				|  |  | +              a = c.specbot_active?(k)
 | 
	
		
			
				|  |  | +              unless c == winner
 | 
	
		
			
				|  |  | +                unless a == 0
 | 
	
		
			
				|  |  | +                  write_user("REQ_UNASSIGN #{k}", c.username)
 | 
	
		
			
				|  |  | +                end
 | 
	
		
			
				|  |  | +              end
 | 
	
		
			
				|  |  | +              if c == winner
 | 
	
		
			
				|  |  | +                unless a == 1
 | 
	
		
			
				|  |  | +                  as = all_servers[k]
 | 
	
		
			
				|  |  | +                  sp = as.fetch("s-p")
 | 
	
		
			
				|  |  | +                  if sp == "true" || sp == "1"
 | 
	
		
			
				|  |  | +                    write_user("REQ_ASSIGN #{k},true", c.username)
 | 
	
		
			
				|  |  | +                  else
 | 
	
		
			
				|  |  | +                    write_user("REQ_ASSIGN #{k}", c.username)
 | 
	
		
			
				|  |  | +                  end
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                end
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +              end
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          } # end of timer
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        } # end of all active servers loop
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      ### the specbot ROLE does ...
 | 
	
		
			
				|  |  | +      elsif cmd == "ASSIGNMENTS_RE"
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if payload =~ /^(\d+\.\d+\.\d+\.\d+:\d{1,5}),(.*),(.*)/
 | 
	
		
			
				|  |  | +          hostport = $1
 | 
	
		
			
				|  |  | +          sp = $2
 | 
	
		
			
				|  |  | +          ping = $3.chomp
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          p hostport
 | 
	
		
			
				|  |  | +          p sp
 | 
	
		
			
				|  |  | +          p ping
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          current = Hash.new()
 | 
	
		
			
				|  |  | +          current.store("active", 1)
 | 
	
		
			
				|  |  | +          current.store("s-p", sp)
 | 
	
		
			
				|  |  | +          current.store("ping", ping)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          # save the hash current to the hash @my_servers
 | 
	
		
			
				|  |  | +          @my_servers[hostport] = @my_servers[hostport].merge(current)
 | 
	
		
			
				|  |  | +          p @my_servers
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          # save new hash to a config file or sth. fixme
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        end
 | 
	
		
			
				|  |  | +      #end of ASSIGNMENTS_RE here..
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      elsif cmd == "MAXSERVERS_RE"
 | 
	
		
			
				|  |  | +        if payload =~ /^(\d+)/
 | 
	
		
			
				|  |  | +          @my_maxservers = $1
 | 
	
		
			
				|  |  | +        end
 | 
	
		
			
				|  |  | +      #end of MAXSERVERS_RE here..
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      elsif cmd == "PING_RE"
 | 
	
		
			
				|  |  | +        if payload =~ /^(\d+\.\d+\.\d+\.\d+:\d{1,5}),(.*)/
 | 
	
		
			
				|  |  | +          hostport = $1
 | 
	
		
			
				|  |  | +          ping = $2
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          current = Hash.new()
 | 
	
		
			
				|  |  | +          current.store("ping", ping)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          # save the hash current to the hash @my_servers
 | 
	
		
			
				|  |  | +          @my_servers[hostport] = @my_servers[hostport].merge(current)
 | 
	
		
			
				|  |  | +          p @my_servers
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          # save new hash to a config file or sth. fixme
 | 
	
		
			
				|  |  | +        end
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      #end of PING_RE here..
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      elsif cmd == "ASSIGN_RE"
 | 
	
		
			
				|  |  | +        #assign_re should only be issued when a req_assign was issued to the specbot before
 | 
	
		
			
				|  |  | +        if payload =~ /^(\d+\.\d+\.\d+\.\d+:\d{1,5}) ([A-Z]+)[\s]?(.*)/
 | 
	
		
			
				|  |  | +          hostport = $1
 | 
	
		
			
				|  |  | +          good = $2
 | 
	
		
			
				|  |  | +          reason = $3
 | 
	
		
			
				|  |  | +          if good == "OK"
 | 
	
		
			
				|  |  | +            current = Hash.new()
 | 
	
		
			
				|  |  | +            current.store("active", 1)
 | 
	
		
			
				|  |  | +            @my_servers[hostport] = @my_servers[hostport].merge(current) # this way it preserves previously saved ping values
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            write_user("REQ_PING #{hostport}")
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            put_log "SYS #{username} assigned to #{hostport} and asked ping for it."
 | 
	
		
			
				|  |  | +            write_role("specbot_admin", "SYS #{username} assigned to #{hostport} and asked ping for it.")
 | 
	
		
			
				|  |  | +          else
 | 
	
		
			
				|  |  | +            put_log "SYS #{username} failed to assign #{hostport}, reason: '#{reason}'"
 | 
	
		
			
				|  |  | +            write_role("specbot_admin", "SYS #{username} failed to assign #{hostport}, reason: '#{reason}'")
 | 
	
		
			
				|  |  | +          end
 | 
	
		
			
				|  |  | +        end
 | 
	
		
			
				|  |  | +      #end of ASSIGN_RE here..
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      elsif cmd == "UNASSIGN_RE"
 | 
	
		
			
				|  |  | +        if payload =~ /^(\d+\.\d+\.\d+\.\d+:\d{1,5}) ([A-Z]+)[\s]?(.*)/
 | 
	
		
			
				|  |  | +          hostport = $1
 | 
	
		
			
				|  |  | +          good = $2
 | 
	
		
			
				|  |  | +          reason = $3
 | 
	
		
			
				|  |  | +          if good == "OK"
 | 
	
		
			
				|  |  | +            current = Hash.new()
 | 
	
		
			
				|  |  | +            current.store("active", 0)
 | 
	
		
			
				|  |  | +            @my_servers[hostport] = @my_servers[hostport].merge(current) # this way it preserves previously saved ping values
 | 
	
		
			
				|  |  | +            put_log "SYS #{username} unassigned #{hostport}"
 | 
	
		
			
				|  |  | +            write_role("specbot_admin", "SYS #{username} unassigned #{hostport}")
 | 
	
		
			
				|  |  | +          else
 | 
	
		
			
				|  |  | +            put_log "SYS #{username} failed to unassign #{hostport}, reason: '#{reason}'"
 | 
	
		
			
				|  |  | +            write_role("specbot_admin", "SYS #{username} failed to unassign #{hostport}, reason: '#{reason}'")
 | 
	
		
			
				|  |  | +          end
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        end
 | 
	
		
			
				|  |  | +      #end of UNASSIGN_RE here..
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      elsif cmd == "REQ_DNS"
 | 
	
		
			
				|  |  | +        # help with format .. but send the raw payload
 | 
	
		
			
				|  |  | +        if payload =~ /^(\d+\.\d+\.\d+\.\d+):(\d{1,5})/
 | 
	
		
			
				|  |  | +          iphost = $1
 | 
	
		
			
				|  |  | +          ipport = $2
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          targetname = $gs.get_cool_dns(iphost, ipport)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          write_user("DNS_RE #{iphost}:#{ipport} #{targetname}") # write back to asking user.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        else # of payload has format
 | 
	
		
			
				|  |  | +          write_user("SYS Command format is REQ_DNS <serverip>:<serverport>")
 | 
	
		
			
				|  |  | +          error = 1
 | 
	
		
			
				|  |  | +        end # of if payload has format
 | 
	
		
			
				|  |  | +      #end of REQ_DNS here..
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      end
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      else  # of if allowed command
 | 
	
	
		
			
				|  | @@ -987,6 +1385,25 @@ module CentralProtocolHandler
 | 
	
		
			
				|  |  |              write_user("ROLES #{my_roles.join(", ")}")
 | 
	
		
			
				|  |  |              write_user("COMMANDS #{my_cmds.join(", ")}")
 | 
	
		
			
				|  |  |              write_role($default_role, "JOINED User '#{@username}' just joined the party.", @username)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            # if that guy is a specbot, ask it for his current list
 | 
	
		
			
				|  |  | +            if my_roles.include?("specbot")
 | 
	
		
			
				|  |  | +              EventMachine.add_timer 2, proc {
 | 
	
		
			
				|  |  | +                write_user("REQ_MAXSERVERS how many can you do?")
 | 
	
		
			
				|  |  | +                write_user("REQ_ASSIGNMENTS gimme all your servers")
 | 
	
		
			
				|  |  | +              }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +              # if more than 1 specbots are connected, then we want to activate the dupe-check.
 | 
	
		
			
				|  |  | +              if connections_by_role("specbot").size > 1
 | 
	
		
			
				|  |  | +                # in 6 seconds we start it. by then, we should have the full serverlists of all bots
 | 
	
		
			
				|  |  | +                EventMachine.add_timer 6, proc {
 | 
	
		
			
				|  |  | +                  put_log("this guy: #{username} triggers the dupecheck now")
 | 
	
		
			
				|  |  | +                  specbot_dupecheck
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +              end
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            end
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |            else
 | 
	
		
			
				|  |  |              put_log "SYS User '#{username}' unknown to me. Saying bye."
 | 
	
		
			
				|  |  |              send_data "SYS User '#{username}' unknown to me. Bye.\n"
 |