commit 5de4881a5989b0f399f3cea18992a41b137d1836 Author: root Date: Sun Jun 4 08:18:29 2023 +0000 first init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..22d0d82 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +vendor diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7a3094a --- /dev/null +++ b/LICENSE @@ -0,0 +1,11 @@ +DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE +Version 2, December 2004 + +Copyright (C) 2004 Sam Hocevar + +Everyone is permitted to copy and distribute verbatim or modified copies of this license document, and changing it is allowed as long as the name is changed. + +DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. You just DO WHAT THE FUCK YOU WANT TO. diff --git a/README.md b/README.md new file mode 100644 index 0000000..867e854 --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +# Telegram chat-robot implementing a register of people + +⚠️ Documentation and code commenting not added + +Simple, asynchronous, scalable, easy to update +The robot sends messages in Russian, but they can easily be replaced with English + +😼 Developed lazily in 2 days diff --git a/START b/START new file mode 100644 index 0000000..a7c449e --- /dev/null +++ b/START @@ -0,0 +1 @@ +sudo -u www-data php mirzaev/telegram/registry/people/system/public/robot.php diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..909884f --- /dev/null +++ b/composer.json @@ -0,0 +1,25 @@ +{ + "name": "mirzaev/telegram-registry-people", + "type": "robot", + "require": { + "badfarm/zanzara": "^0.9.0" + }, + "license": "WTFPL", + "autoload": { + "psr-4": { + "mirzaev\\telegram\\registry\\people\\": "mirzaev/telegram/registry/people/system/" + } + }, + "authors": [ + { + "name": "Arsen Mirzaev Tatyano-Muradovich", + "email": "arsen@mirzaev.sexy" + } + ], + "minimum-stability": "stable", + "config": { + "allow-plugins": { + "php-http/discovery": true + } + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..28b821e --- /dev/null +++ b/composer.lock @@ -0,0 +1,1795 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "39ea6b3ef133c181d1814ce561dd40ae", + "packages": [ + { + "name": "badfarm/zanzara", + "version": "0.9.0", + "source": { + "type": "git", + "url": "https://github.com/badfarm/zanzara.git", + "reference": "76edd38a2f161f105ddfaa00e02fd1e603b7882d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/badfarm/zanzara/zipball/76edd38a2f161f105ddfaa00e02fd1e603b7882d", + "reference": "76edd38a2f161f105ddfaa00e02fd1e603b7882d", + "shasum": "" + }, + "require": { + "clue/http-proxy-react": "^1.8", + "ext-json": "*", + "ext-readline": "*", + "netresearch/jsonmapper": "^4.1", + "opis/closure": "^3.6", + "php": ">=7.4", + "php-di/php-di": "^6.4", + "php-http/multipart-stream-builder": "^1.2", + "psr/container": "^1.1", + "psr/log": "^1.1", + "react/cache": "^1.2", + "react/event-loop": "^1.3", + "react/http": "^1.8" + }, + "require-dev": { + "monolog/monolog": "^2.9", + "phpunit/phpunit": "^9.6", + "symfony/dotenv": "^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Zanzara\\": "src/Zanzara" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michele Righetti" + }, + { + "name": "Mattia Corradi" + } + ], + "description": "Asynchronous PHP Telegram Bot Framework", + "keywords": [ + "async", + "bot", + "php", + "reactphp", + "telegram" + ], + "support": { + "issues": "https://github.com/badfarm/zanzara/issues", + "source": "https://github.com/badfarm/zanzara/tree/0.9.0" + }, + "time": "2023-04-16T14:11:23+00:00" + }, + { + "name": "clue/http-proxy-react", + "version": "v1.8.0", + "source": { + "type": "git", + "url": "https://github.com/clue/reactphp-http-proxy.git", + "reference": "09366dd3e13b36b90f8e47a6acaf5a2c96b79fb5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/clue/reactphp-http-proxy/zipball/09366dd3e13b36b90f8e47a6acaf5a2c96b79fb5", + "reference": "09366dd3e13b36b90f8e47a6acaf5a2c96b79fb5", + "shasum": "" + }, + "require": { + "php": ">=5.3", + "react/promise": "^3 || ^2.1 || ^1.2.1", + "react/socket": "^1.12", + "ringcentral/psr7": "^1.2" + }, + "require-dev": { + "clue/block-react": "^1.5", + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8", + "react/event-loop": "^1.2", + "react/http": "^1.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Clue\\React\\HttpProxy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering" + } + ], + "description": "Async HTTP proxy connector, tunnel any TCP/IP-based protocol through an HTTP CONNECT proxy server, built on top of ReactPHP", + "homepage": "https://github.com/clue/reactphp-http-proxy", + "keywords": [ + "async", + "connect", + "http", + "proxy", + "reactphp" + ], + "support": { + "issues": "https://github.com/clue/reactphp-http-proxy/issues", + "source": "https://github.com/clue/reactphp-http-proxy/tree/v1.8.0" + }, + "funding": [ + { + "url": "https://clue.engineering/support", + "type": "custom" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2022-09-01T14:36:49+00:00" + }, + { + "name": "evenement/evenement", + "version": "v3.0.1", + "source": { + "type": "git", + "url": "https://github.com/igorw/evenement.git", + "reference": "531bfb9d15f8aa57454f5f0285b18bec903b8fb7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/igorw/evenement/zipball/531bfb9d15f8aa57454f5f0285b18bec903b8fb7", + "reference": "531bfb9d15f8aa57454f5f0285b18bec903b8fb7", + "shasum": "" + }, + "require": { + "php": ">=7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "Evenement": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + } + ], + "description": "Événement is a very simple event dispatching library for PHP", + "keywords": [ + "event-dispatcher", + "event-emitter" + ], + "support": { + "issues": "https://github.com/igorw/evenement/issues", + "source": "https://github.com/igorw/evenement/tree/master" + }, + "time": "2017-07-23T21:35:13+00:00" + }, + { + "name": "fig/http-message-util", + "version": "1.1.5", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message-util.git", + "reference": "9d94dc0154230ac39e5bf89398b324a86f63f765" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message-util/zipball/9d94dc0154230ac39e5bf89398b324a86f63f765", + "reference": "9d94dc0154230ac39e5bf89398b324a86f63f765", + "shasum": "" + }, + "require": { + "php": "^5.3 || ^7.0 || ^8.0" + }, + "suggest": { + "psr/http-message": "The package containing the PSR-7 interfaces" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Fig\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Utility classes and constants for use with PSR-7 (psr/http-message)", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "issues": "https://github.com/php-fig/http-message-util/issues", + "source": "https://github.com/php-fig/http-message-util/tree/1.1.5" + }, + "time": "2020-11-24T22:02:12+00:00" + }, + { + "name": "laravel/serializable-closure", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/serializable-closure.git", + "reference": "f23fe9d4e95255dacee1bf3525e0810d1a1b0f37" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/f23fe9d4e95255dacee1bf3525e0810d1a1b0f37", + "reference": "f23fe9d4e95255dacee1bf3525e0810d1a1b0f37", + "shasum": "" + }, + "require": { + "php": "^7.3|^8.0" + }, + "require-dev": { + "nesbot/carbon": "^2.61", + "pestphp/pest": "^1.21.3", + "phpstan/phpstan": "^1.8.2", + "symfony/var-dumper": "^5.4.11" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\SerializableClosure\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Nuno Maduro", + "email": "nuno@laravel.com" + } + ], + "description": "Laravel Serializable Closure provides an easy and secure way to serialize closures in PHP.", + "keywords": [ + "closure", + "laravel", + "serializable" + ], + "support": { + "issues": "https://github.com/laravel/serializable-closure/issues", + "source": "https://github.com/laravel/serializable-closure" + }, + "time": "2023-01-30T18:31:20+00:00" + }, + { + "name": "netresearch/jsonmapper", + "version": "v4.2.0", + "source": { + "type": "git", + "url": "https://github.com/cweiske/jsonmapper.git", + "reference": "f60565f8c0566a31acf06884cdaa591867ecc956" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/f60565f8c0566a31acf06884cdaa591867ecc956", + "reference": "f60565f8c0566a31acf06884cdaa591867ecc956", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", + "php": ">=7.1" + }, + "require-dev": { + "phpunit/phpunit": "~7.5 || ~8.0 || ~9.0", + "squizlabs/php_codesniffer": "~3.5" + }, + "type": "library", + "autoload": { + "psr-0": { + "JsonMapper": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "OSL-3.0" + ], + "authors": [ + { + "name": "Christian Weiske", + "email": "cweiske@cweiske.de", + "homepage": "http://github.com/cweiske/jsonmapper/", + "role": "Developer" + } + ], + "description": "Map nested JSON structures onto PHP classes", + "support": { + "email": "cweiske@cweiske.de", + "issues": "https://github.com/cweiske/jsonmapper/issues", + "source": "https://github.com/cweiske/jsonmapper/tree/v4.2.0" + }, + "time": "2023-04-09T17:37:40+00:00" + }, + { + "name": "opis/closure", + "version": "3.6.3", + "source": { + "type": "git", + "url": "https://github.com/opis/closure.git", + "reference": "3d81e4309d2a927abbe66df935f4bb60082805ad" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opis/closure/zipball/3d81e4309d2a927abbe66df935f4bb60082805ad", + "reference": "3d81e4309d2a927abbe66df935f4bb60082805ad", + "shasum": "" + }, + "require": { + "php": "^5.4 || ^7.0 || ^8.0" + }, + "require-dev": { + "jeremeamia/superclosure": "^2.0", + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.6.x-dev" + } + }, + "autoload": { + "files": [ + "functions.php" + ], + "psr-4": { + "Opis\\Closure\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marius Sarca", + "email": "marius.sarca@gmail.com" + }, + { + "name": "Sorin Sarca", + "email": "sarca_sorin@hotmail.com" + } + ], + "description": "A library that can be used to serialize closures (anonymous functions) and arbitrary objects.", + "homepage": "https://opis.io/closure", + "keywords": [ + "anonymous functions", + "closure", + "function", + "serializable", + "serialization", + "serialize" + ], + "support": { + "issues": "https://github.com/opis/closure/issues", + "source": "https://github.com/opis/closure/tree/3.6.3" + }, + "time": "2022-01-27T09:35:39+00:00" + }, + { + "name": "php-di/invoker", + "version": "2.3.3", + "source": { + "type": "git", + "url": "https://github.com/PHP-DI/Invoker.git", + "reference": "cd6d9f267d1a3474bdddf1be1da079f01b942786" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-DI/Invoker/zipball/cd6d9f267d1a3474bdddf1be1da079f01b942786", + "reference": "cd6d9f267d1a3474bdddf1be1da079f01b942786", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "psr/container": "^1.0|^2.0" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "mnapoli/hard-mode": "~0.3.0", + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Invoker\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Generic and extensible callable invoker", + "homepage": "https://github.com/PHP-DI/Invoker", + "keywords": [ + "callable", + "dependency", + "dependency-injection", + "injection", + "invoke", + "invoker" + ], + "support": { + "issues": "https://github.com/PHP-DI/Invoker/issues", + "source": "https://github.com/PHP-DI/Invoker/tree/2.3.3" + }, + "funding": [ + { + "url": "https://github.com/mnapoli", + "type": "github" + } + ], + "time": "2021-12-13T09:22:56+00:00" + }, + { + "name": "php-di/php-di", + "version": "6.4.0", + "source": { + "type": "git", + "url": "https://github.com/PHP-DI/PHP-DI.git", + "reference": "ae0f1b3b03d8b29dff81747063cbfd6276246cc4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/ae0f1b3b03d8b29dff81747063cbfd6276246cc4", + "reference": "ae0f1b3b03d8b29dff81747063cbfd6276246cc4", + "shasum": "" + }, + "require": { + "laravel/serializable-closure": "^1.0", + "php": ">=7.4.0", + "php-di/invoker": "^2.0", + "php-di/phpdoc-reader": "^2.0.1", + "psr/container": "^1.0" + }, + "provide": { + "psr/container-implementation": "^1.0" + }, + "require-dev": { + "doctrine/annotations": "~1.10", + "friendsofphp/php-cs-fixer": "^2.4", + "mnapoli/phpunit-easymock": "^1.2", + "ocramius/proxy-manager": "^2.11.2", + "phpstan/phpstan": "^0.12", + "phpunit/phpunit": "^9.5" + }, + "suggest": { + "doctrine/annotations": "Install it if you want to use annotations (version ~1.2)", + "ocramius/proxy-manager": "Install it if you want to use lazy injection (version ~2.0)" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "DI\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "The dependency injection container for humans", + "homepage": "https://php-di.org/", + "keywords": [ + "PSR-11", + "container", + "container-interop", + "dependency injection", + "di", + "ioc", + "psr11" + ], + "support": { + "issues": "https://github.com/PHP-DI/PHP-DI/issues", + "source": "https://github.com/PHP-DI/PHP-DI/tree/6.4.0" + }, + "funding": [ + { + "url": "https://github.com/mnapoli", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/php-di/php-di", + "type": "tidelift" + } + ], + "time": "2022-04-09T16:46:38+00:00" + }, + { + "name": "php-di/phpdoc-reader", + "version": "2.2.1", + "source": { + "type": "git", + "url": "https://github.com/PHP-DI/PhpDocReader.git", + "reference": "66daff34cbd2627740ffec9469ffbac9f8c8185c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-DI/PhpDocReader/zipball/66daff34cbd2627740ffec9469ffbac9f8c8185c", + "reference": "66daff34cbd2627740ffec9469ffbac9f8c8185c", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "require-dev": { + "mnapoli/hard-mode": "~0.3.0", + "phpunit/phpunit": "^8.5|^9.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "PhpDocReader\\": "src/PhpDocReader" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PhpDocReader parses @var and @param values in PHP docblocks (supports namespaced class names with the same resolution rules as PHP)", + "keywords": [ + "phpdoc", + "reflection" + ], + "support": { + "issues": "https://github.com/PHP-DI/PhpDocReader/issues", + "source": "https://github.com/PHP-DI/PhpDocReader/tree/2.2.1" + }, + "time": "2020-10-12T12:39:22+00:00" + }, + { + "name": "php-http/discovery", + "version": "1.15.3", + "source": { + "type": "git", + "url": "https://github.com/php-http/discovery.git", + "reference": "3ccd28dd9fb34b52db946abea1b538568e34eae8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/discovery/zipball/3ccd28dd9fb34b52db946abea1b538568e34eae8", + "reference": "3ccd28dd9fb34b52db946abea1b538568e34eae8", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0|^2.0", + "php": "^7.1 || ^8.0" + }, + "conflict": { + "nyholm/psr7": "<1.0" + }, + "provide": { + "php-http/async-client-implementation": "*", + "php-http/client-implementation": "*", + "psr/http-client-implementation": "*", + "psr/http-factory-implementation": "*", + "psr/http-message-implementation": "*" + }, + "require-dev": { + "composer/composer": "^1.0.2|^2.0", + "graham-campbell/phpspec-skip-example-extension": "^5.0", + "php-http/httplug": "^1.0 || ^2.0", + "php-http/message-factory": "^1.0", + "phpspec/phpspec": "^5.1 || ^6.1 || ^7.3", + "symfony/phpunit-bridge": "^6.2" + }, + "type": "composer-plugin", + "extra": { + "class": "Http\\Discovery\\Composer\\Plugin", + "plugin-optional": true + }, + "autoload": { + "psr-4": { + "Http\\Discovery\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Finds and installs PSR-7, PSR-17, PSR-18 and HTTPlug implementations", + "homepage": "http://php-http.org", + "keywords": [ + "adapter", + "client", + "discovery", + "factory", + "http", + "message", + "psr17", + "psr7" + ], + "support": { + "issues": "https://github.com/php-http/discovery/issues", + "source": "https://github.com/php-http/discovery/tree/1.15.3" + }, + "time": "2023-03-31T14:40:37+00:00" + }, + { + "name": "php-http/message-factory", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/message-factory.git", + "reference": "4d8778e1c7d405cbb471574821c1ff5b68cc8f57" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/message-factory/zipball/4d8778e1c7d405cbb471574821c1ff5b68cc8f57", + "reference": "4d8778e1c7d405cbb471574821c1ff5b68cc8f57", + "shasum": "" + }, + "require": { + "php": ">=5.4", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Factory interfaces for PSR-7 HTTP Message", + "homepage": "http://php-http.org", + "keywords": [ + "factory", + "http", + "message", + "stream", + "uri" + ], + "support": { + "issues": "https://github.com/php-http/message-factory/issues", + "source": "https://github.com/php-http/message-factory/tree/1.1.0" + }, + "time": "2023-04-14T14:16:17+00:00" + }, + { + "name": "php-http/multipart-stream-builder", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/multipart-stream-builder.git", + "reference": "11c1d31f72e01c738bbce9e27649a7cca829c30e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/multipart-stream-builder/zipball/11c1d31f72e01c738bbce9e27649a7cca829c30e", + "reference": "11c1d31f72e01c738bbce9e27649a7cca829c30e", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0", + "php-http/discovery": "^1.7", + "php-http/message-factory": "^1.0.2", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0" + }, + "require-dev": { + "nyholm/psr7": "^1.0", + "php-http/message": "^1.5", + "phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Message\\MultipartStream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com" + } + ], + "description": "A builder class that help you create a multipart stream", + "homepage": "http://php-http.org", + "keywords": [ + "factory", + "http", + "message", + "multipart stream", + "stream" + ], + "support": { + "issues": "https://github.com/php-http/multipart-stream-builder/issues", + "source": "https://github.com/php-http/multipart-stream-builder/tree/1.2.0" + }, + "time": "2021-05-21T08:32:01+00:00" + }, + { + "name": "psr/container", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/1.1.2" + }, + "time": "2021-11-05T16:50:12+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "e616d01114759c4c489f93b099585439f795fe35" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", + "reference": "e616d01114759c4c489f93b099585439f795fe35", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory/tree/1.0.2" + }, + "time": "2023-04-10T20:10:41+00:00" + }, + { + "name": "psr/http-message", + "version": "1.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/1.1" + }, + "time": "2023-04-04T09:50:52+00:00" + }, + { + "name": "psr/log", + "version": "1.1.4", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/1.1.4" + }, + "time": "2021-05-03T11:20:27+00:00" + }, + { + "name": "react/cache", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/cache.git", + "reference": "d47c472b64aa5608225f47965a484b75c7817d5b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/cache/zipball/d47c472b64aa5608225f47965a484b75c7817d5b", + "reference": "d47c472b64aa5608225f47965a484b75c7817d5b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "react/promise": "^3.0 || ^2.0 || ^1.1" + }, + "require-dev": { + "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Async, Promise-based cache interface for ReactPHP", + "keywords": [ + "cache", + "caching", + "promise", + "reactphp" + ], + "support": { + "issues": "https://github.com/reactphp/cache/issues", + "source": "https://github.com/reactphp/cache/tree/v1.2.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2022-11-30T15:59:55+00:00" + }, + { + "name": "react/dns", + "version": "v1.10.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/dns.git", + "reference": "a5427e7dfa47713e438016905605819d101f238c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/dns/zipball/a5427e7dfa47713e438016905605819d101f238c", + "reference": "a5427e7dfa47713e438016905605819d101f238c", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "react/cache": "^1.0 || ^0.6 || ^0.5", + "react/event-loop": "^1.2", + "react/promise": "^3.0 || ^2.7 || ^1.2.1", + "react/promise-timer": "^1.9" + }, + "require-dev": { + "phpunit/phpunit": "^9.3 || ^4.8.35", + "react/async": "^4 || ^3 || ^2" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Dns\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Async DNS resolver for ReactPHP", + "keywords": [ + "async", + "dns", + "dns-resolver", + "reactphp" + ], + "support": { + "issues": "https://github.com/reactphp/dns/issues", + "source": "https://github.com/reactphp/dns/tree/v1.10.0" + }, + "funding": [ + { + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2022-09-08T12:22:46+00:00" + }, + { + "name": "react/event-loop", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/event-loop.git", + "reference": "187fb56f46d424afb6ec4ad089269c72eec2e137" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/event-loop/zipball/187fb56f46d424afb6ec4ad089269c72eec2e137", + "reference": "187fb56f46d424afb6ec4ad089269c72eec2e137", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35" + }, + "suggest": { + "ext-event": "~1.0 for ExtEventLoop", + "ext-pcntl": "For signal handling support when using the StreamSelectLoop", + "ext-uv": "* for ExtUvLoop" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\EventLoop\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "ReactPHP's core reactor event loop that libraries can use for evented I/O.", + "keywords": [ + "asynchronous", + "event-loop" + ], + "support": { + "issues": "https://github.com/reactphp/event-loop/issues", + "source": "https://github.com/reactphp/event-loop/tree/v1.3.0" + }, + "funding": [ + { + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2022-03-17T11:10:22+00:00" + }, + { + "name": "react/http", + "version": "v1.8.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/http.git", + "reference": "aa7512ee17258c88466de30f9cb44ec5f9df3ff3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/http/zipball/aa7512ee17258c88466de30f9cb44ec5f9df3ff3", + "reference": "aa7512ee17258c88466de30f9cb44ec5f9df3ff3", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "fig/http-message-util": "^1.1", + "php": ">=5.3.0", + "psr/http-message": "^1.0", + "react/event-loop": "^1.2", + "react/promise": "^3 || ^2.3 || ^1.2.1", + "react/promise-stream": "^1.4", + "react/socket": "^1.12", + "react/stream": "^1.2", + "ringcentral/psr7": "^1.2" + }, + "require-dev": { + "clue/http-proxy-react": "^1.8", + "clue/reactphp-ssh-proxy": "^1.4", + "clue/socks-react": "^1.4", + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35", + "react/async": "^4 || ^3 || ^2", + "react/promise-timer": "^1.9" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Http\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Event-driven, streaming HTTP client and server implementation for ReactPHP", + "keywords": [ + "async", + "client", + "event-driven", + "http", + "http client", + "http server", + "https", + "psr-7", + "reactphp", + "server", + "streaming" + ], + "support": { + "issues": "https://github.com/reactphp/http/issues", + "source": "https://github.com/reactphp/http/tree/v1.8.0" + }, + "funding": [ + { + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2022-09-29T12:55:52+00:00" + }, + { + "name": "react/promise", + "version": "v2.9.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/promise.git", + "reference": "234f8fd1023c9158e2314fa9d7d0e6a83db42910" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/promise/zipball/234f8fd1023c9158e2314fa9d7d0e6a83db42910", + "reference": "234f8fd1023c9158e2314fa9d7d0e6a83db42910", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.36" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "React\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "A lightweight implementation of CommonJS Promises/A for PHP", + "keywords": [ + "promise", + "promises" + ], + "support": { + "issues": "https://github.com/reactphp/promise/issues", + "source": "https://github.com/reactphp/promise/tree/v2.9.0" + }, + "funding": [ + { + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2022-02-11T10:27:51+00:00" + }, + { + "name": "react/promise-stream", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/promise-stream.git", + "reference": "e6d2805e09ad50c4896f65f5e8705fe4ee7731a3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/promise-stream/zipball/e6d2805e09ad50c4896f65f5e8705fe4ee7731a3", + "reference": "e6d2805e09ad50c4896f65f5e8705fe4ee7731a3", + "shasum": "" + }, + "require": { + "php": ">=5.3", + "react/promise": "^3 || ^2.1 || ^1.2", + "react/stream": "^1.0 || ^0.7 || ^0.6 || ^0.5 || ^0.4.6" + }, + "require-dev": { + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "React\\Promise\\Stream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "The missing link between Promise-land and Stream-land for ReactPHP", + "homepage": "https://github.com/reactphp/promise-stream", + "keywords": [ + "Buffer", + "async", + "promise", + "reactphp", + "stream", + "unwrap" + ], + "support": { + "issues": "https://github.com/reactphp/promise-stream/issues", + "source": "https://github.com/reactphp/promise-stream/tree/v1.5.0" + }, + "funding": [ + { + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2022-09-09T11:42:18+00:00" + }, + { + "name": "react/promise-timer", + "version": "v1.9.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/promise-timer.git", + "reference": "aa7a73c74b8d8c0f622f5982ff7b0351bc29e495" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/promise-timer/zipball/aa7a73c74b8d8c0f622f5982ff7b0351bc29e495", + "reference": "aa7a73c74b8d8c0f622f5982ff7b0351bc29e495", + "shasum": "" + }, + "require": { + "php": ">=5.3", + "react/event-loop": "^1.2", + "react/promise": "^3.0 || ^2.7.0 || ^1.2.1" + }, + "require-dev": { + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "React\\Promise\\Timer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "A trivial implementation of timeouts for Promises, built on top of ReactPHP.", + "homepage": "https://github.com/reactphp/promise-timer", + "keywords": [ + "async", + "event-loop", + "promise", + "reactphp", + "timeout", + "timer" + ], + "support": { + "issues": "https://github.com/reactphp/promise-timer/issues", + "source": "https://github.com/reactphp/promise-timer/tree/v1.9.0" + }, + "funding": [ + { + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2022-06-13T13:41:03+00:00" + }, + { + "name": "react/socket", + "version": "v1.12.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/socket.git", + "reference": "81e1b4d7f5450ebd8d2e9a95bb008bb15ca95a7b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/socket/zipball/81e1b4d7f5450ebd8d2e9a95bb008bb15ca95a7b", + "reference": "81e1b4d7f5450ebd8d2e9a95bb008bb15ca95a7b", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.0", + "react/dns": "^1.8", + "react/event-loop": "^1.2", + "react/promise": "^3 || ^2.6 || ^1.2.1", + "react/promise-timer": "^1.9", + "react/stream": "^1.2" + }, + "require-dev": { + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35", + "react/async": "^4 || ^3 || ^2", + "react/promise-stream": "^1.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Socket\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Async, streaming plaintext TCP/IP and secure TLS socket server and client connections for ReactPHP", + "keywords": [ + "Connection", + "Socket", + "async", + "reactphp", + "stream" + ], + "support": { + "issues": "https://github.com/reactphp/socket/issues", + "source": "https://github.com/reactphp/socket/tree/v1.12.0" + }, + "funding": [ + { + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2022-08-25T12:32:25+00:00" + }, + { + "name": "react/stream", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/stream.git", + "reference": "7a423506ee1903e89f1e08ec5f0ed430ff784ae9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/stream/zipball/7a423506ee1903e89f1e08ec5f0ed430ff784ae9", + "reference": "7a423506ee1903e89f1e08ec5f0ed430ff784ae9", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.8", + "react/event-loop": "^1.2" + }, + "require-dev": { + "clue/stream-filter": "~1.2", + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Stream\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Event-driven readable and writable streams for non-blocking I/O in ReactPHP", + "keywords": [ + "event-driven", + "io", + "non-blocking", + "pipe", + "reactphp", + "readable", + "stream", + "writable" + ], + "support": { + "issues": "https://github.com/reactphp/stream/issues", + "source": "https://github.com/reactphp/stream/tree/v1.2.0" + }, + "funding": [ + { + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2021-07-11T12:37:55+00:00" + }, + { + "name": "ringcentral/psr7", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/ringcentral/psr7.git", + "reference": "360faaec4b563958b673fb52bbe94e37f14bc686" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ringcentral/psr7/zipball/360faaec4b563958b673fb52bbe94e37f14bc686", + "reference": "360faaec4b563958b673fb52bbe94e37f14bc686", + "shasum": "" + }, + "require": { + "php": ">=5.3", + "psr/http-message": "~1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "RingCentral\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "PSR-7 message implementation", + "keywords": [ + "http", + "message", + "stream", + "uri" + ], + "support": { + "source": "https://github.com/ringcentral/psr7/tree/master" + }, + "time": "2018-05-29T20:21:04+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [], + "plugin-api-version": "2.2.0" +} diff --git a/import.sql b/import.sql new file mode 100644 index 0000000..cd29d3b --- /dev/null +++ b/import.sql @@ -0,0 +1,162 @@ +-- phpMyAdmin SQL Dump +-- version 5.1.1deb5ubuntu1 +-- https://www.phpmyadmin.net/ +-- +-- Хост: localhost:3306 +-- Время создания: Июн 04 2023 г., 07:56 +-- Версия сервера: 10.6.12-MariaDB-0ubuntu0.22.04.1 +-- Версия PHP: 8.2.6 + +SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; +START TRANSACTION; +SET time_zone = "+00:00"; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; + +-- +-- База данных: `telegram-registry-people` +-- +CREATE DATABASE IF NOT EXISTS `telegram-registry-people` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; +USE `telegram-registry-people`; + +DELIMITER $$ +-- +-- Функции +-- +CREATE DEFINER=`root`@`localhost` FUNCTION `LEVENSHTEIN` (`s1` VARCHAR(255) CHARACTER SET utf8, `s2` VARCHAR(255) CHARACTER SET utf8) RETURNS INT(11) BEGIN + DECLARE s1_len, s2_len, i, j, c, c_temp, cost INT; + DECLARE s1_char CHAR CHARACTER SET utf8; + -- max strlen=255 for this function + DECLARE cv0, cv1 VARBINARY(256); + + SET s1_len = CHAR_LENGTH(s1), + s2_len = CHAR_LENGTH(s2), + cv1 = 0x00, + j = 1, + i = 1, + c = 0; + + IF (s1 = s2) THEN + RETURN (0); + ELSEIF (s1_len = 0) THEN + RETURN (s2_len); + ELSEIF (s2_len = 0) THEN + RETURN (s1_len); + END IF; + + WHILE (j <= s2_len) DO + SET cv1 = CONCAT(cv1, CHAR(j)), + j = j + 1; + END WHILE; + + WHILE (i <= s1_len) DO + SET s1_char = SUBSTRING(s1, i, 1), + c = i, + cv0 = CHAR(i), + j = 1; + + WHILE (j <= s2_len) DO + SET c = c + 1, + cost = IF(s1_char = SUBSTRING(s2, j, 1), 0, 1); + + SET c_temp = ORD(SUBSTRING(cv1, j, 1)) + cost; + IF (c > c_temp) THEN + SET c = c_temp; + END IF; + + SET c_temp = ORD(SUBSTRING(cv1, j+1, 1)) + 1; + IF (c > c_temp) THEN + SET c = c_temp; + END IF; + + SET cv0 = CONCAT(cv0, CHAR(c)), + j = j + 1; + END WHILE; + + SET cv1 = cv0, + i = i + 1; + END WHILE; + + RETURN (c); + END$$ + +DELIMITER ; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `accounts` +-- + +CREATE TABLE `accounts` ( + `id` int(11) NOT NULL COMMENT 'Идентификатор', + `id_telegram` int(11) NOT NULL COMMENT 'Идентификатор в телеграм', + `status` varchar(20) NOT NULL DEFAULT 'active' COMMENT 'Статус', + `admin` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Администратор?', + `created` timestamp NOT NULL DEFAULT current_timestamp() COMMENT 'Дата создания' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `people` +-- + +CREATE TABLE `people` ( + `id` int(11) NOT NULL COMMENT 'Идентификатор', + `name` varchar(80) DEFAULT NULL COMMENT 'Имя', + `surname` varchar(80) DEFAULT NULL COMMENT 'Фамилия', + `patronymic` varchar(80) DEFAULT NULL COMMENT 'Отчество', + `phone` bigint(20) DEFAULT NULL COMMENT 'Номер смартфона', + `address` varchar(255) DEFAULT NULL COMMENT 'Адрес', + `day` int(2) DEFAULT NULL COMMENT 'День рождения', + `month` int(2) DEFAULT NULL COMMENT 'Месяц рождения', + `year` int(4) DEFAULT NULL COMMENT 'Год рождения', + `data` text DEFAULT NULL COMMENT 'Информация', + `cover` varchar(255) DEFAULT NULL COMMENT 'Обложка', + `created` timestamp NOT NULL DEFAULT current_timestamp() COMMENT 'Дата создания', + `updated` timestamp NOT NULL DEFAULT current_timestamp() COMMENT 'Дата обновления' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- +-- Индексы сохранённых таблиц +-- + +-- +-- Индексы таблицы `accounts` +-- +ALTER TABLE `accounts` + ADD UNIQUE KEY `id_2` (`id`), + ADD KEY `id` (`id`); + +-- +-- Индексы таблицы `people` +-- +ALTER TABLE `people` + ADD UNIQUE KEY `id_2` (`id`), + ADD KEY `id` (`id`); + +-- +-- AUTO_INCREMENT для сохранённых таблиц +-- + +-- +-- AUTO_INCREMENT для таблицы `accounts` +-- +ALTER TABLE `accounts` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Идентификатор'; + +-- +-- AUTO_INCREMENT для таблицы `people` +-- +ALTER TABLE `people` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Идентификатор'; +COMMIT; + +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/levenshtein.sql b/levenshtein.sql new file mode 100644 index 0000000..153d2d2 --- /dev/null +++ b/levenshtein.sql @@ -0,0 +1,70 @@ +-- Levenshtein function +-- Source: https://openquery.com.au/blog/levenshtein-mysql-stored-function +-- Levenshtein reference: http://en.wikipedia.org/wiki/Levenshtein_distance + +-- Arjen note: because the levenshtein value is encoded in a byte array, distance cannot exceed 255; +-- thus the maximum string length this implementation can handle is also limited to 255 characters. + +DELIMITER $$ +DROP FUNCTION IF EXISTS LEVENSHTEIN $$ +CREATE FUNCTION LEVENSHTEIN(s1 VARCHAR(255) CHARACTER SET utf8, s2 VARCHAR(255) CHARACTER SET utf8) + RETURNS INT + DETERMINISTIC + BEGIN + DECLARE s1_len, s2_len, i, j, c, c_temp, cost INT; + DECLARE s1_char CHAR CHARACTER SET utf8; + -- max strlen=255 for this function + DECLARE cv0, cv1 VARBINARY(256); + + SET s1_len = CHAR_LENGTH(s1), + s2_len = CHAR_LENGTH(s2), + cv1 = 0x00, + j = 1, + i = 1, + c = 0; + + IF (s1 = s2) THEN + RETURN (0); + ELSEIF (s1_len = 0) THEN + RETURN (s2_len); + ELSEIF (s2_len = 0) THEN + RETURN (s1_len); + END IF; + + WHILE (j <= s2_len) DO + SET cv1 = CONCAT(cv1, CHAR(j)), + j = j + 1; + END WHILE; + + WHILE (i <= s1_len) DO + SET s1_char = SUBSTRING(s1, i, 1), + c = i, + cv0 = CHAR(i), + j = 1; + + WHILE (j <= s2_len) DO + SET c = c + 1, + cost = IF(s1_char = SUBSTRING(s2, j, 1), 0, 1); + + SET c_temp = ORD(SUBSTRING(cv1, j, 1)) + cost; + IF (c > c_temp) THEN + SET c = c_temp; + END IF; + + SET c_temp = ORD(SUBSTRING(cv1, j+1, 1)) + 1; + IF (c > c_temp) THEN + SET c = c_temp; + END IF; + + SET cv0 = CONCAT(cv0, CHAR(c)), + j = j + 1; + END WHILE; + + SET cv1 = cv0, + i = i + 1; + END WHILE; + + RETURN (c); + END $$ + +DELIMITER ; \ No newline at end of file diff --git a/mirzaev/telegram/registry/people/system/public/.gitignore b/mirzaev/telegram/registry/people/system/public/.gitignore new file mode 100644 index 0000000..fa780e2 --- /dev/null +++ b/mirzaev/telegram/registry/people/system/public/.gitignore @@ -0,0 +1 @@ +storage diff --git a/mirzaev/telegram/registry/people/system/public/robot.php b/mirzaev/telegram/registry/people/system/public/robot.php new file mode 100644 index 0000000..05858de --- /dev/null +++ b/mirzaev/telegram/registry/people/system/public/robot.php @@ -0,0 +1,706 @@ +setParseMode(Config::PARSE_MODE_MARKDOWN); + +$bot = new Zanzara(KEY, $config); + +$pdo = new \PDO('mysql:host=localhost;port=3306;dbname=telegram-registry-people;charset=utf8', 'dolboeb', 'sosiska228'); + +function isAdmin(int $id): bool +{ + global $pdo; + + return ($pdo->query("SELECT `admin` FROM accounts WHERE id_telegram=$id")->fetch(PDO::FETCH_ASSOC)['admin'] ?? 0) === 1; +} + +function isActive(int $id): bool +{ + global $pdo; + + return ($pdo->query("SELECT `status` FROM accounts WHERE id_telegram=$id")->fetch(PDO::FETCH_ASSOC)['status'] ?? 'inactive') === 'active'; +} + +function countEntries(): array +{ + global $pdo; + + $date = time(); + + $year = date('Y-m-d H:i:s', $date - 31556952); + $month = date('Y-m-d H:i:s', $date - 2678400); + $week = date('Y-m-d H:i:s', $date - 604800); + $day = date('Y-m-d H:i:s', $date - 86400); + + return $pdo->query( + <<= '$year') AS 'year', + (SELECT COUNT(`id`) FROM `people` WHERE `created` >= '$month') AS 'month', + (SELECT COUNT(`id`) FROM `people` WHERE `created` >= '$week') AS 'week', + (SELECT COUNT(`id`) FROM `people` WHERE `created` >= '$day') AS 'day' + SQL + )->fetch(PDO::FETCH_ASSOC); +} + +function lastUpdate(): string +{ + global $pdo; + + return date('Y\\\.m\\\.d H:i:s', strtotime($pdo->query('SELECT `updated` FROM people ORDER BY updated DESC LIMIT 1')->fetch(PDO::FETCH_ASSOC)['updated'] ?? 0)); +} + +function initEntry(): ?int +{ + global $pdo; + + $pdo->query("INSERT INTO `people` () VALUES ()")->fetch(); + + return $pdo->lastInsertId(); +} + +function generateMenu(Context $ctx): void +{ + $keyboard = [ + 'reply_markup' => + ['inline_keyboard' => [ + [ + ['callback_data' => 'read', 'text' => '🔍 Поиск'], + ] + ], 'resize_keyboard' => false] + ]; + + if (isAdmin($ctx->getMessage()?->getFrom()?->getId()) ?? $ctx->getCallbackQuery()->getFrom()->getId()) + $keyboard['reply_markup']['inline_keyboard'][0][] = ['callback_data' => 'write', 'text' => '📔 Записать']; + + $lastUpdate = lastUpdate(); + $count = countEntries(); + + $ctx->sendMessage( + <<deleteUserDataItem('wait_for'); + + match (null) { + $name => waitFor($ctx, 'name'), + $surname => waitFor($ctx, 'surname'), + $patronymic => waitFor($ctx, 'patronymic'), + $phone => waitFor($ctx, 'phone'), + $address => waitFor($ctx, 'address'), + $year => waitFor($ctx, 'year'), + $month => waitFor($ctx, 'month'), + $day => waitFor($ctx, 'day'), + $data => waitFor($ctx, 'data'), + $cover => waitFor($ctx, 'cover'), + default => (function () use ($ctx) { + $ctx->sendMessage('📦 *Все поля заполнены и записаны в реестре*')->then(function () use ($ctx) { + stopProcess($ctx)->then(function () use ($ctx) { + generateMenu($ctx); + }); + }); + })() + }; +} + +function readEntry( + Context $ctx, + ?string $name = null, + ?string $surname = null, + ?string $patronymic = null, + ?int $phone = null, + ?string $address = null, + ?int $year = null, + ?int $month = null, + ?int $day = null, + ?string $data = null +): PromiseInterface { + $ctx->deleteUserDataItem('wait_for'); + + return match (null) { + $name => waitFor($ctx, 'name'), + $surname => waitFor($ctx, 'surname'), + $patronymic => waitFor($ctx, 'patronymic'), + $phone => waitFor($ctx, 'phone'), + $address => waitFor($ctx, 'address'), + $year => waitFor($ctx, 'year'), + $month => waitFor($ctx, 'month'), + $day => waitFor($ctx, 'day'), + $data => waitFor($ctx, 'data'), + default => (function () use ($ctx) { + return $ctx->sendMessage('📦 *Все поля заполнены*'); + })() + }; +} + +function generateQueryStatus( + Context $ctx, + ?string $name = null, + ?string $surname = null, + ?string $patronymic = null, + ?int $phone = null, + ?string $address = null, + ?int $year = null, + ?int $month = null, + ?int $day = null, + ?string $data = null +): PromiseInterface { + if (isset($name)) $name = preg_replace('/([._\-()!])/', '\\\$1', $name); + if (isset($surname)) $surname = preg_replace('/([._\-()!])/', '\\\$1', $surname); + if (isset($patronymic)) $patronymic = preg_replace('/([._\-()!])/', '\\\$1', $patronymic); + if (isset($phone)) $phone = preg_replace('/([._\-()!])/', '\\\$1', $phone); + if (isset($address)) $address = preg_replace('/([._\-()!])/', '\\\$1', $address); + if (isset($year)) $year = preg_replace('/([._\-()!])/', '\\\$1', $year); + if (isset($month)) $month = preg_replace('/([._\-()!])/', '\\\$1', $month); + if (isset($day)) $day = preg_replace('/([._\-()!])/', '\\\$1', $day); + if (isset($data)) $data = preg_replace('/([._\-()!])/', '\\\$1', $data); + + $keyboard = generateFieldsButtons( + ...[ + 'name' => true, + 'surname' => true, + 'patronymic' => true, + 'name' => true, + 'phone' => true, + 'address' => true, + 'year' => true, + 'month' => true, + 'day' => true, + 'data' => true + ] + ); + + $keyboard['reply_markup']['inline_keyboard'][] = [ + ['callback_data' => 'stop', 'text' => '❎ Отмена'], + ['callback_data' => 'complete', 'text' => '✅ Отправить'] + ]; + + return $ctx->sendMessage( + << 'Введите имя', + 'surname' => 'Введите фамилию', + 'patronymic' => 'Введите отчество', + 'phone' => 'Введите номер телефона', + 'address' => 'Введите адрес', + 'year' => 'Введите год рождения', + 'month' => 'Введите номер месяца рождения', + 'day' => 'Введите номер дня рождения', + 'data' => 'Введите дополнительную информацию', + 'cover' => 'Отправьте обложку \(изображение\)', + default => 'Введите данные для записи в реестр', + }; + + if (isset($value)) $buffer .= "\n\n*Текущее значение:* " . preg_replace('/([._\-()!])/', '\\\$1', $value); + + return $buffer; +} + +function generateLabel(string $target): string +{ + return match ($target) { + 'name' => 'Имя', + 'surname' => 'Фамилия', + 'patronymic' => 'Отчество', + 'phone' => 'Номер', + 'address' => 'Адрес', + 'year' => 'Год', + 'month' => 'Месяц', + 'day' => 'День', + 'data' => 'Дополнительно', + 'cover' => 'Обложка', + default => 'Информация', + }; +} + +function generateFieldsButtons( + ?string $name = null, + ?string $surname = null, + ?string $patronymic = null, + ?int $phone = null, + ?string $address = null, + ?int $year = null, + ?int $month = null, + ?int $day = null, + ?string $data = null, + ?string $cover = null +): array { + $buffer = []; + $buffer2 = []; + + if (isset($name)) count($buffer) < 4 + ? $buffer[] = ['callback_data' => 'name', 'text' => generateLabel('name')] + : $buffer2[] = ['callback_data' => 'name', 'text' => generateLabel('name')]; + if (isset($surname)) count($buffer) < 4 + ? $buffer[] = ['callback_data' => 'surname', 'text' => generateLabel('surname')] + : $buffer2[] = ['callback_data' => 'surname', 'text' => generateLabel('surname')]; + if (isset($patronymic)) count($buffer) < 4 + ? $buffer[] = ['callback_data' => 'patronymic', 'text' => generateLabel('patronymic')] + : $buffer2[] = ['callback_data' => 'patronymic', 'text' => generateLabel('patronymic')]; + if (isset($phone)) count($buffer) < 4 + ? $buffer[] = ['callback_data' => 'phone', 'text' => generateLabel('phone')] + : $buffer2[] = ['callback_data' => 'phone', 'text' => generateLabel('phone')]; + if (isset($address)) count($buffer) < 4 + ? $buffer[] = ['callback_data' => 'address', 'text' => generateLabel('address')] + : $buffer2[] = ['callback_data' => 'address', 'text' => generateLabel('address')]; + if (isset($year)) count($buffer) < 4 + ? $buffer[] = ['callback_data' => 'year', 'text' => generateLabel('year')] + : $buffer2[] = ['callback_data' => 'year', 'text' => generateLabel('year')]; + if (isset($month)) count($buffer) < 4 + ? $buffer[] = ['callback_data' => 'month', 'text' => generateLabel('month')] + : $buffer2[] = ['callback_data' => 'month', 'text' => generateLabel('month')]; + if (isset($day)) count($buffer) < 4 + ? $buffer[] = ['callback_data' => 'day', 'text' => generateLabel('day')] + : $buffer2[] = ['callback_data' => 'day', 'text' => generateLabel('day')]; + if (isset($data)) count($buffer) < 4 + ? $buffer[] = ['callback_data' => 'data', 'text' => generateLabel('data')] + : $buffer2[] = ['callback_data' => 'data', 'text' => generateLabel('data')]; + if (isset($cover)) count($buffer) < 4 + ? $buffer[] = ['callback_data' => 'cover', 'text' => generateLabel('cover')] + : $buffer2[] = ['callback_data' => 'cover', 'text' => generateLabel('cover')]; + + return ['reply_markup' => ['inline_keyboard' => [$buffer, $buffer2], 'resize_keyboard' => false]]; +} + +function waitFor(Context $ctx, string $target): PromiseInterface +{ + return $ctx->getUserDataItem('process')->then(function ($process) use ($ctx, $target) { + if (isset($process)) + return $ctx->setUserDataItem("wait_for", $target)->then(function () use ($ctx, $target, $process) { + return $ctx->sendMessage('⚠️ ' . generateRequestLabel($target, $process['data'][$target]), ['reply_markup' => ['inline_keyboard' => [[['callback_data' => 'delete_field', 'text' => 'Удалить']]], 'resize_keyboard' => false]]); + }); + }); +} + +function updateEntry(int $id, string $name, string|int $value): void +{ + global $pdo; + + try { + $pdo->prepare("UPDATE `people` SET `$name` = :value WHERE `id` = :id")->execute([':value' => $value, ':id' => $id]); + } catch (Exception $e) { + } +} + +function checkEntry(int $id, string $name, string|int $value): bool +{ + global $pdo; + + $query = $pdo->prepare("SELECT `$name` FROM people WHERE `id` = :id"); + + $query->execute([':id' => $id]); + + return $query->fetch(PDO::FETCH_ASSOC)[$name] === $value; +} + +function startSearch(Context $ctx, string $order = 'updated', bool $desc = true, int $page = 1): PromiseInterface +{ + return $ctx->getUserDataItem('process')->then(function ($process) use ($ctx, $order, $desc, $page) { + if (empty($process)) return; + + return stopProcess($ctx)->then(function () use ($ctx, $process, $order, $desc, $page) { + return $ctx->sendMessage('⚙️ Запрос отправляется\.\.\.')->then(function () use ($ctx, $process, $order, $desc, $page) { + foreach ($process['search']($order, $desc, 3, --$page, ...$process['data']) as $entry) { + if (isset($entry['name'])) $entry['name'] = preg_replace('/([._\-()!])/', '\\\$1', $entry['name']); + if (isset($entry['surname'])) $entry['surname'] = preg_replace('/([._\-()!])/', '\\\$1', $entry['surname']); + if (isset($entry['patronymic'])) $entry['patronymic'] = preg_replace('/([._\-()!])/', '\\\$1', $entry['patronymic']); + if (isset($entry['phone'])) $entry['phone'] = preg_replace('/([._\-()!])/', '\\\$1', $entry['phone']); + if (isset($entry['address'])) $entry['address'] = preg_replace('/([._\-()!])/', '\\\$1', $entry['address']); + if (isset($entry['year'])) $entry['year'] = preg_replace('/([._\-()!])/', '\\\$1', $entry['year']); + if (isset($entry['month'])) $entry['month'] = preg_replace('/([._\-()!])/', '\\\$1', $entry['month']); + if (isset($entry['day'])) $entry['day'] = preg_replace('/([._\-()!])/', '\\\$1', $entry['day']); + if (isset($entry['data'])) $entry['data'] = preg_replace('/([._\-()!])/', '\\\$1', $entry['data']); + + $text = "*Имя:* {$entry['name']}\n*Фамилия:* {$entry['surname']}\n*Отчество:* {$entry['patronymic']}\n*Номер:* {$entry['phone']}\n*Адрес:* {$entry['address']}\n*Дата рождения:* {$entry['year']} {$entry['month']} {$entry['day']}\n*Дополнительно:* {$entry['data']}"; + + $file = parse_url($entry['cover'])['path']; + + if (file_exists($file)) $ctx->sendPhoto(new InputFile($file), ['caption' => $text, 'protect_content' => true]); + else $ctx->sendMessage($text, ['protect_content' => true]); + } + }); + }); + }); +} + +function searchSmartEntry( + string $order = 'updated', + bool $desc = true, + int $limit = 3, + int $page = 0, + ?string $name = null, + ?string $surname = null, + ?string $patronymic = null, + ?int $phone = null, + ?string $address = null, + ?int $year = null, + ?int $month = null, + ?int $day = null, + ?string $data = null +): array { + global $pdo; + + if ( + empty($name) + && empty($surname) + && empty($patronymic) + && empty($phone) + && empty($address) + && empty($year) + && empty($month) + && empty($day) + && empty($data) + ) return []; + + $query = 'SELECT * FROM `people` WHERE '; + $args = []; + $another = false; + + if (isset($name)) { + if ($another) $query .= ' && '; + else $another = true; + $query .= 'levenshtein(`name`, :name) < 3 && `name` != \'\''; + $args[':name'] = $name; + } + + if (isset($surname)) { + if ($another) $query .= ' && '; + else $another = true; + $query .= 'levenshtein(`surname`, :surname) < 3 && `surname` != \'\''; + $args[':surname'] = $surname; + } + + if (isset($patronymic)) { + if ($another) $query .= ' && '; + else $another = true; + $query .= 'levenshtein(`patronymic`, :patronymic) < 3 && `patronymic` != \'\''; + $args[':patronymic'] = $patronymic; + } + + if (isset($phone)) { + if ($another) $query .= ' && '; + else $another = true; + $query .= 'levenshtein(`phone`, :phone) < 2 && `phone` != \'\''; + $args[':phone'] = $phone; + } + + if (isset($address)) { + if ($another) $query .= ' && '; + else $another = true; + $query .= 'levenshtein(`address`, :address) < 4 && `address` != \'\''; + $args[':address'] = $address; + } + + if (isset($year)) { + if ($another) $query .= ' && '; + else $another = true; + $query .= '`year` == :year'; + $args[':year'] = $year; + } + + if (isset($month)) { + if ($another) $query .= ' && '; + else $another = true; + $query .= '`month` == :month'; + $args[':month'] = $month; + } + + if (isset($day)) { + if ($another) $query .= ' && '; + else $another = true; + $query .= '`day` == :day'; + $args[':day'] = $day; + } + + if (isset($data)) { + if ($another) $query .= ' && '; + else $another = true; + $query .= 'levenshtein(`data`, :data) < 6 && `data` != \'\''; + $args[':data'] = $data; + } + + $query .= " ORDER BY `$order` " . ($desc ? 'DESC' : 'ASC'); + + $offset = $page === 0 ? 0 : $limit * $page; + $query .= " LIMIT $limit OFFSET $offset"; + + try { + $instance = $pdo->prepare($query); + if ($instance->execute($args)) return $instance->fetchAll(PDO::FETCH_ASSOC); + else return []; + } catch (Exception $e) { + } + + return []; +} + +$stop = false; + +$bot->onUpdate(function (Context $ctx) use (&$stop): void { + if (!isActive($ctx->getMessage()?->getFrom()?->getId() ?? $ctx->getCallbackQuery()->getFrom()->getId())) $stop = true; +}); + +$bot->onCommand('start', function (Context $ctx) use ($stop): void { + if ($stop) return; + generateMenu($ctx); +}); + +$bot->onMessage(function (Context $ctx) use ($stop): void { + $text = $ctx->getMessage()->getText(); + + if (!empty($text) && $text[0] !== '/' || empty($text)) + $ctx->getUserDataItem('process')->then(function ($process) use ($ctx, $text) { + if (empty($process)) return; + + $ctx->getUserDataItem('wait_for')->then(function ($wait_for) use ($ctx, &$process, $text) { + $target = match ($wait_for) { + 'phone', 'day', 'month', 'year' => (function () use ($ctx, $text) { + preg_match_all('!\d+!', $text, $matches); + return (int) implode('', $matches[0]); + })(), + default => $text + }; + + if ($process['type'] === 'createEntry') { + // Создание записи в реестре + + if ($wait_for === 'cover') { + if (!file_exists($path = 'storage/' . $process['id'])) mkdir($path, '0755', true); + + $photos = $ctx->getMessage()->getPhoto(); + + $ctx->getFile(end($photos)->getFileId())->then(function ($file) use ($ctx, $wait_for, &$path, &$process, &$target) { + $url = pathinfo($file->getFilePath()); + + if (!file_exists($path .= '/' . $url['dirname'])) mkdir($path, '0755', true); + + file_put_contents($path .= '/' . $url['basename'], fopen('https://api.telegram.org/file/bot' . KEY . '/' . $file->getFilePath(), 'r')); + updateEntry($process['id'], $wait_for, $path); + + if (checkEntry($process['id'], $wait_for, $path)) { + $process['data'][$wait_for] = $path; + $ctx->setUserDataItem('process', $process)->then(function () use ($ctx, $path, $process) { + $ctx->sendMessage("✏️ *Записано в реестр*\n\n" . generateLabel('cover') . ': ' . ($link = preg_replace('/([._\-()!])/', '\\\$1', STORAGE . '/' . $path)) . "\n[]($link)")->then(function () use ($ctx, $process) { + // Запуск процесса создания + createEntry($ctx, ...$process['data']); + }); + }); + } else $ctx->sendMessage('🚫 Не удалось записать значение в реестр'); + }); + } else { + updateEntry($process['id'], $wait_for, $target); + + if (checkEntry($process['id'], $wait_for, $target)) { + $process['data'][$wait_for] = $target; + $ctx->setUserDataItem('process', $process)->then(function () use ($ctx, $target, $wait_for, $process) { + $ctx->sendMessage("✏️ *Записано в реестр*\n\n" . generateLabel($wait_for) . ': ' . preg_replace('/([._\-()!])/', '\\\$1', $target))->then(function () use ($ctx, $process) { + // Запуск процесса создания + createEntry($ctx, ...$process['data']); + }); + }); + } else $ctx->sendMessage('🚫 *Не удалось записать значение в реестр*'); + } + } else if ($process['type'] === 'readEntry') { + // Чтение записей в реестре + + $process['data'][$wait_for] = $target; + $ctx->setUserDataItem('process', $process)->then(function () use ($ctx, $process) { + generateQueryStatus($ctx, ...$process['data'])->then(function () use ($ctx, $process) { + readEntry($ctx, ...$process['data']); + }); + }); + } + }); + }); +}); + +function read(Context $ctx, bool $smart = false): void +{ + global $stop; + + if ($stop) return; + + // Инициализация процесса в кеше + $ctx->setUserDataItem('process', [ + 'type' => 'readEntry', + 'search' => 'searchSmartEntry', + 'data' => $data = [ + 'name' => null, + 'surname' => null, + 'patronymic' => null, + 'phone' => null, + 'address' => null, + 'year' => null, + 'month' => null, + 'day' => null, + 'data' => null + ] + ])->then(function () use ($ctx, $data) { + $ctx->sendMessage("⚡ *Запущен процесс поиска*")->then(function () use ($ctx, $data) { + generateQueryStatus($ctx, ...$data)->then(function () use ($ctx, $data) { + // Запуск процесса создания поиска + readEntry($ctx, ...$data); + }); + }); + }); +} + +function write(Context $ctx): void +{ + global $stop; + + if ($stop) return; + + if (isAdmin($ctx->getMessage()?->getFrom()?->getId() ?? $ctx->getCallbackQuery()->getFrom()->getId())) { + // Администратор + + if ($id = initEntry()) { + // Инициализирован человек в базе данных + + // Инициализация процесса в кеше + $ctx->setUserDataItem('process', [ + 'type' => 'createEntry', + 'id' => $id, + 'data' => $data = [ + 'name' => null, + 'surname' => null, + 'patronymic' => null, + 'phone' => null, + 'address' => null, + 'year' => null, + 'month' => null, + 'day' => null, + 'data' => null, + 'cover' => null + ] + ])->then(function () use ($ctx, $id, $data) { + $ctx->sendMessage("⚡ *Запущен процесс создания записи*")->then(function () use ($ctx, $data, $id) { + $ctx->sendMessage("📦 *Инициализирована запись в реестре:* $id")->then(function () use ($ctx, $data, $id) { + // Запуск процесса создания + createEntry($ctx, ...$data); + }); + }); + }); + } + } +} + +function stopProcess(Context $ctx): PromiseInterface +{ + return $ctx->deleteUserDataItem('process')->then(function () use ($ctx) { + return $ctx->deleteUserDataItem('wait_for')->then(function () use ($ctx) { + return $ctx->sendMessage('⛔ Процесс завершён'); + }); + }); +} + +function deleteField(Context $ctx): void +{ + $ctx->getUserDataItem('process')->then(function ($process) use ($ctx) { + $ctx->getUserDataItem('wait_for')->then(function ($wait_for) use ($ctx, $process) { + $process['data'][$wait_for] = null; + $ctx->setUserDataItem('process', $process)->then(function () use ($ctx, $process, $wait_for) { + $ctx->sendMessage('🗑️ *Удалено значение поля:* ' . mb_strtolower(generateLabel($wait_for)))->then(function () use ($ctx, $process) { + generateQueryStatus($ctx, ...$process['data'])->then(function () use ($ctx, $process) { + $process['type']($ctx, ...$process['data']); + }); + }); + }); + }); + }); +} + +$bot->onCommand('write', fn ($ctx) => write($ctx)); +$bot->onCommand('read', fn ($ctx) => read($ctx)); +$bot->onCommand('read_smart', fn ($ctx) => read($ctx, true)); + +$bot->onCbQueryData(['write'], fn ($ctx) => write($ctx)); +$bot->onCbQueryData(['read'], fn ($ctx) => read($ctx)); +$bot->onCbQueryData(['read_smart'], fn ($ctx) => read($ctx, true)); + +$bot->onCommand('name', fn ($ctx) => waitFor($ctx, 'name')); +$bot->onCommand('surname', fn ($ctx) => waitFor($ctx, 'surname')); +$bot->onCommand('patronymic', fn ($ctx) => waitFor($ctx, 'patronymic')); +$bot->onCommand('phone', fn ($ctx) => waitFor($ctx, 'phone')); +$bot->onCommand('address', fn ($ctx) => waitFor($ctx, 'address')); +$bot->onCommand('year', fn ($ctx) => waitFor($ctx, 'year')); +$bot->onCommand('month', fn ($ctx) => waitFor($ctx, 'month')); +$bot->onCommand('day', fn ($ctx) => waitFor($ctx, 'day')); +$bot->onCommand('data', fn ($ctx) => waitFor($ctx, 'data')); +$bot->onCommand('cover', fn ($ctx) => waitFor($ctx, 'cover')); + +$bot->onCbQueryData(['name'], fn ($ctx) => waitFor($ctx, 'name')); +$bot->onCbQueryData(['surname'], fn ($ctx) => waitFor($ctx, 'surname')); +$bot->onCbQueryData(['patronymic'], fn ($ctx) => waitFor($ctx, 'patronymic')); +$bot->onCbQueryData(['phone'], fn ($ctx) => waitFor($ctx, 'phone')); +$bot->onCbQueryData(['address'], fn ($ctx) => waitFor($ctx, 'address')); +$bot->onCbQueryData(['year'], fn ($ctx) => waitFor($ctx, 'year')); +$bot->onCbQueryData(['month'], fn ($ctx) => waitFor($ctx, 'month')); +$bot->onCbQueryData(['day'], fn ($ctx) => waitFor($ctx, 'day')); +$bot->onCbQueryData(['data'], fn ($ctx) => waitFor($ctx, 'data')); +$bot->onCbQueryData(['cover'], fn ($ctx) => waitFor($ctx, 'cover')); + +$bot->onCbQueryData(['delete_field'], fn ($ctx) => deleteField($ctx)); + +$bot->onCommand('stop', fn ($ctx) => stopProcess($ctx)); +$bot->onCbQueryData(['stop'], fn ($ctx) => stopProcess($ctx)); + +$bot->onCommand('complete', fn ($ctx) => startSearch($ctx)); +$bot->onCbQueryData(['complete'], fn ($ctx) => startSearch($ctx)); + +$bot->run(); diff --git a/mirzaev/telegram/registry/people/system/settings/.gitignore b/mirzaev/telegram/registry/people/system/settings/.gitignore new file mode 100644 index 0000000..2027072 --- /dev/null +++ b/mirzaev/telegram/registry/people/system/settings/.gitignore @@ -0,0 +1,3 @@ +* +!.gitignore +!*.sample diff --git a/mirzaev/telegram/registry/people/system/settings/key.php.sample b/mirzaev/telegram/registry/people/system/settings/key.php.sample new file mode 100644 index 0000000..106ab10 --- /dev/null +++ b/mirzaev/telegram/registry/people/system/settings/key.php.sample @@ -0,0 +1,3 @@ +