From 5de4881a5989b0f399f3cea18992a41b137d1836 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 4 Jun 2023 08:18:29 +0000 Subject: [PATCH] first init --- .gitignore | 1 + LICENSE | 11 + README.md | 8 + START | 1 + composer.json | 25 + composer.lock | 1795 +++++++++++++++++ import.sql | 162 ++ levenshtein.sql | 70 + .../registry/people/system/public/.gitignore | 1 + .../registry/people/system/public/robot.php | 706 +++++++ .../people/system/settings/.gitignore | 3 + .../people/system/settings/key.php.sample | 3 + .../people/system/settings/storage.php.sample | 3 + 13 files changed, 2789 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 START create mode 100644 composer.json create mode 100644 composer.lock create mode 100644 import.sql create mode 100644 levenshtein.sql create mode 100644 mirzaev/telegram/registry/people/system/public/.gitignore create mode 100644 mirzaev/telegram/registry/people/system/public/robot.php create mode 100644 mirzaev/telegram/registry/people/system/settings/.gitignore create mode 100644 mirzaev/telegram/registry/people/system/settings/key.php.sample create mode 100644 mirzaev/telegram/registry/people/system/settings/storage.php.sample 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 @@ +