<?php

$BOT_TOKEN = '7823454938:AAHdzr_aJ3ayP-gNIat0OXO7kKQ0yC7EPE8';
$CHAT_ID = -1003890654433;

$GROQ_API_KEY = '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';





$PAGES = [

    [
        'username' => 'DiscussingFilm',
        'topic_id' => 3
    ],

    [
        'username' => 'HollywoodHandle',
        'topic_id' => 13
    ],

    [
        'username' => 'FilmUpdates',
        'topic_id' => 33
    ],

    [
        'username' => 'indiewire',
        'topic_id' => 72
    ],

    [
        'username' => 'collider',
        'topic_id' => 74
    ],

    [
        'username' => 'hbo',
        'topic_id' => 76
    ],
    [
        "username"=>"movie_plugke",
        "topic_id"=>538
        ],
           [
        "username"=>"PopcornPlug_",
        "topic_id"=>540
       ],
              [
        "username"=>"CinemaTweets1",
        "topic_id"=>542
       ],
               [
        "username"=>"filmstofilms_",
        "topic_id"=>544
       ],
                [
        "username"=>"everymovieplug",
        "topic_id"=>546
       ],
                [
        "username"=>"FabrizioRomano",
        "topic_id"=>3820
       ]
        

];


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


/*
|--------------------------------------------------------------------------
| SETTINGS
|--------------------------------------------------------------------------
*/

date_default_timezone_set('Asia/Tehran');

$MAX_GROQ_RETRIES = 3;

$GROQ_DELAY = 3;

$POST_DELAY = 2;


/*
|--------------------------------------------------------------------------
| LOG
|--------------------------------------------------------------------------
*/

function logMessage($message)
{
    echo $message . "\n";
}


/*
|--------------------------------------------------------------------------
| HTTP GET
|--------------------------------------------------------------------------
*/

function httpGet($url)
{
    $ch = curl_init($url);

    curl_setopt_array($ch, [

        CURLOPT_RETURNTRANSFER => true,

        CURLOPT_FOLLOWLOCATION => true,

        CURLOPT_MAXREDIRS => 5,

        CURLOPT_CONNECTTIMEOUT => 15,

        CURLOPT_TIMEOUT => 30,

        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);

    $status = curl_getinfo(
        $ch,
        CURLINFO_HTTP_CODE
    );

    /*
    |--------------------------------------------------------------------------
    | PHP 8.5
    |--------------------------------------------------------------------------
    |
    | curl_close() deprecated.
    | Release reference when function ends.
    |
    */

    unset($ch);

    return [

        'ok' =>
            $body !== false &&
            $status >= 200 &&
            $status < 400,

        'body' =>
            $body ?: '',

        'status' =>
            $status,

        'error' =>
            $error

    ];
}


/*
|--------------------------------------------------------------------------
| TELEGRAM
|--------------------------------------------------------------------------
*/

function telegram($method, $data)
{
    global $BOT_TOKEN;

    $url =
        "https://api.telegram.org/bot{$BOT_TOKEN}/{$method}";

    $ch = curl_init($url);

    curl_setopt_array($ch, [

        CURLOPT_POST => true,

        CURLOPT_POSTFIELDS => $data,

        CURLOPT_RETURNTRANSFER => true,

        CURLOPT_CONNECTTIMEOUT => 15,

        CURLOPT_TIMEOUT => 60

    ]);

    $response = curl_exec($ch);

    $error = curl_error($ch);

    unset($ch);

    if ($response === false) {

        return [

            'ok' => false,

            'error' => $error

        ];
    }

    $decoded =
        json_decode(
            $response,
            true
        );

    if (!is_array($decoded)) {

        return [

            'ok' => false,

            'error' => $response

        ];
    }

    return $decoded;
}


/*
|--------------------------------------------------------------------------
| GROQ TRANSLATION
|--------------------------------------------------------------------------
*/

function translateToPersian($title, $text)
{
    global $GROQ_API_KEY;
    global $MAX_GROQ_RETRIES;
    global $GROQ_DELAY;

    $title = trim($title);

    $text = trim($text);


    /*
    |--------------------------------------------------------------------------
    | Original fallback
    |--------------------------------------------------------------------------
    */

    $original = $title;

    if (
        $text !== '' &&
        $text !== $title
    ) {

        $original .=
            "\n\n" .
            $text;
    }


    if ($original === '') {

        return [

            'success' => false,

            'text' => ''

        ];
    }


    /*
    |--------------------------------------------------------------------------
    | Groq API
    |--------------------------------------------------------------------------
    */

    $url =
        'https://api.groq.com/openai/v1/chat/completions';


    $input =
        "TITLE:\n" .
        $title .
        "\n\n" .
        "TEXT:\n" .
        $text;


    $payload = [

        'model' =>
            'llama-3.1-8b-instant',

        'messages' => [

            [

                'role' =>
                    'system',

                'content' =>
                    'Translate English movie and TV news into natural Persian. ' .
                    'Return ONLY the Persian translation. ' .
                    'Preserve movie, TV show, actor and character names naturally. ' .
                    'Do not add explanations. ' .
                    'Do not translate URLs. ' .
                    'Keep paragraph structure. ' .
                    'Do not add a title or commentary.'

            ],

            [

                'role' =>
                    'user',

                'content' =>
                    $input

            ]

        ],

        'temperature' =>
            0.2,

        'max_tokens' =>
            700

    ];


    for (
        $attempt = 1;
        $attempt <= $MAX_GROQ_RETRIES;
        $attempt++
    ) {

        /*
        |--------------------------------------------------------------------------
        | Delay between requests
        |--------------------------------------------------------------------------
        */

        if ($attempt > 1) {

            sleep($GROQ_DELAY);
        }


        $ch =
            curl_init($url);


        curl_setopt_array($ch, [

            CURLOPT_POST =>
                true,

            CURLOPT_RETURNTRANSFER =>
                true,

            CURLOPT_CONNECTTIMEOUT =>
                15,

            CURLOPT_TIMEOUT =>
                60,

            CURLOPT_HTTPHEADER => [

                'Authorization: Bearer ' .
                $GROQ_API_KEY,

                'Content-Type: application/json'

            ],

            CURLOPT_POSTFIELDS =>
                json_encode(
                    $payload,
                    JSON_UNESCAPED_UNICODE |
                    JSON_UNESCAPED_SLASHES
                )

        ]);


        $response =
            curl_exec($ch);


        $httpCode =
            curl_getinfo(
                $ch,
                CURLINFO_HTTP_CODE
            );


        $error =
            curl_error($ch);


        unset($ch);


        /*
        |--------------------------------------------------------------------------
        | CURL ERROR
        |--------------------------------------------------------------------------
        */

        if ($response === false) {

            logMessage(
                "GROQ CURL ERROR: {$error}"
            );

            continue;
        }


        $data =
            json_decode(
                $response,
                true
            );


        /*
        |--------------------------------------------------------------------------
        | RATE LIMIT
        |--------------------------------------------------------------------------
        */

        if ($httpCode === 429) {

            $wait = 15;


            if (
                isset(
                    $data['error']['message']
                )
            ) {

                logMessage(
                    'GROQ RATE LIMIT: ' .
                    $data['error']['message']
                );
            }


            logMessage(
                "Waiting {$wait}s..."
            );


            sleep($wait);

            continue;
        }


        /*
        |--------------------------------------------------------------------------
        | OTHER ERROR
        |--------------------------------------------------------------------------
        */

        if (
            $httpCode < 200 ||
            $httpCode >= 300
        ) {

            logMessage(
                "GROQ ERROR HTTP {$httpCode}"
            );

            logMessage(
                $response
            );

            return [

                'success' =>
                    false,

                'text' =>
                    $original

            ];
        }


        /*
        |--------------------------------------------------------------------------
        | TRANSLATION
        |--------------------------------------------------------------------------
        */

        $translated =
            $data['choices'][0]['message']['content']
            ?? null;


        if (
            is_string($translated) &&
            trim($translated) !== ''
        ) {

            return [

                'success' =>
                    true,

                'text' =>
                    trim($translated)

            ];
        }


        logMessage(
            'GROQ returned empty translation.'
        );

        break;
    }


    /*
    |--------------------------------------------------------------------------
    | FAILED
    |--------------------------------------------------------------------------
    */

    return [

        'success' =>
            false,

        'text' =>
            $original

    ];
}


/*
|--------------------------------------------------------------------------
| CLEAN TEXT
|--------------------------------------------------------------------------
*/

function cleanText($text)
{
    $text =
        strip_tags($text);


    $text =
        html_entity_decode(
            $text,
            ENT_QUOTES | ENT_HTML5,
            'UTF-8'
        );


    $text =
        preg_replace(
            '/\s+/u',
            ' ',
            $text
        );


    return trim($text);
}


/*
|--------------------------------------------------------------------------
| EXTRACT IMAGES
|--------------------------------------------------------------------------
*/

function extractImages($description)
{
    $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;
}


/*
|--------------------------------------------------------------------------
| VIDEO
|--------------------------------------------------------------------------
*/

function hasVideo($description)
{
    return
        stripos(
            $description,
            '>Video<'
        ) !== false
        ||
        preg_match(
            '/<a[^>]+>.*?Video.*?<\/a>/is',
            $description
        );
}


/*
|--------------------------------------------------------------------------
| NITTER -> FXTWITTER
|--------------------------------------------------------------------------
*/

function toFxTwitter($url)
{
    $url =
        preg_replace(
            '/#.*$/',
            '',
            $url
        );


    return preg_replace(

        '/^https?:\/\/(?:www\.)?nitter\.net/i',

        'https://fxtwitter.com',

        $url

    );
}


/*
|--------------------------------------------------------------------------
| PERSIAN DATE
|--------------------------------------------------------------------------
*/

function persianDate($date)
{
    $timestamp =
        strtotime($date);


    if ($timestamp === false) {

        return '';
    }


    /*
    |--------------------------------------------------------------------------
    | Gregorian -> Jalali
    |--------------------------------------------------------------------------
    */

    $gy =
        (int)date('Y', $timestamp);

    $gm =
        (int)date('n', $timestamp);

    $gd =
        (int)date('j', $timestamp);


    $g_d_m = [

        0,

        31,

        59,

        90,

        120,

        151,

        181,

        212,

        243,

        273,

        304,

        334

    ];


    if ($gy > 1600) {

        $jy = 979;

        $gy -= 1600;

    } else {

        $jy = 0;

        $gy -= 621;

    }


    $gy2 =
        ($gm > 2)
            ? $gy + 1
            : $gy;


    $days =
        (365 * $gy)
        + floor(($gy2 + 3) / 4)
        - floor(($gy2 + 99) / 100)
        + floor(($gy2 + 399) / 400)
        - 80
        + $gd
        + $g_d_m[$gm - 1];


    $jy +=
        33 * floor($days / 12053);


    $days %= 12053;


    $jy +=
        4 * floor($days / 1461);


    $days %= 1461;


    if ($days > 365) {

        $jy +=
            floor(($days - 1) / 365);

        $days =
            ($days - 1) % 365;
    }


    if ($days < 186) {

        $jm =
            1 + floor($days / 31);

        $jd =
            1 + ($days % 31);

    } else {

        $jm =
            7 + floor(($days - 186) / 30);

        $jd =
            1 + (($days - 186) % 30);
    }


    return
        sprintf(
            '%04d/%02d/%02d',
            $jy,
            $jm,
            $jd
        );
}


/*
|--------------------------------------------------------------------------
| FORMAT DATE
|--------------------------------------------------------------------------
*/

function formatDate($pubDate)
{
    if (
        trim($pubDate) === ''
    ) {

        return '';
    }


    $timestamp =
        strtotime($pubDate);


    if ($timestamp === false) {

        return '';
    }


    $persian =
        persianDate($pubDate);


    $time =
        date(
            'H:i',
            $timestamp
        );


    return
        $persian .
        ' | ' .
        $time;
}


/*
|--------------------------------------------------------------------------
| BUILD CAPTION
|--------------------------------------------------------------------------
*/

function buildCaption($item)
{
    logMessage(
        'Translating...'
    );


    $translation =
        translateToPersian(

            $item['title'],

            $item['text']

        );


    if (
        $translation['success']
    ) {

        $caption =
            $translation['text'];

    } else {

        logMessage(
            '⚠️ TRANSLATION FAILED - using original'
        );


        $caption =
            $translation['text'] .
            "\n\n⚠️ ترجمه ناموفق بود";
    }


    /*
    |--------------------------------------------------------------------------
    | Date
    |--------------------------------------------------------------------------
    */

    if (
        $item['date'] !== ''
    ) {

        $caption .=
            "\n\n📅 " .
            $item['date'];
    }


    /*
    |--------------------------------------------------------------------------
    | Source
    |--------------------------------------------------------------------------
    */

    if (
        $item['url'] !== ''
    ) {

        $source =
            toFxTwitter(
                $item['url']
            );


        $caption .=
            "\n🔗 منبع: " .
            $source;
    }


    return [

        'caption' =>
            $caption,

        'translation_failed' =>
            !$translation['success']

    ];
}


/*
|--------------------------------------------------------------------------
| CAPTION LIMIT
|--------------------------------------------------------------------------
*/

function limitCaption($caption)
{
    if (
        mb_strlen(
            $caption,
            'UTF-8'
        ) <= 1024
    ) {

        return $caption;
    }


    return
        mb_substr(
            $caption,
            0,
            1000,
            'UTF-8'
        ) .
        '...';
}


/*
|--------------------------------------------------------------------------
| SEND ALBUM CHUNK
|--------------------------------------------------------------------------
*/

function sendAlbumChunk(
    $images,
    $caption,
    $topicId,
    $firstChunk = true
) {
    global $CHAT_ID;


    $media = [];


    foreach (
        $images
        as $index => $image
    ) {

        $photo = [

            'type' =>
                'photo',

            'media' =>
                $image

        ];


        if (
            $firstChunk &&
            $index === 0
        ) {

            $photo['caption'] =
                limitCaption(
                    $caption
                );
        }


        $media[] =
            $photo;
    }


    return telegram(

        'sendMediaGroup',

        [

            'chat_id' =>
                $CHAT_ID,

            'message_thread_id' =>
                $topicId,

            'media' =>
                json_encode(
                    $media,
                    JSON_UNESCAPED_UNICODE |
                    JSON_UNESCAPED_SLASHES
                )

        ]

    );
}


/*
|--------------------------------------------------------------------------
| SEND POST
|--------------------------------------------------------------------------
*/

function sendPost($item, $topicId)
{
    global $CHAT_ID;


    /*
    |--------------------------------------------------------------------------
    | Build caption
    |--------------------------------------------------------------------------
    */

    $captionData =
        buildCaption($item);


    $caption =
        $captionData['caption'];


    /*
    |--------------------------------------------------------------------------
    | VIDEO
    |--------------------------------------------------------------------------
    */

    if (
        $item['has_video']
    ) {

        $videoUrl =
            toFxTwitter(
                $item['url']
            );


        logMessage(
            'Video URL: ' .
            $videoUrl
        );


        return telegram(

            'sendVideo',

            [

                'chat_id' =>
                    $CHAT_ID,

                'message_thread_id' =>
                    $topicId,

                'video' =>
                    $videoUrl,

                'caption' =>
                    limitCaption(
                        $caption
                    )

            ]

        );
    }


    /*
    |--------------------------------------------------------------------------
    | IMAGES
    |--------------------------------------------------------------------------
    */

    if (
        !empty(
            $item['images']
        )
    ) {

        $images =
            $item['images'];


        /*
        |--------------------------------------------------------------------------
        | ONE IMAGE
        |--------------------------------------------------------------------------
        */

        if (
            count($images) === 1
        ) {

            return telegram(

                'sendPhoto',

                [

                    'chat_id' =>
                        $CHAT_ID,

                    'message_thread_id' =>
                        $topicId,

                    'photo' =>
                        $images[0],

                    'caption' =>
                        limitCaption(
                            $caption
                        )

                ]

            );
        }


        /*
        |--------------------------------------------------------------------------
        | TELEGRAM MAX = 10
        |--------------------------------------------------------------------------
        */

        $chunks =
            array_chunk(
                $images,
                10
            );


        logMessage(
            'Album parts: ' .
            count($chunks)
        );


        foreach (
            $chunks
            as $chunkIndex => $chunk
        ) {

            logMessage(
                'Sending album part ' .
                ($chunkIndex + 1) .
                '/' .
                count($chunks)
            );


            $result =
                sendAlbumChunk(

                    $chunk,

                    $caption,

                    $topicId,

                    $chunkIndex === 0

                );


            if (
                !isset(
                    $result['ok']
                ) ||
                $result['ok'] !== true
            ) {

                return $result;
            }


            /*
            |--------------------------------------------------------------------------
            | Telegram albums should not be hammered
            |--------------------------------------------------------------------------
            */

            if (
                $chunkIndex <
                count($chunks) - 1
            ) {

                sleep(2);
            }
        }


        return [

            'ok' =>
                true

        ];
    }


    /*
    |--------------------------------------------------------------------------
    | TEXT
    |--------------------------------------------------------------------------
    */

    return telegram(

        'sendMessage',

        [

            'chat_id' =>
                $CHAT_ID,

            'message_thread_id' =>
                $topicId,

            'text' =>
                $caption

        ]

    );
}


/*
|--------------------------------------------------------------------------
| LOAD SENT
|--------------------------------------------------------------------------
*/

if (
    file_exists(
        $SENT_FILE
    )
) {

    $sent =
        json_decode(

            file_get_contents(
                $SENT_FILE
            ),

            true

        );


    if (
        !is_array($sent)
    ) {

        $sent = [];
    }

} else {

    $sent = [];
}


/*
|--------------------------------------------------------------------------
| START
|--------------------------------------------------------------------------
*/

logMessage(
    'START'
);


foreach (
    $PAGES
    as $page
) {

    $username =
        $page['username'];


    $topicId =
        $page['topic_id'];


    logMessage(
        "\n================================"
    );


    logMessage(
        "PAGE: {$username}"
    );


    /*
    |--------------------------------------------------------------------------
    | RSS
    |--------------------------------------------------------------------------
    */

    $rssUrl =
        'https://nitter.net/' .
        rawurlencode(
            $username
        ) .
        '/rss';


    logMessage(
        "RSS: {$rssUrl}"
    );


    $rss =
        httpGet(
            $rssUrl
        );


    if (
        !$rss['ok']
    ) {

        logMessage(
            "RSS ERROR: {$rss['status']}"
        );


        logMessage(
            $rss['error']
        );


        continue;
    }


    logMessage(
        'RSS OK'
    );


    logMessage(
        'RSS LENGTH: ' .
        strlen(
            $rss['body']
        )
    );


    /*
    |--------------------------------------------------------------------------
    | XML
    |--------------------------------------------------------------------------
    */

    libxml_use_internal_errors(
        true
    );


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


    if (
        $xml === false
    ) {

        logMessage(
            'XML ERROR'
        );

        continue;
    }


    $items =
        $xml->channel->item;


    logMessage(
        'FOUND: ' .
        count($items) .
        ' POSTS'
    );


    /*
    |--------------------------------------------------------------------------
    | ITEMS
    |--------------------------------------------------------------------------
    */

    foreach (
        $items
        as $rssItem
    ) {

        $id =
            trim(
                (string)$rssItem->guid
            );


        if (
            $id === ''
        ) {

            continue;
        }


        $uniqueId =
            $username .
            ':' .
            $id;


        /*
        |--------------------------------------------------------------------------
        | Already sent
        |--------------------------------------------------------------------------
        */

        if (
            isset(
                $sent[$uniqueId]
            )
        ) {

            continue;
        }


        /*
        |--------------------------------------------------------------------------
        | TITLE
        |--------------------------------------------------------------------------
        */

        $title =
            cleanText(
                (string)$rssItem->title
            );


        /*
        |--------------------------------------------------------------------------
        | DESCRIPTION
        |--------------------------------------------------------------------------
        */

        $description =
            (string)$rssItem->description;


        $text =
            cleanText(
                $description
            );


        /*
        |--------------------------------------------------------------------------
        | Remove Video
        |--------------------------------------------------------------------------
        */

        $text =
            preg_replace(
                '/\bVideo\b/i',
                '',
                $text
            );


        $text =
            trim(
                $text
            );


        /*
        |--------------------------------------------------------------------------
        | URL
        |--------------------------------------------------------------------------
        */

        $postUrl =
            trim(
                (string)$rssItem->link
            );


        /*
        |--------------------------------------------------------------------------
        | DATE
        |--------------------------------------------------------------------------
        */

        $pubDate =
            trim(
                (string)$rssItem->pubDate
            );


        $formattedDate =
            formatDate(
                $pubDate
            );


        /*
        |--------------------------------------------------------------------------
        | MEDIA
        |--------------------------------------------------------------------------
        */

        $images =
            extractImages(
                $description
            );


        $video =
            hasVideo(
                $description
            );


        /*
        |--------------------------------------------------------------------------
        | ITEM
        |--------------------------------------------------------------------------
        */

        $item = [

            'id' =>
                $id,

            'title' =>
                $title,

            'text' =>
                $text,

            'url' =>
                $postUrl,

            'date' =>
                $formattedDate,

            'images' =>
                $images,

            'has_video' =>
                $video

        ];


        logMessage(
            "\nSending: {$id}"
        );


        logMessage(
            'Video: ' .
            (
                $video
                    ? 'YES'
                    : 'NO'
            )
        );


        logMessage(
            'Images: ' .
            count($images)
        );


        logMessage(
            'Date: ' .
            (
                $formattedDate !== ''
                    ? $formattedDate
                    : 'UNKNOWN'
            )
        );


        /*
        |--------------------------------------------------------------------------
        | SEND
        |--------------------------------------------------------------------------
        */

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


        /*
        |--------------------------------------------------------------------------
        | SUCCESS
        |--------------------------------------------------------------------------
        */

        if (
            isset(
                $result['ok']
            ) &&
            $result['ok'] === true
        ) {

            logMessage(
                'TELEGRAM: OK'
            );


            /*
            |--------------------------------------------------------------------------
            | IMPORTANT
            |--------------------------------------------------------------------------
            |
            | فقط در RAM ذخیره می‌کنیم.
            | فایل در پایان کل برنامه نوشته می‌شود.
            |
            */

            $sent[$uniqueId] =
                time();

        } else {

            logMessage(
                'TELEGRAM ERROR:'
            );


            logMessage(

                json_encode(

                    $result,

                    JSON_UNESCAPED_UNICODE |
                    JSON_PRETTY_PRINT

                )

            );
        }


        /*
        |--------------------------------------------------------------------------
        | Delay
        |--------------------------------------------------------------------------
        */

        sleep($POST_DELAY);
    }
}


/*
|--------------------------------------------------------------------------
| SAVE SENT ONCE
|--------------------------------------------------------------------------
*/

if (
    file_put_contents(

        $SENT_FILE,

        json_encode(

            $sent,

            JSON_UNESCAPED_UNICODE |
            JSON_PRETTY_PRINT

        ),

        LOCK_EX

    ) === false
) {

    logMessage(
        'WARNING: Could not save sent.json'
    );

} else {

    logMessage(
        'sent.json saved.'
    );
}


logMessage(
    "\nDONE"
);

