*/ final class telegram extends core { /** * Экранирование символов для Markdown * * @param string $text Текст для экранирования * @param array $exception Символы которые будут исключены из списка для экранирования * * @return string Экранированный текст */ public static function unmarkdown(string $text, array $exceptions = []): string { // Инициализация реестра символом для конвертации $from = array_diff( [ '#', '*', '_', '=', '.', '[', ']', '(', ')', '-', '>', '<', '!', '`' ], $exceptions ); // Инициализация реестра целей для конвертации $to = []; foreach ($from as $symbol) $to[] = "\\$symbol"; // Конвертация и выход (успех) return str_replace($from, $to, $text); } /** * Инициализация запчасти * * Проверяет существование запчасти * * @param string $spare Запчасть * * @return string|bool Запчасть, если найдена, иначе false */ public static function spares(string $spare): string|bool { // Поиск запчастей и выход (успех) return match (mb_strtolower($spare)) { 'цевьё' => 'Цевьё', default => false }; } /** * Главное меню * * Команда: /start * * @param context $ctx * * @return void */ public static function menu(context $ctx): void { // Инициализация клавиатуры $keyboard = [ [ ['text' => '🛒 Каталог', 'web_app' => ['url' => 'https://arming.dev.mirzaev.sexy']] ], [ ['text' => '🏛️ О компании'], ['text' => '💬 Контакты'] ], [ ['text' => '🎯 Сообщество'] ] ]; if ($ctx->get('account')?->access['settings']) $keyboard[] = [['text' => '⚙️ Настройки']]; // Отправка сообщения $ctx->sendMessage( static::unmarkdown(<< [ 'keyboard' => $keyboard, 'resize_keyboard' => true ], 'disable_notification' => true ] ); } /** * Начало работы с чат-роботом * * Команда: /start * * @param context $ctx * * @return void */ public static function start(context $ctx): void { // Главное меню static::menu($ctx); } /** * Контакты * * Команда: /contacts * * @param context $ctx * * @return void */ public static function contacts(context $ctx): void { // Отправка сообщения $ctx->sendMessage(static::unmarkdown(<< [ 'inline_keyboard' => [ [ ['text' => '⚡ Связь с менеджером', 'url' => 'https://t.me/iarming'], ], [ ['text' => '📨 Почта', 'callback_data' => 'mail'] ], [ ['text' => '🪖 Сайт', 'url' => 'https://arming.ru'], ['text' => '🛒 Wildberries', 'url' => 'https://www.wildberries.ru/seller/137386'], ['text' => '🛒 Ozon', 'url' => 'https://www.ozon.ru/seller/arming-1086587/products/?miniapp=seller_1086587'], ] ] ], 'link_preview_options' => [ 'is_disabled' => true ], 'disable_notification' => true ]); } /** * Почта * * @param context $ctx * * @return void */ public static function _mail(context $ctx): void { // Отправка сообщения $ctx->sendMessage(static::unmarkdown(<< [ 'is_disabled' => true ], 'disable_notification' => true ]); } /** * Компания * * Команда: /company * * @param context $ctx * * @return void */ public static function company(context $ctx): void { // Отправка сообщения $ctx->sendMessage( static::unmarkdown(<< [ 'inline_keyboard' => [ [ ['text' => '📄 Публичная оферта', 'web_app' => ['url' => 'https://arming.dev.mirzaev.sexy/offer']], ] ] ], 'link_preview_options' => [ 'is_disabled' => true ] ] ); } /** * Сообщество * * Команда: /community * * @param context $ctx * * @return void */ public static function community(context $ctx): void { // Отправка сообщения $ctx->sendMessage(static::unmarkdown(<< [ 'inline_keyboard' => [ [ ['text' => '💬 Основной чат', 'url' => 'https://t.me/arming_zone'], ] ] ], 'link_preview_options' => [ 'is_disabled' => true ], 'disable_notification' => true ]); } /** * Настройки (доступ только авторизованным) * * Команда: /settings * * @param context $ctx * * @return void */ public static function settings(context $ctx): void { if ($ctx->get('account')?->access['settings']) { // Авторизован доступ к настройкам // Отправка сообщения $ctx->sendMessage( static::unmarkdown(<< [ 'inline_keyboard' => [ [ ['text' => '📦 Импорт товаров', 'callback_data' => 'import_request'], ] ] ], 'link_preview_options' => [ 'is_disabled' => true ], 'disable_notification' => true ] ); } else { // Не авторизован доступ к настройкам // Отправка сообщения $ctx->sendMessage('⛔ *Нет доступа*'); } } /** * Запросить файл для импорта товаров (доступ только авторизованным) * * @param context $ctx * * @return void */ public static function import_request(context $ctx): void { if ($ctx->get('account')?->access['settings']) { // Авторизован доступ к настройкам // Отправка сообщения $ctx->sendMessage(static::unmarkdown('Отправьте документ в формате xlsx со списком товаров')) ->then(function ($message) use ($ctx) { // Отправка файла $ctx->sendDocument(new InputFile(CATALOG_EXAMPLE), ['disable_notification' => true]); // Импорт файла $ctx->nextStep([static::class, 'import'], true); }); } else { // Не авторизован доступ к настройкам // Отправка сообщения $ctx->sendMessage('⛔ *Нет доступа*'); } } /** * Импорт товаров (доступ только авторизованным) * * @param context $ctx * * @return void */ public static function import(context $ctx): void { if (($account = $ctx->get('account'))?->access['settings']) { // Авторизован доступ к настройкам // Инициализация документа $document = $ctx->getMessage()?->getDocument(); if ($document instanceof telegram_document) { // Инициализирован документ // Инициализация файла $ctx->getFile($document->getFileId())->then(function ($file) use ($ctx, $document, $account) { if ($file->getFileSize() <= 50000000) { // Не превышает 50 мегабайт (50 000 000 байт) размер файла if (pathinfo(parse_url($file->getFilePath())['path'], PATHINFO_EXTENSION) === 'xlsx') { // Имеет расширение xlsx файл // Initializing the directory in the storage if (!file_exists($storage = STORAGE . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . $account->getKey() . DIRECTORY_SEPARATOR . time())) mkdir($storage, 0775, true); // Сохранение файла file_put_contents( $import = $storage . DIRECTORY_SEPARATOR . 'import.xlsx', file_get_contents('https://api.telegram.org/file/bot' . KEY . '/' . parse_url($file->getFilePath())['path']) ); // Отправка сообщения $ctx->sendMessage(sprintf( <<<'TXT' 🔬 *Выполняется анализ:* %s \(%s байт\) TXT, static::unmarkdown($document->getFileName()), static::unmarkdown((string) $file->getFileSize()) )) ->then(function ($message) use ($ctx, $import) { // Инициализация счётчика загруженных товаров $categories_loaded = $products_loaded = $categories_created = $products_created = $categories_updated = $products_updated = $categories_deleted = $products_deleted = $categories_old = $products_old = $categories_new = $products_new = 0; // Import catalog::import( $import, $categories_loaded, $categories_created, $categories_updated, $categories_deleted, $categories_old, $categories_new, $products_loaded, $products_created, $products_updated, $products_deleted, $products_old, $products_new, language: $account->language ?? settings::active()?->language ?? language::en, // @todo add languages currency: $account->currency ?? settings::active()?->currency ?? currency::usd // @todo add currencies ); // Отправка сообщения $ctx->sendMessage(<<then(function ($message) use ($ctx, $products_loaded, $products_created, $products_updated, $products_deleted, $products_old, $products_new) { $ctx->sendMessage(<<then(function ($message) use ($ctx) { // Завершение диалога $ctx->endConversation(); }); }); }); } else { // Не имеет расширение xlsx файл // Отправка сообщения $ctx->sendMessage(static::unmarkdown('Файл должен иметь расширение xlsx')); } } else { // Превышает 50 мегабайт (50000000 байт) размер файла // Отправка сообщения $ctx->sendMessage(static::unmarkdown('Размер файла не должен превышать 50 мегабайт')); } }); } else { // Не инициализирован документ // Отправка сообщения $ctx->sendMessage(static::unmarkdown('Отправьте документ в формате xlsx со списком товаров')); } } else { // Не авторизован доступ к настройкам // Отправка сообщения $ctx->sendMessage('⛔ *Нет доступа*'); } } /** * Инициализация аккаунта (middleware) * * @param context $ctx * @param Node $next * * @return void */ public static function account(context $ctx, Node $next): void { // Выполнение заблокировано? if ($ctx->get('stop')) return; // Инициализация аккаунта Telegram $telegram = $ctx->getEffectiveUser(); // Инициализация аккаунта $account = account::initialize($telegram->getId(), $telegram); if ($account) { // Инициализирован аккаунт if ($account->banned) { // Заблокирован аккаунт // Отправка сообщения $ctx->sendMessage('⛔ *Ты заблокирован*') ->then(function ($message) use ($ctx) { // Завершение диалога $ctx->endConversation(); }); // Блокировка дальнейшего выполнения $ctx->set('stop', true); } else { // Не заблокирован аккаунт // Запись в буфер $ctx->set('account', $account); // Продолжение выполнения $next($ctx); } } else { // Не инициализирован аккаунт } } /** * Инициализация статуса технических работ (middleware) * * @param context $ctx * @param Node $next * * @return void */ public static function suspension(context $ctx, Node $next): void { // Выполнение заблокировано? if ($ctx->get('stop')) return; // Поиск технических работ $suspension = suspension::search(); if ($suspension && $suspension->targets['telegram-robot']) { // Найдена активная приостановка // Инициализация аккаунта $account = $ctx->get('account'); if ($account) { // Инициализирован аккаунт foreach ($suspension->access as $type => $status) { // Перебор статусов доступа if ($status && $account->{$type}) { // Авторизован аккаунт // Продолжение выполнения $next($ctx); // Выход (успех) return; } } } // Инициализация сообщения $message = "⚠️ *Работа приостановлена*\n*Оставшееся время\:* " . $suspension->message($account->language ?? settings::active()?->language ?? 'en'); // Добавление описания причины приостановки, если найдена if (!empty($suspension->description)) $message .= "\n\n" . $suspension->description[$account->language ?? settings::active()?->language ?? 'en'] ?? array_values($suspension->description)[0]; // Отправка сообщения $ctx->sendMessage($message) ->then(function ($message) use ($ctx) { // Завершение диалога $ctx->endConversation(); }); // Блокировка дальнейшего выполнения $ctx->set('stop', true); } else { // Не найдена активная приостановка // Продолжение выполнения $next($ctx); } } /** * Cart attach * * @param context $ctx * @param string $share Sharing hash * * @return void */ public static function cart_attach(context $ctx, string $share): void { // Initializing account $account = $ctx->get('account'); if ($account) { // Initialized the account // Initializing cart $cart = cart::_read( filter: 'd.share == @share', sort: 'd.updated DESC, d.created DESC, d._key DESC', amount: 1, page: 1, parameters: ['share' => $share] ); // Deinitializing unnecessary variables unset($share); // Unsharing the cart $cart->unshare(); if ($cart instanceof cart) { // Initialized the cart // Connecting the cart to the account $edge = $account->connect($cart); if (!empty($edge)) { // Connected the cart to the account // Initializing products in the cart $products = $cart->products(language: $account->language ?? language::ru, currency: $account->currency ?? currency::rub); if (!empty($products)) { // Initialized products in the cart // Declaring total cost of products $cost = 0; // Declaring formatted list of products for message $list = ''; // Initializing iterator of rows $row = 0; foreach ($products as $product) { // Iterating over products // Generating formatted list of products for message $list .= static::unmarkdown(++$row . '. ' . $product['document']['name'] . ' (' . $product['amount'] . 'шт)') . "\n"; // Generating total cost of products $cost += $product['document']['cost'] * $product['amount']; } // Deinitializing unnecessary variables unset($products, $product, $row); // Initializing currency symbol $symbol = ($account->currency ?? currency::rub)->symbol(); // Initializing delivery cost for message $delivery_cost = $cart->buffer['delivery']['cost']; // Initializing delivery days for message $delivery_days = $cart->buffer['delivery']['days']; // Initializing delivery address for message $delivery_address = $cart->buffer['delivery']['location']['name'] . ', ' . $cart->buffer['delivery']['street']; // Deinitializing unnecessary variables unset($cart); $ctx->sendMessage( << [ 'inline_keyboard' => [ [ /* ['text' => '🧾 Оплатить', 'web_app' => ['url' => 'https://arming.dev.mirzaev.sexy']] */ ['text' => '📦 Оформить заказ', 'url' => 'https://auth.robokassa.ru/Merchant/Index.aspx?MerchantLogin=demo&OutSum=11&Description=Покупка в демо магазине&SignatureValue=2c113e992e2c985e43e348ff3c12f32b'], ] ], 'disable_notification' => true ] ] ); } // Deinitializing unnecessary variables unset($cart, $list); } } // Deinitializing unnecessary variables unset($cart); } // Deinitializing unnecessary variables unset($account); } }