From a408031ef8711bf87e9f8db35f52c498f250b235 Mon Sep 17 00:00:00 2001 From: Miguel Ribeiro Date: Mon, 6 May 2024 00:15:44 +0200 Subject: [PATCH] feat: add new notification methods (telegram, webhooks, gotify) (#295) --- .tmp/.gitignore | 4 +- endpoints/cronjobs/conf.php | 1 - endpoints/cronjobs/sendnotifications.php | 353 +++++++++++++++--- .../{save.php => saveemailnotifications.php} | 20 +- .../notifications/savegotifynotifications.php | 69 ++++ .../savenotificationsettings.php | 67 ++++ .../savetelegramnotifications.php | 69 ++++ .../savewebhooknotifications.php | 71 ++++ ...estmail.php => testemailnotifications.php} | 14 +- .../notifications/testgotifynotifications.php | 71 ++++ .../testtelegramnotifications.php | 69 ++++ .../testwebhooknotifications.php | 74 ++++ images/uploads/logos/wallos.png | Bin 7273 -> 0 bytes includes/i18n/de.php | 13 + includes/i18n/el.php | 13 + includes/i18n/en.php | 13 + includes/i18n/es.php | 13 + includes/i18n/fr.php | 13 + includes/i18n/it.php | 63 ++++ includes/i18n/jp.php | 13 + includes/i18n/pl.php | 13 + includes/i18n/pt.php | 13 + includes/i18n/pt_br.php | 13 + includes/i18n/sr.php | 13 + includes/i18n/sr_lat.php | 13 + includes/i18n/tr.php | 13 + includes/i18n/zh_cn.php | 13 + includes/i18n/zh_tw.php | 13 + includes/version.php | 2 +- index.php | 16 - migrations/000016.php | 64 ++++ scripts/notifications.js | 212 +++++++++++ scripts/settings.js | 88 ----- service-worker.js | 1 + settings.php | 311 ++++++++++++--- styles/dark-theme.css | 10 + styles/styles.css | 61 +++ 37 files changed, 1658 insertions(+), 234 deletions(-) rename endpoints/notifications/{save.php => saveemailnotifications.php} (79%) create mode 100644 endpoints/notifications/savegotifynotifications.php create mode 100644 endpoints/notifications/savenotificationsettings.php create mode 100644 endpoints/notifications/savetelegramnotifications.php create mode 100644 endpoints/notifications/savewebhooknotifications.php rename endpoints/notifications/{sendtestmail.php => testemailnotifications.php} (85%) create mode 100644 endpoints/notifications/testgotifynotifications.php create mode 100644 endpoints/notifications/testtelegramnotifications.php create mode 100644 endpoints/notifications/testwebhooknotifications.php delete mode 100644 images/uploads/logos/wallos.png create mode 100644 migrations/000016.php create mode 100644 scripts/notifications.js diff --git a/.tmp/.gitignore b/.tmp/.gitignore index a3a0c8b..d6b7ef3 100644 --- a/.tmp/.gitignore +++ b/.tmp/.gitignore @@ -1,2 +1,2 @@ -* -!.gitignore \ No newline at end of file +* +!.gitignore diff --git a/endpoints/cronjobs/conf.php b/endpoints/cronjobs/conf.php index eabfc2e..0c48285 100644 --- a/endpoints/cronjobs/conf.php +++ b/endpoints/cronjobs/conf.php @@ -2,5 +2,4 @@ #Webroot path $webPath = "/var/www/html/"; - ?> \ No newline at end of file diff --git a/endpoints/cronjobs/sendnotifications.php b/endpoints/cronjobs/sendnotifications.php index 2e27247..274467a 100644 --- a/endpoints/cronjobs/sendnotifications.php +++ b/endpoints/cronjobs/sendnotifications.php @@ -6,36 +6,109 @@ require_once 'conf.php'; require_once $webPath . 'includes/connect_endpoint_crontabs.php'; - $query = "SELECT * FROM notifications WHERE id = 1"; + $days = 1; + $emailNotificationsEnabled = false; + $gotifyNotificationsEnabled = false; + $telegramNotificationsEnabled = false; + $webhookNotificationsEnabled = false; + + // Get notification settings (how many days before the subscription ends should the notification be sent) + $query = "SELECT days FROM notification_settings"; $result = $db->query($query); if ($row = $result->fetchArray(SQLITE3_ASSOC)) { - $notificationsEnabled = $row['enabled']; $days = $row['days']; - $smtpAddress = $row["smtp_address"]; - $smtpPort = $row["smtp_port"]; - $encryption = $row["encryption"]; - $smtpUsername = $row["smtp_username"]; - $smtpPassword = $row["smtp_password"]; - $fromEmail = $row["from_email"] ? $row["from_email"] : "wallos@wallosapp.com"; - } else { - echo "Notifications are disabled. No need to run."; } - if ($notificationsEnabled) { + + // Check if email notifications are enabled and get the settings + $query = "SELECT * FROM email_notifications"; + $result = $db->query($query); + + if ($row = $result->fetchArray(SQLITE3_ASSOC)) { + $emailNotificationsEnabled = $row['enabled']; + $email['smtpAddress'] = $row["smtp_address"]; + $email['smtpPort'] = $row["smtp_port"]; + $email['encryption'] = $row["encryption"]; + $email['smtpUsername'] = $row["smtp_username"]; + $email['smtpPassword'] = $row["smtp_password"]; + $email['fromEmail'] = $row["from_email"] ? $row["from_email"] : "wallos@wallosapp.com"; + } + + // Check if Gotify notifications are enabled and get the settings + $query = "SELECT * FROM gotify_notifications"; + $result = $db->query($query); + + if ($row = $result->fetchArray(SQLITE3_ASSOC)) { + $gotifyNotificationsEnabled = $row['enabled']; + $gotify['serverUrl'] = $row["url"]; + $gotify['appToken'] = $row["token"]; + } + + // Check if Telegram notifications are enabled and get the settings + $query = "SELECT * FROM telegram_notifications"; + $result = $db->query($query); + + if ($row = $result->fetchArray(SQLITE3_ASSOC)) { + $telegramNotificationsEnabled = $row['enabled']; + $telegram['botToken'] = $row["bot_token"]; + $telegram['chatId'] = $row["chat_id"]; + } + + // Check if Webhook notifications are enabled and get the settings + $query = "SELECT * FROM webhook_notifications"; + $result = $db->query($query); + + if ($row = $result->fetchArray(SQLITE3_ASSOC)) { + $webhookNotificationsEnabled = $row['enabled']; + $webhook['url'] = $row["url"]; + $webhook['request_method'] = $row["request_method"]; + $webhook['headers'] = $row["headers"]; + $webhook['payload'] = $row["payload"]; + $webhook['iterator'] = $row["iterator"]; + if ($webhook['iterator'] === "") { + $webhook['iterator'] = "subscriptions"; + } + } + + $notificationsEnabled = $emailNotificationsEnabled || $gotifyNotificationsEnabled || $telegramNotificationsEnabled || $webhookNotificationsEnabled; + + // If no notifications are enabled, no need to run + if (!$notificationsEnabled) { + echo "Notifications are disabled. No need to run."; + exit(); + } else { + // Get all currencies $currencies = array(); $query = "SELECT * FROM currencies"; $result = $db->query($query); while ($row = $result->fetchArray(SQLITE3_ASSOC)) { - $currencyId = $row['id']; - $currencies[$currencyId] = $row; + $currencies[$row['id']] = $row; + } + + // Get all household members + $stmt = $db->prepare('SELECT * FROM household'); + $resultHousehold = $stmt->execute(); + + $household = []; + while ($rowHousehold = $resultHousehold->fetchArray(SQLITE3_ASSOC)) { + $household[$rowHousehold['id']] = $rowHousehold; + } + + // Get all categories + $stmt = $db->prepare('SELECT * FROM categories'); + $resultCategories = $stmt->execute(); + + $categories = []; + while ($rowCategory = $resultCategories->fetchArray(SQLITE3_ASSOC)) { + $categories[$rowCategory['id']] = $rowCategory; } $stmt = $db->prepare('SELECT * FROM subscriptions WHERE notify = :notify AND inactive = :inactive ORDER BY payer_user_id ASC'); $stmt->bindValue(':notify', 1, SQLITE3_INTEGER); $stmt->bindValue(':inactive', 0, SQLITE3_INTEGER); $resultSubscriptions = $stmt->execute(); - + $notify = []; $i = 0; $currentDate = new DateTime('now'); while ($rowSubscription = $resultSubscriptions->fetchArray(SQLITE3_ASSOC)) { @@ -44,62 +117,224 @@ if ($difference === $days) { $notify[$rowSubscription['payer_user_id']][$i]['name'] = $rowSubscription['name']; $notify[$rowSubscription['payer_user_id']][$i]['price'] = $rowSubscription['price'] . $currencies[$rowSubscription['currency_id']]['symbol']; + $notify[$rowSubscription['payer_user_id']][$i]['currency'] = $currencies[$rowSubscription['currency_id']]['name']; + $notify[$rowSubscription['payer_user_id']][$i]['category'] = $categories[$rowSubscription['category_id']]['name']; + $notify[$rowSubscription['payer_user_id']][$i]['payer'] = $household[$rowSubscription['payer_user_id']]['name']; + $notify[$rowSubscription['payer_user_id']][$i]['date'] = $rowSubscription['next_payment']; $i++; } } if (!empty($notify)) { - require $webPath . 'libs/PHPMailer/PHPMailer.php'; - require $webPath . 'libs/PHPMailer/SMTP.php'; - require $webPath . 'libs/PHPMailer/Exception.php'; + // Email notifications if enabled + if ($emailNotificationsEnabled) { + require $webPath . 'libs/PHPMailer/PHPMailer.php'; + require $webPath . 'libs/PHPMailer/SMTP.php'; + require $webPath . 'libs/PHPMailer/Exception.php'; - $stmt = $db->prepare('SELECT * FROM user WHERE id = :id'); - $stmt->bindValue(':id', 1, SQLITE3_INTEGER); - $result = $stmt->execute(); - $defaultUser = $result->fetchArray(SQLITE3_ASSOC); - $defaultEmail = $defaultUser['email']; - $defaultName = $defaultUser['username']; - - foreach ($notify as $userId => $perUser) { - $dayText = $days == 1 ? "tomorrow" : "in " . $days . " days"; - $message = "The following subscriptions are up for renewal " . $dayText . ":\n"; - - foreach ($perUser as $subscription) { - $message .= $subscription['name'] . " for " . $subscription['price'] . "\n"; - } - - $mail = new PHPMailer(true); - $mail->CharSet="UTF-8"; - $mail->isSMTP(); - - $mail->Host = $smtpAddress; - $mail->SMTPAuth = true; - $mail->Username = $smtpUsername; - $mail->Password = $smtpPassword; - $mail->SMTPSecure = $encryption; - $mail->Port = $smtpPort; - - $stmt = $db->prepare('SELECT * FROM household WHERE id = :userId'); - $stmt->bindValue(':userId', $userId, SQLITE3_INTEGER); + $stmt = $db->prepare('SELECT * FROM user WHERE id = :id'); + $stmt->bindValue(':id', 1, SQLITE3_INTEGER); $result = $stmt->execute(); - $user = $result->fetchArray(SQLITE3_ASSOC); + $defaultUser = $result->fetchArray(SQLITE3_ASSOC); + $defaultEmail = $defaultUser['email']; + $defaultName = $defaultUser['username']; - $email = !empty($user['email']) ? $user['email'] : $defaultEmail; - $name = !empty($user['name']) ? $user['name'] : $defaultName; - - $mail->setFrom($fromEmail, 'Wallos App'); - $mail->addAddress($email, $name); - - $mail->Subject = 'Wallos Notification'; - $mail->Body = $message; - - if ($mail->send()) { - echo "Notifications sent"; - } else { - echo "Error sending notifications: " . $mail->ErrorInfo; + foreach ($notify as $userId => $perUser) { + $dayText = $days == 1 ? "tomorrow" : "in " . $days . " days"; + $message = "The following subscriptions are up for renewal " . $dayText . ":\n"; + + foreach ($perUser as $subscription) { + $message .= $subscription['name'] . " for " . $subscription['price'] . "\n"; + } + + $mail = new PHPMailer(true); + $mail->CharSet="UTF-8"; + $mail->isSMTP(); + + $mail->Host = $email['smtpAddress']; + $mail->SMTPAuth = true; + $mail->Username = $email['smtpUsername']; + $mail->Password = $email['smtpPassword']; + $mail->SMTPSecure = $email['encryption']; + $mail->Port = $email['smtpPort']; + + $stmt = $db->prepare('SELECT * FROM household WHERE id = :userId'); + $stmt->bindValue(':userId', $userId, SQLITE3_INTEGER); + $result = $stmt->execute(); + $user = $result->fetchArray(SQLITE3_ASSOC); + + $emailaddress = !empty($user['email']) ? $user['email'] : $defaultEmail; + $name = !empty($user['name']) ? $user['name'] : $defaultName; + + $mail->setFrom($email['fromEmail'], 'Wallos App'); + $mail->addAddress($emailaddress, $name); + + $mail->Subject = 'Wallos Notification'; + $mail->Body = $message; + + if ($mail->send()) { + echo "Email Notifications sent
"; + } else { + echo "Error sending notifications: " . $mail->ErrorInfo; + } } } + + // Gotify notifications if enabled + if ($gotifyNotificationsEnabled) { + 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"; + } + + $data = array( + 'message' => $message, + 'priority' => 5 + ); + + $data_string = json_encode($data); + + $ch = curl_init($gotify['serverUrl'] . '/message?token=' . $gotify['appToken']); + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); + curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_HTTPHEADER, array( + 'Content-Type: application/json', + 'Content-Length: ' . strlen($data_string)) + ); + + $result = curl_exec($ch); + if ($result === false) { + echo "Error sending notifications: " . curl_error($ch); + } else { + echo "Gotify Notifications sent
"; + } + } + } + + // Telegram notifications if enabled + if ($telegramNotificationsEnabled) { + 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"; + } + + $data = array( + 'chat_id' => $telegram['chatId'], + 'text' => $message + ); + + $data_string = json_encode($data); + + $ch = curl_init('https://api.telegram.org/bot' . $telegram['botToken'] . '/sendMessage'); + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); + curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_HTTPHEADER, array( + 'Content-Type: application/json', + 'Content-Length: ' . strlen($data_string)) + ); + + $result = curl_exec($ch); + if ($result === false) { + echo "Error sending notifications: " . curl_error($ch); + } else { + echo "Telegram Notifications sent
"; + } + } + } + + // Webhook notifications if enabled + if ($webhookNotificationsEnabled) { + // Get webhook payload and turn it into a json object + + $payload = str_replace("{{days_until}}", $days, $webhook['payload']); + $payload_json = json_decode($payload, true); + + $subscription_template = $payload_json["{{subscriptions}}"]; + $subscriptions = []; + + 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); + + if ($user['name']) { + $payer = $user['name']; + } + + foreach ($perUser as $k => $subscription) { + $temp_subscription = $subscription_template[0]; + + foreach ($temp_subscription as $key => $value) { + if (is_string($value)) { + $temp_subscription[$key] = str_replace("{{subscription_name}}", $subscription['name'], $value); + $temp_subscription[$key] = str_replace("{{subscription_price}}", $subscription['price'], $temp_subscription[$key]); + $temp_subscription[$key] = str_replace("{{subscription_currency}}", $subscription['currency'], $temp_subscription[$key]); + $temp_subscription[$key] = str_replace("{{subscription_category}}", $subscription['category'], $temp_subscription[$key]); + $temp_subscription[$key] = str_replace("{{subscription_payer}}", $subscription['payer'], $temp_subscription[$key]); + $temp_subscription[$key] = str_replace("{{subscription_date}}", $subscription['date'], $temp_subscription[$key]); + } + } + $subscriptions[] = $temp_subscription; + + } + } + + $payload_json["{{subscriptions}}"] = $subscriptions; + $payload_json[$webhook['iterator']] = $subscriptions; + unset($payload_json["{{subscriptions}}"]); + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $webhook['url']); + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $webhook['request_method']); + curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload_json)); + if (!empty($customheaders)) { + curl_setopt($ch, CURLOPT_HTTPHEADER, $webhook['headers']); + } + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + + $response = curl_exec($ch); + curl_close($ch); + + if ($response === false) { + echo "Error sending notifications: " . curl_error($ch); + } else { + echo "Webhook Notifications sent
"; + } + + } + + } else { echo "Nothing to notify."; } diff --git a/endpoints/notifications/save.php b/endpoints/notifications/saveemailnotifications.php similarity index 79% rename from endpoints/notifications/save.php rename to endpoints/notifications/saveemailnotifications.php index 79bbce5..8ecbd52 100644 --- a/endpoints/notifications/save.php +++ b/endpoints/notifications/saveemailnotifications.php @@ -2,12 +2,18 @@ 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["days"]) || $data['days'] == "" || !isset($data["smtpaddress"]) || $data["smtpaddress"] == "" || !isset($data["smtpport"]) || $data["smtpport"] == "" || !isset($data["smtpusername"]) || $data["smtpusername"] == "" || @@ -20,7 +26,6 @@ echo json_encode($response); } else { $enabled = $data["enabled"]; - $days = $data["days"]; $smtpAddress = $data["smtpaddress"]; $smtpPort = $data["smtpport"]; $encryption = "tls"; @@ -31,7 +36,7 @@ $smtpPassword = $data["smtppassword"]; $fromEmail = $data["fromemail"]; - $query = "SELECT COUNT(*) FROM notifications"; + $query = "SELECT COUNT(*) FROM email_notifications"; $result = $db->querySingle($query); if ($result === false) { @@ -42,17 +47,16 @@ echo json_encode($response); } else { if ($result == 0) { - $query = "INSERT INTO notifications (enabled, days, smtp_address, smtp_port, smtp_username, smtp_password, from_email, encryption) - VALUES (:enabled, :days, :smtpAddress, :smtpPort, :smtpUsername, :smtpPassword, :fromEmail, :encryption)"; + $query = "INSERT INTO email_notifications (enabled, smtp_address, smtp_port, smtp_username, smtp_password, from_email, encryption) + VALUES (:enabled, :smtpAddress, :smtpPort, :smtpUsername, :smtpPassword, :fromEmail, :encryption)"; } else { - $query = "UPDATE notifications - SET enabled = :enabled, days = :days, smtp_address = :smtpAddress, smtp_port = :smtpPort, + $query = "UPDATE email_notifications + SET enabled = :enabled, smtp_address = :smtpAddress, smtp_port = :smtpPort, smtp_username = :smtpUsername, smtp_password = :smtpPassword, from_email = :fromEmail, encryption = :encryption"; } $stmt = $db->prepare($query); $stmt->bindValue(':enabled', $enabled, SQLITE3_INTEGER); - $stmt->bindValue(':days', $days, SQLITE3_INTEGER); $stmt->bindValue(':smtpAddress', $smtpAddress, SQLITE3_TEXT); $stmt->bindValue(':smtpPort', $smtpPort, SQLITE3_INTEGER); $stmt->bindValue(':smtpUsername', $smtpUsername, SQLITE3_TEXT); diff --git a/endpoints/notifications/savegotifynotifications.php b/endpoints/notifications/savegotifynotifications.php new file mode 100644 index 0000000..3fe903c --- /dev/null +++ b/endpoints/notifications/savegotifynotifications.php @@ -0,0 +1,69 @@ + 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["gotify_url"]) || $data["gotify_url"] == "" || + !isset($data["token"]) || $data["token"] == "" + ) { + $response = [ + "success" => false, + "errorMessage" => translate('fill_mandatory_fields', $i18n) + ]; + echo json_encode($response); + } else { + $enabled = $data["enabled"]; + $url = $data["gotify_url"]; + $token = $data["token"]; + + $query = "SELECT COUNT(*) FROM gotify_notifications"; + $result = $db->querySingle($query); + + if ($result === false) { + $response = [ + "success" => false, + "errorMessage" => translate('error_saving_notifications', $i18n) + ]; + echo json_encode($response); + } else { + if ($result == 0) { + $query = "INSERT INTO gotify_notifications (enabled, url, token) + VALUES (:enabled, :url, :token)"; + } else { + $query = "UPDATE gotify_notifications + SET enabled = :enabled, url = :url, token = :token"; + } + + $stmt = $db->prepare($query); + $stmt->bindValue(':enabled', $enabled, SQLITE3_INTEGER); + $stmt->bindValue(':url', $url, 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, + "errorMessage" => translate('error_saving_notifications', $i18n) + ]; + echo json_encode($response); + } + } + } + } +?> \ No newline at end of file diff --git a/endpoints/notifications/savenotificationsettings.php b/endpoints/notifications/savenotificationsettings.php new file mode 100644 index 0000000..b603fc5 --- /dev/null +++ b/endpoints/notifications/savenotificationsettings.php @@ -0,0 +1,67 @@ + 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["days"]) || $data['days'] == "") { + $response = [ + "success" => false, + "errorMessage" => translate('fill_mandatory_fields', $i18n) + ]; + echo json_encode($response); + } else { + $days = $data["days"]; + $query = "SELECT COUNT(*) FROM notification_settings"; + $result = $db->querySingle($query); + + if ($result === false) { + $response = [ + "success" => false, + "errorMessage" => translate('error_saving_notifications', $i18n) + ]; + echo json_encode($response); + } else { + if ($result == 0) { + $query = "INSERT INTO notification_settings (days) + VALUES (:days)"; + } else { + $query = "UPDATE notification_settings SET days = :days"; + } + + $stmt = $db->prepare($query); + $stmt->bindValue(':days', $days, SQLITE3_INTEGER); + + if ($stmt->execute()) { + $response = [ + "success" => true, + "message" => translate('notifications_settings_saved', $i18n) + ]; + echo json_encode($response); + } else { + $response = [ + "success" => false, + "errorMessage" => translate('error_saving_notifications', $i18n) + ]; + echo json_encode($response); + } + } + } + } else { + $response = [ + "success" => false, + "errorMessage" => "Invalid request method" + ]; + echo json_encode($response); + exit(); + } \ No newline at end of file diff --git a/endpoints/notifications/savetelegramnotifications.php b/endpoints/notifications/savetelegramnotifications.php new file mode 100644 index 0000000..1b86334 --- /dev/null +++ b/endpoints/notifications/savetelegramnotifications.php @@ -0,0 +1,69 @@ + 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["bot_token"]) || $data["bot_token"] == "" || + !isset($data["chat_id"]) || $data["chat_id"] == "" + ) { + $response = [ + "success" => false, + "errorMessage" => translate('fill_mandatory_fields', $i18n) + ]; + echo json_encode($response); + } else { + $enabled = $data["enabled"]; + $bot_token = $data["bot_token"]; + $chat_id = $data["chat_id"]; + + $query = "SELECT COUNT(*) FROM telegram_notifications"; + $result = $db->querySingle($query); + + if ($result === false) { + $response = [ + "success" => false, + "errorMessage" => translate('error_saving_notifications', $i18n) + ]; + echo json_encode($response); + } else { + if ($result == 0) { + $query = "INSERT INTO telegram_notifications (enabled, bot_token, chat_id) + VALUES (:enabled, :bot_token, :chat_id)"; + } else { + $query = "UPDATE telegram_notifications + SET enabled = :enabled, bot_token = :bot_token, chat_id = :chat_id"; + } + + $stmt = $db->prepare($query); + $stmt->bindValue(':enabled', $enabled, SQLITE3_INTEGER); + $stmt->bindValue(':bot_token', $bot_token, SQLITE3_TEXT); + $stmt->bindValue(':chat_id', $chat_id, SQLITE3_TEXT); + + if ($stmt->execute()) { + $response = [ + "success" => true, + "message" => translate('notifications_settings_saved', $i18n) + ]; + echo json_encode($response); + } else { + $response = [ + "success" => false, + "errorMessage" => translate('error_saving_notifications', $i18n) + ]; + echo json_encode($response); + } + } + } + } +?> \ No newline at end of file diff --git a/endpoints/notifications/savewebhooknotifications.php b/endpoints/notifications/savewebhooknotifications.php new file mode 100644 index 0000000..6bb41c5 --- /dev/null +++ b/endpoints/notifications/savewebhooknotifications.php @@ -0,0 +1,71 @@ + 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["webhook_url"]) || $data["webhook_url"] == "" || + !isset($data["payload"]) || $data["payload"] == "" + ) { + $response = [ + "success" => false, + "errorMessage" => translate('fill_mandatory_fields', $i18n) + ]; + echo json_encode($response); + } else { + $enabled = $data["enabled"]; + $url = $data["webhook_url"]; + $headers = $data["headers"]; + $payload = $data["payload"]; + + $query = "SELECT COUNT(*) FROM webhook_notifications"; + $result = $db->querySingle($query); + + if ($result === false) { + $response = [ + "success" => false, + "errorMessage" => translate('error_saving_notifications', $i18n) + ]; + echo json_encode($response); + } else { + if ($result == 0) { + $query = "INSERT INTO webhook_notifications (enabled, url, headers, payload) + VALUES (:enabled, :url, :headers, :payload)"; + } else { + $query = "UPDATE webhook_notifications + SET enabled = :enabled, url = :url, headers = :headers, payload = :payload"; + } + + $stmt = $db->prepare($query); + $stmt->bindValue(':enabled', $enabled, SQLITE3_INTEGER); + $stmt->bindValue(':url', $url, SQLITE3_TEXT); + $stmt->bindValue(':headers', $headers, SQLITE3_TEXT); + $stmt->bindValue(':payload', $payload, SQLITE3_TEXT); + + if ($stmt->execute()) { + $response = [ + "success" => true, + "message" => translate('notifications_settings_saved', $i18n) + ]; + echo json_encode($response); + } else { + $response = [ + "success" => false, + "errorMessage" => translate('error_saving_notifications', $i18n) + ]; + echo json_encode($response); + } + } + } + } +?> \ No newline at end of file diff --git a/endpoints/notifications/sendtestmail.php b/endpoints/notifications/testemailnotifications.php similarity index 85% rename from endpoints/notifications/sendtestmail.php rename to endpoints/notifications/testemailnotifications.php index 1596aca..5657619 100644 --- a/endpoints/notifications/sendtestmail.php +++ b/endpoints/notifications/testemailnotifications.php @@ -7,6 +7,13 @@ use PHPMailer\PHPMailer\Exception; 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); @@ -21,14 +28,13 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") { "success" => false, "errorMessage" => translate('fill_all_fields', $i18n) ]; - echo json_encode($response); + die(json_encode($response)); } else { $enxryption = "tls"; if (isset($data["encryption"])) { $encryption = $data["encryption"]; } - require '../../libs/PHPMailer/PHPMailer.php'; require '../../libs/PHPMailer/SMTP.php'; require '../../libs/PHPMailer/Exception.php'; @@ -66,13 +72,13 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") { "success" => true, "message" => translate('notification_sent_successfuly', $i18n) ]; - echo json_encode($response); + die(json_encode($response)); } else { $response = [ "success" => false, "errorMessage" => translate('email_error', $i18n) . $mail->ErrorInfo ]; - echo json_encode($response); + die(json_encode($response)); } } diff --git a/endpoints/notifications/testgotifynotifications.php b/endpoints/notifications/testgotifynotifications.php new file mode 100644 index 0000000..f1782cc --- /dev/null +++ b/endpoints/notifications/testgotifynotifications.php @@ -0,0 +1,71 @@ + 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["gotify_url"]) || $data["gotify_url"] == "" || + !isset($data["token"]) || $data["token"] == "" + ) { + $response = [ + "success" => false, + "errorMessage" => translate('fill_mandatory_fields', $i18n) + ]; + die(json_encode($response)); + } else { + // Set the message parameters + $title = translate('wallos_notification', $i18n); + $message = translate('test_notification', $i18n); + $priority = 5; + + $url = $data["gotify_url"]; + $token = $data["token"]; + + $ch = curl_init(); + + // Set the URL and other options + curl_setopt($ch, CURLOPT_URL, $url . "/message?token=" . $token); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([ + 'title' => $title, + 'message' => $message, + 'priority' => $priority, + ])); + 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) + ])); +} +?> \ No newline at end of file diff --git a/endpoints/notifications/testtelegramnotifications.php b/endpoints/notifications/testtelegramnotifications.php new file mode 100644 index 0000000..53634da --- /dev/null +++ b/endpoints/notifications/testtelegramnotifications.php @@ -0,0 +1,69 @@ + 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["bottoken"]) || $data["bottoken"] == "" || + !isset($data["chatid"]) || $data["chatid"] == "" + ) { + $response = [ + "success" => false, + "errorMessage" => translate('fill_mandatory_fields', $i18n) + ]; + echo json_encode($response); + } else { + // Set the message parameters + $title = translate('wallos_notification', $i18n); + $message = translate('test_notification', $i18n); + + $botToken = $data["bottoken"]; + $chatId = $data["chatid"]; + + $ch = curl_init(); + + // Set the URL and other options + curl_setopt($ch, CURLOPT_URL, "https://api.telegram.org/bot" . $botToken . "/sendMessage"); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([ + 'chat_id' => $chatId, + 'text' => $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) + ])); +} +?> \ No newline at end of file diff --git a/endpoints/notifications/testwebhooknotifications.php b/endpoints/notifications/testwebhooknotifications.php new file mode 100644 index 0000000..40afed4 --- /dev/null +++ b/endpoints/notifications/testwebhooknotifications.php @@ -0,0 +1,74 @@ + 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["requestmethod"]) || $data["requestmethod"] == "" || + !isset($data["url"]) || $data["url"] == "" || + !isset($data["payload"]) || $data["payload"] == "" + ) { + $response = [ + "success" => false, + "errorMessage" => translate('fill_mandatory_fields', $i18n) + ]; + die(json_encode($response)); + } else { + // Set the message parameters + $title = translate('wallos_notification', $i18n); + $message = translate('test_notification', $i18n); + + $requestmethod = $data["requestmethod"]; + $url = $data["url"]; + $payload = $data["payload"]; + $customheaders = json_decode($data["customheaders"], true); + + $ch = curl_init(); + + // Set the URL and other options + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $requestmethod); + curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); + if (!empty($customheaders)) { + curl_setopt($ch, CURLOPT_HTTPHEADER, $customheaders); + } + 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) + ])); +} + +?> \ No newline at end of file diff --git a/images/uploads/logos/wallos.png b/images/uploads/logos/wallos.png deleted file mode 100644 index 1885ae44f6c43a31ea7a8ef188507adc9cb7b59f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7273 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 "SMTP Passwort", "from_email" => "Absender E-Mail Adresse (optional)", "smtp_info" => "Das SMTP Passwort wird in Klartext übermittelt und gespeichert. Aus Sicherheitsgründen erstelle bitte einen gesonderten Account nur zu diesem Zweck.", + "telegram" => "Telegram", + "telegram_bot_token" => "Telegram Bot Token", + "telegram_chat_id" => "Telegram Chat ID", + "webhook" => "Webhook", + "webhook_url" => "Webhook URL", + "request_method" => "Request Methode", + "custom_headers" => "Benutzerdefinierte Kopfzeilen", + "webhook_payload" => "Webhook Payload", + "webhook_iterator_key" => "Ersetze {{subscriptions}} durch den Schlüsselnamen", + "variables_available" => "Verfügbare Variablen", + "gotify" => "Gotify", + "token" => "Token", "categories" => "Kategorien", "save_category" => "Kategorie speichern", "delete_category" => "Kategorie löschen", @@ -215,6 +227,7 @@ $i18n = [ "email_error" => "E-Mail konnte nicht gesendet werden", "notification_sent_successfuly" => "Benachrichtigung erfolgreich gesendet", "notifications_settings_saved" => "Benachrichtigungseinstellungen erfolgreich gespeichert.", + "notification_failed" => "Benachrichtigung fehlgeschlagen", // Payments "payment_in_use" => "Genutzte Zahlungsmethoden können nicht deaktiviert werden", "failed_update_payment" => "Zahlungsmethode in Datenbank konnte nicht aktualisiert werden", diff --git a/includes/i18n/el.php b/includes/i18n/el.php index 436ade2..b11931e 100644 --- a/includes/i18n/el.php +++ b/includes/i18n/el.php @@ -120,6 +120,18 @@ $i18n = [ "smtp_password" => "SMTP κωδικός", "from_email" => "Από (Προαιρετικό)", "smtp_info" => "Ο κωδικός πρόσβασης SMTP μεταδίδεται και αποθηκεύεται σε απλό κείμενο. Για λόγους ασφαλείας, παρακαλούμε δημιούργησε έναν λογαριασμό μόνο γι' αυτό το σκοπό.", + "telegram" => "Telegram", + "telegram_bot_token" => "Τηλεγραφήματα Bot Token", + "telegram_chat_id" => "Τηλεγραφήματα Chat ID", + "webhook" => "Webhook", + "webhook_url" => "Webhook URL", + "request_method" => "Μέθοδος αίτησης", + "custom_headers" => "Προσαρμοσμένες κεφαλίδες", + "webhook_payload" => "Webhook Payload", + "webhook_iterator_key" => "Αντικαταστήστε {{subscriptions}} με το όνομα του κλειδιού", + "variables_available" => "Διαθέσιμες μεταβλητές", + "gotify" => "Gotify", + "token" => "Token", "categories" => "Κατηγορίες", "save_category" => "Αποθήκευση κατηγορίας", "delete_category" => "Διαγραφή κατηγορίας", @@ -215,6 +227,7 @@ $i18n = [ "email_error" => "Σφάλμα αποστολής email", "notification_sent_successfuly" => "Η ειδοποίηση εστάλη επιτυχώς", "notifications_settings_saved" => "Οι ρυθμίσεις ειδοποίησης αποθηκεύτηκαν με επιτυχία.", + "notification_failed" => "Η ειδοποίηση απέτυχε", // Payments "payment_in_use" => "Δεν είναι εφικτό να απενεργοποιηθεί η χρησιμοποιούμενη μέθοδο πληρωμής", "failed_update_payment" => "Απέτυχε η ενημέρωση της μεθόδου πληρωμής στη βάση δεδομένων", diff --git a/includes/i18n/en.php b/includes/i18n/en.php index 6c90107..e659aaf 100644 --- a/includes/i18n/en.php +++ b/includes/i18n/en.php @@ -120,6 +120,18 @@ $i18n = [ "smtp_password" => "SMTP Password", "from_email" => "From email (Optional)", "smtp_info" => "SMTP Password is transmitted and stored in plaintext. For security, please create an account just for this.", + "telegram" => "Telegram", + "telegram_bot_token" => "Telegram Bot Token", + "telegram_chat_id" => "Telegram Chat ID", + "webhook" => "Webhook", + "webhook_url" => "Webhook URL", + "request_method" => "Request Method", + "custom_headers" => "Custom Headers", + "webhook_payload" => "Webhook Payload", + "webhook_iterator_key" => "Replace {{subscriptions}} with key name", + "variables_available" => "Variables available", + "gotify" => "Gotify", + "token" => "Token", "categories" => "Categories", "save_category" => "Save Category", "delete_category" => "Delete Category", @@ -215,6 +227,7 @@ $i18n = [ "email_error" => "Error sending email", "notification_sent_successfuly" => "Notification sent successfully", "notifications_settings_saved" => "Notification settings saved successfully.", + "notification_failed" => "Notification failed", // Payments "payment_in_use" => "Can't disable used payment method", "failed_update_payment" => "Failed to update payment method in the database", diff --git a/includes/i18n/es.php b/includes/i18n/es.php index 618bf69..dbe7760 100644 --- a/includes/i18n/es.php +++ b/includes/i18n/es.php @@ -120,6 +120,18 @@ $i18n = [ "smtp_password" => "Contraseña SMTP", "from_email" => "Correo electrónico de origen (Opcional)", "smtp_info" => "La contraseña SMTP se transmite y almacena en texto plano. Por seguridad, crea una cuenta solo para esto.", + "telegram" => "Telegram", + "telegram_bot_token" => "Token del Bot de Telegram", + "telegram_chat_id" => "ID del Chat de Telegram", + "webhook" => "Webhook", + "webhook_url" => "URL del Webhook", + "request_method" => "Método de Solicitud", + "custom_headers" => "Cabeceras Personalizadas", + "webhook_payload" => "Carga del Webhook", + "webhook_iterator_key" => "Sustituye {{subscriptions}} por el nombre de la clave", + "variables_available" => "Variables disponibles", + "gotify" => "Gotify", + "token" => "Token", "categories" => "Categorías", "save_category" => "Guardar Categoría", "delete_category" => "Eliminar Categoría", @@ -215,6 +227,7 @@ $i18n = [ "email_error" => "Error al enviar correo electrónico", "notification_sent_successfuly" => "Notificación enviada con éxito", "notifications_settings_saved" => "Configuración de notificaciones guardada con éxito.", + "notification_failed" => "Error al enviar la notificación", // Payments "payment_in_use" => "No se puede desactivar el método de pago utilizado", "failed_update_payment" => "Error al actualizar el método de pago en la base de datos", diff --git a/includes/i18n/fr.php b/includes/i18n/fr.php index ab5c00f..4c1ff38 100644 --- a/includes/i18n/fr.php +++ b/includes/i18n/fr.php @@ -120,6 +120,18 @@ $i18n = [ "smtp_password" => "Mot de passe SMTP", "from_email" => "De l'adresse courriel (facultatif)", "smtp_info" => "Le mot de passe SMTP est transmis et stocké en texte brut. Pour des raisons de sécurité, veuillez créer un compte uniquement à cette fin.", + "telegram" => "Telegram", + "telegram_bot_token" => "Jeton du bot Telegram", + "telegram_chat_id" => "ID de chat Telegram", + "webhook" => "Webhook", + "webhook_url" => "URL du webhook", + "request_method" => "Méthode de requête", + "custom_headers" => "En-têtes personnalisés", + "webhook_payload" => "Charge utile du webhook", + "webhook_iterator_key" => "Remplacer {{subscriptions}} par le nom de la clé", + "variables_available" => "Variables disponibles", + "gotify" => "Gotify", + "token" => "Jeton", "categories" => "Catégories", "save_category" => "Enregistrer la catégorie", "delete_category" => "Supprimer la catégorie", @@ -215,6 +227,7 @@ $i18n = [ "email_error" => "Erreur dlors de l'envoi de courriel", "notification_sent_successfuly" => "Notification envoyée avec succès", "notifications_settings_saved" => "Paramètres de notifications enregistrés avec succès.", + "notification_failed" => "Échec de la notification", // Paiements "payment_in_use" => "Impossible de désactiver la méthode de paiement utilisée", "failed_update_payment" => "Échec de la mise à jour de la méthode de paiement dans la base de données", diff --git a/includes/i18n/it.php b/includes/i18n/it.php index 8688c37..fd695a6 100644 --- a/includes/i18n/it.php +++ b/includes/i18n/it.php @@ -125,6 +125,18 @@ $i18n = [ 'smtp_password' => 'Password SMTP', 'from_email' => 'Da quale e-mail (Opzionale)', 'smtp_info' => 'La password SMTP viene memorizzata e trasmessa in chiaro. Per motivi di sicurezza, si prega di creare un account da utilizzare solo per questo.', + "telegram" => "Telegram", + "telegram_bot_token" => "Telegram Bot Token", + "telegram_chat_id" => "Telegram Chat ID", + "webhook" => "Webhook", + "webhook_url" => "Webhook URL", + "request_method" => "Metodo di richiesta", + "custom_headers" => "Intestazioni personalizzate", + "webhook_payload" => "Webhook Payload", + "webhook_iterator_key" => "Sostituisci {{subscriptions}} con il nome della chiave", + "variables_available" => "Variabili disponibili", + "gotify" => "Gotify", + "token" => "Token", 'categories' => 'Categorie', 'save_category' => 'Salva categoria', 'delete_category' => 'Elimina categoria', @@ -193,6 +205,57 @@ $i18n = [ // Category 'failed_add_category' => 'Impossibile aggiungere la categoria', 'failed_edit_category' => 'Impossibile modificare la categoria', + "category_in_use" => "La categoria è attualmente in uso da almeno un abbonamento", + "failed_remove_category" => "Impossibile rimuovere la categoria", + "category_saved" => "Categoria salvata", + "category_removed" => "Categoria rimossa", + "sort_order_saved" => "Ordine di visualizzazione salvato", + + // Currency + "currency_saved" => "Valuta salvata con successo", + "error_adding_currency" => "Errore nell'aggiunta della valuta", + "failed_to_store_currency" => "Impossibile salvare la valuta nel Database", + "currency_in_use" => "La valuta è attualmente in uso da almeno un abbonamento", + "currency_is_main" => "Impossibile rimuovere la valuta principale", + "failed_to_remove_currency" => "Impossibile rimuovere la valuta", + "failed_to_store_api_key" => "Impossibile salvare la chiave API", + "invalid_api_key" => "Chiave API non valida", + "api_key_saved" => "Chiave API salvata", + "currency_removed" => "Valuta rimossa", + + // Household + "failed_add_household" => "Impossibile aggiungere un membro del nucleo familiare", + "failed_edit_household" => "Impossibile modificare un membro del nucleo familiare", + "failed_remove_household" => "Impossibile rimuovere un membro del nucleo familiare", + "household_in_use" => "Il membro del nucleo familiare è attualmente in uso da almeno un abbonamento", + "member_saved" => "Membro salvato", + "member_removed" => "Membro rimosso", + + // Notifications + "error_saving_notifications" => "Errore nel salvataggio delle notifiche", + "wallos_notification" => "Notifica Wallos", + "test_notification" => "Questa è una notifica di prova", + "email_error" => "Errore nell'invio dell'e-mail", + "notification_sent_successfuly" => "Notifica inviata con successo", + "notifications_settings_saved" => "Impostazioni delle notifiche salvate", + "notification_failed" => "Invio della notifica fallito", + + // Payments + "payment_in_use" => "Questo metodo di pagamento è attualmente in uso da almeno un abbonamento", + "failed_update_payment" => "Aggiornamento del metodo di pagamento fallito", + "enabled" => "abilitato", + "disabled" => "disabilitato", + + // Subscription + "error_fetching_image" => "Errore nel recupero dell'immagine", + "subscription_updated_successfuly" => "Abbonamento aggiornato con successo", + "subscription_added_successfuly" => "Abbonamento aggiunto con successo", + "error_deleting_subscription" => "Errore nell'eliminazione dell'abbonamento", + "invalid_request_method" => "Metodo di richiesta non valido", + + // User + "error_updating_user_data" => "Errore nell'aggiornamento dei dati utente", + "user_details_saved" => "Dettagli utente salvati", ]; ?> diff --git a/includes/i18n/jp.php b/includes/i18n/jp.php index fe677fd..b704435 100644 --- a/includes/i18n/jp.php +++ b/includes/i18n/jp.php @@ -120,6 +120,18 @@ $i18n = [ "smtp_password" => "SMTPパスワード", "from_email" => "送信元アドレス (オプション)", "smtp_info" => "SMTPパスワードは平文で送信および保存されます。セキュリティのため専用のアカウントを作成してください。", + "telegram" => "Telegram", + "telegram_bot_token" => "Telegramボットトークン", + "telegram_chat_id" => "TelegramチャットID", + "webhook" => "Webhook", + "webhook_url" => "Webhook URL", + "request_method" => "リクエストメソッド", + "custom_headers" => "カスタムヘッダー", + "webhook_payload" => "Webhookペイロード", + "webhook_iterator_keu" => "{{subscriptions}}をキー名に置き換える」", + "variables_available" => "利用可能な変数", + "gotify" => "Gotify", + "token" => "トークン", "categories" => "カテゴリ", "save_category" => "カテゴリを保存", "delete_category" => "カテゴリを削除", @@ -215,6 +227,7 @@ $i18n = [ "email_error" => "電子メールの送信エラー", "notification_sent_successfuly" => "通知の送信に成功しました", "notifications_settings_saved" => "通知設定の保存に成功", + "notification_failed" => "通知の送信に失敗", // Payments "payment_in_use" => "使用中の支払い方法は削除できません", "failed_update_payment" => "データーベースの支払い方法の更新に失敗しました", diff --git a/includes/i18n/pl.php b/includes/i18n/pl.php index 1b58a42..833eec2 100644 --- a/includes/i18n/pl.php +++ b/includes/i18n/pl.php @@ -120,6 +120,18 @@ $i18n = [ "smtp_password" => "Hasło SMTP", "from_email" => "Z adresu e-mail (opcjonalnie)", "smtp_info" => "Hasło SMTP jest przesyłane i przechowywane w postaci zwykłego tekstu. Ze względów bezpieczeństwa utwórz konto tylko w tym celu.", + "telegram" => "Telegram", + "telegram_bot_token" => "Token bota", + "telegram_chat_id" => "ID czatu", + "webhook" => "Webhook", + "webhook_url" => "URL webhooka", + "request_method" => "Metoda żądania", + "custom_headers" => "Niestandardowe nagłówki", + "webhook_payload" => "Dane webhooka", + "webhook_iterator_key" => "Zastąp {{subscriptions}} nazwą klucza", + "variables_available" => "Dostępne zmienne", + "gotify" => "Gotify", + "token" => "Token", "categories" => "Kategorie", "save_category" => "Zapisz kategorię", "delete_category" => "Usuń kategorię", @@ -213,6 +225,7 @@ $i18n = [ "wallos_notification" => "Powiadomienie Wallos", "test_notification" => "To jest powiadomienie testowe. Jeśli to widzisz, konfiguracja jest prawidłowa.", "email_error" => "Błąd podczas wysyłania wiadomości e-mail", + "notification_failed" => "Powiadomienie nie powiodło się", "notification_sent_successfuly" => "Powiadomienie wysłane pomyślnie", "notifications_settings_saved" => "Ustawienia powiadomień zostały zapisane.", // Payments diff --git a/includes/i18n/pt.php b/includes/i18n/pt.php index eb119fb..0dfeb18 100644 --- a/includes/i18n/pt.php +++ b/includes/i18n/pt.php @@ -120,6 +120,18 @@ $i18n = [ "smtp_password" => "Password SMTP", "from_email" => "Email de envio (Opcional)", "smtp_info" => "A Password é armazenada e transmitida em texto. Por segurança, crie uma conta só para esta finalidade.", + "telegram" => "Telegram", + "telegram_bot_token" => "Token do Bot Telegram", + "telegram_chat_id" => "ID do Chat Telegram", + "webhook" => "Webhook", + "webhook_url" => "URL do Webhook", + "request_method" => "Método de Pedido", + "custom_headers" => "Cabeçalhos Personalizados", + "webhook_payload" => "Payload do Webhook", + "webhook_iterator_key" => "Substituir {{subscriptions}} pelo nome da chave", + "variables_available" => "Variáveis Disponíveis", + "gotify" => "Gotify", + "token" => "Token", "categories" => "Categorias", "save_category" => "Guardar Categoria", "delete_category" => "Apagar Categoria", @@ -215,6 +227,7 @@ $i18n = [ "email_error" => "Erro ao enviar email", "notification_sent_successfuly" => "Notificação enviada com sucesso", "notifications_settings_saved" => "Configuração de notificações guardada.", + "notification_failed" => "Erro ao enviar notificação", // Payments "payment_in_use" => "Não pode desactivar método de pagamento em uso", "failed_update_payment" => "Erro ao actualizar método de pagamento na base de dados", diff --git a/includes/i18n/pt_br.php b/includes/i18n/pt_br.php index 0e0fd30..4aa5201 100644 --- a/includes/i18n/pt_br.php +++ b/includes/i18n/pt_br.php @@ -118,6 +118,18 @@ $i18n = [ "smtp_password" => "Senha SMTP", "from_email" => "Email de envio (Opcional)", "smtp_info" => "A senha do SMTP é transmitida em texto puro. Por segurança, crie uma conta só para esta finalidade.", + "telegram" => "Telegram", + "telegram_bot_token" => "Token do Bot", + "telegram_chat_id" => "Chat ID", + "webhook" => "Webhook", + "webhook_url" => "URL do Webhook", + "request_method" => "Método de requisição", + "custom_headers" => "Cabeçalhos personalizados", + "webhook_payload" => "Payload do Webhook", + "webhook_iterator_key" => "Substituir {{subscriptions}} pelo nome da chave", + "variables_available" => "Variáveis disponíveis", + "gotify" => "Gotify", + "token" => "Token", "categories" => "Categorias", "save_category" => "Salvar categoria", "delete_category" => "Excluir categoria", @@ -213,6 +225,7 @@ $i18n = [ "email_error" => "Erro ao enviar email", "notification_sent_successfuly" => "Notificação enviada com sucesso", "notifications_settings_saved" => "Configurações de notificação salvas com sucesso", + "notification_failed" => "Falha ao enviar notificação", // Payments "payment_in_use" => "Não é possível desativar o método de pagamento", "failed_update_payment" => "Erro ao atualizar o método de pagamento no banco de dados.", diff --git a/includes/i18n/sr.php b/includes/i18n/sr.php index ba82a40..886befd 100644 --- a/includes/i18n/sr.php +++ b/includes/i18n/sr.php @@ -120,6 +120,18 @@ $i18n = [ "smtp_password" => "SMTP лозинка", "from_email" => "Од е-поште (Опционо)", "smtp_info" => "SMTP лозинка се преноси и чува у обичном тексту. Из сигурносних разлога, молимо вас да направите налог само за ово.", + "telegram" => "Телеграм", + "telegram_bot_token" => "Телеграм бот токен", + "telegram_chat_id" => "Телеграм чет ID", + "webhook" => "Вебхук", + "webhook_url" => "Вебхук URL", + "request_method" => "Метод захтева", + "custom_headers" => "Прилагођени заглавља", + "webhook_payload" => "Вебхук Пајлоад", + "webhook_iterator_key" => "{{subscriptions}} замени кључним итератором", + "variables_available" => "Доступне променљиве", + "gotify" => "Готифи", + "token" => "Токен", "categories" => "Категорије", "save_category" => "Сачувај категорију", "delete_category" => "Избриши категорију", @@ -215,6 +227,7 @@ $i18n = [ "email_error" => "Грешка при слању е-поште", "notification_sent_successfuly" => "Обавештење успешно послато", "notifications_settings_saved" => "Подешавања обавештења успешно сачувана.", + "notification_failed" => "Обавештење није послато", // Плаћања "payment_in_use" => "Не може се онемогућити коришћени начин плаћања", "failed_update_payment" => "Ажурирање начина плаћања у бази података није успело", diff --git a/includes/i18n/sr_lat.php b/includes/i18n/sr_lat.php index 8fb2edb..b0d0a5d 100644 --- a/includes/i18n/sr_lat.php +++ b/includes/i18n/sr_lat.php @@ -120,6 +120,18 @@ $i18n = [ "smtp_password" => "SMTP lozinka", "from_email" => "Od e-pošte (Opciono)", "smtp_info" => "SMTP lozinka se prenosi i čuva u običnom tekstu. Iz sigurnosnih razloga, molimo vas da napravite nalog samo za ovo.", + "telegram" => "Telegram", + "telegram_bot_token" => "Telegram bot token", + "telegram_chat_id" => "Telegram chat ID", + "webhook" => "Webhook", + "webhook_url" => "Webhook URL", + "request_method" => "Metod zahteva", + "custom_headers" => "Prilagođeni zaglavlja", + "webhook_payload" => "Webhook payload", + "webhook_iterator_key" => "Zameni {{subscriptions}} sa ključem", + "variables_available" => "Dostupne promenljive", + "gotify" => "Gotify", + "token" => "Token", "categories" => "Kategorije", "save_category" => "Sačuvaj kategoriju", "delete_category" => "Izbriši kategoriju", @@ -215,6 +227,7 @@ $i18n = [ "email_error" => "Greška pri slanju e-pošte", "notification_sent_successfuly" => "Obaveštenje uspešno poslato", "notifications_settings_saved" => "Podešavanja obaveštenja uspešno sačuvana.", + "notification_failed" => "Obaveštenje nije poslato", // Plaćanja "payment_in_use" => "Nije moguće onemogućiti korišćeni način plaćanja", "failed_update_payment" => "Nije uspelo ažuriranje načina plaćanja u bazi podataka", diff --git a/includes/i18n/tr.php b/includes/i18n/tr.php index a2897ef..9930dc2 100644 --- a/includes/i18n/tr.php +++ b/includes/i18n/tr.php @@ -120,6 +120,18 @@ $i18n = [ "smtp_password" => "SMTP Şifresi", "from_email" => "Gönderen e-posta (İsteğe bağlı)", "smtp_info" => "SMTP Şifresi düz metin olarak iletilir ve saklanır. Güvenlik için, lütfen bunun için özel bir hesap oluşturun.", + "telegram" => "Telegram", + "telegram_bot_token" => "Telegram Bot Token", + "telegram_chat_id" => "Telegram Chat ID", + "webhook" => "Webhook", + "webhook_url" => "Webhook URL", + "request_method" => "İstek Metodu", + "custom_headers" => "Özel Başlıklar", + "webhook_payload" => "Webhook Payload", + "webhook_iterator_key" => "{{subscriptions}}'yi anahtar olarak değiştir", + "variables_available" => "Kullanılabilir Değişkenler", + "gotify" => "Gotify", + "token" => "Token", "categories" => "Kategoriler", "save_category" => "Kategoriyi Kaydet", "delete_category" => "Kategoriyi Sil", @@ -215,6 +227,7 @@ $i18n = [ "email_error" => "E-posta gönderilirken hata oluştu", "notification_sent_successfuly" => "Bildirim başarıyla gönderildi", "notifications_settings_saved" => "Bildirim ayarları başarıyla kaydedildi.", + "notification_failed" => "Bildirim gönderilemedi", // Payments "payment_in_use" => "Kullanımda olan ödeme yöntemi devre dışı bırakılamaz", "failed_update_payment" => "Ödeme yöntemi veritabanında güncellenemedi", diff --git a/includes/i18n/zh_cn.php b/includes/i18n/zh_cn.php index 37ed3e4..caba1f8 100644 --- a/includes/i18n/zh_cn.php +++ b/includes/i18n/zh_cn.php @@ -127,6 +127,18 @@ $i18n = [ "smtp_password" => "SMTP 密码", "from_email" => "发件人邮箱(可选)", "smtp_info" => "SMTP 密码以明文传输和存储。为安全起见,建议专门为 Wallos 创建一个账户。", + "telegram" => "Telegram", + "telegram_bot_token" => "Telegram 机器人令牌", + "telegram_chat_id" => "Telegram 聊天 ID", + "webhook" => "Webhook", + "webhook_url" => "Webhook URL", + "request_method" => "请求方法", + "custom_headers" => "自定义标头", + "webhook_payload" => "Webhook 负载", + "webhook_iterator_key" => "替换 {{subscriptions}} 为键名", + "variables_available" => "可用变量", + "gotify" => "Gotify", + "token" => "令牌", "categories" => "分类", "save_category" => "保存分类", "delete_category" => "删除分类", @@ -226,6 +238,7 @@ $i18n = [ "wallos_notification" => "Wallos 通知", "test_notification" => "这是一条测试通知。如果您看到此消息,说明 Wallos 通知邮件配置正确。", "email_error" => "发送电子邮件时出错", + "notification_failed" => "通知发送失败", "notification_sent_successfuly" => "通知已成功发送", "notifications_settings_saved" => "通知设置已成功保存。", diff --git a/includes/i18n/zh_tw.php b/includes/i18n/zh_tw.php index 70224c1..292a049 100644 --- a/includes/i18n/zh_tw.php +++ b/includes/i18n/zh_tw.php @@ -120,6 +120,18 @@ $i18n = [ "smtp_password" => "SMTP 密碼", "from_email" => "寄件人信箱(可選)", "smtp_info" => "SMTP 密碼將以明文傳輸和儲存。為了安全起見,建議專門為 Wallos 建立一個帳戶。", + "telegram" => "Telegram", + "telegram_bot_token" => "Telegram 機器人令牌", + "telegram_chat_id" => "Telegram 聊天 ID", + "webhook" => "Webhook", + "webhook_url" => "Webhook URL", + "request_method" => "請求方法", + "custom_headers" => "自訂標頭", + "webhook_payload" => "Webhook 載荷", + "webhook_iterator_key" => "替換 {{subscriptions}} 為鍵名", + "variables_available" => "可用變數", + "gotify" => "Gotify", + "token" => "令牌", "categories" => "分類", "save_category" => "儲存分類", "delete_category" => "刪除分類", @@ -215,6 +227,7 @@ $i18n = [ "email_error" => "傳送到電子信箱時發生錯誤", "notification_sent_successfuly" => "通知已成功傳送", "notifications_settings_saved" => "通知設定已成功儲存。", + "notification_failed" => "通知傳送失敗", // Payments "payment_in_use" => "無法停用正在使用的付款方式", "failed_update_payment" => "更新資料庫中的付款方式失敗", diff --git a/includes/version.php b/includes/version.php index 44ad6d2..dc8059f 100644 --- a/includes/version.php +++ b/includes/version.php @@ -1,3 +1,3 @@ diff --git a/index.php b/index.php index 631de00..15311f8 100644 --- a/index.php +++ b/index.php @@ -26,16 +26,6 @@ } } - $notificationsEnabled = false; - $query = "SELECT enabled FROM notifications WHERE id = 1"; - $result = $db->query($query); - if ($result) { - $row = $result->fetchArray(SQLITE3_ASSOC); - if ($row) { - $notificationsEnabled = $row['enabled']; - } - } - $headerClass = count($subscriptions) > 0 ? "main-actions" : "main-actions hidden"; $defaultLogo = $theme == "light" ? "images/siteicons/" . $colorTheme . "/wallos.png" : "images/siteicons/" . $colorTheme . "/walloswhite.png"; ?> @@ -285,16 +275,10 @@ -
-
diff --git a/migrations/000016.php b/migrations/000016.php new file mode 100644 index 0000000..b333136 --- /dev/null +++ b/migrations/000016.php @@ -0,0 +1,64 @@ +exec('CREATE TABLE IF NOT EXISTS telegram_notifications ( + enabled BOOLEAN DEFAULT 0, + bot_token TEXT DEFAULT "", + chat_id TEXT DEFAULT "" +)'); + +$db->exec('CREATE TABLE IF NOT EXISTS webhook_notifications ( + enabled BOOLEAN DEFAULT 0, + headers TEXT DEFAULT "", + url TEXT DEFAULT "", + request_method TEXT DEFAULT "POST", + payload TEXT DEFAULT "", + iterator TEXT DEFAULT "" +)'); + +$db->exec('CREATE TABLE IF NOT EXISTS gotify_notifications ( + enabled BOOLEAN DEFAULT 0, + url TEXT DEFAULT "", + token TEXT DEFAULT "" +)'); + +$db->exec('CREATE TABLE IF NOT EXISTS email_notifications ( + enabled BOOLEAN DEFAULT 0, + smtp_address TEXT DEFAULT "", + smtp_port INTEGER DEFAULT 587, + smtp_username TEXT DEFAULT "", + smtp_password TEXT DEFAULT "", + from_email TEXT DEFAULT "", + encryption TEXT DEFAULT "tls" +)'); + +$db->exec('CREATE TABLE IF NOT EXISTS notification_settings ( + days INTEGER DEFAULT 0 +)'); + +// Check if old email notifications table has data and migrate it +$result = $db->query('SELECT COUNT(*) as count FROM notifications'); +$row = $result->fetchArray(SQLITE3_ASSOC); + +if ($row['count'] > 0) { + // Copy data from notifications to email_notifications + $db->exec('INSERT INTO email_notifications (enabled, smtp_address, smtp_port, smtp_username, smtp_password, from_email, encryption) + SELECT enabled, smtp_address, smtp_port, smtp_username, smtp_password, from_email, encryption FROM notifications'); + + // Copy data from notifications to notification_settings + $db->exec('INSERT INTO notification_settings (days) + SELECT days FROM notifications'); + + if ($db->changes() > 0) { + $db->exec('DROP TABLE IF EXISTS notifications'); + } +} else { + $db->exec('DROP TABLE IF EXISTS notifications'); +} + +?> \ No newline at end of file diff --git a/scripts/notifications.js b/scripts/notifications.js new file mode 100644 index 0000000..4502edc --- /dev/null +++ b/scripts/notifications.js @@ -0,0 +1,212 @@ +function openNotificationsSettings(type) { + // Get all .account-notification-section-settings elements + var sections = document.querySelectorAll('.account-notification-section-settings'); + var targetSection = document.querySelector(`.account-notification-section-settings[data-type="${type}"]`); + + // Remove the is-open class from all elements + sections.forEach(function(section) { + if (section !== targetSection) { + section.classList.remove('is-open'); + } + }); + + // Add the is-open class to the element with data-type=type + + if (targetSection && !targetSection.classList.contains('is-open')) { + targetSection.classList.add('is-open'); + } else { + targetSection.classList.remove('is-open'); + } +} + +function makeFetchCall(url, data, button) { + return fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + }) + .then(response => response.json()) + .then(data => { + if (data.success) { + showSuccessMessage(data.message); + } else { + showErrorMessage(data.message); + } + button.disabled = false; + }) + .catch((error) => { + showErrorMessage(error); + button.disabled = false; + }); + +} + +function saveNotifications() { + const button = document.getElementById("saveNotifications"); + button.disabled = true; + const days = document.querySelector('#days').value; + + const url = 'endpoints/notifications/savenotificationsettings.php'; + const data = { days: days }; + + makeFetchCall(url, data, button); +} + +function saveNotificationsEmailButton() { + const button = document.getElementById("saveNotificationsEmail"); + button.disabled = true; + + const enabled = document.getElementById("emailenabled").checked ? 1 : 0; + const smtpAddress = document.getElementById("smtpaddress").value; + const smtpPort = document.getElementById("smtpport").value; + const encryption = document.querySelector('input[name="encryption"]:checked').value; + const smtpUsername = document.getElementById("smtpusername").value; + const smtpPassword = document.getElementById("smtppassword").value; + const fromEmail = document.getElementById("fromemail").value; + + const data = { + enabled: enabled, + smtpaddress: smtpAddress, + smtpport: smtpPort, + encryption: encryption, + smtpusername: smtpUsername, + smtppassword: smtpPassword, + fromemail: fromEmail + }; + + makeFetchCall('endpoints/notifications/saveemailnotifications.php', data, button); +} + +function testNotificationEmailButton() { + const button = document.getElementById("testNotificationsEmail"); + button.disabled = true; + + const smtpAddress = document.getElementById("smtpaddress").value; + const smtpPort = document.getElementById("smtpport").value; + const encryption = document.querySelector('input[name="encryption"]:checked').value; + const smtpUsername = document.getElementById("smtpusername").value; + const smtpPassword = document.getElementById("smtppassword").value; + const fromEmail = document.getElementById("fromemail").value; + + const data = { + smtpaddress: smtpAddress, + smtpport: smtpPort, + encryption: encryption, + smtpusername: smtpUsername, + smtppassword: smtpPassword, + fromemail: fromEmail + }; + + makeFetchCall('endpoints/notifications/testemailnotifications.php', data, button); +} + +function saveNotificationsWebhookButton() { + const button = document.getElementById("saveNotificationsWebhook"); + button.disabled = true; + + const enabled = document.getElementById("webhookenabled").checked ? 1 : 0; + const webhook_url = document.getElementById("webhookurl").value; + const headers = document.getElementById("webhookcustomheaders").value; + const payload = document.getElementById("webhookpayload").value; + + const data = { + enabled: enabled, + webhook_url: webhook_url, + headers: headers, + payload: payload + }; + + makeFetchCall('endpoints/notifications/savewebhooknotifications.php', data, button); +} + +function testNotificationsWebhookButton() { + const button = document.getElementById("testNotificationsWebhook"); + button.disabled = true; + + const enabled = document.getElementById("webhookenabled").checked ? 1 : 0; + const requestmethod = document.getElementById("webhookrequestmethod").value; + const url = document.getElementById("webhookurl").value; + const customheaders = document.getElementById("webhookcustomheaders").value; + const payload = document.getElementById("webhookpayload").value; + + const data = { + enabled: enabled, + requestmethod: requestmethod, + url: url, + customheaders: customheaders, + payload: payload + }; + + makeFetchCall('endpoints/notifications/testwebhooknotifications.php', data, button); +} + +function saveNotificationsTelegramButton() { + const button = document.getElementById("saveNotificationsTelegram"); + button.disabled = true; + + const enabled = document.getElementById("telegramenabled").checked ? 1 : 0; + const chat_id = document.getElementById("telegramchatid").value; + const bot_token = document.getElementById("telegrambottoken").value; + + const data = { + enabled: enabled, + chat_id: chat_id, + bot_token: bot_token + }; + + makeFetchCall('endpoints/notifications/savetelegramnotifications.php', data, button); +} + +function testNotificationsTelegramButton() { + const button = document.getElementById("testNotificationsTelegram"); + button.disabled = true; + + const enabled = document.getElementById("telegramenabled").checked ? 1 : 0; + const bottoken = document.getElementById("telegrambottoken").value; + const chatid = document.getElementById("telegramchatid").value; + + const data = { + enabled: enabled, + bottoken: bottoken, + chatid: chatid + }; + + makeFetchCall('endpoints/notifications/testtelegramnotifications.php', data, button); +} + +function saveNotificationsGotifyButton() { + const button = document.getElementById("saveNotificationsGotify"); + button.disabled = true; + + const enabled = document.getElementById("gotifyenabled").checked ? 1 : 0; + const gotify_url = document.getElementById("gotifyurl").value; + const token = document.getElementById("gotifytoken").value; + + const data = { + enabled: enabled, + gotify_url: gotify_url, + token: token + }; + + makeFetchCall('endpoints/notifications/savegotifynotifications.php', data, button); +} + +function testNotificationsGotifyButton() { + const button = document.getElementById("testNotificationsGotify"); + button.disabled = true; + + const enabled = document.getElementById("gotifyenabled").checked ? 1 : 0; + const gotify_url = document.getElementById("gotifyurl").value; + const token = document.getElementById("gotifytoken").value; + + const data = { + enabled: enabled, + gotify_url: gotify_url, + token: token + }; + + makeFetchCall('endpoints/notifications/testgotifynotifications.php', data, button); +} + diff --git a/scripts/settings.js b/scripts/settings.js index 9b3901c..6564631 100644 --- a/scripts/settings.js +++ b/scripts/settings.js @@ -842,94 +842,6 @@ function addFixerKeyButton() { }); } -function saveNotificationsButton() { - const button = document.getElementById("saveNotifications"); - button.disabled = true; - - const enabled = document.getElementById("notifications").checked ? 1 : 0; - const days = document.getElementById("days").value; - const smtpAddress = document.getElementById("smtpaddress").value; - const smtpPort = document.getElementById("smtpport").value; - const encryption = document.querySelector('input[name="encryption"]:checked').value; - const smtpUsername = document.getElementById("smtpusername").value; - const smtpPassword = document.getElementById("smtppassword").value; - const fromEmail = document.getElementById("fromemail").value; - - const data = { - enabled: enabled, - days: days, - smtpaddress: smtpAddress, - smtpport: smtpPort, - encryption: encryption, - smtpusername: smtpUsername, - smtppassword: smtpPassword, - fromemail: fromEmail - }; - - fetch('endpoints/notifications/save.php', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(data) - }) - .then(response => response.json()) - .then(data => { - if (data.success) { - showSuccessMessage(data.message); - } else { - showErrorMessage(data.errorMessage); - } - button.disabled = false; - }) - .catch(error => { - showErrorMessage(translate('error_saving_notification_data')); - button.disabled = false; - }); -} - -function testNotificationButton() { - const button = document.getElementById("testNotifications"); - button.disabled = true; - - const smtpAddress = document.getElementById("smtpaddress").value; - const smtpPort = document.getElementById("smtpport").value; - const encryption = document.querySelector('input[name="encryption"]:checked').value; - const smtpUsername = document.getElementById("smtpusername").value; - const smtpPassword = document.getElementById("smtppassword").value; - const fromEmail = document.getElementById("fromemail").value; - - const data = { - smtpaddress: smtpAddress, - smtpport: smtpPort, - encryption: encryption, - smtpusername: smtpUsername, - smtppassword: smtpPassword, - fromemail: fromEmail - }; - - fetch('endpoints/notifications/sendtestmail.php', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(data) - }) - .then(response => response.json()) - .then(data => { - if (data.success) { - showSuccessMessage(data.message); - } else { - showErrorMessage(data.errorMessage); - } - button.disabled = false; - }) - .catch(error => { - showErrorMessage(translate('error_sending_notification')); - button.disabled = false; - }); -} - function switchTheme() { const darkThemeCss = document.querySelector("#dark-theme"); darkThemeCss.disabled = !darkThemeCss.disabled; diff --git a/service-worker.js b/service-worker.js index 9d32d57..d67dd7c 100644 --- a/service-worker.js +++ b/service-worker.js @@ -23,6 +23,7 @@ self.addEventListener('install', function(event) { 'scripts/dashboard.js', 'scripts/stats.js', 'scripts/settings.js', + 'scripts/notifications.js', 'scripts/registration.js', 'scripts/i18n/en.js', 'scripts/i18n/de.js', diff --git a/settings.php b/settings.php index 1a69eb8..4b593bb 100644 --- a/settings.php +++ b/settings.php @@ -176,7 +176,8 @@ query($sql); $rowCount = 0; @@ -186,14 +187,107 @@ } if ($rowCount == 0) { - $notifications['enabled'] = false; $notifications['days'] = 1; - $notifications['smtp_address'] = ""; - $notifications['smtp_port'] = ""; - $notifications['smtp_username'] = ""; - $notifications['smtp_password'] = ""; - $notifications['from_email'] = ""; - $notifications['encryption'] = "tls"; + } + + // Email notifications + $sql = "SELECT * FROM email_notifications LIMIT 1"; + $result = $db->query($sql); + + $rowCount = 0; + while ($row = $result->fetchArray(SQLITE3_ASSOC)) { + $notificationsEmail['enabled'] = $row['enabled']; + $notificationsEmail['smtp_address'] = $row['smtp_address']; + $notificationsEmail['smtp_port'] = $row['smtp_port']; + $notificationsEmail['encryption'] = $row['encryption']; + $notificationsEmail['smtp_username'] = $row['smtp_username']; + $notificationsEmail['smtp_password'] = $row['smtp_password']; + $notificationsEmail['from_email'] = $row['from_email']; + $rowCount++; + } + + if ($rowCount == 0) { + $notificationsEmail['enabled'] = 0; + $notificationsEmail['smtp_address'] = ""; + $notificationsEmail['smtp_port'] = 587; + $notificationsEmail['encryption'] = "tls"; + $notificationsEmail['smtp_username'] = ""; + $notificationsEmail['smtp_password'] = ""; + $notificationsEmail['from_email'] = ""; + } + + // Telegram notifications + $sql = "SELECT * FROM telegram_notifications LIMIT 1"; + $result = $db->query($sql); + + $rowCount = 0; + while ($row = $result->fetchArray(SQLITE3_ASSOC)) { + $notificationsTelegram['enabled'] = $row['enabled']; + $notificationsTelegram['bot_token'] = $row['bot_token']; + $notificationsTelegram['chat_id'] = $row['chat_id']; + $rowCount++; + } + + if ($rowCount == 0) { + $notificationsTelegram['enabled'] = 0; + $notificationsTelegram['bot_token'] = ""; + $notificationsTelegram['chat_id'] = ""; + } + + // Webhook notifications + $sql = "SELECT * FROM webhook_notifications LIMIT 1"; + $result = $db->query($sql); + + $rowCount = 0; + while ($row = $result->fetchArray(SQLITE3_ASSOC)) { + $notificationsWebhook['enabled'] = $row['enabled']; + $notificationsWebhook['url'] = $row['url']; + $notificationsWebhook['request_method'] = $row['request_method']; + $notificationsWebhook['headers'] = $row['headers']; + $notificationsWebhook['payload'] = $row['payload']; + $notificationsWebhook['iterator'] = $row['iterator']; + $rowCount++; + } + + if ($rowCount == 0) { + $notificationsWebhook['enabled'] = 0; + $notificationsWebhook['url'] = ""; + $notificationsWebhook['request_method'] = "POST"; + $notificationsWebhook['headers'] = ""; + $notificationsWebhook['iterator'] = ""; + $notificationsWebhook['payload'] = ' +{ + "days_until": "{{days_until}}", + "{{subscriptions}}": [ + { + "name": "{{subscription_name}}", + "price": "{{subscription_price}}", + "currency": "{{subscription_currency}}", + "category": "{{subscription_category}}", + "date": "{{subscription_date}}", + "payer": "{{subscription_payer}}" + } + ] + +}'; + } + + // Gotify notifications + $sql = "SELECT * FROM gotify_notifications LIMIT 1"; + $result = $db->query($sql); + + $rowCount = 0; + while ($row = $result->fetchArray(SQLITE3_ASSOC)) { + $notificationsGotify['enabled'] = $row['enabled']; + $notificationsGotify['url'] = $row['url']; + $notificationsGotify['token'] = $row['token']; + $rowCount++; + } + + if ($rowCount == 0) { + $notificationsGotify['enabled'] = 0; + $notificationsGotify['url'] = ""; + $notificationsGotify['token'] = ""; } ?> @@ -203,54 +297,160 @@

@@ -702,6 +902,7 @@ + div:first-of-type { + margin-top: 20px; +} + +.account-notification-section-settings > div:last-of-type { + margin-bottom: 20px; +} + .account-notifications .buttons { gap: 15px; } @@ -965,6 +1008,21 @@ input[type="text"]:disabled { cursor: not-allowed; } +textarea { + font-size: 16px; + background-color: #FFFFFF; + border: 1px solid #ccc; + border-radius: 8px; + padding: 5px 14px; + color: #202020; + width: 100%; + height: 245px; +} + +textarea.thin { + height: 80px; +} + @media (max-width: 768px) { input[type="checkbox"] { width: 20px; @@ -1046,6 +1104,9 @@ input[type="text"]:disabled { padding-bottom: 0px; } +.capitalize { + text-transform: capitalize; +} .error { display: block;