Created
July 12, 2014 05:53
-
-
Save psylone/bd0c94169dd69c10cadc to your computer and use it in GitHub Desktop.
Control players with the same IP
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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