WebSocket работает, пока приложение открыто. Когда пользователь свернул приложение, нужны push-нотификации. Мы сделали единый адаптер:
# push_service.py — сервис мобильных пушей
import asyncio
import firebase_admin
from firebase_admin import messaging
from aioapns import APNs, NotificationRequest, PushType
class PushService:
def __init__(self, config):
# Firebase для Android
firebase_admin.initialize_app(firebase_admin.credentials.Certificate(
config['firebase_credentials_path']
))
# APNs для iOS
self.apns = APNs(
key=config['apns_key_path'],
key_id=config['apns_key_id'],
team_id=config['apns_team_id'],
topic=config['apns_bundle_id'],
use_sandbox=config.get('apns_sandbox', False),
)
async def send(self, user_id: str, title: str, body: str,
data: dict, tokens: list[dict]):
tasks = []
for token_info in tokens:
if token_info['platform'] == 'android':
tasks.append(self._send_fcm(token_info['token'], title, body, data))
elif token_info['platform'] == 'ios':
tasks.append(self._send_apns(token_info['token'], title, body, data))
results = await asyncio.gather(*tasks, return_exceptions=True)
# Обработка невалидных токенов
for i, result in enumerate(results):
if isinstance(result, Exception):
await self._handle_failed_token(tokens[i], result)
return results
async def _send_fcm(self, token, title, body, data):
message = messaging.Message(
notification=messaging.Notification(title=title, body=body),
data={k: str(v) for k, v in data.items()},
token=token,
android=messaging.AndroidConfig(
priority='high',
ttl=60, # 60 секунд TTL для спортивных событий
),
)
return messaging.send(message)
async def _send_apns(self, token, title, body, data):
request = NotificationRequest(
device_token=token,
message={
"aps": {
"alert": {"title": title, "body": body},
"sound": "score_update.wav",
"badge": 1,
"mutable-content": 1,
},
**data,
},
push_type=PushType.ALERT,
time_to_live=60,
)
return await self.apns.send_notification(request)
Оставить комментарий