183 lines
6.3 KiB
PHP
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__, 2) . '/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);
|
|
}
|
|
|
|
|