commit
fd2e1d81f8
12
README.md
12
README.md
|
@ -59,6 +59,18 @@ You can use following jobs as an example:
|
|||
0 0 * * * /usr/bin/php /path/to/point-tools/app/console point:update:subscriptions --all-users --env=prod
|
||||
```
|
||||
|
||||
## Setting Telegram webhook (to enable bot)
|
||||
|
||||
```shell
|
||||
php app/console telegram:webhook set your-domain.tld
|
||||
```
|
||||
|
||||
## Removing Telegram webhook
|
||||
|
||||
```shell
|
||||
php app/console telegram:webhook delete
|
||||
```
|
||||
|
||||
# Running tests
|
||||
|
||||
## Configure environment variables
|
||||
|
|
|
@ -19,6 +19,7 @@ class AppKernel extends Kernel
|
|||
new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
|
||||
new JMS\SerializerBundle\JMSSerializerBundle(),
|
||||
new Misd\GuzzleBundle\MisdGuzzleBundle(),
|
||||
new Csa\Bundle\GuzzleBundle\CsaGuzzleBundle(),
|
||||
new Ob\HighchartsBundle\ObHighchartsBundle(),
|
||||
new Knp\Bundle\MarkdownBundle\KnpMarkdownBundle(),
|
||||
new Knp\Bundle\PaginatorBundle\KnpPaginatorBundle(),
|
||||
|
|
|
@ -90,3 +90,6 @@ knp_markdown:
|
|||
knp_paginator:
|
||||
template:
|
||||
pagination: KnpPaginatorBundle:Pagination:twitter_bootstrap_v3_pagination.html.twig
|
||||
|
||||
csa_guzzle:
|
||||
profiler: '%kernel.debug%'
|
|
@ -24,3 +24,7 @@ parameters:
|
|||
|
||||
# Token for Go crawler https://bitbucket.org/skobkin/point-tools-crawler
|
||||
crawler_token: test_token
|
||||
|
||||
# Telegram bot
|
||||
telegram_token: "123456:some-token"
|
||||
telegram_max_connections: 2
|
||||
|
|
|
@ -24,7 +24,9 @@
|
|||
"doctrine/doctrine-migrations-bundle": "^1.0",
|
||||
"jms/serializer-bundle": "^1.1",
|
||||
"knplabs/knp-markdown-bundle": "^1.4",
|
||||
"knplabs/knp-paginator-bundle": "^2.5"
|
||||
"knplabs/knp-paginator-bundle": "^2.5",
|
||||
"unreal4u/telegram-api": "^2.2",
|
||||
"csa/guzzle-bundle": "^2.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"sensio/generator-bundle": "~2.3",
|
||||
|
|
384
composer.lock
generated
384
composer.lock
generated
|
@ -4,8 +4,69 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "2afa2daba03d5922ce606ef250dae660",
|
||||
"content-hash": "f890dca974c5dbd0ada78afc457f249b",
|
||||
"packages": [
|
||||
{
|
||||
"name": "csa/guzzle-bundle",
|
||||
"version": "v2.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/csarrazi/CsaGuzzleBundle.git",
|
||||
"reference": "9796e5c28e02d5c2f0aa1376e8390b1d29159d28"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/csarrazi/CsaGuzzleBundle/zipball/9796e5c28e02d5c2f0aa1376e8390b1d29159d28",
|
||||
"reference": "9796e5c28e02d5c2f0aa1376e8390b1d29159d28",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"guzzlehttp/guzzle": "^6.1",
|
||||
"namshi/cuzzle": "^2.0",
|
||||
"php": ">=5.5.0",
|
||||
"symfony/dependency-injection": "^2.6|^3.0",
|
||||
"symfony/expression-language": "^2.6|^3.0",
|
||||
"symfony/filesystem": "^2.3|^3.0",
|
||||
"symfony/framework-bundle": "^2.6|^3.0",
|
||||
"twig/twig": "^1.12|^2.0"
|
||||
},
|
||||
"conflict": {
|
||||
"guzzlehttp/command": "*",
|
||||
"guzzlehttp/guzzle-services": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/cache": "^1.1",
|
||||
"phpunit/phpunit": "^4.8",
|
||||
"symfony/phpunit-bridge": "^2.7|^3.0",
|
||||
"symfony/web-profiler-bundle": "^2.3|^3.0"
|
||||
},
|
||||
"suggest": {
|
||||
"doctrine/cache": "Allows caching of responses"
|
||||
},
|
||||
"type": "symfony-bundle",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.2.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Csa\\Bundle\\GuzzleBundle\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Charles Sarrazin",
|
||||
"email": "charles@sarraz.in"
|
||||
}
|
||||
],
|
||||
"description": "A bundle integrating GuzzleHttp >= 4.0",
|
||||
"time": "2016-08-25T12:09:22+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/annotations",
|
||||
"version": "v1.3.0",
|
||||
|
@ -1004,6 +1065,177 @@
|
|||
"abandoned": "guzzlehttp/guzzle",
|
||||
"time": "2015-03-18T18:23:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/guzzle",
|
||||
"version": "6.2.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/guzzle.git",
|
||||
"reference": "ebf29dee597f02f09f4d5bbecc68230ea9b08f60"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/ebf29dee597f02f09f4d5bbecc68230ea9b08f60",
|
||||
"reference": "ebf29dee597f02f09f4d5bbecc68230ea9b08f60",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"guzzlehttp/promises": "^1.0",
|
||||
"guzzlehttp/psr7": "^1.3.1",
|
||||
"php": ">=5.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-curl": "*",
|
||||
"phpunit/phpunit": "^4.0",
|
||||
"psr/log": "^1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "6.2-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/functions_include.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"GuzzleHttp\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Michael Dowling",
|
||||
"email": "mtdowling@gmail.com",
|
||||
"homepage": "https://github.com/mtdowling"
|
||||
}
|
||||
],
|
||||
"description": "Guzzle is a PHP HTTP client library",
|
||||
"homepage": "http://guzzlephp.org/",
|
||||
"keywords": [
|
||||
"client",
|
||||
"curl",
|
||||
"framework",
|
||||
"http",
|
||||
"http client",
|
||||
"rest",
|
||||
"web service"
|
||||
],
|
||||
"time": "2016-10-08T15:01:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/promises",
|
||||
"version": "v1.3.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/promises.git",
|
||||
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646",
|
||||
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.5.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"GuzzleHttp\\Promise\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/functions_include.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Michael Dowling",
|
||||
"email": "mtdowling@gmail.com",
|
||||
"homepage": "https://github.com/mtdowling"
|
||||
}
|
||||
],
|
||||
"description": "Guzzle promises library",
|
||||
"keywords": [
|
||||
"promise"
|
||||
],
|
||||
"time": "2016-12-20T10:07:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/psr7",
|
||||
"version": "1.3.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/psr7.git",
|
||||
"reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/5c6447c9df362e8f8093bda8f5d8873fe5c7f65b",
|
||||
"reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.4.0",
|
||||
"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.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"GuzzleHttp\\Psr7\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/functions_include.php"
|
||||
]
|
||||
},
|
||||
"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"
|
||||
],
|
||||
"time": "2016-06-24T23:00:38+00:00"
|
||||
},
|
||||
{
|
||||
"name": "incenteev/composer-parameter-handler",
|
||||
"version": "v2.1.2",
|
||||
|
@ -1809,6 +2041,56 @@
|
|||
],
|
||||
"time": "2016-11-26T00:15:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "namshi/cuzzle",
|
||||
"version": "2.0.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/namshi/cuzzle.git",
|
||||
"reference": "89849bb9c729a3d8aabf94c0b66e77c7df38abda"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/namshi/cuzzle/zipball/89849bb9c729a3d8aabf94c0b66e77c7df38abda",
|
||||
"reference": "89849bb9c729a3d8aabf94c0b66e77c7df38abda",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"guzzlehttp/guzzle": "^6.0",
|
||||
"php": ">=5.5.0",
|
||||
"psr/log": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.2.2"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Namshi\\Cuzzle\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nikita Nefedov",
|
||||
"email": "inefedor@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "cirpo",
|
||||
"email": "alessandro.cinelli@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Get the cURL shell command from a Guzzle request",
|
||||
"time": "2016-11-23T08:01:36+00:00"
|
||||
},
|
||||
{
|
||||
"name": "ob/highcharts-bundle",
|
||||
"version": "1.5",
|
||||
|
@ -2072,6 +2354,56 @@
|
|||
],
|
||||
"time": "2015-07-25T16:39:46+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"
|
||||
],
|
||||
"time": "2016-08-06T14:39:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/log",
|
||||
"version": "1.0.2",
|
||||
|
@ -2880,6 +3212,56 @@
|
|||
],
|
||||
"time": "2016-11-23T18:41:40+00:00"
|
||||
},
|
||||
{
|
||||
"name": "unreal4u/telegram-api",
|
||||
"version": "v2.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/unreal4u/telegram-api.git",
|
||||
"reference": "dd6f58387569d045bf2581dff909f7874bf7d27a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/unreal4u/telegram-api/zipball/dd6f58387569d045bf2581dff909f7874bf7d27a",
|
||||
"reference": "dd6f58387569d045bf2581dff909f7874bf7d27a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"guzzlehttp/guzzle": "~6.0",
|
||||
"php": ">=7.0.0",
|
||||
"psr/log": "~1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"monolog/monolog": "~1.17",
|
||||
"phpunit/php-code-coverage": "~3.3",
|
||||
"phpunit/phpunit": ">=5.2",
|
||||
"squizlabs/php_codesniffer": "~2.3"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"unreal4u\\TelegramAPI\\": "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": "A complete Telegram bot API implementation written in PHP, with support for inline bots!",
|
||||
"keywords": [
|
||||
"api",
|
||||
"telegram",
|
||||
"telegram bot"
|
||||
],
|
||||
"time": "2016-12-04T10:20:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "zendframework/zend-code",
|
||||
"version": "2.6.3",
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
namespace Skobkin\Bundle\PointToolsBundle\Command;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use unreal4u\TelegramAPI\Telegram\Methods\DeleteWebhook;
|
||||
use unreal4u\TelegramAPI\Telegram\Methods\SetWebhook;
|
||||
|
||||
/**
|
||||
* Sets or deletes Telegram bot Web-Hook
|
||||
* @see https://core.telegram.org/bots/api#setwebhook
|
||||
*/
|
||||
class TelegramSetWebHookCommand extends ContainerAwareCommand
|
||||
{
|
||||
const MODE_SET = 'set';
|
||||
const MODE_DELETE = 'delete';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('telegram:webhook')
|
||||
->setDescription('Set webhook')
|
||||
->addArgument('mode', InputArgument::REQUIRED, 'Command mode (set or delete)')
|
||||
->addArgument('host', InputArgument::OPTIONAL, 'Host of telegram hook')
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$container = $this->getContainer();
|
||||
$telegramClient = $container->get('point_tools.telegram.api_client');
|
||||
|
||||
if (self::MODE_SET === strtolower($input->getArgument('mode'))) {
|
||||
if (!$input->hasArgument('host')) {
|
||||
throw new \InvalidArgumentException('Host must be specified when using --set flag');
|
||||
}
|
||||
|
||||
$router = $container->get('router');
|
||||
$token = $container->getParameter('telegram_token');
|
||||
|
||||
$url = sprintf(
|
||||
'https://%s%s',
|
||||
$input->getArgument('host'),
|
||||
$router->generate('telegram_webhook', ['token' => $token])
|
||||
);
|
||||
|
||||
$output->writeln('Setting webhook: '.$url);
|
||||
|
||||
$setWebHook = new SetWebhook();
|
||||
$setWebHook->url = $url;
|
||||
$setWebHook->max_connections = (int) $container->getParameter('telegram_max_connections');
|
||||
|
||||
$telegramClient->performApiRequest($setWebHook);
|
||||
|
||||
$output->writeln('Done');
|
||||
} elseif (self::MODE_DELETE === strtolower($input->getArgument('mode'))) {
|
||||
$output->writeln('Deleting webhook');
|
||||
|
||||
$deleteWebHook = new DeleteWebhook();
|
||||
|
||||
$telegramClient->performApiRequest($deleteWebHook);
|
||||
|
||||
$output->writeln('Done');
|
||||
} else {
|
||||
throw new \InvalidArgumentException(sprintf('Mode must be exaclty one of: %s', implode(', ', [self::MODE_SET, self::MODE_DELETE])));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
namespace Skobkin\Bundle\PointToolsBundle\Controller\Telegram;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use unreal4u\TelegramAPI\Telegram\Types\Update;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
class WebHookController extends Controller
|
||||
{
|
||||
public function receiveUpdateAction(Request $request, $token)
|
||||
{
|
||||
if ($token !== $savedToken = $this->getParameter('telegram_token')) {
|
||||
throw $this->createNotFoundException();
|
||||
}
|
||||
|
||||
$content = json_decode($request->getContent(), true);
|
||||
|
||||
$update = new Update(
|
||||
$content,
|
||||
$this->get('logger')
|
||||
);
|
||||
|
||||
$this->get('point_tools.telegram.update_processor')->process($update);
|
||||
|
||||
return new JsonResponse('received');
|
||||
}
|
||||
}
|
|
@ -53,14 +53,14 @@ class User
|
|||
/**
|
||||
* @var ArrayCollection
|
||||
*
|
||||
* @ORM\OneToMany(targetEntity="Subscription", mappedBy="author")
|
||||
* @ORM\OneToMany(targetEntity="Subscription", mappedBy="author", fetch="EXTRA_LAZY")
|
||||
*/
|
||||
private $subscribers;
|
||||
|
||||
/**
|
||||
* @var ArrayCollection
|
||||
*
|
||||
* @ORM\OneToMany(targetEntity="Subscription", mappedBy="subscriber")
|
||||
* @ORM\OneToMany(targetEntity="Subscription", mappedBy="subscriber", fetch="EXTRA_LAZY")
|
||||
*/
|
||||
private $subscriptions;
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ class SubscriptionEventRepository extends EntityRepository
|
|||
}
|
||||
|
||||
/**
|
||||
* Get last subscriptions QueryBuilder for pagination
|
||||
* Get last global subscriptions QueryBuilder for pagination
|
||||
*
|
||||
* @return QueryBuilder
|
||||
*/
|
||||
|
@ -63,4 +63,19 @@ class SubscriptionEventRepository extends EntityRepository
|
|||
->orderBy('se.date', 'desc')
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get last global subscription events
|
||||
*
|
||||
* @param int $limit
|
||||
*
|
||||
* @return SubscriptionEvent[]
|
||||
*/
|
||||
public function getLastSubscriptionEvents($limit = 20)
|
||||
{
|
||||
$qb = $this->createLastSubscriptionEventsQuery();
|
||||
$qb->setMaxResults($limit);
|
||||
|
||||
return $qb->getQuery()->getResult();
|
||||
}
|
||||
}
|
|
@ -2,6 +2,14 @@ index:
|
|||
path: /
|
||||
defaults: { _controller: SkobkinPointToolsBundle:Main:index }
|
||||
|
||||
telegram_webhook:
|
||||
path: /telegram/webhook/{token}
|
||||
defaults: { _controller: SkobkinPointToolsBundle:Telegram/WebHook:receiveUpdate, _format: json }
|
||||
methods: [POST]
|
||||
requirements:
|
||||
token: "\d+\:[\w-]+"
|
||||
_format: json
|
||||
|
||||
user_search_ajax:
|
||||
path: /ajax/users/search/{login}
|
||||
defaults: { _controller: SkobkinPointToolsBundle:Main:searchUserAjax, _format: json }
|
||||
|
|
|
@ -1,4 +1,13 @@
|
|||
services:
|
||||
# Guzzle 6 client for Telegram
|
||||
point_tools.http.telegram_client:
|
||||
class: GuzzleHttp\Client
|
||||
arguments: [{ timeout: 3.0 }]
|
||||
tags:
|
||||
- { name: csa_guzzle.client }
|
||||
|
||||
# Guzzle 5 client for Point API
|
||||
# TODO upgrade and remove misd bundle
|
||||
skobkin_point_tools.http_client:
|
||||
class: %guzzle.client.class%
|
||||
arguments: [ "%point_base_url%" ]
|
||||
|
@ -68,8 +77,23 @@ services:
|
|||
|
||||
# Twig extensions
|
||||
point_tools.twig.point_avatar_extension:
|
||||
class: Skobkin\Bundle\PointToolsBundle\Twig\PointAvatarExtension
|
||||
class: Skobkin\Bundle\PointToolsBundle\Twig\PointUserExtension
|
||||
public: false
|
||||
arguments: ['@skobkin_point_tools.api_user']
|
||||
tags:
|
||||
- { name: twig.extension }
|
||||
|
||||
# Telegram API client
|
||||
point_tools.telegram.api_client:
|
||||
class: unreal4u\TelegramAPI\TgLog
|
||||
arguments: [%telegram_token%, @logger, @point_tools.http.telegram_client]
|
||||
|
||||
# Telegram simple message sender
|
||||
point_tools.telegram.simple_sender:
|
||||
class: Skobkin\Bundle\PointToolsBundle\Service\Telegram\SimpleSender
|
||||
arguments: [@point_tools.telegram.api_client]
|
||||
|
||||
# Telegram command processor
|
||||
point_tools.telegram.update_processor:
|
||||
class: Skobkin\Bundle\PointToolsBundle\Service\Telegram\IncomingUpdateProcessor
|
||||
arguments: [%point_id%, @point_tools.telegram.api_client, @doctrine.orm.entity_manager, @twig]
|
|
@ -0,0 +1,7 @@
|
|||
*Help*:
|
||||
|
||||
/last - shows last global subscription events
|
||||
/last %user% - shows last user subscribers events
|
||||
/help shows this message
|
||||
|
||||
Visit [Point Tools](https://point.skobk.in/) for more info.
|
|
@ -0,0 +1,11 @@
|
|||
Last global subscription events:
|
||||
|
||||
{% set subscription = constant('\\Skobkin\\Bundle\\PointToolsBundle\\Entity\\SubscriptionEvent::ACTION_SUBSCRIBE') %}
|
||||
{# @var event \Skobkin\Bundle\PointToolsBundle\Entity\SubscriptionEvent #}
|
||||
{% for event in events %}
|
||||
{% set sub_login = event.subscriber.login %}
|
||||
{% set author_login = event.author.login %}
|
||||
{{ event.date|date('d M H:i') }} [@{{ sub_login }}]({{ sub_login|point_user_url(true) }}){% if subscription == event.action %} -> {% else %} X {% endif %}[@{{ author_login }}]({{ author_login|point_user_url(true) }})
|
||||
{% endfor %}
|
||||
|
||||
See more events on [Point Tools](https://point.skobk.in/) site.
|
|
@ -0,0 +1,7 @@
|
|||
*Point Tools statistics:*
|
||||
|
||||
Total users: {{ total_users }}
|
||||
Active users: {{ active_users }}
|
||||
24 hours events: {{ today_events }}
|
||||
|
||||
Visit [Point Tools](https://point.skobk.in/) for more info.
|
|
@ -5,7 +5,7 @@
|
|||
{% block content %}
|
||||
<h1 class="user-login">
|
||||
<img src="{{ avatar_url }}">
|
||||
<a href="//{{ user.login }}.point.im/blog/" target="_blank">{{ user.login }}</a>
|
||||
<a href="{{ user.login|point_user_blog_url }}" target="_blank">{{ user.login }}</a>
|
||||
</h1>
|
||||
|
||||
<div class="user-subscribers">
|
||||
|
|
|
@ -0,0 +1,170 @@
|
|||
<?php
|
||||
|
||||
namespace Skobkin\Bundle\PointToolsBundle\Service\Telegram;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use unreal4u\TelegramAPI\Telegram\Methods\AnswerInlineQuery;
|
||||
use unreal4u\TelegramAPI\Telegram\Methods\SendMessage;
|
||||
use unreal4u\TelegramAPI\Telegram\Types\Inline\Query;
|
||||
use unreal4u\TelegramAPI\Telegram\Types\InputMessageContent\Text;
|
||||
use unreal4u\TelegramAPI\Telegram\Types\Message;
|
||||
use unreal4u\TelegramAPI\Telegram\Types\Update;
|
||||
use unreal4u\TelegramAPI\TgLog;
|
||||
|
||||
/**
|
||||
* @todo refactor
|
||||
*/
|
||||
class IncomingUpdateProcessor
|
||||
{
|
||||
const CHAT_TYPE_PRIVATE = 'private';
|
||||
const CHAT_TYPE_GROUP = 'group';
|
||||
|
||||
const PARSE_MODE_MARKDOWN = 'Markdown';
|
||||
const PARSE_MODE_HTML5 = 'HTML';
|
||||
|
||||
/**
|
||||
* @var TgLog
|
||||
*/
|
||||
private $client;
|
||||
|
||||
/**
|
||||
* @var EntityManagerInterface
|
||||
*/
|
||||
private $em;
|
||||
|
||||
/**
|
||||
* @var \Twig_Environment
|
||||
*/
|
||||
private $twig;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $pointUserId;
|
||||
|
||||
/**
|
||||
* @param TgLog $client
|
||||
*/
|
||||
public function __construct(int $pointUserId, TgLog $client, EntityManagerInterface $em, \Twig_Environment $twig)
|
||||
{
|
||||
$this->client = $client;
|
||||
$this->em = $em;
|
||||
$this->twig = $twig;
|
||||
$this->pointUserId = $pointUserId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes update and delegates it to corresponding service
|
||||
*
|
||||
* @param Update $update
|
||||
*/
|
||||
public function process(Update $update)
|
||||
{
|
||||
if ($update->message && $update->message instanceof Message) {
|
||||
$chatType = $update->message->chat->type;
|
||||
|
||||
if (self::CHAT_TYPE_PRIVATE === $chatType) {
|
||||
$this->processPrivateMessage($update);
|
||||
} elseif (self::CHAT_TYPE_GROUP === $chatType) {
|
||||
|
||||
}
|
||||
} elseif ($update->inline_query && $update->inline_query instanceof Query) {
|
||||
$this->processInlineQuery($update);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo refactor
|
||||
*
|
||||
* @param Update $update
|
||||
*/
|
||||
private function processPrivateMessage(Update $update)
|
||||
{
|
||||
$chatId = $update->message->chat->id;
|
||||
$text = $update->message->text;
|
||||
|
||||
$sendMessage = new SendMessage();
|
||||
$sendMessage->chat_id = $chatId;
|
||||
$sendMessage->parse_mode = self::PARSE_MODE_MARKDOWN;
|
||||
$sendMessage->disable_web_page_preview = true;
|
||||
|
||||
$words = explode(' ', $text, 3);
|
||||
|
||||
if (0 === count($words)) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch ($words[0]) {
|
||||
case 'l':
|
||||
case '/last':
|
||||
case 'last':
|
||||
if (array_key_exists(1, $words)) {
|
||||
$sendMessage->text = 'Not implemented yet :(';
|
||||
} else {
|
||||
$events = $this->em->getRepository('SkobkinPointToolsBundle:SubscriptionEvent')->getLastSubscriptionEvents(10);
|
||||
$sendMessage->text = $this->twig->render('@SkobkinPointTools/Telegram/last_global_subscriptions.md.twig', ['events' => $events]);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'sub':
|
||||
case '/sub':
|
||||
case 'subscribers':
|
||||
$sendMessage->text = 'Subscribers list here...';
|
||||
break;
|
||||
|
||||
case 'stats':
|
||||
case '/stats':
|
||||
$stats = [
|
||||
'total_users' => $this->em->getRepository('SkobkinPointToolsBundle:User')->getUsersCount(),
|
||||
'active_users' => $this->em->getRepository('SkobkinPointToolsBundle:Subscription')->getUserSubscribersCountById($this->pointUserId),
|
||||
'today_events' => $this->em->getRepository('SkobkinPointToolsBundle:SubscriptionEvent')->getLastDayEventsCount(),
|
||||
];
|
||||
|
||||
$sendMessage->text = $this->twig->render('@SkobkinPointTools/Telegram/stats.md.twig', $stats);
|
||||
|
||||
break;
|
||||
|
||||
case '/help':
|
||||
default:
|
||||
$sendMessage->text = $this->twig->render('@SkobkinPointTools/Telegram/help.md.twig');
|
||||
break;
|
||||
}
|
||||
|
||||
$this->client->performApiRequest($sendMessage);
|
||||
}
|
||||
|
||||
private function processInlineQuery(Update $update)
|
||||
{
|
||||
$queryId = $update->inline_query->id;
|
||||
$text = $update->inline_query->query;
|
||||
|
||||
if (mb_strlen($text) < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
$answerInlineQuery = new AnswerInlineQuery();
|
||||
$answerInlineQuery->inline_query_id = $queryId;
|
||||
|
||||
foreach ($this->em->getRepository('SkobkinPointToolsBundle:User')->findUsersLikeLogin($text) 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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
namespace Skobkin\Bundle\PointToolsBundle\Service\Telegram;
|
||||
|
||||
use GuzzleHttp\Exception\ClientException;
|
||||
use unreal4u\TelegramAPI\Telegram\Methods\SendMessage;
|
||||
use unreal4u\TelegramAPI\TgLog;
|
||||
|
||||
/**
|
||||
* Service which sends simple messages to Telegram users
|
||||
*/
|
||||
class SimpleSender
|
||||
{
|
||||
/**
|
||||
* @var TgLog
|
||||
*/
|
||||
private $client;
|
||||
|
||||
/**
|
||||
* @param TgLog $client
|
||||
*/
|
||||
public function __construct(TgLog $client)
|
||||
{
|
||||
$this->client = $client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send simple message
|
||||
*
|
||||
* @param int $chatId
|
||||
* @param string $text
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function sendMessage(int $chatId, string $text): bool
|
||||
{
|
||||
$sendMessage = new SendMessage();
|
||||
$sendMessage->chat_id = $chatId;
|
||||
$sendMessage->text = $text;
|
||||
|
||||
try {
|
||||
$this->client->performApiRequest($sendMessage);
|
||||
|
||||
return true;
|
||||
} catch (ClientException $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Skobkin\Bundle\PointToolsBundle\Twig;
|
||||
|
||||
use Skobkin\Bundle\PointToolsBundle\Service\UserApi;
|
||||
|
||||
class PointAvatarExtension extends \Twig_Extension
|
||||
{
|
||||
/**
|
||||
* @var UserApi
|
||||
*/
|
||||
private $userApi;
|
||||
|
||||
public function __construct(UserApi $userApi)
|
||||
{
|
||||
$this->userApi = $userApi;
|
||||
}
|
||||
|
||||
public function getFunctions()
|
||||
{
|
||||
return [
|
||||
new \Twig_SimpleFunction('point_avatar', [$this, 'pointAvatarFunction']),
|
||||
new \Twig_SimpleFunction('point_avatar_small', [$this, 'pointAvatarSmallFunction']),
|
||||
new \Twig_SimpleFunction('point_avatar_medium', [$this, 'pointAvatarMediumFunction']),
|
||||
new \Twig_SimpleFunction('point_avatar_large', [$this, 'pointAvatarLargeFunction']),
|
||||
];
|
||||
}
|
||||
|
||||
public function pointAvatarSmallFunction($login)
|
||||
{
|
||||
return $this->pointAvatarFunction($login, UserApi::AVATAR_SIZE_SMALL);
|
||||
}
|
||||
|
||||
public function pointAvatarMediumFunction($login)
|
||||
{
|
||||
return $this->pointAvatarFunction($login, UserApi::AVATAR_SIZE_MEDIUM);
|
||||
}
|
||||
|
||||
public function pointAvatarLargeFunction($login)
|
||||
{
|
||||
return $this->pointAvatarFunction($login, UserApi::AVATAR_SIZE_LARGE);
|
||||
}
|
||||
|
||||
public function pointAvatarFunction($login, $size)
|
||||
{
|
||||
return $this->userApi->getAvatarUrlByLogin($login, $size);
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return 'point_tools_avatars';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
|
||||
namespace Skobkin\Bundle\PointToolsBundle\Twig;
|
||||
|
||||
use Skobkin\Bundle\PointToolsBundle\Service\UserApi;
|
||||
|
||||
class PointUserExtension extends \Twig_Extension
|
||||
{
|
||||
const POINT_HOST = 'point.im';
|
||||
|
||||
/**
|
||||
* @var UserApi
|
||||
*/
|
||||
private $userApi;
|
||||
|
||||
public function __construct(UserApi $userApi)
|
||||
{
|
||||
$this->userApi = $userApi;
|
||||
}
|
||||
|
||||
public function getFunctions()
|
||||
{
|
||||
return [
|
||||
new \Twig_SimpleFunction('point_avatar', [$this, 'pointAvatarFunction']),
|
||||
new \Twig_SimpleFunction('point_avatar_small', [$this, 'pointAvatarSmallFunction']),
|
||||
new \Twig_SimpleFunction('point_avatar_medium', [$this, 'pointAvatarMediumFunction']),
|
||||
new \Twig_SimpleFunction('point_avatar_large', [$this, 'pointAvatarLargeFunction']),
|
||||
new \Twig_SimpleFunction('point_user_url', [$this, 'pointUserUrl']),
|
||||
new \Twig_SimpleFunction('point_user_blog_url', [$this, 'pointUserBlogUrl']),
|
||||
];
|
||||
}
|
||||
|
||||
public function getFilters()
|
||||
{
|
||||
return [
|
||||
new \Twig_SimpleFilter('point_avatar', [$this, 'pointAvatarFunction']),
|
||||
new \Twig_SimpleFilter('point_avatar_small', [$this, 'pointAvatarSmallFunction']),
|
||||
new \Twig_SimpleFilter('point_avatar_medium', [$this, 'pointAvatarMediumFunction']),
|
||||
new \Twig_SimpleFilter('point_avatar_large', [$this, 'pointAvatarLargeFunction']),
|
||||
new \Twig_SimpleFilter('point_user_url', [$this, 'pointUserUrl']),
|
||||
new \Twig_SimpleFilter('point_user_blog_url', [$this, 'pointUserBlogUrl']),
|
||||
];
|
||||
}
|
||||
|
||||
public function pointAvatarSmallFunction(string $login): string
|
||||
{
|
||||
return $this->pointAvatarFunction($login, UserApi::AVATAR_SIZE_SMALL);
|
||||
}
|
||||
|
||||
public function pointAvatarMediumFunction(string $login): string
|
||||
{
|
||||
return $this->pointAvatarFunction($login, UserApi::AVATAR_SIZE_MEDIUM);
|
||||
}
|
||||
|
||||
public function pointAvatarLargeFunction(string $login): string
|
||||
{
|
||||
return $this->pointAvatarFunction($login, UserApi::AVATAR_SIZE_LARGE);
|
||||
}
|
||||
|
||||
public function pointAvatarFunction(string $login, $size): string
|
||||
{
|
||||
return $this->userApi->getAvatarUrlByLogin($login, $size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $login
|
||||
* @param bool $forceHttps
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function pointUserUrl(string $login, bool $forceHttps = false): string
|
||||
{
|
||||
return sprintf('%s//%s.%s/', $forceHttps ? 'https' : '', $login, self::POINT_HOST);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $login
|
||||
* @param bool $forceHttps
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function pointUserBlogUrl(string $login, bool $forceHttps = false): string
|
||||
{
|
||||
return sprintf('%s//%s.%s/blog/', $forceHttps ? 'https' : '', $login, self::POINT_HOST);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue