Files
boc/iom/notifications/notifier.py
T
Bernt bae705aa97 ARCHITECTURE: NFC roadmap, edge AI, audit logging
- 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
2026-06-29 16:24:48 +00:00

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()