feat: add discord and pushover as notification agents (#300)
fix: most error messages of the notifications endpoints would not reach the frontend
This commit is contained in:
parent
4199d4c3e7
commit
899482982e
@ -2,4 +2,5 @@
|
||||
|
||||
#Webroot path
|
||||
$webPath = "/var/www/html/";
|
||||
|
||||
?>
|
||||
@ -11,6 +11,8 @@
|
||||
$gotifyNotificationsEnabled = false;
|
||||
$telegramNotificationsEnabled = false;
|
||||
$webhookNotificationsEnabled = false;
|
||||
$pushoverNotificationsEnabled = false;
|
||||
$discordNotificationsEnabled = false;
|
||||
|
||||
// Get notification settings (how many days before the subscription ends should the notification be sent)
|
||||
$query = "SELECT days FROM notification_settings";
|
||||
@ -35,6 +37,17 @@
|
||||
$email['fromEmail'] = $row["from_email"] ? $row["from_email"] : "wallos@wallosapp.com";
|
||||
}
|
||||
|
||||
// Check if Discord notifications are enabled and get the settings
|
||||
$query = "SELECT * FROM discord_notifications";
|
||||
$result = $db->query($query);
|
||||
|
||||
if ($row = $result->fetchArray(SQLITE3_ASSOC)) {
|
||||
$discordNotificationsEnabled = $row['enabled'];
|
||||
$discord['webhook_url'] = $row["webhook_url"];
|
||||
$discord['bot_username'] = $row["bot_username"];
|
||||
$discord['bot_avatar_url'] = $row["bot_avatar_url"];
|
||||
}
|
||||
|
||||
// Check if Gotify notifications are enabled and get the settings
|
||||
$query = "SELECT * FROM gotify_notifications";
|
||||
$result = $db->query($query);
|
||||
@ -55,6 +68,16 @@
|
||||
$telegram['chatId'] = $row["chat_id"];
|
||||
}
|
||||
|
||||
// Check if Pushover notifications are enabled and get the settings
|
||||
$query = "SELECT * FROM pushover_notifications";
|
||||
$result = $db->query($query);
|
||||
|
||||
if ($row = $result->fetchArray(SQLITE3_ASSOC)) {
|
||||
$pushoverNotificationsEnabled = $row['enabled'];
|
||||
$pushover['user_key'] = $row["user_key"];
|
||||
$pushover['token'] = $row["token"];
|
||||
}
|
||||
|
||||
// Check if Webhook notifications are enabled and get the settings
|
||||
$query = "SELECT * FROM webhook_notifications";
|
||||
$result = $db->query($query);
|
||||
@ -71,7 +94,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
$notificationsEnabled = $emailNotificationsEnabled || $gotifyNotificationsEnabled || $telegramNotificationsEnabled || $webhookNotificationsEnabled;
|
||||
$notificationsEnabled = $emailNotificationsEnabled || $gotifyNotificationsEnabled || $telegramNotificationsEnabled || $webhookNotificationsEnabled || $pushoverNotificationsEnabled || $discordNotificationsEnabled;
|
||||
|
||||
// If no notifications are enabled, no need to run
|
||||
if (!$notificationsEnabled) {
|
||||
@ -181,6 +204,68 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Discord notifications if enabled
|
||||
if ($discordNotificationsEnabled) {
|
||||
foreach ($notify as $userId => $perUser) {
|
||||
// Get name of user from household table
|
||||
$stmt = $db->prepare('SELECT * FROM household WHERE id = :userId');
|
||||
$stmt->bindValue(':userId', $userId, SQLITE3_INTEGER);
|
||||
$result = $stmt->execute();
|
||||
$user = $result->fetchArray(SQLITE3_ASSOC);
|
||||
|
||||
$title = translate('wallos_notification', $i18n);
|
||||
|
||||
$dayText = $days == 1 ? "tomorrow" : "in " . $days . " days";
|
||||
if ($user['name']) {
|
||||
$message = $user['name'] . ", the following subscriptions are up for renewal " . $dayText . ":\n";
|
||||
} else {
|
||||
$message = "The following subscriptions are up for renewal " . $dayText . ":\n";
|
||||
}
|
||||
|
||||
foreach ($perUser as $subscription) {
|
||||
$message .= $subscription['name'] . " for " . $subscription['price'] . "\n";
|
||||
}
|
||||
|
||||
$postfields = [
|
||||
'content' => $message,
|
||||
'embeds' => [
|
||||
[
|
||||
'title' => $title,
|
||||
'description' => $message,
|
||||
'color' => hexdec("FF0000")
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
if (!empty($discord['bot_username'])) {
|
||||
$postfields['username'] = $discord['bot_username'];
|
||||
}
|
||||
|
||||
if (!empty($discord['bot_avatar_url'])) {
|
||||
$postfields['avatar_url'] = $discord['bot_avatar_url'];
|
||||
}
|
||||
|
||||
$ch = curl_init();
|
||||
|
||||
curl_setopt($ch, CURLOPT_URL, $discord['webhook_url']);
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($postfields));
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
'Content-Type: application/json'
|
||||
]);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
if ($result === false) {
|
||||
echo "Error sending notifications: " . curl_error($ch);
|
||||
} else {
|
||||
echo "Discord Notifications sent<br />";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Gotify notifications if enabled
|
||||
if ($gotifyNotificationsEnabled) {
|
||||
foreach ($notify as $userId => $perUser) {
|
||||
@ -271,6 +356,48 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Pushover notifications if enabled
|
||||
if ($pushoverNotificationsEnabled) {
|
||||
foreach ($notify as $userId => $perUser) {
|
||||
// Get name of user from household table
|
||||
$stmt = $db->prepare('SELECT * FROM household WHERE id = :userId');
|
||||
$stmt->bindValue(':userId', $userId, SQLITE3_INTEGER);
|
||||
$result = $stmt->execute();
|
||||
$user = $result->fetchArray(SQLITE3_ASSOC);
|
||||
|
||||
$dayText = $days == 1 ? "tomorrow" : "in " . $days . " days";
|
||||
if ($user['name']) {
|
||||
$message = $user['name'] . ", the following subscriptions are up for renewal " . $dayText . ":\n";
|
||||
} else {
|
||||
$message = "The following subscriptions are up for renewal " . $dayText . ":\n";
|
||||
}
|
||||
|
||||
foreach ($perUser as $subscription) {
|
||||
$message .= $subscription['name'] . " for " . $subscription['price'] . "\n";
|
||||
}
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, "https://api.pushover.net/1/messages.json");
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
|
||||
'token' => $pushover['token'],
|
||||
'user' => $pushover['user_key'],
|
||||
'message' => $message,
|
||||
]));
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
$result = curl_exec($ch);
|
||||
|
||||
curl_close($ch);
|
||||
|
||||
if ($result === false) {
|
||||
echo "Error sending notifications: " . curl_error($ch);
|
||||
} else {
|
||||
echo "Pushover Notifications sent<br />";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Webhook notifications if enabled
|
||||
if ($webhookNotificationsEnabled) {
|
||||
// Get webhook payload and turn it into a json object
|
||||
|
||||
72
endpoints/notifications/savediscordnotifications.php
Normal file
72
endpoints/notifications/savediscordnotifications.php
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
require_once '../../includes/connect_endpoint.php';
|
||||
session_start();
|
||||
|
||||
if (!isset($_SESSION['loggedin']) || $_SESSION['loggedin'] !== true) {
|
||||
die(json_encode([
|
||||
"success" => false,
|
||||
"message" => translate('session_expired', $i18n)
|
||||
]));
|
||||
}
|
||||
|
||||
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
$postData = file_get_contents("php://input");
|
||||
$data = json_decode($postData, true);
|
||||
|
||||
if (
|
||||
!isset($data["url"]) || $data["url"] == ""
|
||||
) {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"message" => translate('fill_mandatory_fields', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
} else {
|
||||
$enabled = $data["enabled"];
|
||||
$webhook_url = $data["url"];
|
||||
$bot_username = $data["bot_username"];
|
||||
$bot_avatar_url = $data["bot_avatar"];
|
||||
|
||||
$query = "SELECT COUNT(*) FROM discord_notifications";
|
||||
$result = $db->querySingle($query);
|
||||
|
||||
if ($result === false) {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"message" => translate('error_saving_notifications', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
} else {
|
||||
if ($result == 0) {
|
||||
$query = "INSERT INTO discord_notifications (enabled, webhook_url, bot_username, bot_avatar_url)
|
||||
VALUES (:enabled, :webhook_url, :bot_username, :bot_avatar_url)";
|
||||
} else {
|
||||
$query = "UPDATE pushover_notifications
|
||||
SET enabled = :enabled, webhook_url = :webhook_url, bot_username = :bot_username, bot_avatar_url = :bot_avatar_url";
|
||||
}
|
||||
|
||||
$stmt = $db->prepare($query);
|
||||
$stmt->bindValue(':enabled', $enabled, SQLITE3_INTEGER);
|
||||
$stmt->bindValue(':webhook_url', $webhook_url, SQLITE3_TEXT);
|
||||
$stmt->bindValue(':bot_username', $bot_username, SQLITE3_TEXT);
|
||||
$stmt->bindValue(':bot_avatar_url', $bot_avatar_url, SQLITE3_TEXT);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
$response = [
|
||||
"success" => true,
|
||||
"message" => translate('notifications_settings_saved', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
} else {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"message" => translate('error_saving_notifications', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@ -21,7 +21,7 @@
|
||||
) {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"errorMessage" => translate('fill_mandatory_fields', $i18n)
|
||||
"message" => translate('fill_mandatory_fields', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
} else {
|
||||
@ -42,7 +42,7 @@
|
||||
if ($result === false) {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"errorMessage" => translate('error_saving_notifications', $i18n)
|
||||
"message" => translate('error_saving_notifications', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
} else {
|
||||
@ -73,7 +73,7 @@
|
||||
} else {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"errorMessage" => translate('error_saving_notifications', $i18n)
|
||||
"message" => translate('error_saving_notifications', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
) {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"errorMessage" => translate('fill_mandatory_fields', $i18n)
|
||||
"message" => translate('fill_mandatory_fields', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
} else {
|
||||
@ -33,7 +33,7 @@
|
||||
if ($result === false) {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"errorMessage" => translate('error_saving_notifications', $i18n)
|
||||
"message" => translate('error_saving_notifications', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
} else {
|
||||
@ -59,7 +59,7 @@
|
||||
} else {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"errorMessage" => translate('error_saving_notifications', $i18n)
|
||||
"message" => translate('error_saving_notifications', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
if (!isset($data["days"]) || $data['days'] == "") {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"errorMessage" => translate('fill_mandatory_fields', $i18n)
|
||||
"message" => translate('fill_mandatory_fields', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
} else {
|
||||
@ -28,7 +28,7 @@
|
||||
if ($result === false) {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"errorMessage" => translate('error_saving_notifications', $i18n)
|
||||
"message" => translate('error_saving_notifications', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
} else {
|
||||
@ -51,7 +51,7 @@
|
||||
} else {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"errorMessage" => translate('error_saving_notifications', $i18n)
|
||||
"message" => translate('error_saving_notifications', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
}
|
||||
@ -60,7 +60,7 @@
|
||||
} else {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"errorMessage" => "Invalid request method"
|
||||
"message" => "Invalid request method"
|
||||
];
|
||||
echo json_encode($response);
|
||||
exit();
|
||||
|
||||
71
endpoints/notifications/savepushovernotifications.php
Normal file
71
endpoints/notifications/savepushovernotifications.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
require_once '../../includes/connect_endpoint.php';
|
||||
session_start();
|
||||
|
||||
if (!isset($_SESSION['loggedin']) || $_SESSION['loggedin'] !== true) {
|
||||
die(json_encode([
|
||||
"success" => false,
|
||||
"message" => translate('session_expired', $i18n)
|
||||
]));
|
||||
}
|
||||
|
||||
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
$postData = file_get_contents("php://input");
|
||||
$data = json_decode($postData, true);
|
||||
|
||||
if (
|
||||
!isset($data["user_key"]) || $data["user_key"] == "" ||
|
||||
!isset($data["token"]) || $data["token"] == ""
|
||||
) {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"message" => translate('fill_mandatory_fields', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
} else {
|
||||
$enabled = $data["enabled"];
|
||||
$user_key = $data["user_key"];
|
||||
$token = $data["token"];
|
||||
|
||||
$query = "SELECT COUNT(*) FROM pushover_notifications";
|
||||
$result = $db->querySingle($query);
|
||||
|
||||
if ($result === false) {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"message" => translate('error_saving_notifications', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
} else {
|
||||
if ($result == 0) {
|
||||
$query = "INSERT INTO pushover_notifications (enabled, user_key, token)
|
||||
VALUES (:enabled, :user_key, :token)";
|
||||
} else {
|
||||
$query = "UPDATE pushover_notifications
|
||||
SET enabled = :enabled, user_key = :user_key, token = :token";
|
||||
}
|
||||
|
||||
$stmt = $db->prepare($query);
|
||||
$stmt->bindValue(':enabled', $enabled, SQLITE3_INTEGER);
|
||||
$stmt->bindValue(':user_key', $user_key, SQLITE3_TEXT);
|
||||
$stmt->bindValue(':token', $token, SQLITE3_TEXT);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
$response = [
|
||||
"success" => true,
|
||||
"message" => translate('notifications_settings_saved', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
} else {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"message" => translate('error_saving_notifications', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@ -19,7 +19,7 @@
|
||||
) {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"errorMessage" => translate('fill_mandatory_fields', $i18n)
|
||||
"message" => translate('fill_mandatory_fields', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
} else {
|
||||
@ -33,7 +33,7 @@
|
||||
if ($result === false) {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"errorMessage" => translate('error_saving_notifications', $i18n)
|
||||
"message" => translate('error_saving_notifications', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
} else {
|
||||
@ -59,7 +59,7 @@
|
||||
} else {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"errorMessage" => translate('error_saving_notifications', $i18n)
|
||||
"message" => translate('error_saving_notifications', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
) {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"errorMessage" => translate('fill_mandatory_fields', $i18n)
|
||||
"message" => translate('fill_mandatory_fields', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
} else {
|
||||
@ -34,7 +34,7 @@
|
||||
if ($result === false) {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"errorMessage" => translate('error_saving_notifications', $i18n)
|
||||
"message" => translate('error_saving_notifications', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
} else {
|
||||
@ -61,7 +61,7 @@
|
||||
} else {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"errorMessage" => translate('error_saving_notifications', $i18n)
|
||||
"message" => translate('error_saving_notifications', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
}
|
||||
|
||||
90
endpoints/notifications/testdiscordnotifications.php
Normal file
90
endpoints/notifications/testdiscordnotifications.php
Normal file
@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
require_once '../../includes/connect_endpoint.php';
|
||||
session_start();
|
||||
|
||||
if (!isset($_SESSION['loggedin']) || $_SESSION['loggedin'] !== true) {
|
||||
die(json_encode([
|
||||
"success" => false,
|
||||
"message" => translate('session_expired', $i18n)
|
||||
]));
|
||||
}
|
||||
|
||||
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
$postData = file_get_contents("php://input");
|
||||
$data = json_decode($postData, true);
|
||||
|
||||
if (
|
||||
!isset($data["url"]) || $data["url"] == ""
|
||||
) {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"message" => translate('fill_mandatory_fields', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
} else {
|
||||
// Set the message parameters
|
||||
$title = translate('wallos_notification', $i18n);
|
||||
$message = translate('test_notification', $i18n);
|
||||
|
||||
$webhook_url = $data["url"];
|
||||
$bot_username = $data["bot_username"];
|
||||
$bot_avatar_url = $data["bot_avatar"];
|
||||
|
||||
$postfields = [
|
||||
'content' => $message,
|
||||
'embeds' => [
|
||||
[
|
||||
'title' => $title,
|
||||
'description' => $message,
|
||||
'color' => hexdec("FF0000")
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
if (!empty($bot_username)) {
|
||||
$postfields['username'] = $bot_username;
|
||||
}
|
||||
|
||||
if (!empty($bot_avatar_url)) {
|
||||
$postfields['avatar_url'] = $bot_avatar_url;
|
||||
}
|
||||
|
||||
$ch = curl_init();
|
||||
|
||||
// Set the URL and other options
|
||||
curl_setopt($ch, CURLOPT_URL, $webhook_url);
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($postfields));
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
'Content-Type: application/json'
|
||||
]);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
// Execute the request
|
||||
$response = curl_exec($ch);
|
||||
|
||||
// Close the cURL session
|
||||
curl_close($ch);
|
||||
|
||||
// Check if the message was sent successfully
|
||||
if ($response === false) {
|
||||
die(json_encode([
|
||||
"success" => false,
|
||||
"message" => translate('notification_failed', $i18n)
|
||||
]));
|
||||
} else {
|
||||
die(json_encode([
|
||||
"success" => true,
|
||||
"message" => translate('notification_sent_successfuly', $i18n)
|
||||
]));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
die(json_encode([
|
||||
"success" => false,
|
||||
"message" => translate("invalid_request_method", $i18n)
|
||||
]));
|
||||
}
|
||||
|
||||
?>
|
||||
@ -26,7 +26,7 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
) {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"errorMessage" => translate('fill_all_fields', $i18n)
|
||||
"message" => translate('fill_all_fields', $i18n)
|
||||
];
|
||||
die(json_encode($response));
|
||||
} else {
|
||||
@ -76,7 +76,7 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
} else {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"errorMessage" => translate('email_error', $i18n) . $mail->ErrorInfo
|
||||
"message" => translate('email_error', $i18n) . $mail->ErrorInfo
|
||||
];
|
||||
die(json_encode($response));
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
) {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"errorMessage" => translate('fill_mandatory_fields', $i18n)
|
||||
"message" => translate('fill_mandatory_fields', $i18n)
|
||||
];
|
||||
die(json_encode($response));
|
||||
} else {
|
||||
|
||||
71
endpoints/notifications/testpushovernotifications.php
Normal file
71
endpoints/notifications/testpushovernotifications.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
require_once '../../includes/connect_endpoint.php';
|
||||
session_start();
|
||||
|
||||
if (!isset($_SESSION['loggedin']) || $_SESSION['loggedin'] !== true) {
|
||||
die(json_encode([
|
||||
"success" => false,
|
||||
"message" => translate('session_expired', $i18n)
|
||||
]));
|
||||
}
|
||||
|
||||
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
$postData = file_get_contents("php://input");
|
||||
$data = json_decode($postData, true);
|
||||
|
||||
if (
|
||||
!isset($data["user_key"]) || $data["user_key"] == "" ||
|
||||
!isset($data["token"]) || $data["token"] == ""
|
||||
) {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"message" => translate('fill_mandatory_fields', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
} else {
|
||||
// Set the message parameters
|
||||
$message = translate('test_notification', $i18n);
|
||||
|
||||
$user_key = $data["user_key"];
|
||||
$token = $data["token"];
|
||||
|
||||
$ch = curl_init();
|
||||
|
||||
// Set the URL and other options
|
||||
curl_setopt($ch, CURLOPT_URL, "https://api.pushover.net/1/messages.json");
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
|
||||
'token' => $token,
|
||||
'user' => $user_key,
|
||||
'message' => $message,
|
||||
]));
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
// Execute the request
|
||||
$response = curl_exec($ch);
|
||||
|
||||
// Close the cURL session
|
||||
curl_close($ch);
|
||||
|
||||
// Check if the message was sent successfully
|
||||
if ($response === false) {
|
||||
die(json_encode([
|
||||
"success" => false,
|
||||
"message" => translate('notification_failed', $i18n)
|
||||
]));
|
||||
} else {
|
||||
die(json_encode([
|
||||
"success" => true,
|
||||
"message" => translate('notification_sent_successfuly', $i18n)
|
||||
]));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
die(json_encode([
|
||||
"success" => false,
|
||||
"message" => translate("invalid_request_method", $i18n)
|
||||
]));
|
||||
}
|
||||
|
||||
?>
|
||||
@ -19,7 +19,7 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
) {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"errorMessage" => translate('fill_mandatory_fields', $i18n)
|
||||
"message" => translate('fill_mandatory_fields', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
} else {
|
||||
|
||||
@ -21,7 +21,7 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
) {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"errorMessage" => translate('fill_mandatory_fields', $i18n)
|
||||
"message" => translate('fill_mandatory_fields', $i18n)
|
||||
];
|
||||
die(json_encode($response));
|
||||
} else {
|
||||
|
||||
@ -46,6 +46,7 @@
|
||||
<link rel="stylesheet" href="styles/themes/yellow.css?<?= $version ?>" id="yellow-theme" <?= $colorTheme != "yellow" ? "disabled" : "" ?>>
|
||||
<link rel="stylesheet" href="styles/barlow.css">
|
||||
<link rel="stylesheet" href="styles/font-awesome.min.css">
|
||||
<link rel="stylesheet" href="styles/brands.css">
|
||||
<script type="text/javascript" src="scripts/all.js?<?= $version ?>"></script>
|
||||
<script type="text/javascript" src="scripts/common.js?<?= $version ?>"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
@ -132,6 +132,11 @@ $i18n = [
|
||||
"variables_available" => "Verfügbare Variablen",
|
||||
"gotify" => "Gotify",
|
||||
"token" => "Token",
|
||||
"discord" => "Discord",
|
||||
"discord_bot_username" => "Bot Benutzername",
|
||||
"discord_bot_avatar_url" => "Bot Avatar URL",
|
||||
"pushover" => "Pushover",
|
||||
"pushover_user_key" => "Pushover User Key",
|
||||
"categories" => "Kategorien",
|
||||
"save_category" => "Kategorie speichern",
|
||||
"delete_category" => "Kategorie löschen",
|
||||
|
||||
@ -132,6 +132,11 @@ $i18n = [
|
||||
"variables_available" => "Διαθέσιμες μεταβλητές",
|
||||
"gotify" => "Gotify",
|
||||
"token" => "Token",
|
||||
"discord" => "Discord",
|
||||
"discord_bot_username" => "Discord Bot Username",
|
||||
"discord_bot_avatar_url" => "Discord Bot Avatar URL",
|
||||
"pushover" => "Pushover",
|
||||
"pushover_user_key" => "Pushover User Key",
|
||||
"categories" => "Κατηγορίες",
|
||||
"save_category" => "Αποθήκευση κατηγορίας",
|
||||
"delete_category" => "Διαγραφή κατηγορίας",
|
||||
|
||||
@ -132,6 +132,11 @@ $i18n = [
|
||||
"variables_available" => "Variables available",
|
||||
"gotify" => "Gotify",
|
||||
"token" => "Token",
|
||||
"discord" => "Discord",
|
||||
"discord_bot_username" => "Discord Bot Username",
|
||||
"discord_bot_avatar_url" => "Discord Bot Avatar URL",
|
||||
"pushover" => "Pushover",
|
||||
"pushover_user_key" => "Pushover User Key",
|
||||
"categories" => "Categories",
|
||||
"save_category" => "Save Category",
|
||||
"delete_category" => "Delete Category",
|
||||
|
||||
@ -132,6 +132,11 @@ $i18n = [
|
||||
"variables_available" => "Variables disponibles",
|
||||
"gotify" => "Gotify",
|
||||
"token" => "Token",
|
||||
"discord" => "Discord",
|
||||
"discord_bot_username" => "Nombre de usuario del bot",
|
||||
"discord_bot_avatar_url" => "URL del avatar del bot",
|
||||
"pushover" => "Pushover",
|
||||
"pushover_user_key" => "Clave de usuario",
|
||||
"categories" => "Categorías",
|
||||
"save_category" => "Guardar Categoría",
|
||||
"delete_category" => "Eliminar Categoría",
|
||||
|
||||
@ -132,6 +132,11 @@ $i18n = [
|
||||
"variables_available" => "Variables disponibles",
|
||||
"gotify" => "Gotify",
|
||||
"token" => "Jeton",
|
||||
"discord" => "Discord",
|
||||
"discord_bot_username" => "Nom d'utilisateur du bot Discord",
|
||||
"discord_bot_avatar_url" => "URL de l'avatar du bot Discord",
|
||||
"pushover" => "Pushover",
|
||||
"pushover_user_key" => "Clé utilisateur Pushover",
|
||||
"categories" => "Catégories",
|
||||
"save_category" => "Enregistrer la catégorie",
|
||||
"delete_category" => "Supprimer la catégorie",
|
||||
|
||||
@ -137,6 +137,11 @@ $i18n = [
|
||||
"variables_available" => "Variabili disponibili",
|
||||
"gotify" => "Gotify",
|
||||
"token" => "Token",
|
||||
"discord" => "Discord",
|
||||
"discord_bot_username" => "Nome utente del bot",
|
||||
"discord_bot_avatar_url" => "URL dell'avatar del bot",
|
||||
"pushover" => "Pushover",
|
||||
"pushover_user_key" => "Chiave utente",
|
||||
'categories' => 'Categorie',
|
||||
'save_category' => 'Salva categoria',
|
||||
'delete_category' => 'Elimina categoria',
|
||||
|
||||
@ -132,6 +132,11 @@ $i18n = [
|
||||
"variables_available" => "利用可能な変数",
|
||||
"gotify" => "Gotify",
|
||||
"token" => "トークン",
|
||||
"discord" => "Discord",
|
||||
"discord_bot_username" => "Discordボットユーザー名",
|
||||
"discord_bot_avatar_url" => "DiscordボットアバターURL",
|
||||
"pushover" => "Pushover",
|
||||
"pushover_user_key" => "Pushoverユーザーキー",
|
||||
"categories" => "カテゴリ",
|
||||
"save_category" => "カテゴリを保存",
|
||||
"delete_category" => "カテゴリを削除",
|
||||
|
||||
@ -132,6 +132,11 @@ $i18n = [
|
||||
"variables_available" => "Dostępne zmienne",
|
||||
"gotify" => "Gotify",
|
||||
"token" => "Token",
|
||||
"discord" => "Discord",
|
||||
"discord_bot_username" => "Nazwa użytkownika bota",
|
||||
"discord_bot_avatar_url" => "URL awatara bota",
|
||||
"pushover" => "Pushover",
|
||||
"pushover_user_key" => "Klucz użytkownika",
|
||||
"categories" => "Kategorie",
|
||||
"save_category" => "Zapisz kategorię",
|
||||
"delete_category" => "Usuń kategorię",
|
||||
|
||||
@ -132,6 +132,11 @@ $i18n = [
|
||||
"variables_available" => "Variáveis Disponíveis",
|
||||
"gotify" => "Gotify",
|
||||
"token" => "Token",
|
||||
"discord" => "Discord",
|
||||
"discord_bot_username" => "Nome de Utilizador do Bot",
|
||||
"discord_bot_avatar_url" => "URL do Avatar do Bot",
|
||||
"pushover" => "Pushover",
|
||||
"pushover_user_key" => "Chave de Utilizador Pushover",
|
||||
"categories" => "Categorias",
|
||||
"save_category" => "Guardar Categoria",
|
||||
"delete_category" => "Apagar Categoria",
|
||||
|
||||
@ -130,6 +130,11 @@ $i18n = [
|
||||
"variables_available" => "Variáveis disponíveis",
|
||||
"gotify" => "Gotify",
|
||||
"token" => "Token",
|
||||
"discord" => "Discord",
|
||||
"discord_bot_username" => "Nome do Bot",
|
||||
"discord_bot_avatar_url" => "URL do Avatar",
|
||||
"pushover" => "Pushover",
|
||||
"pushover_user_key" => "Chave do Usuário",
|
||||
"categories" => "Categorias",
|
||||
"save_category" => "Salvar categoria",
|
||||
"delete_category" => "Excluir categoria",
|
||||
|
||||
@ -132,6 +132,11 @@ $i18n = [
|
||||
"variables_available" => "Доступне променљиве",
|
||||
"gotify" => "Готифи",
|
||||
"token" => "Токен",
|
||||
"discord" => "Дискорд",
|
||||
"discord_bot_username" => "Дискорд бот корисничко име",
|
||||
"discord_bot_avatar_url" => "Дискорд бот URL аватара",
|
||||
"pushover" => "Пушовер",
|
||||
"pushover_user_key" => "Пушовер кориснички кључ",
|
||||
"categories" => "Категорије",
|
||||
"save_category" => "Сачувај категорију",
|
||||
"delete_category" => "Избриши категорију",
|
||||
|
||||
@ -132,6 +132,11 @@ $i18n = [
|
||||
"variables_available" => "Dostupne promenljive",
|
||||
"gotify" => "Gotify",
|
||||
"token" => "Token",
|
||||
"discord" => "Discord",
|
||||
"discord_bot_username" => "Discord bot korisničko ime",
|
||||
"discord_bot_avatar_url" => "Discord bot URL avatara",
|
||||
"pushover" => "Pushover",
|
||||
"pushover_user_key" => "Pushover korisnički ključ",
|
||||
"categories" => "Kategorije",
|
||||
"save_category" => "Sačuvaj kategoriju",
|
||||
"delete_category" => "Izbriši kategoriju",
|
||||
|
||||
@ -132,6 +132,11 @@ $i18n = [
|
||||
"variables_available" => "Kullanılabilir Değişkenler",
|
||||
"gotify" => "Gotify",
|
||||
"token" => "Token",
|
||||
"discord" => "Discord",
|
||||
"discord_bot_username" => "Discord Bot Kullanıcı Adı",
|
||||
"discord_bot_avatar_url" => "Discord Bot Avatar URL",
|
||||
"pushover" => "Pushover",
|
||||
"pushover_user_key" => "Pushover Kullanıcı Anahtarı",
|
||||
"categories" => "Kategoriler",
|
||||
"save_category" => "Kategoriyi Kaydet",
|
||||
"delete_category" => "Kategoriyi Sil",
|
||||
|
||||
@ -139,6 +139,11 @@ $i18n = [
|
||||
"variables_available" => "可用变量",
|
||||
"gotify" => "Gotify",
|
||||
"token" => "令牌",
|
||||
"discord" => "Discord",
|
||||
"discord_bot_username" => "Discord 机器人用户名",
|
||||
"discord_bot_avatar_url" => "Discord 机器人头像 URL",
|
||||
"pushover" => "Pushover",
|
||||
"pushover_user_key" => "Pushover 用户密钥",
|
||||
"categories" => "分类",
|
||||
"save_category" => "保存分类",
|
||||
"delete_category" => "删除分类",
|
||||
|
||||
@ -132,6 +132,11 @@ $i18n = [
|
||||
"variables_available" => "可用變數",
|
||||
"gotify" => "Gotify",
|
||||
"token" => "令牌",
|
||||
"discord" => "Discord",
|
||||
"discord_bot_username" => "Discord 機器人使用者名稱",
|
||||
"discord_bot_avatar_url" => "Discord 機器人頭像 URL",
|
||||
"pushover" => "Pushover",
|
||||
"pushover_user_key" => "Pushover 使用者金鑰",
|
||||
"categories" => "分類",
|
||||
"save_category" => "儲存分類",
|
||||
"delete_category" => "刪除分類",
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
<?php
|
||||
$version = "v1.24.0";
|
||||
$version = "v1.25.0";
|
||||
?>
|
||||
|
||||
19
migrations/000017.php
Normal file
19
migrations/000017.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This migration adds tables to store the date about the new notification methods (pushover and discord)
|
||||
*/
|
||||
|
||||
/** @noinspection PhpUndefinedVariableInspection */
|
||||
$db->exec('CREATE TABLE IF NOT EXISTS pushover_notifications (
|
||||
enabled BOOLEAN DEFAULT 0,
|
||||
user_key TEXT DEFAULT "",
|
||||
token TEXT DEFAULT ""
|
||||
)');
|
||||
|
||||
$db->exec('CREATE TABLE IF NOT EXISTS discord_notifications (
|
||||
enabled BOOLEAN DEFAULT 0,
|
||||
webhook_url TEXT DEFAULT "",
|
||||
bot_username TEXT DEFAULT "",
|
||||
bot_avatar_url TEXT DEFAULT ""
|
||||
)');
|
||||
@ -210,3 +210,74 @@ function testNotificationsGotifyButton() {
|
||||
makeFetchCall('endpoints/notifications/testgotifynotifications.php', data, button);
|
||||
}
|
||||
|
||||
function saveNotificationsPushoverButton() {
|
||||
const button = document.getElementById("saveNotificationsPushover");
|
||||
button.disabled = true;
|
||||
|
||||
const enabled = document.getElementById("pushoverenabled").checked ? 1 : 0;
|
||||
const user_key = document.getElementById("pushoveruserkey").value;
|
||||
const token = document.getElementById("pushovertoken").value;
|
||||
|
||||
const data = {
|
||||
enabled: enabled,
|
||||
user_key: user_key,
|
||||
token: token
|
||||
};
|
||||
|
||||
makeFetchCall('endpoints/notifications/savepushovernotifications.php', data, button);
|
||||
}
|
||||
|
||||
function testNotificationsPushoverButton() {
|
||||
const button = document.getElementById("testNotificationsPushover");
|
||||
button.disabled = true;
|
||||
|
||||
const enabled = document.getElementById("pushoverenabled").checked ? 1 : 0;
|
||||
const user_key = document.getElementById("pushoveruserkey").value;
|
||||
const token = document.getElementById("pushovertoken").value;
|
||||
|
||||
const data = {
|
||||
enabled: enabled,
|
||||
user_key: user_key,
|
||||
token: token
|
||||
};
|
||||
|
||||
makeFetchCall('endpoints/notifications/testpushovernotifications.php', data, button);
|
||||
}
|
||||
|
||||
function saveNotificationsDiscordButton() {
|
||||
const button = document.getElementById("saveNotificationsDiscord");
|
||||
button.disabled = true;
|
||||
|
||||
const enabled = document.getElementById("discordenabled").checked ? 1 : 0;
|
||||
const url = document.getElementById("discordurl").value;
|
||||
const bot_username = document.getElementById("discordbotusername").value;
|
||||
const bot_avatar = document.getElementById("discordbotavatar").value;
|
||||
|
||||
const data = {
|
||||
enabled: enabled,
|
||||
url: url,
|
||||
bot_username: bot_username,
|
||||
bot_avatar: bot_avatar
|
||||
};
|
||||
|
||||
makeFetchCall('endpoints/notifications/savediscordnotifications.php', data, button);
|
||||
}
|
||||
|
||||
function testNotificationsDiscordButton() {
|
||||
const button = document.getElementById("testNotificationsDiscord");
|
||||
button.disabled = true;
|
||||
|
||||
const enabled = document.getElementById("discordenabled").checked ? 1 : 0;
|
||||
const url = document.getElementById("discordurl").value;
|
||||
const bot_username = document.getElementById("discordbotusername").value;
|
||||
const bot_avatar = document.getElementById("discordbotavatar").value;
|
||||
|
||||
const data = {
|
||||
enabled: enabled,
|
||||
url: url,
|
||||
bot_username: bot_username,
|
||||
bot_avatar: bot_avatar
|
||||
};
|
||||
|
||||
makeFetchCall('endpoints/notifications/testdiscordnotifications.php', data, button);
|
||||
}
|
||||
@ -13,12 +13,15 @@ self.addEventListener('install', function(event) {
|
||||
'styles/dark-theme.css',
|
||||
'styles/login.css',
|
||||
'styles/font-awesome.min.css',
|
||||
'styles/brands.css',
|
||||
'styles/barlow.css',
|
||||
'styles/themes/red.css',
|
||||
'styles/themes/green.css',
|
||||
'styles/themes/yellow.css',
|
||||
'webfonts/fa-solid-900.woff2',
|
||||
'webfonts/fa-solid-900.ttf',
|
||||
'webfonts/fa-brands-400.woff2',
|
||||
'webfonts/fa-brands-400.ttf',
|
||||
'scripts/common.js',
|
||||
'scripts/dashboard.js',
|
||||
'scripts/stats.js',
|
||||
|
||||
90
settings.php
90
settings.php
@ -216,6 +216,44 @@
|
||||
$notificationsEmail['from_email'] = "";
|
||||
}
|
||||
|
||||
// Discord notifications
|
||||
$sql = "SELECT * FROM discord_notifications LIMIT 1";
|
||||
$result = $db->query($sql);
|
||||
|
||||
$rowCount = 0;
|
||||
while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
|
||||
$notificationsDiscord['enabled'] = $row['enabled'];
|
||||
$notificationsDiscord['webhook_url'] = $row['webhook_url'];
|
||||
$notificationsDiscord['bot_username'] = $row['bot_username'];
|
||||
$notificationsDiscord['bot_avatar'] = $row['bot_avatar_url'];
|
||||
$rowCount++;
|
||||
}
|
||||
|
||||
if ($rowCount == 0) {
|
||||
$notificationsDiscord['enabled'] = 0;
|
||||
$notificationsDiscord['url'] = "";
|
||||
$notificationsDiscord['bot_username'] = "";
|
||||
$notificationsDiscord['bot_avatar'] = "";
|
||||
}
|
||||
|
||||
// Pushover notifications
|
||||
$sql = "SELECT * FROM pushover_notifications LIMIT 1";
|
||||
$result = $db->query($sql);
|
||||
|
||||
$rowCount = 0;
|
||||
while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
|
||||
$notificationsPushover['enabled'] = $row['enabled'];
|
||||
$notificationsPushover['token'] = $row['token'];
|
||||
$notificationsPushover['user_key'] = $row['user_key'];
|
||||
$rowCount++;
|
||||
}
|
||||
|
||||
if ($rowCount == 0) {
|
||||
$notificationsPushover['enabled'] = 0;
|
||||
$notificationsPushover['token'] = "";
|
||||
$notificationsPushover['user_key'] = "";
|
||||
}
|
||||
|
||||
// Telegram notifications
|
||||
$sql = "SELECT * FROM telegram_notifications LIMIT 1";
|
||||
$result = $db->query($sql);
|
||||
@ -358,6 +396,33 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="account-notifications-section">
|
||||
<header class="account-notification-section-header" onclick="openNotificationsSettings('discord');">
|
||||
<h3>
|
||||
<i class="fa-brands fa-discord"></i>
|
||||
<?= translate('discord', $i18n) ?>
|
||||
</h3>
|
||||
</header>
|
||||
<div class="account-notification-section-settings" data-type="discord">
|
||||
<div class="form-group-inline">
|
||||
<input type="checkbox" id="discordenabled" name="discordenabled" <?= $notificationsDiscord['enabled'] ? "checked" : "" ?>>
|
||||
<label for="discordenabled" class="capitalize"><?= translate('enabled', $i18n) ?></label>
|
||||
</div>
|
||||
<div class="form-group-inline">
|
||||
<input type="text" name="discordurl" id="discordurl" placeholder="<?= translate('webhook_url', $i18n) ?>" value="<?= $notificationsDiscord['webhook_url'] ?>" />
|
||||
</div>
|
||||
<div class="form-group-inline">
|
||||
<input type="text" name="discordbotusername" id="discordbotusername" placeholder="<?= translate('discord_bot_username', $i18n) ?>" value="<?= $notificationsDiscord['bot_username'] ?>" />
|
||||
</div>
|
||||
<div class="form-group-inline">
|
||||
<input type="text" name="discordbotavatar" id="discordbotavatar" placeholder="<?= translate('discord_bot_avatar_url', $i18n) ?>" value="<?= $notificationsDiscord['bot_avatar'] ?>" />
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<input type="button" class="secondary-button thin" value="<?= translate('test', $i18n) ?>" id="testNotificationsDiscord" onClick="testNotificationsDiscordButton()"/>
|
||||
<input type="submit" class="thin" value="<?= translate('save', $i18n) ?>" id="saveNotificationsDiscord" onClick="saveNotificationsDiscordButton()"/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="account-notifications-section">
|
||||
<header class="account-notification-section-header" onclick="openNotificationsSettings('gotify');">
|
||||
<h3>
|
||||
@ -382,6 +447,31 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="account-notifications-section">
|
||||
<header class="account-notification-section-header" onclick="openNotificationsSettings('pushover');">
|
||||
<h3>
|
||||
<i class="fa-brands fa-pinterest-p"></i>
|
||||
<?= translate('pushover', $i18n) ?>
|
||||
</h3>
|
||||
</header>
|
||||
<div class="account-notification-section-settings" data-type="pushover">
|
||||
<div class="form-group-inline">
|
||||
<input type="checkbox" id="pushoverenabled" name="pushoverenabled" <?= $notificationsPushover['enabled'] ? "checked" : "" ?>>
|
||||
<label for="pushoverenabled" class="capitalize"><?= translate('enabled', $i18n) ?></label>
|
||||
</div>
|
||||
<div class="form-group-inline">
|
||||
<input type="text" name="pushoveruserkey" id="pushoveruserkey" placeholder="<?= translate('pushover_user_key', $i18n) ?>" value="<?= $notificationsPushover['user_key'] ?>" />
|
||||
</div>
|
||||
<div class="form-group-inline">
|
||||
<input type="text" name="pushovertoken" id="pushovertoken" placeholder="<?= translate('token', $i18n) ?>" value="<?= $notificationsPushover['token'] ?>" />
|
||||
</div>
|
||||
|
||||
<div class="buttons">
|
||||
<input type="button" class="secondary-button thin" value="<?= translate('test', $i18n) ?>" id="testNotificationsPushover" onClick="testNotificationsPushoverButton()"/>
|
||||
<input type="submit" class="thin" value="<?= translate('save', $i18n) ?>" id="saveNotificationsPushover" onClick="saveNotificationsPushoverButton()"/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="account-notifications-section">
|
||||
<header class="account-notification-section-header" onclick="openNotificationsSettings('telegram');">
|
||||
<h3>
|
||||
|
||||
1594
styles/brands.css
Normal file
1594
styles/brands.css
Normal file
File diff suppressed because it is too large
Load Diff
9
styles/fontawesome.min.css
vendored
Normal file
9
styles/fontawesome.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
webfonts/fa-brands-400.ttf
Normal file
BIN
webfonts/fa-brands-400.ttf
Normal file
Binary file not shown.
BIN
webfonts/fa-brands-400.woff2
Normal file
BIN
webfonts/fa-brands-400.woff2
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user