Вход Регистрация
Файл: new_top/core/classes/Counter.php
Строк: 226
<?php
/**
 * Counter — registration of hits and generation of counter images
 */

declare(strict_types=1);

class 
Counter
{
    
/** Available visual styles (1..11) */
    
public static function availableStyles(): array
    {
        return [
            
1  => 'Синий',
            
2  => 'Изумруд',
            
3  => 'Янтарь',
            
4  => 'Фиолет',
            
5  => 'Тёмный',
            
6  => 'Индиго',
            
7  => 'Зелёный',
            
8  => 'Рубин',
            
9  => 'Серый',
            
10 => 'Океан',
            
11 => 'Бронза',
        ];
    }

    public static function 
registerView(int $platformId): ?array
    {
        try {
            
$pf = Database::fetch(
                
'SELECT * FROM platforms WHERE id = ? LIMIT 1',
                [
$platformId]
            );
        } catch (
Throwable $e) {
            return 
null;
        }

        if (!
$pf || (int)$pf['ban'] === 1) {
            return 
$pf;
        }

        if ((int)
$pf['mode'] === 1) {
            return 
$pf;
        }

        
$ip = client_ip();
        
$ua = client_ua();
        
$now = time();
        
$dayStart = mktime(0, 0, 0, (int)date('m'), (int)date('d'), (int)date('Y'));

        try {
            
$check = class_exists('AntiCheat')
                ? 
AntiCheat::checkHit($platformId, $ip, $ua)
                : [
'allow' => true, 'reason' => 'ok'];
            if (!
$check['allow']) {
                return 
$pf;
            }
        } catch (
Throwable $e) {
            
// count anyway if anti-cheat fails
        
}

        try {
            
$existsHs = Database::fetchColumn(
                
'SELECT id FROM hs WHERE pf = ? AND ip = ? AND time >= ? LIMIT 1',
                [
$platformId, $ip, $dayStart]
            );

            
$isMobile = self::isMobile($ua);

            if (!
$existsHs) {
                
Database::query(
                    
'INSERT INTO hs (pf, ip, ua, time) VALUES (?, ?, ?, ?)',
                    [
$platformId, $ip, $ua, $now]
                );
                
$extra = $isMobile ? ', mb = mb + 1' : ', pc = pc + 1';
                
Database::query(
                    
"UPDATE platforms SET hs = hs + 1, hs_all = hs_all + 1, hs_today = hs_today + 1 {$extra} WHERE id = ?",
                    [
$platformId]
                );
                
$pf['hs'] = (int)$pf['hs'] + 1;
            }

            
Database::query(
                
'INSERT INTO ht (pf, ip, ua, time) VALUES (?, ?, ?, ?)',
                [
$platformId, $ip, $ua, $now]
            );
            
Database::query(
                
'UPDATE platforms SET ht = ht + 1, ht_all = ht_all + 1, ht_today = ht_today + 1 WHERE id = ?',
                [
$platformId]
            );
            
$pf['ht'] = (int)$pf['ht'] + 1;

            
$onExists = Database::fetchColumn(
                
'SELECT id FROM on_log WHERE pf = ? AND ip = ? LIMIT 1',
                [
$platformId, $ip]
            );
            if (
$onExists) {
                
Database::query('UPDATE on_log SET time = ?, ua = ? WHERE id = ?', [$now, $ua, $onExists]);
            } else {
                
Database::query(
                    
'INSERT INTO on_log (pf, ip, ua, time) VALUES (?, ?, ?, ?)',
                    [
$platformId, $ip, $ua, $now]
                );
            }
        } catch (
Throwable $e) {
            
// still render image with existing numbers
        
}

        return 
$pf;
    }

    public static function 
registerIn(int $platformId): ?array
    {
        
$pf = Database::fetch(
            
'SELECT * FROM platforms WHERE id = ? AND ban = 0 AND mode = 0',
            [
$platformId]
        );
        if (!
$pf) {
            return 
null;
        }

        
$ip = client_ip();
        
$ua = client_ua();
        
$now = time();
        
$dayStart = mktime(0, 0, 0, (int)date('m'), (int)date('d'), (int)date('Y'));

        try {
            
$check = class_exists('AntiCheat')
                ? 
AntiCheat::checkIn($platformId, $ip, $ua)
                : [
'allow' => true, 'reason' => 'ok'];
            if (
$check['allow']) {
                
$exists = Database::fetchColumn(
                    
'SELECT id FROM in_log WHERE pf = ? AND ip = ? AND time >= ? LIMIT 1',
                    [
$platformId, $ip, $dayStart]
                );
                if (!
$exists) {
                    
Database::query(
                        
'INSERT INTO in_log (pf, ip, ua, time) VALUES (?, ?, ?, ?)',
                        [
$platformId, $ip, $ua, $now]
                    );
                    
Database::query(
                        
'UPDATE platforms SET in_count = in_count + 1 WHERE id = ?',
                        [
$platformId]
                    );
                    if (
class_exists('Points')) {
                        
Points::rewardInbound($platformId);
                    }
                }
            }
        } catch (
Throwable $e) {
        }

        return 
$pf;
    }

    public static function 
renderImage(?array $pf, string $type = 'big'): void
    
{
        while (
ob_get_level() > 0) {
            
ob_end_clean();
        }

        
$type = ($type === 'small') ? 'small' : 'big';
        
$width  = $type === 'big' ? 88 : 60;
        
$height = $type === 'big' ? 31 : 20;

        if (!
$pf) {
            
self::outputStatus($type, 'mod');
            return;
        }
        if ((int)(
$pf['ban'] ?? 0) === 1) {
            
self::outputStatus($type, 'ban');
            return;
        }
        if ((int)(
$pf['mode'] ?? 0) === 1) {
            
self::outputStatus($type, 'mod');
            return;
        }

        
$hs = (int)($pf['hs'] ?? 0);
        
$ht = (int)($pf['ht'] ?? 0);
        
$style = (int)($type === 'big' ? ($pf['style_big'] ?? 1) : ($pf['style_small'] ?? 1));
        if (
$style < 1 || $style > 11) {
            
$style = 1;
        }

        
// 1) GD modern draw (most reliable)
        
if (function_exists('imagecreatetruecolor')) {
            
self::drawStyledCounter($hs, $ht, $width, $height, $type, $style);
            return;
        }

        
// 2) Template GIF without text if present
        
$gifPath = ASSETS . "/cn/{$type}/{$style}.gif";
        if (
is_file($gifPath)) {
            
header('Content-Type: image/gif');
            
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
            
header('Pragma: no-cache');
            
readfile($gifPath);
            return;
        }

        
// 3) Hardcoded minimal GIF
        
self::outputMinimalGif();
    }

    private static function 
outputStatus(string $type, string $status): void
    
{
        
$path = ASSETS . "/cn/{$type}/{$status}.gif";
        if (
is_file($path)) {
            
header('Content-Type: image/gif');
            
header('Cache-Control: no-store');
            
readfile($path);
            return;
        }
        if (
function_exists('imagecreatetruecolor')) {
            
$w = $type === 'big' ? 88 : 60;
            
$h = $type === 'big' ? 31 : 20;
            
$img = imagecreatetruecolor($w, $h);
            
$bg = $status === 'ban'
                
? imagecolorallocate($img, 120, 30, 30)
                : 
imagecolorallocate($img, 100, 80, 20);
            
$fg = imagecolorallocate($img, 255, 255, 255);
            
imagefilledrectangle($img, 0, 0, $w, $h, $bg);
            
$label = $status === 'ban' ? 'BAN' : 'MOD';
            
imagestring($img, 3, (int)(($w - imagefontwidth(3) * strlen($label)) / 2), (int)(($h - imagefontheight(3)) / 2), $label, $fg);
            
header('Content-Type: image/png');
            
header('Cache-Control: no-store');
            
imagepng($img);
            
imagedestroy($img);
            return;
        }
        
self::outputMinimalGif();
    }

    private static function 
styleColors(int $style): array
    {
        
$map = [
            
1  => [30, 58, 95, 66, 153, 225],
            
2  => [16, 70, 60, 0, 200, 160],
            
3  => [80, 55, 18, 245, 180, 50],
            
4  => [55, 30, 75, 170, 120, 255],
            
5  => [18, 18, 28, 100, 100, 120],
            
6  => [28, 32, 90, 100, 120, 255],
            
7  => [12, 60, 40, 40, 200, 120],
            
8  => [90, 25, 35, 255, 90, 110],
            
9  => [45, 45, 48, 160, 160, 165],
            
10 => [18, 40, 70, 50, 140, 220],
            
11 => [70, 42, 20, 220, 160, 80],
        ];
        return 
$map[$style] ?? $map[1];
    }

    private static function 
drawStyledCounter(int $hs, int $ht, int $w, int $h, string $type, int $style): void
    
{
        
$c = self::styleColors($style);
        
$img = imagecreatetruecolor($w, $h);
        
imagealphablending($img, true);
        
$bg = imagecolorallocate($img, $c[0], $c[1], $c[2]);
        
$accent = imagecolorallocate($img, $c[3], $c[4], $c[5]);
        
$fg = imagecolorallocate($img, 255, 255, 255);
        
$muted = imagecolorallocate($img, 180, 195, 220);
        
imagefilledrectangle($img, 0, 0, $w - 1, $h - 1, $bg);
        
imagefilledrectangle($img, 0, 0, 3, $h - 1, $accent);

        
$hsStr = (string)$hs;
        
$htStr = (string)$ht;
        
$fontFile = ASSETS . '/cn/fonts/font.ttf';
        if (!
is_file($fontFile)) {
            
$fontFile = ASSETS . '/cn/fonts/Comfortaa-Light.ttf';
        }

        if (
is_file($fontFile) && function_exists('imagettftext')) {
            
$size = $type === 'big' ? 9.0 : 7.0;
            
$y = $type === 'big' ? 21 : 14;
            
imagettftext($img, $size, 0, 8, $y, $fg, $fontFile, $hsStr);
            
$sepX = $type === 'big' ? 40 : 28;
            
imagettftext($img, $size - 1, 0, $sepX, $y, $muted, $fontFile, '/');
            
imagettftext($img, $size, 0, $sepX + 8, $y, $fg, $fontFile, $htStr);
        } else {
            
$font = $type === 'big' ? 3 : 2;
            
$text = $hsStr . '/' . $htStr;
            
$tw = imagefontwidth($font) * strlen($text);
            
$th = imagefontheight($font);
            
imagestring($img, $font, (int)max(6, ($w - $tw) / 2), (int)(($h - $th) / 2), $text, $fg);
        }

        
header('Content-Type: image/png');
        
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
        
header('Pragma: no-cache');
        
imagepng($img);
        
imagedestroy($img);
    }

    private static function 
outputMinimalGif(): void
    
{
        
header('Content-Type: image/gif');
        
header('Cache-Control: no-store');
        echo 
base64_decode('R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7');
    }

    private static function 
isMobile(string $ua): bool
    
{
        
$ua = strtolower($ua);
        foreach ([
'mobile', 'android', 'iphone', 'ipad', 'ipod', 'webos', 'blackberry', 'opera mini', 'iemobile'] as $n) {
            if (
strpos($ua, $n) !== false) {
                return 
true;
            }
        }
        return 
false;
    }

    public static function 
embedCodes(int $id, string $baseUrl): array
    {
        
$baseUrl = rtrim($baseUrl, '/');
        return [
            
'big' => '<a href="' . $baseUrl . '/in/' . $id . '" target="_blank" rel="nofollow">'
                
. '<img src="' . $baseUrl . '/cn/big/' . $id . '" alt="top" width="88" height="31" border="0" /></a>',
            
'small' => '<a href="' . $baseUrl . '/in/' . $id . '" target="_blank" rel="nofollow">'
                
. '<img src="' . $baseUrl . '/cn/small/' . $id . '" alt="top" width="60" height="20" border="0" /></a>',
        ];
    }
}
Онлайн: 1
Реклама