From f2eb59336e4eaf5c71e8a1d12d70796c5df66500 Mon Sep 17 00:00:00 2001 From: Arsen Mirzaev Tatyano-Muradovich Date: Tue, 6 Jan 2026 14:02:18 +0500 Subject: [PATCH] created from `kodorvan/neurobot` --- author/project/system/databases/.gitignore | 2 +- .../system/databases/scripts/account.php | 71 +++ author/project/system/models/account.php | 377 ++++++++++++++ .../project/system/models/authorizations.php | 120 +++++ author/project/system/models/settings.php | 106 ++++ .../system/models/telegram/commands.php | 393 +++++++++++++++ .../system/models/telegram/middlewares.php | 469 ++++++++++++++++++ .../telegram/processes/language/select.php | 152 ++++++ author/project/system/public/telegram.php | 101 ++++ .../project/system/settings/system.php.sample | 11 +- .../system/settings/telegram.php.sample | 7 + composer.json | 9 +- 12 files changed, 1814 insertions(+), 4 deletions(-) create mode 100644 author/project/system/databases/scripts/account.php create mode 100644 author/project/system/models/account.php create mode 100644 author/project/system/models/authorizations.php create mode 100644 author/project/system/models/settings.php create mode 100644 author/project/system/models/telegram/commands.php create mode 100644 author/project/system/models/telegram/middlewares.php create mode 100644 author/project/system/models/telegram/processes/language/select.php create mode 100644 author/project/system/public/telegram.php create mode 100644 author/project/system/settings/telegram.php.sample diff --git a/author/project/system/databases/.gitignore b/author/project/system/databases/.gitignore index c936709..94d59c2 100644 --- a/author/project/system/databases/.gitignore +++ b/author/project/system/databases/.gitignore @@ -1,3 +1,3 @@ !.gitignore +!*.php *.baza -*.php diff --git a/author/project/system/databases/scripts/account.php b/author/project/system/databases/scripts/account.php new file mode 100644 index 0000000..e41d4c8 --- /dev/null +++ b/author/project/system/databases/scripts/account.php @@ -0,0 +1,71 @@ +database->read( + filter: fn(record $$record) => $$record->domain === 'buddy_volkodav', + amount: 1, + offset: 0 +)[0] ?? null; + +var_dump($$account); + +// Initializing the account authorizations model +$$authorizations_model = new authorizations(); + +// Searching for the account authorizations +$$authorizations = $$authorizations_model->database->read( + filter: fn(record $$record) => $$record->account === $$account->identifier, + amount: 1, + offset: 0 +)[0] ?? null; + +var_dump($$authorizations); + diff --git a/author/project/system/models/account.php b/author/project/system/models/account.php new file mode 100644 index 0000000..ba8ecbd --- /dev/null +++ b/author/project/system/models/account.php @@ -0,0 +1,377 @@ + + */ +final class account extends core implements record_interface +{ + use record_trait; + + /** + * File + * + * @var string $$database Path to the database file + */ + protected string $$file = DATABASES . DIRECTORY_SEPARATOR . 'accounts.baza'; + + /** + * Database + * + * @var database $$database The database + */ + public protected(set) database $$database; + + /** + * Constructor + * + * @method record|null $$record The record + * + * @return void + */ + public function __construct(?record $$record = null) + { + // Initializing the database + $$this->database = new database() + ->encoding(encoding::utf8) + ->columns( + new column('identifier', type::long_long_unsigned), + new column('identifier_telegram', type::long_long_unsigned), + new column('domain', type::string, ['length' => 32]), + new column('name_first', type::string, ['length' => 64]), + new column('name_second', type::string, ['length' => 64]), + new column('language', type::string, ['length' => 2]), + new column('robot', type::char), + /* new column('', type::), */ + new column('updated', type::integer_unsigned), + new column('created', type::integer_unsigned) + ) + ->connect($$this->file); + + // Initializing the record + $$record instanceof record and $$this->record = $$record; + } + + /** + * Initialize + * + * @param telegram_user $$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 static|null The account, if found, updated or created + */ + public function initialize(telegram_user $$telegram): ?static + { + // Searching for the account in the database + $$account = $$this->database->read(filter: fn(record $$record) => $$record->identifier_telegram === $$telegram->getId(), amount: 1)[0] ?? null; + + if ($$account instanceof record) { + // Found the account record + + if ( + $$account->domain !== (string) $$telegram->getUsername() || + $$account->name_first !== (string) $$telegram->getFirstName() || + $$account->name_second !== (string) $$telegram->getLastName() || + $$account->language !== (string) $$telegram->getLanguageCode() + ) { + // The telegram account was updated + + // Updating the account in the database + $$updated = $$this->database->read( + filter: fn(record $$record) => $$record->identifier_telegram === $$telegram->getId(), + update: function (record &$$record) use ($$telegram) { + // Writing new values into the record + $$record->domain = (string) $$telegram->getUsername(); + $$record->name_first = (string) $$telegram->getFirstName(); + $$record->name_second = (string) $$telegram->getLastName(); + $$record->language = (string) $$telegram->getLanguageCode(); + $$record->updated = svoboda::timestamp(); + }, + amount: 1 + )[0] ?? null; + + if ($$updated instanceof record && $$updated->values() !== $$account->values()) { + // Updated the account in the database + + // Writing the updated record into the account object + $$this->record = $$updated; + + // Deserializing parameters + $$this->deserialize(); + + // Exit (success) + return $$this; + } 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'); + } + } + + // Writing the found record into the account object + $$this->record = $$account; + + // Deserializing parameters + $$this->deserialize(); + + // Exit (success) + return $$this; + } else { + // Not found the account record + + if ($$this->registrate($$telegram)) { + // Registered the account + + // Searching for the registered account in the database + $$registered = $$this->database->read(filter: fn(record $$record) => $$record->identifier_telegram === $$telegram->getId(), amount: 1)[0] ?? null; + + if ($$registered instanceof record) { + // Found the registered account + + // Writing the registered record into the account object + $$this->record = $$registered; + + // Deserializing parameters + $$this->deserialize(); + + // Exit (success) + return $$this; + } 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 + * + * Create the account by the telegram account data + * + * @param telegram_user $$telegram The telegram account + * + * @return record|false The record, if created + */ + public function registrate(telegram_user $$telegram): record|false + { + // Creating the record + $$record = $$this->write( + telegram_identifier: (int) $$telegram->getId(), + name_first: (string) $$telegram->getFirstName(), + name_last: (string) $$telegram->getLastName(), + domain: (string) $$telegram->getUsername(), + language: (string) $$telegram->getLanguageCode(), + robot: (bool) $$telegram->isBot() + ); + + if ($$record instanceof record) { + // The record was writed into the database + + // Initializing the authorizations model + $$authorizations = new authorizations(); + + // Creating the authorizations record + $$authorizations->write(account: $$record->identifier); + + // Initializing the settings model + $$settings = new settings(); + + // Creating the account settings + $$settings->write(account: $$record->identifier); + + // Initializing the chat model + $$chat = new chat(); + + // Creating the account chat + $$record->chat = $$chat->write(account: $$record->identifier, network: NETWORK_DEFAULT); + + // Initializing the tariff model + $$tariff = new tariff(); + + // Creating the tariff record + $$record->tariff = $$tariff->write(account: $$record->identifier, invoice: 0, active: 1, type: TARIFF_DEFAULT ?? tariff_type::free); + + // Writing the record into the database + $$record = $$this->database->read( + filter: fn(record $$_record) => $$_record->identifier === $$record->identifier, + update: fn(record &$$_record) => $$_record = $$record, + amount: 1 + )[0] ?? null; + + // Exit (success) + return $$record; + } + + // Exit (fail) + return false; + } + + /** + * Write + * + * @param int $$telegram_identifier The telegram account identifier + * @param string $$name_first + * @param string $$name_last + * @param string $$domain + * @param language|string $$language + * @param bool $$robot Is a robot? + * + * @return record|false The record, if created + */ + public function write( + int $$telegram_identifier, + string $$domain = '', + string $$name_first = '', + string $$name_last = '', + language|string $$language = LANGUAGE_DEFAULT ?? language::en, + bool $$robot = false, + ): record|false { + // Initializing the record + $$record = $$this->database->record( + $$this->database->count() + 1, + (int) $$telegram_identifier, + $$domain, + $$name_first, + $$name_last, + $$language instanceof language ? $$language->name : (string) $$language, + (int) $$robot, + /* */ + svoboda::timestamp(), + svoboda::timestamp() + ); + + // Writing the record into the database + $$created = $$this->database->write($$record); + + // Exit (success) + return $$created ? $$record : false; + } + + /** + * Serialize + * + * @return self The instance from which the method was called (fluent interface) + */ + public function serialize(): self + { + // Serializing the record parameters + $$this->record->language = $$this->record->language->name; + + // Exit (success) + return $$this; + } + + /** + * Deserialize + * + * @return self The instance from which the method was called (fluent interface) + */ + public function deserialize(): self + { + // Deserializing the record parameters + $$this->record->language = language::{$$this->record->language} ?? LANGUAGE_DEFAULT ?? language::en; + + // Exit (success) + return $$this; + } + + /** + * Authorizations + * + * Search for the account authorizations + * + * @return authorizations|null The account authorizations + */ + public function authorizations(): ?authorizations + { + // Search for the account authorizations + $$authorizations = new authorizations()->read(filter: fn(record $$record) => $$record->active === 1 && $$record->account === $$this->identifier); + + if ($$authorizations instanceof authorizations) { + // Found the account authorizations + + // Exit (success) + return $$authorizations; + } + + // Exit (fail) + return null; + } + + /** + * Settings + * + * Search for the account settings + * + * @return settings|null The account settings + */ + public function settings(): ?settings + { + // Search for the account settings + $$settings = new settings()->read(filter: fn(record $$record) => $$record->active === 1 && $$record->account === $$this->identifier); + + if ($$settings instanceof settings) { + // Found the account settings + + // Exit (success) + return $$settings; + } + + // Exit (fail) + return null; + } +} + diff --git a/author/project/system/models/authorizations.php b/author/project/system/models/authorizations.php new file mode 100644 index 0000000..dd4daa4 --- /dev/null +++ b/author/project/system/models/authorizations.php @@ -0,0 +1,120 @@ + + */ +final class authorizations extends core implements record_interface +{ + use record_trait; + + /** + * File + * + * @var string $$database Path to the database file + */ + protected string $$file = DATABASES . DIRECTORY_SEPARATOR . 'authorizations.baza'; + + /** + * Database + * + * @var database $$database The database + */ + public protected(set) database $$database; + + /** + * Constructor + * + * @method record|null $$record The record + * + * @return void + */ + public function __construct(?record $$record = null) + { + // Initializing the database + $$this->database = new database() + ->encoding(encoding::utf8) + ->columns( + new column('identifier', type::long_long_unsigned), + new column('account', type::long_long_unsigned), + new column('system', type::char), + new column('settings', type::char), + new column('chat', type::char), + /* new column('', type::char), */ + new column('system_settings', type::char), + new column('updated', type::integer_unsigned), + new column('created', type::integer_unsigned) + ) + ->connect($$this->file); + + // Initializing the record + $$record instanceof record and $$this->record = $$record; + } + + /** + * Write + * + * @param int $$account The account identifier + * @param int $$system + * @param int $$settings + * @param int $$system_settings + * + * @return int|false The record identifier, if created + */ + public function write( + int $$account, + int $$system = 1, + int $$settings = 1, + int $$system_settings = 0, + ): int|false + { + $$record = $$this->database->record( + $$this->database->count() + 1, + $$account, + $$system, + $$settings, + $$system_settings, + svoboda::timestamp(), + svoboda::timestamp() + ); + + // Writing the record into the database + $$created = $$this->database->write($$record); + + // Exit (success) + return $$created ? $$record->identifier : false; + } +} + diff --git a/author/project/system/models/settings.php b/author/project/system/models/settings.php new file mode 100644 index 0000000..8e839e9 --- /dev/null +++ b/author/project/system/models/settings.php @@ -0,0 +1,106 @@ + + */ +final class settings extends core implements record_interface +{ + use record_trait; + + /** + * File + * + * @var string $$database Path to the database file + */ + protected string $$file = DATABASES . DIRECTORY_SEPARATOR . 'settings.baza'; + + /** + * Database + * + * @var database $$database The database + */ + public protected(set) database $$database; + + /** + * Constructor + * + * @method record|null $$record The record + * + * @return void + */ + public function __construct(?record $$record = null) + { + // Initializing the database + $$this->database = new database() + ->encoding(encoding::utf8) + ->columns( + new column('identifier', type::long_long_unsigned), + new column('account', type::long_long_unsigned), + /* new column('', type::), */ + new column('updated', type::integer_unsigned), + new column('created', type::integer_unsigned) + ) + ->connect($$this->file); + + // Initializing the record + $$record instanceof record and $$this->record = $$record; + } + + /** + * Write + * + * @param int $$account The account identifier (0 for disable) + * + * @return int|false The record identifier, if created + */ + public function write( + int $$account = 0, + ): int|false { + $$record = $$this->database->record( + $$this->database->count() + 1, + $$account, + svoboda::timestamp(), + svoboda::timestamp() + ); + + // Writing the record into the database + $$created = $$this->database->write($$record); + + // Exit (success) + return $$created ? $$record->identifier : false; + } +} + diff --git a/author/project/system/models/telegram/commands.php b/author/project/system/models/telegram/commands.php new file mode 100644 index 0000000..cc2cb0b --- /dev/null +++ b/author/project/system/models/telegram/commands.php @@ -0,0 +1,393 @@ + + */ +final class commands extends core +{ + /** + * Start + * + * Responce for command: "/start" + * + * @param context $$context Request data from Telegram + * + * @return void + */ + public static function start(context $$context): void + { + static::menu($$context); + } + + /** + * Menu + * + * Responce for command: '/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 account) { + // Initialized the account + + // Initializing the language + $$language = $$context->get('language'); + + if ($$language instanceof language) { + // Initialized the language + + // Initializing localization + $$localization = $$context->get('localization'); + + if ($$localization) { + // Initialized localization + + // Initializing the title + $$title = '📋 *' . $$localization['menu_title'] . '*'; + + // Initializing accounts + /* $$accounts_message = '*' . $$localization['menu_accounts'] . ':* ' . ((new account)->database->count() ?? 0); */ + + // Initializing the account tariff + $$tariff = $$account->tariff(); + + // Declaring the tariff button + $$tariff_button = []; + + if ($$tariff instanceof tariff) { + // Initialized the account tariff + + // Initializing the tariff button + $$tariff_button = [ + 'text' => '🔐 ' . $$tariff->type->label($$language) . ' (' . $$tariff->used . '/' . $$tariff->tokens . ')', + 'callback_data' => 'tariffs' + ]; + } else { + + // Initialized the account tariff + + // Initializing the tariff button + $$tariff_button = [ + 'text' => '⚠️ ' . $$localization['menu_tariff_empty'], + 'callback_data' => 'tariffs' + ]; + } + + // Initializing the account chat + $$chat = $$account->chat(); + + // Initializing the chto text + $$howto = $$localization['menu_howto']; + + // Sending the message + $$context->sendMessage( + << [ + 'inline_keyboard' => [ + /* [ + [ + 'text' => '⚙️ ' . $$localization[''], + 'callback_data' => '' + ] + ] */ + ], + 'disable_notification' => true, + 'remove_keyboard' => true + ], + ] + )->then(function (message $$message) use ($$context) { + // Sended the message + + }); + } else { + // Not initialized localization + + // Sending the message + $$context->sendMessage('⚠️ *Failed to initialize localization*') + ->then(function (message $$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 $$message) use ($$context) { + // Sended the message + + // 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 $$message) use ($$context) { + // Ending the conversation process + $$context->endConversation(); + }); + } + } + + /** + * Account + * + * Responce for the command: "/account" + * + * Sends information about account with menu + * + * @param context $$context Request data from Telegram + * + * @return void + */ + public static function account(context $$context): void + { + // Initializing the account + $$account = $$context->get('account'); + + if ($$account instanceof account) { + // Initialized the account + + // Initializing localization + $$localization = $$context->get('localization'); + + if ($$localization) { + // Initialized localization + + // Initializing title for the message + $$title = '🫵 ' . $$localization['account_title']; + + // Declaring buufer of rows about authorizations + $$authorizations = ''; + + // Initializing rows about authorization + foreach ($$account->values() as $$key => $$value) { + // Iterating over account parameters + + if (str_starts_with($$key, 'authorized_')) { + // Iterating over account authorizations + + // Skipping system authorizations + if (str_starts_with($$key, 'authorized_system_')) continue; + + // Writing into buffer of rows about authorizations + $$authorizations .= ($$value ? '✅' : '❎') . ' *' . ($$localization["account_$$key"] ?? $$key) . ':* ' . ($$value ? $$localization['yes'] : $$localization['no']) . "\n"; + } + } + + // Trimming the last line break character + $$authorizations = trim($$authorizations, "\n"); + + // Sending the message + $$context->sendMessage( + << [ + 'remove_keyboard' => true, + 'disable_notification' => true + ], + 'link_preview_options' => [ + 'is_disabled' => true + ] + ] + ); + } else { + // Not initialized localization + + // Sending the message + $$context->sendMessage('⚠️ *Failed to initialize localization*') + ->then(function (message $$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 $$message) use ($$context) { + // Ending the conversation process + $$context->endConversation(); + }); + } + } + + /** + * Language + * + * Responce for the command: "/language" + * + * Send the 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 account) { + // Initialized the account + + // Initializing language + $$language = $$context->get('language'); + + if ($$language instanceof language) { + // Initialized language + + // Initializing localization + $$localization = $$context->get('localization'); + + if ($$localization) { + // Initialized localization + + // Sending the language selection + process_language_select::menu( + context: $$context, + prefix: 'settings_language_', + title: '🌏 *' . $$localization['settings_select_language_title'] . '*', + description: '🌏 *' . $$localization['settings_select_language_description'] . '*' + ); + } else { + // Not initialized localization + + // Sending the message + $$context->sendMessage('⚠️ *Failed to initialize localization*') + ->then(function (message $$message) use ($$context) { + // Sended the message + + // Ending the conversation process + $$context->endConversation(); + }); + } + } else { + // Not initialized language + + // Sending the message + $$context->sendMessage('⚠️ *Failed to initialize language*') + ->then(function (message $$message) use ($$context) { + // Sended the message + + // 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 $$message) use ($$context) { + // Sended the message + + // 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 account) { + // 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 $$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 $$message) use ($$context) { + // Ending the conversation process + $$context->endConversation(); + }); + } + } +} + diff --git a/author/project/system/models/telegram/middlewares.php b/author/project/system/models/telegram/middlewares.php new file mode 100644 index 0000000..0a01fc2 --- /dev/null +++ b/author/project/system/models/telegram/middlewares.php @@ -0,0 +1,469 @@ + + */ +final class middlewares extends core +{ + /** + * Account (middleware) + * + * Initialize or registrate the account and write it into 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); + + if ($$account instanceof account) { + // 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 $$message) use ($$context) { + // Sended the message + + // Ending the conversation process + $$context->endConversation(); + }); + } + } + + /** + * Authorizations (middleware) + * + * Initialize the account authorizations and write them into the `authorizations` variable inside the `$$context` + * + * @param context $$context + * @param node $$next + * + * @return void + */ + public static function authorizations(context $$context, node $$next): void + { + // Is the process stopped? + if ($$context->get('stop')) return; + + // Initializing the account + $$account = $$context->get('account'); + + if ($$account instanceof account) { + // Initialized the account + + // Initializing the account authorizations + $$authorizations = $$account->authorizations(); + + if ($$authorizations instanceof authorizations) { + // Initialized the account authorizations + + // Writing the account authorizations into the context variable + $$context->set('authorizations', $$authorizations); + + // Continuation of the process + $$next($$context); + } else { + // Not initialized the account + + // Sending the message + $$context->sendMessage('⚠️ *Failed to initialize your Telegram account authorizations*') + ->then(function (message $$message) use ($$context) { + // Sended the message + + // 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 $$message) use ($$context) { + // Sended the message + + // 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 account) { + // Initialized the account + + if ($$account->language instanceof language) { + // Initialized the language parameter + + try { + // Writing the account language into the context variable + $$context->set('language', $$account->language); + } catch (error $$error) { + // Not initialized the language + + // Writing the default language into the context variable + $$context->set('language', LANGUAGE_DEFAULT ?? language::en); + } + } else { + // Not initialized the language parameter + + // Writing the default language into the context variable + $$context->set('language', LANGUAGE_DEFAULT ?? 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 $$message) use ($$context) { + // Sended the message + + // 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 account) { + // 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)) { + // Initialized the localization + + // Writing localization into the context variable + $$context->set('localization', $$localization); + + // Continuation of the process + $$next($$context); + } else { + // Not initialized the localization + + // Sending the message + $$context->sendMessage('⚠️ *Failed to initialize localization*') + ->then(function (message $$message) use ($$context) { + // Sended the message + + // 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 $$message) use ($$context) { + // Sended the message + + // Ending the conversation process + $$context->endConversation(); + }); + } + } else { + // Not initialized language + + // Sending the message + $$context->sendMessage('⚠️ *Failed to initialize language*') + ->then(function (message $$message) use ($$context) { + // Sended the message + + // 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 $$message) use ($$context) { + // Sended the message + + // 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 account) { + // Initialized the account + + // Initializing the account authorizations + $$authorizations = $$context->get('authorizations'); + + if ($$authorizations instanceof authorizations) { + // Initialized the account authorizations + + if ($$authorizations->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 $$message) use ($$context) { + // Sended the message + + // 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 $$message) use ($$context) { + // Sended the message + + // Ending the conversation process + $$context->endConversation(); + }); + } + } + } else { + // Not initialized the account authorizations + + // Sending the message + $$context->sendMessage('⚠️ *Failed to initialize your Telegram account authorizations*') + ->then(function (message $$message) use ($$context) { + // Sended the message + + // 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 $$message) use ($$context) { + // Sended the message + + // 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 account) { + // Initialized the account + + // Initializing the account authorizations + $$authorizations = $$context->get('authorizations'); + + if ($$authorizations instanceof authorizations) { + // Initialized the account authorizations + + if ($$authorizations->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 $$message) use ($$context) { + // Sended the message + + // 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 $$message) use ($$context) { + // Sended the message + + // Ending the conversation process + $$context->endConversation(); + }); + } + } + } else { + // Not initialized the account + + // Sending the message + $$context->sendMessage('⚠️ *Failed to initialize your Telegram account authorizations*') + ->then(function (message $$message) use ($$context) { + // Sended the message + + // 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 $$message) use ($$context) { + // Sended the message + + // Ending the conversation process + $$context->endConversation(); + }); + } + } +} + diff --git a/author/project/system/models/telegram/processes/language/select.php b/author/project/system/models/telegram/processes/language/select.php new file mode 100644 index 0000000..f45bcab --- /dev/null +++ b/author/project/system/models/telegram/processes/language/select.php @@ -0,0 +1,152 @@ + + */ +final class select extends core +{ + /** + * Language + * + * Send the language choose menu + * + * @param context $$context Request data from Telegram + * @param string $$prefix Prefix for 'callback_data' (`$$prefix . $$language->name`) + * @param string $$title Title of the message + * @param string $$description Description of the message + * @param array $$exclude Languages that will be excluded ['ru', 'en'...] + * + * @return void + */ + public static function menu(context $$context, string $$prefix, string $$title, string $$description, array $$exclude = []): void + { + // Initializing the account + $$account = $$context->get('account'); + + if ($$account instanceof record) { + // Initialized the account + + // Initializing language + $$language = $$context->get('language'); + + if ($$language) { + // Initialized language + + // 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; + + // Initializing buffer of languages + $$languages = language::cases(); + + // Deleting the actual language from buffer of languages + unset($$languages[array_search($$language, $$languages, strict: true)]); + + // Sorting buffer of languages by the actual language + $$languages = [$$language, ...$$languages]; + + foreach ($$languages as $$language) { + // Iterating over languages + + // Skipping excluded languages + if (array_search($$language->name, $$exclude, strict: true) !== false) continue; + + // 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' => $$prefix . $$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 === 0 && empty($$keyboard[0]) ? 0 : ++$$row] = [ + [ + 'text' => '🗂 ' . $$localization['select_language_button_add'], + 'url' => 'https://git.svoboda.works/${REPO_OWNER}\${REPO_NAME}/src/branch/stable/kodorvan/neurobot/system/localizations' + ] + ]; + + // Sending the message + $$context->sendMessage( + $$title ?? '🌏 *' . $$localization['select_language_title'] . "*\n" . ($$description ?? $$localization['select_language_description']), + [ + 'reply_markup' => [ + 'inline_keyboard' => $$keyboard, + 'disable_notification' => true + ], + ] + ); + } else { + // Not initialized localization + + // Sending the message + $$context->sendMessage('⚠️ *Failed to initialize localization*') + ->then(function (message $$message) use ($$context) { + // Sended the message + + // Ending the conversation process + $$context->endConversation(); + }); + } + } else { + // Not initialized language + + // Sending the message + $$context->sendMessage('⚠️ *Failed to initialize language*') + ->then(function (message $$message) use ($$context) { + // Sended the message + + // 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 $$message) use ($$context) { + // Sended the message + + // Ending the conversation process + $$context->endConversation(); + }); + } + } +} diff --git a/author/project/system/public/telegram.php b/author/project/system/public/telegram.php new file mode 100644 index 0000000..82bedcb --- /dev/null +++ b/author/project/system/public/telegram.php @@ -0,0 +1,101 @@ +setParseMode(config::PARSE_MODE_MARKDOWN); +$$config->useReactFileSystem(true); + +// Initializing the robot +$$robot = new Zanzara(ROBOT['key'], $$config); + +// 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, 'authorizations']); +$$robot->middleware([middlewares::class, 'welcome']); + +// Initializing the robot commands handlers +$$robot->onCommand('start', [commands::class, 'start']); +$$robot->onCommand('menu', [commands::class, 'menu']); +$$robot->onCommand('language', [commands::class, 'language'])->middleware([middlewares::class, 'settings']); +$$robot->onCommand('society', [commands::class, 'society']); + +// Initializing the robot settings language 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)); +}; + +// Starting chat-robot +$$robot->run(); diff --git a/author/project/system/settings/system.php.sample b/author/project/system/settings/system.php.sample index 7ebee3d..549fb63 100644 --- a/author/project/system/settings/system.php.sample +++ b/author/project/system/settings/system.php.sample @@ -1,4 +1,13 @@ null, + 'key' => '' +]); diff --git a/composer.json b/composer.json index af543fc..b9cb8db 100755 --- a/composer.json +++ b/composer.json @@ -22,10 +22,15 @@ "issues": "https://git.svoboda.works${REPO_LINK}/issues" }, "require": { - "php": "^8.4", + "php": "^8.5", "mirzaev/minimal": "^3.7", "mirzaev/baza": "^3.3", - "mirzaev/languages": "^1", + "mirzaev/record": "^1.0", + "mirzaev/languages": "^1.0", + "mirzaev/currencies": "^2.0", + "mirzaev/unmarkdown": "^1.0", + "svoboda/time": "^1.0", + "badfarm/zanzara": "^0.9.1", "twig/twig": "^3.2", "twig/extra-bundle": "^3.7", "twig/intl-extra": "^3.10"