Files
ai_web/backend/apps/notifications/api.py
2026-01-28 16:00:56 +08:00

163 lines
5.3 KiB
Python

"""
Notifications API routes.
"""
from typing import List, Optional
import csv
from datetime import datetime
from ninja import Router
from ninja_jwt.authentication import JWTAuth
from ninja.pagination import paginate, PageNumberPagination
from django.shortcuts import get_object_or_404
from django.http import HttpResponse
from django.utils import timezone
from .models import Notification
from .utils import get_notification_preference
from .schemas import (
NotificationOut,
UnreadCountOut,
MessageOut,
NotificationPreferenceOut,
NotificationPreferenceIn,
)
router = Router()
@router.get("/", response=List[NotificationOut], auth=JWTAuth())
@paginate(PageNumberPagination, page_size=20)
def list_notifications(
request,
is_read: Optional[bool] = None,
type: Optional[str] = None,
start: Optional[datetime] = None,
end: Optional[datetime] = None,
):
"""Get current user's notifications."""
queryset = Notification.objects.filter(user=request.auth)
if is_read is not None:
queryset = queryset.filter(is_read=is_read)
if type:
queryset = queryset.filter(type=type)
if start:
queryset = queryset.filter(created_at__gte=start)
if end:
queryset = queryset.filter(created_at__lte=end)
return [
NotificationOut(
id=n.id,
user_id=n.user_id,
type=n.type,
title=n.title,
content=n.content,
related_id=n.related_id,
related_type=n.related_type,
is_read=n.is_read,
created_at=n.created_at,
)
for n in queryset
]
@router.get("/preferences/", response=NotificationPreferenceOut, auth=JWTAuth())
def get_preferences(request):
"""Get current user's notification preferences."""
preference = get_notification_preference(request.auth)
return NotificationPreferenceOut(
user_id=preference.user_id,
enable_bounty=preference.enable_bounty,
enable_price_alert=preference.enable_price_alert,
enable_system=preference.enable_system,
updated_at=preference.updated_at,
)
@router.patch("/preferences/", response=NotificationPreferenceOut, auth=JWTAuth())
def update_preferences(request, data: NotificationPreferenceIn):
"""Update notification preferences."""
preference = get_notification_preference(request.auth)
update_data = data.dict(exclude_unset=True)
for key, value in update_data.items():
setattr(preference, key, value)
preference.save()
return NotificationPreferenceOut(
user_id=preference.user_id,
enable_bounty=preference.enable_bounty,
enable_price_alert=preference.enable_price_alert,
enable_system=preference.enable_system,
updated_at=preference.updated_at,
)
@router.get("/unread-count/", response=UnreadCountOut, auth=JWTAuth())
def get_unread_count(request):
"""Get count of unread notifications."""
count = Notification.objects.filter(user=request.auth, is_read=False).count()
return UnreadCountOut(count=count)
@router.get("/export/", auth=JWTAuth())
def export_notifications_csv(request):
"""Export current user's notifications to CSV."""
notifications = Notification.objects.filter(user=request.auth).order_by("-created_at")
response = HttpResponse(content_type="text/csv; charset=utf-8")
filename = f'notifications_{timezone.now().strftime("%Y%m%d_%H%M%S")}.csv'
response["Content-Disposition"] = f'attachment; filename="{filename}"'
response.write("\ufeff")
writer = csv.writer(response)
writer.writerow(["created_at", "type", "title", "content", "is_read"])
for notification in notifications:
writer.writerow(
[
notification.created_at.isoformat(),
notification.type,
notification.title,
notification.content or "",
"true" if notification.is_read else "false",
]
)
return response
@router.post("/{notification_id}/read/", response=MessageOut, auth=JWTAuth())
def mark_as_read(request, notification_id: int):
"""Mark a notification as read."""
notification = get_object_or_404(
Notification,
id=notification_id,
user=request.auth
)
notification.is_read = True
notification.save()
return MessageOut(message="已标记为已读", success=True)
@router.post("/read-all/", response=MessageOut, auth=JWTAuth())
def mark_all_as_read(request):
"""Mark all notifications as read."""
Notification.objects.filter(user=request.auth, is_read=False).update(is_read=True)
return MessageOut(message="已全部标记为已读", success=True)
@router.delete("/{notification_id}", response=MessageOut, auth=JWTAuth())
def delete_notification(request, notification_id: int):
"""Delete a notification."""
notification = get_object_or_404(
Notification,
id=notification_id,
user=request.auth
)
notification.delete()
return MessageOut(message="通知已删除", success=True)
@router.delete("/", response=MessageOut, auth=JWTAuth())
def delete_all_read(request):
"""Delete all read notifications."""
Notification.objects.filter(user=request.auth, is_read=True).delete()
return MessageOut(message="已删除所有已读通知", success=True)