<?php
namespace App\Library\TelegramBot\CandidatesPhotoTelegramBot;
use App\Entity\CalendarEvent;
use App\Entity\Candidate;
use App\Entity\CountPlusSettings;
use App\Entity\Person;
use App\Entity\TelegramMessage;
use App\Entity\TelegramUser;
use App\Entity\User;
use App\Enum\Candidate\Status;
use App\Exception\TelegramBot\MessageCantBeDeleted;
use App\Exception\TelegramBot\MessageCantBeDeletedForEveryone;
use App\Exception\TelegramBot\MessageEditedBySameTextException;
use App\Exception\TelegramBot\MessageIdentifierIsNotSpecified;
use App\Exception\TelegramBot\MessageToDeleteNotFoundException;
use App\Exception\TelegramBot\MessageToEditNotFoundException;
use App\Library\TelegramBot\BaseTelegramBot;
use App\Library\TelegramBot\TelegramObject\Message;
use App\Library\TelegramBot\TelegramObject\Update;
use App\Library\Utils\Other\Other;
use App\Library\Utils\StringUtils;
use App\Service\CalendarEvent\CalendarEventService;
use App\Service\Candidate\CandidateService;
use App\Service\CountPlusSettings\CountPlusSettingsService;
use App\Service\DeleteRemoteMessages\DeleteRemoteMessagesService;
use App\Service\EntityManagerService;
use App\Service\Image\ImageService;
use App\Service\Person\PersonService;
use App\Service\TelegramBot\TelegramBotService;
use App\Service\TelegramBotChat\TelegramBotChatService;
use App\Service\TelegramBotNavigation\TelegramBotNavigationService;
use App\Service\TelegramChat\TelegramChatService;
use App\Service\TelegramMessage\TelegramMessageService;
use App\Service\TelegramUser\TelegramUserService;
use App\Service\User\UserService;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\KernelInterface;
use App\Library\TelegramBot\CandidatesPhotoTelegramBot\Enum\Menu\Menu;
use App\Library\TelegramBot\CandidatesPhotoTelegramBot\Enum\EditableMessage\EditableMessage;
/*
* Настройка команд в @BotFather:
start - Начало работы
novii_podschet_plusov - Начать новый подсчет плюсов с последнего сообщения в чате
kto_ne_postavil - Список тех, кто не поставил +
ustanovit_kol_vo_uchastnikov - Установить кол-во участников в группе
avto_perezapusk_schetch_plusov - Вкл/выкл авто перезапуск счетчика плюсов
posmotret_nastroiki_bota - Посмотреть настройки бота
udalit_uchastn_bolee_48_chasov - Удалить участников из учета плюсов с активностью более 48 часов
*/
class CandidatesPhotoTelegramBot extends BaseTelegramBot
{
/**
* @var array
*/
protected $sentMessages = [];
/**
* @var TelegramChatService
*/
private $telegramChatService;
/**
* @var KernelInterface
*/
private $kernel;
/**
* @var TelegramBotChatService
*/
private $telegramBotChatService;
/**
* @var DeleteRemoteMessagesService
*/
private $deleteRemoteMessagesService;
/**
* @var TelegramUserService
*/
private $telegramUserService;
/**
* @var UserService
*/
private $userService;
/**
* @var CandidateService
*/
private $candidateService;
/**
* @var PersonService
*/
private $personService;
/**
* @var CalendarEventService
*/
private $calendarEventService;
/**
* @var BotNavigation
*/
public $botNavigation;
public function __construct(LoggerInterface $logger, EntityManagerInterface $em, TelegramBotChatService $telegramBotChatService,
KernelInterface $kernel, TelegramMessageService $telegramMessageService,
DeleteRemoteMessagesService $deleteRemoteMessagesService,
TelegramUserService $telegramUserService,
EntityManagerService $emService,
TelegramChatService $telegramChatService,
TelegramBotService $telegramBotService, UserService $userService,
CandidateService $candidateService, PersonService $personService,
TelegramBotNavigationService $telegramBotNavigationService, CalendarEventService $calendarEventService,
ImageService $imageService)
{
parent::__construct($logger, $em, $telegramMessageService, $emService, $telegramBotService, $telegramBotNavigationService,
$imageService);
$this->telegramBotChatService = $telegramBotChatService;
$this->kernel = $kernel;
$this->deleteRemoteMessagesService = $deleteRemoteMessagesService;
$this->telegramUserService = $telegramUserService;
$this->telegramBotService = $telegramBotService;
$this->userService = $userService;
$this->candidateService = $candidateService;
$this->personService = $personService;
$this->calendarEventService = $calendarEventService;
$this->setApiToken($_ENV["CANDIDATES_PHOTO_TELEGRAM_BOT_API_TOKEN"]);
// $this->setBotTelegramIds([/*dev*/ "6871142341", /*prod*/ "6341096966"]);
$this->setInnerBotId("candidate_photos_bot");
$this->telegramChatService = $telegramChatService;
$this->botNavigation = new BotNavigation($this, $calendarEventService, $userService, $candidateService);
}
public function handleUpdate($update)
{
$chatId = $update->getData()["message"]["chat"]["id"] ?? null;
$text = $update->getData()["message"]["text"] ?? null;
$username = $update->getData()["message"]["from"]["username"] ?? "";
$userId = $update->getData()["message"]["from"]["id"] ?? null;
$firstName = $update->getData()["message"]["from"]["first_name"] ?? "";
$lastName = $update->getData()["message"]["from"]["last_name"] ?? "";
$isCallbackQuery = isset($update->getData()['callback_query']);
if (!isset($update->getData()['message'])
&& (!$isCallbackQuery || !isset($update->getData()['callback_query']['message']))) {
return;
}
$messageData = ($isCallbackQuery
? $update->getData()['callback_query']['message']
: $update->getData()['message']);
$message = $this->telegramMessageService->createOrGet($messageData, false);
$user = $this->telegramUserService->createOrGet($isCallbackQuery
? $update->getData()['callback_query']['from']
: $messageData["from"]);
$this->handleMessage($update, $message, $user, $isCallbackQuery);
}
// private function checkPhotoEditableMessageExists(TelegramUser $user, string $chatId): bool
// {
// $editableMessageId = $this->getEditableMessageId($user, EditableMessage::EDITABLE_MESSAGE_ID__PHOTO);
// if ($editableMessageId) {
// return $this->checkRemoteMessageExists($chatId, $editableMessageId);
// }
// return false;
// }
/**
* @var Candidate
*/
public $candidate;
/**
* @var TelegramUser
*/
public $telegramUser;
/**
* @var User
*/
public $user;
public function handleMessage(Update $update, TelegramMessage $message, TelegramUser $user, bool $isCallbackQuery = false)
{
$botOrGroupChatId = $message->getChatId();
$messageObj = $isCallbackQuery ? $update->getCallbackQuery()->getMessage() : $update->getMessage();
$navSelectedMenuItem = null;
$navMenuId = null;
if ($isCallbackQuery) {
$this->setNavigationSelectedItemIdByUpdate($user, $update);
$navMenuId = $this->getNavigationMenuIdByUpdate($update);
$navSelectedMenuItem = $this->getNavigationSelectedItem($user, $navMenuId);
}
$text = $isCallbackQuery
? $update->getCallbackQuery()->getDataField()
: $messageObj->getText();
$username = $user->getUsername();
// if ($update->getMessage() && $update->getMessage()->getFrom()) {
// /** @var TelegramUser|null $user */
// $user = $this->telegramUserService->createOrGet($update->getMessage()->getFrom()->getData());
// }
//todo redo
// if ($botOrGroupChatId != "172060981") {
// return;
// }
$sendMessages = [];
$appUser = $this->userService->getFirst([
"telegramUserId" => $user->getUserId()
]);
if (!$appUser) {
$sendMessages[] = $user->getName() . ", мы Вас не узнали 🙂. Пожалуйста, обратитесь к администратору.";
} else if ($appUser) {
$this->telegramUser = $user;
$this->user = $appUser;
$candidate = $this->candidateService->getLastDraft($appUser);
if (!$candidate) {
$navItemIds = $this->botNavigation->createCandidateFieldsMenu()['navItemIds'];
$this->botNavigation->resetCandidateFieldNamedNav($user,
($messageObj->getPhoto() ? $navItemIds[Menu::PHOTO_MENU_ID] : $navItemIds[Menu::PERSON_MENU_ID]));
$candidate = $this->candidateService->createDraft($appUser);
}
$this->candidate = $candidate;
if ($navSelectedMenuItem) {
$this->botNavigation->onAnyBotMenuItemSelect($botOrGroupChatId, $user, $navMenuId, $navSelectedMenuItem);
} else if ($messageObj && ($text || $messageObj->getPhoto())) {
$navItem = $this->getNavigationSelectedItem($user, Menu::CANDIDATE_FIELD_MENU_ID);
$lastSelectedCandidateFieldId = $navItem ? $navItem['id'] : null;
if ($messageObj->getPhoto() && $lastSelectedCandidateFieldId != Menu::PHOTO_MENU_ID) {
$lastSelectedCandidateFieldId = Menu::PHOTO_MENU_ID;
} else if ($text && !$messageObj->getPhoto() && !in_array($lastSelectedCandidateFieldId, [
Menu::PERSON_MENU_ID,
Menu::COMMENT_MENU_ID,
Menu::REVIEW_APPROVE_COMMENT_MENU_ID,
Menu::DATE_MENU_ID,
])) {
$lastSelectedCandidateFieldId = Menu::PERSON_MENU_ID;
}
$this->onContentSend($botOrGroupChatId, $messageObj, $user, $update, $lastSelectedCandidateFieldId, $text);
}
// $candidate = $this->candidateService->getDefault([
// "firstName" =>
// ]);
// $imagePath = $this->downloadMessagePhoto($update);
// dump($imagePath);
}
foreach ($sendMessages as $sendMessage) {
$this->sendMessage($botOrGroupChatId, $sendMessage);
}
}
private function onContentSend($chatId, $messageObj, TelegramUser $user, Update $update, $lastSelectedCandidateFieldId, $text)
{
switch ($lastSelectedCandidateFieldId) {
case Menu::PERSON_MENU_ID:
if ($text) {
try {
$this->deleteRemoteMessage($chatId, $messageObj->getMessageId());
} catch (\Throwable $exception) {
//ignore
}
$persons = $this->personService->findByTelegramText($text);
if ($persons) {
$this->botNavigation->sendSelectPersonMenu($chatId, $user, $persons, $text);
return;
} else {
$msg = "По вашему запросу \""
. htmlspecialchars($text) . "\" участник не найден. Пожалуйста, проверьте правильность написания"
. " имени или фамилии.\n\n"
. "🙍♂️ Введите имя участника заново:";
$this->botNavigation->sendSelectCandidateFieldMenu($chatId, $user, $msg);
return;
}
}
break;
case Menu::COMMENT_MENU_ID:
if ($text) {
try {
$this->deleteRemoteMessage($chatId, $messageObj->getMessageId());
} catch (\Throwable $exception) {
//ignore
}
$this->candidate->setComment($text);
$this->em->flush();
$this->botNavigation->sendSelectCandidateFieldMenu($chatId, $user);
}
break;
case Menu::REVIEW_APPROVE_COMMENT_MENU_ID:
if ($text) {
try {
$this->deleteRemoteMessage($chatId, $messageObj->getMessageId());
} catch (\Throwable $exception) {
//ignore
}
$this->candidate->setReviewApproveComment($text);
$this->em->flush();
$this->botNavigation->sendSelectCandidateFieldMenu($chatId, $user);
}
break;
case Menu::DATE_MENU_ID:
if ($text) {
try {
$this->deleteRemoteMessage($chatId, $messageObj->getMessageId());
} catch (\Throwable $exception) {
//ignore
}
$date = null;
try {
$date = new \DateTime($text . (new \DateTime())->format(" H:i:s"));
} catch (\Throwable $exception) {
//ignore
}
if (!$date) {
$msg = "❌ Неверный формат даты. Пожалуйста, введите дату в формате ДД.ММ.ГГГГ"
. " (например, 27.11.2025):";
$this->botNavigation->sendSelectCandidateFieldMenu($chatId, $user, $msg);
return;
}
$this->candidate->setCreatedAt($date);
$this->em->flush();
$this->botNavigation->sendSelectCandidateFieldMenu($chatId, $user);
}
break;
case Menu::PHOTO_MENU_ID:
$image = $this->downloadMessagePhoto($update);
$this->candidate->setImage($image);
$this->em->flush();
$this->updateCandidatePhoto($chatId, $update->getMessage()->getLastPhoto()->getFileId(), $messageObj);
$this->botNavigation->sendSelectCandidateFieldMenu($chatId, $user);
break;
default:
throw new \Exception("Unknown: " . $lastSelectedCandidateFieldId);
}
}
public function updateCandidatePhoto($chatId, $fileId, Message $messageToDelete = null)
{
$isPhotoChanged = false;
$telegramMessageId = $this->getEditableMessageId($this->telegramUser,
EditableMessage::EDITABLE_MESSAGE_ID__PHOTO);
if ($telegramMessageId) {
$isPhotoChanged = true;
try {
$this->editRemoteMessage($chatId, $telegramMessageId, null, null, $fileId);
} catch (MessageEditedBySameTextException $exception) {
//ignore
$isPhotoChanged = false;
} catch (MessageToEditNotFoundException $exception) {
$isPhotoChanged = false;
}
}
if (!$isPhotoChanged) {
$this->botNavigation->deleteMainEditableMessage($this->telegramUser, $chatId);
$this->botNavigation->editOrSendPhotoEditableMessage($this->telegramUser, $chatId, $fileId);
}
if ($messageToDelete) {
try {
$this->deleteRemoteMessage($chatId, $messageToDelete->getMessageId());
} catch (\Throwable $exception) {
//ignore
}
}
}
public function onPersonMenuItemSelect($chatId, TelegramUser $user, $selectedItemId, $navSelectedMenuItem)
{
/**
* @var Person
*/
$person = $this->personService->getBaseService()->get($navSelectedMenuItem['id']);
$this->candidate->setPerson($person);
$this->em->flush();
$this->botNavigation->sendSelectCandidateFieldMenu($chatId, $user);
}
public function onCalendarEventMenuItemSelect($chatId, TelegramUser $user, $selectedItemId, $navSelectedMenuItem)
{
/**
* @var CalendarEvent
*/
$event = $this->calendarEventService->getBaseService()->get($navSelectedMenuItem['id']);
$this->candidate->setCalendarEvent($event);
$this->em->flush();
$this->botNavigation->sendSelectCandidateFieldMenu($chatId, $user);
}
public function onAuthorMenuItemSelect($chatId, TelegramUser $user, $selectedItemId, $navSelectedMenuItem)
{
/**
* @var User
*/
$author = $this->userService->getBaseService()->get($navSelectedMenuItem['id']);
$this->candidate->setCurator($author);
$this->em->persist($this->candidate);
$this->em->persist($author);
$this->em->flush();
$this->botNavigation->sendSelectCandidateFieldMenu($chatId, $user);
}
public function onStatusMenuItemSelect($chatId, TelegramUser $user, $selectedItemId, $navSelectedMenuItem)
{
//do nothing. Status is set on confirm
$this->botNavigation->sendSelectCandidateFieldMenu($chatId, $user);
}
public function onCandidateConfirmMenuItemSelect($chatId, TelegramUser $user)
{
if ($this->candidateService->existsSame($this->candidate)) {
$msg = "❌ Кандидат с таким именем уже зарегистрирован для данного мероприятия."
. " Пожалуйста, измените имя кандидата или мероприятие.";
$this->botNavigation->sendSelectCandidateFieldMenu($chatId, $user, $msg);
return;
}
$navStatusSelectedItem = $this->getNavigationSelectedItem($user,
Menu::STATUS_MENU_ID);
$confirmResult = $this->candidateService->confirmCandidate($this->candidate,
($navStatusSelectedItem ? $navStatusSelectedItem['id'] : Status::STATUS_NEW));
if ($confirmResult['result']) {
if ($this->candidate->getImage()) {
$this->personService->setPersonImage($this->candidate->getPerson(), $this->candidate->getImage());
}
$this->botNavigation->sendAfterCandidateSendMenu($chatId, $user);
$this->botNavigation->resetEditableMessages($user);
} else {
$needFieldsText = array_reduce($confirmResult['needFields'], function($carry, $item) {
return $carry . ($carry ? ", " : "") . $item['text'];
}, "");
$needFieldsText = StringUtils::addDot($needFieldsText);
$msg = "❌ Невозможно отправить"
. " анкету. Не все данные введены или не соответствуют требованиям: $needFieldsText Выберите поле анкеты участника для изменения:";
$this->botNavigation->sendSelectCandidateFieldMenu($chatId, $user, $msg);
return;
}
}
public function sendMenuById($chatId, TelegramUser $user, $menuId, $msg = null)
{
switch ($menuId) {
case Menu::CALENDAR_EVENT_MENU_ID:
$this->botNavigation->sendSelectCalendarEventMenu($chatId, $user);
break;
// case Menu::PERSON_MENU_ID:
// $this->botNavigation->sendSelectPersonMenu($chatId, $user);
// break;
case Menu::AUTHOR_MENU_ID:
$this->botNavigation->sendSelectAuthorMenu($chatId, $user);
break;
case Menu::STATUS_MENU_ID:
$this->botNavigation->sendSelectStatusMenu($chatId, $user);
break;
case Menu::CANDIDATE_FIELD_MENU_ID:
$this->botNavigation->sendSelectCandidateFieldMenu($chatId, $user, $msg);
break;
case Menu::OTHER_MENU_ID:
$this->botNavigation->sendSelectOtherMenu($chatId, $user, $msg);
break;
default:
throw new \Exception("Unknown: " . $menuId);
}
}
public function onCopyLastCandidateMenuItemSelect($chatId, TelegramUser $user, $navSelectedMenuItem, $sendNextMenuId = null)
{
$lastCandidate = $this->candidateService->getLastNonDraftCandidate($this->user);
if (!$sendNextMenuId) {
$sendNextMenuId = Menu::OTHER_MENU_ID;
}
if ($lastCandidate) {
$this->candidateService->copyCandidateDataToDraft($lastCandidate, $this->candidate);
if ($lastCandidate->getImage()) {
$clonedImage = $this->imageService->cloneImage($lastCandidate->getImage());
$messageData = $this->sendImage($chatId,
$this->imageService->getRealPath($clonedImage));
$this->updateCandidatePhoto($chatId,
$messageData->getLastPhoto()->getFileId(), $messageData);
$this->candidate->setImage($clonedImage);
$this->em->flush();
}
$msg = "✅ Анкета последнего участника скопирована в черновик."
. " Теперь вы можете изменить необходимые поля или подтвердить регистрацию участника.";
$this->sendMenuById($chatId, $user, $sendNextMenuId, $msg);
} else {
$this->sendMenuById($chatId, $user, $sendNextMenuId, "❌ У Вас нет ранее зарегистрированных участников.");
}
}
public function onResetCandidateMenuItemSelect($chatId, TelegramUser $user, $navSelectedMenuItem, $sendNextMenuId = null)
{
$image = $this->candidate->getImage();
if ($image) {
$this->candidate->setImage(null);
$this->imageService->delete($image, false);
}
$this->candidate
->setPerson(null)
->setCalendarEvent(null)
->setImage(null)
->setCurator(null)
->setComment(null)
->setReviewApproveComment(null)
;
$this->em->flush();
if ($this->getEditableMessageId($user,
EditableMessage::EDITABLE_MESSAGE_ID__PHOTO)) {
try {
$this->deleteRemoteMessage($chatId, $this->getEditableMessageId($user,
EditableMessage::EDITABLE_MESSAGE_ID__PHOTO));
} catch (\Throwable $exception) {
//ignore
}
}
$msg = "✅ Анкета сброшена.";
$this->sendMenuById($chatId, $user, $sendNextMenuId, $msg);
}
public function onUpdatesHandled()
{
if ($this->sentMessages) {
foreach ($this->sentMessages as $message) {
$this->em->persist($message);
}
$this->em->flush();
$this->sentMessages = [];
}
}
private function runBotCommandStartNewPlusCounter(CountPlusSettings $countPlusSettings, &$sendMessages, TelegramUser $user, $text, $chatId, $adminChatId)
{
if (!$user->getWaitBotCommandParam()) {
$user->changeWaitBotCommandParam(["novii_podschet_plusov" => "askYesNo"]);
$this->emService->save($user);
$sendMessages[] = "Уверены? Введите \"да\" или \"нет\" (без кавычек)";
return;
} else {
$result = $this->checkCommandParamType($text, "string", $adminChatId, $user, null, null, false,
null, true);
if ($result === "yes") {
$this->startNewPlusCounter($chatId, $countPlusSettings, $sendMessages);
$user->clearWaitBotCommandParam();
$this->emService->save($user);
return;
} else if ($result === "no") {
$user->clearWaitBotCommandParam();
$this->emService->save($user);
$sendMessages[] = "Команда отменена";
return;
}
}
}
public function startNewPlusCounter($chatId, CountPlusSettings $countPlusSettings, &$sendMessages,
$includeLastPlusMessage = false)
{
if ($countPlusSettings->getUsersListMessageId() &&
$countPlusSettings->getCountAfterMessageId())
{
$statistics = $this->telegramMessageService->getPlusMessagesStatistics($chatId, $countPlusSettings,
false, false);
$statistics .= "\n\nПодсчет завершен";
$statistics .= "\n-----";
if ($countPlusSettings->getUsersListMessageId()) {
$usersListMessage = $this->telegramMessageService->getUsersListMessage($chatId,
$countPlusSettings);
if ($usersListMessage) {
$this->editRemoteMessage($chatId, $usersListMessage->getMessageId(),
"💫💫💫💫💫️ Спасибо, все участники отметились!");
$removeAt = (new \DateTime())->setTime($countPlusSettings->getAutoRestartTime()->format("H"),
$countPlusSettings->getAutoRestartTime()->format("i"));
$removeAfterMins = null;
if (new \DateTime() >= $removeAt) {
$removeAt = null;
$removeAfterMins = 1;
}
$this->deleteRemoteMessagesService->create(
$usersListMessage, $removeAfterMins, $removeAt);
}
}
$sendMessages[] = $statistics;
$countPlusSettings->setUsersListMessageId(null);
$this->em->flush();
}
$q = $this->em->getRepository(TelegramMessage::class)->createQueryBuilder('tm');
$q
->where("tm.chatId = :chatId")
// ->andWhere("tm.isDeleted != true") //не ставить!
->setParameter("chatId", $chatId)
->setMaxResults($includeLastPlusMessage ? 2 : 1)
->orderBy("tm.id", "DESC");
$message = $q->getQuery()->getResult();
/** @var TelegramMessage $message */
if ($message) {
$message = $message[!$includeLastPlusMessage ? 0 : (count($message) > 1 ? 1 : 0)];
$countPlusSettings->setCountAfterMessageId($message->getId());
// if ($message->getText()) {
// $sendMessages[] = "Последнее сообщение {$message->getDateTime()->format("H:i")}" .
// " от {$message->getName()}: " . $message->getText();
// }
}
$countPlusSettings->setStartedAt(new \DateTime());
$this->em->flush();
$sendMessages[] = "Новый счетчик плюсов создан!";
}
public function onMessageSend($message)
{
$this->sentMessages[] = $message;
}
private function ktoNePostavil($chatId, $countPlusSettings, array &$sendMessages)
{
$allChatUsers = $this->telegramMessageService
->getAllChatUsers($chatId);
/** @var TelegramMessage[] $plusUsers */
$plusUsers = $this->telegramMessageService->getPlusMessages($chatId, $countPlusSettings);
$usersDidntSendPlus = array_filter($allChatUsers, function ($cur) use ($plusUsers) {
foreach ($plusUsers as $plusUser) {
if ((int)$plusUser->getUserId() == (int)$cur['userId']) {
return false;
}
}
return true;
});
$usersDidntSentPlusStatistics = "Список не отметившихся (нажмите на имя, чтобы перейти в чат):\n\n";
$usersDidntSendPlusStr = array_map(function ($cur) {return "<a href=\"tg://user?id=" . $cur['userId'] . "\">" . trim($cur['name']) . "</a>";},
$usersDidntSendPlus);
$usersDidntSendPlusStr = array_reduce($usersDidntSendPlusStr,
function ($cur, $all) {return $all . ($all ? "\n" : "") . $cur;});
$all = Other::getSettings("allUsers", true);
$all = explode("\r\n", $all);
$plusMessageUserNames = $this->telegramMessageService->getPlusMessages($chatId, $countPlusSettings);
$plusMessageUserNames = array_map(function ($cur) {return "<a href=\"tg://user?id=" . $cur->getUserId() . "\">" . trim($cur->getName()) . "</a>'";}, $plusMessageUserNames);
$usersDidntSentPlusStatistics .= $usersDidntSendPlusStr;
$usersDidntSentPlusStatistics .= "\nНайдено: " . count($usersDidntSendPlus) . " из " . count($allChatUsers) . "\n";
// $manualList = array_diff($all, $plusMessageUserNames);
// $usersDidntSentPlusStatistics .= "\nСравнение с ручным списком:\n\n" .
// array_reduce($manualList, function ($c, $a) {return $a . "\n". $c;});
// $usersDidntSentPlusStatistics .= "\nНайдено: " . count($manualList) . "\n";
$sendMessages[] = $usersDidntSentPlusStatistics;
}
private function avtoPerezapuskSchetchPlusov(CountPlusSettings $countPlusSettings, array &$sendMessages)
{
if (!$countPlusSettings->getChatUsersCount()) {
$sendMessages[] = "Сначала необходимо ввести кол-во участников группы с " .
"помощью команды /ustanovit_kol_vo_uchastnikov";
return;
}
$countPlusSettings->toggleAutoRestartPlusCounter();
$this->emService->save($countPlusSettings);
$sendMessages[] = "Авто перезапуск счетчика плюсов при достижении" .
" плюсов в кол-ве " . $countPlusSettings->getChatUsersCount() .
" " . $countPlusSettings->getAutoRestartPlusCounterText() .
($countPlusSettings->getAutoRestartPlusCounter() ?
".\nВнимание! При встулении или выходе из группы участников," .
" необходимо заново установить вручную кол-во участников группы" .
" для правильного срабатывания авто перезапуска счетчика плюсов, с пом." .
" команды /ustanovit_kol_vo_uchastnikov!" : "");
}
private function ustanovitKolVoUchastnikov(CountPlusSettings $countPlusSettings, array &$sendMessages, TelegramUser $user, $text,
$chatId)
{
if ($user->getWaitBotCommandParam() ==
["ustanovit_kol_vo_uchastnikov" => "usersCount"])
{
$result = $this->checkCommandParamType($text, "int", $chatId, $user, 1);
if ($result === false || $result === "canceled") {
return;
}
$countPlusSettings->setChatUsersCount((int)$text);
$user->setWaitBotCommandParam(null);
$this->emService->save($countPlusSettings, $user);
$sendMessages[] = "Установлено кол-во участников группы: " . $text;
return;
}
$sendMessages[] = "Введите кол-во участников группы. Либо введите слово \"отмена\""
. " (без кавычек) для отмены ввода";
$user->setWaitBotCommandParam(["ustanovit_kol_vo_uchastnikov" => "usersCount"]);
$this->emService->save($user);
}
private function posmotretNastroikiBota(CountPlusSettings $countPlusSettings, array &$sendMessages)
{
$result = "Настройки бота:
- Введенное кол-во участников группы: {$countPlusSettings->getChatUsersCountText()}
- Авто перезапуск счетчика плюсов (при достижении плюсов в кол-ве: " .
"{$countPlusSettings->getChatUsersCountText()}): "
. "{$countPlusSettings->getAutoRestartPlusCounterText()}";
$sendMessages[] = $result;
}
/**
* @param array|null|TelegramUser[] $admins
* @param CountPlusSettings $countPlusSettings
* @param $chatId
* @param TelegramUser $user
* @param TelegramMessage $message
* @param $isPlusMessage
* @return void
* @throws MessageIdentifierIsNotSpecified
*/
private function handleNonAdminMessage(?array $admins, CountPlusSettings $countPlusSettings, $chatId, TelegramUser $user, TelegramMessage $message,
$isPlusMessage)
{
if (!$isPlusMessage) {
return;
}
$sendMessages = [];
if ($countPlusSettings->getStartedAt() &&
new \DateTime() > (clone $countPlusSettings->getStartedAt())->modify("+48 hour")
) {
return;
}
$result = null;
if ($message->getMessageId() != 0) {
try {
$result = $this->deleteRemoteMessage($message->getChatId(), $message->getMessageId());
} catch (MessageToDeleteNotFoundException|MessageCantBeDeleted|MessageCantBeDeletedForEveryone
$exception)
{
$result = ["result" => true];
}
} else if ($message->getMessageId() == 0) {
$result = ["result" => true];
}
if ($result["result"] === true) {
$message->setIsDeleted(true);
$this->em->flush();
}
$this->restartPlusCounterOnTimeOutIfNeeded($admins, $chatId, $countPlusSettings);
if ($this->telegramMessageService->isMessageWithPlusWasAlreadySend(
$countPlusSettings, $message->getUserId()))
{
$result = $this->sendMessage($chatId, "✔️ Спасибо, {$user->getName()}, ваша отметка уже была учтена." .
" (данное сообщение автоматически удалится через 1 мин.)");
} else {
$result = $this->sendMessage($chatId, "✔️ Спасибо, {$user->getName()}, ваша отметка учтена." .
" (данное сообщение автоматически удалится через 1 мин.)");
}
$this->deleteRemoteMessagesService->create($result, 1);
$this->updatePlusList($countPlusSettings, $chatId);
foreach ($sendMessages as $sendMessage) {
$this->sendMessage($chatId, $sendMessage);
}
if ($isPlusMessage && $countPlusSettings->getChatUsersCount() &&
$countPlusSettings->getAutoRestartPlusCounter())
{
$this->restartPlusCounterIfComplete($chatId, $countPlusSettings, $admins);
}
}
private function restartPlusCounterOnTimeOutIfNeeded($admins, $chatId, CountPlusSettings $countPlusSettings): void
{
$autoRestartTime = null;
if ($countPlusSettings->getAutoRestartTime() && $countPlusSettings->getStartedAt()) {
$autoRestartTime = (clone $countPlusSettings->getStartedAt())
->modify("+1 day")
->setTime($countPlusSettings->getAutoRestartTime()->format("H"),
$countPlusSettings->getAutoRestartTime()->format("i"));
}
$isPlusCounterRestartTime = $autoRestartTime && (new \DateTime() >= $autoRestartTime);
if ($isPlusCounterRestartTime) {
$adminMsg = "Срабтал автоматический перезапуск счетчика плюсов по времени: " .
$countPlusSettings->getAutoRestartTime()->format("H:i");
$this->restartPlusCounter($admins, $adminMsg, $chatId, $countPlusSettings, true);
}
}
private function isPlusCounterComplete(CountPlusSettings $countPlusSettings, $chatId): bool
{
return $countPlusSettings->getChatUsersCount() ==
count($this->telegramMessageService->getPlusMessages($chatId, $countPlusSettings));
}
private function restartPlusCounterIfComplete($chatId, CountPlusSettings $countPlusSettings, $admins)
{
$isPlusCounterComplete = $this->isPlusCounterComplete($countPlusSettings, $chatId);
$adminMsg = null;
if ($isPlusCounterComplete) {
$adminMsg = "Кол-во плюсов достигло кол-ва участников в группе: " .
$countPlusSettings->getChatUsersCount();
}
if ($isPlusCounterComplete)
{
$this->restartPlusCounter($admins, $adminMsg, $chatId, $countPlusSettings);
}
}
private function restartPlusCounter($admins, $adminMsg, $chatId, CountPlusSettings $countPlusSettings,
$includeLastPlusMessage = false)
{
foreach ($admins as $admin) {
try {
$this->sendMessage($admin->getUserId(), $adminMsg);
$this->startNewPlusCounter($chatId, $countPlusSettings, $tmpSendMessages, $includeLastPlusMessage);
foreach ($tmpSendMessages as $tmpSendMessage) {
$this->sendMessage($admin->getUserId(), $tmpSendMessage);
}
} catch (\Throwable $e) {
$this->logger->error("Error sending message to admin: " . $e->getMessage());
}
}
}
public function updatePlusList(CountPlusSettings $countPlusSettings, $chatId)
{
$statistics = $this->telegramMessageService->getPlusMessagesStatistics($chatId, $countPlusSettings);
if (!$countPlusSettings->getUsersListMessageId()) {
$result = $this->sendMessage($chatId, $statistics);
$countPlusSettings->setUsersListMessageId($result->getMessageId());
$this->em->flush();
} else {
try {
$this->editRemoteMessage($chatId, $countPlusSettings->getUsersListMessageId(),
$statistics);
} catch (MessageEditedBySameTextException $exception) {
//do nothing
} catch (MessageToEditNotFoundException $exception) {
$result = $this->sendMessage($chatId, $statistics);
$countPlusSettings->setUsersListMessageId($result->getMessageId());
$this->em->flush();
}
}
}
protected function onBotAddedToGroup(Update $update, string $chatId, string $userId)
{
$user = $this->telegramUserService->createOrGet($update->getMessage()->getFrom()->getData());
$group = $this->telegramChatService->createOrGetDefault([
"chatId" => $update->getMessage()->getChat()->getId(),
"title" => $update->getMessage()->getChat()->getTitle(),
"type" => $update->getMessage()->getChat()->getType(),
]);
$this->telegramUserService->addAdministratesChat($user, $group);
$bot = $this->getTelegramBotEntity();
$this->telegramBotService->addBotToChat($bot, $group);
}
}