From dcd7be98169b9e881f2330e8f2e0a72acbc1b277 Mon Sep 17 00:00:00 2001 From: Fasutoa Date: Wed, 18 Jun 2025 22:40:52 +0500 Subject: [PATCH] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D1=88=D0=B8=D0=B5=D1=81=D1=8F=20?= =?UTF-8?q?=D1=84=D0=B0=D0=B9=D0=BB=D1=8B=20=D0=BF=D0=BE=20=D1=82=D0=B3=20?= =?UTF-8?q?+=20=D0=BF=D0=BE=D0=B4=D1=81=D1=82=D1=80=D0=BE=D0=B9=D0=BA?= =?UTF-8?q?=D0=B0=20=D0=BA=D0=BE=D0=BD=D1=84=D0=B8=D0=B3=D0=B0=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=B4=20=D1=82=D0=B5=D0=BB=D0=B5=D0=B3=D1=80=D0=B0=D1=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 6148 -> 6148 bytes app/.DS_Store | Bin 8196 -> 8196 bytes app/Jobs/CreateTgPostJob.php | 2 +- app/Services/.DS_Store | Bin 6148 -> 6148 bytes app/Services/Telegram/Handler.php | 179 +++++++++++++++++++++++ app/Services/Telegram/TgService.php | 214 ++++++++++++++++++++++++++++ config/telegraph.php | 214 ++++++++++++++++++++++++++++ 7 files changed, 608 insertions(+), 1 deletion(-) create mode 100644 app/Services/Telegram/Handler.php create mode 100644 app/Services/Telegram/TgService.php create mode 100644 config/telegraph.php diff --git a/.DS_Store b/.DS_Store index 665f35e172496a8c97c6b7f7690a67edaff7346c..df15b32dd068b1485cdc86358b612d8daed816b0 100644 GIT binary patch delta 55 zcmZoMXfc@J&&atkU^g=(=VTrhLoqgnWQKf(JccxeOosH7;^ds9{QMk-$%3pRoBdc8 LFmGn(_{$FfmmCiU delta 31 ncmZoMXfc@J&&aVcU^g=($7CKB!_8qV8<{6INN#55_{$FfnGy-6 diff --git a/app/.DS_Store b/app/.DS_Store index 852a6e2efa3bbdecdbea26c8f1e0d72ff70d3a54..ec6d776905ba5a883102440bdf190ec8951c4307 100644 GIT binary patch delta 25 gcmZp1XmQvOAk4_HIZ)V)k&$8YIuWtW^F-3P0bvIREdT%j delta 25 gcmZp1XmQvOAk4_PIZ)V)k&$uoIuWtW^F-3P0bwEsF8}}l diff --git a/app/Jobs/CreateTgPostJob.php b/app/Jobs/CreateTgPostJob.php index 25fea7d..fec1f75 100644 --- a/app/Jobs/CreateTgPostJob.php +++ b/app/Jobs/CreateTgPostJob.php @@ -44,7 +44,7 @@ class CreateTgPostJob implements ShouldQueue public function handle() { - $chat = TelegraphChat::find(4); + $chat = TelegraphChat::find(1); $baseUrl = config('app.url'); $messageIds = []; $captionSent = false; diff --git a/app/Services/.DS_Store b/app/Services/.DS_Store index 65573c975ea38610b836ae189b211668532b84fe..ab243f34a5e03a47efce7bf5305865ccc50cadb4 100644 GIT binary patch delta 136 zcmZoMXfc=|&e%3FQH+&?fq{WzVxovF6OaJ{AexbZL4biFouP;!ks&vwI5}rxqB>Xs z2SW%$DnkwsBS|LZ=jTk+mf4u?%s$ybgk>`~2M-5h+s4H2%#-;=6h%P>Dgbc;5CaWn OH~_>9n;k{=GXntaZW?<4 delta 81 zcmZoMXfc=|&Zs)EPlatest('publish_at')->first(); + +// if (!$post) { +// $this->reply("Нет опубликованных постов для отправки"); +// return; +// } + $chat = TelegraphChat::find(4); + log::info($chat); + $chat->markdown('zov')->send(); + + $message = ''; + + $message .= "*{$post->title}*\n\n"; + + if (is_array($post->content)) { + $message .= $this->parseContentBlocks($post->content); + } elseif (is_string($post->content)) { + $contentBlocks = json_decode($post->content, true); + if (is_array($contentBlocks)) { + $message .= $this->parseContentBlocks($contentBlocks); + } else { + $message .= $this->convertToMarkdown($post->content); + } + } else { + $message .= $this->convertToMarkdown((string) $post->content); + } + + if ($post->slug) { + $url = config('app.url') . "posts/{$post->slug}"; + $message .= "\n\n[Читать полностью]($url)"; + } + + // Отправляем сообщение с Markdown +// $this->chat->markdown($message)->send(); + + // Обработка изображений и отправка сообщения в Telegram + if ($post->images) { + $images = is_string($post->images) ? json_decode($post->images, true) : $post->images; + $baseUrl = config('app.url'); // Базовый URL, например, https://your-domain.com + + if (is_array($images) && !empty($images)) { + $mediaGroup = []; + foreach ($images as $index => $image) { + $mediaItem = [ + 'type' => 'photo', + 'media' => config('app.url') . 'storage/' . ltrim($image, '/'), + ]; + // Добавляем текст только к первому изображению + if ($index === 0) { + $mediaItem['caption'] = $message; // Основной текст поста + $mediaItem['parse_mode'] = 'Markdown'; // Поддержка Markdown + } + $mediaGroup[] = $mediaItem; + } + +// $chat = TelegraphChat::find(0); +// $chat->mediaGroup($mediaGroup)->send(); + + +// $page = $chat->page()->content($mediaGroup)->create(); +// $bot = TelegraphBot::first(); +// $page = $bot->page()->title($post->title)->content($post->content)->create(); +// $articleUrl = $page->url(); +// $url = "https://api.telegram.org/bot7746238162:AAFGi4XwIZ0lnnNL72tlxrmqAgbHmRBMFVs/sendMessage"; +// +// $publishDateTime = strtotime('2025-04-27 20:27:00'); +// $scheduleDate = Carbon::parse($publishDateTime)->timestamp; +// +// $data = [ +// 'chat_id' => $chat, +// 'text' => $articleUrl, +// 'schedule_date' => $scheduleDate +// ]; +// +// $response = Http::post($url, $data); +// if ($response->failed()) { +// throw new \Exception('Ошибка при планировании поста: ' . $response->body()); +// } + + +// $publishDate = $post->publish_at > now() ? $post->publish_at->timestamp : null; +// dispatch(new CreateVkPost($post->title, $message, $images, $post->id, $publishDate)); + + } else { + $this->chat->markdown($message)->send(); + } + } else { + // Если нет изображений, отправляем только текст + Log::info('dasdsa'); + $this->chat->markdown($message)->send(); + } + } catch (\Exception $e) { + Log::error('Ошибка при публикации в Telegram: ' . $e->getMessage()); + $this->reply("Произошла ошибка при отправке поста"); + } + } + + private function parseContentBlocks(array $blocks): string + { + $text = ''; + foreach ($blocks as $block) { + $content = $this->decodeUnicode($block['data']['content'] ?? ''); + switch ($block['type'] ?? '') { + case 'heading': + $text .= "*" . $content . "*\n\n"; + break; + case 'paragraph': + $text .= $this->convertToMarkdown($content) . "\n\n"; + break; + case 'list': + if (isset($block['data']['items'])) { + foreach ($block['data']['items'] as $item) { + $text .= "- " . $item . "\n"; + } + $text .= "\n"; + } + break; + default: + $text .= $content . "\n\n"; + break; + } + } + return trim($text); + } + + private function convertToMarkdown(string $text): string + { + // Декодируем HTML-сущности + $text = html_entity_decode($text, ENT_QUOTES, 'UTF-8'); + $text = $this->decodeUnicode($text); + $text = preg_replace('/

(.*?)<\/p>/', '$1', $text); + $text = preg_replace('/(.*?)<\/b>/', '*$1*', $text); + $text = preg_replace('/(.*?)<\/i>/', '_$1_', $text); + $text = preg_replace('/(.*?)<\/strong>/', '*$1*', $text); + $text = preg_replace('/(.*?)<\/em>/', '_$1_', $text); + // Очищаем от HTML-тегов, декодируем оставшиеся сущности и экранируем спецсимволы для MarkdownV2 + return strip_tags($text); + } + + private function decodeUnicode(string $text): string + { + return preg_replace_callback( + '/\\\\u([0-9a-fA-F]{4})/', + function ($match) { + return mb_convert_encoding(pack('H*', $match[1]), 'UTF-8', 'UCS-2BE'); + }, + $text + ); + } + + protected function handleUnknownCommand(string|\Illuminate\Support\Stringable $command): void + { + $this->reply("Неизвестная команда: {$command}"); + } +} \ No newline at end of file diff --git a/app/Services/Telegram/TgService.php b/app/Services/Telegram/TgService.php new file mode 100644 index 0000000..6fa7f2b --- /dev/null +++ b/app/Services/Telegram/TgService.php @@ -0,0 +1,214 @@ +createMediaGroup($text, $images); +// $response = $chat->mediaGroup($mediaGroup)->send(); +// if ($response->successful()) { +// $messages = $response->json()['result']; +// $mediaGroupId = $messages[0]['message_id']; +// $messageIds = array_map(function($msg) { +// return $msg['message_id']; +// }, $messages); +// return [$mediaGroupId, $messageIds]; +// } +// } +// else{ +// $response = $chat->markdown($text)->send(); +// if ($response->successful()) { +// $messageId = $response->telegraphMessageId(); +// } +// return [$messageId, null]; +// } +// } + + public function createPost($text, $images, $videos, $documents, $publishDate) + { + $chat = TelegraphChat::find(4); + Log::info($images); + Log::info($videos); + Log::info($documents); + + if (!empty($images) || !empty($videos)) { + // Создаем медиагруппу из изображений и видео (до 10 элементов) + $mediaItems = []; + foreach ($images as $image) { + $mediaItems[] = ['type' => 'photo', 'media' => $image]; + } + foreach ($videos as $video) { + $mediaItems[] = ['type' => 'video', 'media' => $video]; + } + $mediaItems = array_slice($mediaItems, 0, 10); + if (!empty($mediaItems)) { + $mediaItems[0]['caption'] = $text; + $mediaItems[0]['parse_mode'] = 'Markdown'; + } + $response = $chat->mediaGroup($mediaItems)->send(); + if ($response->successful()) { + $messages = $response->json()['result']; + $mainMessageId = $messages[0]['message_id']; + $mediaMessageIds = array_map(function($msg) { + return $msg['message_id']; + }, $messages); + } + +// // Отправляем документы +// $documentMessageIds = []; +// foreach ($documents as $document) { +// $response = $chat->document($document)->caption($text)->parseMode('Markdown')->send(); +// if ($response->successful()) { +// $documentMessageIds[] = $response->telegraphMessageId(); +// } +// } +// $allMessageIds = array_merge($mediaMessageIds, $documentMessageIds); + return [$mainMessageId, $mediaMessageIds]; + } elseif (!empty($documents)) { + // Отправляем только документы + $documentMessageIds = []; + $mainMessageId = null; + foreach ($documents as $index => $document) { + $response = $chat->document($document)->caption($text)->parseMode('Markdown')->send(); + if ($response->successful()) { + $messageId = $response->telegraphMessageId(); + $documentMessageIds[] = $messageId; + if ($index == 0) { + $mainMessageId = $messageId; + } + } + } + return [$mainMessageId, $documentMessageIds]; + } else { + // Отправляем только текст + $response = $chat->markdown($text)->send(); + if ($response->successful()) { + $messageId = $response->telegraphMessageId(); + return [$messageId, [$messageId]]; + } + } + } + + public function updatePost($post_id, $text, $images, $media_ids) + { + $chat = TelegraphChat::find(1); + + if ($images !== []) { + try { +// if (count($images) !== count($media_ids)) { +// foreach ($media_ids as $messageId) { +// $chat->deleteMessage($messageId)->send(); +// } +// +// $modifiedText = $text . "\n\n_(сообщение изменено)_"; +// +// $result = $this->createPost($modifiedText, $images); +// +// return [ +// 'post_id' => $result[0], +// 'media_ids' => $result[1] ?? [] +// ]; +// } + + $firstMessageId = $media_ids[0]; + $chat->editCaption($firstMessageId) + ->markdown($text) + ->send(); + +// $messageIds = []; +// $firstMessageId = null; + +// foreach ($media_ids as $index => $messageId) { +// if (!isset($images[$index])) { +// continue; +// } +// +// $newMedia = $images[$index]; +// $response = $chat->editMedia($messageId) +// ->photo(config('app.url') . $newMedia) +// ->send(); +// +// if ($response->successful()) { +// $updatedMessageId = $response->json()['result']['message_id']; +// $messageIds[] = $updatedMessageId; +// +// if ($index === 0) { +// } +// } +// } + + } catch (\Exception $e) { + Log::error('Ошибка при изменении поста ' . $e->getMessage()); + return []; // Или null/исключение + } + } else { + // Для текстовых сообщений + $chat->edit($post_id) + ->markdown($text) + ->send(); + } + + + +// $chat = TelegraphChat::find(4); +// if ($images !== []){ +// try { +// Log::info(json_encode($media_ids)); +// $firstMessageId = $media_ids[0]; +// foreach ($media_ids as $index => $messageId) { +// $newMedia = $images[$index]; +// Log::info($newMedia); +// Log::info($messageId); +// $chat->editMedia($messageId) +// ->photo(config('app.url') . $newMedia) +// ->send(); +// } +// $chat->editCaption($firstMessageId) +// ->markdown($text) +// ->send(); +// +// } catch (\Exception $e) { +// Log::error('Ошибка при изменении поста ' . $e->getMessage()); +// } +// } +// else{ +// $chat->edit($post_id)->markdown($text)->send(); +// } + } + + private function createMediaGroup($text, $images) + { + try { + $baseUrl = config('app.url'); + + if (is_array($images) && !empty($images)) { + $mediaGroup = []; + foreach ($images as $index => $image) { + $mediaItem = [ + 'type' => 'photo', + 'media' => $baseUrl . $image, +// https://crack-gar-specially.ngrok-free.app/storage/posts/gallery/01JT5R37Z05S119VCRRFEADSAG.jpg + ]; + + if ($index === 0) { + $mediaItem['caption'] = $text; + $mediaItem['parse_mode'] = 'Markdown'; + } + $mediaGroup[] = $mediaItem; + } + return $mediaGroup; + } + } catch (\Exception $e) { + Log::error('Ошибка при публикации в Telegram: ' . $e->getMessage()); + } + } +} \ No newline at end of file diff --git a/config/telegraph.php b/config/telegraph.php new file mode 100644 index 0000000..a1ad541 --- /dev/null +++ b/config/telegraph.php @@ -0,0 +1,214 @@ + 'https://api.telegram.org/', + + /* + * Sets Telegraph messages default parse mode + * allowed values: html|markdown|MarkdownV2 + */ + 'default_parse_mode' => Telegraph::PARSE_HTML, + + 'webhook' => [ + /* + * Sets the webhook URL that will be exposed by the server, + * this can be customized or entirely disabled (by setting it to NULL) + */ + 'url' => '/telegraph/{token}/webhook', + + /* + * Sets the handler to be used when Telegraph + * receives a new webhook call. + * + * For reference, see https://docs.defstudio.it/telegraph/webhooks/overview + */ + 'handler' => \App\Services\Telegram\Handler::class, + + /* + * Middleware to be applied to the webhook route + */ + 'middleware' => [], + + /* + * Sets a custom domain when registering a webhook. This will allow a local telegram bot api server + * to reach the webhook. Disabled by default + * + * For reference, see https://core.telegram.org/bots/api#using-a-local-bot-api-server + */ + // 'domain' => 'http://my.custom.domain', + + /* + * If enabled, unknown webhook commands are + * reported as exception in application logs + */ + 'report_unknown_commands' => env('TELEGRAPH_REPORT_UNKNOWN_COMMANDS', true), + + /** + * secret token to be sent in a X-Telegram-Bot-Api-Secret-Token header + * to verify the authenticity of the webhook + */ + 'secret' => env('TELEGRAPH_WEBHOOK_SECRET'), + + /** + * maximum allowed simultaneous connections to the webhook (defaults to 40) + */ + 'max_connections' => env('TELEGRAPH_WEBHOOK_MAX_CONNECTIONS', 40), + + /** + * List of event types for which the webhook should fire. + * + * Specify a null to receive all update types except `chat_member`, `message_reaction`, + * and `message_reaction_count` (by default). + * + * @see https://core.telegram.org/bots/api#setwebhook + */ + 'allowed_updates' => null, + + /* + * If enabled, Telegraph dumps received + * webhook messages to logs + */ + 'debug' => env('TELEGRAPH_WEBHOOK_DEBUG', false), + ], + + /* + * Sets HTTP request timeout when interacting with Telegram servers + */ + 'http_timeout' => env('TELEGRAPH_HTTP_TIMEOUT', 30), + + /* + * Sets HTTP connection request timeout when interacting with Telegram servers + */ + 'http_connection_timeout' => env('TELEGRAPH_HTTP_CONNECTION_TIMEOUT', 10), + + 'security' => [ + /* + * if enabled, allows callback queries from unregistered chats + */ + 'allow_callback_queries_from_unknown_chats' => true, + + /* + * if enabled, allows messages and commands from unregistered chats + */ + 'allow_messages_from_unknown_chats' => true, + + /* + * if enabled, store unknown chats as new TelegraphChat models + */ + 'store_unknown_chats_in_db' => true, + ], + + /* + * Set model class for both TelegraphBot and TelegraphChat, + * to allow more customization. + * + * Bot model must be or extend `DefStudio\Telegraph\Models\TelegraphBot::class` + * Chat model must be or extend `DefStudio\Telegraph\Models\TelegraphChat::class` + */ + 'models' => [ + 'bot' => DefStudio\Telegraph\Models\TelegraphBot::class, + 'chat' => DefStudio\Telegraph\Models\TelegraphChat::class, + ], + + 'storage' => [ + /** + * Default storage driver to be used for Telegraph data + */ + 'default' => 'file', + + 'stores' => [ + 'file' => [ + /** + * Telegraph cache driver to be used, must implement + * DefStudio\Telegraph\Contracts\StorageDriver contract + */ + 'driver' => \DefStudio\Telegraph\Storage\FileStorageDriver::class, + + /* + * Laravel Storage disk to use. See /config/filesystems/disks for available disks + * If 'null', Laravel default store will be used, + */ + 'disk' => 'local', + + /** + * Folder inside filesystem to be used as root for Telegraph storage + */ + 'root' => 'telegraph', + ], + 'cache' => [ + /** + * Telegraph cache driver to be used, must implement + * DefStudio\Telegraph\Contracts\StorageDriver contract + */ + 'driver' => \DefStudio\Telegraph\Storage\CacheStorageDriver::class, + + /* + * Laravel Cache store to use. See /config/cache/stores for available stores + * If 'null', Laravel default store will be used, + */ + 'store' => null, + + /* + * Prefix to be prepended to cache keys + */ + 'key_prefix' => 'tgph', + ], + ], + ], + + /** + * Attachment validation rules, Telegram bot API defaults are set + * can be changed to match higher limits when using a local bot + * API server (ref. https://core.telegram.org/bots/api#using-a-local-bot-api-server) + */ + 'attachments' => [ + 'thumbnail' => [ + 'max_size_kb' => 200, + 'max_height_px' => 320, + 'max_width_px' => 320, + 'allowed_ext' => ['jpg'], + ], + 'photo' => [ + 'max_size_mb' => 10, + 'max_ratio' => 20, + 'height_width_sum_px' => 10000, + ], + 'animation' => [ + 'max_size_mb' => 50, + ], + 'video' => [ + 'max_size_mb' => 50, + ], + 'audio' => [ + 'max_size_mb' => 50, + ], + 'document' => [ + 'max_size_mb' => 50, + ], + 'sticker' => [ + 'max_size_mb' => 50, + ], + ], + + /* + * Sets preferences for commands + */ + 'commands' => [ + /* + * Defines a list of characters that are the identifier of a command sent to the chat. + * + * Default is `/` + */ + 'start_with' => ['/'], + ], + + 'payments' => [ + 'provider_token' => env('TELEGRAPH_PAYMENT_PROVIDER_TOKEN', ''), + ], +];