messenger = $messageSender; $this->userApi = $userApi; $this->accountFactory = $accountFactory; $this->em = $em; $this->twig = $twig; $this->pointUserId = $pointUserId; $this->userRepo = $em->getRepository('SkobkinPointToolsBundle:User'); $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) { throw new \LogicException('This service can process only private chat messages'); } 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.'); } try { $words = explode(' ', $message->text, 10); if (0 === count($words)) { return; } switch ($words[0]) { case '/link': case 'link': 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`)'); } break; case '/me': case 'me': 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.'); } break; case '/last': case 'last': 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); } break; case '/sub': case 'sub': 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.'); } } break; case '/stats': case 'stats': $this->sendStats($account); break; case '/help': default: $this->sendHelp($account); break; } } catch (CommandProcessingException $e) { $this->sendError($account, 'Processing error', $e->getMessage()); if ($e->getPrevious()) { throw $e->getPrevious(); } } catch (\Exception $e) { $this->sendError($account, 'Unknown error'); throw $e; } } private function linkAccount(Account $account, string $login, string $password): bool { /** @var User $user */ if (null === $user = $this->userRepo->findUserByLogin($login)) { throw new CommandProcessingException('User not found in Point Tools database. Please try again later.'); } if ($this->userApi->isAuthDataValid($login, $password)) { $account->setUser($user); return true; } return false; } private function sendAccountLinked(Account $account) { $this->messenger->sendMessageToUser($account, 'Account linked. Try using /me now.'); } private function sendUserSubscribers(Account $account, User $user) { $subscribers = []; foreach ($user->getSubscribers() as $subscription) { $subscribers[] = '@'.$subscription->getSubscriber()->getLogin(); } $this->sendTemplatedMessage( $account, '@SkobkinPointTools/Telegram/user_subscribers.md.twig', [ 'user' => $user, 'subscribers' => $subscribers, ] ); } private function sendUserEvents(Account $account, User $user) { $events = $this->subscriptionEventRepo->getUserLastSubscribersEvents($user, 10); $this->sendTemplatedMessage( $account, '@SkobkinPointTools/Telegram/last_user_subscriptions.md.twig', [ 'user' => $user, 'events' => $events, ] ); } private function sendGlobalEvents(Account $account) { $events = $this->subscriptionEventRepo->getLastSubscriptionEvents(10); $this->sendTemplatedMessage($account, '@SkobkinPointTools/Telegram/last_global_subscriptions.md.twig', ['events' => $events]); } private function sendStats(Account $account) { $this->sendTemplatedMessage( $account, '@SkobkinPointTools/Telegram/stats.md.twig', [ 'total_users' => $this->userRepo->getUsersCount(), 'active_users' => $this->subscriptionRepo->getUserSubscribersCountById($this->pointUserId), 'today_events' => $this->subscriptionEventRepo->getLastDayEventsCount(), ] ); } private function sendHelp(Account $account) { $this->sendTemplatedMessage($account, '@SkobkinPointTools/Telegram/help.md.twig'); } private function sendError(Account $account, string $title, string $text = '') { $this->sendTemplatedMessage( $account, '@SkobkinPointTools/Telegram/error.md.twig', [ 'title' => $title, 'text' => $text, ] ); } private function sendTemplatedMessage( Account $account, string $template, array $templateData = [], ReplyKeyboardMarkup $keyboardMarkup = null, bool $disableWebPreview = true, string $format = MessageSender::PARSE_MODE_MARKDOWN ): bool { $text = $this->twig->render($template, $templateData); return $this->messenger->sendMessageToUser($account, $text, $format, $keyboardMarkup, $disableWebPreview, false); } private function sendPlainTextMessage(Account $account, string $text, ReplyKeyboardMarkup $keyboardMarkup = null, bool $disableWebPreview = true): bool { return $this->messenger->sendMessageToUser($account, $text, MessageSender::PARSE_MODE_NOPARSE, $keyboardMarkup, $disableWebPreview); } }