Files
2025-07-24 16:18:27 +07:00

513 lines
16 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace App\Http\Services;
use App\Models\Setting;
use Carbon\Carbon;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
class Discord
{
protected ?string $token;
protected ?string $group;
// Discord embed colors
const COLOR_SUCCESS = 3066993; // Green
const COLOR_ERROR = 15158332; // Red
const COLOR_INFO = 3447003; // Blue
const COLOR_WARNING = 16776960; // Yellow
const COLOR_VIP = 16711935; // Purple
public function __construct()
{
$record = Setting::where('key', 'setting')->first();
if ($record) {
$setting = json_decode($record->value);
$this->token = $setting->discord_webhook_id ?? null;
$this->group = $setting->discord_webhook_token ?? null;
} else {
$this->token = null;
$this->group = null;
}
}
protected function sendDiscordMessage(array $payload)
{
if (!$this->token || !$this->group) {
Log::channel('Custom')->warning('Discord notification not sent: Missing webhook ID or token');
return null;
}
$webhookUrl = "https://discord.com/api/webhooks/{$this->token}/{$this->group}";
try {
return Http::post($webhookUrl, $payload);
} catch (\Exception $exception) {
Log::channel('Custom')->error('Failed to send Discord notification: ' . $exception->getMessage());
return null;
}
}
/**
* Send simple message with embed
*/
public function SendMessage($message = '', $color = self::COLOR_INFO, $title = null)
{
$embed = [
'description' => $message,
'color' => $color,
'timestamp' => now()->toIso8601String(),
];
if ($title) {
$embed['title'] = $title;
}
$payload = [
'embeds' => [$embed]
];
return $this->sendDiscordMessage($payload);
}
/**
* Send error message with embed
*/
public function NotifyDiscordFailure($reason, $data = null)
{
$fields = [
[
'name' => '🚫 Lý do lỗi',
'value' => $reason,
'inline' => false,
],
];
if ($data) {
$fields[] = [
'name' => '📄 Dữ liệu liên quan',
'value' => "```json\n" . substr(json_encode($data, JSON_PRETTY_PRINT), 0, 1000) . "\n```",
'inline' => false,
];
}
$embed = [
'title' => '🔴 Gửi Discord thất bại',
'color' => self::COLOR_ERROR,
'fields' => $fields,
'timestamp' => now()->toIso8601String(),
];
Log::channel('Custom')->error('NotifyDiscordFailure: ' . $reason, ['data' => $data]);
return null;
}
/**
* Send VPS information with enhanced embed
*/
public function SendInformation($product = [], $user = '', $password = '', $port = 22)
{
$fields = [
[
'name' => '🌐 Địa chỉ IP',
'value' => isset($product->IpAddress->ip) ? $product->IpAddress->ip : 'N/A',
'inline' => true,
],
[
'name' => '👤 Tài khoản',
'value' => $user ?: 'root',
'inline' => true,
],
[
'name' => '🔌 Cổng SSH',
'value' => (string) $port,
'inline' => true,
],
[
'name' => '🔐 Mật khẩu',
'value' => "||{$password}||", // Spoiler text
'inline' => true,
],
[
'name' => '⏰ Hết hạn',
'value' => isset($product->next_due_date) ?
Carbon::parse($product->next_due_date)->format('d/m/Y H:i') : 'Không giới hạn',
'inline' => true,
],
[
'name' => '💻 Hệ điều hành',
'value' => (isset($product->Os->OsGroup->name) ? $product->Os->OsGroup->name : '') . ' ' . (isset($product->Os->version) ? $product->Os->version : ''),
'inline' => true,
],
];
// Add SSH command
$ipAddress = isset($product->IpAddress->ip) ? $product->IpAddress->ip : 'IP_ADDRESS';
$sshCommand = "ssh {$user}@{$ipAddress}";
if ($port != 22) {
$sshCommand .= " -p {$port}";
}
$embed = [
'title' => '🎉 VPS đã được khởi tạo thành công!',
'description' => "**Đơn hàng:** #" . (isset($product->order_id) ? $product->order_id : '') . "\n**SSH Command:**\n```bash\n{$sshCommand}\n```",
'color' => self::COLOR_SUCCESS,
'fields' => $fields,
'footer' => [
'text' => 'VPS Management System',
'icon_url' => 'https://cdn-icons-png.flaticon.com/512/868/868681.png'
],
'timestamp' => now()->toIso8601String(),
];
return $this->sendDiscordMessage(['embeds' => [$embed]]);
}
/**
* Send error message with enhanced formatting
*/
public function SendErrorMessage($data, $context = null)
{
$content = is_string($data) ? $data : json_encode($data, JSON_PRETTY_PRINT);
$fields = [];
if ($context) {
$fields[] = [
'name' => '📍 Ngữ cảnh',
'value' => $context,
'inline' => false,
];
}
$fields[] = [
'name' => '⚠️ Chi tiết lỗi',
'value' => "```json\n" . substr($content, 0, 1000) . "\n```",
'inline' => false,
];
$embed = [
'title' => '🚨 Lỗi hệ thống',
'description' => '**Admin:** Đã xảy ra lỗi trong quá trình xử lý dịch vụ',
'color' => self::COLOR_ERROR,
'fields' => $fields,
'footer' => [
'text' => 'Error Notification System'
],
'timestamp' => now()->toIso8601String(),
];
return $this->sendDiscordMessage(['embeds' => [$embed]]);
}
/**
* Send new user registration notification
*/
public function SendNewUserRegistration($email, $code, $verificationLink)
{
$fields = [
[
'name' => '📧 Email đăng ký',
'value' => $email,
'inline' => true,
],
[
'name' => '🔢 Mã xác thực',
'value' => "`{$code}`",
'inline' => true,
],
[
'name' => '🔗 Link xác thực',
'value' => "[Nhấn để xác thực]({$verificationLink})",
'inline' => false,
],
];
$embed = [
'title' => '🎉 Thành viên mới đăng ký!',
'description' => '**Có người dùng mới vừa tạo tài khoản**',
'color' => self::COLOR_SUCCESS,
'fields' => $fields,
'thumbnail' => [
'url' => 'https://cdn-icons-png.flaticon.com/512/1077/1077114.png'
],
'timestamp' => now()->toIso8601String(),
];
return $this->sendDiscordMessage(['embeds' => [$embed]]);
}
/**
* Send customer recharge notification
*/
public function SendCustomerRecharge($customer, $amount, $method = null)
{
$customerName = trim("{$customer->firstname} {$customer->lastname}");
$fields = [
[
'name' => '👤 Khách hàng',
'value' => $customerName ?: 'N/A',
'inline' => true,
],
[
'name' => '📧 Email',
'value' => isset($customer->email) ? $customer->email : 'N/A',
'inline' => true,
],
[
'name' => '💰 Số tiền nạp',
'value' => '**' . number_format($amount, 0, ',', '.') . ' VNĐ**',
'inline' => true,
],
];
if ($method) {
$fields[] = [
'name' => '💳 Phương thức',
'value' => $method,
'inline' => true,
];
}
$fields[] = [
'name' => '🕒 Thời gian',
'value' => Carbon::now()->format('d/m/Y H:i:s'),
'inline' => true,
];
$embed = [
'title' => '💎 Khách hàng nạp tiền thành công',
'description' => "**{$customerName}** vừa nạp tiền vào tài khoản",
'color' => self::COLOR_VIP,
'fields' => $fields,
'thumbnail' => [
'url' => 'https://cdn-icons-png.flaticon.com/512/3135/3135715.png'
],
'timestamp' => now()->toIso8601String(),
];
return $this->sendDiscordMessage(['embeds' => [$embed]]);
}
/**
* Send job execution notification
*/
public function SendJobRunInfo($jobName, $status, $additionalInfo = null, $duration = null)
{
$statusEmoji = match (strtolower($status)) {
'success', 'completed' => '✅',
'failed', 'error' => '❌',
'running', 'processing' => '⏳',
'warning' => '⚠️',
default => '📊'
};
$color = match (strtolower($status)) {
'success', 'completed' => self::COLOR_SUCCESS,
'failed', 'error' => self::COLOR_ERROR,
'warning' => self::COLOR_WARNING,
default => self::COLOR_INFO
};
$fields = [
[
'name' => '⏱️ Thời gian chạy',
'value' => Carbon::now()->format('d/m/Y H:i:s'),
'inline' => true,
],
[
'name' => '📊 Trạng thái',
'value' => "{$statusEmoji} {$status}",
'inline' => true,
],
];
if ($duration) {
$fields[] = [
'name' => '⏲️ Thời gian thực thi',
'value' => $duration,
'inline' => true,
];
}
if ($additionalInfo) {
$info = is_string($additionalInfo) ? $additionalInfo : json_encode($additionalInfo, JSON_PRETTY_PRINT);
$fields[] = [
'name' => '📋 Thông tin chi tiết',
'value' => "```\n" . substr($info, 0, 1000) . "\n```",
'inline' => false,
];
}
$embed = [
'title' => "⚙️ Job Execution: {$jobName}",
'color' => $color,
'fields' => $fields,
'timestamp' => now()->toIso8601String(),
];
return $this->sendDiscordMessage(['embeds' => [$embed]]);
}
/**
* Send order paid notification with enhanced formatting
*/
public function SendOrderPaidNotification($invoice)
{
$invoiceItem = $invoice->invoiceItem()->with([
'vps',
'hosting',
'os.osGroup',
'addons.addonItems'
])->first();
if (!$invoiceItem) {
return $this->SendErrorMessage('Không tìm thấy invoice item từ invoice ID: ' . $invoice->id, 'Order Paid Process');
}
$product = $invoiceItem->product;
$os = $invoiceItem->os;
$osGroup = isset($os->osGroup) ? $os->osGroup : null;
$addons = $invoiceItem->addons;
$customer = $invoice->customer;
$fields = [
[
'name' => '🧾 Mã đơn hàng',
'value' => "**#{$invoice->order_num}**",
'inline' => true,
],
[
'name' => '📦 Sản phẩm',
'value' => "#" . (isset($product->id) ? $product->id : '') . " - " . (isset($product->name) ? $product->name : ''),
'inline' => true,
],
[
'name' => '💰 Tổng thanh toán',
'value' => '**' . number_format($invoice->total, 0, ',', '.') . ' VNĐ**',
'inline' => true,
],
[
'name' => '👤 Khách hàng',
'value' => trim((isset($customer->firstname) ? $customer->firstname : '') . ' ' . (isset($customer->lastname) ? $customer->lastname : '')),
'inline' => true,
],
[
'name' => '📧 Email',
'value' => isset($customer->email) ? $customer->email : 'N/A',
'inline' => true,
],
[
'name' => '🕒 Thời gian thanh toán',
'value' => Carbon::parse($invoice->date_paid)->format('d/m/Y H:i:s'),
'inline' => true,
],
];
if ($osGroup || $os) {
$fields[] = [
'name' => '🖥️ Hệ điều hành',
'value' => (isset($osGroup->name) ? $osGroup->name : '') . ' ' . (isset($os->version) ? $os->version : ''),
'inline' => true,
];
}
// Add addons if exist
if ($addons && $addons->count()) {
$addonsText = "";
foreach ($addons as $addon) {
$addonsText .= "• {$addon->addonItems->name} (x{$addon->qty}) - " . number_format($addon->price, 0, ',', '.') . " VNĐ\n";
}
$fields[] = [
'name' => '➕ Dịch vụ bổ sung',
'value' => $addonsText,
'inline' => false,
];
}
$embed = [
'title' => '💵 Đơn hàng được thanh toán thành công!',
'description' => "**Khách hàng:** " . (isset($customer->firstname) ? $customer->firstname : '') . " " . (isset($customer->lastname) ? $customer->lastname : '') . "\n**Đơn hàng:** #{$invoice->order_num}",
'color' => self::COLOR_SUCCESS,
'fields' => $fields,
'thumbnail' => [
'url' => 'https://cdn-icons-png.flaticon.com/512/3135/3135673.png'
],
'footer' => [
'text' => 'Order Management System'
],
'timestamp' => now()->toIso8601String(),
];
return $this->sendDiscordMessage(['embeds' => [$embed]]);
}
/**
* Send service renewal notification
*/
public function SendServiceRenewal($service, $period)
{
$fields = [
[
'name' => '🏷️ Dịch vụ',
'value' => isset($service->name) ? $service->name : 'N/A',
'inline' => true,
],
[
'name' => '📅 Gia hạn thêm',
'value' => $period,
'inline' => true,
],
[
'name' => '📅 Ngày hết hạn mới',
'value' => Carbon::parse($service->next_due_date)->format('d/m/Y'),
'inline' => true,
],
];
$embed = [
'title' => '🔄 Dịch vụ được gia hạn',
'color' => self::COLOR_INFO,
'fields' => $fields,
'timestamp' => now()->toIso8601String(),
];
return $this->sendDiscordMessage(['embeds' => [$embed]]);
}
/**
* Send system maintenance notification
*/
public function SendMaintenanceNotification($title, $description, $startTime = null, $endTime = null)
{
$fields = [];
if ($startTime) {
$fields[] = [
'name' => '🕐 Bắt đầu',
'value' => Carbon::parse($startTime)->format('d/m/Y H:i:s'),
'inline' => true,
];
}
if ($endTime) {
$fields[] = [
'name' => '🕑 Kết thúc dự kiến',
'value' => Carbon::parse($endTime)->format('d/m/Y H:i:s'),
'inline' => true,
];
}
$embed = [
'title' => "🔧 {$title}",
'description' => $description,
'color' => self::COLOR_WARNING,
'fields' => $fields,
'timestamp' => now()->toIso8601String(),
];
return $this->sendDiscordMessage(['embeds' => [$embed]]);
}
}