Skip to content

Instantly share code, notes, and snippets.

@psylone
Created July 12, 2014 05:53
Show Gist options
  • Save psylone/bd0c94169dd69c10cadc to your computer and use it in GitHub Desktop.
Save psylone/bd0c94169dd69c10cadc to your computer and use it in GitHub Desktop.
Control players with the same IP
module IPTracker
class IP
include Comparable
# Количество секунд, после которого игроки
# с одинаковым IP считаются разными
TIMESTAMP_LIMIT = 86400
attr_reader :ip
def initialize player, ip
@player = player
@ip = ip
end
# Добавляем в Redis пару IP адрес - время захода (в секундах)
def add!
Cache.engine.hset key, @ip, Time.now.to_i
# Сохраняем IP в базу, если его там ещё не было
@player.ip_addr = @ip and @player.save! unless @player.ip_addr
end
def registry
Cache.engine.hgetall key
end
def entries
registry.keys
end
def timestamp
Cache.engine.hget(key, @ip).to_i
end
# Ищет IP для other среди IP адресов текущего объекта
# если найден совпадающий адрес, он записывается
# в @ip текущего объекта
#
# @param [IP] объект для которого происходит поиск адреса
# @return [true, false]
def find other
current_ip = entries.find{ |ip| ip == other.ip }
if current_ip
self.ip = current_ip
true
else
false
end
end
# Если время захода с IP первого объекта больше,
# чем время захода второго (с того же IP)
# на 24 часа, то первый объект считается больше
# второго
def <=> other
return nil unless other.instance_of?(IP) && timestamp != 0 && other.timestamp != 0
if (timestamp - other.timestamp).abs < TIMESTAMP_LIMIT
-1
elsif (timestamp - other.timestamp).abs > TIMESTAMP_LIMIT
1
else
0
end
end
private
def key
["player", @player.id, "ip"].join ":"
end
def ip= value
@ip = value
end
end
# Ищет совпадение ip адресов двух игроков
#
# @param [Player] один игрок
# @param [Player] другой игрок
# @return [true, false]
def self.compare player, target, log = true
ip1 = IP.new player, player.ip_addr
ip2 = IP.new target, target.ip_addr
result = ip2.find(ip1) && ip1 < ip2
log_incident(player) if log && result
result
rescue ArgumentError
false
end
# Получаем список нарушений использования одинакового IP
def self.get_frauds
Cache.engine.zrange "fraud_ips", 0, -1, withscores: true
end
# Записываем IP адрес в Redis при входе в игру
def track_ip! ip
IP.new(self, ip).add!
end
private
# Увеличиваем в Redis (Sorted Set) счётчик нарушителя на единицу
#
# @param [Player]
def self.log_incident player
Cache.engine.zincrby "fraud_ips", 1, player.id
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment