WIP: Symfony 6 project remake #2
1
.env
1
.env
|
@ -38,3 +38,4 @@ APP_CRAWLER_SECRET=some_secret_for_crawler_change_it_right_away
|
||||||
|
|
||||||
# Telegram Bot settings
|
# Telegram Bot settings
|
||||||
TELEGRAM_BOT_TOKEN=123:abc
|
TELEGRAM_BOT_TOKEN=123:abc
|
||||||
|
TELEGRAM_WEBHOOK_MAX_CONNECTIONS=2
|
||||||
|
|
|
@ -37,9 +37,9 @@
|
||||||
"symfony/twig-bundle": "6.2.*",
|
"symfony/twig-bundle": "6.2.*",
|
||||||
"symfony/validator": "6.2.*",
|
"symfony/validator": "6.2.*",
|
||||||
"symfony/yaml": "6.2.*",
|
"symfony/yaml": "6.2.*",
|
||||||
|
"telegram-bot/api": "^2.3",
|
||||||
"twig/extra-bundle": "^2.12|^3.0",
|
"twig/extra-bundle": "^2.12|^3.0",
|
||||||
"twig/twig": "^2.12|^3.0",
|
"twig/twig": "^2.12|^3.0"
|
||||||
"unreal4u/telegram-api": "*"
|
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"allow-plugins": {
|
"allow-plugins": {
|
||||||
|
|
607
composer.lock
generated
607
composer.lock
generated
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "8d586ece7c8c5b193ba055d36ad7f285",
|
"content-hash": "fa19d360fa749ba51772278ee535bbb3",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "doctrine/annotations",
|
"name": "doctrine/annotations",
|
||||||
|
@ -1555,315 +1555,6 @@
|
||||||
},
|
},
|
||||||
"time": "2022-05-23T21:33:49+00:00"
|
"time": "2022-05-23T21:33:49+00:00"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "guzzlehttp/guzzle",
|
|
||||||
"version": "6.5.8",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/guzzle/guzzle.git",
|
|
||||||
"reference": "a52f0440530b54fa079ce76e8c5d196a42cad981"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/a52f0440530b54fa079ce76e8c5d196a42cad981",
|
|
||||||
"reference": "a52f0440530b54fa079ce76e8c5d196a42cad981",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"ext-json": "*",
|
|
||||||
"guzzlehttp/promises": "^1.0",
|
|
||||||
"guzzlehttp/psr7": "^1.9",
|
|
||||||
"php": ">=5.5",
|
|
||||||
"symfony/polyfill-intl-idn": "^1.17"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"ext-curl": "*",
|
|
||||||
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0",
|
|
||||||
"psr/log": "^1.1"
|
|
||||||
},
|
|
||||||
"suggest": {
|
|
||||||
"psr/log": "Required for using the Log middleware"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"extra": {
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-master": "6.5-dev"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"files": [
|
|
||||||
"src/functions_include.php"
|
|
||||||
],
|
|
||||||
"psr-4": {
|
|
||||||
"GuzzleHttp\\": "src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Graham Campbell",
|
|
||||||
"email": "hello@gjcampbell.co.uk",
|
|
||||||
"homepage": "https://github.com/GrahamCampbell"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Michael Dowling",
|
|
||||||
"email": "mtdowling@gmail.com",
|
|
||||||
"homepage": "https://github.com/mtdowling"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Jeremy Lindblom",
|
|
||||||
"email": "jeremeamia@gmail.com",
|
|
||||||
"homepage": "https://github.com/jeremeamia"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "George Mponos",
|
|
||||||
"email": "gmponos@gmail.com",
|
|
||||||
"homepage": "https://github.com/gmponos"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Tobias Nyholm",
|
|
||||||
"email": "tobias.nyholm@gmail.com",
|
|
||||||
"homepage": "https://github.com/Nyholm"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Márk Sági-Kazár",
|
|
||||||
"email": "mark.sagikazar@gmail.com",
|
|
||||||
"homepage": "https://github.com/sagikazarmark"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Tobias Schultze",
|
|
||||||
"email": "webmaster@tubo-world.de",
|
|
||||||
"homepage": "https://github.com/Tobion"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Guzzle is a PHP HTTP client library",
|
|
||||||
"homepage": "http://guzzlephp.org/",
|
|
||||||
"keywords": [
|
|
||||||
"client",
|
|
||||||
"curl",
|
|
||||||
"framework",
|
|
||||||
"http",
|
|
||||||
"http client",
|
|
||||||
"rest",
|
|
||||||
"web service"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/guzzle/guzzle/issues",
|
|
||||||
"source": "https://github.com/guzzle/guzzle/tree/6.5.8"
|
|
||||||
},
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"url": "https://github.com/GrahamCampbell",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://github.com/Nyholm",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle",
|
|
||||||
"type": "tidelift"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"time": "2022-06-20T22:16:07+00:00"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "guzzlehttp/promises",
|
|
||||||
"version": "1.5.2",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/guzzle/promises.git",
|
|
||||||
"reference": "b94b2807d85443f9719887892882d0329d1e2598"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/guzzle/promises/zipball/b94b2807d85443f9719887892882d0329d1e2598",
|
|
||||||
"reference": "b94b2807d85443f9719887892882d0329d1e2598",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": ">=5.5"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"symfony/phpunit-bridge": "^4.4 || ^5.1"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"extra": {
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-master": "1.5-dev"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"files": [
|
|
||||||
"src/functions_include.php"
|
|
||||||
],
|
|
||||||
"psr-4": {
|
|
||||||
"GuzzleHttp\\Promise\\": "src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Graham Campbell",
|
|
||||||
"email": "hello@gjcampbell.co.uk",
|
|
||||||
"homepage": "https://github.com/GrahamCampbell"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Michael Dowling",
|
|
||||||
"email": "mtdowling@gmail.com",
|
|
||||||
"homepage": "https://github.com/mtdowling"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Tobias Nyholm",
|
|
||||||
"email": "tobias.nyholm@gmail.com",
|
|
||||||
"homepage": "https://github.com/Nyholm"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Tobias Schultze",
|
|
||||||
"email": "webmaster@tubo-world.de",
|
|
||||||
"homepage": "https://github.com/Tobion"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Guzzle promises library",
|
|
||||||
"keywords": [
|
|
||||||
"promise"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/guzzle/promises/issues",
|
|
||||||
"source": "https://github.com/guzzle/promises/tree/1.5.2"
|
|
||||||
},
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"url": "https://github.com/GrahamCampbell",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://github.com/Nyholm",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises",
|
|
||||||
"type": "tidelift"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"time": "2022-08-28T14:55:35+00:00"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "guzzlehttp/psr7",
|
|
||||||
"version": "1.9.0",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/guzzle/psr7.git",
|
|
||||||
"reference": "e98e3e6d4f86621a9b75f623996e6bbdeb4b9318"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/e98e3e6d4f86621a9b75f623996e6bbdeb4b9318",
|
|
||||||
"reference": "e98e3e6d4f86621a9b75f623996e6bbdeb4b9318",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": ">=5.4.0",
|
|
||||||
"psr/http-message": "~1.0",
|
|
||||||
"ralouphie/getallheaders": "^2.0.5 || ^3.0.0"
|
|
||||||
},
|
|
||||||
"provide": {
|
|
||||||
"psr/http-message-implementation": "1.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"ext-zlib": "*",
|
|
||||||
"phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.10"
|
|
||||||
},
|
|
||||||
"suggest": {
|
|
||||||
"laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"extra": {
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-master": "1.9-dev"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"files": [
|
|
||||||
"src/functions_include.php"
|
|
||||||
],
|
|
||||||
"psr-4": {
|
|
||||||
"GuzzleHttp\\Psr7\\": "src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Graham Campbell",
|
|
||||||
"email": "hello@gjcampbell.co.uk",
|
|
||||||
"homepage": "https://github.com/GrahamCampbell"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Michael Dowling",
|
|
||||||
"email": "mtdowling@gmail.com",
|
|
||||||
"homepage": "https://github.com/mtdowling"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "George Mponos",
|
|
||||||
"email": "gmponos@gmail.com",
|
|
||||||
"homepage": "https://github.com/gmponos"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Tobias Nyholm",
|
|
||||||
"email": "tobias.nyholm@gmail.com",
|
|
||||||
"homepage": "https://github.com/Nyholm"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Márk Sági-Kazár",
|
|
||||||
"email": "mark.sagikazar@gmail.com",
|
|
||||||
"homepage": "https://github.com/sagikazarmark"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Tobias Schultze",
|
|
||||||
"email": "webmaster@tubo-world.de",
|
|
||||||
"homepage": "https://github.com/Tobion"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "PSR-7 message implementation that also provides common utility methods",
|
|
||||||
"keywords": [
|
|
||||||
"http",
|
|
||||||
"message",
|
|
||||||
"psr-7",
|
|
||||||
"request",
|
|
||||||
"response",
|
|
||||||
"stream",
|
|
||||||
"uri",
|
|
||||||
"url"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/guzzle/psr7/issues",
|
|
||||||
"source": "https://github.com/guzzle/psr7/tree/1.9.0"
|
|
||||||
},
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"url": "https://github.com/GrahamCampbell",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://github.com/Nyholm",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7",
|
|
||||||
"type": "tidelift"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"time": "2022-06-20T21:43:03+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "jms/metadata",
|
"name": "jms/metadata",
|
||||||
"version": "2.8.0",
|
"version": "2.8.0",
|
||||||
|
@ -2734,59 +2425,6 @@
|
||||||
},
|
},
|
||||||
"time": "2019-01-08T18:20:26+00:00"
|
"time": "2019-01-08T18:20:26+00:00"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "psr/http-message",
|
|
||||||
"version": "1.0.1",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/php-fig/http-message.git",
|
|
||||||
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
|
|
||||||
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": ">=5.3.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": "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/master"
|
|
||||||
},
|
|
||||||
"time": "2016-08-06T14:39:51+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "psr/log",
|
"name": "psr/log",
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
|
@ -2837,50 +2475,6 @@
|
||||||
},
|
},
|
||||||
"time": "2021-07-14T16:46:02+00:00"
|
"time": "2021-07-14T16:46:02+00:00"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "ralouphie/getallheaders",
|
|
||||||
"version": "3.0.3",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/ralouphie/getallheaders.git",
|
|
||||||
"reference": "120b605dfeb996808c31b6477290a714d356e822"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
|
|
||||||
"reference": "120b605dfeb996808c31b6477290a714d356e822",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": ">=5.6"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"php-coveralls/php-coveralls": "^2.1",
|
|
||||||
"phpunit/phpunit": "^5 || ^6.5"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"files": [
|
|
||||||
"src/getallheaders.php"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Ralph Khattar",
|
|
||||||
"email": "ralph.khattar@gmail.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "A polyfill for getallheaders.",
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/ralouphie/getallheaders/issues",
|
|
||||||
"source": "https://github.com/ralouphie/getallheaders/tree/develop"
|
|
||||||
},
|
|
||||||
"time": "2019-03-08T08:55:37+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "sensio/framework-extra-bundle",
|
"name": "sensio/framework-extra-bundle",
|
||||||
"version": "v6.2.10",
|
"version": "v6.2.10",
|
||||||
|
@ -5372,93 +4966,6 @@
|
||||||
],
|
],
|
||||||
"time": "2022-11-03T14:55:06+00:00"
|
"time": "2022-11-03T14:55:06+00:00"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "symfony/polyfill-intl-idn",
|
|
||||||
"version": "v1.27.0",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/symfony/polyfill-intl-idn.git",
|
|
||||||
"reference": "639084e360537a19f9ee352433b84ce831f3d2da"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/639084e360537a19f9ee352433b84ce831f3d2da",
|
|
||||||
"reference": "639084e360537a19f9ee352433b84ce831f3d2da",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": ">=7.1",
|
|
||||||
"symfony/polyfill-intl-normalizer": "^1.10",
|
|
||||||
"symfony/polyfill-php72": "^1.10"
|
|
||||||
},
|
|
||||||
"suggest": {
|
|
||||||
"ext-intl": "For best performance"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"extra": {
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-main": "1.27-dev"
|
|
||||||
},
|
|
||||||
"thanks": {
|
|
||||||
"name": "symfony/polyfill",
|
|
||||||
"url": "https://github.com/symfony/polyfill"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"files": [
|
|
||||||
"bootstrap.php"
|
|
||||||
],
|
|
||||||
"psr-4": {
|
|
||||||
"Symfony\\Polyfill\\Intl\\Idn\\": ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Laurent Bassin",
|
|
||||||
"email": "laurent@bassin.info"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Trevor Rowbotham",
|
|
||||||
"email": "trevor.rowbotham@pm.me"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Symfony Community",
|
|
||||||
"homepage": "https://symfony.com/contributors"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions",
|
|
||||||
"homepage": "https://symfony.com",
|
|
||||||
"keywords": [
|
|
||||||
"compatibility",
|
|
||||||
"idn",
|
|
||||||
"intl",
|
|
||||||
"polyfill",
|
|
||||||
"portable",
|
|
||||||
"shim"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.27.0"
|
|
||||||
},
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"url": "https://symfony.com/sponsor",
|
|
||||||
"type": "custom"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://github.com/fabpot",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
|
||||||
"type": "tidelift"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"time": "2022-11-03T14:55:06+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-intl-normalizer",
|
"name": "symfony/polyfill-intl-normalizer",
|
||||||
"version": "v1.27.0",
|
"version": "v1.27.0",
|
||||||
|
@ -7274,6 +6781,66 @@
|
||||||
],
|
],
|
||||||
"time": "2023-02-16T09:57:23+00:00"
|
"time": "2023-02-16T09:57:23+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "telegram-bot/api",
|
||||||
|
"version": "v2.3.25",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/TelegramBot/Api.git",
|
||||||
|
"reference": "7a534219842ad59835eb89909ca58f8b8e3223a0"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/TelegramBot/Api/zipball/7a534219842ad59835eb89909ca58f8b8e3223a0",
|
||||||
|
"reference": "7a534219842ad59835eb89909ca58f8b8e3223a0",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-curl": "*",
|
||||||
|
"php": ">=5.5.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"codeception/codeception": "*",
|
||||||
|
"phpunit/phpunit": "~4.0",
|
||||||
|
"squizlabs/php_codesniffer": "2.*"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "1.0-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"TelegramBot\\Api\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Ilya Gusev",
|
||||||
|
"email": "mail@igusev.ru",
|
||||||
|
"homepage": "https://php-cat.com",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "PHP Wrapper for Telegram Bot API",
|
||||||
|
"homepage": "https://github.com/TelegramBot/Api",
|
||||||
|
"keywords": [
|
||||||
|
"bot",
|
||||||
|
"bot api",
|
||||||
|
"php",
|
||||||
|
"telegram"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/TelegramBot/Api/issues",
|
||||||
|
"source": "https://github.com/TelegramBot/Api/tree/v2.3.25"
|
||||||
|
},
|
||||||
|
"time": "2023-03-06T10:06:04+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "twig/extra-bundle",
|
"name": "twig/extra-bundle",
|
||||||
"version": "v3.5.1",
|
"version": "v3.5.1",
|
||||||
|
@ -7429,58 +6996,6 @@
|
||||||
],
|
],
|
||||||
"time": "2023-02-08T07:49:20+00:00"
|
"time": "2023-02-08T07:49:20+00:00"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "unreal4u/telegram-api",
|
|
||||||
"version": "v1.1.1",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/unreal4u/telegram-api.git",
|
|
||||||
"reference": "501a02062942fb533bbcdf6f9f538368208db65a"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/unreal4u/telegram-api/zipball/501a02062942fb533bbcdf6f9f538368208db65a",
|
|
||||||
"reference": "501a02062942fb533bbcdf6f9f538368208db65a",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"guzzlehttp/guzzle": "~6.0",
|
|
||||||
"php": ">=7.0.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"phpmd/phpmd": "@stable",
|
|
||||||
"phpunit/phpunit": "@stable",
|
|
||||||
"squizlabs/php_codesniffer": "@stable"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"unreal4u\\": "src"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Camilo Sperberg",
|
|
||||||
"email": "me@unreal4u.com",
|
|
||||||
"homepage": "https://github.com/unreal4u/telegram-api/graphs/contributors"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Complete implementation used to communicate with the open-source Telegram API",
|
|
||||||
"keywords": [
|
|
||||||
"api",
|
|
||||||
"telegram",
|
|
||||||
"telegram bot"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/unreal4u/telegram-api/issues",
|
|
||||||
"source": "https://github.com/unreal4u/telegram-api/tree/master"
|
|
||||||
},
|
|
||||||
"time": "2016-01-26T21:46:33+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "webmozart/assert",
|
"name": "webmozart/assert",
|
||||||
"version": "1.11.0",
|
"version": "1.11.0",
|
||||||
|
|
|
@ -4,6 +4,14 @@
|
||||||
# Put parameters here that don't need to change on each machine where the app is deployed
|
# Put parameters here that don't need to change on each machine where the app is deployed
|
||||||
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
|
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
|
||||||
parameters:
|
parameters:
|
||||||
|
env(APP_POINT_SCHEME): 'https'
|
||||||
|
env(APP_POINT_DOMAIN): 'point.im'
|
||||||
|
env(APP_POINT_BASE_URL): 'https://point.im'
|
||||||
|
env(APP_POINT_API_DELAY): 5000
|
||||||
|
env(APP_USER_ID): '435'
|
||||||
|
env(APP_USER_LOGIN): 'point-tools'
|
||||||
|
env(TELEGRAM_BOT_TOKEN): 'abc:123'
|
||||||
|
env(APP_CRAWLER_SECRET): 'some_secret_for_crawler_change_it_right_away'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
# default configuration for services in *this* file
|
# default configuration for services in *this* file
|
||||||
|
@ -11,19 +19,19 @@ services:
|
||||||
autowire: true # Automatically injects dependencies in your services.
|
autowire: true # Automatically injects dependencies in your services.
|
||||||
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
|
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
|
||||||
bind:
|
bind:
|
||||||
# Point Tools
|
|
||||||
$appUserId: '%env(int:APP_USER_ID)%'
|
|
||||||
$appUserLogin: 'env(string:APP_USER_LOGIN)'
|
|
||||||
# Telegram Bot API
|
# Telegram Bot API
|
||||||
$telegramToken: 'env(string:TELEGRAM_BOT_TOKEN)'
|
$telegramToken: '%env(string:TELEGRAM_BOT_TOKEN)%'
|
||||||
|
$telegramWebhookMaxConnections: 'env(int:TELEGRAM_WEBHOOK_MAX_CONNECTIONS)'
|
||||||
$debugEnabled: '%kernel.debug%'
|
$debugEnabled: '%kernel.debug%'
|
||||||
# Point API
|
# Point API
|
||||||
$pointDomain: 'env(string:APP_POINT_DOMAIN)'
|
$pointDomain: '%env(string:APP_POINT_DOMAIN)%'
|
||||||
$pointScheme: 'env(string:APP_POINT_SCHEME)'
|
$pointScheme: '%env(string:APP_POINT_SCHEME)%'
|
||||||
$pointApiDelay: '%env(int:APP_POINT_API_DELAY)%'
|
$pointApiDelay: '%env(int:APP_POINT_API_DELAY)%'
|
||||||
$pointApiClient: '@app.point.http_client'
|
$pointApiClient: '@app.point.http_client'
|
||||||
|
$pointAppUserId: '%env(int:APP_USER_ID)%'
|
||||||
|
$pointAppUserLogin: '%env(string:APP_USER_LOGIN)%'
|
||||||
# Crawler API
|
# Crawler API
|
||||||
$crawlerSecret: 'env(string:APP_CRAWLER_SECRET)'
|
$crawlerSecret: '%env(string:APP_CRAWLER_SECRET)%'
|
||||||
|
|
||||||
# makes classes in src/ available to be used as services
|
# makes classes in src/ available to be used as services
|
||||||
# this creates a service per class whose id is the fully-qualified class name
|
# this creates a service per class whose id is the fully-qualified class name
|
||||||
|
@ -39,5 +47,10 @@ services:
|
||||||
class: Symfony\Component\HttpClient\HttpClient
|
class: Symfony\Component\HttpClient\HttpClient
|
||||||
factory: [null, 'create']
|
factory: [null, 'create']
|
||||||
arguments:
|
arguments:
|
||||||
base_uri: '%point_base_url%'
|
-
|
||||||
timeout: 5.0
|
base_uri: '%env(string:APP_POINT_SCHEME)%://%env(string:APP_POINT_DOMAIN)%'
|
||||||
|
timeout: 5.0
|
||||||
|
|
||||||
|
TelegramBot\Api\BotApi:
|
||||||
|
arguments:
|
||||||
|
$token: '%env(string:TELEGRAM_BOT_TOKEN)%'
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace src\PointToolsBundle\Service\Telegram;
|
|
||||||
|
|
||||||
use unreal4u\TelegramAPI\Telegram\Types\{Inline\Query, Message, Update};
|
|
||||||
use src\PointToolsBundle\Service\Telegram\InlineQueryProcessor;
|
|
||||||
use src\PointToolsBundle\Service\Telegram\PrivateMessageProcessor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches incoming messages processing to corresponding services
|
|
||||||
*/
|
|
||||||
class IncomingUpdateDispatcher
|
|
||||||
{
|
|
||||||
const CHAT_TYPE_PRIVATE = 'private';
|
|
||||||
const CHAT_TYPE_GROUP = 'group';
|
|
||||||
|
|
||||||
/** @var InlineQueryProcessor */
|
|
||||||
private $inlineQueryProcessor;
|
|
||||||
|
|
||||||
/** @var PrivateMessageProcessor */
|
|
||||||
private $privateMessageProcessor;
|
|
||||||
|
|
||||||
|
|
||||||
public function __construct(PrivateMessageProcessor $privateMessageProcessor, InlineQueryProcessor $inlineQueryProcessor)
|
|
||||||
{
|
|
||||||
$this->privateMessageProcessor = $privateMessageProcessor;
|
|
||||||
$this->inlineQueryProcessor = $inlineQueryProcessor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes update and delegates it to corresponding service
|
|
||||||
*
|
|
||||||
* @param Update $update
|
|
||||||
*/
|
|
||||||
public function process(Update $update): void
|
|
||||||
{
|
|
||||||
if ($update->message && $update->message instanceof Message) {
|
|
||||||
$chatType = $update->message->chat->type;
|
|
||||||
|
|
||||||
if (self::CHAT_TYPE_PRIVATE === $chatType) {
|
|
||||||
$this->privateMessageProcessor->process($update->message);
|
|
||||||
} elseif (self::CHAT_TYPE_GROUP === $chatType) {
|
|
||||||
// @todo implement
|
|
||||||
}
|
|
||||||
} elseif ($update->inline_query && $update->inline_query instanceof Query) {
|
|
||||||
$this->inlineQueryProcessor->process($update->inline_query);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace src\PointToolsBundle\Service\Telegram;
|
|
||||||
|
|
||||||
use src\PointToolsBundle\Repository\UserRepository;
|
|
||||||
use unreal4u\TelegramAPI\Telegram\Methods\AnswerInlineQuery;
|
|
||||||
use unreal4u\TelegramAPI\Telegram\Types\Inline\Query;
|
|
||||||
use unreal4u\TelegramAPI\Telegram\Types\InputMessageContent\Text;
|
|
||||||
use unreal4u\TelegramAPI\TgLog;
|
|
||||||
use function Skobkin\Bundle\PointToolsBundle\Service\Telegram\mb_strlen;
|
|
||||||
|
|
||||||
class InlineQueryProcessor
|
|
||||||
{
|
|
||||||
/** @var UserRepository */
|
|
||||||
private $userRepo;
|
|
||||||
|
|
||||||
/** @var TgLog */
|
|
||||||
private $client;
|
|
||||||
|
|
||||||
|
|
||||||
public function __construct(UserRepository $userRepository, TgLog $client)
|
|
||||||
{
|
|
||||||
$this->userRepo = $userRepository;
|
|
||||||
$this->client = $client;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function process(Query $inlineQuery): void
|
|
||||||
{
|
|
||||||
if (mb_strlen($inlineQuery->query) < 2) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$answerInlineQuery = new AnswerInlineQuery();
|
|
||||||
$answerInlineQuery->inline_query_id = $inlineQuery->id;
|
|
||||||
|
|
||||||
foreach ($this->userRepo->findUsersLikeLogin($inlineQuery->query) as $user) {
|
|
||||||
$article = new Query\Result\Article();
|
|
||||||
$article->title = $user->getLogin();
|
|
||||||
|
|
||||||
$contentText = new Text();
|
|
||||||
$contentText->message_text = sprintf(
|
|
||||||
"@%s:\nName: %s\nSubscribers: %d",
|
|
||||||
$user->getLogin(),
|
|
||||||
$user->getName(),
|
|
||||||
$user->getSubscribers()->count()
|
|
||||||
);
|
|
||||||
|
|
||||||
$article->input_message_content = $contentText;
|
|
||||||
$article->id = md5($user->getId());
|
|
||||||
|
|
||||||
$answerInlineQuery->addResult($article);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->client->performApiRequest($answerInlineQuery);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace src\PointToolsBundle\Service\Telegram;
|
|
||||||
|
|
||||||
use src\PointToolsBundle\Entity\User;
|
|
||||||
use src\PointToolsBundle\Entity\UserRenameEvent;
|
|
||||||
use src\PointToolsBundle\Service\Telegram\MessageSender;
|
|
||||||
use src\PointToolsBundle\Entity\{Telegram\Account};
|
|
||||||
use src\PointToolsBundle\Repository\Telegram\AccountRepository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notifies Telegram users about some events
|
|
||||||
*/
|
|
||||||
class Notifier
|
|
||||||
{
|
|
||||||
/** @var AccountRepository */
|
|
||||||
private $accountsRepo;
|
|
||||||
|
|
||||||
/** @var MessageSender */
|
|
||||||
private $messenger;
|
|
||||||
|
|
||||||
|
|
||||||
public function __construct(AccountRepository $accountRepository, MessageSender $messenger)
|
|
||||||
{
|
|
||||||
$this->accountsRepo = $accountRepository;
|
|
||||||
$this->messenger = $messenger;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param UserRenameEvent[] $userRenameEvents
|
|
||||||
*/
|
|
||||||
public function sendUsersRenamedNotification(array $userRenameEvents): void
|
|
||||||
{
|
|
||||||
$accounts = $this->accountsRepo->findBy(['renameNotification' => true]);
|
|
||||||
|
|
||||||
$this->messenger->sendMassTemplatedMessage($accounts, '@SkobkinPointTools/Telegram/users_renamed_notification.md.twig', ['events' => $userRenameEvents]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send notification about changes in user's subscribers list
|
|
||||||
*
|
|
||||||
* @param User $user
|
|
||||||
* @param User[] $subscribed
|
|
||||||
* @param User[] $unsubscribed
|
|
||||||
*/
|
|
||||||
public function sendUserSubscribersUpdatedNotification(User $user, array $subscribed, array $unsubscribed): bool
|
|
||||||
{
|
|
||||||
/** @var Account $account */
|
|
||||||
$account = $this->accountsRepo->findOneBy(
|
|
||||||
[
|
|
||||||
'user' => $user,
|
|
||||||
'subscriberNotification' => true,
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
if (null === $account) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->messenger->sendTemplatedMessage(
|
|
||||||
$account,
|
|
||||||
'@SkobkinPointTools/Telegram/user_subscribers_updated_notification.md.twig',
|
|
||||||
[
|
|
||||||
'user' => $user,
|
|
||||||
'subscribed' => $subscribed,
|
|
||||||
'unsubscribed' => $unsubscribed,
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,9 +6,7 @@ namespace App\Command;
|
||||||
use App\Service\Telegram\MessageSender;
|
use App\Service\Telegram\MessageSender;
|
||||||
use Symfony\Component\Console\Attribute\AsCommand;
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
use Symfony\Component\Console\Command\Command;
|
use Symfony\Component\Console\Command\Command;
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
use Symfony\Component\Console\Input\{InputArgument, InputInterface, InputOption};
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
|
|
||||||
|
|
|
@ -5,13 +5,11 @@ namespace App\Command;
|
||||||
|
|
||||||
use Symfony\Component\Console\Attribute\AsCommand;
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
use Symfony\Component\Console\Command\Command;
|
use Symfony\Component\Console\Command\Command;
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
use Symfony\Component\Console\Input\{InputArgument, InputInterface};
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
use unreal4u\Telegram\Methods\SetWebhook;
|
use TelegramBot\Api\BotApi;
|
||||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||||
use unreal4u\TgLog;
|
|
||||||
|
|
||||||
#[AsCommand(name: 'app:telegram:webhook', description: 'Set webhook')]
|
#[AsCommand(name: 'app:telegram:webhook', description: 'Set webhook')]
|
||||||
class TelegramWebhookCommand extends Command
|
class TelegramWebhookCommand extends Command
|
||||||
|
@ -20,7 +18,7 @@ class TelegramWebhookCommand extends Command
|
||||||
private const MODE_DELETE = 'delete';
|
private const MODE_DELETE = 'delete';
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly TgLog $client,
|
private readonly BotApi $client,
|
||||||
private readonly UrlGeneratorInterface $router,
|
private readonly UrlGeneratorInterface $router,
|
||||||
private readonly string $telegramToken,
|
private readonly string $telegramToken,
|
||||||
private readonly int $telegramWebhookMaxConnections,
|
private readonly int $telegramWebhookMaxConnections,
|
||||||
|
@ -49,15 +47,21 @@ class TelegramWebhookCommand extends Command
|
||||||
|
|
||||||
$io->info('Setting webhook: ' . $url);
|
$io->info('Setting webhook: ' . $url);
|
||||||
|
|
||||||
$setWebHook = new SetWebhook();
|
try {
|
||||||
$setWebHook->url = $url;
|
$this->client->setWebhook(
|
||||||
$setWebHook->max_connections = $this->telegramWebhookMaxConnections;
|
url: $url,
|
||||||
|
max_connections: $this->telegramWebhookMaxConnections,
|
||||||
$this->client->performApiRequest($setWebHook);
|
);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$io->error(\sprintf(
|
||||||
|
'setWebhook error: %s',
|
||||||
|
$e->getMessage(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
$output->writeln('Done');
|
$output->writeln('Done');
|
||||||
} elseif (self::MODE_DELETE === strtolower($input->getArgument('mode'))) {
|
} elseif (self::MODE_DELETE === strtolower($input->getArgument('mode'))) {
|
||||||
$io->warning('Unsupported until moving to another library.');
|
$this->client->deleteWebhook();
|
||||||
} else {
|
} else {
|
||||||
throw new \InvalidArgumentException(sprintf('Mode must be exactly one of: %s', implode(', ', [self::MODE_SET, self::MODE_DELETE])));
|
throw new \InvalidArgumentException(sprintf('Mode must be exactly one of: %s', implode(', ', [self::MODE_SET, self::MODE_DELETE])));
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ class UpdateSubscriptionsCommand extends Command
|
||||||
private readonly UserApi $api,
|
private readonly UserApi $api,
|
||||||
private readonly SubscriptionsManager $subscriptionManager,
|
private readonly SubscriptionsManager $subscriptionManager,
|
||||||
private readonly int $pointApiDelay,
|
private readonly int $pointApiDelay,
|
||||||
private readonly int $appUserId,
|
private readonly int $pointAppUserId,
|
||||||
) {
|
) {
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
}
|
}
|
||||||
|
@ -155,9 +155,9 @@ class UpdateSubscriptionsCommand extends Command
|
||||||
} else {
|
} else {
|
||||||
/** @var User $serviceUser */
|
/** @var User $serviceUser */
|
||||||
try {
|
try {
|
||||||
$serviceUser = $this->userRepo->findActiveUserWithSubscribers($this->appUserId);
|
$serviceUser = $this->userRepo->findActiveUserWithSubscribers($this->pointAppUserId);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$this->logger->error('Error while getting active user with subscribers', ['app_user_id' => $this->appUserId]);
|
$this->logger->error('Error while getting active user with subscribers', ['app_user_id' => $this->pointAppUserId]);
|
||||||
|
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
|
@ -166,7 +166,7 @@ class UpdateSubscriptionsCommand extends Command
|
||||||
$this->logger->warning('Service user not found or marked as removed. Falling back to API.');
|
$this->logger->warning('Service user not found or marked as removed. Falling back to API.');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$serviceUser = $this->api->getUserById($this->appUserId);
|
$serviceUser = $this->api->getUserById($this->pointAppUserId);
|
||||||
} catch (UserNotFoundException $e) {
|
} catch (UserNotFoundException $e) {
|
||||||
throw new \RuntimeException('Service user not found in the database and could not be retrieved from API.');
|
throw new \RuntimeException('Service user not found in the database and could not be retrieved from API.');
|
||||||
}
|
}
|
||||||
|
@ -175,7 +175,7 @@ class UpdateSubscriptionsCommand extends Command
|
||||||
$this->logger->info('Getting service subscribers');
|
$this->logger->info('Getting service subscribers');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$usersForUpdate = $this->api->getUserSubscribersById($this->appUserId);
|
$usersForUpdate = $this->api->getUserSubscribersById($this->pointAppUserId);
|
||||||
} catch (UserNotFoundException $e) {
|
} catch (UserNotFoundException $e) {
|
||||||
$this->logger->critical('Service user deleted or API response is invalid');
|
$this->logger->critical('Service user deleted or API response is invalid');
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,7 @@ declare(strict_types=1);
|
||||||
namespace App\Command;
|
namespace App\Command;
|
||||||
|
|
||||||
use App\Entity\User;
|
use App\Entity\User;
|
||||||
use App\Exception\Api\ForbiddenException;
|
use App\Exception\Api\{ForbiddenException, UserNotFoundException};
|
||||||
use App\Exception\Api\UserNotFoundException;
|
|
||||||
use App\Repository\UserRepository;
|
use App\Repository\UserRepository;
|
||||||
use App\Service\Api\UserApi;
|
use App\Service\Api\UserApi;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
@ -13,8 +12,7 @@ use Psr\Log\LoggerInterface;
|
||||||
use Symfony\Component\Console\Attribute\AsCommand;
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
use Symfony\Component\Console\Command\Command;
|
use Symfony\Component\Console\Command\Command;
|
||||||
use Symfony\Component\Console\Helper\ProgressBar;
|
use Symfony\Component\Console\Helper\ProgressBar;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\{InputInterface, InputOption};
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
|
|
||||||
|
@ -23,11 +21,11 @@ class UpdateUsersPrivacyCommand extends Command
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly EntityManagerInterface $em,
|
private readonly EntityManagerInterface $em,
|
||||||
private readonly LoggerInterface $logger,
|
private readonly LoggerInterface $logger,
|
||||||
private readonly UserRepository $userRepo,
|
private readonly UserRepository $userRepo,
|
||||||
private readonly UserApi $api,
|
private readonly UserApi $api,
|
||||||
private readonly int $pointApiDelay,
|
private readonly int $pointApiDelay,
|
||||||
private readonly int $pointAppUserId,
|
private readonly int $pointAppUserId,
|
||||||
) {
|
) {
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,8 +14,8 @@ class MainController extends AbstractController
|
||||||
private const AJAX_AUTOCOMPLETE_SIZE = 10;
|
private const AJAX_AUTOCOMPLETE_SIZE = 10;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly int $appUserId,
|
private readonly int $pointAppUserId,
|
||||||
private readonly string $appUserLogin,
|
private readonly string $pointAppUserLogin,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,9 +49,9 @@ class MainController extends AbstractController
|
||||||
'form' => $form->createView(),
|
'form' => $form->createView(),
|
||||||
'autocomplete_size' => self::AJAX_AUTOCOMPLETE_SIZE,
|
'autocomplete_size' => self::AJAX_AUTOCOMPLETE_SIZE,
|
||||||
'users_count' => $userRepository->getUsersCount(),
|
'users_count' => $userRepository->getUsersCount(),
|
||||||
'subscribers_count' => $subscriptionRepository->getUserSubscribersCountById($this->appUserId),
|
'subscribers_count' => $subscriptionRepository->getUserSubscribersCountById($this->pointAppUserId),
|
||||||
'events_count' => $subscriptionEventRepository->getLastDayEventsCount(),
|
'events_count' => $subscriptionEventRepository->getLastDayEventsCount(),
|
||||||
'service_login' => $this->appUserLogin,
|
'service_login' => $this->pointAppUserLogin,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,11 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace App\Controller\Telegram;
|
namespace App\Controller\Telegram;
|
||||||
|
|
||||||
|
use App\Service\Telegram\IncomingUpdateDispatcher;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
use src\PointToolsBundle\Service\Telegram\IncomingUpdateDispatcher;
|
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
use Symfony\Component\HttpFoundation\{JsonResponse, Request, Response};
|
use Symfony\Component\HttpFoundation\{JsonResponse, Request, Response};
|
||||||
use unreal4u\Telegram\Types\Update;
|
use TelegramBot\Api\Types\Update;
|
||||||
|
|
||||||
class WebHookController extends AbstractController
|
class WebHookController extends AbstractController
|
||||||
{
|
{
|
||||||
|
@ -23,11 +23,13 @@ class WebHookController extends AbstractController
|
||||||
throw $this->createNotFoundException();
|
throw $this->createNotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
$content = \json_decode($request->getContent(), flags: JSON_THROW_ON_ERROR);
|
try {
|
||||||
|
$content = \json_decode($request->getContent(), flags: JSON_THROW_ON_ERROR);
|
||||||
|
} catch (\JsonException $e) {
|
||||||
|
return new JsonResponse('bad json', JsonResponse::HTTP_UNPROCESSABLE_ENTITY);
|
||||||
|
}
|
||||||
|
|
||||||
$update = new Update(
|
$update = Update::fromResponse($content);
|
||||||
$content,
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$updateDispatcher->process($update);
|
$updateDispatcher->process($update);
|
||||||
|
|
12
src/Enum/Telegram/ChatTypeEnum.php
Normal file
12
src/Enum/Telegram/ChatTypeEnum.php
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Enum\Telegram;
|
||||||
|
|
||||||
|
enum ChatTypeEnum: string
|
||||||
|
{
|
||||||
|
case Private = 'private';
|
||||||
|
case Group = 'group';
|
||||||
|
case SuperGroup = 'supergroup';
|
||||||
|
case Channel = 'channel';
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ use App\Factory\AbstractFactory;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
use App\Entity\Telegram\Account;
|
use App\Entity\Telegram\Account;
|
||||||
use App\Repository\Telegram\AccountRepository;
|
use App\Repository\Telegram\AccountRepository;
|
||||||
use unreal4u\Telegram\Types\Message;
|
use TelegramBot\Api\Types\Message;
|
||||||
|
|
||||||
class AccountFactory extends AbstractFactory
|
class AccountFactory extends AbstractFactory
|
||||||
{
|
{
|
||||||
|
@ -20,17 +20,16 @@ class AccountFactory extends AbstractFactory
|
||||||
|
|
||||||
public function findOrCreateFromMessage(Message $message): Account
|
public function findOrCreateFromMessage(Message $message): Account
|
||||||
{
|
{
|
||||||
if (null === $account = $this->accountRepository->findOneBy(['id' => $message->from->id])) {
|
if (null === $account = $this->accountRepository->findOneBy(['id' => $message->getFrom()->getId()])) {
|
||||||
$account = new Account($message->from->id);
|
$account = new Account($message->getFrom()->getId());
|
||||||
$this->accountRepository->save($account);
|
$this->accountRepository->save($account);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setting/updating account data
|
|
||||||
$account->updateFromMessageData(
|
$account->updateFromMessageData(
|
||||||
$message->from->first_name,
|
$message->getFrom()->getFirstName(),
|
||||||
$message->from->last_name,
|
$message->getFrom()->getLastName(),
|
||||||
$message->from->username,
|
$message->getFrom()->getUsername(),
|
||||||
$message->chat->id
|
$message->getFrom()->getId(),
|
||||||
);
|
);
|
||||||
|
|
||||||
return $account;
|
return $account;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace App\Repository\Telegram;
|
namespace App\Repository\Telegram;
|
||||||
|
|
37
src/Service/Telegram/IncomingUpdateDispatcher.php
Normal file
37
src/Service/Telegram/IncomingUpdateDispatcher.php
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Service\Telegram;
|
||||||
|
|
||||||
|
use App\Enum\Telegram\ChatTypeEnum;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
use TelegramBot\Api\Types\Update;
|
||||||
|
|
||||||
|
/** Dispatches incoming messages processing to corresponding services */
|
||||||
|
class IncomingUpdateDispatcher
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly PrivateMessageProcessor $privateMessageProcessor,
|
||||||
|
private readonly InlineQueryProcessor $inlineQueryProcessor,
|
||||||
|
private readonly LoggerInterface $log,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function process(Update $update): void
|
||||||
|
{
|
||||||
|
if ($update->getMessage() && $update->getMessage()->getText()) {
|
||||||
|
$chatType = $update->getMessage()->getChat()->getType();
|
||||||
|
match (ChatTypeEnum::tryFrom($chatType)) {
|
||||||
|
ChatTypeEnum::Private => $this->privateMessageProcessor->process($update),
|
||||||
|
default => $this->log->info(\sprintf(
|
||||||
|
'Unsupported message type \'%s\' received.\n %s\n %s',
|
||||||
|
$chatType,
|
||||||
|
$update->getMessage()->getChat()->getId(),
|
||||||
|
$update->getMessage()->getText(),
|
||||||
|
))
|
||||||
|
};
|
||||||
|
} elseif ($update->getInlineQuery()) {
|
||||||
|
$this->inlineQueryProcessor->process($update->getInlineQuery());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
52
src/Service/Telegram/InlineQueryProcessor.php
Normal file
52
src/Service/Telegram/InlineQueryProcessor.php
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Service\Telegram;
|
||||||
|
|
||||||
|
use App\Repository\UserRepository;
|
||||||
|
use TelegramBot\Api\BotApi;
|
||||||
|
use TelegramBot\Api\Types\Inline\InlineQuery;
|
||||||
|
use TelegramBot\Api\Types\Inline\InputMessageContent\Text;
|
||||||
|
use TelegramBot\Api\Types\Inline\QueryResult\Article;
|
||||||
|
|
||||||
|
class InlineQueryProcessor
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly UserRepository $userRepo,
|
||||||
|
private readonly BotApi $client,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function process(InlineQuery $inlineQuery): void
|
||||||
|
{
|
||||||
|
$text = $inlineQuery->getQuery();
|
||||||
|
|
||||||
|
if (\mb_strlen($text) < 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$results = [];
|
||||||
|
|
||||||
|
foreach ($this->userRepo->findUsersLikeLogin($text) as $key => $user) {
|
||||||
|
$results[] = new Article(
|
||||||
|
id: \hash('md5', (string) $user->getId()),
|
||||||
|
title: $user->getLogin(),
|
||||||
|
inputMessageContent: new Text(
|
||||||
|
messageText: \sprintf(
|
||||||
|
"@%s:\nName: %s\nSubscribers: %d",
|
||||||
|
$user->getLogin(),
|
||||||
|
$user->getName(),
|
||||||
|
$user->getSubscribers()->count()
|
||||||
|
),
|
||||||
|
parseMode: MessageSender::PARSE_PLAIN,
|
||||||
|
disableWebPagePreview: true,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->client->answerInlineQuery(
|
||||||
|
$inlineQuery->getId(),
|
||||||
|
$results,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,54 +1,37 @@
|
||||||
<?php
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace src\PointToolsBundle\Service\Telegram;
|
namespace App\Service\Telegram;
|
||||||
|
|
||||||
use GuzzleHttp\Exception\ClientException;
|
use App\Entity\Telegram\Account;
|
||||||
use src\PointToolsBundle\Entity\Telegram\Account;
|
use Psr\Log\LoggerInterface;
|
||||||
use unreal4u\TelegramAPI\Abstracts\KeyboardMethods;
|
use TelegramBot\Api\BotApi;
|
||||||
use unreal4u\TelegramAPI\Telegram\Methods\SendMessage;
|
use TelegramBot\Api\Types\ReplyKeyboardMarkup;
|
||||||
use unreal4u\TelegramAPI\TgLog;
|
use Twig\Environment;
|
||||||
|
|
||||||
/**
|
|
||||||
* Service which sends simple messages to Telegram users
|
|
||||||
*/
|
|
||||||
class MessageSender
|
class MessageSender
|
||||||
{
|
{
|
||||||
public const PARSE_PLAIN = '';
|
public const PARSE_PLAIN = '';
|
||||||
public const PARSE_MARKDOWN = 'Markdown';
|
public const PARSE_MARKDOWN = 'Markdown';
|
||||||
public const PARSE_HTML5 = 'HTML';
|
public const PARSE_MARKDOWN_V2 = 'MarkdownV2';
|
||||||
|
public const PARSE_HTML = 'HTML';
|
||||||
|
|
||||||
/** @var TgLog */
|
public function __construct(
|
||||||
private $client;
|
private readonly BotApi $client,
|
||||||
|
private readonly Environment $twig,
|
||||||
/** @var \Twig_Environment */
|
private readonly LoggerInterface $log,
|
||||||
private $twig;
|
) {
|
||||||
|
|
||||||
/**
|
|
||||||
* @param TgLog $client
|
|
||||||
*/
|
|
||||||
public function __construct(TgLog $client, \Twig_Environment $twig)
|
|
||||||
{
|
|
||||||
$this->client = $client;
|
|
||||||
$this->twig = $twig;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @param Account[] $accounts */
|
||||||
* @param Account[] $accounts
|
|
||||||
* @param string $template
|
|
||||||
* @param array $templateData
|
|
||||||
* @param KeyboardMethods|null $keyboardMarkup
|
|
||||||
* @param bool $disableWebPreview
|
|
||||||
* @param bool $disableNotifications
|
|
||||||
* @param string $parseMode
|
|
||||||
*/
|
|
||||||
public function sendMassTemplatedMessage(
|
public function sendMassTemplatedMessage(
|
||||||
array $accounts,
|
array $accounts,
|
||||||
string $template,
|
string $template,
|
||||||
array $templateData = [],
|
array $templateData = [],
|
||||||
KeyboardMethods $keyboardMarkup = null,
|
ReplyKeyboardMarkup $keyboardMarkup = null,
|
||||||
bool $disableWebPreview = true,
|
bool $disableWebPreview = true,
|
||||||
bool $disableNotifications = false,
|
bool $disableNotifications = false,
|
||||||
string $parseMode = self::PARSE_MARKDOWN
|
string $parseMode = self::PARSE_MARKDOWN_V2
|
||||||
): void
|
): void
|
||||||
{
|
{
|
||||||
$text = $this->twig->render($template, $templateData);
|
$text = $this->twig->render($template, $templateData);
|
||||||
|
@ -62,10 +45,10 @@ class MessageSender
|
||||||
Account $account,
|
Account $account,
|
||||||
string $template,
|
string $template,
|
||||||
array $templateData = [],
|
array $templateData = [],
|
||||||
KeyboardMethods $keyboardMarkup = null,
|
ReplyKeyboardMarkup $keyboardMarkup = null,
|
||||||
bool $disableWebPreview = true,
|
bool $disableWebPreview = true,
|
||||||
bool $disableNotifications = false,
|
bool $disableNotifications = false,
|
||||||
string $parseMode = self::PARSE_MARKDOWN
|
string $parseMode = self::PARSE_MARKDOWN_V2
|
||||||
): bool
|
): bool
|
||||||
{
|
{
|
||||||
$text = $this->twig->render($template, $templateData);
|
$text = $this->twig->render($template, $templateData);
|
||||||
|
@ -77,7 +60,7 @@ class MessageSender
|
||||||
Account $account,
|
Account $account,
|
||||||
string $text,
|
string $text,
|
||||||
string $parseMode = self::PARSE_PLAIN,
|
string $parseMode = self::PARSE_PLAIN,
|
||||||
KeyboardMethods $keyboardMarkup = null,
|
ReplyKeyboardMarkup $keyboardMarkup = null,
|
||||||
bool $disableWebPreview = false,
|
bool $disableWebPreview = false,
|
||||||
bool $disableNotifications = false
|
bool $disableNotifications = false
|
||||||
): bool
|
): bool
|
||||||
|
@ -89,25 +72,29 @@ class MessageSender
|
||||||
int $chatId,
|
int $chatId,
|
||||||
string $text,
|
string $text,
|
||||||
string $parseMode = self::PARSE_PLAIN,
|
string $parseMode = self::PARSE_PLAIN,
|
||||||
KeyboardMethods $keyboardMarkup = null,
|
ReplyKeyboardMarkup $keyboardMarkup = null,
|
||||||
bool $disableWebPreview = false,
|
bool $disableWebPreview = false,
|
||||||
bool $disableNotifications = false
|
bool $disableNotifications = false
|
||||||
): bool
|
): bool
|
||||||
{
|
{
|
||||||
$sendMessage = new SendMessage();
|
|
||||||
$sendMessage->chat_id = (string)$chatId;
|
|
||||||
$sendMessage->text = $text;
|
|
||||||
$sendMessage->parse_mode = $parseMode;
|
|
||||||
$sendMessage->disable_web_page_preview = $disableWebPreview;
|
|
||||||
$sendMessage->disable_notification = $disableNotifications;
|
|
||||||
$sendMessage->reply_markup = $keyboardMarkup;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->client->performApiRequest($sendMessage);
|
$this->client->sendMessage(
|
||||||
|
chatId: (string) $chatId,
|
||||||
|
text: $text,
|
||||||
|
parseMode: $parseMode,
|
||||||
|
disablePreview: $disableWebPreview,
|
||||||
|
replyMarkup: $keyboardMarkup,
|
||||||
|
disableNotification: $disableNotifications,
|
||||||
|
);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (ClientException $e) {
|
} catch (\Exception $e) {
|
||||||
|
$this->log->error('sendMessageToChat', [
|
||||||
|
'error' => $e->getMessage(),
|
||||||
|
'file' => $e->getFile() . ':' . $e->getLine(),
|
||||||
|
]);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
55
src/Service/Telegram/Notifier.php
Normal file
55
src/Service/Telegram/Notifier.php
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Service\Telegram;
|
||||||
|
|
||||||
|
use App\Entity\{User, UserRenameEvent};
|
||||||
|
use App\Repository\Telegram\AccountRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies Telegram users about some events
|
||||||
|
*/
|
||||||
|
class Notifier
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly AccountRepository $accountsRepo,
|
||||||
|
private readonly MessageSender $messenger,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param UserRenameEvent[] $userRenameEvents */
|
||||||
|
public function sendUsersRenamedNotification(array $userRenameEvents): void
|
||||||
|
{
|
||||||
|
$accounts = $this->accountsRepo->findBy(['renameNotification' => true]);
|
||||||
|
|
||||||
|
$this->messenger->sendMassTemplatedMessage($accounts, 'Telegram/users_renamed_notification.md.twig', ['events' => $userRenameEvents]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param User[] $subscribed
|
||||||
|
* @param User[] $unsubscribed
|
||||||
|
*/
|
||||||
|
public function sendUserSubscribersUpdatedNotification(User $user, array $subscribed, array $unsubscribed): bool
|
||||||
|
{
|
||||||
|
$account = $this->accountsRepo->findOneBy(
|
||||||
|
[
|
||||||
|
'user' => $user,
|
||||||
|
'subscriberNotification' => true,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
if (null === $account) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->messenger->sendTemplatedMessage(
|
||||||
|
$account,
|
||||||
|
'Telegram/user_subscribers_updated_notification.md.twig',
|
||||||
|
[
|
||||||
|
'user' => $user,
|
||||||
|
'subscribed' => $subscribed,
|
||||||
|
'unsubscribed' => $unsubscribed,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,139 +1,70 @@
|
||||||
<?php
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace src\PointToolsBundle\Service\Telegram;
|
namespace App\Service\Telegram;
|
||||||
|
|
||||||
|
use App\Enum\Telegram\ChatTypeEnum;
|
||||||
|
use App\Exception\Telegram\CommandProcessingException;
|
||||||
|
use App\Factory\Telegram\AccountFactory;
|
||||||
|
use App\Service\Api\UserApi;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use src\PointToolsBundle\Entity\User;
|
use App\Entity\Telegram\Account;
|
||||||
use src\PointToolsBundle\Repository\SubscriptionEventRepository;
|
use App\Entity\User;
|
||||||
use src\PointToolsBundle\Repository\SubscriptionRepository;
|
use App\Repository\Telegram\AccountRepository;
|
||||||
use src\PointToolsBundle\Repository\UserRepository;
|
use App\Repository\{SubscriptionEventRepository, SubscriptionRepository, UserRepository};
|
||||||
use src\PointToolsBundle\Service\Telegram\IncomingUpdateDispatcher;
|
use TelegramBot\Api\Types\{ReplyKeyboardMarkup, ReplyKeyboardRemove, Update};
|
||||||
use src\PointToolsBundle\Service\Telegram\MessageSender;
|
|
||||||
use src\PointToolsBundle\Entity\{Telegram\Account};
|
|
||||||
use src\PointToolsBundle\Exception\Telegram\CommandProcessingException;
|
|
||||||
use src\PointToolsBundle\Repository\{Telegram\AccountRepository};
|
|
||||||
use src\PointToolsBundle\Service\Factory\Telegram\AccountFactory;
|
|
||||||
use src\PointToolsBundle\Service\Api\UserApi;
|
|
||||||
use unreal4u\TelegramAPI\Telegram\Types\{Message, ReplyKeyboardMarkup, ReplyKeyboardRemove};
|
|
||||||
|
|
||||||
/** Processes all private messages */
|
/** Processes all private messages */
|
||||||
class PrivateMessageProcessor
|
class PrivateMessageProcessor
|
||||||
{
|
{
|
||||||
/** @var MessageSender */
|
|
||||||
private $messenger;
|
|
||||||
|
|
||||||
/** @var UserApi */
|
|
||||||
private $userApi;
|
|
||||||
|
|
||||||
/** @var AccountFactory */
|
|
||||||
private $accountFactory;
|
|
||||||
|
|
||||||
/** @var EntityManagerInterface */
|
|
||||||
private $em;
|
|
||||||
|
|
||||||
/** @var UserRepository */
|
|
||||||
private $userRepo;
|
|
||||||
|
|
||||||
/** @var AccountRepository */
|
|
||||||
private $accountRepo;
|
|
||||||
|
|
||||||
/** @var SubscriptionRepository */
|
|
||||||
private $subscriptionRepo;
|
|
||||||
|
|
||||||
/** @var SubscriptionEventRepository */
|
|
||||||
private $subscriptionEventRepo;
|
|
||||||
|
|
||||||
/** @var int */
|
|
||||||
private $pointUserId;
|
|
||||||
|
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
EntityManagerInterface $em,
|
private readonly EntityManagerInterface $em,
|
||||||
UserRepository $userRepository,
|
private readonly UserRepository $userRepo,
|
||||||
AccountRepository $accountRepository,
|
private readonly AccountRepository $accountRepo,
|
||||||
SubscriptionRepository $subscriptionRepository,
|
private readonly SubscriptionRepository $subscriptionRepo,
|
||||||
SubscriptionEventRepository $subscriptionRecordRepository,
|
private readonly SubscriptionEventRepository $subscriptionEventRepo,
|
||||||
MessageSender $messageSender,
|
private readonly MessageSender $messenger,
|
||||||
UserApi $userApi,
|
private readonly UserApi $userApi,
|
||||||
AccountFactory $accountFactory,
|
private readonly AccountFactory $accountFactory,
|
||||||
int $appUserId
|
private readonly int $pointAppUserId,
|
||||||
) {
|
) {
|
||||||
$this->em = $em;
|
|
||||||
$this->userRepo = $userRepository;
|
|
||||||
$this->accountRepo = $accountRepository;
|
|
||||||
$this->subscriptionRepo = $subscriptionRepository;
|
|
||||||
$this->subscriptionEventRepo = $subscriptionRecordRepository;
|
|
||||||
$this->messenger = $messageSender;
|
|
||||||
$this->userApi = $userApi;
|
|
||||||
$this->accountFactory = $accountFactory;
|
|
||||||
$this->pointUserId = $appUserId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function process(Message $message): void
|
public function process(Update $update): void
|
||||||
{
|
{
|
||||||
if (!IncomingUpdateDispatcher::CHAT_TYPE_PRIVATE === $message->chat->type) {
|
if (!ChatTypeEnum::Private->value === $update->getMessage()->getChat()->getType()) {
|
||||||
throw new \LogicException('This service can process only private chat messages');
|
throw new \LogicException('This service can process only private chat messages');
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Registering Telegram user
|
$account = $this->accountFactory->findOrCreateFromMessage($update->getMessage());
|
||||||
/** @var Account $account */
|
|
||||||
$account = $this->accountFactory->findOrCreateFromMessage($message);
|
|
||||||
$this->em->flush();
|
$this->em->flush();
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
// Low-level message in case of incorrect $account
|
$this->messenger->sendMessageToChat(
|
||||||
$this->messenger->sendMessageToChat($message->chat->id, 'There was an error during your Telegram account registration. Try again or report the bug.');
|
$update->getMessage()->getChat()->getId(),
|
||||||
|
'There was an error during your Telegram account registration. Try again or report the bug.'
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$words = explode(' ', $message->text, 10);
|
$words = explode(' ', $update->getMessage()?->getText() ?? '', 10);
|
||||||
|
|
||||||
if (0 === count($words)) {
|
if (0 === count($words)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($words[0]) {
|
match ($words[0]) {
|
||||||
case '/link':
|
'/link', 'link' => $this->processLink($account, $words),
|
||||||
case 'link':
|
'/me', 'me' => $this->processMe($account),
|
||||||
$this->processLink($account, $words);
|
'/last', 'last' => $this->processLast($account, $words),
|
||||||
break;
|
'/sub', 'sub' => $this->processSub($account, $words),
|
||||||
|
'/stats', 'stats' => $this->processStats($account),
|
||||||
case '/me':
|
'/set' => $this->processSet($account, $words),
|
||||||
case 'me':
|
'/exit', 'exit' => $this->processExit($account),
|
||||||
$this->processMe($account);
|
default => $this->processHelp($account),
|
||||||
break;
|
};
|
||||||
|
|
||||||
case '/last':
|
|
||||||
case 'last':
|
|
||||||
$this->processLast($account, $words);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '/sub':
|
|
||||||
case 'sub':
|
|
||||||
$this->processSub($account, $words);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '/stats':
|
|
||||||
case 'stats':
|
|
||||||
$this->processStats($account);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Settings menu
|
|
||||||
case '/set':
|
|
||||||
$this->processSet($account, $words);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Exit from any menu and remove keyboard
|
|
||||||
case '/exit':
|
|
||||||
case 'exit':
|
|
||||||
$this->processExit($account);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '/help':
|
|
||||||
default:
|
|
||||||
$this->processHelp($account);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} catch (CommandProcessingException $e) {
|
} catch (CommandProcessingException $e) {
|
||||||
$this->sendError($account, 'Processing error', $e->getMessage());
|
$this->sendError($account, 'Processing error', $e->getMessage());
|
||||||
|
|
||||||
|
@ -149,7 +80,6 @@ class PrivateMessageProcessor
|
||||||
|
|
||||||
private function linkAccount(Account $account, string $login, string $password): bool
|
private function linkAccount(Account $account, string $login, string $password): bool
|
||||||
{
|
{
|
||||||
/** @var User $user */
|
|
||||||
if (null === $user = $this->userRepo->findUserByLogin($login)) {
|
if (null === $user = $this->userRepo->findUserByLogin($login)) {
|
||||||
throw new CommandProcessingException('User not found in Point Tools database. Please try again later.');
|
throw new CommandProcessingException('User not found in Point Tools database. Please try again later.');
|
||||||
}
|
}
|
||||||
|
@ -165,9 +95,8 @@ class PrivateMessageProcessor
|
||||||
|
|
||||||
private function processLink(Account $account, array $words): void
|
private function processLink(Account $account, array $words): void
|
||||||
{
|
{
|
||||||
if (array_key_exists(2, $words)) {
|
if (\array_key_exists(2, $words)) {
|
||||||
if ($this->linkAccount($account, $words[1], $words[2])) {
|
if ($this->linkAccount($account, $words[1], $words[2])) {
|
||||||
// Saving linking status
|
|
||||||
$this->em->flush();
|
$this->em->flush();
|
||||||
$this->sendAccountLinked($account);
|
$this->sendAccountLinked($account);
|
||||||
} else {
|
} else {
|
||||||
|
@ -189,7 +118,7 @@ class PrivateMessageProcessor
|
||||||
|
|
||||||
private function processLast(Account $account, array $words): void
|
private function processLast(Account $account, array $words): void
|
||||||
{
|
{
|
||||||
if (array_key_exists(1, $words)) {
|
if (\array_key_exists(1, $words)) {
|
||||||
if (null !== $user = $this->userRepo->findUserByLogin($words[1])) {
|
if (null !== $user = $this->userRepo->findUserByLogin($words[1])) {
|
||||||
$this->sendUserEvents($account, $user);
|
$this->sendUserEvents($account, $user);
|
||||||
} else {
|
} else {
|
||||||
|
@ -202,18 +131,16 @@ class PrivateMessageProcessor
|
||||||
|
|
||||||
private function processSub(Account $account, array $words): void
|
private function processSub(Account $account, array $words): void
|
||||||
{
|
{
|
||||||
if (array_key_exists(1, $words)) {
|
if (\array_key_exists(1, $words)) {
|
||||||
if (null !== $user = $this->userRepo->findUserByLogin($words[1])) {
|
if (null !== $user = $this->userRepo->findUserByLogin($words[1])) {
|
||||||
$this->sendUserSubscribers($account, $user);
|
$this->sendUserSubscribers($account, $user);
|
||||||
} else {
|
} else {
|
||||||
$this->sendError($account, 'User not found');
|
$this->sendError($account, 'User not found');
|
||||||
}
|
}
|
||||||
|
} elseif ($user = $account->getUser()) {
|
||||||
|
$this->sendUserSubscribers($account, $user);
|
||||||
} else {
|
} else {
|
||||||
if ($user = $account->getUser()) {
|
$this->sendError($account, 'Account not linked', 'You must /link your account first to be able to use this command.');
|
||||||
$this->sendUserSubscribers($account, $user);
|
|
||||||
} else {
|
|
||||||
$this->sendError($account, 'Account not linked', 'You must /link your account first to be able to use this command.');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,10 +151,10 @@ class PrivateMessageProcessor
|
||||||
|
|
||||||
private function processSet(Account $account, array $words): void
|
private function processSet(Account $account, array $words): void
|
||||||
{
|
{
|
||||||
$keyboard = new ReplyKeyboardMarkup();
|
$keyboard = new ReplyKeyboardMarkup([], true);
|
||||||
|
|
||||||
if (array_key_exists(1, $words)) {
|
if (\array_key_exists(1, $words)) {
|
||||||
if (array_key_exists(2, $words)) {
|
if (\array_key_exists(2, $words)) {
|
||||||
if ('renames' === $words[2]) {
|
if ('renames' === $words[2]) {
|
||||||
$account->toggleRenameNotification();
|
$account->toggleRenameNotification();
|
||||||
$this->em->flush();
|
$this->em->flush();
|
||||||
|
@ -246,22 +173,22 @@ class PrivateMessageProcessor
|
||||||
$this->sendError($account, 'Notification type does not exist.');
|
$this->sendError($account, 'Notification type does not exist.');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$keyboard->keyboard = [
|
$keyboard->setKeyboard([
|
||||||
['/set notifications renames'],
|
['/set notifications renames'],
|
||||||
['/set notifications subscribers'],
|
['/set notifications subscribers'],
|
||||||
['exit'],
|
['exit'],
|
||||||
];
|
]);
|
||||||
|
|
||||||
$this->messenger->sendMessage($account, 'Choose which notification type to toggle', MessageSender::PARSE_PLAIN, $keyboard);
|
$this->messenger->sendMessage($account, 'Choose which notification type to toggle', MessageSender::PARSE_PLAIN, $keyboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$keyboard->keyboard = [
|
$keyboard->setKeyboard([
|
||||||
['/set notifications'],
|
['/set notifications'],
|
||||||
['exit'],
|
['exit'],
|
||||||
];
|
]);
|
||||||
|
|
||||||
$this->messenger->sendTemplatedMessage($account, '@SkobkinPointTools/Telegram/settings.md.twig', ['account' => $account], $keyboard);
|
$this->messenger->sendTemplatedMessage($account, 'Telegram/settings.md.twig', ['account' => $account], $keyboard);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,7 +197,7 @@ class PrivateMessageProcessor
|
||||||
*/
|
*/
|
||||||
private function processExit(Account $account): void
|
private function processExit(Account $account): void
|
||||||
{
|
{
|
||||||
$keyboardRemove = new ReplyKeyboardRemove();
|
$keyboardRemove = new ReplyKeyboardRemove(true);
|
||||||
|
|
||||||
$this->messenger->sendMessage($account, 'Done', MessageSender::PARSE_PLAIN, $keyboardRemove);
|
$this->messenger->sendMessage($account, 'Done', MessageSender::PARSE_PLAIN, $keyboardRemove);
|
||||||
}
|
}
|
||||||
|
@ -294,7 +221,7 @@ class PrivateMessageProcessor
|
||||||
|
|
||||||
$this->messenger->sendTemplatedMessage(
|
$this->messenger->sendTemplatedMessage(
|
||||||
$account,
|
$account,
|
||||||
'@SkobkinPointTools/Telegram/user_subscribers.md.twig',
|
'Telegram/user_subscribers.md.twig',
|
||||||
[
|
[
|
||||||
'user' => $user,
|
'user' => $user,
|
||||||
'subscribers' => $subscribers,
|
'subscribers' => $subscribers,
|
||||||
|
@ -308,7 +235,7 @@ class PrivateMessageProcessor
|
||||||
|
|
||||||
$this->messenger->sendTemplatedMessage(
|
$this->messenger->sendTemplatedMessage(
|
||||||
$account,
|
$account,
|
||||||
'@SkobkinPointTools/Telegram/last_user_subscriptions.md.twig',
|
'Telegram/last_user_subscriptions.md.twig',
|
||||||
[
|
[
|
||||||
'user' => $user,
|
'user' => $user,
|
||||||
'events' => $events,
|
'events' => $events,
|
||||||
|
@ -320,17 +247,17 @@ class PrivateMessageProcessor
|
||||||
{
|
{
|
||||||
$events = $this->subscriptionEventRepo->getLastSubscriptionEvents(10);
|
$events = $this->subscriptionEventRepo->getLastSubscriptionEvents(10);
|
||||||
|
|
||||||
$this->messenger->sendTemplatedMessage($account, '@SkobkinPointTools/Telegram/last_global_subscriptions.md.twig', ['events' => $events]);
|
$this->messenger->sendTemplatedMessage($account, 'Telegram/last_global_subscriptions.md.twig', ['events' => $events]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function sendStats(Account $account): void
|
private function sendStats(Account $account): void
|
||||||
{
|
{
|
||||||
$this->messenger->sendTemplatedMessage(
|
$this->messenger->sendTemplatedMessage(
|
||||||
$account,
|
$account,
|
||||||
'@SkobkinPointTools/Telegram/stats.md.twig',
|
'Telegram/stats.md.twig',
|
||||||
[
|
[
|
||||||
'total_users' => $this->userRepo->getUsersCount(),
|
'total_users' => $this->userRepo->getUsersCount(),
|
||||||
'active_users' => $this->subscriptionRepo->getUserSubscribersCountById($this->pointUserId),
|
'active_users' => $this->subscriptionRepo->getUserSubscribersCountById($this->pointAppUserId),
|
||||||
'telegram_accounts' => $this->accountRepo->getAccountsCount(),
|
'telegram_accounts' => $this->accountRepo->getAccountsCount(),
|
||||||
'telegram_linked_accounts' => $this->accountRepo->getLinkedAccountsCount(),
|
'telegram_linked_accounts' => $this->accountRepo->getLinkedAccountsCount(),
|
||||||
'today_events' => $this->subscriptionEventRepo->getLastDayEventsCount(),
|
'today_events' => $this->subscriptionEventRepo->getLastDayEventsCount(),
|
||||||
|
@ -340,20 +267,18 @@ class PrivateMessageProcessor
|
||||||
|
|
||||||
private function sendHelp(Account $account): void
|
private function sendHelp(Account $account): void
|
||||||
{
|
{
|
||||||
$this->messenger->sendTemplatedMessage($account, '@SkobkinPointTools/Telegram/help.md.twig');
|
$this->messenger->sendTemplatedMessage($account, 'Telegram/help.md.twig');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function sendError(Account $account, string $title, string $text = ''): void
|
private function sendError(Account $account, string $title, string $text = ''): void
|
||||||
{
|
{
|
||||||
$this->messenger->sendTemplatedMessage(
|
$this->messenger->sendTemplatedMessage(
|
||||||
$account,
|
$account,
|
||||||
'@SkobkinPointTools/Telegram/error.md.twig',
|
'Telegram/error.md.twig',
|
||||||
[
|
[
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'text' => $text,
|
'text' => $text,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
|
@ -1,7 +1,7 @@
|
||||||
*Last global subscription events:*
|
*Last global subscription events:*
|
||||||
|
|
||||||
{% set subscription = constant('\\Skobkin\\Bundle\\PointToolsBundle\\Entity\\SubscriptionEvent::ACTION_SUBSCRIBE') %}
|
{% set subscription = constant('\\App\\Entity\\SubscriptionEvent::ACTION_SUBSCRIBE') %}
|
||||||
{# @var event \Skobkin\Bundle\PointToolsBundle\Entity\SubscriptionEvent #}
|
{# @var event \App\Entity\SubscriptionEvent #}
|
||||||
{% for event in events %}
|
{% for event in events %}
|
||||||
{% set sub_login = event.subscriber.login %}
|
{% set sub_login = event.subscriber.login %}
|
||||||
{% set author_login = event.author.login %}
|
{% set author_login = event.author.login %}
|
|
@ -1,8 +1,8 @@
|
||||||
{# @var user \Skobkin\Bundle\PointToolsBundle\Entity\User #}
|
{# @var user \App\Entity\User #}
|
||||||
*Last for @{{ user.login }}:*
|
*Last for @{{ user.login }}:*
|
||||||
|
|
||||||
{% set subscription = constant('\\Skobkin\\Bundle\\PointToolsBundle\\Entity\\SubscriptionEvent::ACTION_SUBSCRIBE') %}
|
{% set subscription = constant('\\App\\Entity\\SubscriptionEvent::ACTION_SUBSCRIBE') %}
|
||||||
{# @var event \Skobkin\Bundle\PointToolsBundle\Entity\SubscriptionEvent #}
|
{# @var event \App\Entity\SubscriptionEvent #}
|
||||||
{% for event in events %}
|
{% for event in events %}
|
||||||
{% set sub_login = event.subscriber.login %}
|
{% set sub_login = event.subscriber.login %}
|
||||||
{{ event.date|date('d M y H:i') }} {% if subscription == event.action %} + {% else %} - {% endif %} [@{{ sub_login }}]({{ sub_login|point_user_url }})
|
{{ event.date|date('d M y H:i') }} {% if subscription == event.action %} + {% else %} - {% endif %} [@{{ sub_login }}]({{ sub_login|point_user_url }})
|
|
@ -1,4 +1,4 @@
|
||||||
{# @var account \Skobkin\Bundle\PointToolsBundle\Entity\Telegram\Account #}
|
{# @var account \App\Entity\Telegram\Account #}
|
||||||
*Your current settings:*
|
*Your current settings:*
|
||||||
|
|
||||||
Account /link status: {% if account.user %}linked to [@{{ account.user.login }}]({{ account.user.login|point_user_url }}){% else %}Not linked{% endif %}
|
Account /link status: {% if account.user %}linked to [@{{ account.user.login }}]({{ account.user.login|point_user_url }}){% else %}Not linked{% endif %}
|
|
@ -1,4 +1,4 @@
|
||||||
{# @var user \Skobkin\Bundle\PointToolsBundle\Entity\User #}
|
{# @var user \App\Entity\User #}
|
||||||
*@{{ user.login }} subscribers:*
|
*@{{ user.login }} subscribers:*
|
||||||
|
|
||||||
{% if subscribers|length > 0 %}
|
{% if subscribers|length > 0 %}
|
|
@ -1,5 +1,5 @@
|
||||||
{# @var subscribed \Skobkin\Bundle\PointToolsBundle\Entity\User[] #}
|
{# @var subscribed \App\Entity\User[] #}
|
||||||
{# @var unsubscribed \Skobkin\Bundle\PointToolsBundle\Entity\User[] #}
|
{# @var unsubscribed \App\Entity\User[] #}
|
||||||
*Subscribers list changed:*
|
*Subscribers list changed:*
|
||||||
|
|
||||||
{% if subscribed|length > 0 %}
|
{% if subscribed|length > 0 %}
|
|
@ -1,6 +1,6 @@
|
||||||
*Following users recently renamed themselves:*
|
*Following users recently renamed themselves:*
|
||||||
|
|
||||||
{# @var event \Skobkin\Bundle\PointToolsBundle\Entity\UserRenameEvent #}
|
{# @var event \App\Entity\UserRenameEvent #}
|
||||||
{% for event in events %}
|
{% for event in events %}
|
||||||
{% set login_old = event.oldLogin %}
|
{% set login_old = event.oldLogin %}
|
||||||
{% set login_new = event.user.login %}
|
{% set login_new = event.user.login %}
|
Loading…
Reference in a new issue