bae705aa97
- Add NFC ePassport roadmap (ICAO 9303, eIDAS) - Add TensorFlow.js edge face detection (BlazeFace) - Add structured audit logger (GDPR-compliant) - Risk scoring support Part of KYC Apple Native UX v1.1.0
251 lines
7.8 KiB
Python
251 lines
7.8 KiB
Python
"""
|
|
Notification System
|
|
Email, SMS, Push notifications for IOM platform
|
|
"""
|
|
|
|
from typing import Dict, List, Optional
|
|
from dataclasses import dataclass
|
|
from enum import Enum
|
|
from datetime import datetime
|
|
|
|
|
|
class NotificationChannel(str, Enum):
|
|
"""Notification channels"""
|
|
EMAIL = "email"
|
|
SMS = "sms"
|
|
PUSH = "push"
|
|
WEBHOOK = "webhook"
|
|
SLACK = "slack"
|
|
|
|
|
|
class NotificationPriority(str, Enum):
|
|
"""Notification priorities"""
|
|
LOW = "low"
|
|
MEDIUM = "medium"
|
|
HIGH = "high"
|
|
CRITICAL = "critical"
|
|
|
|
|
|
@dataclass
|
|
class Notification:
|
|
"""Notification message"""
|
|
id: str
|
|
channel: NotificationChannel
|
|
recipient: str
|
|
subject: str
|
|
body: str
|
|
priority: NotificationPriority
|
|
timestamp: str
|
|
metadata: Optional[Dict] = None
|
|
|
|
|
|
class NotificationEngine:
|
|
"""
|
|
Multi-channel notification engine
|
|
|
|
Supports:
|
|
- Email (SMTP)
|
|
- SMS (Twilio/simulated)
|
|
- Push (Firebase/APNs)
|
|
- Webhook (HTTP callbacks)
|
|
- Slack (webhooks)
|
|
"""
|
|
|
|
def __init__(self):
|
|
self.providers: Dict[NotificationChannel, callable] = {
|
|
NotificationChannel.EMAIL: self._send_email,
|
|
NotificationChannel.SMS: self._send_sms,
|
|
NotificationChannel.PUSH: self._send_push,
|
|
NotificationChannel.WEBHOOK: self._send_webhook,
|
|
NotificationChannel.SLACK: self._send_slack
|
|
}
|
|
self.history: List[Notification] = []
|
|
|
|
def send(
|
|
self,
|
|
channel: NotificationChannel,
|
|
recipient: str,
|
|
subject: str,
|
|
body: str,
|
|
priority: NotificationPriority = NotificationPriority.MEDIUM,
|
|
metadata: Optional[Dict] = None
|
|
) -> Dict:
|
|
"""Send notification"""
|
|
notification = Notification(
|
|
id=f"NOT-{datetime.utcnow().strftime('%Y%m%d%H%M%S')}",
|
|
channel=channel,
|
|
recipient=recipient,
|
|
subject=subject,
|
|
body=body,
|
|
priority=priority,
|
|
timestamp=datetime.utcnow().isoformat(),
|
|
metadata=metadata
|
|
)
|
|
|
|
# Send via provider
|
|
provider = self.providers.get(channel)
|
|
if provider:
|
|
result = provider(notification)
|
|
else:
|
|
result = {"status": "failed", "error": "Unknown channel"}
|
|
|
|
# Store in history
|
|
self.history.append(notification)
|
|
|
|
return {
|
|
"notification_id": notification.id,
|
|
"channel": channel.value,
|
|
"recipient": recipient,
|
|
"status": result.get("status", "unknown"),
|
|
"timestamp": notification.timestamp
|
|
}
|
|
|
|
def send_bulk(
|
|
self,
|
|
notifications: List[Dict]
|
|
) -> List[Dict]:
|
|
"""Send multiple notifications"""
|
|
results = []
|
|
for notif in notifications:
|
|
result = self.send(
|
|
channel=NotificationChannel(notif["channel"]),
|
|
recipient=notif["recipient"],
|
|
subject=notif["subject"],
|
|
body=notif["body"],
|
|
priority=NotificationPriority(notif.get("priority", "medium"))
|
|
)
|
|
results.append(result)
|
|
return results
|
|
|
|
def notify_stakeholder(
|
|
self,
|
|
stakeholder_type: str,
|
|
event_type: str,
|
|
data: Dict
|
|
) -> List[Dict]:
|
|
"""Notify stakeholder about event"""
|
|
notifications = []
|
|
|
|
if stakeholder_type == "municipality":
|
|
if event_type == "critical_defect":
|
|
notifications.append({
|
|
"channel": "email",
|
|
"recipient": "municipality@example.com",
|
|
"subject": f"Critical defect detected: {data.get('location', 'Unknown')}",
|
|
"body": f"A critical defect has been detected. Location: {data.get('location')}. Condition: {data.get('condition')}",
|
|
"priority": "critical"
|
|
})
|
|
|
|
elif stakeholder_type == "property_owner":
|
|
if event_type == "maintenance_required":
|
|
notifications.append({
|
|
"channel": "email",
|
|
"recipient": "owner@example.com",
|
|
"subject": "Maintenance required",
|
|
"body": f"Your property requires maintenance. Estimated cost: ${data.get('cost', 0)}",
|
|
"priority": "high"
|
|
})
|
|
|
|
return self.send_bulk(notifications)
|
|
|
|
def _send_email(self, notification: Notification) -> Dict:
|
|
"""Send email notification"""
|
|
# In production, use SMTP
|
|
print(f"[EMAIL] To: {notification.recipient}")
|
|
print(f"[EMAIL] Subject: {notification.subject}")
|
|
print(f"[EMAIL] Body: {notification.body[:100]}...")
|
|
return {"status": "sent"}
|
|
|
|
def _send_sms(self, notification: Notification) -> Dict:
|
|
"""Send SMS notification"""
|
|
# In production, use Twilio
|
|
print(f"[SMS] To: {notification.recipient}")
|
|
print(f"[SMS] Body: {notification.body[:160]}")
|
|
return {"status": "sent"}
|
|
|
|
def _send_push(self, notification: Notification) -> Dict:
|
|
"""Send push notification"""
|
|
# In production, use Firebase/APNs
|
|
print(f"[PUSH] To: {notification.recipient}")
|
|
print(f"[PUSH] Title: {notification.subject}")
|
|
return {"status": "sent"}
|
|
|
|
def _send_webhook(self, notification: Notification) -> Dict:
|
|
"""Send webhook notification"""
|
|
# In production, use HTTP client
|
|
print(f"[WEBHOOK] URL: {notification.recipient}")
|
|
print(f"[WEBHOOK] Payload: {notification.body[:100]}...")
|
|
return {"status": "sent"}
|
|
|
|
def _send_slack(self, notification: Notification) -> Dict:
|
|
"""Send Slack notification"""
|
|
# In production, use Slack webhook
|
|
print(f"[SLACK] Channel: {notification.recipient}")
|
|
print(f"[SLACK] Message: {notification.body[:100]}...")
|
|
return {"status": "sent"}
|
|
|
|
def get_history(self, limit: int = 100) -> List[Dict]:
|
|
"""Get notification history"""
|
|
return [
|
|
{
|
|
"id": n.id,
|
|
"channel": n.channel.value,
|
|
"recipient": n.recipient,
|
|
"subject": n.subject,
|
|
"priority": n.priority.value,
|
|
"timestamp": n.timestamp
|
|
}
|
|
for n in self.history[-limit:]
|
|
]
|
|
|
|
|
|
# Example usage
|
|
def example_notifications():
|
|
"""Example: Notification system"""
|
|
print("=== Notification Engine Demo ===\n")
|
|
|
|
engine = NotificationEngine()
|
|
|
|
# Send email
|
|
print("Sending email...")
|
|
result = engine.send(
|
|
channel=NotificationChannel.EMAIL,
|
|
recipient="admin@landvex.com",
|
|
subject="Critical alert: Bridge condition",
|
|
body="The bridge on Main Street has degraded to condition 4. Immediate action required.",
|
|
priority=NotificationPriority.CRITICAL
|
|
)
|
|
print(f"Status: {result['status']}\n")
|
|
|
|
# Send SMS
|
|
print("Sending SMS...")
|
|
result = engine.send(
|
|
channel=NotificationChannel.SMS,
|
|
recipient="+46701234567",
|
|
subject="Alert",
|
|
body="Critical defect detected near your location. Please check the app.",
|
|
priority=NotificationPriority.HIGH
|
|
)
|
|
print(f"Status: {result['status']}\n")
|
|
|
|
# Notify stakeholder
|
|
print("Notifying municipality...")
|
|
results = engine.notify_stakeholder(
|
|
stakeholder_type="municipality",
|
|
event_type="critical_defect",
|
|
data={"location": "Main Street Bridge", "condition": 4}
|
|
)
|
|
print(f"Sent: {len(results)} notifications\n")
|
|
|
|
# History
|
|
print("Notification history:")
|
|
history = engine.get_history()
|
|
for h in history:
|
|
print(f" [{h['channel']}] {h['subject']} ({h['priority']})")
|
|
|
|
return engine
|
|
|
|
|
|
if __name__ == '__main__':
|
|
example_notifications()
|