<?php

namespace Heanup\Frame\Library;

/**
 * IP频率限制,一定程度上反垃圾
 */
class AntiSpam
{
    const ANTI_SPAM_MINUTE = 'anti_spam:minute';
    const ANTI_SPAM_HOUR = 'anti_spam:hour';
    const ANTI_SPAM_DAY = 'anti_spam:year';
    const ANTI_SPAM_LOCKED = 'anti_spam:locked';
    // 频率设置
    protected static $limits = array(
        self::ANTI_SPAM_MINUTE => 500,
        self::ANTI_SPAM_HOUR => 2000,
        self::ANTI_SPAM_DAY => 10000,
    );
    // 正常过期
    protected static $expire = array(
        self::ANTI_SPAM_MINUTE => 60,
        self::ANTI_SPAM_HOUR => 3600,
        self::ANTI_SPAM_DAY => 86400,
    );
    // 封禁时间
    protected static $forbiddenTime = array(
        self::ANTI_SPAM_MINUTE => 60,
        self::ANTI_SPAM_HOUR => 3600,
        self::ANTI_SPAM_DAY => 86400,
    );

    public static function check()
    {
        // 检查是否已经被封杀
        if (self::getConnection()->get(self::getKey(self::ANTI_SPAM_LOCKED))) {
            return FALSE;
        }
        foreach (self::$limits as $key => $limit) {
            $expire = self::$expire[$key];
            $key = self::getKey($key);
            $value = self::getConnection()->get($key);
            if (!$value) {
                // 值不存在就设置
                self::getConnection()->set($key, 1, $expire);
            } elseif ($value > $limit) {
                // 封禁时间
                $expire = self::$forbiddenTime[$key];
                self::getConnection()->set(self::getKey(self::ANTI_SPAM_LOCKED), 1, $expire);
                return FALSE;
            } else {
                // 正常情况下+1
                self::getConnection()->increment($key, 1);
            }
        }
        return TRUE;
    }

    protected static function getKey($key)
    {
        $ip = \Heanup\Frame\Helper::getClientIp(TRUE);
        return $key . ':' . $ip;
    }

    protected static function getConnection()
    {
        static $connection = null;
        if ($connection) {
            return $connection;
        }
        $cfg = \Heanup\Config\Memcache\AntiSpam::getData();
        $connection = new \Memcached;
        $connection->setOption(\Memcached::OPT_COMPRESSION, TRUE);
        $connection->setOption(\Memcached::OPT_DISTRIBUTION, TRUE);
        $connection->setOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE, TRUE);
        $connection->setOption(\Memcached::OPT_NO_BLOCK, TRUE);
        $connection->setOption(\Memcached::OPT_CONNECT_TIMEOUT, 50);
        $connection->setOption(\Memcached::OPT_POLL_TIMEOUT, 50);
        $connection->addServers($cfg);
        return $connection;
    }

}