feat: add internal notification endpoint for rTorrent event hooks
All checks were successful
Build MIPS Binary / build (push) Successful in 1m51s

This commit is contained in:
spinline
2026-02-13 12:08:40 +03:00
parent ae2c9c934d
commit e062a3c8cd
3 changed files with 47 additions and 0 deletions

View File

@@ -7,6 +7,7 @@ use rust_embed::RustEmbed;
pub mod auth; pub mod auth;
pub mod setup; pub mod setup;
pub mod notifications;
#[derive(RustEmbed)] #[derive(RustEmbed)]
#[folder = "../frontend/dist"] #[folder = "../frontend/dist"]

View File

@@ -0,0 +1,44 @@
use axum::{
extract::{State, Query},
http::StatusCode,
};
use serde::Deserialize;
use shared::{AppEvent, SystemNotification, NotificationLevel};
use crate::AppState;
#[derive(Deserialize)]
pub struct TorrentFinishedQuery {
pub name: String,
pub hash: String,
}
pub async fn torrent_finished_handler(
State(state): State<AppState>,
Query(params): Query<TorrentFinishedQuery>,
) -> StatusCode {
tracing::info!("Torrent finished notification received: {} ({})", params.name, params.hash);
let message = format!("Torrent tamamlandı: {}", params.name);
// 1. Send to active SSE clients (for Toast)
let notification = SystemNotification {
level: NotificationLevel::Success,
message: message.clone(),
};
let _ = state.event_bus.send(AppEvent::Notification(notification));
// 2. Send Web Push Notification (for Background)
#[cfg(feature = "push-notifications")]
{
let push_store = state.push_store.clone();
let title = "Torrent Tamamlandı".to_string();
let body = message;
tokio::spawn(async move {
if let Err(e) = crate::push::send_push_notification(&push_store, &title, &body).await {
tracing::error!("Failed to send push notification from webhook: {}", e);
}
});
}
StatusCode::OK
}

View File

@@ -60,6 +60,7 @@ async fn auth_middleware(
|| path.starts_with("/api/server_fns/get_setup_status") || path.starts_with("/api/server_fns/get_setup_status")
|| path.starts_with("/api/server_fns/Setup") || path.starts_with("/api/server_fns/Setup")
|| path.starts_with("/api/server_fns/setup") || path.starts_with("/api/server_fns/setup")
|| path.starts_with("/api/internal/")
|| path.starts_with("/swagger-ui") || path.starts_with("/swagger-ui")
|| path.starts_with("/api-docs") || path.starts_with("/api-docs")
|| !path.starts_with("/api/") || !path.starts_with("/api/")
@@ -434,6 +435,7 @@ async fn main() {
let db_for_ctx = db.clone(); let db_for_ctx = db.clone();
let app = app let app = app
.route("/api/events", get(sse::sse_handler)) .route("/api/events", get(sse::sse_handler))
.route("/api/internal/torrent-finished", post(handlers::notifications::torrent_finished_handler))
.route("/api/server_fns/{*fn_name}", post({ .route("/api/server_fns/{*fn_name}", post({
let scgi_path = scgi_path_for_ctx.clone(); let scgi_path = scgi_path_for_ctx.clone();
let db = db_for_ctx.clone(); let db = db_for_ctx.clone();