mirror of
https://github.com/ellite/Wallos.git
synced 2025-12-23 23:18:07 -05:00
feat: make container shutdown instant & graceful
feat: make container shutdown instant & graceful (#916) feat: add pushplus notification service (#911) feat: option to delete ai recommendations fix: parsing ai recommendations from gemini (#909)
This commit is contained in:
52
endpoints/ai/delete_recommendation.php
Normal file
52
endpoints/ai/delete_recommendation.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
require_once '../../includes/connect_endpoint.php';
|
||||
|
||||
if (isset($_SESSION['loggedin']) && $_SESSION['loggedin'] === true) {
|
||||
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
$input = file_get_contents('php://input');
|
||||
$data = json_decode($input, true);
|
||||
|
||||
$recommendationId = isset($data['id']) ? (int) $data['id'] : 0;
|
||||
|
||||
if ($recommendationId <= 0) {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"message" => translate('error', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Delete the recommendation for the user
|
||||
$stmt = $db->prepare("DELETE FROM ai_recommendations WHERE id = ? AND user_id = ?");
|
||||
$stmt->bindValue(1, $recommendationId, SQLITE3_INTEGER);
|
||||
$stmt->bindValue(2, $userId, SQLITE3_INTEGER);
|
||||
$result = $stmt->execute();
|
||||
|
||||
if ($db->changes() > 0) {
|
||||
$response = [
|
||||
"success" => true,
|
||||
"message" => translate('success', $i18n)
|
||||
];
|
||||
} else {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"message" => translate('error', $i18n)
|
||||
];
|
||||
}
|
||||
|
||||
echo json_encode($response);
|
||||
} else {
|
||||
http_response_code(405);
|
||||
echo json_encode([
|
||||
"success" => false,
|
||||
"message" => translate('invalid_request_method', $i18n)
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"message" => translate('session_expired', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
}
|
||||
@@ -516,7 +516,7 @@ while ($userToNotify = $usersToNotify->fetchArray(SQLITE3_ASSOC)) {
|
||||
$result = $stmt->execute();
|
||||
$user = $result->fetchArray(SQLITE3_ASSOC);
|
||||
|
||||
// 构建消息内容
|
||||
// Build Message Content
|
||||
$messageContent = "";
|
||||
if ($user['name']) {
|
||||
$messageContent = $user['name'] . ", the following subscriptions are up for renewal:\n";
|
||||
@@ -529,7 +529,7 @@ while ($userToNotify = $usersToNotify->fetchArray(SQLITE3_ASSOC)) {
|
||||
$messageContent .= $subscription['name'] . " for " . $subscription['formatted_price'] . " (" . $dayText . ")\n";
|
||||
}
|
||||
|
||||
// 准备 PushPlus 数据
|
||||
// Prepare PushPlus Data
|
||||
$data = array(
|
||||
'token' => $pushplus['token'],
|
||||
'title' => '订阅续期提醒 - Wallos',
|
||||
|
||||
@@ -194,6 +194,8 @@ $i18n = [
|
||||
"telegram" => "Telegram",
|
||||
"telegram_bot_token" => "Token služby Telegram Bot",
|
||||
"telegram_chat_id" => "ID chatu v Telegramu",
|
||||
"pushplus" => "Pushplus",
|
||||
"pushplus_token" => "Pushplus Token",
|
||||
"webhook" => "Webhook",
|
||||
"webhook_url" => "Adresa URL webhooku",
|
||||
"request_method" => "Metoda požadavku",
|
||||
|
||||
@@ -194,6 +194,8 @@ $i18n = [
|
||||
"telegram" => "Telegram",
|
||||
"telegram_bot_token" => "Telegram Bot Token",
|
||||
"telegram_chat_id" => "Telegram Chat ID",
|
||||
"pushplus" => "Pushplus",
|
||||
"pushplus_token" => "Pushplus Token",
|
||||
"webhook" => "Webhook",
|
||||
"webhook_url" => "Webhook URL",
|
||||
"request_method" => "Request-metode",
|
||||
|
||||
@@ -193,6 +193,8 @@ $i18n = [
|
||||
"telegram" => "Telegram",
|
||||
"telegram_bot_token" => "Telegram Bot Token",
|
||||
"telegram_chat_id" => "Telegram Chat ID",
|
||||
"pushplus" => "Pushplus",
|
||||
"pushplus_token" => "Pushplus Token",
|
||||
"webhook" => "Webhook",
|
||||
"webhook_url" => "Webhook URL",
|
||||
"request_method" => "Request Methode",
|
||||
|
||||
@@ -193,6 +193,8 @@ $i18n = [
|
||||
"telegram" => "Telegram",
|
||||
"telegram_bot_token" => "Τηλεγραφήματα Bot Token",
|
||||
"telegram_chat_id" => "Τηλεγραφήματα Chat ID",
|
||||
"pushplus" => "Pushplus",
|
||||
"pushplus_token" => "Pushplus Token",
|
||||
"webhook" => "Webhook",
|
||||
"webhook_url" => "Webhook URL",
|
||||
"request_method" => "Μέθοδος αίτησης",
|
||||
|
||||
@@ -194,6 +194,8 @@ $i18n = [
|
||||
"telegram" => "Telegram",
|
||||
"telegram_bot_token" => "Telegram Bot Token",
|
||||
"telegram_chat_id" => "Telegram Chat ID",
|
||||
"pushplus" => "Pushplus",
|
||||
"pushplus_token" => "Pushplus Token",
|
||||
"webhook" => "Webhook",
|
||||
"webhook_url" => "Webhook URL",
|
||||
"request_method" => "Request Method",
|
||||
|
||||
@@ -193,6 +193,8 @@ $i18n = [
|
||||
"telegram" => "Telegram",
|
||||
"telegram_bot_token" => "Token del Bot de Telegram",
|
||||
"telegram_chat_id" => "ID del Chat de Telegram",
|
||||
"pushplus" => "Pushplus",
|
||||
"pushplus_token" => "Token de Pushplus",
|
||||
"webhook" => "Webhook",
|
||||
"webhook_url" => "URL del Webhook",
|
||||
"request_method" => "Método de Solicitud",
|
||||
|
||||
@@ -193,6 +193,8 @@ $i18n = [
|
||||
"telegram" => "Telegram",
|
||||
"telegram_bot_token" => "Jeton du bot Telegram",
|
||||
"telegram_chat_id" => "ID de chat Telegram",
|
||||
"pushplus" => "Pushplus",
|
||||
"pushplus_token" => "Jeton Pushplus",
|
||||
"webhook" => "Webhook",
|
||||
"webhook_url" => "URL du webhook",
|
||||
"request_method" => "Méthode de requête",
|
||||
|
||||
@@ -194,6 +194,8 @@ $i18n = [
|
||||
"telegram" => "Telegram",
|
||||
"telegram_bot_token" => "Token Bot Telegram",
|
||||
"telegram_chat_id" => "ID Obrolan Telegram",
|
||||
"pushplus" => "Pushplus",
|
||||
"pushplus_token" => "Token Pushplus",
|
||||
"webhook" => "Webhook",
|
||||
"webhook_url" => "URL Webhook",
|
||||
"request_method" => "Metode Permintaan",
|
||||
|
||||
@@ -201,6 +201,8 @@ $i18n = [
|
||||
"telegram" => "Telegram",
|
||||
"telegram_bot_token" => "Telegram Bot Token",
|
||||
"telegram_chat_id" => "Telegram Chat ID",
|
||||
"pushplus" => "Pushplus",
|
||||
"pushplus_token" => "Pushplus Token",
|
||||
"webhook" => "Webhook",
|
||||
"webhook_url" => "Webhook URL",
|
||||
"request_method" => "Metodo di richiesta",
|
||||
|
||||
@@ -194,6 +194,8 @@ $i18n = [
|
||||
"telegram" => "Telegram",
|
||||
"telegram_bot_token" => "Telegramボットトークン",
|
||||
"telegram_chat_id" => "TelegramチャットID",
|
||||
"pushplus" => "Pushplus",
|
||||
"pushplus_token" => "Pushplusトークン",
|
||||
"webhook" => "Webhook",
|
||||
"webhook_url" => "Webhook URL",
|
||||
"request_method" => "リクエストメソッド",
|
||||
|
||||
@@ -193,6 +193,8 @@ $i18n = [
|
||||
"telegram" => "텔레그램",
|
||||
"telegram_bot_token" => "텔레그램 봇 토큰",
|
||||
"telegram_chat_id" => "텔레그램 채팅 ID",
|
||||
"pushplus" => "Pushplus",
|
||||
"pushplus_token" => "Pushplus 토큰",
|
||||
"webhook" => "웹훅",
|
||||
"webhook_url" => "웹훅 URL",
|
||||
"request_method" => "요청 메서드",
|
||||
|
||||
@@ -194,6 +194,8 @@ $i18n = [
|
||||
"telegram" => "Telegram",
|
||||
"telegram_bot_token" => "Telegram Bot Token",
|
||||
"telegram_chat_id" => "Telegram Chat ID",
|
||||
"pushplus" => "Pushplus",
|
||||
"pushplus_token" => "Pushplus Token",
|
||||
"webhook" => "Webhook",
|
||||
"webhook_url" => "Webhook URL",
|
||||
"request_method" => "Request Methode",
|
||||
|
||||
@@ -193,6 +193,8 @@ $i18n = [
|
||||
"telegram" => "Telegram",
|
||||
"telegram_bot_token" => "Token bota",
|
||||
"telegram_chat_id" => "ID czatu",
|
||||
"pushplus" => "Pushplus",
|
||||
"pushplus_token" => "Token Pushplus",
|
||||
"webhook" => "Webhook",
|
||||
"webhook_url" => "URL webhooka",
|
||||
"request_method" => "Metoda żądania",
|
||||
|
||||
@@ -193,6 +193,8 @@ $i18n = [
|
||||
"telegram" => "Telegram",
|
||||
"telegram_bot_token" => "Token do Bot Telegram",
|
||||
"telegram_chat_id" => "ID do Chat Telegram",
|
||||
"pushplus" => "Pushplus",
|
||||
"pushplus_token" => "Token do Pushplus",
|
||||
"webhook" => "Webhook",
|
||||
"webhook_url" => "URL do Webhook",
|
||||
"request_method" => "Método de Pedido",
|
||||
|
||||
@@ -193,6 +193,8 @@ $i18n = [
|
||||
"telegram" => "Telegram",
|
||||
"telegram_bot_token" => "Token do Bot",
|
||||
"telegram_chat_id" => "Chat ID",
|
||||
"pushplus" => "Pushplus",
|
||||
"pushplus_token" => "Token do Pushplus",
|
||||
"webhook" => "Webhook",
|
||||
"webhook_url" => "URL do Webhook",
|
||||
"request_method" => "Método de requisição",
|
||||
|
||||
@@ -193,6 +193,8 @@ $i18n = [
|
||||
"telegram" => "Telegram",
|
||||
"telegram_bot_token" => "Токен Telegram-бота",
|
||||
"telegram_chat_id" => "Telegram Chat ID",
|
||||
"pushplus" => "Pushplus",
|
||||
"pushplus_token" => "Токен Pushplus",
|
||||
"webhook" => "Webhook",
|
||||
"webhook_url" => "Webhook URL",
|
||||
"request_method" => "Метод запроса",
|
||||
|
||||
@@ -193,6 +193,8 @@ $i18n = [
|
||||
"telegram" => "Telegram",
|
||||
"telegram_bot_token" => "Telegram Bot žeton",
|
||||
"telegram_chat_id" => "ID klepeta Telegrama",
|
||||
"pushplus" => "Pushplus",
|
||||
"pushplus_token" => "Pushplus žeton",
|
||||
"webhook" => "Webhook",
|
||||
"webhook_url" => "Webhook URL",
|
||||
"request_method" => "Metoda zahteve",
|
||||
|
||||
@@ -193,6 +193,8 @@ $i18n = [
|
||||
"telegram" => "Телеграм",
|
||||
"telegram_bot_token" => "Телеграм бот токен",
|
||||
"telegram_chat_id" => "Телеграм чет ID",
|
||||
"pushplus" => "Pushplus",
|
||||
"pushplus_token" => "Pushplus токен",
|
||||
"webhook" => "Вебхук",
|
||||
"webhook_url" => "Вебхук URL",
|
||||
"request_method" => "Метод захтева",
|
||||
|
||||
@@ -193,6 +193,8 @@ $i18n = [
|
||||
"telegram" => "Telegram",
|
||||
"telegram_bot_token" => "Telegram bot token",
|
||||
"telegram_chat_id" => "Telegram chat ID",
|
||||
"pushplus" => "Pushplus",
|
||||
"pushplus_token" => "Pushplus token",
|
||||
"webhook" => "Webhook",
|
||||
"webhook_url" => "Webhook URL",
|
||||
"request_method" => "Metod zahteva",
|
||||
|
||||
@@ -193,6 +193,8 @@ $i18n = [
|
||||
"telegram" => "Telegram",
|
||||
"telegram_bot_token" => "Telegram Bot Token",
|
||||
"telegram_chat_id" => "Telegram Chat ID",
|
||||
"pushplus" => "Pushplus",
|
||||
"pushplus_token" => "Pushplus Token",
|
||||
"webhook" => "Webhook",
|
||||
"webhook_url" => "Webhook URL",
|
||||
"request_method" => "İstek Metodu",
|
||||
|
||||
@@ -193,6 +193,8 @@ $i18n = [
|
||||
"telegram" => "Telegram",
|
||||
"telegram_bot_token" => "Токен Telegram-бота",
|
||||
"telegram_chat_id" => "Telegram Chat ID",
|
||||
"pushplus" => "Pushplus",
|
||||
"pushplus_token" => "Pushplus токен",
|
||||
"webhook" => "Webhook",
|
||||
"webhook_url" => "Webhook URL",
|
||||
"request_method" => "Метод запиту",
|
||||
|
||||
@@ -194,6 +194,8 @@ $i18n = [
|
||||
"telegram" => "Telegram",
|
||||
"telegram_bot_token" => "Mã thông báo Bot Telegram",
|
||||
"telegram_chat_id" => "ID cuộc trò chuyện Telegram",
|
||||
"pushplus" => "Pushplus",
|
||||
"pushplus_token" => "Mã thông báo Pushplus",
|
||||
"webhook" => "Webhook",
|
||||
"webhook_url" => "URL Webhook",
|
||||
"request_method" => "Phương thức yêu cầu",
|
||||
|
||||
@@ -194,6 +194,8 @@ $i18n = [
|
||||
"telegram" => "Telegram",
|
||||
"telegram_bot_token" => "Telegram 機器人令牌",
|
||||
"telegram_chat_id" => "Telegram 聊天 ID",
|
||||
"pushplus" => "PushPlus",
|
||||
"pushplus_token" => "消息令牌或者是用户令牌",
|
||||
"webhook" => "Webhook",
|
||||
"webhook_url" => "Webhook 網址",
|
||||
"request_method" => "請求方法",
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<?php
|
||||
$version = "v4.1.1";
|
||||
$version = "v4.2.0";
|
||||
?>
|
||||
12
index.php
12
index.php
@@ -197,7 +197,7 @@ while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
|
||||
<?php
|
||||
|
||||
foreach ($aiRecommendations as $key => $recommendation) { ?>
|
||||
<li class="ai-recommendation-item">
|
||||
<li class="ai-recommendation-item" data-id="<?= $recommendation['id'] ?>">
|
||||
<div class="ai-recommendation-header">
|
||||
<h3>
|
||||
<span><?= ($key + 1) . ". " ?></span>
|
||||
@@ -205,9 +205,15 @@ while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
|
||||
</h3>
|
||||
<span class="item-arrow-down fa fa-caret-down"></span>
|
||||
</div>
|
||||
|
||||
<p class="collapsible"><?= htmlspecialchars($recommendation['description']) ?></p>
|
||||
<p><?= htmlspecialchars($recommendation['savings']) ?></p>
|
||||
<p class="ai-recommendation-savings">
|
||||
<?= htmlspecialchars($recommendation['savings']) ?>
|
||||
<span>
|
||||
<a href="#" class="delete-ai-recommendation" title="<?= translate('delete', $i18n) ?>">
|
||||
<i class="fa fa-trash"></i>
|
||||
</a>
|
||||
</span>
|
||||
</p>
|
||||
</li>
|
||||
<?php } ?>
|
||||
</ul>
|
||||
|
||||
14
migrations/000040.php
Normal file
14
migrations/000040.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
// This migration adds a pushplus_notifications table to store PushPlus notification settings.
|
||||
|
||||
$tableQuery = $db->query("SELECT name FROM sqlite_master WHERE type='table' AND name='pushplus_notifications'");
|
||||
$tableExists = $tableQuery->fetchArray(SQLITE3_ASSOC);
|
||||
if ($tableExists === false) {
|
||||
$db->exec("
|
||||
CREATE TABLE pushplus_notifications (
|
||||
enabled INTEGER NOT NULL DEFAULT 0,
|
||||
token TEXT,
|
||||
user_id INTEGER
|
||||
);
|
||||
");
|
||||
}
|
||||
@@ -4,4 +4,29 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
item.classList.toggle("expanded");
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelectorAll(".delete-ai-recommendation").forEach(function (el) {
|
||||
el.addEventListener("click", function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const item = el.closest(".ai-recommendation-item");
|
||||
const id = item.getAttribute("data-id");
|
||||
fetch("endpoints/ai/delete_recommendation.php", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ id: id })
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
item.remove();
|
||||
showSuccessMessage(translate('success'));
|
||||
} else {
|
||||
showErrorMessage(data.message || "Delete failed.");
|
||||
}
|
||||
})
|
||||
.catch(() => showErrorMessage(translate('unknown_error')));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
28
settings.php
28
settings.php
@@ -223,22 +223,22 @@ $userData['currency_symbol'] = $currencies[$main_currency]['symbol'];
|
||||
|
||||
|
||||
// PushPlus notifications
|
||||
$sql = "SELECT * FROM pushplus_notifications WHERE user_id = :userId LIMIT 1";
|
||||
$stmt = $db->prepare($sql);
|
||||
$stmt->bindValue(':userId', $userId, SQLITE3_INTEGER);
|
||||
$result = $stmt->execute();
|
||||
$sql = "SELECT * FROM pushplus_notifications WHERE user_id = :userId LIMIT 1";
|
||||
$stmt = $db->prepare($sql);
|
||||
$stmt->bindValue(':userId', $userId, SQLITE3_INTEGER);
|
||||
$result = $stmt->execute();
|
||||
|
||||
$rowCount = 0;
|
||||
while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
|
||||
$notificationsPushPlus['enabled'] = $row['enabled'];
|
||||
$notificationsPushPlus['token'] = $row['token'];
|
||||
$rowCount++;
|
||||
}
|
||||
$rowCount = 0;
|
||||
while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
|
||||
$notificationsPushPlus['enabled'] = $row['enabled'];
|
||||
$notificationsPushPlus['token'] = $row['token'];
|
||||
$rowCount++;
|
||||
}
|
||||
|
||||
if ($rowCount == 0) {
|
||||
$notificationsPushPlus['enabled'] = 0;
|
||||
$notificationsPushPlus['token'] = "";
|
||||
}
|
||||
if ($rowCount == 0) {
|
||||
$notificationsPushPlus['enabled'] = 0;
|
||||
$notificationsPushPlus['token'] = "";
|
||||
}
|
||||
|
||||
// Ntfy notifications
|
||||
$sql = "SELECT * FROM ntfy_notifications WHERE user_id = :userId LIMIT 1";
|
||||
|
||||
@@ -3042,6 +3042,19 @@ input[type="radio"]:checked+label::after {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
.ai-recommendation-item p.ai-recommendation-savings {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.ai-recommendation-item p.ai-recommendation-savings a {
|
||||
color: var(--main-color);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.ai-recommendation-item.expanded p.ai-recommendation-savings {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user