gitdataai/libs/service/push_helper.rs
ZhenYi 14f6e1e500 feat(core): initialize project with access control and AI integration
- Add gitignore and prettier configuration files for project scaffolding
- Implement room access control service with project member verification
- Create user access key management with CRUD operations and activity logging
- Add accordion UI component for frontend expandable sections
- Implement room AI configuration with list, upsert, and delete operations
- Add AI event types for agent join/leave/status change tracking
- Create streaming AI processing services for mode and react patterns
- Build room AI service with model detection and idempotency handling
- Integrate chat service orchestration for AI message processing
- Add typing indicators and stream cancellation for AI interactions
- Implement mention parsing and context extraction for AI agents
2026-05-03 06:04:31 +08:00

77 lines
2.4 KiB
Rust

use crate::push::{PushPayload, WebPushService};
use db::database::AppDatabase;
use models::users::user_notification;
use sea_orm::EntityTrait;
use std::sync::Arc;
use uuid::Uuid;
/// Helper function to send push notification to a user.
/// Reads the user's push subscription from `user_notification` table.
/// Non-blocking: failures are logged but don't affect the caller.
pub async fn send_push_notification(
push: &WebPushService,
db: &AppDatabase,
user_id: Uuid,
payload: &PushPayload,
) -> Result<(), String> {
let prefs = user_notification::Entity::find_by_id(user_id)
.one(db)
.await
.map_err(|e| format!("Failed to read push subscription: {}", e))?;
if let Some(prefs) = prefs {
if prefs.push_enabled
&& let Some(endpoint) = &prefs.push_subscription_endpoint
&& let Some(p256dh) = &prefs.push_subscription_keys_p256dh
&& let Some(auth) = &prefs.push_subscription_keys_auth
{
push.send(endpoint, p256dh, auth, payload)
.await
.map_err(|e| format!("WebPush send failed: {}", e))?;
}
}
Ok(())
}
/// Spawn a background task to send push notification.
/// Failures are logged but don't affect the caller.
pub fn spawn_push_notification(
push: Option<Arc<WebPushService>>,
db: AppDatabase,
user_id: Uuid,
payload: PushPayload,
) {
tokio::spawn(async move {
if let Some(push) = push {
if let Err(e) = send_push_notification(&push, &db, user_id, &payload).await {
tracing::warn!(user_id = %user_id, error = %e, "Push notification failed");
}
}
});
}
/// Create a push notification callback for RoomService.
pub fn create_push_notification_fn(
push: Arc<WebPushService>,
db: AppDatabase,
) -> room::PushNotificationFn {
Arc::new(
move |user_id: Uuid, title: String, body: Option<String>, url: Option<String>| {
let push = push.clone();
let db = db.clone();
let payload = PushPayload {
title,
body: body.unwrap_or_default(),
url,
icon: None,
};
tokio::spawn(async move {
if let Err(e) = send_push_notification(&push, &db, user_id, &payload).await {
tracing::warn!(user_id = %user_id, error = %e, "Push notification failed");
}
});
},
)
}