Telegram Cron umgebaut
This commit is contained in:
@@ -0,0 +1,299 @@
|
||||
<?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.
|
||||
*/
|
||||
|
||||
function telegramHttpPostJson(string $url, array $payload): array
|
||||
{
|
||||
$jsonPayload = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
if ($jsonPayload === false) {
|
||||
return [
|
||||
'ok' => false,
|
||||
'error' => 'Die Telegram-Anfrage konnte nicht als JSON kodiert werden.',
|
||||
'body' => null,
|
||||
];
|
||||
}
|
||||
|
||||
if (DIRECTORY_SEPARATOR === '\\' && function_exists('shell_exec')) {
|
||||
$urlBase64 = base64_encode($url);
|
||||
$payloadBase64 = base64_encode($jsonPayload);
|
||||
$powerShellScript = str_replace(
|
||||
['__URL_BASE64__', '__PAYLOAD_BASE64__'],
|
||||
[$urlBase64, $payloadBase64],
|
||||
<<<'PS'
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$url = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('__URL_BASE64__'))
|
||||
$body = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('__PAYLOAD_BASE64__'))
|
||||
try {
|
||||
$response = Invoke-RestMethod -Method Post -Uri $url -ContentType 'application/json' -Body $body
|
||||
[PSCustomObject]@{
|
||||
ok = $true
|
||||
body = ($response | ConvertTo-Json -Depth 20 -Compress)
|
||||
error = ''
|
||||
} | ConvertTo-Json -Compress
|
||||
} catch {
|
||||
$stream = $null
|
||||
$responseBody = ''
|
||||
if ($_.Exception.Response) {
|
||||
try {
|
||||
$stream = $_.Exception.Response.GetResponseStream()
|
||||
if ($stream) {
|
||||
$reader = New-Object System.IO.StreamReader($stream)
|
||||
$responseBody = $reader.ReadToEnd()
|
||||
}
|
||||
} catch {
|
||||
} finally {
|
||||
if ($stream) {
|
||||
$stream.Dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
[PSCustomObject]@{
|
||||
ok = $false
|
||||
body = $responseBody
|
||||
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')) {
|
||||
$ch = curl_init($url);
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_HTTPHEADER => [
|
||||
'Content-Type: application/json',
|
||||
'Content-Length: ' . strlen($jsonPayload),
|
||||
],
|
||||
CURLOPT_POSTFIELDS => $jsonPayload,
|
||||
CURLOPT_TIMEOUT => 20,
|
||||
]);
|
||||
|
||||
$body = curl_exec($ch);
|
||||
$error = curl_error($ch);
|
||||
curl_close($ch);
|
||||
|
||||
return [
|
||||
'ok' => $body !== false,
|
||||
'error' => $body === false ? $error : null,
|
||||
'body' => $body !== false ? $body : null,
|
||||
];
|
||||
}
|
||||
|
||||
$context = stream_context_create([
|
||||
'http' => [
|
||||
'method' => 'POST',
|
||||
'header' => implode("\r\n", [
|
||||
'Content-Type: application/json',
|
||||
'Content-Length: ' . strlen($jsonPayload),
|
||||
]),
|
||||
'content' => $jsonPayload,
|
||||
'timeout' => 20,
|
||||
'ignore_errors' => true,
|
||||
],
|
||||
]);
|
||||
|
||||
$body = @file_get_contents($url, false, $context);
|
||||
|
||||
return [
|
||||
'ok' => $body !== false,
|
||||
'error' => $body === false ? 'HTTP-Request fehlgeschlagen.' : null,
|
||||
'body' => $body !== false ? $body : null,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
curl_close($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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user