Initial Commit
This commit is contained in:
100
app/Services/Channels/DiscordChannel.php
Normal file
100
app/Services/Channels/DiscordChannel.php
Normal file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Channels;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
class DiscordChannel implements NotificationChannelInterface
|
||||
{
|
||||
private Client $client;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->client = new Client(['timeout' => 10]);
|
||||
}
|
||||
|
||||
public function send(array $config, string $message, array $data = []): bool
|
||||
{
|
||||
if (!isset($config['webhook_url'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$embed = $this->createEmbed($message, $data);
|
||||
|
||||
$response = $this->client->post($config['webhook_url'], [
|
||||
'json' => [
|
||||
'embeds' => [$embed]
|
||||
]
|
||||
]);
|
||||
|
||||
return $response->getStatusCode() === 204;
|
||||
} catch (\Exception $e) {
|
||||
error_log("Discord send failed: " . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private function createEmbed(string $message, array $data): array
|
||||
{
|
||||
$color = $this->getColorByDaysLeft($data['days_left'] ?? null);
|
||||
|
||||
$embed = [
|
||||
'title' => '🔔 Domain Expiration Alert',
|
||||
'description' => $message,
|
||||
'color' => $color,
|
||||
'timestamp' => date('c'),
|
||||
'footer' => [
|
||||
'text' => 'Domain Monitor'
|
||||
]
|
||||
];
|
||||
|
||||
if (isset($data['domain'])) {
|
||||
$embed['fields'] = [
|
||||
[
|
||||
'name' => 'Domain',
|
||||
'value' => $data['domain'],
|
||||
'inline' => true
|
||||
],
|
||||
[
|
||||
'name' => 'Days Left',
|
||||
'value' => $data['days_left'],
|
||||
'inline' => true
|
||||
],
|
||||
[
|
||||
'name' => 'Expiration Date',
|
||||
'value' => $data['expiration_date'],
|
||||
'inline' => true
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
return $embed;
|
||||
}
|
||||
|
||||
private function getColorByDaysLeft(?int $daysLeft): int
|
||||
{
|
||||
if ($daysLeft === null) {
|
||||
return 0x808080; // Gray
|
||||
}
|
||||
|
||||
if ($daysLeft <= 0) {
|
||||
return 0xFF0000; // Red
|
||||
}
|
||||
|
||||
if ($daysLeft <= 3) {
|
||||
return 0xFF4500; // Orange Red
|
||||
}
|
||||
|
||||
if ($daysLeft <= 7) {
|
||||
return 0xFFA500; // Orange
|
||||
}
|
||||
|
||||
if ($daysLeft <= 30) {
|
||||
return 0xFFFF00; // Yellow
|
||||
}
|
||||
|
||||
return 0x00FF00; // Green
|
||||
}
|
||||
}
|
||||
|
||||
91
app/Services/Channels/EmailChannel.php
Normal file
91
app/Services/Channels/EmailChannel.php
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Channels;
|
||||
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
|
||||
class EmailChannel implements NotificationChannelInterface
|
||||
{
|
||||
public function send(array $config, string $message, array $data = []): bool
|
||||
{
|
||||
$mail = new PHPMailer(true);
|
||||
|
||||
try {
|
||||
// Server settings
|
||||
$mail->isSMTP();
|
||||
$mail->Host = $_ENV['MAIL_HOST'];
|
||||
$mail->SMTPAuth = true;
|
||||
$mail->Username = $_ENV['MAIL_USERNAME'];
|
||||
$mail->Password = $_ENV['MAIL_PASSWORD'];
|
||||
$mail->SMTPSecure = $_ENV['MAIL_ENCRYPTION'];
|
||||
$mail->Port = $_ENV['MAIL_PORT'];
|
||||
|
||||
// Recipients
|
||||
$mail->setFrom($_ENV['MAIL_FROM_ADDRESS'], $_ENV['MAIL_FROM_NAME']);
|
||||
$mail->addAddress($config['email']);
|
||||
|
||||
// Content
|
||||
$mail->isHTML(true);
|
||||
$mail->Subject = $this->getSubject($data);
|
||||
$mail->Body = $this->formatHtmlBody($message, $data);
|
||||
$mail->AltBody = strip_tags($message);
|
||||
|
||||
$mail->send();
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
error_log("Email send failed: {$mail->ErrorInfo}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private function getSubject(array $data): string
|
||||
{
|
||||
if (isset($data['domain'])) {
|
||||
$daysLeft = $data['days_left'];
|
||||
if ($daysLeft <= 0) {
|
||||
return "🚨 URGENT: Domain {$data['domain']} has EXPIRED";
|
||||
}
|
||||
if ($daysLeft == 1) {
|
||||
return "⚠️ CRITICAL: Domain {$data['domain']} expires TOMORROW";
|
||||
}
|
||||
return "⚠️ Domain Expiration Alert: {$data['domain']} ({$daysLeft} days)";
|
||||
}
|
||||
|
||||
return "Domain Monitor Alert";
|
||||
}
|
||||
|
||||
private function formatHtmlBody(string $message, array $data): string
|
||||
{
|
||||
$messageHtml = nl2br(htmlspecialchars($message));
|
||||
|
||||
return "
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
|
||||
.container { max-width: 600px; margin: 0 auto; padding: 20px; }
|
||||
.header { background: #4A90E2; color: white; padding: 20px; border-radius: 5px 5px 0 0; }
|
||||
.content { background: #f9f9f9; padding: 20px; border: 1px solid #ddd; }
|
||||
.footer { background: #333; color: white; padding: 10px; text-align: center; font-size: 12px; border-radius: 0 0 5px 5px; }
|
||||
.button { display: inline-block; padding: 10px 20px; background: #4A90E2; color: white; text-decoration: none; border-radius: 5px; margin-top: 10px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class='container'>
|
||||
<div class='header'>
|
||||
<h2>🔔 Domain Monitor Alert</h2>
|
||||
</div>
|
||||
<div class='content'>
|
||||
<p>$messageHtml</p>
|
||||
</div>
|
||||
<div class='footer'>
|
||||
<p>This is an automated message from Domain Monitor</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
";
|
||||
}
|
||||
}
|
||||
|
||||
17
app/Services/Channels/NotificationChannelInterface.php
Normal file
17
app/Services/Channels/NotificationChannelInterface.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Channels;
|
||||
|
||||
interface NotificationChannelInterface
|
||||
{
|
||||
/**
|
||||
* Send notification through the channel
|
||||
*
|
||||
* @param array $config Channel-specific configuration
|
||||
* @param string $message Message to send
|
||||
* @param array $data Additional data for formatting
|
||||
* @return bool Success status
|
||||
*/
|
||||
public function send(array $config, string $message, array $data = []): bool;
|
||||
}
|
||||
|
||||
85
app/Services/Channels/SlackChannel.php
Normal file
85
app/Services/Channels/SlackChannel.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Channels;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
class SlackChannel implements NotificationChannelInterface
|
||||
{
|
||||
private Client $client;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->client = new Client(['timeout' => 10]);
|
||||
}
|
||||
|
||||
public function send(array $config, string $message, array $data = []): bool
|
||||
{
|
||||
if (!isset($config['webhook_url'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$payload = [
|
||||
'text' => $message,
|
||||
'blocks' => $this->createBlocks($message, $data)
|
||||
];
|
||||
|
||||
$response = $this->client->post($config['webhook_url'], [
|
||||
'json' => $payload
|
||||
]);
|
||||
|
||||
return $response->getStatusCode() === 200;
|
||||
} catch (\Exception $e) {
|
||||
error_log("Slack send failed: " . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private function createBlocks(string $message, array $data): array
|
||||
{
|
||||
$blocks = [
|
||||
[
|
||||
'type' => 'header',
|
||||
'text' => [
|
||||
'type' => 'plain_text',
|
||||
'text' => '🔔 Domain Expiration Alert'
|
||||
]
|
||||
],
|
||||
[
|
||||
'type' => 'section',
|
||||
'text' => [
|
||||
'type' => 'mrkdwn',
|
||||
'text' => $message
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
if (isset($data['domain'])) {
|
||||
$blocks[] = [
|
||||
'type' => 'section',
|
||||
'fields' => [
|
||||
[
|
||||
'type' => 'mrkdwn',
|
||||
'text' => "*Domain:*\n{$data['domain']}"
|
||||
],
|
||||
[
|
||||
'type' => 'mrkdwn',
|
||||
'text' => "*Days Left:*\n{$data['days_left']}"
|
||||
],
|
||||
[
|
||||
'type' => 'mrkdwn',
|
||||
'text' => "*Expiration:*\n{$data['expiration_date']}"
|
||||
],
|
||||
[
|
||||
'type' => 'mrkdwn',
|
||||
'text' => "*Registrar:*\n{$data['registrar']}"
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
return $blocks;
|
||||
}
|
||||
}
|
||||
|
||||
42
app/Services/Channels/TelegramChannel.php
Normal file
42
app/Services/Channels/TelegramChannel.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Channels;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
class TelegramChannel implements NotificationChannelInterface
|
||||
{
|
||||
private Client $client;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->client = new Client([
|
||||
'base_uri' => 'https://api.telegram.org',
|
||||
'timeout' => 10,
|
||||
]);
|
||||
}
|
||||
|
||||
public function send(array $config, string $message, array $data = []): bool
|
||||
{
|
||||
if (!isset($config['bot_token']) || !isset($config['chat_id'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$response = $this->client->post("/bot{$config['bot_token']}/sendMessage", [
|
||||
'json' => [
|
||||
'chat_id' => $config['chat_id'],
|
||||
'text' => $message,
|
||||
'parse_mode' => 'HTML',
|
||||
'disable_web_page_preview' => true,
|
||||
]
|
||||
]);
|
||||
|
||||
return $response->getStatusCode() === 200;
|
||||
} catch (\Exception $e) {
|
||||
error_log("Telegram send failed: " . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user