<?php
namespace App\EventSubscriber\App;
use App\Entity\AutomatedConversationMessagesMailing;
use App\Entity\PlatformEvent;
use App\Entity\UsageEvent;
use App\Event\ConversationMessageDeletedByReceiverEvent;
use App\Event\ConversationMessageDirectAppliedEvent;
use App\Event\ConversationMessageReadEvent;
use App\Event\ConversationMessageRestoredByReceiverEvent;
use App\Event\ConversationMessageSentEvent;
use App\Service\ActivityMonitoringService;
use App\Service\BrowserPushNotificationService;
use App\Service\ConversationMessageService;
use App\Service\ConversionEventService;
use App\Service\DirectEmailCommunicationService;
use App\Service\NotificationService;
use App\Service\PlatformEventService;
use App\Service\RecurrentJobService;
use App\Service\UsageEventService;
use App\Service\UserService;
use App\Service\WhatsAppIntegration\WhatsAppMessageService;
use App\SymfonyMessage\NotifyUserAboutUnreadIntegratedExternalPartnerCustomerPremiumRadarMessageViaWhatsAppSymfonyMessage;
use App\SymfonyMessage\NotifyUserAboutUnreadOrganicConversationMessageViaWhatsAppSymfonyMessage;
use App\SymfonyMessage\UpdateCachedUnreadConversationMessagesCountSymfonyMessage;
use App\Utility\DateTimeUtility;
use DateTime;
use Exception;
use JanusHercules\DatawarehouseIntegration\Domain\Entity\BusinessEvent;
use JanusHercules\DatawarehouseIntegration\Domain\Entity\ExternalPartnerEvent;
use JanusHercules\DatawarehouseIntegration\Domain\Service\BusinessEventDomainService;
use JanusHercules\DatawarehouseIntegration\Domain\Service\ExternalPartnerEventDomainService;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Messenger\Stamp\DelayStamp;
use Throwable;
class ConversationMessageEventSubscriber implements EventSubscriberInterface
{
private ActivityMonitoringService $activityMonitoringService;
private LoggerInterface $logger;
private BrowserPushNotificationService $browserPushNotificationService;
private UserService $userService;
private BusinessEventDomainService $businessEventDomainService;
private ConversionEventService $conversionEventService;
private ConversationMessageService $conversationMessageService;
private UsageEventService $usageEventService;
private ExternalPartnerEventDomainService $externalPartnerEventDomainService;
private DirectEmailCommunicationService $directEmailCommunicationService;
private MessageBusInterface $messageBus;
private RecurrentJobService $recurrentJobService;
private WhatsAppMessageService $whatsAppMessageService;
private PlatformEventService $platformEventService;
public function __construct(
ActivityMonitoringService $activityMonitoringService,
LoggerInterface $logger,
BrowserPushNotificationService $browserPushNotificationService,
UserService $userService,
BusinessEventDomainService $businessEventDomainService,
ConversionEventService $conversionEventService,
ConversationMessageService $conversationMessageService,
UsageEventService $usageEventService,
ExternalPartnerEventDomainService $externalPartnerEventDomainService,
DirectEmailCommunicationService $directEmailCommunicationService,
MessageBusInterface $messageBus,
RecurrentJobService $recurrentJobService,
WhatsAppMessageService $whatsAppMessageService,
PlatformEventService $platformEventService
) {
$this->activityMonitoringService = $activityMonitoringService;
$this->logger = $logger;
$this->browserPushNotificationService = $browserPushNotificationService;
$this->userService = $userService;
$this->businessEventDomainService = $businessEventDomainService;
$this->conversionEventService = $conversionEventService;
$this->conversationMessageService = $conversationMessageService;
$this->usageEventService = $usageEventService;
$this->externalPartnerEventDomainService = $externalPartnerEventDomainService;
$this->directEmailCommunicationService = $directEmailCommunicationService;
$this->messageBus = $messageBus;
$this->recurrentJobService = $recurrentJobService;
$this->whatsAppMessageService = $whatsAppMessageService;
$this->platformEventService = $platformEventService;
}
public static function getSubscribedEvents(): array
{
return [
ConversationMessageSentEvent::class => 'onConversationMessageSent',
ConversationMessageDirectAppliedEvent::class => 'onConversationMessageDirectApplied',
ConversationMessageReadEvent::class => 'onConversationMessageRead',
ConversationMessageDeletedByReceiverEvent::class => 'onConversationMessageDeletedByReceiverEvent',
ConversationMessageRestoredByReceiverEvent::class => 'onConversationMessageRestoredByReceiverEvent'
];
}
/**
* @throws Exception
*/
public function onConversationMessageSent(ConversationMessageSentEvent $event): void
{
$this->messageBus->dispatch(
new UpdateCachedUnreadConversationMessagesCountSymfonyMessage(
$event->getConversationMessage()->getReceiverProfile()->getUser()
)
);
$conversationMessage = $event->getConversationMessage();
try {
$this->activityMonitoringService->handleConversationMessageSentActivity($conversationMessage);
} catch (Throwable $t) {
// While this is important for us, it's not crucial for the user, which is why we ensure that a user doesn't
// run into an error if we get an exception.
$this->logger->warning(
"Error while calling ActivityMonitoringService::handleConversationMessageSentActivity: {$t->getMessage()}",
['exception' => $t]);
}
$this->browserPushNotificationService->handleConversationMessageSent($conversationMessage);
$this->businessEventDomainService->writeNewEvent(
BusinessEvent::EVENT_TYPE_SENT_SINGLE_CONVERSATION_MESSAGE,
$conversationMessage->getSenderProfile()->getUser(),
$conversationMessage->getRelatedRecurrentJob(),
$conversationMessage->getRelatedWantedJob(),
json_encode([
'conversationMessageId' => $conversationMessage->getId(),
'joboffererProfileId' => $conversationMessage->getSenderProfile()->isJobofferer() ? $conversationMessage->getSenderProfile()->getId() : $conversationMessage->getReceiverProfile()->getId(),
'jobseekerProfileId' => $conversationMessage->getSenderProfile()->isJobseeker() ? $conversationMessage->getSenderProfile()->getId() : $conversationMessage->getReceiverProfile()->getId(),
'senderIsJobseeker' => $conversationMessage->getSenderProfile()->isJobseeker(),
'senderIsJobofferer' => $conversationMessage->getSenderProfile()->isJobofferer(),
'isPartOfMultiple' => !is_null($conversationMessage->getMultiConversationMessagesMailing()),
'isPartOfAutomatedConversationMessagesMailing' => !is_null($conversationMessage->getAutomatedConversationMessagesMailing())
])
);
if ($conversationMessage->isAutomatedMessage()) {
$this->businessEventDomainService->writeNewEvent(
BusinessEvent::EVENT_TYPE_SENT_AUTOMATED_CONVERSATION_MESSAGE,
$conversationMessage->getReceiverProfile()->getUser(),
$conversationMessage->getRelatedRecurrentJob(),
$conversationMessage->getRelatedWantedJob(),
json_encode([
'conversationMessageId' => $conversationMessage->getId(),
'jobseekerProfileId' => $conversationMessage->getJobseekerProfile()->getId(),
'joboffererProfileId' => $conversationMessage->getJoboffererProfile()->getId(),
'senderIsJobseeker' => false,
'senderIsJobofferer' => true,
'automatedConversationMessagesMailingId' => $conversationMessage->getAutomatedConversationMessagesMailing()->getId(),
'automatedConversationMessagesMailingType' => $conversationMessage->getAutomatedConversationMessagesMailing()->getMailingType(),
'automatedConversationMessagesTriggeringSide' => $conversationMessage->getAutomatedConversationMessagesMailing()->getTriggeringSide()
])
);
}
if ($conversationMessage->isAutomatedJobradarMessage()) {
$this->logger->warning(
"Conversation Message '{$conversationMessage->getId()}' is an automated Jobradar message, but these must no longer be created, because they are replaced by Jobradar Matches."
);
} elseif (!$conversationMessage->isAutomatedMessage()) {
$since = DateTime::createFromFormat('d/m/Y', '25/09/2019');
if ($this->conversationMessageService->getNumberOfMessagesAndExtendedApplicationsReceivedByProfileWithoutAutomatedMessagesSinceDate(
$conversationMessage->getReceiverProfile(),
$since
) >= 4
&& !$this->usageEventService->hasEventOccurredForUser(
$conversationMessage->getReceiverProfile()->getUser(),
UsageEvent::EVENT_TYPE_USER_RECEIVED_FIVE_MESSAGES_EXCLUDING_JOBRADAR
)
) {
$this->usageEventService->eventHasOccurredForUser(
$conversationMessage->getReceiverProfile()->getUser(),
UsageEvent::EVENT_TYPE_USER_RECEIVED_FIVE_MESSAGES_EXCLUDING_JOBRADAR
);
}
if ($conversationMessage->getSenderProfile()->getUser()->isJobofferer()) {
$this->usageEventService->eventHasOccurredForUser(
$conversationMessage->getSenderProfile()->getUser(),
UsageEvent::EVENT_TYPE_JOBOFFERER_SENT_MESSAGE
);
}
if ($conversationMessage->getSenderProfile()->getUser()->isJobseeker()) {
$this->usageEventService->eventHasOccurredForUser(
$conversationMessage->getSenderProfile()->getUser(),
UsageEvent::EVENT_TYPE_JOBSEEKER_SENT_MESSAGE
);
}
$this->usageEventService->eventHasOccurredForUser(
$conversationMessage->getSenderProfile()->getUser(),
UsageEvent::EVENT_TYPE_USER_SENT_CONVERSATION_MESSAGE
);
if ($conversationMessage->getReceiverProfile()->isJobseeker()) {
if ($this->whatsAppMessageService->canProfileReceiveWhatsAppMessages($conversationMessage->getReceiverProfile())) {
$this->messageBus->dispatch(
new NotifyUserAboutUnreadOrganicConversationMessageViaWhatsAppSymfonyMessage(
$conversationMessage
),
[DelayStamp::delayUntil(
DateTimeUtility::createDateTimeUtcForUpcomingMinuteSecond(
(int)DateTimeUtility::createDateTimeUtc()->format('i'),
(int)DateTimeUtility::createDateTimeUtc()->format('s'),
false,
7,
21
)
)]
);
}
}
if (!is_null($conversationMessage->getMultiConversationMessagesMailing())) {
$this->businessEventDomainService->writeNewEvent(
BusinessEvent::EVENT_TYPE_SENT_MULTIPLE_CONVERSATION_MESSAGES,
$conversationMessage->getSenderProfile()->getUser(),
null,
null,
json_encode([
'jobseekerProfileId' => $conversationMessage->getJobseekerProfile()->getId(),
'joboffererProfileId' => $conversationMessage->getJoboffererProfile()->getId(),
'senderIsJobseeker' => $conversationMessage->getSenderProfile()->isJobseeker(),
'senderIsJobofferer' => $conversationMessage->getSenderProfile()->isJobofferer()
])
);
$this->usageEventService->eventHasOccurredForUser(
$conversationMessage->getSenderProfile()->getUser(),
UsageEvent::EVENT_TYPE_USER_SENT_CONVERSATION_MESSAGE
);
$this->usageEventService->eventHasOccurredForUser($conversationMessage->getSenderProfile()->getUser(), UsageEvent::EVENT_TYPE_USER_HAS_SENT_MULTIPLE_MESSAGES);
if ($conversationMessage->getSenderProfile()->isJobseeker()) {
$this->usageEventService->eventHasOccurredForUser($conversationMessage->getSenderProfile()->getUser(), UsageEvent::EVENT_TYPE_JOBSEEKER_SENT_MESSAGE);
} elseif ($conversationMessage->getSenderProfile()->isJobofferer()) {
$this->usageEventService->eventHasOccurredForUser($conversationMessage->getSenderProfile()->getUser(), UsageEvent::EVENT_TYPE_JOBOFFERER_SENT_MESSAGE);
}
}
}
if (!is_null($conversationMessage->getAutomatedConversationMessagesMailing())) {
if (!is_null($conversationMessage->getJoboffererProfile()->getUser()->getExternalPartner()) && $conversationMessage->getAutomatedConversationMessagesMailing()->getMailingType() === AutomatedConversationMessagesMailing::MAILING_TYPE_JOBRADAR) {
$this->logger->warning(
"Conversation Message '{$conversationMessage->getId()}' is an automated Jobradar message, but these must no longer be created, because they are replaced by Jobradar Matches."
);
$this->externalPartnerEventDomainService->writeEvent(
ExternalPartnerEvent::EVENT_TYPE_JOBRADAR_CREATED,
$conversationMessage->getJoboffererProfile()->getUser()->getExternalPartner(),
$conversationMessage->getRelatedRecurrentJob(),
null,
$conversationMessage->getRelatedWantedJob(),
$conversationMessage,
null,
null,
$conversationMessage->getRelatedWantedJob()->getJobseekerProfile()->getUser(),
null
);
}
if ($conversationMessage->getAutomatedConversationMessagesMailing()->getMailingType() === AutomatedConversationMessagesMailing::MAILING_TYPE_INTEGRATED_EXTERNAL_PARTNER_CUSTOMER_PREMIUM_RADAR) {
if ($conversationMessage->getReceiverProfile()->isJobseeker()) {
if ($this->whatsAppMessageService->canProfileReceiveWhatsAppMessages($conversationMessage->getReceiverProfile())) {
$this->messageBus->dispatch(
new NotifyUserAboutUnreadIntegratedExternalPartnerCustomerPremiumRadarMessageViaWhatsAppSymfonyMessage(
$conversationMessage
),
[DelayStamp::delayUntil(
DateTimeUtility::createDateTimeUtcForUpcomingMinuteSecond(
(int)DateTimeUtility::createDateTimeUtc()->format('i'),
(int)DateTimeUtility::createDateTimeUtc()->format('s'),
false,
7,
21
)
)]
);
}
}
$this->externalPartnerEventDomainService->writeEvent(
ExternalPartnerEvent::EVENT_TYPE_PREMIUM_JOBRADAR_CREATED,
$conversationMessage->getJoboffererProfile()->getUser()->getExternalPartner(),
$conversationMessage->getRelatedRecurrentJob(),
null,
$conversationMessage->getRelatedWantedJob(),
$conversationMessage,
null,
null,
$conversationMessage->getRelatedWantedJob()->getJobseekerProfile()->getUser(),
null
);
}
if ($conversationMessage->getAutomatedConversationMessagesMailing()->getMailingType() === AutomatedConversationMessagesMailing::MAILING_TYPE_WISAG) {
$this->externalPartnerEventDomainService->writeEvent(
ExternalPartnerEvent::EVENT_TYPE_WISAG_RADAR_CREATED,
$conversationMessage->getJoboffererProfile()->getUser()->getExternalPartner(),
$conversationMessage->getRelatedRecurrentJob(),
null,
$conversationMessage->getRelatedWantedJob(),
$conversationMessage,
null,
null,
$conversationMessage->getRelatedWantedJob()->getJobseekerProfile()->getUser(),
null
);
}
if ($conversationMessage->getAutomatedConversationMessagesMailing()->getMailingType() === AutomatedConversationMessagesMailing::MAILING_TYPE_WISAG_PREMIUM) {
$this->externalPartnerEventDomainService->writeEvent(
ExternalPartnerEvent::EVENT_TYPE_WISAG_PREMIUM_RADAR_CREATED,
$conversationMessage->getJoboffererProfile()->getUser()->getExternalPartner(),
$conversationMessage->getRelatedRecurrentJob(),
null,
$conversationMessage->getRelatedWantedJob(),
$conversationMessage,
null,
null,
$conversationMessage->getRelatedWantedJob()->getJobseekerProfile()->getUser(),
null
);
}
}
$this->userService->unpauseIfPaused(
$conversationMessage->getSenderProfile()->getUser()
);
$this->conversionEventService->handleConversionGoalReached(
ConversionEventService::CAMPAIGN_ID_OUTGOING_DIRECT_EMAILS,
2,
null,
$event->getConversationMessage()->getSenderProfile()->getUser()
);
foreach ([0, 1, 2, 3, 4, 5, 6, 7] as $subcampaignId) {
$this->conversionEventService->handleConversionGoalReached(
ConversionEventService::CAMPAIGN_ID_RECURRENT_JOBS_SEARCH_FOR_ONE_SPECIFIC_CUSTOMER,
$subcampaignId,
null,
$event->getConversationMessage()->getSenderProfile()->getUser(),
$event->getConversationMessage()->getRelatedRecurrentJob(),
null,
null,
!is_null($event->getConversationMessage()->getRelatedRecurrentJob())
? $event->getConversationMessage()->getRelatedRecurrentJob()->getIntegratedExternalPartnerCustomer()
: null
);
}
if ($this->conversationMessageService->getNumberOfUnreadMessages($event->getConversationMessage()->getSenderProfile(), ConversationMessageService::SUB_FILTER_TYPE_NONE) === 0) {
$this->conversionEventService->handleConversionGoalReached(
ConversionEventService::CAMPAIGN_ID_NOTIFICATION,
NotificationService::NOTIFICATION_TYPE_UNREAD_CONVERSATION_MESSAGES,
null,
$event->getConversationMessage()->getSenderProfile()->getUser()
);
}
$this->conversionEventService->handleConversionGoalReached(
ConversionEventService::CAMPAIGN_ID_JOBSEEKER_MAILING_150621,
0,
null,
$event->getConversationMessage()->getSenderProfile()->getUser()
);
if ($conversationMessage->getSenderProfile()->getUser()->isJobseeker() && !is_null($conversationMessage->getRelatedRecurrentJob()) && $this->recurrentJobService->recurrentJobBelongsToJobooGmbH($conversationMessage->getRelatedRecurrentJob())) {
$this->conversionEventService->handleConversionGoalReached(
ConversionEventService::CAMPAIGN_ID_RECURRENT_JOBS_BELONGING_TO_JOBOO_GMBH_INFO_MAIL,
0,
null,
$event->getConversationMessage()->getSenderProfile()->getUser()
);
}
$this->conversionEventService->handleConversionGoalReached(
ConversionEventService::CAMPAIGN_ID_WHATSAPP_MESSAGE_ABOUT_UNREAD_ORGANIC_CONVERSATION_MESSAGE,
0,
null,
$event->getConversationMessage()->getSenderProfile()->getUser(),
$event->getConversationMessage()->getRelatedRecurrentJob()
);
$this->conversionEventService->handleConversionGoalReached(
ConversionEventService::CAMPAIGN_ID_WHATSAPP_MESSAGE_ABOUT_UNREAD_INTEGRATED_EXTERNAL_PARTNER_CUSTOMER_PREMIUM_RADAR_MESSAGE,
0,
null,
$event->getConversationMessage()->getSenderProfile()->getUser(),
$event->getConversationMessage()->getRelatedRecurrentJob(),
null,
json_encode(['goalReachedBy' => 'conversationMessageSent'])
);
if ($event->getConversationMessage()->isAutomatedMessage()
&& !is_null(
$event->getConversationMessage()->getAutomatedConversationMessagesMailing()
)
&& $event->getConversationMessage()->getAutomatedConversationMessagesMailing()->getMailingType()
=== AutomatedConversationMessagesMailing::MAILING_TYPE_INTEGRATED_EXTERNAL_PARTNER_CUSTOMER_PREMIUM_RADAR
) {
$this->platformEventService->eventHasOccurred(
PlatformEvent::EVENT_TYPE_INTEGRATED_EXTERNAL_PARTNER_CUSTOMER_PREMIUM_RADAR_WAS_CREATED_FOR_CUSTOMER,
$event->getConversationMessage()->getSenderProfile()->getUser()->getIntegratedExternalPartnerCustomer()->getId()
);
}
foreach ([0, 1, 2, 3] as $subcampaignId) {
$this->conversionEventService->handleConversionGoalReached(
ConversionEventService::CAMPAIGN_ID_INTERNAL_APPLICATION_TRACKING_RECURRENT_JOBS_SEARCH,
$subcampaignId,
null,
$event->getConversationMessage()->getSenderProfile()->getUser(),
$event->getConversationMessage()->getRelatedRecurrentJob()
);
}
foreach ([0, 1, 2, 3] as $subcampaignId) {
$this->conversionEventService->handleConversionGoalReached(
ConversionEventService::CAMPAIGN_ID_INTERNAL_APPLICATION_TRACKING_RECURRENT_JOBS_SEARCH_ALL_JOBS,
$subcampaignId,
null,
$event->getConversationMessage()->getSenderProfile()->getUser(),
$event->getConversationMessage()->getRelatedRecurrentJob()
);
}
foreach ([0, 1, 2, 3] as $subcampaignId) {
$this->conversionEventService->handleConversionGoalReached(
ConversionEventService::CAMPAIGN_ID_INTERNAL_APPLICATION_TRACKING_AUTOMATED_CONVERSATION_MESSAGES_MAILING,
$subcampaignId,
null,
$event->getConversationMessage()->getSenderProfile()->getUser(),
$event->getConversationMessage()->getRelatedRecurrentJob()
);
}
foreach ([0, 1, 2] as $subcampaignId) {
$this->conversionEventService->handleConversionGoalReached(
ConversionEventService::CAMPAIGN_ID_INTERNAL_APPLICATION_TRACKING_INTEGRATED_EXTERNAL_PARTNER_CUSTOMER_PREMIUM_RADAR,
$subcampaignId,
null,
$event->getConversationMessage()->getSenderProfile()->getUser(),
$event->getConversationMessage()->getRelatedRecurrentJob()
);
}
foreach ([0, 1] as $subcampaignId) {
$this->conversionEventService->handleConversionGoalReached(
ConversionEventService::CAMPAIGN_ID_INTERNAL_APPLICATION_TRACKING_INITIAL_JOBOFFERER_CONVERSATION_MESSAGE,
$subcampaignId,
null,
$event->getConversationMessage()->getSenderProfile()->getUser(),
$event->getConversationMessage()->getRelatedRecurrentJob()
);
}
}
/** @throws Exception */
public function onConversationMessageDirectApplied(ConversationMessageDirectAppliedEvent $event)
{
$conversationMessage = $event->getConversationMessage();
$this->conversionEventService->handleConversionGoalReached(
ConversionEventService::CAMPAIGN_ID_NOTIFICATION,
NotificationService::NOTIFICATION_TYPE_UNREAD_JOBRADAR_MATCHES
);
$this->businessEventDomainService->writeNewEvent(
BusinessEvent::EVENT_TYPE_TRIGGERED_DIRECT_APPLICATION_FROM_CONVERSATION_MESSAGE,
$conversationMessage->getReceiverProfile()->getUser(),
$conversationMessage->getRelatedRecurrentJob(),
$conversationMessage->getRelatedWantedJob(),
json_encode(['conversationMessageId' => $conversationMessage->getId(), 'appliedConversationMessageId' => $event->getApplicationConversationMessage()->getId()])
);
$this->directEmailCommunicationService->createOutgoingEmailFromConversationMessage($event->getApplicationConversationMessage());
}
public function onConversationMessageRead(
ConversationMessageReadEvent $event
): void {
$this->messageBus->dispatch(
new UpdateCachedUnreadConversationMessagesCountSymfonyMessage(
$event->getConversationMessage()->getReceiverProfile()->getUser()
)
);
}
public function onConversationMessageDeletedByReceiverEvent(
ConversationMessageDeletedByReceiverEvent $event
): void {
$this->messageBus->dispatch(
new UpdateCachedUnreadConversationMessagesCountSymfonyMessage(
$event->getConversationMessage()->getSenderProfile()->getUser()
)
);
}
public function onConversationMessageRestoredByReceiverEvent(
ConversationMessageRestoredByReceiverEvent $event
): void {
$this->messageBus->dispatch(
new UpdateCachedUnreadConversationMessagesCountSymfonyMessage(
$event->getConversationMessage()->getSenderProfile()->getUser()
)
);
}
}