Transit into git.mirzaev.sexya
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
vendor
 | 
			
		||||
							
								
								
									
										49
									
								
								composer.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								composer.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "mirzaev/vk-arangodb",
 | 
			
		||||
    "description": "Module for mirzaev/vk framework for storage data in ArangoDB",
 | 
			
		||||
    "keywords": [
 | 
			
		||||
        "ArangoDB",
 | 
			
		||||
        "vk",
 | 
			
		||||
        "module"
 | 
			
		||||
    ],
 | 
			
		||||
    "type": "vk-module",
 | 
			
		||||
    "license": "WTFPL",
 | 
			
		||||
    "homepage": "https://git.mirzaev.sexy/mirzaev/vk-arangodb",
 | 
			
		||||
    "authors": [
 | 
			
		||||
        {
 | 
			
		||||
            "name": "Arsen Mirzaev Tatyano-Muradovich",
 | 
			
		||||
            "email": "arsen@mirzaev.sexy",
 | 
			
		||||
            "homepage": "https://mirzaev.sexy",
 | 
			
		||||
            "role": "Programmer"
 | 
			
		||||
        }
 | 
			
		||||
    ],
 | 
			
		||||
    "support": {
 | 
			
		||||
        "email": "arsen@mirzaev.sexy",
 | 
			
		||||
        "wiki": "https://git.mirzaev.sexy/mirzaev/vk-arangodb/wiki",
 | 
			
		||||
        "issues": "https://git.mirzaev.sexy/mirzaev/vk-arangodb/issues"
 | 
			
		||||
    },
 | 
			
		||||
    "funding": [
 | 
			
		||||
        {
 | 
			
		||||
            "type": "funding",
 | 
			
		||||
            "url": "https://fund.mirzaev.sexy"
 | 
			
		||||
        }
 | 
			
		||||
    ],
 | 
			
		||||
    "require": {
 | 
			
		||||
        "php": "^8.1",
 | 
			
		||||
        "mirzaev/vk": "~4.0.1",
 | 
			
		||||
        "mirzaev/accounts": "1.2.x-dev",
 | 
			
		||||
        "mirzaev/arangodb": "^1.0.0",
 | 
			
		||||
        "triagens/arangodb": "~3.9.x-dev",
 | 
			
		||||
        "guzzlehttp/guzzle": "~7.5"
 | 
			
		||||
    },
 | 
			
		||||
    "autoload": {
 | 
			
		||||
        "psr-4": {
 | 
			
		||||
            "mirzaev\\vk\\arangodb\\": "mirzaev/vk/arangodb/system"
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "autoload-dev": {
 | 
			
		||||
        "psr-4": {
 | 
			
		||||
            "mirzaev\\vk\\arangodb\\tests\\": "mirzaev/vk/arangodb/tests"
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1013
									
								
								composer.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										1013
									
								
								composer.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1
									
								
								mirzaev/vk/arangodb/system/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								mirzaev/vk/arangodb/system/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
storage/*
 | 
			
		||||
							
								
								
									
										167
									
								
								mirzaev/vk/arangodb/system/journal.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										167
									
								
								mirzaev/vk/arangodb/system/journal.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,167 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace mirzaev\vk\arangodb;
 | 
			
		||||
 | 
			
		||||
// Файлы проекта
 | 
			
		||||
use mirzaev\arangodb\collection;
 | 
			
		||||
 | 
			
		||||
// Фреймворк ArangoDB
 | 
			
		||||
use mirzaev\arangodb\document;
 | 
			
		||||
use mirzaev\vk\arangodb\longpoll;
 | 
			
		||||
 | 
			
		||||
// Библиотека для работы с API-сервера ArangoDB
 | 
			
		||||
use ArangoDBClient\Connection as _connection;
 | 
			
		||||
use ArangoDBClient\Statement as _statement;
 | 
			
		||||
use ArangoDBClient\Document as _document;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Журнал
 | 
			
		||||
 *
 | 
			
		||||
 * Используется для хранения информации об изменениях других коллекций
 | 
			
		||||
 * Связывается с отслеживаемой коллекцией ребром
 | 
			
		||||
 *
 | 
			
		||||
 * @param _connection $session Сессия соединения с базой данных
 | 
			
		||||
 * @param _document $document Инстанция (static::COLLECTION_JOURNAL)
 | 
			
		||||
 */
 | 
			
		||||
class journal
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Настройки архитектуры базы данных
 | 
			
		||||
     */
 | 
			
		||||
    const COLLECTION_JOURNAL = 'journal';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Конструктор
 | 
			
		||||
     *
 | 
			
		||||
     * @param _connection $session Сессия соединения с базой данных
 | 
			
		||||
     * @param _document $document Инстанция (static::COLLECTION_JOURNAL)
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        public _connection $session,
 | 
			
		||||
        public _document $document
 | 
			
		||||
    ) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Инициализация
 | 
			
		||||
     *
 | 
			
		||||
     * @param _connection $session Сессия соединения с базой данных
 | 
			
		||||
     * @param string $document Идентификатор документа
 | 
			
		||||
     * @param bool $create Создавать коллекции при их отсутствии
 | 
			
		||||
     *
 | 
			
		||||
     * @return static|null Объект с инстанцией журнала
 | 
			
		||||
     */
 | 
			
		||||
    public static function init(_connection $session, string $document, bool $create = true): ?static
 | 
			
		||||
    {
 | 
			
		||||
        if ($create) {
 | 
			
		||||
            // Запрошено создание коллекций в случае их отсутствия
 | 
			
		||||
 | 
			
		||||
            // Инициализация коллекций
 | 
			
		||||
            collection::init($session, static::COLLECTION_JOURNAL);
 | 
			
		||||
            collection::init($session, longpoll::COLLECTION_ACCESSED, true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (empty($journal = static::search($session, $document))) {
 | 
			
		||||
            // Не найден журнал (подразумевается, что его не существует)
 | 
			
		||||
 | 
			
		||||
            if (empty($journal = document::write($session, static::COLLECTION_JOURNAL, [
 | 
			
		||||
                'events' => [],
 | 
			
		||||
                'expires' => strtotime('first day of next month 00:00')
 | 
			
		||||
            ]))) {
 | 
			
		||||
                // Не удалось создать документ
 | 
			
		||||
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (empty(document::write($session, longpoll::COLLECTION_ACCESSED, ['_from' => $document, '_to' => $journal]))) {
 | 
			
		||||
                // Не удалось создать ребро: {$document} -> ЖУРНАЛ
 | 
			
		||||
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Инициализация инстанции журнала и возврат
 | 
			
		||||
        return new static($session, $journal);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Поиск журнала
 | 
			
		||||
     *
 | 
			
		||||
     * Находит актуальный документ журнала
 | 
			
		||||
     *
 | 
			
		||||
     * @param _connection $session Сессия соединения с базой данных
 | 
			
		||||
     * @param string $document Идентификатор документа
 | 
			
		||||
     *
 | 
			
		||||
     * @return _document|null Инстанция (static::COLLECTION_JOURNAL) или его идентификатор
 | 
			
		||||
     */
 | 
			
		||||
    public static function search(_connection $session, string $document): _document|null
 | 
			
		||||
    {
 | 
			
		||||
        // Инициализация ярлыка названия коллекции
 | 
			
		||||
        $collection = static::COLLECTION_JOURNAL;
 | 
			
		||||
 | 
			
		||||
        // Инициализация ярлыка названия ребра
 | 
			
		||||
        $edge = longpoll::COLLECTION_ACCESSED;
 | 
			
		||||
 | 
			
		||||
        // Инициализация даты для разделения по журналам
 | 
			
		||||
        $time = time();
 | 
			
		||||
 | 
			
		||||
        // Поиск журнала
 | 
			
		||||
        $journal = (new _statement(
 | 
			
		||||
            $session,
 | 
			
		||||
            [
 | 
			
		||||
                'query' => <<<AQL
 | 
			
		||||
                    FOR a IN $collection
 | 
			
		||||
                    LET b = (
 | 
			
		||||
                        FOR vertex, edge IN INBOUND a $edge
 | 
			
		||||
                        FILTER vertex._id == $document
 | 
			
		||||
                        LIMIT 1
 | 
			
		||||
                        RETURN vertex
 | 
			
		||||
                    )
 | 
			
		||||
                    FILTER a.expires >= $time
 | 
			
		||||
                    LIMIT 1
 | 
			
		||||
                    RETURN a
 | 
			
		||||
                AQL,
 | 
			
		||||
                "batchSize" => 1000,
 | 
			
		||||
                "sanitize"  => true
 | 
			
		||||
            ]
 | 
			
		||||
        ))->execute();
 | 
			
		||||
 | 
			
		||||
        // Инициализация буфера вывода
 | 
			
		||||
        $buffer = [];
 | 
			
		||||
 | 
			
		||||
        foreach ($journal as $key => $value) {
 | 
			
		||||
            // Перебор параметров для универсализации вывода
 | 
			
		||||
 | 
			
		||||
            // Запись в буфер
 | 
			
		||||
            $buffer[$key] = $value;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Возврат (подразумевается, что в буфере только 1 значение - инстанция (static::COLLECTION_JOURNAL))
 | 
			
		||||
        return $buffer[0] ?? null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Запись в журнал
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $event Событие
 | 
			
		||||
     * @param array $data Дополнительная информация
 | 
			
		||||
     *
 | 
			
		||||
     * @return bool Статус обработки
 | 
			
		||||
     */
 | 
			
		||||
    public function write(string $event, array $data = []): bool
 | 
			
		||||
    {
 | 
			
		||||
        // Запись в инстанцию документа
 | 
			
		||||
        $this->document->events += [
 | 
			
		||||
            [
 | 
			
		||||
                'date' => time(),
 | 
			
		||||
                'event' => $event,
 | 
			
		||||
                'data' => $data
 | 
			
		||||
            ]
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        // Запись в базу данных
 | 
			
		||||
        return document::update($this->session, $this->document);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										430
									
								
								mirzaev/vk/arangodb/system/longpoll.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										430
									
								
								mirzaev/vk/arangodb/system/longpoll.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,430 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace mirzaev\vk\arangodb;
 | 
			
		||||
 | 
			
		||||
// Файлы проекта
 | 
			
		||||
use mirzaev\arangodb\connection;
 | 
			
		||||
use mirzaev\arangodb\collection;
 | 
			
		||||
use mirzaev\arangodb\terminal;
 | 
			
		||||
use mirzaev\arangodb\document;
 | 
			
		||||
use mirzaev\vk\arangodb\traits\HTTP\headers\content\disposition;
 | 
			
		||||
 | 
			
		||||
// Библиотека для работы с API-сервера ArangoDB
 | 
			
		||||
use ArangoDBClient\Document as _document;
 | 
			
		||||
 | 
			
		||||
// Библиотека браузера
 | 
			
		||||
use GuzzleHttp\Client as Guzzle;
 | 
			
		||||
 | 
			
		||||
// Встроенные библиотеки
 | 
			
		||||
use Exception;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * LongPoll API ВКонтакте
 | 
			
		||||
 *
 | 
			
		||||
 * @todo
 | 
			
		||||
 * 1. Проработать создание индексов в базе данных
 | 
			
		||||
 */
 | 
			
		||||
class longpoll
 | 
			
		||||
{
 | 
			
		||||
    use disposition {
 | 
			
		||||
        disposition::filename as disposition_filename;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const COLLECTION_USERS = 'user';
 | 
			
		||||
    const COLLECTION_GROUPS = 'group';
 | 
			
		||||
    const COLLECTION_CHATS = 'chat';
 | 
			
		||||
    const COLLECTION_MESSAGES = 'message';
 | 
			
		||||
    const COLLECTION_ACCESSED = 'accessed';
 | 
			
		||||
 | 
			
		||||
    public static string $path_storage = __DIR__ . '/storage';
 | 
			
		||||
    public static string $path_storage_accounts = '/accounts';
 | 
			
		||||
    public static string $path_storage_accounts_images = '/images';
 | 
			
		||||
    public static string $path_storage_accounts_videos = '/videos';
 | 
			
		||||
    public static string $path_storage_accounts_audios = '/audios';
 | 
			
		||||
    public static string $path_storage_vk = '/vk';
 | 
			
		||||
    public static string $path_storage_vk_stickers = '/stickers';
 | 
			
		||||
 | 
			
		||||
    protected bool $journal = true;
 | 
			
		||||
 | 
			
		||||
    public function __construct(protected connection $connection)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Сохранить событие в базу данных
 | 
			
		||||
     *
 | 
			
		||||
     * @param array $updates События
 | 
			
		||||
     *
 | 
			
		||||
     * @return bool Статус сохранения
 | 
			
		||||
     */
 | 
			
		||||
    public function save(array $update): bool
 | 
			
		||||
    {
 | 
			
		||||
        try {
 | 
			
		||||
            // Динамический вызов метода-обработчика события
 | 
			
		||||
            if ($this->{$update['type']}($update['object'], $update['group_id'], $update['event_id'])) {
 | 
			
		||||
                // Удалось сохранить в базу данных
 | 
			
		||||
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
        } catch (Exception $e) {
 | 
			
		||||
            terminal::write($e->getMessage() . PHP_EOL . $e->getFile() . ':' . $e->getLine());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Событие: "message_new"
 | 
			
		||||
     *
 | 
			
		||||
     * Новое сообщение
 | 
			
		||||
     *
 | 
			
		||||
     * @param array $data Данные сообщения
 | 
			
		||||
     * @param int $group Идентификатор группы
 | 
			
		||||
     * @param string $event Идентификатор события
 | 
			
		||||
     *
 | 
			
		||||
     * @return bool
 | 
			
		||||
     */
 | 
			
		||||
    public function message_new(array $data, int $group, string $event): bool
 | 
			
		||||
    {
 | 
			
		||||
        if ($this->connection->create) {
 | 
			
		||||
            // Запрошено создание коллекций в случае их отсутствия
 | 
			
		||||
 | 
			
		||||
            collection::init($this->connection->session, static::COLLECTION_USERS);
 | 
			
		||||
            collection::init($this->connection->session, static::COLLECTION_MESSAGES);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($message = document::write($this->connection->session, static::COLLECTION_MESSAGES, static::messages($data, true))) {
 | 
			
		||||
            // Записано сообщение
 | 
			
		||||
 | 
			
		||||
            // Инициализация коллекции
 | 
			
		||||
            $collection = static::COLLECTION_MESSAGES;
 | 
			
		||||
 | 
			
		||||
            // Инициализация аккаунтов
 | 
			
		||||
            $from = ('mirzaev\\vk\\arangodb\\vk\\' . static::type($data['message']['from_id']))::init($this->connection->session, $data['message']['from_id']);
 | 
			
		||||
            $to = ('mirzaev\\vk\\arangodb\\vk\\' . static::type($data['message']['peer_id']))::init($this->connection->session, $data['message']['peer_id']);
 | 
			
		||||
 | 
			
		||||
            if ($from instanceof _document && $to instanceof _document) {
 | 
			
		||||
                // Инициализированы аккаунты
 | 
			
		||||
 | 
			
		||||
                if ($this->connection->create) {
 | 
			
		||||
                    // Запрошено создание коллекций в случае их отсутствия
 | 
			
		||||
 | 
			
		||||
                    collection::init($this->connection->session, static::COLLECTION_ACCESSED, edge: true);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (document::write($this->connection->session, static::COLLECTION_ACCESSED, [], ['_from' => $from->getId(), '_to' => $message])) {
 | 
			
		||||
                    // Записано ребро: АККАУНТ (отправитель) -> СООБЩЕНИЕ
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (document::write($this->connection->session, static::COLLECTION_ACCESSED, [], ['_from' => $message, '_to' => $to->getId()])) {
 | 
			
		||||
                    // Записно ребро: СООБЩЕНИЕ -> АККАУНТ (получатель)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Журналирование
 | 
			
		||||
            if ($this->journal && journal::init($this->connection->session, $message)->write('create', [
 | 
			
		||||
                'account' => $from,
 | 
			
		||||
                'changes' => [
 | 
			
		||||
                    'new' => collection::search($this->connection->session, <<<AQL
 | 
			
		||||
                        FOR a IN $collection
 | 
			
		||||
                        FILTER a._id == $message
 | 
			
		||||
                        LIMIT 1
 | 
			
		||||
                        RETURN a.data
 | 
			
		||||
                    AQL),
 | 
			
		||||
                    'old' => null
 | 
			
		||||
                ]
 | 
			
		||||
            ])) {
 | 
			
		||||
                // Записано ребро: СООБЩЕНИЕ -> СООБЩЕНИЕ
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        throw new Exception('Не удалось сохранить сообщение в базу даннных', 500);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Обработка сообщений
 | 
			
		||||
     *
 | 
			
		||||
     * @param array $messages Сообщения или сообщение
 | 
			
		||||
     * @param bool $download Активация скачивания файлов на сервер
 | 
			
		||||
     * @param bool $clean Активация очистки массива от пустых данных сообщения
 | 
			
		||||
     *
 | 
			
		||||
     * @return array Обработанные сообщения (зависит от входных данных)
 | 
			
		||||
     *
 | 
			
		||||
     * @todo
 | 
			
		||||
     * 1. Переделать $message['vk']['metadata']['action']['cover']
 | 
			
		||||
     * 2. Переделать $message['vk']['metadata']['payload']
 | 
			
		||||
     * 3. Узнать про Notify API и добавить message_tag
 | 
			
		||||
     * 4. В будущем удалить $message['message']['body']
 | 
			
		||||
     * 5. Переделать $message['vk']['metadata']['conversation']['members']['amount_test'] (или удалить)
 | 
			
		||||
     * 6. Разобраться с "Мультидиалогом" для старых версий API и существует ли он в новых
 | 
			
		||||
     */
 | 
			
		||||
    public static function messages(array $messages, bool $download = false, bool $clean = true): array
 | 
			
		||||
    {
 | 
			
		||||
        if (isset($messages['message'])) {
 | 
			
		||||
            // Передано одно сообщение
 | 
			
		||||
 | 
			
		||||
            // Инициализация
 | 
			
		||||
            $buffer[] = &$messages;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        foreach ($buffer ?? $messages as &$message) {
 | 
			
		||||
            // Перебор сообщений
 | 
			
		||||
 | 
			
		||||
            $message = [
 | 
			
		||||
                'data' => [
 | 
			
		||||
                    'id' => [
 | 
			
		||||
                        'global' => $message['message']['id'],
 | 
			
		||||
                        'local' => $message['message']['conversation_message_id']
 | 
			
		||||
                    ],
 | 
			
		||||
                    'text' => $message['message']['text'] ?? $message['message']['body'],
 | 
			
		||||
                    'forward' => static::messages($message['message']['fwd_messages']),
 | 
			
		||||
                    'reply' => static::messages($message['message']['fwd_messages']),
 | 
			
		||||
                    'attachments' => static::attachments($message['message']['attachments'], $download, $clean)
 | 
			
		||||
                ],
 | 
			
		||||
                'metadata' => [
 | 
			
		||||
                    'date' => [
 | 
			
		||||
                        'create' => $message['message']['date'] ?? null,
 | 
			
		||||
                        'update' => $message['message']['update_time'] ?? null
 | 
			
		||||
                    ],
 | 
			
		||||
                    'action' => [
 | 
			
		||||
                        'type' => $message['message']['action'] ?? null,
 | 
			
		||||
                        'target' => [
 | 
			
		||||
                            'id' => $message['message']['action']['member_id'] ?? null
 | 
			
		||||
                        ],
 | 
			
		||||
                        'text' => $message['message']['action']['text'] ?? null,
 | 
			
		||||
                        'email ' => $message['message']['action']['email'] ?? null,
 | 
			
		||||
                        'cover ' => $message['message']['action']['photo'] ?? null
 | 
			
		||||
                    ],
 | 
			
		||||
                    'hash' => $message['message']['random_id'] ?? null,
 | 
			
		||||
                    'type' => $message['message']['out'] ?? null,
 | 
			
		||||
                    'admin' => [
 | 
			
		||||
                        'id' => $message['message']['admin_author_id'] ?? null
 | 
			
		||||
                    ],
 | 
			
		||||
                    'pinned' => [
 | 
			
		||||
                        'date' => $message['message']['pinned_at'] ?? null
 | 
			
		||||
                    ],
 | 
			
		||||
                    'emoji' => $message['message']['emoji'] ?? null,
 | 
			
		||||
                    'readed' => $message['message']['read_state'] ?? null,
 | 
			
		||||
                    'listened' => $message['message']['was_listened'] ?? null,
 | 
			
		||||
                    'hidden' => $message['message']['is_hidden'] ?? null,
 | 
			
		||||
                    'cropped' => $message['message']['is_cropped'] ?? null,
 | 
			
		||||
                    'deleted' => $message['message']['deleted'] ?? null,
 | 
			
		||||
                    'conversation' =>
 | 
			
		||||
                    [
 | 
			
		||||
                        'id' => $message['message']['chat_id'] ?? null,
 | 
			
		||||
                        'admin' => [
 | 
			
		||||
                            'id' => $message['message']['admin_id'] ?? null
 | 
			
		||||
                        ],
 | 
			
		||||
                        'title' => $message['message']['title'] ?? null,
 | 
			
		||||
                        'members' => [
 | 
			
		||||
                            'amount' => $message['message']['members_count'] ?? null,
 | 
			
		||||
                            'amount_test' => $message['message']['users_count'] ?? null
 | 
			
		||||
                        ],
 | 
			
		||||
                        'active' => $message['message']['chat_active'] ?? null,
 | 
			
		||||
                        'settings' => [
 | 
			
		||||
                            'push' => $message['message']['push_settings'] ?? null
 | 
			
		||||
                        ]
 | 
			
		||||
                    ],
 | 
			
		||||
                    'important' => $message['message']['important'] ?? null,
 | 
			
		||||
                    'source' => [
 | 
			
		||||
                        'from' => $message['message']['ref'] ?? null,
 | 
			
		||||
                        'data' => $message['message']['ref_source'] ?? null
 | 
			
		||||
                    ],
 | 
			
		||||
                    'payload' => $message['message']['payload'] ?? null,
 | 
			
		||||
                    'geo' => [
 | 
			
		||||
                        $message['message']['geo'] ?? null
 | 
			
		||||
                    ],
 | 
			
		||||
                    'keyboard' => [
 | 
			
		||||
                        'block' => $message['client_info']['keyboard'] ?? null,
 | 
			
		||||
                        'inline' => $message['client_info']['inline_keyboard'] ?? null,
 | 
			
		||||
                        'buttons' => $message['client_info']['button_actions'] ?? null,
 | 
			
		||||
                    ],
 | 
			
		||||
                    'carousel' => $message['client_info']['carousel'] ?? null,
 | 
			
		||||
                    'language' => $message['client_info']['lang_id'] ?? null,
 | 
			
		||||
                ]
 | 
			
		||||
            ];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Очистка массива, если активировано
 | 
			
		||||
        $clean and static::cleaner($messages);
 | 
			
		||||
 | 
			
		||||
        return $messages;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Обработка вложений
 | 
			
		||||
     *
 | 
			
		||||
     * @param array $attachments Вложения
 | 
			
		||||
     * @param bool $download Активация скачивания файлов на сервер
 | 
			
		||||
     * @param bool $clean Активация очистки массива от пустых данных сообщения
 | 
			
		||||
     *
 | 
			
		||||
     * @return array Обработанные вложения
 | 
			
		||||
     */
 | 
			
		||||
    public static function attachments(array $attachments, bool $download = false, bool $clean = false): array
 | 
			
		||||
    {
 | 
			
		||||
        foreach ($attachments as &$attachment) {
 | 
			
		||||
            // Перебор вложений
 | 
			
		||||
 | 
			
		||||
            if ($attachment['type'] === 'photo') {
 | 
			
		||||
                // Изображение
 | 
			
		||||
 | 
			
		||||
                $attachment = [
 | 
			
		||||
                    'data' => [
 | 
			
		||||
                        'date' => $attachment['photo']['date'] ?? null,
 | 
			
		||||
                        'id' => $attachment['photo']['id'] ?? null,
 | 
			
		||||
                        'album' => [
 | 
			
		||||
                            'id' => $attachment['photo']['album_id'] ?? null
 | 
			
		||||
                        ],
 | 
			
		||||
                        'account' => [
 | 
			
		||||
                            'id' => $attachment['photo']['user_id'] ?? null,
 | 
			
		||||
                            'admin' => $attachment['photo']['owner_id'] ?? null
 | 
			
		||||
                        ],
 | 
			
		||||
                        'tags' => $attachment['photo']['has_tags'] ?? null,
 | 
			
		||||
                        'access' => [
 | 
			
		||||
                            'key' => $attachment['photo']['access_key'] ?? null
 | 
			
		||||
                        ],
 | 
			
		||||
                        'text' => $attachment['photo']['text'] ?? null,
 | 
			
		||||
                        'storage' => static::sizes($attachment['photo']['sizes'], $download) ?? null
 | 
			
		||||
                    ],
 | 
			
		||||
                    'metadata' => [
 | 
			
		||||
                        'type' => $attachment['type'] ?? null
 | 
			
		||||
                    ]
 | 
			
		||||
                ];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Очистка массива, если активировано
 | 
			
		||||
        $clean and static::cleaner($attachments);
 | 
			
		||||
 | 
			
		||||
        return $attachments;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Сортировка размеров файла из вложения
 | 
			
		||||
     *
 | 
			
		||||
     * @param array $sizes Размеры файла согласно спецификации в API
 | 
			
		||||
     * @param bool $download Активация скачивания файлов на сервер
 | 
			
		||||
     * @param int|null $id Идентификатор аккаунта кому принадлежат изображения
 | 
			
		||||
     *
 | 
			
		||||
     * @return array Обработанные размеры
 | 
			
		||||
     *
 | 
			
		||||
     * @see https://vk.com/dev/photo_sizes
 | 
			
		||||
     */
 | 
			
		||||
    public static function sizes(array $sizes, bool $download = false, int|null $id = null): array
 | 
			
		||||
    {
 | 
			
		||||
        foreach ($sizes as &$size) {
 | 
			
		||||
            // Перебор размеров
 | 
			
		||||
 | 
			
		||||
            if ($download) {
 | 
			
		||||
                // Запрошено сохранение на сервер
 | 
			
		||||
 | 
			
		||||
                // Инициализация
 | 
			
		||||
                $browser = new Guzzle();
 | 
			
		||||
 | 
			
		||||
                // Инициализация директории
 | 
			
		||||
                if (!file_exists($path = static::$path_storage . (isset($id) ? static::$path_storage_accounts . PHP_EOL . $id : static::$path_storage_vk) . static::$path_storage_accounts_images . PHP_EOL . date('Y_m_d', time())))
 | 
			
		||||
                    if (!mkdir($path, 0755, true))
 | 
			
		||||
                        throw new Exception('Не удалось инициализировать директорию: ' . $path);
 | 
			
		||||
 | 
			
		||||
                // Генерация временного файла с уникальным дескриптором
 | 
			
		||||
                $file = tempnam($path, '');
 | 
			
		||||
 | 
			
		||||
                // Сохранение в файл
 | 
			
		||||
                $request = $browser->get($size['url'], ['sink' => $file]);
 | 
			
		||||
 | 
			
		||||
                var_dump($request->getHeaders());
 | 
			
		||||
                die;
 | 
			
		||||
 | 
			
		||||
                // Чтение расширения файла
 | 
			
		||||
                $ext = $request->getHeader('Mime-Type');
 | 
			
		||||
 | 
			
		||||
                // Перезапись
 | 
			
		||||
                rename($file, dirname($file) . PHP_EOL . (static::disposition_filename($request->getHeader('Content-Disposition')[0]) ?? 1));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Инициализация
 | 
			
		||||
            $size = [
 | 
			
		||||
                'data' => [
 | 
			
		||||
                    'width' => [
 | 
			
		||||
                        'value' => $size['width'],
 | 
			
		||||
                        'unit' => 'px'
 | 
			
		||||
                    ],
 | 
			
		||||
                    'height' => [
 | 
			
		||||
                        'value' => $size['height'],
 | 
			
		||||
                        'unit' => 'px'
 | 
			
		||||
                    ],
 | 
			
		||||
                    'source' => [
 | 
			
		||||
                        'vk' => $size['url']
 | 
			
		||||
                    ]
 | 
			
		||||
                ],
 | 
			
		||||
                'metadata' => [
 | 
			
		||||
                    'type' => $size['type']
 | 
			
		||||
                ]
 | 
			
		||||
            ];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $sizes;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Инициализация
 | 
			
		||||
    public static function cleaner(array &$target): bool
 | 
			
		||||
    {
 | 
			
		||||
        // Инициализация
 | 
			
		||||
        $changes = false;
 | 
			
		||||
 | 
			
		||||
        foreach ($target as $key => &$value) {
 | 
			
		||||
            // Перебор элементов массива
 | 
			
		||||
 | 
			
		||||
            if ($value === null || $value === []) {
 | 
			
		||||
                // Пустое значение
 | 
			
		||||
 | 
			
		||||
                // Удаление из массива по ключу
 | 
			
		||||
                unset($target[$key]);
 | 
			
		||||
 | 
			
		||||
                // Запись обозначения о том, что были произведены изменения
 | 
			
		||||
                $changes = true;
 | 
			
		||||
            } else if (is_array($value)) {
 | 
			
		||||
                // Элемент является массивом
 | 
			
		||||
 | 
			
		||||
                // Начало рекурсии (повторяется до тех пор пока производятся изменения за итерацию)
 | 
			
		||||
                while (static::cleaner($value));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $changes;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function truncate()
 | 
			
		||||
    {
 | 
			
		||||
        collection::truncate($this->connection->session, static::COLLECTION_USERS);
 | 
			
		||||
        collection::truncate($this->connection->session, static::COLLECTION_GROUPS);
 | 
			
		||||
        collection::truncate($this->connection->session, static::COLLECTION_CHATS);
 | 
			
		||||
        collection::truncate($this->connection->session, static::COLLECTION_MESSAGES);
 | 
			
		||||
        collection::truncate($this->connection->session, static::COLLECTION_ACCESSED);
 | 
			
		||||
        collection::truncate($this->connection->session, journal::COLLECTION_JOURNAL);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Определить тип аккаунта
 | 
			
		||||
     *
 | 
			
		||||
     * @param int $id Идентификатор
 | 
			
		||||
     *
 | 
			
		||||
     * @return string Возвращает 'user', если не прошли другие проверки
 | 
			
		||||
     */
 | 
			
		||||
    public static function type(int $id): string
 | 
			
		||||
    {
 | 
			
		||||
        // Чат
 | 
			
		||||
        if ($id - 2000000000 >= 0) return static::COLLECTION_CHATS;
 | 
			
		||||
 | 
			
		||||
        // Группа
 | 
			
		||||
        if (((string) $id)[0] === '-') return static::COLLECTION_GROUPS;
 | 
			
		||||
 | 
			
		||||
        return static::COLLECTION_USERS;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										20
									
								
								mirzaev/vk/arangodb/system/terminal.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								mirzaev/vk/arangodb/system/terminal.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace mirzaev\vk\arangodb;
 | 
			
		||||
 | 
			
		||||
class terminal
 | 
			
		||||
{
 | 
			
		||||
    protected const PREFIX = 'arangodb';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Запись в вывод
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $text Текст сообщения
 | 
			
		||||
     */
 | 
			
		||||
    public static function write(string $text): void
 | 
			
		||||
    {
 | 
			
		||||
        echo '[Модуль][' . self::PREFIX . '] ' . $text . PHP_EOL;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,82 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace mirzaev\vk\arangodb\traits\HTTP\headers\content;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Обработка заголовка: "Content-Disposition"
 | 
			
		||||
 *
 | 
			
		||||
 * @see https://developer.mozilla.org/ru/docs/Web/HTTP/Headers/Content-Disposition
 | 
			
		||||
 */
 | 
			
		||||
trait disposition
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Поиск значения filename
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $raw Необработанное значение заголовка
 | 
			
		||||
     */
 | 
			
		||||
    private static function filename(string $raw): ?string
 | 
			
		||||
    {
 | 
			
		||||
        // Инициализация
 | 
			
		||||
        $raw = trim($raw);
 | 
			
		||||
 | 
			
		||||
        if (strpos($raw, ';') === false) {
 | 
			
		||||
            // Разделитель параметров не найден (пустая строка или отсутствие параметров)
 | 
			
		||||
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Инициализация
 | 
			
		||||
        $params = [];
 | 
			
		||||
        $_params = explode(';', $raw);
 | 
			
		||||
        $type = $_params[0];
 | 
			
		||||
        unset($_params[0]);
 | 
			
		||||
 | 
			
		||||
        if (str_contains($type, 'attachment')) {
 | 
			
		||||
            // В заголовке указано, что это скачиваемый файл
 | 
			
		||||
 | 
			
		||||
            foreach ($_params as $param) {
 | 
			
		||||
                if (str_contains($param, '=')) {
 | 
			
		||||
                    // Параметр подходит по маске: "текст=текст"
 | 
			
		||||
 | 
			
		||||
                    // Чтение и запись в переменные
 | 
			
		||||
                    [$key, $value] = explode('=', $param, 2);
 | 
			
		||||
 | 
			
		||||
                    // Запись в буфер
 | 
			
		||||
                    $params[trim($key)] = trim($value);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Инициализация (порядок связан с приоритетом)
 | 
			
		||||
            $masks = ['filename*' => true, 'filename' => false];
 | 
			
		||||
            $targets = [];
 | 
			
		||||
 | 
			
		||||
            foreach ($masks as $mask => $utf8) {
 | 
			
		||||
                // Перебор значений масок
 | 
			
		||||
 | 
			
		||||
                if (isset($params[$mask])) {
 | 
			
		||||
                    // Параметр из буфера прошел проверку по маске
 | 
			
		||||
 | 
			
		||||
                    // Инициализация
 | 
			
		||||
                    $target = trim($params[$mask]);
 | 
			
		||||
 | 
			
		||||
                    // Надо разобраться с этим
 | 
			
		||||
                    if ($utf8 && strpos($target, "utf-8''") === 0 && $target = substr($target, strlen("utf-8''")))
 | 
			
		||||
                        $target = rawurldecode($target);
 | 
			
		||||
 | 
			
		||||
                    // Надо разобраться с этим
 | 
			
		||||
                    if (substr($target, 0, 1) === '"' && substr($target, -1, 1) === '"')
 | 
			
		||||
                        $target = substr($target, 1, -1);
 | 
			
		||||
 | 
			
		||||
                    $targets[$mask] = $target;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Возврат по приоритету
 | 
			
		||||
            return $targets[$masks[0]] ?? $targets[$masks[1]];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,14 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace mirzaev\vk\arangodb\traits\HTTP\headers\content;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Обработка заголовка: "Content-Type"
 | 
			
		||||
 *
 | 
			
		||||
 * @see https://developer.mozilla.org/ru/docs/Web/HTTP/Headers/Content-Type
 | 
			
		||||
 */
 | 
			
		||||
trait type
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										82
									
								
								mirzaev/vk/arangodb/system/vk/chat.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								mirzaev/vk/arangodb/system/vk/chat.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,82 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace mirzaev\vk\arangodb\vk;
 | 
			
		||||
 | 
			
		||||
use mirzaev\vk\arangodb\longpoll;
 | 
			
		||||
use mirzaev\vk\arangodb\journal;
 | 
			
		||||
use mirzaev\arangodb\collection;
 | 
			
		||||
use mirzaev\arangodb\document;
 | 
			
		||||
use ArangoDBClient\Document as _document;
 | 
			
		||||
 | 
			
		||||
use ArangoDBClient\Connection as _connection;
 | 
			
		||||
 | 
			
		||||
class chat
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Инициализация
 | 
			
		||||
     *
 | 
			
		||||
     * @param _connection $session Сессия соединения с базой данных
 | 
			
		||||
     * @param int $id Идентификатор ВКонтакте
 | 
			
		||||
     * @param bool $journal Записывать в журнал
 | 
			
		||||
     * @param bool $create Создавать коллекции при их отсутствии
 | 
			
		||||
     *
 | 
			
		||||
     * @return ?_document Инстанция документа
 | 
			
		||||
     */
 | 
			
		||||
    public static function init(_connection $session, int $id, bool $journal = true, bool $create = true): ?_document
 | 
			
		||||
    {
 | 
			
		||||
        // Инициализация коллекции
 | 
			
		||||
        $collection = longpoll::COLLECTION_CHATS;
 | 
			
		||||
 | 
			
		||||
        if ($create) {
 | 
			
		||||
            // Запрошено создание коллекций в случае их отсутствия
 | 
			
		||||
 | 
			
		||||
            // Создание коллекции
 | 
			
		||||
            collection::init($session, $collection);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($account = collection::search($session, <<<AQL
 | 
			
		||||
                FOR x IN $collection
 | 
			
		||||
                FILTER x.data.data.id == $id
 | 
			
		||||
                LIMIT 1
 | 
			
		||||
                RETURN x.data
 | 
			
		||||
            AQL)) {
 | 
			
		||||
            // Найден аккаунт
 | 
			
		||||
 | 
			
		||||
            return $account;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($account = document::write($session, $collection, ['data' => ['id' => $id]])) {
 | 
			
		||||
            // Аккаунт записан
 | 
			
		||||
 | 
			
		||||
            // Журналирование
 | 
			
		||||
            if ($journal && journal::init($session, $account)->write('create', [
 | 
			
		||||
                'changes' => [
 | 
			
		||||
                    'new' => collection::search($session, <<<AQL
 | 
			
		||||
                            FOR a IN $collection
 | 
			
		||||
                            FILTER a._id == $account
 | 
			
		||||
                            LIMIT 1
 | 
			
		||||
                            RETURN a.data
 | 
			
		||||
                        AQL),
 | 
			
		||||
                    'old' => null
 | 
			
		||||
                ]
 | 
			
		||||
            ])) {
 | 
			
		||||
                // Записаны данные в журнал
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if ($account = collection::search($session, <<<AQL
 | 
			
		||||
                    FOR x IN $collection
 | 
			
		||||
                    FILTER x.data.data.id == $id
 | 
			
		||||
                    LIMIT 1
 | 
			
		||||
                    RETURN x
 | 
			
		||||
                AQL)) {
 | 
			
		||||
                // Найден аккаунт
 | 
			
		||||
 | 
			
		||||
                return $account;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										82
									
								
								mirzaev/vk/arangodb/system/vk/group.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								mirzaev/vk/arangodb/system/vk/group.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,82 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace mirzaev\vk\arangodb\vk;
 | 
			
		||||
 | 
			
		||||
use mirzaev\vk\arangodb\longpoll;
 | 
			
		||||
use mirzaev\vk\arangodb\journal;
 | 
			
		||||
use mirzaev\arangodb\collection;
 | 
			
		||||
use mirzaev\arangodb\document;
 | 
			
		||||
use ArangoDBClient\Document as _document;
 | 
			
		||||
 | 
			
		||||
use ArangoDBClient\Connection as _connection;
 | 
			
		||||
 | 
			
		||||
class group
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Инициализация
 | 
			
		||||
     *
 | 
			
		||||
     * @param _connection $session Сессия соединения с базой данных
 | 
			
		||||
     * @param int $id Идентификатор ВКонтакте
 | 
			
		||||
     * @param bool $journal Записывать в журнал
 | 
			
		||||
     * @param bool $create Создавать коллекции при их отсутствии
 | 
			
		||||
     *
 | 
			
		||||
     * @return ?_document Инстанция документа
 | 
			
		||||
     */
 | 
			
		||||
    public static function init(_connection $session, int $id, bool $journal = true, bool $create = true): ?_document
 | 
			
		||||
    {
 | 
			
		||||
        // Инициализация коллекции
 | 
			
		||||
        $collection = longpoll::COLLECTION_GROUPS;
 | 
			
		||||
 | 
			
		||||
        if ($create) {
 | 
			
		||||
            // Запрошено создание коллекций в случае их отсутствия
 | 
			
		||||
 | 
			
		||||
            // Создание коллекции
 | 
			
		||||
            collection::init($session, $collection);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($account = collection::search($session, <<<AQL
 | 
			
		||||
                FOR x IN $collection
 | 
			
		||||
                FILTER x.data.data.id == $id
 | 
			
		||||
                LIMIT 1
 | 
			
		||||
                RETURN x.data
 | 
			
		||||
            AQL)) {
 | 
			
		||||
            // Найден аккаунт
 | 
			
		||||
 | 
			
		||||
            return $account;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($account = document::write($session, $collection, ['data' => ['id' => $id]])) {
 | 
			
		||||
            // Аккаунт записан
 | 
			
		||||
 | 
			
		||||
            // Журналирование
 | 
			
		||||
            if ($journal && journal::init($session, $account)->write('create', [
 | 
			
		||||
                'changes' => [
 | 
			
		||||
                    'new' => collection::search($session, <<<AQL
 | 
			
		||||
                            FOR a IN $collection
 | 
			
		||||
                            FILTER a._id == $account
 | 
			
		||||
                            LIMIT 1
 | 
			
		||||
                            RETURN a.data
 | 
			
		||||
                        AQL),
 | 
			
		||||
                    'old' => null
 | 
			
		||||
                ]
 | 
			
		||||
            ])) {
 | 
			
		||||
                // Записаны данные в журнал
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if ($account = collection::search($session, <<<AQL
 | 
			
		||||
                    FOR x IN $collection
 | 
			
		||||
                    FILTER x.data.data.id == $id
 | 
			
		||||
                    LIMIT 1
 | 
			
		||||
                    RETURN x
 | 
			
		||||
                AQL)) {
 | 
			
		||||
                // Найден аккаунт
 | 
			
		||||
 | 
			
		||||
                return $account;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										82
									
								
								mirzaev/vk/arangodb/system/vk/user.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								mirzaev/vk/arangodb/system/vk/user.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,82 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace mirzaev\vk\arangodb\vk;
 | 
			
		||||
 | 
			
		||||
use mirzaev\vk\arangodb\longpoll;
 | 
			
		||||
use mirzaev\vk\arangodb\journal;
 | 
			
		||||
use mirzaev\arangodb\collection;
 | 
			
		||||
use mirzaev\arangodb\document;
 | 
			
		||||
use ArangoDBClient\Document as _document;
 | 
			
		||||
 | 
			
		||||
use ArangoDBClient\Connection as _connection;
 | 
			
		||||
 | 
			
		||||
class user
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Инициализация
 | 
			
		||||
     *
 | 
			
		||||
     * @param _connection $session Сессия соединения с базой данных
 | 
			
		||||
     * @param int $id Идентификатор ВКонтакте
 | 
			
		||||
     * @param bool $journal Записывать в журнал
 | 
			
		||||
     * @param bool $create Создавать коллекции при их отсутствии
 | 
			
		||||
     *
 | 
			
		||||
     * @return ?_document Инстанция документа
 | 
			
		||||
     */
 | 
			
		||||
    public static function init(_connection $session, int $id, bool $journal = true, bool $create = true): ?_document
 | 
			
		||||
    {
 | 
			
		||||
        // Инициализация коллекции
 | 
			
		||||
        $collection = longpoll::COLLECTION_USERS;
 | 
			
		||||
 | 
			
		||||
        if ($create) {
 | 
			
		||||
            // Запрошено создание коллекций в случае их отсутствия
 | 
			
		||||
 | 
			
		||||
            // Создание коллекции
 | 
			
		||||
            collection::init($session, $collection);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($account = collection::search($session, <<<AQL
 | 
			
		||||
                FOR x IN $collection
 | 
			
		||||
                FILTER x.id == $id
 | 
			
		||||
                LIMIT 1
 | 
			
		||||
                RETURN x
 | 
			
		||||
            AQL)) {
 | 
			
		||||
            // Найден аккаунт
 | 
			
		||||
 | 
			
		||||
            return $account;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($account = document::write($session, $collection, ['id' => $id])) {
 | 
			
		||||
            // Аккаунт записан
 | 
			
		||||
 | 
			
		||||
            // Журналирование
 | 
			
		||||
            if ($journal && journal::init($session, $account)->write('create', [
 | 
			
		||||
                'changes' => [
 | 
			
		||||
                    'new' => collection::search($session, <<<AQL
 | 
			
		||||
                            FOR a IN $collection
 | 
			
		||||
                            FILTER a._id == $account
 | 
			
		||||
                            LIMIT 1
 | 
			
		||||
                            RETURN a.data
 | 
			
		||||
                        AQL),
 | 
			
		||||
                    'old' => null
 | 
			
		||||
                ]
 | 
			
		||||
            ])) {
 | 
			
		||||
                // Записаны данные в журнал
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if ($account = collection::search($session, <<<AQL
 | 
			
		||||
                    FOR x IN $collection
 | 
			
		||||
                    FILTER x.data.data.id == $id
 | 
			
		||||
                    LIMIT 1
 | 
			
		||||
                    RETURN x
 | 
			
		||||
                AQL)) {
 | 
			
		||||
                // Найден аккаунт
 | 
			
		||||
 | 
			
		||||
                return $account;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user