✨Implementation of the push notifications service, including sending notifications to specific subscribers and multiple subscribers, as well as creating standardized notification payloads.
parent
514eb41f6c
commit
baf90ddf79
@ -0,0 +1,106 @@
|
||||
from pywebpush import webpush, WebPushException
|
||||
import json
|
||||
from typing import List, Dict, Any
|
||||
import logging
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from app.config import VAPID_PRIVATE_KEY, VAPID_CLAIMS
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def get_audience(endpoint: str) -> str:
|
||||
parsed = urlparse(endpoint)
|
||||
return f"{parsed.scheme}://{parsed.netloc}"
|
||||
|
||||
class PushService:
|
||||
def __init__(self):
|
||||
self.vapid_private_key = VAPID_PRIVATE_KEY
|
||||
self.vapid_claims = VAPID_CLAIMS
|
||||
|
||||
async def send_notification(self, subscription: Dict[str, Any], payload: Dict[str, Any]) -> bool:
|
||||
"""
|
||||
Envoie une notification push à un abonné spécifique.
|
||||
|
||||
Args:
|
||||
subscription: Les informations de souscription push
|
||||
payload: Le contenu de la notification
|
||||
|
||||
Returns:
|
||||
bool: True si l'envoi a réussi, False sinon
|
||||
"""
|
||||
try:
|
||||
vapid_claims = self.vapid_claims
|
||||
vapid_claims["aud"] = get_audience(subscription["endpoint"])
|
||||
|
||||
print(f"Envoi de la notification push à {subscription} avec les claims: {vapid_claims}")
|
||||
print(f"Payload: {json.dumps(payload)}")
|
||||
|
||||
webpush(
|
||||
subscription_info=subscription,
|
||||
data=json.dumps(payload),
|
||||
vapid_private_key=self.vapid_private_key,
|
||||
vapid_claims=vapid_claims,
|
||||
verbose=True
|
||||
)
|
||||
return True
|
||||
except WebPushException as e:
|
||||
logger.error(f"Erreur lors de l'envoi de la notification push: {str(e)}")
|
||||
return False
|
||||
except Exception as e:
|
||||
logger.error(f"Erreur inattendue lors de l'envoi de la notification push: {str(e)}")
|
||||
return False
|
||||
|
||||
async def send_notification_to_all(self, subscriptions: List[Dict[str, Any]], payload: Dict[str, Any]) -> Dict[str, int]:
|
||||
"""
|
||||
Envoie une notification à plusieurs abonnés.
|
||||
|
||||
Args:
|
||||
subscriptions: Liste des informations de souscription
|
||||
payload: Le contenu de la notification
|
||||
|
||||
Returns:
|
||||
Dict contenant le nombre de succès et d'échecs
|
||||
"""
|
||||
results = {
|
||||
"success": 0,
|
||||
"failed": 0
|
||||
}
|
||||
|
||||
for subscription in subscriptions:
|
||||
success = await self.send_notification(subscription, payload)
|
||||
if success:
|
||||
results["success"] += 1
|
||||
else:
|
||||
results["failed"] += 1
|
||||
|
||||
return results
|
||||
|
||||
def create_notification_payload(self, title: str, body: str, icon: str = None) -> Dict[str, Any]:
|
||||
"""
|
||||
Crée un payload de notification standardisé.
|
||||
|
||||
Args:
|
||||
title: Titre de la notification
|
||||
body: Corps du message
|
||||
icon: URL de l'icône (optionnel)
|
||||
|
||||
Returns:
|
||||
Dict contenant le payload formaté
|
||||
"""
|
||||
payload = {
|
||||
"notification": {
|
||||
"title": title,
|
||||
"body": body
|
||||
},
|
||||
"data": {
|
||||
"url": "/map"
|
||||
}
|
||||
}
|
||||
|
||||
if icon:
|
||||
payload["notification"]["icon"] = icon
|
||||
|
||||
return payload
|
||||
|
||||
# Instance singleton du service
|
||||
push_service = PushService()
|
Loading…
Reference in new issue