Files
2026-04-08 13:52:16 +02:00

183 lines
6.3 KiB
PHP

<?php
declare(strict_types=1);
/**
* Telegram-Transportfunktionen fuer Bot-Nachrichten und Dateiversand.
*
* Diese Datei kapselt die HTTP-Kommunikation mit der Telegram Bot API,
* sowohl fuer JSON-Requests als auch fuer Multipart-Uploads von Bildern
* und Dokumenten. Die Cron-Tasks muessen dadurch keine Request-Details kennen.
*/
require_once dirname(__DIR__, 3) . '/public/telegram/lib/http.php';
function telegramHttpPostMultipart(string $url, array $fields, string $fileField, string $filePath, ?string $fileName = null): array
{
if (!is_file($filePath)) {
return [
'ok' => false,
'error' => 'Datei fuer Telegram-Versand nicht gefunden: ' . $filePath,
'body' => null,
];
}
if (DIRECTORY_SEPARATOR === '\\' && function_exists('shell_exec')) {
$urlBase64 = base64_encode($url);
$filePathBase64 = base64_encode($filePath);
$fileNameBase64 = base64_encode((string) ($fileName ?? basename($filePath)));
$fieldsBase64 = base64_encode(json_encode($fields, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?: '{}');
$fileFieldBase64 = base64_encode($fileField);
$powerShellScript = str_replace(
['__URL_BASE64__', '__FILE_PATH_BASE64__', '__FILE_NAME_BASE64__', '__FIELDS_BASE64__', '__FILE_FIELD_BASE64__'],
[$urlBase64, $filePathBase64, $fileNameBase64, $fieldsBase64, $fileFieldBase64],
<<<'PS'
$ErrorActionPreference = 'Stop'
$url = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('__URL_BASE64__'))
$filePath = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('__FILE_PATH_BASE64__'))
$fileName = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('__FILE_NAME_BASE64__'))
$fileField = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('__FILE_FIELD_BASE64__'))
$fieldsJson = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('__FIELDS_BASE64__'))
$fieldsObject = $fieldsJson | ConvertFrom-Json
$form = @{}
foreach ($property in $fieldsObject.PSObject.Properties) {
$form[$property.Name] = [string] $property.Value
}
$form[$fileField] = Get-Item -LiteralPath $filePath
try {
$response = Invoke-RestMethod -Method Post -Uri $url -Form $form
[PSCustomObject]@{
ok = $true
body = ($response | ConvertTo-Json -Depth 20 -Compress)
error = ''
} | ConvertTo-Json -Compress
} catch {
[PSCustomObject]@{
ok = $false
body = ''
error = $_.Exception.Message
} | ConvertTo-Json -Compress
}
PS
);
$encodedCommandBinary = function_exists('iconv')
? iconv('UTF-8', 'UTF-16LE', $powerShellScript)
: $powerShellScript;
$encodedCommand = base64_encode($encodedCommandBinary === false ? $powerShellScript : $encodedCommandBinary);
$command = 'powershell -NoProfile -ExecutionPolicy Bypass -EncodedCommand ' . $encodedCommand;
$rawOutput = shell_exec($command);
if ($rawOutput !== null && trim($rawOutput) !== '') {
$decodedShell = json_decode(trim($rawOutput), true);
if (is_array($decodedShell)) {
return [
'ok' => (bool) ($decodedShell['ok'] ?? false),
'error' => $decodedShell['error'] ?? null,
'body' => $decodedShell['body'] ?? null,
];
}
}
}
if (function_exists('curl_init')) {
$payload = $fields;
$extension = strtolower((string) pathinfo($filePath, PATHINFO_EXTENSION));
$mimeType = match ($extension) {
'png' => 'image/png',
'jpg', 'jpeg' => 'image/jpeg',
'svg' => 'image/svg+xml',
default => 'application/octet-stream',
};
$payload[$fileField] = new CURLFile($filePath, $mimeType, $fileName ?? basename($filePath));
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$error = curl_error($ch);
return [
'ok' => $body !== false,
'error' => $body === false ? $error : null,
'body' => $body !== false ? $body : null,
];
}
return [
'ok' => false,
'error' => 'Multipart-Versand ist ohne curl nicht verfuegbar.',
'body' => null,
];
}
function telegramSendBotMessage(array $telegramConfig, string $chatId, string $messageText): bool
{
$botToken = trim((string) ($telegramConfig['bot_token'] ?? ''));
if ($botToken === '' || $chatId === '' || $messageText === '') {
return false;
}
$response = telegramHttpPostJson(
'https://api.telegram.org/bot' . $botToken . '/sendMessage',
[
'chat_id' => $chatId,
'text' => appendTelegramServiceFooter($messageText),
]
);
return (bool) ($response['ok'] ?? false);
}
function telegramSendBotDocument(array $telegramConfig, string $chatId, string $filePath, string $caption = ''): bool
{
$botToken = trim((string) ($telegramConfig['bot_token'] ?? ''));
if ($botToken === '' || $chatId === '' || !is_file($filePath)) {
return false;
}
$response = telegramHttpPostMultipart(
'https://api.telegram.org/bot' . $botToken . '/sendDocument',
[
'chat_id' => $chatId,
'caption' => appendTelegramServiceFooter($caption),
],
'document',
$filePath,
basename($filePath)
);
return (bool) ($response['ok'] ?? false);
}
function telegramSendBotPhoto(array $telegramConfig, string $chatId, string $filePath, string $caption = ''): bool
{
$botToken = trim((string) ($telegramConfig['bot_token'] ?? ''));
if ($botToken === '' || $chatId === '' || !is_file($filePath)) {
return false;
}
$response = telegramHttpPostMultipart(
'https://api.telegram.org/bot' . $botToken . '/sendPhoto',
[
'chat_id' => $chatId,
'caption' => appendTelegramServiceFooter($caption),
],
'photo',
$filePath,
basename($filePath)
);
return (bool) ($response['ok'] ?? false);
}