2024-07-21 16:55:39 +02:00
< ? php
namespace App\MessageHandler ;
2024-08-23 02:35:09 +02:00
use App\Config\Provider\AbstractProvider ;
2024-07-21 16:55:39 +02:00
use App\Config\TriggerAction ;
2024-08-16 23:23:51 +02:00
use App\Config\WebhookScheme ;
2024-07-21 16:55:39 +02:00
use App\Entity\Domain ;
use App\Entity\DomainEvent ;
use App\Entity\WatchList ;
use App\Entity\WatchListTrigger ;
use App\Message\ProcessDomainTrigger ;
2024-08-16 23:23:51 +02:00
use App\Notifier\DomainOrderErrorNotification ;
use App\Notifier\DomainOrderNotification ;
use App\Notifier\DomainUpdateNotification ;
2024-07-21 16:55:39 +02:00
use App\Repository\DomainRepository ;
use App\Repository\WatchListRepository ;
2024-08-25 03:31:09 +02:00
use App\Service\StatService ;
2024-08-22 18:11:07 +02:00
use Psr\Cache\CacheItemPoolInterface ;
2024-08-04 14:45:27 +02:00
use Psr\Log\LoggerInterface ;
2024-07-29 15:28:05 +02:00
use Symfony\Component\HttpKernel\KernelInterface ;
2024-07-21 16:55:39 +02:00
use Symfony\Component\Mailer\Exception\TransportExceptionInterface ;
use Symfony\Component\Mailer\MailerInterface ;
use Symfony\Component\Messenger\Attribute\AsMessageHandler ;
2024-08-16 23:23:51 +02:00
use Symfony\Component\Messenger\Exception\ExceptionInterface ;
2024-08-05 01:30:27 +02:00
use Symfony\Component\Mime\Address ;
2024-08-18 21:49:34 +02:00
use Symfony\Component\Notifier\Notification\ChatNotificationInterface ;
2024-08-16 23:23:51 +02:00
use Symfony\Component\Notifier\Recipient\Recipient ;
use Symfony\Component\Notifier\Transport\AbstractTransportFactory ;
2024-08-17 22:22:18 +02:00
use Symfony\Component\Notifier\Transport\Dsn ;
2024-08-06 03:38:00 +02:00
use Symfony\Contracts\HttpClient\HttpClientInterface ;
2024-07-21 16:55:39 +02:00
#[AsMessageHandler]
final readonly class ProcessDomainTriggerHandler
{
2024-08-16 23:23:51 +02:00
private Address $sender ;
2024-07-21 16:55:39 +02:00
public function __construct (
2024-08-16 23:23:51 +02:00
string $mailerSenderEmail ,
string $mailerSenderName ,
2024-07-21 16:55:39 +02:00
private WatchListRepository $watchListRepository ,
2024-08-02 23:24:52 +02:00
private DomainRepository $domainRepository ,
2024-08-04 14:45:27 +02:00
private KernelInterface $kernel ,
2024-08-06 03:38:00 +02:00
private LoggerInterface $logger ,
2024-08-16 23:23:51 +02:00
private HttpClientInterface $client ,
2024-08-23 21:19:34 +02:00
private MailerInterface $mailer ,
2024-08-25 03:31:09 +02:00
private CacheItemPoolInterface $cacheItemPool ,
private StatService $statService
2024-08-02 23:24:52 +02:00
) {
2024-08-16 23:23:51 +02:00
$this -> sender = new Address ( $mailerSenderEmail , $mailerSenderName );
2024-07-21 16:55:39 +02:00
}
/**
* @ throws TransportExceptionInterface
2024-08-02 23:24:52 +02:00
* @ throws \Exception
2024-08-16 23:23:51 +02:00
* @ throws ExceptionInterface
2024-07-21 16:55:39 +02:00
*/
public function __invoke ( ProcessDomainTrigger $message ) : void
{
/** @var WatchList $watchList */
2024-08-02 23:24:52 +02:00
$watchList = $this -> watchListRepository -> findOneBy ([ 'token' => $message -> watchListToken ]);
2024-07-21 16:55:39 +02:00
/** @var Domain $domain */
2024-08-02 23:24:52 +02:00
$domain = $this -> domainRepository -> findOneBy ([ 'ldhName' => $message -> ldhName ]);
2024-07-21 16:55:39 +02:00
2024-07-30 21:34:48 +02:00
$connector = $watchList -> getConnector ();
if ( null !== $connector && $domain -> getDeleted ()) {
2024-08-04 14:45:27 +02:00
$this -> logger -> notice ( 'Watchlist {watchlist} is linked to connector {connector}. A purchase attempt will be made for domain name {ldhName} with provider {provider}.' , [
'watchlist' => $message -> watchListToken ,
'connector' => $connector -> getId (),
'ldhName' => $message -> ldhName ,
'provider' => $connector -> getProvider () -> value ,
]);
2024-07-30 21:34:48 +02:00
try {
2024-08-07 01:10:56 +02:00
$provider = $connector -> getProvider ();
if ( null === $provider ) {
throw new \Exception ( 'Provider not found' );
2024-08-02 23:24:52 +02:00
}
2024-08-06 03:38:00 +02:00
2024-08-07 01:10:56 +02:00
$connectorProviderClass = $provider -> getConnectorProvider ();
2024-08-23 02:35:09 +02:00
/** @var AbstractProvider $connectorProvider */
$connectorProvider = new $connectorProviderClass ( $connector -> getAuthData (), $this -> client , $this -> cacheItemPool , $this -> kernel );
2024-08-07 01:10:56 +02:00
$connectorProvider -> orderDomain ( $domain , $this -> kernel -> isDebug ());
2024-08-06 11:58:41 +02:00
2024-08-18 21:49:34 +02:00
$notification = ( new DomainOrderNotification ( $this -> sender , $domain , $connector ));
$this -> mailer -> send ( $notification -> asEmailMessage ( new Recipient ( $watchList -> getUser () -> getEmail ())) -> getMessage ());
$this -> sendChatNotification ( $watchList , $notification );
2024-08-22 18:11:07 +02:00
2024-08-25 03:31:09 +02:00
$this -> statService -> incrementStat ( 'stats.domain.purchased' );
2024-08-02 23:24:52 +02:00
} catch ( \Throwable ) {
2024-08-04 14:45:27 +02:00
$this -> logger -> warning ( 'Unable to complete purchase. An error message is sent to user {username}.' , [
'username' => $watchList -> getUser () -> getUserIdentifier (),
]);
2024-08-18 21:49:34 +02:00
$notification = ( new DomainOrderErrorNotification ( $this -> sender , $domain ));
$this -> mailer -> send ( $notification -> asEmailMessage ( new Recipient ( $watchList -> getUser () -> getEmail ())) -> getMessage ());
$this -> sendChatNotification ( $watchList , $notification );
2024-08-22 18:11:07 +02:00
2024-08-25 03:31:09 +02:00
$this -> statService -> incrementStat ( 'stats.domain.purchase.failed' );
2024-07-29 16:10:34 +02:00
}
2024-07-30 21:34:48 +02:00
}
/** @var DomainEvent $event */
2024-08-03 16:14:46 +02:00
foreach ( $domain -> getEvents () -> filter ( fn ( $event ) => $message -> updatedAt < $event -> getDate () && $event -> getDate () < new \DateTime ()) as $event ) {
2024-07-30 21:34:48 +02:00
$watchListTriggers = $watchList -> getWatchListTriggers ()
2024-08-02 23:24:52 +02:00
-> filter ( fn ( $trigger ) => $trigger -> getEvent () === $event -> getAction ());
2024-07-29 16:10:34 +02:00
2024-07-30 21:34:48 +02:00
/** @var WatchListTrigger $watchListTrigger */
foreach ( $watchListTriggers -> getIterator () as $watchListTrigger ) {
2024-08-04 14:45:27 +02:00
$this -> logger -> info ( 'Action {event} has been detected on the domain name {ldhName}. A notification is sent to user {username}.' , [
'event' => $event -> getAction (),
'ldhName' => $message -> ldhName ,
'username' => $watchList -> getUser () -> getUserIdentifier (),
]);
2024-08-16 23:23:51 +02:00
$recipient = new Recipient ( $watchList -> getUser () -> getEmail ());
$notification = new DomainUpdateNotification ( $this -> sender , $event );
2024-08-02 23:24:52 +02:00
if ( TriggerAction :: SendEmail == $watchListTrigger -> getAction ()) {
2024-08-16 23:23:51 +02:00
$this -> mailer -> send ( $notification -> asEmailMessage ( $recipient ) -> getMessage ());
} elseif ( TriggerAction :: SendChat == $watchListTrigger -> getAction ()) {
2024-08-18 21:49:34 +02:00
$this -> sendChatNotification ( $watchList , $notification );
}
2024-08-22 18:11:07 +02:00
2024-08-25 03:31:09 +02:00
$this -> statService -> incrementStat ( 'stats.alert.sent' );
2024-08-18 21:49:34 +02:00
}
}
}
/**
* @ throws \Symfony\Component\Notifier\Exception\TransportExceptionInterface
*/
private function sendChatNotification ( WatchList $watchList , ChatNotificationInterface $notification ) : void
{
2024-08-25 03:55:20 +02:00
$webhookDsn = $watchList -> getWebhookDsn ();
if ( null !== $webhookDsn && 0 !== count ( $webhookDsn )) {
foreach ( $webhookDsn as $dsnString ) {
2024-08-18 21:49:34 +02:00
$dsn = new Dsn ( $dsnString );
$scheme = $dsn -> getScheme ();
$webhookScheme = WebhookScheme :: tryFrom ( $scheme );
if ( null !== $webhookScheme ) {
$transportFactoryClass = $webhookScheme -> getChatTransportFactory ();
/** @var AbstractTransportFactory $transportFactory */
$transportFactory = new $transportFactoryClass ();
try {
$transportFactory -> create ( $dsn ) -> send ( $notification -> asChatMessage ( new Recipient ()));
$this -> logger -> info ( 'Chat message sent with {schema} for Watchlist {token}' ,
[
'scheme' => $webhookScheme -> name ,
'token' => $watchList -> getToken (),
]);
} catch ( \Throwable ) {
$this -> logger -> error ( 'Unable to send a chat message to {scheme} for Watchlist {token}' ,
[
'scheme' => $webhookScheme -> name ,
'token' => $watchList -> getToken (),
]);
2024-08-16 23:23:51 +02:00
}
2024-07-21 16:55:39 +02:00
}
}
}
}
}