2017-01-05 20:17:19 +00:00
< ? php
namespace Skobkin\Bundle\PointToolsBundle\Service\Telegram ;
use Doctrine\ORM\EntityManagerInterface ;
use Skobkin\Bundle\PointToolsBundle\Entity\Telegram\Account ;
use Skobkin\Bundle\PointToolsBundle\Entity\User ;
use Skobkin\Bundle\PointToolsBundle\Exception\Telegram\CommandProcessingException ;
use Skobkin\Bundle\PointToolsBundle\Repository\SubscriptionEventRepository ;
use Skobkin\Bundle\PointToolsBundle\Repository\SubscriptionRepository ;
2017-01-07 18:53:31 +00:00
use Skobkin\Bundle\PointToolsBundle\Repository\Telegram\AccountRepository ;
2017-01-05 20:17:19 +00:00
use Skobkin\Bundle\PointToolsBundle\Repository\UserRepository ;
use Skobkin\Bundle\PointToolsBundle\Service\Factory\Telegram\AccountFactory ;
use Skobkin\Bundle\PointToolsBundle\Service\UserApi ;
use unreal4u\TelegramAPI\Telegram\Types\Message ;
2017-01-06 17:18:39 +00:00
use unreal4u\TelegramAPI\Telegram\Types\ReplyKeyboardMarkup ;
2017-01-06 19:19:44 +00:00
use unreal4u\TelegramAPI\Telegram\Types\ReplyKeyboardRemove ;
2017-01-05 20:17:19 +00:00
/**
* Processes all private messages
*/
class PrivateMessageProcessor
{
/**
2017-01-06 17:18:39 +00:00
* @ var MessageSender
2017-01-05 20:17:19 +00:00
*/
2017-01-06 17:18:39 +00:00
private $messenger ;
2017-01-05 20:17:19 +00:00
/**
* @ var UserApi
*/
private $userApi ;
/**
* @ var AccountFactory
*/
private $accountFactory ;
/**
* @ var EntityManagerInterface
*/
private $em ;
/**
* @ var UserRepository
*/
private $userRepo ;
2017-01-07 18:53:31 +00:00
/**
* @ var AccountRepository
*/
private $accountRepo ;
2017-01-05 20:17:19 +00:00
/**
* @ var SubscriptionRepository
*/
private $subscriptionRepo ;
/**
* @ var SubscriptionEventRepository
*/
private $subscriptionEventRepo ;
/**
* @ var int
*/
private $pointUserId ;
2017-01-06 21:38:20 +00:00
public function __construct ( MessageSender $messageSender , UserApi $userApi , AccountFactory $accountFactory , EntityManagerInterface $em , int $pointUserId )
2017-01-05 20:17:19 +00:00
{
2017-01-06 17:18:39 +00:00
$this -> messenger = $messageSender ;
2017-01-05 20:17:19 +00:00
$this -> userApi = $userApi ;
$this -> accountFactory = $accountFactory ;
$this -> em = $em ;
$this -> pointUserId = $pointUserId ;
$this -> userRepo = $em -> getRepository ( 'SkobkinPointToolsBundle:User' );
2017-01-07 18:53:31 +00:00
$this -> accountRepo = $em -> getRepository ( 'SkobkinPointToolsBundle:Telegram\Account' );
2017-01-05 20:17:19 +00:00
$this -> subscriptionRepo = $em -> getRepository ( 'SkobkinPointToolsBundle:Subscription' );
$this -> subscriptionEventRepo = $em -> getRepository ( 'SkobkinPointToolsBundle:SubscriptionEvent' );
}
public function process ( Message $message )
{
if ( ! IncomingUpdateDispatcher :: CHAT_TYPE_PRIVATE === $message -> chat -> type ) {
2017-01-06 17:18:39 +00:00
throw new \LogicException ( 'This service can process only private chat messages' );
2017-01-05 20:17:19 +00:00
}
2017-01-06 17:18:39 +00:00
try {
// Registering Telegram user
/** @var Account $account */
$account = $this -> accountFactory -> findOrCreateFromMessage ( $message );
$this -> em -> flush ();
} catch ( \Exception $e ) {
// Low-level message in case of incorrect $account
$this -> messenger -> sendMessageToChat ( $message -> chat -> id , 'There was an error during your Telegram account registration. Try again or report the bug.' );
2017-01-05 20:17:19 +00:00
}
try {
2017-01-06 17:18:39 +00:00
$words = explode ( ' ' , $message -> text , 10 );
if ( 0 === count ( $words )) {
return ;
}
2017-01-05 20:17:19 +00:00
switch ( $words [ 0 ]) {
case '/link' :
case 'link' :
2017-01-06 19:19:44 +00:00
$this -> processLink ( $account , $words );
2017-01-05 20:17:19 +00:00
break ;
case '/me' :
case 'me' :
2017-01-06 19:19:44 +00:00
$this -> processMe ( $account );
2017-01-05 20:17:19 +00:00
break ;
case '/last' :
case 'last' :
2017-01-06 19:19:44 +00:00
$this -> processLast ( $account , $words );
2017-01-05 20:17:19 +00:00
break ;
case '/sub' :
case 'sub' :
2017-01-06 19:19:44 +00:00
$this -> processSub ( $account , $words );
2017-01-05 20:17:19 +00:00
break ;
case '/stats' :
case 'stats' :
2017-01-06 19:19:44 +00:00
$this -> processStats ( $account );
break ;
2017-01-05 20:17:19 +00:00
2017-01-06 19:19:44 +00:00
// Settings menu
case '/set' :
$this -> processSet ( $account , $words );
break ;
// Exit from any menu and remove keyboard
case '/exit' :
case 'exit' :
$this -> processExit ( $account );
2017-01-05 20:17:19 +00:00
break ;
case '/help' :
default :
2017-01-06 19:19:44 +00:00
$this -> processHelp ( $account );
2017-01-05 20:17:19 +00:00
break ;
}
} catch ( CommandProcessingException $e ) {
2017-01-06 17:18:39 +00:00
$this -> sendError ( $account , 'Processing error' , $e -> getMessage ());
2017-01-05 20:17:19 +00:00
if ( $e -> getPrevious ()) {
throw $e -> getPrevious ();
}
} catch ( \Exception $e ) {
2017-01-06 17:18:39 +00:00
$this -> sendError ( $account , 'Unknown error' );
2017-01-05 20:17:19 +00:00
throw $e ;
}
}
private function linkAccount ( Account $account , string $login , string $password ) : bool
{
2017-01-05 21:30:52 +00:00
/** @var User $user */
if ( null === $user = $this -> userRepo -> findUserByLogin ( $login )) {
throw new CommandProcessingException ( 'User not found in Point Tools database. Please try again later.' );
}
2017-01-05 20:17:19 +00:00
2017-01-05 21:30:52 +00:00
if ( $this -> userApi -> isAuthDataValid ( $login , $password )) {
2017-01-05 20:17:19 +00:00
$account -> setUser ( $user );
return true ;
}
return false ;
}
2017-01-06 19:19:44 +00:00
private function processLink ( Account $account , array $words )
{
if ( array_key_exists ( 2 , $words )) {
if ( $this -> linkAccount ( $account , $words [ 1 ], $words [ 2 ])) {
// Saving linking status
$this -> em -> flush ();
$this -> sendAccountLinked ( $account );
} else {
$this -> sendError ( $account , 'Account linking error' , 'Check login and password or try again later.' );
}
} else {
$this -> sendError ( $account , 'Login/Password error' , 'You need to specify login and password separated by space after /link (example: `/link mylogin MypASSw0rd`)' );
}
}
private function processMe ( Account $account )
{
if ( $user = $account -> getUser ()) {
$this -> sendUserEvents ( $account , $user );
} else {
$this -> sendError ( $account , 'Account not linked' , 'You must /link your account first to be able to use this command.' );
}
}
private function processLast ( Account $account , array $words )
{
if ( array_key_exists ( 1 , $words )) {
if ( null !== $user = $this -> userRepo -> findUserByLogin ( $words [ 1 ])) {
$this -> sendUserEvents ( $account , $user );
} else {
$this -> sendError ( $account , 'User not found' );
}
} else {
$this -> sendGlobalEvents ( $account );
}
}
private function processSub ( Account $account , array $words )
{
if ( array_key_exists ( 1 , $words )) {
if ( null !== $user = $this -> userRepo -> findUserByLogin ( $words [ 1 ])) {
$this -> sendUserSubscribers ( $account , $user );
} else {
$this -> sendError ( $account , 'User not found' );
}
} else {
if ( $user = $account -> getUser ()) {
$this -> sendUserSubscribers ( $account , $user );
} else {
$this -> sendError ( $account , 'Account not linked' , 'You must /link your account first to be able to use this command.' );
}
}
}
private function processStats ( Account $account )
{
$this -> sendStats ( $account );
}
private function processSet ( Account $account , array $words )
{
$keyboard = new ReplyKeyboardMarkup ();
if ( array_key_exists ( 1 , $words )) {
if ( array_key_exists ( 2 , $words )) {
if ( 'renames' === $words [ 2 ]) {
$account -> toggleRenameNotification ();
$this -> em -> flush ();
2017-01-06 21:38:20 +00:00
$this -> messenger -> sendMessage ( $account , 'Renaming notifications are turned ' . ( $account -> isRenameNotification () ? 'on' : 'off' ));
2017-01-06 19:19:44 +00:00
} elseif ( 'subscribers' === $words [ 2 ]) {
$account -> toggleSubscriberNotification ();
$this -> em -> flush ();
2017-01-06 21:38:20 +00:00
$this -> messenger -> sendMessage ( $account , 'Subscribers notifications are turned ' . ( $account -> isSubscriberNotification () ? 'on' : 'off' ));
2017-01-07 11:30:30 +00:00
if ( $account -> isSubscriberNotification () && null === $account -> getUser ()) {
$this -> messenger -> sendMessage ( $account , 'You need to /link you account to receive these notifications.' );
}
2017-01-06 19:19:44 +00:00
} else {
$this -> sendError ( $account , 'Notification type does not exist.' );
}
} else {
$keyboard -> keyboard = [
[ '/set notifications renames' ],
[ '/set notifications subscribers' ],
[ 'exit' ],
];
2017-01-06 21:38:20 +00:00
$this -> messenger -> sendMessage ( $account , 'Choose which notification type to toggle' , MessageSender :: PARSE_PLAIN , $keyboard );
2017-01-06 19:19:44 +00:00
}
} else {
$keyboard -> keyboard = [
[ '/set notifications' ],
[ 'exit' ],
];
2017-01-06 21:38:20 +00:00
$this -> messenger -> sendTemplatedMessage ( $account , '@SkobkinPointTools/Telegram/settings.md.twig' , [ 'account' => $account ], $keyboard );
2017-01-06 19:19:44 +00:00
}
}
/**
* Processes exit from keyboard menus and removes the keyboard
*/
private function processExit ( Account $account )
{
$keyboardRemove = new ReplyKeyboardRemove ();
2017-01-06 21:38:20 +00:00
$this -> messenger -> sendMessage ( $account , 'Done' , MessageSender :: PARSE_PLAIN , $keyboardRemove );
2017-01-06 19:19:44 +00:00
}
private function processHelp ( Account $account )
{
$this -> sendHelp ( $account );
}
2017-01-06 17:18:39 +00:00
private function sendAccountLinked ( Account $account )
2017-01-05 20:17:19 +00:00
{
2017-01-06 21:38:20 +00:00
$this -> messenger -> sendMessage ( $account , 'Account linked. Try using /me now.' );
2017-01-05 20:17:19 +00:00
}
2017-01-06 17:18:39 +00:00
private function sendUserSubscribers ( Account $account , User $user )
2017-01-05 20:17:19 +00:00
{
$subscribers = [];
foreach ( $user -> getSubscribers () as $subscription ) {
$subscribers [] = '@' . $subscription -> getSubscriber () -> getLogin ();
}
2017-01-06 21:38:20 +00:00
$this -> messenger -> sendTemplatedMessage (
2017-01-06 17:18:39 +00:00
$account ,
'@SkobkinPointTools/Telegram/user_subscribers.md.twig' ,
[
'user' => $user ,
'subscribers' => $subscribers ,
]
);
2017-01-05 20:17:19 +00:00
}
2017-01-06 17:18:39 +00:00
private function sendUserEvents ( Account $account , User $user )
2017-01-05 20:17:19 +00:00
{
$events = $this -> subscriptionEventRepo -> getUserLastSubscribersEvents ( $user , 10 );
2017-01-06 21:38:20 +00:00
$this -> messenger -> sendTemplatedMessage (
2017-01-06 17:18:39 +00:00
$account ,
'@SkobkinPointTools/Telegram/last_user_subscriptions.md.twig' ,
[
'user' => $user ,
'events' => $events ,
]
);
2017-01-05 20:17:19 +00:00
}
2017-01-06 17:18:39 +00:00
private function sendGlobalEvents ( Account $account )
2017-01-05 20:17:19 +00:00
{
$events = $this -> subscriptionEventRepo -> getLastSubscriptionEvents ( 10 );
2017-01-06 21:38:20 +00:00
$this -> messenger -> sendTemplatedMessage ( $account , '@SkobkinPointTools/Telegram/last_global_subscriptions.md.twig' , [ 'events' => $events ]);
2017-01-05 20:17:19 +00:00
}
2017-01-06 17:18:39 +00:00
private function sendStats ( Account $account )
2017-01-05 20:17:19 +00:00
{
2017-01-06 21:38:20 +00:00
$this -> messenger -> sendTemplatedMessage (
2017-01-06 17:18:39 +00:00
$account ,
'@SkobkinPointTools/Telegram/stats.md.twig' ,
[
'total_users' => $this -> userRepo -> getUsersCount (),
'active_users' => $this -> subscriptionRepo -> getUserSubscribersCountById ( $this -> pointUserId ),
2017-01-07 18:53:31 +00:00
'telegram_accounts' => $this -> accountRepo -> getAccountsCount (),
'telegram_linked_accounts' => $this -> accountRepo -> getLinkedAccountsCount (),
2017-01-06 17:18:39 +00:00
'today_events' => $this -> subscriptionEventRepo -> getLastDayEventsCount (),
]
);
2017-01-05 20:17:19 +00:00
}
2017-01-06 17:18:39 +00:00
private function sendHelp ( Account $account )
2017-01-05 20:17:19 +00:00
{
2017-01-06 21:38:20 +00:00
$this -> messenger -> sendTemplatedMessage ( $account , '@SkobkinPointTools/Telegram/help.md.twig' );
2017-01-06 17:18:39 +00:00
}
2017-01-05 20:17:19 +00:00
2017-01-06 17:18:39 +00:00
private function sendError ( Account $account , string $title , string $text = '' )
{
2017-01-06 21:38:20 +00:00
$this -> messenger -> sendTemplatedMessage (
2017-01-06 17:18:39 +00:00
$account ,
'@SkobkinPointTools/Telegram/error.md.twig' ,
[
'title' => $title ,
'text' => $text ,
]
);
2017-01-05 20:17:19 +00:00
}
}