furry/mobile/views.py

468 lines
15 KiB
Python

"""
Mobile API Views für React Native Integration
"""
from django.shortcuts import render
from django.http import JsonResponse
from django.contrib.auth.decorators import login_required
from django.views.decorators.csrf import csrf_exempt
from django.utils import timezone
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework import status
from .models import MobileDevice, PushNotification, OfflineSync, MobileAnalytics, MobileCache, MobileSession
from .serializers import MobileDeviceSerializer, PushNotificationSerializer
import json
@api_view(['POST'])
@permission_classes([IsAuthenticated])
def register_device(request):
"""Mobile Device registrieren für Push Notifications"""
try:
data = request.data
device_token = data.get('device_token')
device_type = data.get('device_type', 'web')
if not device_token:
return Response({'error': 'Device token required'}, status=status.HTTP_400_BAD_REQUEST)
# Device erstellen oder aktualisieren
device, created = MobileDevice.objects.get_or_create(
device_token=device_token,
defaults={
'user': request.user,
'device_type': device_type,
'device_name': data.get('device_name', ''),
'device_model': data.get('device_model', ''),
'os_version': data.get('os_version', ''),
'app_version': data.get('app_version', ''),
}
)
if not created:
# Device aktualisieren
device.user = request.user
device.device_type = device_type
device.device_name = data.get('device_name', device.device_name)
device.device_model = data.get('device_model', device.device_model)
device.os_version = data.get('os_version', device.os_version)
device.app_version = data.get('app_version', device.app_version)
device.is_active = True
device.save()
serializer = MobileDeviceSerializer(device)
return Response(serializer.data, status=status.HTTP_201_CREATED if created else status.HTTP_200_OK)
except Exception as e:
return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
@api_view(['DELETE'])
@permission_classes([IsAuthenticated])
def unregister_device(request, device_token):
"""Mobile Device deregistrieren"""
try:
device = MobileDevice.objects.get(
device_token=device_token,
user=request.user
)
device.is_active = False
device.save()
return Response({'message': 'Device unregistered'}, status=status.HTTP_200_OK)
except MobileDevice.DoesNotExist:
return Response({'error': 'Device not found'}, status=status.HTTP_404_NOT_FOUND)
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def get_user_devices(request):
"""User's Mobile Devices abrufen"""
devices = MobileDevice.objects.filter(user=request.user, is_active=True)
serializer = MobileDeviceSerializer(devices, many=True)
return Response(serializer.data)
@api_view(['POST'])
@permission_classes([IsAuthenticated])
def send_push_notification(request):
"""Push Notification senden"""
try:
data = request.data
user_id = data.get('user_id')
notification_type = data.get('notification_type')
title = data.get('title')
message = data.get('message')
data_payload = data.get('data', {})
if not all([user_id, notification_type, title, message]):
return Response({'error': 'Missing required fields'}, status=status.HTTP_400_BAD_REQUEST)
# Get user's active devices
devices = MobileDevice.objects.filter(
user_id=user_id,
is_active=True
)
notifications = []
for device in devices:
notification = PushNotification.objects.create(
user_id=user_id,
device=device,
notification_type=notification_type,
title=title,
message=message,
data=data_payload
)
notifications.append(notification)
# Send actual push notification (would integrate with Firebase/APNS)
# send_push_notification_to_device(notifications)
serializer = PushNotificationSerializer(notifications, many=True)
return Response(serializer.data, status=status.HTTP_201_CREATED)
except Exception as e:
return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
@api_view(['POST'])
@permission_classes([IsAuthenticated])
def sync_offline_data(request):
"""Offline Data Sync für Mobile App"""
try:
data = request.data
sync_type = data.get('sync_type')
sync_data = data.get('data', {})
device_token = data.get('device_token')
if not sync_type or not device_token:
return Response({'error': 'Missing required fields'}, status=status.HTTP_400_BAD_REQUEST)
# Get device
try:
device = MobileDevice.objects.get(
device_token=device_token,
user=request.user,
is_active=True
)
except MobileDevice.DoesNotExist:
return Response({'error': 'Device not found'}, status=status.HTTP_404_NOT_FOUND)
# Create sync record
sync = OfflineSync.objects.create(
user=request.user,
device=device,
sync_type=sync_type,
data=sync_data,
status='pending'
)
# Process sync based on type
if sync_type == 'orders':
# Sync orders
pass
elif sync_type == 'products':
# Sync products
pass
elif sync_type == 'auctions':
# Sync auctions
pass
sync.status = 'completed'
sync.synced_at = timezone.now()
sync.save()
return Response({
'sync_id': str(sync.id),
'status': sync.status,
'synced_at': sync.synced_at
}, status=status.HTTP_200_OK)
except Exception as e:
return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
@api_view(['POST'])
@permission_classes([IsAuthenticated])
def track_analytics(request):
"""Mobile Analytics Event tracken"""
try:
data = request.data
event_type = data.get('event_type')
event_data = data.get('event_data', {})
session_id = data.get('session_id', '')
screen_name = data.get('screen_name', '')
device_token = data.get('device_token')
if not event_type or not device_token:
return Response({'error': 'Missing required fields'}, status=status.HTTP_400_BAD_REQUEST)
# Get device
try:
device = MobileDevice.objects.get(
device_token=device_token,
user=request.user,
is_active=True
)
except MobileDevice.DoesNotExist:
return Response({'error': 'Device not found'}, status=status.HTTP_404_NOT_FOUND)
# Create analytics record
analytics = MobileAnalytics.objects.create(
user=request.user,
device=device,
event_type=event_type,
event_data=event_data,
session_id=session_id,
screen_name=screen_name
)
return Response({'analytics_id': str(analytics.id)}, status=status.HTTP_201_CREATED)
except Exception as e:
return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def get_mobile_products(request):
"""Mobile-optimierte Produktliste"""
from products.models import Product
from products.serializers import ProductSerializer
# Mobile-optimierte Filter
products = Product.objects.filter(is_active=True).select_related('category')
# Pagination
page = int(request.GET.get('page', 1))
per_page = int(request.GET.get('per_page', 20))
start = (page - 1) * per_page
end = start + per_page
products_page = products[start:end]
serializer = ProductSerializer(products_page, many=True)
return Response({
'products': serializer.data,
'total': products.count(),
'page': page,
'per_page': per_page,
'has_next': end < products.count(),
'has_previous': page > 1
})
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def get_mobile_auctions(request):
"""Mobile-optimierte Auktionen"""
from auction.models import Auction
from auction.serializers import AuctionSerializer
auctions = Auction.objects.filter(status='active').select_related('created_by')
# Pagination
page = int(request.GET.get('page', 1))
per_page = int(request.GET.get('per_page', 10))
start = (page - 1) * per_page
end = start + per_page
auctions_page = auctions[start:end]
serializer = AuctionSerializer(auctions_page, many=True)
return Response({
'auctions': serializer.data,
'total': auctions.count(),
'page': page,
'per_page': per_page,
'has_next': end < auctions.count(),
'has_previous': page > 1
})
@api_view(['POST'])
@permission_classes([IsAuthenticated])
def start_session(request):
"""Mobile Session starten"""
try:
data = request.data
device_token = data.get('device_token')
session_id = data.get('session_id')
if not device_token or not session_id:
return Response({'error': 'Missing required fields'}, status=status.HTTP_400_BAD_REQUEST)
# Get device
try:
device = MobileDevice.objects.get(
device_token=device_token,
user=request.user,
is_active=True
)
except MobileDevice.DoesNotExist:
return Response({'error': 'Device not found'}, status=status.HTTP_404_NOT_FOUND)
# Create or update session
session, created = MobileSession.objects.get_or_create(
session_id=session_id,
defaults={
'user': request.user,
'device': device,
'is_active': True
}
)
if not created:
session.is_active = True
session.save()
return Response({
'session_id': session.session_id,
'started_at': session.started_at
}, status=status.HTTP_200_OK)
except Exception as e:
return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
@api_view(['POST'])
@permission_classes([IsAuthenticated])
def end_session(request, session_id):
"""Mobile Session beenden"""
try:
session = MobileSession.objects.get(
session_id=session_id,
user=request.user,
is_active=True
)
session.end_session()
return Response({
'session_id': session.session_id,
'duration': session.duration,
'ended_at': session.ended_at
}, status=status.HTTP_200_OK)
except MobileSession.DoesNotExist:
return Response({'error': 'Session not found'}, status=status.HTTP_404_NOT_FOUND)
@api_view(['POST'])
@permission_classes([IsAuthenticated])
def report_error(request):
"""Mobile App Error melden"""
try:
data = request.data
error_level = data.get('error_level', 'error')
error_type = data.get('error_type')
error_message = data.get('error_message')
stack_trace = data.get('stack_trace', '')
device_token = data.get('device_token')
if not error_type or not error_message or not device_token:
return Response({'error': 'Missing required fields'}, status=status.HTTP_400_BAD_REQUEST)
# Get device
try:
device = MobileDevice.objects.get(
device_token=device_token,
user=request.user,
is_active=True
)
except MobileDevice.DoesNotExist:
return Response({'error': 'Device not found'}, status=status.HTTP_404_NOT_FOUND)
# Create error record
error = MobileError.objects.create(
user=request.user,
device=device,
error_level=error_level,
error_type=error_type,
error_message=error_message,
stack_trace=stack_trace,
app_version=data.get('app_version', ''),
os_version=data.get('os_version', ''),
device_info=data.get('device_info', {})
)
return Response({'error_id': str(error.id)}, status=status.HTTP_201_CREATED)
except Exception as e:
return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def get_mobile_cache(request, cache_type):
"""Mobile Cache abrufen"""
try:
cache_key = request.GET.get('key', 'default')
cache = MobileCache.objects.filter(
user=request.user,
cache_type=cache_type,
cache_key=cache_key,
expires_at__gt=timezone.now()
).first()
if cache:
return Response({
'data': cache.cache_data,
'expires_at': cache.expires_at
})
else:
return Response({'data': None}, status=status.HTTP_404_NOT_FOUND)
except Exception as e:
return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
@api_view(['POST'])
@permission_classes([IsAuthenticated])
def update_mobile_cache(request, cache_type):
"""Mobile Cache aktualisieren"""
try:
data = request.data
cache_key = data.get('key', 'default')
cache_data = data.get('data', {})
expires_in = data.get('expires_in', 3600) # Default 1 hour
expires_at = timezone.now() + timezone.timedelta(seconds=expires_in)
cache, created = MobileCache.objects.update_or_create(
user=request.user,
cache_type=cache_type,
cache_key=cache_key,
defaults={
'cache_data': cache_data,
'expires_at': expires_at
}
)
return Response({
'cache_id': str(cache.id),
'expires_at': cache.expires_at
}, status=status.HTTP_201_CREATED if created else status.HTTP_200_OK)
except Exception as e:
return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)