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:
Miguel Ribeiro 2024-05-06 18:55:10 +02:00 committed by GitHub
parent 4199d4c3e7
commit 899482982e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
40 changed files with 2317 additions and 23 deletions

View File

@ -2,4 +2,5 @@
#Webroot path
$webPath = "/var/www/html/";
?>

View File

@ -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

View 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);
}
}
}
}
?>

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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();

View 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);
}
}
}
}
?>

View File

@ -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);
}

View File

@ -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);
}

View 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)
]));
}
?>

View File

@ -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));
}

View File

@ -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 {

View 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)
]));
}
?>

View File

@ -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 {

View File

@ -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 {

View File

@ -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">

View File

@ -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",

View File

@ -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" => "Διαγραφή κατηγορίας",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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',

View File

@ -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" => "カテゴリを削除",

View File

@ -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ę",

View File

@ -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",

View File

@ -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",

View File

@ -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" => "Избриши категорију",

View File

@ -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",

View File

@ -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",

View File

@ -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" => "删除分类",

View File

@ -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" => "刪除分類",

View File

@ -1,3 +1,3 @@
<?php
$version = "v1.24.0";
$version = "v1.25.0";
?>

19
migrations/000017.php Normal file
View 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 ""
)');

View File

@ -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);
}

View File

@ -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',

View File

@ -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

File diff suppressed because it is too large Load Diff

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

Binary file not shown.

Binary file not shown.