Initial commit: delta-chat-bot
This commit is contained in:
commit
8f47610133
10 changed files with 3603 additions and 0 deletions
120
php-proxy/media.php
Normal file
120
php-proxy/media.php
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
<?php
|
||||
/**
|
||||
* Telegram Media Proxy with cache
|
||||
*
|
||||
* GET /media.php?url=https://tg.i-c-a.su/media/CHANNEL/POSTID/HASH.ext
|
||||
*
|
||||
* Returns cached image or proxies from tg.i-c-a.su.
|
||||
* Old cache files are cleaned up probabilistically (~2% of requests).
|
||||
*/
|
||||
|
||||
define('IMG_DIR', __DIR__ . '/cache/img');
|
||||
define('TG_BASE', 'https://tg.i-c-a.su');
|
||||
define('UA', 'Mozilla/5.0 (compatible; ProxyBot/1.0)');
|
||||
define('MEDIA_TTL', 86400);
|
||||
|
||||
$url = $_GET['url'] ?? '';
|
||||
if (!$url || strpos($url, TG_BASE) !== 0) {
|
||||
header('HTTP/1.1 400 Bad Request');
|
||||
echo 'Invalid URL';
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!is_dir(IMG_DIR)) mkdir(IMG_DIR, 0755, true);
|
||||
|
||||
// Determine cache path from URL
|
||||
$path = parse_url($url, PHP_URL_PATH);
|
||||
$basename = basename($path);
|
||||
if (!preg_match('/\.\w+$/', $basename)) {
|
||||
$basename .= '.jpg';
|
||||
}
|
||||
$cacheFile = IMG_DIR . '/' . $basename;
|
||||
|
||||
// Content type map
|
||||
$extToType = [
|
||||
'jpg' => 'image/jpeg',
|
||||
'jpeg' => 'image/jpeg',
|
||||
'png' => 'image/png',
|
||||
'gif' => 'image/gif',
|
||||
'webp' => 'image/webp',
|
||||
];
|
||||
$ext = strtolower(pathinfo($basename, PATHINFO_EXTENSION));
|
||||
$contentType = $extToType[$ext] ?? 'image/jpeg';
|
||||
|
||||
// Periodic cleanup (~2% of requests)
|
||||
maybeCleanOldCache();
|
||||
|
||||
// Serve from cache if fresh
|
||||
if (file_exists($cacheFile) && filemtime($cacheFile) > time() - MEDIA_TTL) {
|
||||
header('Content-Type: ' . $contentType);
|
||||
header('Content-Length: ' . filesize($cacheFile));
|
||||
header('Cache-Control: public, max-age=' . MEDIA_TTL);
|
||||
header('X-Cache: HIT');
|
||||
readfile($cacheFile);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Fetch from tg.i-c-a.su
|
||||
$ctx = stream_context_create(['http' => ['timeout' => 60, 'user_agent' => UA, 'follow_location' => true]]);
|
||||
$data = @file_get_contents($url, false, $ctx);
|
||||
|
||||
if (!$data) {
|
||||
header('HTTP/1.1 502 Bad Gateway');
|
||||
echo 'Failed to fetch media';
|
||||
exit;
|
||||
}
|
||||
|
||||
// Verify it's actually an image before caching
|
||||
$imageSignatures = [
|
||||
"\xff\xd8\xff", // JPEG
|
||||
"\x89\x50\x4e\x47", // PNG
|
||||
"GIF87a", // GIF
|
||||
"GIF89a", // GIF
|
||||
"RIFF", // WebP
|
||||
];
|
||||
$isImage = false;
|
||||
foreach ($imageSignatures as $sig) {
|
||||
if (strncmp($data, $sig, strlen($sig)) === 0) {
|
||||
$isImage = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$isImage) {
|
||||
header('HTTP/1.1 415 Unsupported Media Type');
|
||||
header('Content-Type: text/plain');
|
||||
echo 'Not an image';
|
||||
exit;
|
||||
}
|
||||
|
||||
// Save to cache
|
||||
file_put_contents($cacheFile, $data);
|
||||
|
||||
// Return
|
||||
header('Content-Type: ' . $contentType);
|
||||
header('Content-Length: ' . strlen($data));
|
||||
header('Cache-Control: public, max-age=' . MEDIA_TTL);
|
||||
header('X-Cache: MISS');
|
||||
echo $data;
|
||||
|
||||
// Clean files older than TTL, runs ~2% of requests
|
||||
function maybeCleanOldCache(): void {
|
||||
if (rand(1, 50) !== 1) return;
|
||||
$dir = IMG_DIR;
|
||||
if (!is_dir($dir)) return;
|
||||
$cutoff = time() - MEDIA_TTL;
|
||||
$imgExts = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
|
||||
$dh = opendir($dir);
|
||||
if (!$dh) return;
|
||||
while (($f = readdir($dh)) !== false) {
|
||||
if ($f === '.' || $f === '..') continue;
|
||||
$fp = $dir . '/' . $f;
|
||||
if (!is_file($fp)) continue;
|
||||
$ext = strtolower(pathinfo($fp, PATHINFO_EXTENSION));
|
||||
// Remove non-image files and files older than TTL
|
||||
if (!in_array($ext, $imgExts) || filemtime($fp) < $cutoff) {
|
||||
unlink($fp);
|
||||
}
|
||||
}
|
||||
closedir($dh);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue