'111:token',
'chat' => '@username', // @username канала/чата или числовой id начинающийся с -100
'src' => 'truexanewsua', // источник
'first' => 10, // сколько постов репостить при первом запуске
'ads' => '~\s*\|?\s*(ТРУХА|Надіслати новину).*$~us', // регэксп рекламного хвоста
'skip_words' => ['промокод', 'реклама', 'партнерська', '#ad'], // слова в тексте поста -> скип
'skip_links' => ['bit.ly', 'cutt.ly', 't.me/+'], // подстроки в ссылках текста и url-кнопок -> скип
'skip_buttons' => true, // скипать любой пост с url-кнопками
];
const TEXT_LIMIT = 4096; // лимит текста сообщения (premium: 8192)
const CAPTION_LIMIT = 1024; // лимит подписи к медиа (premium: 4096)
function apiGet(string $method, array $params) {
global $config;
$response = @file_get_contents(
"https://api.telegram.org/bot{$config['bot']}/$method?" . http_build_query($params),
false,
stream_context_create(['http' => ['ignore_errors' => true, 'timeout' => 30]])
);
if ($response === false) return false;
$decoded = json_decode($response, true) ?: [];
empty($decoded['ok']) and exitIfChatForbidden($decoded);
return $decoded;
}
function apiUpload(string $method, array $params) {
global $config;
$curl = curl_init("https://api.telegram.org/bot{$config['bot']}/$method");
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_POSTFIELDS => $params,
CURLOPT_TIMEOUT => 300,
CURLOPT_CONNECTTIMEOUT => 10,
]);
$response = curl_exec($curl);
curl_close($curl);
if ($response === false) return false;
$decoded = json_decode($response, true) ?: [];
empty($decoded['ok']) and exitIfChatForbidden($decoded);
return $decoded;
}
function exitIfChatForbidden(array $response): void {
if (($response['error_code'] ?? 0) == 403 || str_contains($response['description'] ?? '', 'chat not found')) exit(2);
}
function randomUserAgent() {
$desktop = ['Windows NT 10.0; Win64; x64', 'Windows NT 11.0; Win64; x64',
'Macintosh; Intel Mac OS X 10_15_7', 'X11; Linux x86_64'][rand(0, 3)];
$webkit = 'AppleWebKit/537.36 (KHTML, like Gecko)';
$chrome = 'Chrome/' . rand(126, 132) . '.0.' . rand(6000, 6900) . '.' . rand(30, 220);
return match (rand(1, 5)) {
1 => "Mozilla/5.0 ($desktop) $webkit $chrome Safari/537.36",
2 => "Mozilla/5.0 ($desktop) $webkit $chrome Safari/537.36 Edg/" . rand(126, 132) . '.0.0.0',
3 => "Mozilla/5.0 ($desktop; rv:" . ($firefox = rand(130, 134)) . ".0) Gecko/20100101 Firefox/$firefox.0",
4 => "Mozilla/5.0 (Linux; Android " . rand(12, 15) . '; SM-S' . rand(911, 928) . "B) $webkit $chrome Mobile Safari/537.36",
5 => 'Mozilla/5.0 (iPhone; CPU iPhone OS ' . rand(16, 18) . '_' . rand(0, 6) . ' like Mac OS X) AppleWebKit/605.1.15'
. ' (KHTML, like Gecko) Version/' . rand(16, 18) . '.' . rand(0, 6) . ' Mobile/15E148 Safari/604.1',
};
}
for ($attempt = 0; $attempt < 3; $attempt++) {
$html = @file_get_contents("https://t.me/s/{$config['src']}", false, stream_context_create([
'http' => ['header' => 'User-Agent: ' . randomUserAgent(), 'timeout' => 30, 'ignore_errors' => true],
]));
if (str_contains((string)$html, 'data-post')) break;
sleep(2);
}
str_contains((string)$html, 'data-post') or exit("fetch fail\n");
preg_match_all(
'~data-post="' . $config['src'] . '/(\d+)".*?(?=
str_contains($url, '.mp4') || str_contains($url, '.mov') ? 'video' : 'photo';
$mimeType = fn($type, $url) => $type == 'video' ? (str_contains($url, '.mov') ? 'video/quicktime' : 'video/mp4') : 'image/jpeg';
$truncate = fn($text, $limit) => mb_strlen($text) > $limit ? mb_substr($text, 0, $limit - 1) . '…' : $text;
$fileIdCache = json_decode(@file_get_contents("$stateFile.m") ?: '[]', true) ?: [];
$lastProcessedId = 0; $networkFailed = false; $caption = '';
$sendTextFallback = function () use (&$networkFailed, $config, &$caption, $truncate) {
if ($caption === '') return;
$decoded = apiGet('sendMessage', ['chat_id' => $config['chat'], 'text' => $truncate($caption, TEXT_LIMIT)]);
$decoded === false and $networkFailed = true;
};
foreach ($posts as $post) {
if ($post[1] <= $lastPostedId) continue;
preg_match('~message_text[^>]*>(.*?)
~s', $post[0], $textMatch);
preg_match_all("~photo_wrap[^>]*url\('([^']+)'~", $post[0], $photos);
preg_match_all('~