From dd90f0adbeedb846ae368162d4020e8af01a24e8 Mon Sep 17 00:00:00 2001 From: Mirzaev Date: Mon, 14 Nov 2022 03:09:13 +1000 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=BE=D0=BB=D0=BD=D0=B0=D1=8F=20=D0=BF?= =?UTF-8?q?=D0=B5=D1=80=D0=B5=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mirzaev/vk/arangodb/system/longpoll.php | 241 +++++++++++----------- mirzaev/vk/arangodb/system/vk/account.php | 90 ++++++++ mirzaev/vk/arangodb/system/vk/chat.php | 104 +++++----- mirzaev/vk/arangodb/system/vk/group.php | 81 ++++---- mirzaev/vk/arangodb/system/vk/user.php | 82 -------- 5 files changed, 310 insertions(+), 288 deletions(-) create mode 100644 mirzaev/vk/arangodb/system/vk/account.php delete mode 100644 mirzaev/vk/arangodb/system/vk/user.php diff --git a/mirzaev/vk/arangodb/system/longpoll.php b/mirzaev/vk/arangodb/system/longpoll.php index aaba671..3bb42b6 100644 --- a/mirzaev/vk/arangodb/system/longpoll.php +++ b/mirzaev/vk/arangodb/system/longpoll.php @@ -32,7 +32,7 @@ class longpoll disposition::filename as disposition_filename; } - const COLLECTION_USERS = 'user'; + const COLLECTION_ACCOUNTS = 'account'; const COLLECTION_GROUPS = 'group'; const COLLECTION_CHATS = 'chat'; const COLLECTION_MESSAGES = 'message'; @@ -69,6 +69,7 @@ class longpoll return true; } } catch (Exception $e) { + // Запись ошибки в буфер вывода terminal::write($e->getMessage() . PHP_EOL . $e->getFile() . ':' . $e->getLine()); } @@ -78,8 +79,6 @@ class longpoll /** * Событие: "message_new" * - * Новое сообщение - * * @param array $data Данные сообщения * @param int $group Идентификатор группы * @param string $event Идентификатор события @@ -91,17 +90,15 @@ class longpoll if ($this->connection->create) { // Запрошено создание коллекций в случае их отсутствия - collection::init($this->connection->session, static::COLLECTION_USERS); + // Инициализация коллекций + collection::init($this->connection->session, static::COLLECTION_ACCOUNTS); collection::init($this->connection->session, static::COLLECTION_MESSAGES); } - if ($message = document::write($this->connection->session, static::COLLECTION_MESSAGES, static::messages($data, true))) { + if ($message = document::write($this->connection->session, static::COLLECTION_MESSAGES, static::messages($data, $data['message']['from_id']))) { // Записано сообщение - // Инициализация коллекции - $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']); @@ -111,14 +108,15 @@ class longpoll 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' => $from->getId(), '_to' => $message])) { // Записано ребро: АККАУНТ (отправитель) -> СООБЩЕНИЕ } - if (document::write($this->connection->session, static::COLLECTION_ACCESSED, [], ['_from' => $message, '_to' => $to->getId()])) { + if (document::write($this->connection->session, static::COLLECTION_ACCESSED, ['_from' => $message, '_to' => $to->getId()])) { // Записно ребро: СООБЩЕНИЕ -> АККАУНТ (получатель) } } @@ -127,12 +125,16 @@ class longpoll if ($this->journal && journal::init($this->connection->session, $message)->write('create', [ 'account' => $from, 'changes' => [ - 'new' => collection::search($this->connection->session, << collection::search($this->connection->session, sprintf( + <<<'AQL' + FOR a IN %s + FILTER a._id == "%s" + LIMIT 1 + RETURN a.data + AQL, + static::COLLECTION_MESSAGES, + $message + )), 'old' => null ] ])) { @@ -150,8 +152,8 @@ class longpoll * Обработка сообщений * * @param array $messages Сообщения или сообщение - * @param bool $download Активация скачивания файлов на сервер - * @param bool $clean Активация очистки массива от пустых данных сообщения + * @param ?int $id Идентификатор аккаунта которому принадлежат вложения + * @param bool $clean Очистить массив от пустых данных? * * @return array Обработанные сообщения (зависит от входных данных) * @@ -163,94 +165,87 @@ class longpoll * 5. Переделать $message['vk']['metadata']['conversation']['members']['amount_test'] (или удалить) * 6. Разобраться с "Мультидиалогом" для старых версий API и существует ли он в новых */ - public static function messages(array $messages, bool $download = false, bool $clean = true): array + public static function messages(array $messages, ?int $id = null, bool $clean = true): array { - if (isset($messages['message'])) { - // Передано одно сообщение - - // Инициализация - $buffer[] = &$messages; - } + // Универсализация входных данных - передано одно сообщение + 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) + 'id' => [ + 'global' => $message['message']['id'], + 'local' => $message['message']['conversation_message_id'] ], - 'metadata' => [ - 'date' => [ - 'create' => $message['message']['date'] ?? null, - 'update' => $message['message']['update_time'] ?? null + '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'], $id, $clean), + '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 ], - '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, + '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_author_id'] ?? null + 'id' => $message['message']['admin_id'] ?? null ], - 'pinned' => [ - 'date' => $message['message']['pinned_at'] ?? null + 'title' => $message['message']['title'] ?? null, + 'members' => [ + 'amount' => $message['message']['members_count'] ?? null, + 'amount_test' => $message['message']['users_count'] ?? 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, - ] + '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; @@ -260,12 +255,12 @@ class longpoll * Обработка вложений * * @param array $attachments Вложения - * @param bool $download Активация скачивания файлов на сервер - * @param bool $clean Активация очистки массива от пустых данных сообщения + * @param ?int $id Идентификатор аккаунта которому принадлежат изображения + * @param bool $clean Очистить массив от пустых данных? * * @return array Обработанные вложения */ - public static function attachments(array $attachments, bool $download = false, bool $clean = false): array + public static function attachments(array $attachments, ?int $id = null, bool $clean = true): array { foreach ($attachments as &$attachment) { // Перебор вложений @@ -289,7 +284,7 @@ class longpoll 'key' => $attachment['photo']['access_key'] ?? null ], 'text' => $attachment['photo']['text'] ?? null, - 'storage' => static::sizes($attachment['photo']['sizes'], $download) ?? null + 'storage' => static::sizes($attachment['photo']['sizes'], $id) ?? null ], 'metadata' => [ 'type' => $attachment['type'] ?? null @@ -298,36 +293,35 @@ class longpoll } } - // Очистка массива, если активировано + // Очистка массива $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 + * + * @param array $sizes Размеры изображения согласно спецификации в API + * @param ?int $id Идентификатор аккаунта которому принадлежат изображения + * + * @return array Обработанные размеры */ - public static function sizes(array $sizes, bool $download = false, int|null $id = null): array + public static function sizes(array $sizes, ?int $id = null): array { foreach ($sizes as &$size) { // Перебор размеров - if ($download) { - // Запрошено сохранение на сервер + if (isset($id)) { + // Запрошена запись файлов на сервер // Инициализация $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 (!file_exists($path = static::$path_storage . static::$path_storage_accounts . PHP_EOL . $id . static::$path_storage_accounts_images . PHP_EOL . date('Y_m_d', time()))) if (!mkdir($path, 0755, true)) throw new Exception('Не удалось инициализировать директорию: ' . $path); @@ -371,8 +365,13 @@ class longpoll return $sizes; } - - // Инициализация + /** + * Очистить массив от пустых значений + * + * @param array $target Обрабатываемый массив + * + * @return bool Массив был изменён? + */ public static function cleaner(array &$target): bool { // Инициализация @@ -400,9 +399,16 @@ class longpoll return $changes; } - public function truncate() + /** + * Очистить базу данных + * + * Предполагается использование для автоматизации тестирования + * + * @return void + */ + public function truncate(): void { - collection::truncate($this->connection->session, static::COLLECTION_USERS); + collection::truncate($this->connection->session, static::COLLECTION_ACCOUNTS); collection::truncate($this->connection->session, static::COLLECTION_GROUPS); collection::truncate($this->connection->session, static::COLLECTION_CHATS); collection::truncate($this->connection->session, static::COLLECTION_MESSAGES); @@ -411,11 +417,11 @@ class longpoll } /** - * Определить тип аккаунта + * Определить тип субъекта * * @param int $id Идентификатор * - * @return string Возвращает 'user', если не прошли другие проверки + * @return string Возвращает static::COLLECTION_ACCOUNTS, если не прошли другие проверки */ public static function type(int $id): string { @@ -423,8 +429,9 @@ class longpoll if ($id - 2000000000 >= 0) return static::COLLECTION_CHATS; // Группа - if (((string) $id)[0] === '-') return static::COLLECTION_GROUPS; + if ($id < 0) return static::COLLECTION_GROUPS; - return static::COLLECTION_USERS; + // Аккаунт + return static::COLLECTION_ACCOUNTS; } } diff --git a/mirzaev/vk/arangodb/system/vk/account.php b/mirzaev/vk/arangodb/system/vk/account.php new file mode 100644 index 0000000..e4bebf5 --- /dev/null +++ b/mirzaev/vk/arangodb/system/vk/account.php @@ -0,0 +1,90 @@ + + */ +class account +{ + /** + * Инициализировать + * + * @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 + { + if ($create) { + // Запрошено создание коллекций в случае их отсутствия + + // Инициализация коллекции + collection::init($session, longpoll::COLLECTION_ACCOUNTS); + } + + // Поиск + if ($account = static::search($session, $id)); + else if ($account = document::write($session, longpoll::COLLECTION_ACCOUNTS, ['id' => $id]) and $journal) + journal::init($session, $account)->write('create', [ + 'changes' => [ + 'new' => collection::search($session, sprintf( + <<<'AQL' + FOR x IN %s + FILTER x._id == "%s" + LIMIT 1 + RETURN x + AQL, + longpoll::COLLECTION_ACCOUNTS, + $account + )), + 'old' => null + ] + ]); + + // Поиск + return static::search($session, $id); + } + + /** + * Найти + * + * @param _connection $session Сессия соединения с базой данных + * @param int $id Идентификатор ВКонтакте + * + * @return ?_document Инстанция документа + */ + public static function search(_connection $session, int $id): ?_document + { + return collection::search($session, sprintf( + <<<'AQL' + FOR x IN %s + FILTER x.id == %u + LIMIT 1 + RETURN x + AQL, + longpoll::COLLECTION_ACCOUNTS, + $id + )); + } +} diff --git a/mirzaev/vk/arangodb/system/vk/chat.php b/mirzaev/vk/arangodb/system/vk/chat.php index c4d317e..813b876 100644 --- a/mirzaev/vk/arangodb/system/vk/chat.php +++ b/mirzaev/vk/arangodb/system/vk/chat.php @@ -4,14 +4,24 @@ 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; +// Модуль ArangoDB для фреймворка ВКонтакте +use mirzaev\vk\arangodb\longpoll, + mirzaev\vk\arangodb\journal; -use ArangoDBClient\Connection as _connection; +// Фреймворк ArangoDB +use mirzaev\arangodb\collection, + mirzaev\arangodb\document; +// Библиотека для работы с API ArabgoDB +use ArangoDBClient\Document as _document, + ArangoDBClient\Connection as _connection; + +/** + * Чат ВКонтакте + * + * @package mirzaev\vk\arangodb\vk + * @author Arsen Mirzaev Tatyano-Muradovich + */ class chat { /** @@ -19,64 +29,62 @@ class chat * * @param _connection $session Сессия соединения с базой данных * @param int $id Идентификатор ВКонтакте - * @param bool $journal Записывать в журнал - * @param bool $create Создавать коллекции при их отсутствии + * @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); + collection::init($session, longpoll::COLLECTION_CHATS); } - if ($account = collection::search($session, << ['id' => $id]])) { - // Аккаунт записан - - // Журналирование - if ($journal && journal::init($session, $account)->write('create', [ + // Поиск + if ($chat = static::search($session, $id)); + else if ($chat = document::write($session, longpoll::COLLECTION_CHATS, ['id' => $id]) and $journal) + journal::init($session, $chat)->write('create', [ 'changes' => [ - 'new' => collection::search($session, << collection::search($session, sprintf( + <<<'AQL' + FOR x IN %s + FILTER x._id == "%s" LIMIT 1 - RETURN a.data - AQL), + RETURN x + AQL, + longpoll::COLLECTION_CHATS, + $chat + )), 'old' => null ] - ])) { - // Записаны данные в журнал - } + ]); - if ($account = collection::search($session, << ['id' => $id]])) { - // Аккаунт записан - - // Журналирование - if ($journal && journal::init($session, $account)->write('create', [ + // Поиск + if ($group = static::search($session, $id)); + else if ($group = document::write($session, longpoll::COLLECTION_GROUPS, ['id' => $id]) and $journal) + journal::init($session, $group)->write('create', [ 'changes' => [ - 'new' => collection::search($session, << collection::search($session, sprintf( + <<<'AQL' + FOR x IN %s + FILTER x._id == "%s" LIMIT 1 - RETURN a.data - AQL), + RETURN x + AQL, + longpoll::COLLECTION_GROUPS, + $group + )), 'old' => null ] - ])) { - // Записаны данные в журнал - } + ]); - if ($account = collection::search($session, << $id])) { - // Аккаунт записан - - // Журналирование - if ($journal && journal::init($session, $account)->write('create', [ - 'changes' => [ - 'new' => collection::search($session, << null - ] - ])) { - // Записаны данные в журнал - } - - if ($account = collection::search($session, <<