<?php

error_reporting(E_ALL);
ini_set('display_errors', '1');

header('Content-Type: text/plain; charset=utf-8');

set_error_handler(function (
    $severity,
    $message,
    $file,
    $line
) {
    throw new ErrorException(
        $message,
        0,
        $severity,
        $file,
        $line
    );
});

$BOT_TOKEN = '7823454938:AAHdzr_aJ3ayP-gNIat0OXO7kKQ0yC7EPE8';
$CHAT_ID = 70643903;
$NITTER_INSTANCE = 'nitter.net'; 

$PAGES = [
    [
        'username' => 'DiscussingFilm',
        'topic_id' => 123
    ],
];

$SENT_FILE = __DIR__ . '/sent.json';

function httpGet($url)
{
    try {
        $ch = curl_init($url);
        if ($ch === false) {
            throw new Exception('curl_init() failed');
        }

        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_MAXREDIRS => 5,
            CURLOPT_CONNECTTIMEOUT => 15,
            CURLOPT_TIMEOUT => 30,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/130 Safari/537.36',
            CURLOPT_HTTPHEADER => [
                'Accept: application/rss+xml, application/xml, text/xml, */*'
            ]
        ]);

        $body = curl_exec($ch);
        $error = curl_error($ch);
        $errno = curl_errno($ch);
        $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
 

        if ($body === false) {
            throw new Exception("cURL error [{$errno}]: {$error}");
        }

        return [
            'ok' => $status >= 200 && $status < 400,
            'body' => $body,
            'status' => $status,
            'error' => $error
        ];
    } catch (Throwable $e) {
        return [
            'ok' => false,
            'body' => '',
            'status' => 0,
            'error' => get_class($e) . ': ' . $e->getMessage()
        ];
    }
}

function telegram($method, $data)
{
    global $BOT_TOKEN;
    try {
        $url = "https://api.telegram.org/bot{$BOT_TOKEN}/{$method}";
        $ch = curl_init($url);
        if ($ch === false) {
            throw new Exception('Telegram curl_init() failed');
        }

        curl_setopt_array($ch, [
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => $data,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_CONNECTTIMEOUT => 15,
            CURLOPT_TIMEOUT => 60,
            CURLOPT_SSL_VERIFYPEER => false
        ]);

        $response = curl_exec($ch);
        $error = curl_error($ch);
        $errno = curl_errno($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  
  
        if ($response === false) {
            throw new Exception("Telegram cURL error [{$errno}]: {$error}");
        }

        $decoded = json_decode($response, true);
        if (!is_array($decoded)) {
            throw new Exception("Invalid Telegram response. HTTP {$httpCode}: {$response}");
        }

        return $decoded;
    } catch (Throwable $e) {
        return [
            'ok' => false,
            'error' => get_class($e) . ': ' . $e->getMessage()
        ];
    }
}

function cleanText($text)
{
    try {
        $text = strip_tags($text);
        $text = html_entity_decode($text, ENT_QUOTES | ENT_HTML5, 'UTF-8');
        $text = preg_replace('/\s+/u', ' ', $text);
        return trim($text);
    } catch (Throwable $e) {
        throw new Exception('cleanText(): ' . $e->getMessage());
    }
}

function extractImages($description)
{
    try {
        $images = [];
        preg_match_all('/<img[^>]+src=["\']([^"\']+)["\']/i', $description, $matches);

        foreach (($matches[1] ?? []) as $url) {
            $url = html_entity_decode($url, ENT_QUOTES | ENT_HTML5, 'UTF-8');
            if (!in_array($url, $images, true)) {
                $images[] = $url;
            }
        }
        return $images;
    } catch (Throwable $e) {
        throw new Exception('extractImages(): ' . $e->getMessage());
    }
}

function hasVideo($description)
{
    try {
        return stripos($description, '>Video<') !== false || preg_match('/<a[^>]+>.*?Video.*?<\/a>/is', $description);
    } catch (Throwable $e) {
        throw new Exception('hasVideo(): ' . $e->getMessage());
    }
}

function toFxTwitter($url)
{
    global $NITTER_INSTANCE;
    try {
        $url = preg_replace('/#.*$/', '', $url);
        return preg_replace('/^https?:\/\/(?:www\.)?' . preg_quote($NITTER_INSTANCE, '/') . '/i', 'https://fxtwitter.com', $url);
    } catch (Throwable $e) {
        throw new Exception('toFxTwitter(): ' . $e->getMessage());
    }
}

function sendPost($item, $topicId)
{
    global $CHAT_ID;
    try {
        $caption = $item['title'];
        if ($item['text'] !== '' && $item['text'] !== $item['title']) {
            $caption .= "\n\n" . $item['text'];
        }

        if ($item['has_video']) {
            $videoUrl = toFxTwitter($item['url']);
            return telegram('sendVideo', [
                'chat_id' => $CHAT_ID,
                //'message_thread_id' => $topicId,
                'video' => $videoUrl,
                'caption' => $caption
            ]);
        }

        if (!empty($item['images'])) {
            return telegram('sendPhoto', [
                'chat_id' => $CHAT_ID,
                //'message_thread_id' => $topicId,
                'photo' => $item['images'][0],
                'caption' => $caption
            ]);
        }

        return telegram('sendMessage', [
            'chat_id' => $CHAT_ID,
           // 'message_thread_id' => $topicId,
            'text' => $caption
        ]);
    } catch (Throwable $e) {
        return [
            'ok' => false,
            'error' => 'sendPost(): ' . get_class($e) . ': ' . $e->getMessage()
        ];
    }
}

try {
    echo "START\n\n";

    try {
        if (file_exists($SENT_FILE)) {
            $sent = json_decode(file_get_contents($SENT_FILE), true);
            if (!is_array($sent)) {
                $sent = [];
            }
        } else {
            $sent = [];
        }
    } catch (Throwable $e) {
        throw new Exception('Loading sent.json failed: ' . $e->getMessage());
    }

    foreach ($PAGES as $pageIndex => $page) {
        try {
            if (!isset($page['username'], $page['topic_id'])) {
                throw new Exception("Invalid page config at index {$pageIndex}");
            }

            $username = $page['username'];
            $topicId = $page['topic_id'];
            $rssUrl = 'https://' . $NITTER_INSTANCE . '/' . rawurlencode($username) . '/rss';

            echo "================================\n";
            echo "PAGE: {$username}\n";
            echo "RSS: {$rssUrl}\n";

            $rss = httpGet($rssUrl);
            if (!$rss['ok']) {
                echo "RSS ERROR: " . $rss['status'] . "\n";
                echo $rss['error'] . "\n";
                continue;
            }

            echo "RSS OK\n";
            echo "RSS LENGTH: " . strlen($rss['body']) . "\n";

            libxml_use_internal_errors(true);
            $xml = simplexml_load_string($rss['body']);

            if ($xml === false) {
                $xmlErrors = libxml_get_errors();
                $errorText = 'XML ERROR';
                foreach ($xmlErrors as $xmlError) {
                    $errorText .= "\n" . trim($xmlError->message);
                }
                libxml_clear_errors();
                throw new Exception($errorText);
            }

            $items = $xml->channel->item;
            echo "FOUND: " . count($items) . " POSTS\n";

            foreach ($items as $rssItem) {
                try {
                    $id = trim((string)$rssItem->guid);
                    if ($id === '') {
                        echo "SKIP: no ID\n";
                        continue;
                    }

                    $uniqueId = $username . ':' . $id;
                    if (isset($sent[$uniqueId])) {
                        continue;
                    }

                    $title = cleanText((string)$rssItem->title);
                    $description = (string)$rssItem->description;
                    $text = cleanText($description);
                    $text = preg_replace('/\bVideo\b/i', '', $text);
                    $text = trim($text);
                    $postUrl = trim((string)$rssItem->link);
                    $images = extractImages($description);
                    $hasVideo = hasVideo($description);

                    $item = [
                        'id' => $id,
                        'title' => $title,
                        'text' => $text,
                        'url' => $postUrl,
                        'images' => $images,
                        'has_video' => $hasVideo
                    ];

                    echo "\nSending: {$id}\n";
                    echo "Video: " . ($hasVideo ? 'YES' : 'NO') . "\n";
                    echo "Images: " . count($images) . "\n";

                    $result = sendPost($item, $topicId);

                    if (isset($result['ok']) && $result['ok'] === true) {
                        echo "TELEGRAM: OK\n";
                        $sent[$uniqueId] = time();
                        $saved = file_put_contents(
                            $SENT_FILE,
                            json_encode($sent, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT),
                            LOCK_EX
                        );

                        if ($saved === false) {
                            echo "WARNING: Could not write sent.json\n";
                        }
                    } else {
                        echo "TELEGRAM ERROR:\n";
                        echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
                        echo "\n";
                    }

                    sleep(1);
                } catch (Throwable $e) {
                    echo "\nPOST ERROR:\n";
                    echo get_class($e) . ': ' . $e->getMessage() . "\n";
                    echo "FILE: " . $e->getFile() . "\n";
                    echo "LINE: " . $e->getLine() . "\n";
                    continue;
                }
            }
        } catch (Throwable $e) {
            echo "\nPAGE ERROR:\n";
            echo get_class($e) . ': ' . $e->getMessage() . "\n";
            echo "FILE: " . $e->getFile() . "\n";
            echo "LINE: " . $e->getLine() . "\n";
            continue;
        }
    }

    echo "\nDONE\n";
} catch (Throwable $e) {
    echo "\n\n========== FATAL ERROR ==========\n";
    echo 'TYPE: ' . get_class($e) . "\n";
    echo 'MESSAGE: ' . $e->getMessage() . "\n";
    echo 'FILE: ' . $e->getFile() . "\n";
    echo 'LINE: ' . $e->getLine() . "\n";
    echo "=================================\n";
}