Compare commits

...

68 Commits
2.1.0 ... 5.0.1

Author SHA1 Message Date
8b5a49747b why so shroomious 2026-01-06 14:04:51 +05:00
f2eb59336e created from kodorvan/neurobot 2026-01-06 14:02:18 +05:00
913dfb8a92 fixed $ 2025-11-04 16:19:18 +07:00
372d008545 added copying *.sample files script 2025-11-04 16:12:31 +07:00
e38a870e71 controller HTML response 2025-11-04 10:55:58 +07:00
36b48d14d1 suggest mirzaev/files and delete files trait 2025-11-04 02:41:27 +07:00
1261738c3d languages support + deleted @author tags 2025-10-26 18:06:27 +07:00
9718bec887 languages and currencies 2025-10-26 17:34:50 +07:00
7f8525789e update minimal 2025-10-11 16:35:55 +07:00
c6f7f65360 deleting when empty 2025-07-06 13:22:05 +07:00
c65f7d4055 deleting when empty 2025-07-06 13:21:53 +07:00
bdef194b68 deleting when empty 2025-07-06 13:21:38 +07:00
a3eeacc4b4 flex-grow: 1; 2025-07-06 13:20:42 +07:00
da69b20491 colorscheme 2025-07-06 13:19:30 +07:00
1d4d3e5f24 updated and renamed 2025-07-06 13:18:26 +07:00
2b417f1649 fixed paths 2025-07-06 13:16:42 +07:00
1ee4c9a7dd deleted session 2025-07-06 11:59:42 +07:00
ece40a8644 added tabs 2025-07-06 11:28:56 +07:00
6e5339a7d9 added russian 2025-07-06 10:41:28 +07:00
b989a89e2b fixed 2025-07-06 10:41:04 +07:00
fbcb72a47b deleted arangodb 2025-07-06 10:35:42 +07:00
485ac59c69 english localization 2025-07-06 10:28:46 +07:00
315f9bb7e3 added localizations 2025-07-06 10:27:23 +07:00
9baf88d93c updated dependencies 2025-07-05 22:37:42 +07:00
d3a47b04fb body margin unset 2025-04-10 22:47:34 +07:00
1a05a0413d returned templater 2025-04-10 22:33:05 +07:00
8c777e72c7 $ to $$ 2025-03-30 00:37:01 +07:00
a62b5ad3e5 resolved #13, resolved #14, resolved #15 2025-02-26 13:40:06 +07:00
4eecb4c5ed resolved #13, resolved #14 2025-02-26 13:27:59 +07:00
ff663e7bf7 resolved #12 2025-02-21 12:07:50 +07:00
32d92bcc7e resolved #11 2025-02-21 12:07:15 +07:00
5c06ec423a resolved #10 2025-02-21 11:57:23 +07:00
41c0e2717c "/css/themes/default" to "/themes/default/css" 2024-12-17 15:17:45 +07:00
6109c2dd2f added fonts 2024-12-17 15:02:07 +07:00
9f375114ef deleted spaces 2024-12-17 14:25:47 +07:00
f8f6119ef6 added dynamic load css 2024-12-17 14:25:10 +07:00
9ef52e1dfc "javascript" to "js" 2024-12-17 14:22:47 +07:00
d3775bf96d some syntax errors 2024-12-16 23:23:46 +07:00
510a80665b added "/themes/default/" 2024-12-16 23:21:31 +07:00
e805fe9e76 fixed for core.html 2024-12-16 23:21:10 +07:00
2c29d0c842 added "/themes/default/" 2024-12-16 23:18:03 +07:00
93311f1857 getGlobal to getGlobals() 2024-12-16 22:47:43 +07:00
b86e856fe7 views\manager to views\templater 2024-12-16 22:44:36 +07:00
a893aa6b5a $minimal to $core 2024-12-16 22:42:08 +07:00
321c28a53e ${REPO_OWNER}\${REPO_NAME}\models\enumerations\language 2024-12-16 22:23:31 +07:00
9b958b6a88 $$router to $$core 2024-12-16 20:01:33 +07:00
24fcef43f7 PUBLIC to INDEX lol 2024-12-16 20:00:20 +07:00
c9e5cb3762 mirzaev\minimal\http\enumerations\content 2024-12-16 19:50:07 +07:00
2c6ed07ded {{ theme }} to "default" back 2024-12-16 18:33:58 +07:00
96388c220e any type instead fixed "module" 2024-12-16 18:25:49 +07:00
c2cba489d1 added dynamic load javascript 2024-12-16 18:23:15 +07:00
aad0a5a051 forget about it 2024-12-16 18:16:53 +07:00
8159f6866d created main.html 2024-12-16 18:15:28 +07:00
9dccb451f6 added aside.html 2024-12-16 18:13:59 +07:00
9f3b87c1ed created aside.html 2024-12-16 18:13:16 +07:00
e0845e2ef1 added colors.css 2024-12-16 17:08:39 +07:00
5c0f1815c0 created colors.css 2024-12-16 17:07:28 +07:00
6a4cfb8e2f deleted EOL 2024-12-16 17:05:44 +07:00
7ddf05ead3 Обновить author/project/system/public/css/themes/default/system.css 2024-12-16 17:04:53 +07:00
b6d2725848 separated 2024-12-16 17:04:30 +07:00
3a2e102e11 created footer.css 2024-12-16 17:04:01 +07:00
3aa8936fc5 created aside.css 2024-12-16 17:03:32 +07:00
3af08b07ed created header.css 2024-12-16 17:03:13 +07:00
4f4d31b64a created system.css 2024-12-16 17:02:39 +07:00
c0515a4171 separating main.css 2024-12-16 16:59:26 +07:00
02d1350982 {{ theme }} 2024-12-16 16:54:55 +07:00
37ae0546fd INDEX to PUBLIC 2024-12-16 15:52:52 +07:00
0510dca375 removed dublicate 2024-12-16 15:52:20 +07:00
155 changed files with 2253 additions and 1174 deletions

1
.gitignore vendored
View File

@@ -1,4 +1,3 @@
!.gitignore
composer.phar
composer.lock
vendor

View File

@@ -5,9 +5,11 @@ declare(strict_types=1);
namespace ${REPO_OWNER}\${REPO_NAME}\controllers;
// Files of the project
use ${REPO_OWNER}\${REPO_NAME}\views\manager,
${REPO_OWNER}\${REPO_NAME}\models\core as models,
${REPO_OWNER}\${REPO_NAME}\models\session;
use ${REPO_OWNER}\${REPO_NAME}\views\templater,
${REPO_OWNER}\${REPO_NAME}\models\core as models;
// Library for languages support
use mirzaev\languages\language;
// Framework for PHP
use mirzaev\minimal\core as minimal,
@@ -20,25 +22,17 @@ use mirzaev\minimal\core as minimal,
*
* @package ${REPO_OWNER}\${REPO_NAME}\controllers
*
* @param session $$session Instance of the session
* @param language $$language Language
* @param response $$response Response
* @param array $$errors Registry of errors
*
* @method void __construct(minimal $$minimal, bool $$initialize) Constructor
* @method void __construct(minimal $$minimal) Constructor
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author ${REPO_OWNER} <mail@domain.zone>
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
class core extends controller
{
/**
* Session
*
* @var session|null $$session Instance of the session
*/
protected readonly session $$session;
/**
* Language
*
@@ -64,62 +58,26 @@ class core extends controller
* @var array $$errors Registry of errors
*/
protected array $$errors = [
'session' => [],
'account' => []
'system' => []
];
/**
* Constructor
*
* @param minimal $$minimal Instance of the MINIMAL
* @param minimal $$core Instance of the MINIMAL
* @param bool $$initialize Initialize a controller?
*
* @return void
*/
public function __construct(minimal $$minimal, bool $$initialize = true)
public function __construct(minimal $$core)
{
// Blocking requests from CloudFlare (better to write this blocking into nginx config file)
if (isset($$_SERVER['HTTP_USER_AGENT']) && $$_SERVER['HTTP_USER_AGENT'] === 'nginx-ssl early hints') return status::bruh->label;
// Initializing the view template engine instance
$$this->view = new templater();
// For the extends system
parent::__construct(core: $$minimal);
if ($$initialize) {
// Requestet initializing
// Initializing core of the models
new models();
// Initializing of the date until which the session will be active
$$expires = strtotime('+1 week');
// Initializing of default value of hash of the session
$$_COOKIE["session"] ??= null;
// Initializing of session
$$this->session = new session($$_COOKIE["session"], $$expires, $$this->errors['session']);
// Handle a problems with initializing a session
if (!empty($$this->errors['session'])) die;
else if ($$_COOKIE["session"] !== $$this->session->hash) {
// Hash of the session is changed (implies that the session has expired and recreated)
// Write a new hash of the session to cookies
setcookie(
'session',
$$this->session->hash,
[
'expires' => $$expires,
'path' => '/',
'secure' => true,
'httponly' => true,
'samesite' => 'strict'
]
);
}
// Initializing of preprocessor of views
$$this->view = new templater($$this->session);
}
parent::__construct(core: $$core);
}
}

View File

@@ -8,7 +8,8 @@ namespace ${REPO_OWNER}\${REPO_NAME}\controllers;
use ${REPO_OWNER}\${REPO_NAME}\controllers\core;
// Framework for PHP
use mirzaev\minimal\http\enumerations\status;
use mirzaev\minimal\http\enumerations\content,
mirzaev\minimal\http\enumerations\status;
/**
* Index
@@ -20,7 +21,7 @@ use mirzaev\minimal\http\enumerations\status;
* @method null index() Main page
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author ${REPO_OWNER} <mail@domain.zone>
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
final class index extends core
{
@@ -30,7 +31,7 @@ final class index extends core
* @var array $$errors Registry of errors
*/
protected array $$errors = [
'session' => []
'system' => []
];
/**
@@ -40,8 +41,8 @@ final class index extends core
*/
public function index(): null
{
if (str_contains($$this->request->headers['accept'], content::any->value)) {
// Request for any response
if (str_contains($$this->request->headers['accept'] ?? '', content::html->value)) {
// Request for HTML response
// Render page
$$page = $$this->view->render('index.html');

View File

@@ -0,0 +1,3 @@
!.gitignore
!*.php
*.baza

View File

@@ -0,0 +1,71 @@
<?php
declare(strict_types=1);
namespace ${REPO_OWNER}\${REPO_NAME};
// Files of the project
use ${REPO_OWNER}\${REPO_NAME}\models\account,
${REPO_OWNER}\${REPO_NAME}\models\authorizations,
${REPO_OWNER}\${REPO_NAME}\models\chat,
${REPO_OWNER}\${REPO_NAME}\models\tariff;
// Svoboda time
use svoboda\time\statement as svoboda;
// Baza database
use mirzaev\baza\record;
// Enabling debugging
/* ini_set('error_reporting', E_ALL);
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1); */
// Initializing path to the public directory
define('INDEX', __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'public');
// Initializing path to the root directory
define('ROOT', INDEX . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR);
// Initializing path to the settings directory
define('SETTINGS', INDEX . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'settings');
// 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 data
require(SETTINGS . DIRECTORY_SEPARATOR . 'telegram.php');
// Initializing dependencies
require ROOT . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
// Initializing the account model
$$account_model = new account();
// Searching for the account
$$account = $$account_model->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);

View File

@@ -0,0 +1,6 @@
<?php
// Exit (success)
return [
'' => ''
]

View File

@@ -0,0 +1,6 @@
<?php
// Exit (success)
return [
'' => ''
]

View File

@@ -0,0 +1,377 @@
<?php
declare(strict_types=1);
namespace ${REPO_OWNER}\${REPO_NAME}\models;
// Files of the project
use ${REPO_OWNER}\${REPO_NAME}\models\core,
${REPO_OWNER}\${REPO_NAME}\models\authorizations,
${REPO_OWNER}\${REPO_NAME}\models\chat,
${REPO_OWNER}\${REPO_NAME}\models\settings,
${REPO_OWNER}\${REPO_NAME}\models\tariff,
${REPO_OWNER}\${REPO_NAME}\models\code,
${REPO_OWNER}\${REPO_NAME}\models\enumerations\tariff as tariff_type;
// The library for languages support
use mirzaev\languages\language;
// Baza database
use mirzaev\baza\database,
mirzaev\baza\column,
mirzaev\baza\record,
mirzaev\baza\enumerations\encoding,
mirzaev\baza\enumerations\type;
// Active Record pattern
use mirzaev\record\interfaces\record as record_interface,
mirzaev\record\traits\record as record_trait;
// Svoboda time
use svoboda\time\statement as svoboda;
// Framework for Telegram
use Zanzara\Telegram\Type\User as telegram_user;
// Built-in libraries
use Exception as exception,
RuntimeException as exception_runtime;
/**
* Account
*
* @package ${REPO_OWNER}\${REPO_NAME}\models
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
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;
}
}

View File

@@ -0,0 +1,120 @@
<?php
declare(strict_types=1);
namespace ${REPO_OWNER}\${REPO_NAME}\models;
// Files of the project
use ${REPO_OWNER}\${REPO_NAME}\models\core;
// Baza database
use mirzaev\baza\database,
mirzaev\baza\column,
mirzaev\baza\record,
mirzaev\baza\enumerations\encoding,
mirzaev\baza\enumerations\type;
// Active Record pattern
use mirzaev\record\interfaces\record as record_interface,
mirzaev\record\traits\record as record_trait;
// Svoboda time
use svoboda\time\statement as svoboda;
// Framework for Telegram
use Zanzara\Telegram\Type\User as telegram;
// Built-in libraries
use Exception as exception,
RuntimeException as exception_runtime;
/**
* Authorizations
*
* @package ${REPO_OWNER}\${REPO_NAME}\models
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
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;
}
}

View File

@@ -8,15 +8,6 @@ namespace ${REPO_OWNER}\${REPO_NAME}\models;
use mirzaev\minimal\model,
mirzaev\minimal\http\enumerations\status;
// Framework for ArangoDB
use mirzaev\arangodb\connection as arangodb,
mirzaev\arangodb\collection,
mirzaev\arangodb\document;
// Library for ArangoDB
use ArangoDBClient\Document as _document,
ArangoDBClient\DocumentHandler as _document_handler;
// Built-in libraries
use exception;
@@ -25,206 +16,29 @@ use exception;
*
* @package ${REPO_OWNER}\${REPO_NAME}\models
*
* @param public ARANGODB Path to the file with ArangoDB session connection data
* @param arangodb $$arangodb Instance of the ArangoDB session
*
* @method void __construct(bool $$initialize, ?arangodb $$arangodb) Constructor
* @method _document|static|array|null read(string $$filter, string $$sort, int $$amount, int $$page, string $$return, array $$parameters, array &$$errors) Read document from ArangoDB
* @method void __construct() Constructor
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author ${REPO_OWNER} <mail@domain.zone>
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
class core extends model
{
/**
* ArangoDB connection daa
* File
*
* @var string ARANGODB Path to the file with ArangoDB session connection data
* @var string $database Path to the database file
*/
final public const string ARANGODB = __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'settings' . DIRECTORY_SEPARATOR . 'arangodb.php';
/**
* ArangoDB
*
* @var arangodb $$arangodb Instance of the ArangoDB session
*/
protected static arangodb $$arangodb;
protected string $$file = DATABASES . DIRECTORY_SEPARATOR . 'example.baza';
/**
* Constructor
*
* @param bool $$initialize Initialize a model?
* @param ?arangodb $$arangodb Instance of the ArangoDB session
* Initialize the database
*
* @return void
*/
public function __construct(bool $$initialize = true, ?arangodb $$arangodb = null)
public function __construct()
{
// For the extends system
parent::__construct($$initialize);
if ($$initialize) {
// Initializing is requested
// Writing an instance of a session of ArangoDB to the property
self::$$arangodb = $$arangodb ?? new arangodb(require static::ARANGODB);
}
}
/**
* Read document from ArangoDB
*
* @param string $$filter Expression for filtering (AQL)
* @param string $$sort Expression for sorting (AQL)
* @param int $$amount Amount of documents for collect
* @param int $$page Page
* @param string $$return Expression describing the parameters to return (AQL)
* @param array $$parameters Binded parameters for placeholders ['placeholder' => parameter]
* @param array &$$errors Registry of errors
*
* @return mixed An array of instances of documents from ArangoDB, if they are found
*/
public static function _read(
string $$filter = '',
string $$sort = 'd.created DESC, d._key DESC',
int $$amount = 1,
int $$page = 1,
string $$return = 'd',
array $$parameters = [],
array &$$errors = []
): _document|static|array|null {
try {
if (collection::initialize(static::COLLECTION, static::TYPE)) {
// Initialized the collection
// Read from ArangoDB
$$result = collection::execute(
sprintf(
<<<'AQL'
FOR d IN @@collection
%s
%s
LIMIT @offset, @amount
RETURN %s
AQL,
empty($$filter) ? '' : "FILTER $$filter",
empty($$sort) ? '' : "SORT $$sort",
empty($$return) ? 'd' : $$return
),
[
'@collection' => static::COLLECTION,
'offset' => --$$page <= 0 ? 0 : $$page * $$amount,
'amount' => $$amount
] + $$parameters,
errors: $$errors
);
if ($$amount === 1 && $$result instanceof _document) {
// Received only 1 document and @todo rebuild
// Initializing the object
$$object = new static;
if (method_exists($$object, '__document')) {
// Object can implement a document from ArangoDB
// Writing the instance of document from ArangoDB to the implement object
$$object->__document($$result);
// Exit (success)
return $$object;
}
}
// Exit (success)
return $$result;
} else throw new exception('Failed to initialize ' . static::TYPE . ' collection: ' . static::COLLECTION);
} catch (exception $$e) {
// Writing to registry of errors
$$errors[] = [
'text' => $$e->getMessage(),
'file' => $$e->getFile(),
'line' => $$e->getLine(),
'stack' => $$e->getTrace()
];
}
// Exit (fail)
return null;
}
/**
* Write
*
* @param string $$name Name of the property
* @param mixed $$value Value of the property
*
* @return void
*/
public function __set(string $$name, mixed $$value = null): void
{
match ($$name) {
'arangodb' => (function () use ($$value) {
if (isset(static::$$arangodb)) throw new exception('Forbidden to reinitialize the ArangoDB session($$this::$$arangodb)', status::internal_server_error->value);
else if ($$value instanceof arangodb) self::$$arangodb = $$value;
else throw new exception('Session of connection to ArangoDB ($$this::$$arangodb) is need to be mirzaev\arangodb\connection', status::internal_server_error->value);
})(),
default => parent::__set($$name, $$value)
};
}
/**
* Read
*
* @param string $$name Name of the property
*
* @return mixed Content of the property, if they are found
*/
public function __get(string $$name): mixed
{
return match ($$name) {
default => parent::__get($$name)
};
}
/**
* Delete
*
* @param string $$name Name of the property
*
* @return void
*/
public function __unset(string $$name): void
{
// Deleting a property and exit (success)
parent::__unset($$name);
}
/**
* Check of initialization
*
* @param string $$name Name of the property
*
* @return bool The property is initialized?
*/
public function __isset(string $$name): bool
{
// Check of initialization of the property and exit (success)
return parent::__isset($$name);
}
/**
* Call a static property or method
*
* @param string $$name Name of the property or the method
* @param array $$arguments Arguments for the method
*/
public static function __callStatic(string $$name, array $$arguments): mixed
{
return match ($$name) {
'arangodb' => (new static)->__get('arangodb'),
default => throw new exception("Not found: $$name", 500)
};
}
}

View File

@@ -1,50 +0,0 @@
<?php
declare(strict_types=1);
namespace ${REPO_OWNER}\${REPO_NAME}\models\enumerations;
/**
* Language
*
* Types of languages by ISO 639-1 standart
*
* @package ${REPO_OWNER}\${REPO_NAME}\models\enumerations
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
* @author ${REPO_OWNER} <mail@domain.zone>
*/
enum language
{
case en;
case ru;
/**
* Label
*
* Initialize label of the 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
{
// Exit (success)
return match ($$this) {
language::en => match ($$language) {
language::en => 'English',
language::ru => 'Английский'
},
language::ru => match ($$language) {
language::en => 'Russian',
language::ru => 'Русский'
}
};
}
}

View File

@@ -1,21 +0,0 @@
<?php
declare(strict_types=1);
namespace ${REPO_OWNER}\${REPO_NAME}\models\enumerations;
/**
* Session
*
* Types of session verification
*
* @package ${REPO_OWNER}\${REPO_NAME}\models\enumerations
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author ${REPO_OWNER} <mail@domain.zone>
*/
enum session
{
case hash_only;
case hash_else_address;
}

View File

@@ -1,31 +0,0 @@
<?php
declare(strict_types=1);
namespace ${REPO_OWNER}\${REPO_NAME}\models\interfaces;
// Framework for ArangoDB
use mirzaev\arangodb\enumerations\collection\type;
/**
* Collection
*
* Interface for implementing a collection from ArangoDB
*
* @package ${REPO_OWNER}\${REPO_NAME}\models\interfaces
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author ${REPO_OWNER} <mail@domain.zone>
*/
interface collection
{
/**
* Name of the collection in ArangoDB
*/
public const string COLLECTION = 'THIS_COLLECTION_SHOULD_NOT_EXIST';
/**
* Type of the collection in ArangoDB
*/
public const type TYPE = type::document;
}

View File

@@ -1,81 +0,0 @@
<?php
declare(strict_types=1);
namespace ${REPO_OWNER}\${REPO_NAME}\models\interfaces;
// Library для ArangoDB
use ArangoDBClient\Document as _document;
/**
* Document
*
* Interface for implementing a document instance from ArangoDB
*
* @param _document $$document An instance of the ArangoDB document from ArangoDB (protected readonly)
*
* @package ${REPO_OWNER}\${REPO_NAME}\models\interfaces
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author ${REPO_OWNER} <mail@domain.zone>
*/
interface document
{
/**
* Write
*
* Write a property into an instance of the ArangoDB document
*
* @param string $$name Name of the property
* @param mixed $$value Content of the property
*
* @return void
*/
public function __set(string $$name, mixed $$value = null): void;
/**
* Read
*
* Read a property from an instance of the ArangoDB docuemnt
*
* @param string $$name Name of the property
*
* @return mixed Content of the property
*/
public function __get(string $$name): mixed;
/**
* Delete
*
* Deinitialize the property in an instance of the ArangoDB document
*
* @param string $$name Name of the property
*
* @return void
*/
public function __unset(string $$name): void;
/**
* Check of initialization
*
* Check of initialization of the property into an instance of the ArangoDB document
*
* @param string $$name Name of the property
*
* @return bool The property is initialized?
*/
public function __isset(string $$name): bool;
/**
* Execute a method
*
* Execute a method from an instance of the ArangoDB document
*
* @param string $$name Name of the method
* @param array $$arguments Arguments for the method
*
* @return mixed Result of execution of the method
*/
public function __call(string $$name, array $$arguments = []): mixed;
}

View File

@@ -1,233 +0,0 @@
<?php
declare(strict_types=1);
namespace ${REPO_OWNER}\${REPO_NAME}\models;
// Files of the project
use ${REPO_OWNER}\${REPO_NAME}\models\traits\status,
${REPO_OWNER}\${REPO_NAME}\models\traits\buffer,
${REPO_OWNER}\${REPO_NAME}\models\traits\document as document_trait,
${REPO_OWNER}\${REPO_NAME}\models\interfaces\document as document_interface,
${REPO_OWNER}\${REPO_NAME}\models\interfaces\collection as collection_interface,
${REPO_OWNER}\${REPO_NAME}\models\enumerations\session as verification,
${REPO_OWNER}\${REPO_NAME}\models\enumerations\language;
// Framework for ArangoDB
use mirzaev\arangodb\collection,
mirzaev\arangodb\document;
// Library для ArangoDB
use ArangoDBClient\Document as _document;
// Built-in libraries
use exception;
/**
* Session model
*
* @package ${REPO_OWNER}\${REPO_NAME}\models
*
* @param string COLLECTION Name of the collection in ArangoDB
* @param verification VERIFICATION Type of session verification
*
* @method void __construct(?string $$hash, ?int $$expires, array &$$errors) Constructor
* @method document|null hash(string $$hash, array &$$errors) Search by hash
* @method document|null address(string $$address, array &$$errors) Search by IP-address
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author ${REPO_OWNER} <mail@domain.zone>
*/
final class session extends core implements document_interface, collection_interface
{
use status, document_trait, buffer, cart {
buffer::write as write;
cart::initialize as cart;
}
/**
* Collection name
*
* @var string COLLECTION Name of the collection in ArangoDB
*/
final public const string COLLECTION = 'session';
/**
* Session verification type
*
* @var verification VERIFICATION Type of session verification
*/
final public const verification VERIFICATION = verification::hash_else_address;
/**
* Constructor
*
* Initialize session and write into the $$this->document property
*
* @param ?string $$hash Hash of the session in ArangoDB
* @param ?int $$expires Date of expiring of the session (used for creating a new session)
* @param array &$$errors Registry of errors
*
* @return void
*/
public function __construct(?string $$hash = null, ?int $$expires = null, array &$$errors = [])
{
try {
if (collection::initialize(static::COLLECTION, static::TYPE, errors: $$errors)) {
// Initialized the collection
if (isset($$hash) && $$document = $$this->hash($$hash, errors: $$errors)) {
// Found the instance of the ArangoDB document of session and received a session hash
// Writing document instance of the session from ArangoDB to the property of the implementing object
$$this->__document($$document);
} else if (static::VERIFICATION === verification::hash_else_address && $$document = $$this->address($$_SERVER['REMOTE_ADDR'], errors: $$errors)) {
// Found the instance of the ArangoDB document of session and received a session hash
// Writing document instance of the session from ArangoDB to the property of the implementing object
$$this->__document($$document);
} else {
// Not found the instance of the ArangoDB document of session
// Initializing a new session and write they into ArangoDB
$$_id = document::write(
static::COLLECTION,
[
'active' => true,
'expires' => $$expires ?? time() + 604800,
'address' => $$_SERVER['REMOTE_ADDR'],
'x-forwarded-for' => $$_SERVER['HTTP_X_FORWARDED_FOR'] ?? null,
'referer' => $$_SERVER['HTTP_REFERER'] ?? null,
'useragent' => $$_SERVER['HTTP_USER_AGENT'] ?? null
]
);
if ($$session = collection::execute(
<<<'AQL'
FOR d IN @@collection
FILTER d._id == @_id && d.expires > @time && d.active == true
RETURN d
AQL,
[
'@collection' => static::COLLECTION,
'_id' => $$_id,
'time' => time()
],
errors: $$errors
)) {
// Found the instance of just created new session
// Generating a hash and write into the instance of the ArangoDB document of session property
$$session->hash = sodium_bin2hex(sodium_crypto_generichash($$_id));
if (document::update($$session, errors: $$errors)) {
// Writed to ArangoDB
// Writing instance of the session document from ArangoDB to the property of the implementing object
$$this->__document($$session);
} else throw new exception('Failed to write the session data');
} else throw new exception('Failed to create or find just created session');
}
} else throw new exception('Failed to initialize ' . static::TYPE . ' collection: ' . static::COLLECTION);
} catch (exception $$e) {
// Writing to the registry of errors
$$errors[] = [
'text' => $$e->getMessage(),
'file' => $$e->getFile(),
'line' => $$e->getLine(),
'stack' => $$e->getTrace()
];
}
}
/**
* Search by hash
*
* Search for the session in ArangoDB by hash
*
* @param string $$hash Hash of the session in ArangoDB
* @param array &$$errors Registry of errors
*
* @return _document|null instance of document of the session in ArangoDB
*/
public static function hash(string $$hash, array &$$errors = []): ?_document
{
try {
if (collection::initialize(static::COLLECTION, static::TYPE, errors: $$errors)) {
// Collection initialized
// Search the session data in ArangoDB
return collection::execute(
<<<'AQL'
FOR d IN @@collection
FILTER d.hash == @hash && d.expires > @time && d.active == true
RETURN d
AQL,
[
'@collection' => static::COLLECTION,
'hash' => $$hash,
'time' => time()
],
errors: $$errors
);
} else throw new exception('Failed to initialize ' . static::TYPE . ' collection: ' . static::COLLECTION);
} catch (exception $$e) {
// Writing to the registry of errors
$$errors[] = [
'text' => $$e->getMessage(),
'file' => $$e->getFile(),
'line' => $$e->getLine(),
'stack' => $$e->getTrace()
];
}
// Exit (fail)
return null;
}
/**
* Search by IP-address
*
* Search for the session in ArangoDB by IP-address
*
* @param string $$address IP-address writed to the session in ArangoDB
* @param array &$$errors Registry of errors
*
* @return _document|null instance of document of the session in ArangoDB
*/
public static function address(string $$address, array &$$errors = []): ?_document
{
try {
if (collection::initialize(static::COLLECTION, static::TYPE, errors: $$errors)) {
// Collection initialized
// Search the session data in ArangoDB
return collection::execute(
<<<'AQL'
FOR d IN @@collection
FILTER d.address == @address && d.expires > @time && d.active == true
SORT d.updated DESC
LIMIT 1
RETURN d
AQL,
[
'@collection' => static::COLLECTION,
'address' => $$address,
'time' => time()
],
errors: $$errors
);
} else throw new exception('Failed to initialize ' . static::TYPE . ' collection: ' . static::COLLECTION);
} catch (exception $$e) {
// Writing to the registry of errors
$$errors[] = [
'text' => $$e->getMessage(),
'file' => $$e->getFile(),
'line' => $$e->getLine(),
'stack' => $$e->getTrace()
];
}
// Exit (fail)
return null;
}}

View File

@@ -0,0 +1,106 @@
<?php
declare(strict_types=1);
namespace ${REPO_OWNER}\${REPO_NAME}\models;
// Files of the project
use ${REPO_OWNER}\${REPO_NAME}\models\core,
${REPO_OWNER}\${REPO_NAME}\models\tariff,
${REPO_OWNER}\${REPO_NAME}\models\enumerations\tariff as tariff_type,
${REPO_OWNER}\${REPO_NAME}\models\enumerations\acquiring as acquiring;
// Baza database
use mirzaev\baza\database,
mirzaev\baza\column,
mirzaev\baza\record,
mirzaev\baza\enumerations\encoding,
mirzaev\baza\enumerations\type;
// Active Record pattern
use mirzaev\record\interfaces\record as record_interface,
mirzaev\record\traits\record as record_trait;
// Svoboda time
use svoboda\time\statement as svoboda;
// Built-in libraries
use Exception as exception,
RuntimeException as exception_runtime;
/**
* Settings
*
* @package ${REPO_OWNER}\${REPO_NAME}\models
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
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;
}
}

View File

@@ -0,0 +1,393 @@
<?php
declare(strict_types=1);
namespace ${REPO_OWNER}\${REPO_NAME}\models\telegram;
// Files of the project
use ${REPO_OWNER}\${REPO_NAME}\models\core,
${REPO_OWNER}\${REPO_NAME}\models\account,
${REPO_OWNER}\${REPO_NAME}\models\settings,
${REPO_OWNER}\${REPO_NAME}\models\telegram\settings as telegram_settings,
${REPO_OWNER}\${REPO_NAME}\models\telegram\processes\language\select as process_language_select;
// Library for languages support
use mirzaev\languages\language;
// The library for escaping all markdown symbols
use function mirzaev\unmarkdown;
// Framework for Telegram
use Zanzara\Context as context,
Zanzara\Telegram\Type\Message as message,
Zanzara\Telegram\Type\Input\InputFile as file_input;
/**
* Telegram commands
*
* @package ${REPO_OWNER}\${REPO_NAME}\models\telegram
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
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(
<<<TXT
$$title
$$howto
TXT,
[
'reply_markup' => [
'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(
<<<TXT
$$title
$$authorizations
TXT,
[
'reply_markup' => [
'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();
});
}
}
}

View File

@@ -0,0 +1,469 @@
<?php
declare(strict_types=1);
namespace ${REPO_OWNER}\${REPO_NAME}\models\telegram;
// Files of the project
use ${REPO_OWNER}\${REPO_NAME}\models\core,
${REPO_OWNER}\${REPO_NAME}\models\account,
${REPO_OWNER}\${REPO_NAME}\models\authorizations;
// The library for languages support
use mirzaev\languages\language;
// The library for escaping all markdown symbols
use function mirzaev\unmarkdown;
// Framework for Telegram
use Zanzara\Context as context,
Zanzara\Telegram\Type\Message as message,
Zanzara\Middleware\MiddlewareNode as node;
// Built-in libraries
use Error as error;
/**
* Telegram middlewares
*
* @package ${REPO_OWNER}\${REPO_NAME}\models\telegram
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
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();
});
}
}
}

View File

@@ -0,0 +1,152 @@
<?php
declare(strict_types=1);
namespace ${REPO_OWNER}\${REPO_NAME}\models\telegram\processes\language;
// Files of the project
use ${REPO_OWNER}\${REPO_NAME}\models\core;
// Library for languages support
use mirzaev\languages\language;
// Baza database
use mirzaev\baza\record;
// Framework for Telegram
use Zanzara\Context as context,
Zanzara\Telegram\Type\Message as message;
/**
* Telegram language select
*
* @package ${REPO_OWNER}\${REPO_NAME}\models\telegram\processes\language
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
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();
});
}
}
}

View File

@@ -1,84 +0,0 @@
<?php
declare(strict_types=1);
namespace ${REPO_OWNER}\${REPO_NAME}\models\traits;
// Files of the project
use ${REPO_OWNER}\${REPO_NAME}\models\traits\document as document_trait,
${REPO_OWNER}\${REPO_NAME}\models\interfaces\document as document_interface,
${REPO_OWNER}\${REPO_NAME}\models\interfaces\collection as collection_interface,
${REPO_OWNER}\${REPO_NAME}\models\enumerations\language;
// Library for ArangoDB
use ArangoDBClient\Document as _document;
// Framework for ArangoDB
use mirzaev\arangodb\collection,
mirzaev\arangodb\document;
// Built-in libraries
use exception;
/**
* Buffer
*
* Storage of data in the document from ArangoDB
*
* @uses document
* @uses document_interface
* @uses collection_interface
*
* @param static COLLECTION Name of the collection in ArangoDB
* @param static TYPE Type of the collection in ArangoDB
*
* @package ${REPO_OWNER}\${REPO_NAME}\models\traits
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author ${REPO_OWNER} <mail@domain.zone>
*/
trait buffer
{
/**
* Write to buffer of the document
*
* @param array $$data Data for writing (merge)
* @param array &$$errors Registry of errors
*
* @return bool Is data has written into the document from ArangoDB?
*/
public function write(array $$data, array &$$errors = []): bool
{
try {
if (collection::initialize(static::COLLECTION, static::TYPE, errors: $$errors)) {
// Initialized the collection
// Is the instance of the document from ArangoDB are initialized?
if (!isset($$this->document)) throw new exception('The instance of the sessoin document from ArangoDB is not initialized');
// Writing data into buffer of the instance of the document from ArangoDB
$$this->document->buffer = array_replace_recursive($$this->document->buffer ?? [], $$data);
// Is the buffer of the instance of the document from ArangoDB exceed 10 megabytes?
if (mb_strlen(json_encode($$this->document->buffer)) > 10485760) throw new exception('The buffer size exceeds 10 megabytes');
// Serializing parameters
if ($$this->document->language instanceof language) $$this->document->language = $$this->document->language->name;
// Writing to ArangoDB and exit (success)
return document::update($$this->document, errors: $$errors);
} else throw new exception('Failed to initialize ' . static::TYPE . ' collection: ' . static::COLLECTION);
} catch (exception $$e) {
// Writing to the registry of errors
$$errors[] = [
'text' => $$e->getMessage(),
'file' => $$e->getFile(),
'line' => $$e->getLine(),
'stack' => $$e->getTrace()
];
}
// Exit (fail)
return false;
}
}

View File

@@ -1,206 +0,0 @@
<?php
declare(strict_types=1);
namespace ${REPO_OWNER}\${REPO_NAME}\models\traits;
// Files of the project
use ${REPO_OWNER}\${REPO_NAME}\models\interfaces\document as document_interface,
${REPO_OWNER}\${REPO_NAME}\models\interfaces\collection as collection_interface,
${REPO_OWNER}\${REPO_NAME}\models\connect;
// Library для ArangoDB
use ArangoDBClient\Document as _document;
// Framework for ArangoDB
use mirzaev\arangodb\connection as arangodb,
mirzaev\arangodb\document as framework_document,
mirzaev\arangodb\collection;
// Built-in libraries
use exception;
/**
* Trait for implementing a document instance from ArangoDB
*
* @uses document_interface
*
* @var protected readonly _document|null $$document An instance of the ArangoDB document
*
* @package ${REPO_OWNER}\${REPO_NAME}\models\traits
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author ${REPO_OWNER} <mail@domain.zone>
*/
trait document
{
/**
* Document
*
* @var _document $$document An instance of the document from ArangoDB
*/
protected readonly _document $$document;
/**
* Constructor
*
* @param bool $$initialize Initialize a model?
* @param ?arangodb $$arangodb Instance of a session of ArangoDB
* @param _document|null|false $$document An instance of the ArangoDB document
*
* @return void
*/
public function __construct(
bool $$initialize = true,
?arangodb $$arangodb = null,
_document|null|false $$document = false
) {
// For the extends system
parent::__construct($$initialize, $$arangodb);
// Writing to the property
if ($$document instanceof _document) $$this->__document($$document);
else if ($$document === null) throw new exception('Failed to initialize an instance of the document from ArangoDB');
}
/**
* Write or read document
*
* @param _document|null $$document Instance of document from ArangoDB
*
* @return _document|null Instance of document from ArangoDB
*/
public function __document(?_document $$document = null): ?_document
{
// Writing a property storing a document instance to ArangoDB
if ($$document) $$this->document ??= $$document;
// Read a property storing a document instance to ArangoDB and exit (success)
return $$this->document ?? null;
}
/**
* Connect
*
* @param collecton_interface $$document Document
* @param array &$$errors Registry of errors
*
* @return string|null The identifier of the created edge of the "connect" collection, if created
*/
public function connect(collection_interface $$document, array &$$errors = []): ?string
{
try {
if (collection::initialize(static::COLLECTION, static::TYPE, errors: $$errors)) {
if (collection::initialize(connect::COLLECTION, connect::TYPE, errors: $$errors)) {
if (collection::initialize($$document::COLLECTION, $$document::TYPE, errors: $$errors)) {
// Initialized collections
if ($$this->document instanceof _document) {
// Initialized instance of the document from ArangoDB
// Writing document and exit (success)
return framework_document::write(
connect::COLLECTION,
[
'_from' => $$document->getId(),
'_to' => $$this->document->getId()
],
errors: $$errors
);
} else throw new exception('The instance of the document from ArangoDB is not initialized');
} else throw new exception('Failed to initialize ' . $$document::TYPE . ' collection: ' . $$document::COLLECTION);
} else throw new exception('Failed to initialize ' . connect::TYPE . ' collection: ' . connect::COLLECTION);
} else throw new exception('Failed to initialize ' . static::TYPE . ' collection: ' . static::COLLECTION);
} catch (exception $$e) {
// Writing to the registry of errors
$$errors[] = [
'text' => $$e->getMessage(),
'file' => $$e->getFile(),
'line' => $$e->getLine(),
'stack' => $$e->getTrace()
];
}
// Exit (fail)
return null;
}
/**
* Write
*
* Write a property into an instance of the ArangoDB document
*
* @param string $$name Name of the property
* @param mixed $$value Content of the property
*
* @return void
*/
public function __set(string $$name, mixed $$value = null): void
{
// Writing to the property into an instance of the ArangoDB document and exit (success)
$$this->document->{$$name} = $$value;
}
/**
* Read
*
* Read a property from an instance of the ArangoDB docuemnt
*
* @param string $$name Name of the property
*
* @return mixed Content of the property
*/
public function __get(string $$name): mixed
{
// Read a property from an instance of the ArangoDB document and exit (success)
return match ($$name) {
default => $$this->document->{$$name}
};
}
/**
* Delete
*
* Deinitialize the property in an instance of the ArangoDB document
*
* @param string $$name Name of the property
*
* @return void
*/
public function __unset(string $$name): void
{
// Delete the property in an instance of the ArangoDB document and exit (success)
unset($$this->document->{$$name});
}
/**
* Check of initialization
*
* Check of initialization of the property into an instance of the ArangoDB document
*
* @param string $$name Name of the property
*
* @return bool The property is initialized?
*/
public function __isset(string $$name): bool
{
// Check of initializatio nof the property and exit (success)
return isset($$this->document->{$$name});
}
/**
* Execute a method
*
* Execute a method from an instance of the ArangoDB document
*
* @param string $$name Name of the method
* @param array $$arguments Arguments for the method
*
* @return mixed Result of execution of the method
*/
public function __call(string $$name, array $$arguments = []): mixed
{
// Execute the method and exit (success)
return method_exists($$this->document, $$name) ? $$this->document->{$$name}($$arguments) ?? null : null;
}
}

View File

@@ -1,66 +0,0 @@
<?php
declare(strict_types=1);
namespace ${REPO_OWNER}\${REPO_NAME}\models\traits;
// Built-in libraries
use exception;
/**
* Files
*
* Trait with files handlers
*
* @method static void delete(string $$directory, array &$$errors)
*
* @package ${REPO_OWNER}\${REPO_NAME}\models\traits
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author ${REPO_OWNER} <mail@domain.zone>
*/
trait files
{
/**
* Delete
*
* Delete files recursively
*
* @param string $$directory Directory
* @param array &$$errors Registry of errors
*
* @return void
*/
private static function delete(string $$directory, array &$$errors = []): void
{
try {
if (file_exists($$directory)) {
// Directory exists
// Deleting descendant files and directories (enter to the recursion)
foreach (scandir($$directory) as $$file) {
if ($$file === '.' || $$file === '..') continue;
else if (is_dir("$$directory/$$file")) static::delete("$$directory/$$file", $$errors);
else unlink("$$directory/$$file");
}
// Deleting the directory
rmdir($$directory);
// Exit (success)
return;
} else throw new exception('Directory does not exist');
} catch (exception $$e) {
// Writing to the registry of errors
$$errors[] = [
'text' => $$e->getMessage(),
'file' => $$e->getFile(),
'line' => $$e->getLine(),
'stack' => $$e->getTrace()
];
}
// Exit (fail)
return;
}
}

View File

@@ -1,59 +0,0 @@
<?php
declare(strict_types=1);
namespace ${REPO_OWNER}\${REPO_NAME}\models\traits;
// Files of the project
use ${REPO_OWNER}\${REPO_NAME}\models\traits\document as document_trait,
${REPO_OWNER}\${REPO_NAME}\models\interfaces\document as document_interface;
// Built-in libraries
use exception;
/**
* Status (DUMB SHIT)
*
* Trait for initialization of a status
*
* @uses document_trait
* @uses document_interface
*
* @method bool|null status(array &$$errors) Check document by its status
*
* @package ${REPO_OWNER}\${REPO_NAME}\models\traits
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author ${REPO_OWNER} <mail@domain.zone>
*/
trait status
{
/**
* Status
*
* Check document by its status
*
* @param array &$$errors Registry of errors
*
* @return ?bool Status, if found
*/
public function status(array &$$errors = []): ?bool
{
try {
// Read from ArangoDB and exit (success)
return $$this->document->active ?? false;
} catch (exception $$e) {
// Writing to the registry of errors
$$errors[] = [
'text' => $$e->getMessage(),
'file' => $$e->getFile(),
'line' => $$e->getLine(),
'stack' => $$e->getTrace()
];
}
// Exit (fail)
return null;
}
}

View File

@@ -0,0 +1,34 @@
@font-face {
font-family: 'DejaVu';
src: url("/fonts/dejavu/DejaVuLGCSans-ExtraLight.ttf");
font-weight: 200;
font-style: normal;
}
@font-face {
font-family: 'DejaVu';
src: url("/fonts/dejavu/DejaVuLGCSans.ttf");
font-weight: 400;
font-style: normal;
}
@font-face {
font-family: 'DejaVu';
src: url("/fonts/dejavu/DejaVuLGCSans-Oblique.ttf");
font-weight: 400;
font-style: italic;
}
@font-face {
font-family: 'DejaVu';
src: url("/fonts/dejavu/DejaVuLGCSans-Bold.ttf");
font-weight: 500;
font-style: normal;
}
@font-face {
font-family: 'DejaVu';
src: url("/fonts/dejavu/DejaVuLGCSans-BoldOblique.ttf");
font-weight: 500;
font-style: italic;
}

View File

@@ -0,0 +1,139 @@
@font-face {
font-family: 'Fira';
src: url('/fonts/fira/FiraSans-Hair.woff2') format('woff2'), url('/fonts/fira/FiraSans-Hair.woff') format('woff');
font-weight: 100;
font-style: normal;
}
@font-face {
font-family: 'Fira';
src: url('/fonts/fira/FiraSans-HairItalic.woff2') format('woff2'), url('/fonts/fira/FiraSans-HairItalic.woff') format('woff');
font-weight: 100;
font-style: italic;
}
@font-face {
font-family: 'Fira';
src: url('/fonts/fira/FiraSans-UltraLight.woff2') format('woff2'), url('/fonts/fira/FiraSans-UltraLight.woff') format('woff');
font-weight: 200;
font-style: normal;
}
@font-face {
font-family: 'Fira';
src: url('/fonts/fira/FiraSans-UltraLightItalic.woff2') format('woff2'), url('/fonts/fira/FiraSans-UltraLightItalic.woff') format('woff');
font-weight: 200;
font-style: italic;
}
@font-face {
font-family: 'Fira';
src: url('/fonts/fira/FiraSans-Light.woff2') format('woff2'), url('/fonts/fira/FiraSans-Light.woff') format('woff');
font-weight: 300;
font-style: normal;
}
@font-face {
font-family: 'Fira';
src: url('/fonts/fira/FiraSans-LightItalic.woff2') format('woff2'), url('/fonts/fira/FiraSans-LightItalic.woff') format('woff');
font-weight: 300;
font-style: italic;
}
@font-face {
font-family: 'Fira';
src: url('/fonts/fira/FiraSans-Regular.woff2') format('woff2'), url('/fonts/fira/FiraSans-Regular.woff') format('woff');
font-weight: 400;
font-style: normal;
}
@font-face {
font-family: 'Fira';
src: url('/fonts/fira/FiraSans-Italic.woff2') format('woff2'), url('/fonts/fira/FiraSans-Italic.woff') format('woff');
font-weight: 400;
font-style: italic;
}
@font-face {
font-family: 'Fira';
src: url('/fonts/fira/FiraMono-Medium.woff2') format('woff2'), url('/fonts/fira/FiraMono-Medium.woff') format('woff');
font-weight: 500;
font-style: normal;
}
@font-face {
font-family: 'Fira';
src: url('/fonts/fira/FiraSans-MediumItalic.woff2') format('woff2'), url('/fonts/fira/FiraSans-MediumItalic.woff') format('woff');
font-weight: 500;
font-style: italic;
}
@font-face {
font-family: 'Fira';
src: url('/fonts/fira/FiraSans-SemiBold.woff2') format('woff2'), url('/fonts/fira/FiraSans-SemiBold.woff') format('woff');
font-weight: 600;
font-style: normal;
}
@font-face {
font-family: 'Fira';
src: url('/fonts/fira/FiraSans-SemiBoldItalic.woff2') format('woff2'), url('/fonts/fira/FiraSans-SemiBoldItalic.woff') format('woff');
font-weight: 600;
font-style: italic;
}
@font-face {
font-family: 'Fira';
src: url('/fonts/fira/FiraSans-Bold.woff2') format('woff2'), url('/fonts/fira/FiraSans-Bold.woff') format('woff');
font-weight: 700;
font-style: normal;
}
@font-face {
font-family: 'Fira';
src: url('/fonts/fira/FiraSans-BoldItalic.woff2') format('woff2'), url('/fonts/fira/FiraSans-BoldItalic.woff') format('woff');
font-weight: 700;
font-style: italic;
}
@font-face {
font-family: 'Fira';
src: url('/fonts/fira/FiraSans-ExtraBold.woff2') format('woff2'), url('/fonts/fira/FiraSans-ExtraBold.woff') format('woff');
font-weight: 800;
font-style: normal;
}
@font-face {
font-family: 'Fira';
src: url('/fonts/fira/FiraSans-ExtraBoldItalic.woff2') format('woff2'), url('/fonts/fira/FiraSans-ExtraBoldItalic.woff') format('woff');
font-weight: 800;
font-style: italic;
}
@font-face {
font-family: 'Fira';
src: url('/fonts/fira/FiraSans-Heavy.woff2') format('woff2'), url('/fonts/fira/FiraSans-Heavy.woff') format('woff');
font-weight: 900;
font-style: normal;
}
@font-face {
font-family: 'Fira';
src: url('/fonts/fira/FiraSans-HeavyItalic.woff2') format('woff2'), url('/fonts/fira/FiraSans-HeavyItalic.woff') format('woff');
font-weight: 900;
font-style: italic;
}
@font-face {
font-family: 'Fira' Mono;
src: url('/fonts/fira/FiraMono-Regular.woff2') format('woff2'), url('/fonts/fira/FiraMono-Regular.woff') format('woff');
font-weight: 400;
font-style: normal;
}
@font-face {
font-family: 'Fira' Mono;
src: url('/fonts/fira/FiraMono-Bold.woff2') format('woff2'), url('/fonts/fira/FiraMono-Bold.woff') format('woff');
font-weight: 600;
font-style: normal;
}

View File

@@ -0,0 +1,31 @@
@font-face {
font-family: 'Hack';
src: url('/fonts/hack/hack-regular.woff2?sha=3114f1256') format('woff2'), url('/fonts/hack/hack-regular.woff?sha=3114f1256') format('woff');
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Hack';
src: url('/fonts/hack/hack-bold.woff2?sha=3114f1256') format('woff2'), url('/fonts/hack/hack-bold.woff?sha=3114f1256') format('woff');
font-weight: 700;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Hack';
src: url('/fonts/hack/hack-italic.woff2?sha=3114f1256') format('woff2'), url('/fonts/hack/hack-italic.woff?sha=3114f1256') format('woff');
font-weight: 400;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'Hack';
src: url('/fonts/hack/hack-bolditalic.woff2?sha=3114f1256') format('woff2'), url('/fonts/hack/hack-bolditalic.woff?sha=3114f1256') format('woff');
font-weight: 700;
font-style: italic;
font-display: swap;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More