From 845a9d04e070b3a07a7806d54590905778ed664a Mon Sep 17 00:00:00 2001 From: mirzaev Date: Sat, 1 Feb 2025 23:06:28 +0700 Subject: [PATCH] rebuilding architecture; resolved #1, resolved #2, resolved #3, resolved #4, resolved #5, resolved #6 --- composer.json | 5 +- examples/demonstration_1_0_0.png | Bin examples/nginx/negotiator.svoboda.conf | 0 examples/systemd/negotiator-telegram.service | 0 .../system/localizations/english.php | 26 + .../system/localizations/russian.php | 26 + svoboda/negotiator/system/models/account.php | 190 ++++++ svoboda/negotiator/system/models/core.php | 24 +- .../system/models/enumerations/language.php | 20 +- svoboda/negotiator/system/models/telegram.php | 48 -- .../system/models/telegram/buttons.php | 123 ++++ .../system/models/telegram/commands.php | 274 +++++++++ .../system/models/telegram/middlewares.php | 552 ++++++++++++++++++ .../system/models/telegram/settings.php | 155 +++++ svoboda/negotiator/system/public/telegram.php | 74 ++- .../system/settings/telegram.php.sample | 0 .../system/storage/images/mushroom.jpg | Bin 17 files changed, 1422 insertions(+), 95 deletions(-) mode change 100644 => 100755 examples/demonstration_1_0_0.png mode change 100644 => 100755 examples/nginx/negotiator.svoboda.conf mode change 100644 => 100755 examples/systemd/negotiator-telegram.service create mode 100644 svoboda/negotiator/system/localizations/english.php create mode 100644 svoboda/negotiator/system/localizations/russian.php create mode 100755 svoboda/negotiator/system/models/account.php delete mode 100755 svoboda/negotiator/system/models/telegram.php create mode 100755 svoboda/negotiator/system/models/telegram/buttons.php create mode 100755 svoboda/negotiator/system/models/telegram/commands.php create mode 100755 svoboda/negotiator/system/models/telegram/middlewares.php create mode 100755 svoboda/negotiator/system/models/telegram/settings.php mode change 100644 => 100755 svoboda/negotiator/system/settings/telegram.php.sample mode change 100644 => 100755 svoboda/negotiator/system/storage/images/mushroom.jpg diff --git a/composer.json b/composer.json index fbf5897..f6fb0fe 100755 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "svoboda/negotiator", - "description": "Chat-robot negotiator of the Svoboda organization", + "description": "Svoboda Telegram chat-robot negotiator", "homepage": "https://git.svoboda.works/svoboda/negotiator", "type": "chat-robot", "keywords": [ @@ -26,7 +26,8 @@ "php": "^8.4", "mirzaev/minimal": "^3.4.0", "badfarm/zanzara": "^0.9.1", - "react/filesystem": "^0.1.2" + "react/filesystem": "^0.1.2", + "mirzaev/baza": "^3.1.0" }, "require-dev": { "phpunit/phpunit": "~9.5" diff --git a/examples/demonstration_1_0_0.png b/examples/demonstration_1_0_0.png old mode 100644 new mode 100755 diff --git a/examples/nginx/negotiator.svoboda.conf b/examples/nginx/negotiator.svoboda.conf old mode 100644 new mode 100755 diff --git a/examples/systemd/negotiator-telegram.service b/examples/systemd/negotiator-telegram.service old mode 100644 new mode 100755 diff --git a/svoboda/negotiator/system/localizations/english.php b/svoboda/negotiator/system/localizations/english.php new file mode 100644 index 0000000..ed44f3d --- /dev/null +++ b/svoboda/negotiator/system/localizations/english.php @@ -0,0 +1,26 @@ + 'Svoboda', + + // Settings + 'settings_language_title' => 'Language', + 'settings_language_add' => 'Add a language', + 'settings_language_update_success' => 'Language replaced:', + 'settings_language_update_fail' => 'Failed to replace language', + + // Authorizing + 'not_authorized_system' => 'You do not have access to the system', + 'not_authorized_contact' => 'You do not have access to contact with the organisation', + 'not_authorized_request' => 'You do not have access to requesting to the organisation', + 'not_authorized_settings' => 'You do not have access to the settings', + 'not_authorized_system_settings' => 'You do not have access to the system settings', + + // Errors + 'not_initialized_account' => '', + + // Other + 'why_so_shroomious' => 'why so shroomious', +]; diff --git a/svoboda/negotiator/system/localizations/russian.php b/svoboda/negotiator/system/localizations/russian.php new file mode 100644 index 0000000..5278c07 --- /dev/null +++ b/svoboda/negotiator/system/localizations/russian.php @@ -0,0 +1,26 @@ + 'Свобода', + + // Настройки + 'settings_language_title' => 'Язык', + 'settings_language_add' => 'Добавить язык', + 'settings_language_update_success' => 'Язык заменён:', + 'settings_language_update_fail' => 'Не удалось заменить язык', + + // Авторизация + 'not_authorized_system' => 'У тебя нет доступа к системе', + 'not_authorized_contact' => 'У тебя нет доступа к коммуникации с организацией', + 'not_authorized_request' => 'У тебя нет доступа к отправке запросов в организацию', + 'not_authorized_settings' => 'У тебя нет доступа к настройкам', + 'not_authorized_system_settings' => 'У тебя нет доступа к системным настройкам', + + // Ошибки + 'not_initialized_account' => '', + + // Прочее + 'why_so_shroomious' => 'почему такой грибъёзный', +]; diff --git a/svoboda/negotiator/system/models/account.php b/svoboda/negotiator/system/models/account.php new file mode 100755 index 0000000..23a22b4 --- /dev/null +++ b/svoboda/negotiator/system/models/account.php @@ -0,0 +1,190 @@ + + */ +final class account extends core +{ + /** + * File + * + * @var string $database Path to the accounts database file + */ + protected string $file = DATABASES . DIRECTORY_SEPARATOR . 'accounts.baza'; + + /** + * Database + * + * @var database $database The database + */ + public static database $database; + + /** + * Constructor + * + * @return void + */ + public function __construct() + { + // Initializing the database + static::$database = new database() + ->encoding(encoding::utf8) + ->columns( + new column('identifier', type::integer_unsigned), + new column('name_first', type::string, ['length' => 64]), + new column('name_second', type::string, ['length' => 64]), + new column('domain', type::string, ['length' => 32]), + new column('language', type::string, ['length' => 2]), + new column('robot', type::char), + new column('authorized_system', type::char), + new column('authorized_contact', type::char), + new column('authorized_request', type::char), + new column('authorized_settings', type::char), + new column('authorized_system_settings', type::char) + ) + ->connect($this->file); + } + + /** + * Initialize + * + * Searches for the account record in the database, and if it does not find it, it creates it + * + * @param telegram $telegram The telegram account + * + * @throws exception_runtime if update the account record in the database by the telegram account values + * @throws exception_runtime if failed to find the registered account + * @throws exception_runtime if failed to registrate the account + * + * @return record The account record from the database + */ + public function initialize(telegram $telegram): record + { + // Searching for the account in the database + $account = static::$database->read(filter: fn(record $record) => $record->identifier === $telegram->getId(), amount: 1)[0] ?? null; + + if ($account instanceof record) { + // Found the account record + + if ( + $account->name_first !== $telegram->getFirstName() || + $account->name_second !== $telegram->getLastName() || + $account->domain !== $telegram->getUsername() + ) { + // The telegram account was updated + + // Updating the account in the database + $updated = static::$database->read( + filter: fn(record $record) => $record->identifier === $telegram->getId(), + update: function (record &$record) use ($telegram){ + // Writing new values into the record + $record->name_first = $telegram->getFirstName(); + $record->name_second = $telegram->getLastName(); + $record->domain = $telegram->getUsername(); + }, + amount: 1 + )[0] ?? null; + + if ($updated instanceof record && $updated->values() !== $account->values()) { + // Updated the account in the database + + // Exit (success) + return $updated; + } else { + // Not updated the account in the database + + // Exit (fail) + throw new exception_runtime('Failed to update the account record in the database by the telegram account values'); + } + } + + // Exit (success) + return $account; + } else { + // Not found the account record + + if ($this->registrate($telegram)) { + // Registered the account + + // Searching for the registered account in the database + $account = static::$database->read(filter: fn(record $record) => $record->identifier === $telegram->getId(), amount: 1)[0] ?? null; + + if ($account instanceof record) { + // Found the registered account + + // Exit (success) + return $account; + } else { + // Not found the registered account + + // Exit (fail) + throw new exception_runtime('Failed to find the registered account'); + } + } else { + // Not registered the account + + // Exit (fail) + throw new exception_runtime('Failed to registrate the account'); + } + } + } + + /** + * Registrate + * + * Creates the account record in the database + * + * @param telegram $telegram The telegram account + * + * @return bool Is the accound record created? + */ + public function registrate(telegram $telegram): bool + { + // Initializing the record + $record = static::$database->record( + (int) $telegram->getId(), + $telegram->getFirstName(), + $telegram->getLastName(), + $telegram->getUsername(), + $telegram->getLanguageCode(), + (int) $telegram->isBot(), + 1, + 1, + 1, + 1, + 0 + ); + + // Creating the accound record in the database + $created = static::$database->write($record); + + // Exit (success) + return $created; + } +} diff --git a/svoboda/negotiator/system/models/core.php b/svoboda/negotiator/system/models/core.php index be12231..e3edd0b 100755 --- a/svoboda/negotiator/system/models/core.php +++ b/svoboda/negotiator/system/models/core.php @@ -7,34 +7,26 @@ namespace svoboda\negotiator\models; // Framework for PHP use mirzaev\minimal\model; +// Baza database +use mirzaev\baza\database, + mirzaev\baza\column, + mirzaev\baza\enumerations\encoding; + // Built-in libraries use exception; /** - * Models core + * Core * * @package svoboda\negotiator\models * - * @method void __construct(bool $initialize) Constructor + * @method void __construct() Constructor * * @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License - * @author svoboda + * @author Arsen Mirzaev Tatyano-Muradovich */ class core extends model { - /** - * Constructor - * - * @param bool $initialize Initialize a model? - * - * @return void - */ - public function __construct(bool $initialize = true) - { - // For the extends system - parent::__construct($initialize); - } - /** * Write * diff --git a/svoboda/negotiator/system/models/enumerations/language.php b/svoboda/negotiator/system/models/enumerations/language.php index f8cae8a..945b89a 100755 --- a/svoboda/negotiator/system/models/enumerations/language.php +++ b/svoboda/negotiator/system/models/enumerations/language.php @@ -28,10 +28,6 @@ enum language * @param language|null $language Language into which to translate * * @return string Translated label of the language - * - * @todo - * 1. More languages - * 2. Cases??? */ public function label(?language $language = language::en): string { @@ -47,4 +43,20 @@ enum language } }; } + + /** + * Flag + * + * Initialize tge flag emoji of the language + * + * @return string The flag emoji of the language + */ + public function flag(): string + { + // Exit (success) + return match ($this) { + language::en => '🇺🇸', + language::ru => '🇷🇺' + }; + } } diff --git a/svoboda/negotiator/system/models/telegram.php b/svoboda/negotiator/system/models/telegram.php deleted file mode 100755 index f64d353..0000000 --- a/svoboda/negotiator/system/models/telegram.php +++ /dev/null @@ -1,48 +0,0 @@ - - */ -final class telegram extends core -{ - /** - * Society - * - * Responce for the command: "/society" - * - * @param context $ctx - * - * @return void - */ - public static function society(context $ctx): void - { - $ctx->sendPhoto( - new InputFile(STORAGE . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'mushroom.jpg'), - [ - 'caption' => 'why so shroomious', - 'disable_notification' => true - ] - ); - } -} diff --git a/svoboda/negotiator/system/models/telegram/buttons.php b/svoboda/negotiator/system/models/telegram/buttons.php new file mode 100755 index 0000000..0c0510d --- /dev/null +++ b/svoboda/negotiator/system/models/telegram/buttons.php @@ -0,0 +1,123 @@ + + */ +final class settings extends core +{ + /** + * Settings: language + * + * Responce for the command: "/language" + * + * Sends a language selection menu + * + * @param context $context Request data from Telegram + * + * @return void + */ + public static function settings_language(context $context): void + { + // Initializing the account + $account = $context->get('account'); + + if ($account instanceof record) { + // Initialized the account + + // Initializing localization + $localization = $context->get('localization'); + + if ($localization) { + // Initialized localization + + // Initializing the title + $title = '🌏 *' . $localization['language_settings'] . '*'; + + // Declaring the buffer of generated keyboard with languages + $keyboard = []; + + // Initializing the iterator of rows + $row = 0; + + foreach (language::cases() as $language) { + // Iterating over languages + + // Initializing the row + $keyboard[$row] ??= []; + + // Writing the language choose button into the buffer of generated keyboard with languages + $keyboard[$row][] = [ + 'text' => ($language->flag() ? $language->flag() . ' ' : '') . $language->label($language), + 'callback_data' => 'settings_language_' . $language->name + ]; + + // When reaching 4 buttons in a row, move to the next row + if (count($keyboard[$row]) === 4) ++$row; + } + + // Sending the message + $context->sendMessage( + << [ + 'inline_keyboard' => $keyboard + ], + 'disable_notification' => true + ] + ) + ->then(function ($message) use ($context) { + // + }); + } else { + // Not initialized localization + + // Sending the message + $context->sendMessage('⚠️ *Failed to initialize localization*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } + } else { + // Not initialized the account + + // Sending the message + $context->sendMessage('⚠️ *Failed to initialize your Telegram account*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } + } +} diff --git a/svoboda/negotiator/system/models/telegram/commands.php b/svoboda/negotiator/system/models/telegram/commands.php new file mode 100755 index 0000000..5bad970 --- /dev/null +++ b/svoboda/negotiator/system/models/telegram/commands.php @@ -0,0 +1,274 @@ + + */ +final class commands extends core +{ + /** + * Menu + * + * Responce for the commands: "/start", '/menu' + * + * @param context $context Request data from Telegram + * + * @return void + */ + public static function menu(context $context): void + { + // Initializing the account + $account = $context->get('account'); + + if ($account instanceof record) { + // Initialized the account + + // Initializing localization + $localization = $context->get('localization'); + + if ($localization) { + // Initialized localization + + // Initializing the title + $title = '*' . $localization['svoboda'] . '*'; + + // Sending the message + $context->sendMessage(<<then(function ($message) use ($context) { + // + }); + } else { + // Not initialized localization + + // Sending the message + $context->sendMessage('⚠️ *Failed to initialize localization*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } + } else { + // Not initialized the account + + // Sending the message + $context->sendMessage('⚠️ *Failed to initialize your Telegram account*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } + } + + /** + * Message + * + * Responce for the command: "/message" + * + * Start a process for creating message + * + * @param context $context Request data from Telegram + * + * @return void + */ + public static function message(context $context): void + { + // Initializing the account + $account = $context->get('account'); + + if ($account instanceof record) { + // Initialized the account + + // Initializing the title + $title = ''; + + // Sending the message + $context->sendMessage(<<then(function ($message) use ($context) { + // + }); + } else { + // Not initialized the account + + // Sending the message + $context->sendMessage('⚠️ *Failed to initialize your Telegram account*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } + } + + /** + * Language + * + * Responce for the command: "/language" + * + * Sends a language selection menu + * + * @param context $context Request data from Telegram + * + * @return void + */ + public static function language(context $context): void + { + // Initializing the account + $account = $context->get('account'); + + if ($account instanceof record) { + // Initialized the account + + // Initializing localization + $localization = $context->get('localization'); + + if ($localization) { + // Initialized localization + + // Declaring the buffer of generated keyboard with languages + $keyboard = []; + + // Initializing the iterator of rows + $row = 0; + + foreach (language::cases() as $language) { + // Iterating over languages + + // Initializing the row + $keyboard[$row] ??= []; + + // Writing the language choose button into the buffer of generated keyboard with languages + $keyboard[$row][] = [ + 'text' => ($language->flag() ? $language->flag() . ' ' : '') . $language->label($language), + 'callback_data' => 'settings_language_' . $language->name + ]; + + // When reaching 4 buttons in a row, move to the next row + if (count($keyboard[$row]) === 4) ++$row; + } + + // Writing the button for helping lozalizing + $keyboard[++$row] = [ + [ + 'text' => '🗂 ' . $localization['settings_language_add'], + 'url' => 'https://git.svoboda.works/svoboda/negotiator/src/branch/stable/svoboda/negotiator/system/localizations' + ] + ]; + + // Sending the message + $context->sendMessage( + '🌏 *' . $localization['settings_language_title'] . '*', + [ + 'reply_markup' => [ + 'inline_keyboard' => $keyboard + ], + 'disable_notification' => true + ] + ); + } else { + // Not initialized localization + + // Sending the message + $context->sendMessage('⚠️ *Failed to initialize localization*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } + } else { + // Not initialized the account + + // Sending the message + $context->sendMessage('⚠️ *Failed to initialize your Telegram account*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } + } + + /** + * Society + * + * Responce for the command: "/society" + * + * Sends the "mushroom" image and the localized text "why so shroomious" + * + * @param context $context Request data from Telegram + * + * @return void + */ + public static function society(context $context): void + { + // Initializing the account + $account = $context->get('account'); + + if ($account instanceof record) { + // Initialized the account + + // Initializing localization + $localization = $context->get('localization'); + + if ($localization) { + // Initialized localization + + // Sending the message + $context->sendPhoto( + new file_input(STORAGE . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'mushroom.jpg'), + [ + 'caption' => $localization['why_so_shroomious'], + 'disable_notification' => true + ] + ); + } else { + // Not initialized localization + + // Sending the message + $context->sendMessage('⚠️ *Failed to initialize localization*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } + } else { + // Not initialized the account + + // Sending the message + $context->sendMessage('⚠️ *Failed to initialize your Telegram account*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } + } +} diff --git a/svoboda/negotiator/system/models/telegram/middlewares.php b/svoboda/negotiator/system/models/telegram/middlewares.php new file mode 100755 index 0000000..15fc389 --- /dev/null +++ b/svoboda/negotiator/system/models/telegram/middlewares.php @@ -0,0 +1,552 @@ + + */ +final class middlewares extends core +{ + /** + * Account (middleware) + * + * Initialize or registrate the account and write it to the `account` variable inside the `$context` + * + * @param context $context + * @param node $next + * + * @return void + */ + public static function account(context $context, node $next): void + { + // Is the process stopped? + if ($context->get('stop')) return; + + // Initializing the telegram account + $telegram = $context->getEffectiveUser(); + + // Initializing the account + /* $account = new account()->initialize($telegram); */ + $account = (new account())->initialize($telegram); + + if ($account instanceof record) { + // Initialized the account + + // Writing the account into the context variable + $context->set('account', $account); + + // Continuation of the process + $next($context); + } else { + // Not initialized the account + + // Sending the message + $context->sendMessage('⚠️ *Failed to initialize your Telegram account*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } + } + + /** + * Language (middleware) + * + * Implement the account language + * + * @param context $context + * @param node $next + * + * @return void + */ + public static function language(context $context, node $next): void + { + // Is the process stopped? + if ($context->get('stop')) return; + + // Initializing the account + $account = $context->get('account'); + + if ($account instanceof record) { + // Initialized the account + + if ($account->language) { + // Initialized the language parameter + + try { + // Writing the account language into the context variable + $context->set('language', language::{$account->language}); + } catch (error $error) { + // Not initialized the language + + // Writing the default language into the context variable + $context->set('language', language::en); + } + } else { + // Not initialized the language parameter + + // Writing the default language into the context variable + $context->set('language', language::en); + } + + // Continuation of the process + $next($context); + } else { + // Not initialized the account + + // Sending the message + $context->sendMessage('⚠️ *Failed to initialize your Telegram account*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } + } + + /** + * Localization (middleware) + * + * Implement the account language and initialize the localization file + * + * @param context $context + * @param node $next + * + * @return void + */ + public static function localization(context $context, node $next): void + { + // Is the process stopped? + if ($context->get('stop')) return; + + // Initializing the account + $account = $context->get('account'); + + if ($account instanceof record) { + // Initialized the account + + // Initializing the language + $language = $context->get('language'); + + if ($language instanceof language) { + // Initialized the language + + // Initializing path to the localization file + $file = LOCALIZATIONS . DIRECTORY_SEPARATOR . strtolower($language->label()) . '.php'; + + if (file_exists($file) && is_readable($file)) { + // Found the localization file + + // Initializing localization + $localization = require($file); + + if (is_array($localization)) { + // Initializae localization + + // Writing localization into the context variable + $context->set('localization', $localization); + + // Continuation of the process + $next($context); + } else { + + // Sending the message + $context->sendMessage('⚠️ *Failed to initialize localization*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } + } else { + // Not found the localization file + + // Sending the message + $context->sendMessage('⚠️ *Failed to initialize the localization file*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } + } else { + // Not initialized language + + // Sending the message + $context->sendMessage('⚠️ *Failed to initialize language*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } + } else { + // Not initialized the account + + // Sending the message + $context->sendMessage('⚠️ *Failed to initialize your Telegram account*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } + } + + /** + * System (middleware) + * + * Check the account for access to the system + * + * @param context $context + * @param node $next + * + * @return void + */ + public static function system(context $context, node $next): void + { + // Is the process stopped? + if ($context->get('stop')) return; + + // Initializing the account + $account = $context->get('account'); + + if ($account instanceof record) { + // Initialized the account + + if ($account->authorized_system) { + // Authorized the account to the system + + // Continuation of the process + $next($context); + } else { + // Not authorized the account to the system + + // Initializing localization + $localization = $context->get('localization'); + + if ($localization) { + // Initialized localization + + // Sending the message + $context->sendMessage('⛔ *' . $localization['not_authorized_system'] . '*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + + // Stopping the process + $context->set('stop', true); + } else { + // Not initialized localization + + // Sending the message + $context->sendMessage('⚠️ *Failed to initialize localization*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } + } + } else { + // Not initialized the account + + // Sending the message + $context->sendMessage('⚠️ *Failed to initialize your Telegram account*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } + } + + /** + * Contact (middleware) + * + * Check the account for access to contact with the organization + * + * @param context $context + * @param node $next + * + * @return void + */ + public static function contact(context $context, node $next): void + { + // Is the process stopped? + if ($context->get('stop')) return; + + // Initializing the account + $account = $context->get('account'); + + if ($account instanceof record) { + // Initialized the account + + if ($account->authorized_contact) { + // Authorized the account to contact with the organization + + // Continuation of the process + $next($context); + } else { + // Not authorized the account to contact with the organization + + // Initializing localization + $localization = $context->get('localization'); + + if ($localization) { + // Initialized localization + + // Sending the message + $context->sendMessage('⛔ *' . $localization['not_authorized_contact'] . '*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + + // Stopping the process + $context->set('stop', true); + } else { + // Not initialized localization + + // Sending the message + $context->sendMessage('⚠️ *Failed to initialize localization*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } + } + } else { + // Not initialized the account + + // Sending the message + $context->sendMessage('⚠️ *Failed to initialize your Telegram account*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } + } + + /** + * Request (middleware) + * + * Check the account for access to request to the organization + * + * @param context $context + * @param node $next + * + * @return void + */ + public static function request(context $context, node $next): void + { + // Is the process stopped? + if ($context->get('stop')) return; + + // Initializing the account + $account = $context->get('account'); + + if ($account instanceof record) { + // Initialized the account + + if ($account->authorized_request) { + // Authorized the account to request to the organization + + // Continuation of the process + $next($context); + } else { + // Not authorized the account to request to the organization + + // Initializing localization + $localization = $context->get('localization'); + + if ($localization) { + // Initialized localization + + // Sending the message + $context->sendMessage('⛔ *' . $localization['not_authorized_request'] . '*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + + // Stopping the process + $context->set('stop', true); + } else { + // Not initialized localization + + // Sending the message + $context->sendMessage('⚠️ *Failed to initialize localization*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } + } + } else { + // Not initialized the account + + // Sending the message + $context->sendMessage('⚠️ *Failed to initialize your Telegram account*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } + } + + /** + * Settings (middleware) + * + * Check the account for access to the settings + * + * @param context $context + * @param node $next + * + * @return void + */ + public static function settings(context $context, node $next): void + { + // Is the process stopped? + if ($context->get('stop')) return; + + // Initializing the account + $account = $context->get('account'); + + if ($account instanceof record) { + // Initialized the account + + if ($account->authorized_settings) { + // Authorized the account to the settings + + // Continuation of the process + $next($context); + } else { + // Not authorized the account to the settings + + // Initializing localization + $localization = $context->get('localization'); + + if ($localization) { + // Initialized localization + + // Sending the message + $context->sendMessage('⛔ *' . $localization['not_authorized_settings'] . '*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + + // Stopping the process + $context->set('stop', true); + } else { + // Not initialized localization + + // Sending the message + $context->sendMessage('⚠️ *Failed to initialize localization*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } + } + } else { + // Not initialized the account + + // Sending the message + $context->sendMessage('⚠️ *Failed to initialize your Telegram account*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } + } + + /** + * System settings (middleware) + * + * Check the account for access to the system settings + * + * @param context $context + * @param node $next + * + * @return void + */ + public static function system_settings(context $context, node $next): void + { + // Is the process stopped? + if ($context->get('stop')) return; + + // Initializing the account + $account = $context->get('account'); + + if ($account instanceof record) { + // Initialized the account + + if ($account->authorized_system_settings) { + // Authorized the account to the system settings + + // Continuation of the process + $next($context); + } else { + // Not authorized the account to the system settings + + // Initializing localization + $localization = $context->get('localization'); + + if ($localization) { + // Initialized localization + + // Sending the message + $context->sendMessage('⛔ *' . $localization['not_authorized_system_settings'] . '*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + + // Stopping the process + $context->set('stop', true); + } else { + // Not initialized localization + + // Sending the message + $context->sendMessage('⚠️ *Failed to initialize localization*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } + } + } else { + // Not initialized the account + + // Sending the message + $context->sendMessage('⚠️ *Failed to initialize your Telegram account*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } + } +} diff --git a/svoboda/negotiator/system/models/telegram/settings.php b/svoboda/negotiator/system/models/telegram/settings.php new file mode 100755 index 0000000..2fec87e --- /dev/null +++ b/svoboda/negotiator/system/models/telegram/settings.php @@ -0,0 +1,155 @@ + + */ +final class settings extends core +{ + /** + * Language + * + * Write language into the account record + * + * @param context $context Request data from Telegram + * @param language $language The language + * + * @return void + */ + public static function language(context $context, language $language): void + { + // Initializing the account + $account = $context->get('account'); + + if ($account instanceof record) { + // Initialized the account + + // Initializing localization + $localization = $context->get('localization'); + + if ($localization) { + // Initialized localization + + // Updating the account in the database + $updated = account::$database->read( + filter: fn(record $record) => $record->identifier === $account->identifier, + update: function (record &$record) use ($language) { + // Writing new language value into the record + $record->language = $language->name; + }, + amount: 1 + )[0] ?? null; + + if ($updated instanceof record) { + // Updated the account in the database + + // Writing the updated account into the context variable + $context->set('account', $updated); + + middlewares::language($context, new node(function (context $context) use ($account, $updated) { + // Updated language + + middlewares::localization($context, new node(function (context $context) use ($account, $updated) { + // Updated localization + + // Initializing localization + $localization = $context->get('localization'); + + if ($localization) { + // Initialized localization + try { + // Initializing the old language + $old = language::{$account->language}; + + // Initializing the new language + $new = language::{$updated->language}; + + // Sending the message + $context->sendMessage('✅ *' . $localization['settings_language_update_success'] . '* ' . ($old->flag() ? $old->flag() . ' ' : '') . $old->label($new) . ' » ' . ($new->flag() ? $new->flag() . ' ' : '') . $new->label($new)) + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } catch (error $error) { + // Failed to send the message about language update + + // Sending the message + $context->sendMessage('❎ *' . $localization['settings_language_update_fail']) + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } + } else { + // Not initialized localization + + // Sending the message + $context->sendMessage('⚠️ *Failed to initialize localization*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } + })); + })); + } else { + // Not updated the account in the database + + // Sending the message + $context->sendMessage('❎ *' . $localization['settings_language_update_fail']) + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } + } else { + // Not initialized localization + + // Sending the message + $context->sendMessage('⚠️ *Failed to initialize localization*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } + } else { + // Not initialized the account + + // Sending the message + $context->sendMessage('⚠️ *Failed to initialize your Telegram account*') + ->then(function ($message) use ($context) { + // Ending the conversation process + $context->endConversation(); + }); + } + } +} diff --git a/svoboda/negotiator/system/public/telegram.php b/svoboda/negotiator/system/public/telegram.php index 869a3a7..4551c3c 100755 --- a/svoboda/negotiator/system/public/telegram.php +++ b/svoboda/negotiator/system/public/telegram.php @@ -4,17 +4,17 @@ declare(strict_types=1); namespace svoboda\negotiator; - // Files of the project -use svoboda\negotiator\models\telegram; - -// Framework for PHP -use mirzaev\minimal\core; +use svoboda\negotiator\models\telegram\middlewares, + svoboda\negotiator\models\telegram\commands, + svoboda\negotiator\models\telegram\buttons, + svoboda\negotiator\models\telegram\settings, + svoboda\negotiator\models\enumerations\language; // Framework for Telegram -use Zanzara\Zanzara, - Zanzara\Context, - Zanzara\Config; +use Zanzara\Zanzara as zanzara, + Zanzara\Context as context, + Zanzara\Config as config; // Enabling debugging /* ini_set('error_reporting', E_ALL); @@ -24,38 +24,62 @@ ini_set('display_startup_errors', 1); */ // Initializing path to the public directory define('INDEX', __DIR__); -// Initializing path to the project root directory +// Initializing path to the root directory define('ROOT', INDEX . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR); -// Initializing path to the directory of settings +// Initializing path to the settings directory define('SETTINGS', INDEX . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'settings'); -// Initializing path to the storage +// Initializing path to the storage directory define('STORAGE', INDEX . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'storage'); +// Initializing path to the databases directory +define('DATABASES', INDEX . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'databases'); + +// Initializing path to the localizations directory +define('LOCALIZATIONS', INDEX . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'localizations'); + // Initiailizing telegram key define('TELEGRAM_KEY', require(SETTINGS . DIRECTORY_SEPARATOR . 'telegram.php')); // Initializing dependencies require ROOT . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php'; -var_dump(TELEGRAM_KEY); - -// Initializing core -$core = new core(namespace: __NAMESPACE__); - -$config = new Config(); -$config->setParseMode(Config::PARSE_MODE_MARKDOWN); +// Initializing the configuration +$config = new config(); +$config->setParseMode(config::PARSE_MODE_MARKDOWN); $config->useReactFileSystem(true); -$bot = new Zanzara(TELEGRAM_KEY, $config); +// Initializing the robot +$robot = new Zanzara(TELEGRAM_KEY, $config); -$bot->onUpdate(function (Context $ctx): void { - var_dump('biba'); -}); +// Initializing the updates listener +$robot->onUpdate(function (Context $context): void {}); + +// Initializing the robot middlewares +$robot->middleware([middlewares::class, 'account']); +$robot->middleware([middlewares::class, 'language']); +$robot->middleware([middlewares::class, 'localization']); +$robot->middleware([middlewares::class, 'system']); + +// Initializing the robot commands handlers +$robot->onCommand('start', [commands::class, 'menu']); +$robot->onCommand('menu', [commands::class, 'menu']); +/* $robot->onCommand('request', [telegram::class, 'request_start'])->middleware([telegram::class, 'request']); */ +$robot->onCommand('language', [commands::class, 'language'])->middleware([middlewares::class, 'settings']); +$robot->onCommand('society', [commands::class, 'society']); + +// Initializing the robot protected commands handlers +/* $robot->onCommand('system_settings', [commands::class, 'system_settings'])->middleware([middlewares::class, 'system_settings']); */ + +// Initializing the robot buttons handlers +foreach (language::cases() as $language) { + // Iterating over languages + + // Initializing language buttons + $robot->onCbQueryData(['settings_language_' . $language->name], fn(context $context) => settings::language($context, $language)); +}; -/* $bot->onCommand('start', fn($ctx) => telegram::start($ctx)); */ -$bot->onCommand('society', fn($ctx) => telegram::society($ctx)); // Starting chat-robot -$bot->run(); +$robot->run(); diff --git a/svoboda/negotiator/system/settings/telegram.php.sample b/svoboda/negotiator/system/settings/telegram.php.sample old mode 100644 new mode 100755 diff --git a/svoboda/negotiator/system/storage/images/mushroom.jpg b/svoboda/negotiator/system/storage/images/mushroom.jpg old mode 100644 new mode 100755