Spaces:
Running
Running
| from django.views.decorators.csrf import csrf_exempt | |
| from django.shortcuts import render, get_object_or_404, redirect | |
| from django.contrib.auth.decorators import login_required, user_passes_test | |
| from django.http import JsonResponse, HttpResponse | |
| from django.views.decorators.http import require_POST | |
| from django.utils import timezone | |
| import json | |
| from .models import ( | |
| Bhagat, | |
| Event, | |
| Attendance, | |
| PushSubscription, | |
| Notification, | |
| Region, | |
| BhajanCategory, | |
| Bhajan, | |
| OptionPoll, | |
| Poll, | |
| Books, | |
| Sections, | |
| Chapters, | |
| Gallery, | |
| Wallpaper | |
| ) | |
| from django.conf import settings | |
| from django.core import serializers | |
| from django.db.models import Q | |
| import requests | |
| from rest_framework.decorators import api_view, permission_classes | |
| from rest_framework.permissions import AllowAny | |
| from rest_framework.response import Response | |
| from .utils import jwt_required | |
| from rest_framework_simplejwt.tokens import RefreshToken | |
| from pywebpush import webpush, WebPushException | |
| def gCaptchaVerifer(token): | |
| secret_key = settings.RECAPTCHA_SECRET_KEY | |
| data = {"response": token, "secret": secret_key} | |
| resp = requests.post("https://www.google.com/recaptcha/api/siteverify", data=data) | |
| return resp.json() | |
| def is_superadmin(user): | |
| return user.user_type == "superadmin" | |
| def is_regionadmin(user): | |
| return user.user_type == "regionadmin" | |
| def is_monitor(user): | |
| return user.user_type == "monitor" | |
| def dataEntry(request): | |
| # with open("./api/bhajanData.json", "r",encoding="utf-8") as f: | |
| # data = json.load(f)["Prasang"] | |
| # for bhajan in data: | |
| # category = BhajanCategory.objects.filter(link=bhajan['CatId']).first() | |
| # Bhajan.objects.create( | |
| # title=bhajan['title'], | |
| # title_guj=bhajan['title_guj'], | |
| # category=category, | |
| # lyrics=bhajan['lyrics'], | |
| # isEng = bhajan['isEng'], | |
| # isHnd = bhajan['isHnd'], | |
| # isGer = bhajan['isGer'], | |
| # isAudio = bhajan['isAudio'], | |
| # audio_url=bhajan['audio_url'] if bhajan['isAudio'] else "" | |
| # ) | |
| # print(bhajan['title']) | |
| return HttpResponse("Data Entry Page") | |
| def bhajanCategoryList(request): | |
| categories = BhajanCategory.objects.all() | |
| categoryArr = [] | |
| for category in categories: | |
| categoryArr.append( | |
| {"name": category.name, "link": category.link, "icon": category.icon if category.icon else None} | |
| ) | |
| lyricsBase = ( | |
| "https://huggingface.co/spaces/thejagstudio/MusicStore/raw/main/HTML Files/" | |
| ) | |
| audioBase = "https://huggingface.co/spaces/thejagstudio/MusicStore/resolve/main/Bhajan Audio/" | |
| return JsonResponse( | |
| {"categories": categoryArr, "lyricsBase": lyricsBase, "audioBase": audioBase} | |
| ) | |
| def bhajanList(request, catLink): | |
| if catLink == "all-kirtan": | |
| bhajans = Bhajan.objects.all() | |
| category = "All Kirtan" | |
| else: | |
| bhajans = Bhajan.objects.filter(category__link=catLink) | |
| category = BhajanCategory.objects.get(link=catLink).name | |
| bhajanArr = [] | |
| for bhajan in bhajans: | |
| bhajanArr.append( | |
| { | |
| "id": bhajan.bhajanId, | |
| "title": bhajan.title, | |
| "title_guj": bhajan.title_guj, | |
| "lyrics": bhajan.lyrics, | |
| "audio_url": bhajan.audio_url, | |
| "isEng": bhajan.isEng, | |
| "isHnd": bhajan.isHnd, | |
| "isGer": bhajan.isGer, | |
| "isAudio": bhajan.isAudio, | |
| } | |
| ) | |
| lyricsBase = ( | |
| "https://huggingface.co/spaces/thejagstudio/MusicStore/raw/main/HTML Files/" | |
| ) | |
| audioBase = "https://huggingface.co/spaces/thejagstudio/MusicStore/resolve/main/Bhajan Audio/" | |
| return JsonResponse( | |
| { | |
| "bhajans": bhajanArr, | |
| "lyricsBase": lyricsBase, | |
| "audioBase": audioBase, | |
| "category": category, | |
| } | |
| ) | |
| def bhajanDetail(request, bhajanId): | |
| bhajan = Bhajan.objects.filter(bhajanId=bhajanId).first() | |
| if not bhajan: | |
| return JsonResponse({"error": "Bhajan not found"}) | |
| else: | |
| return JsonResponse( | |
| { | |
| "id": bhajan.bhajanId, | |
| "title": bhajan.title, | |
| "title_guj": bhajan.title_guj, | |
| "category": bhajan.category.name, | |
| "lyrics": bhajan.lyrics, | |
| "audio_url": bhajan.audio_url, | |
| "isEng": bhajan.isEng, | |
| "isHnd": bhajan.isHnd, | |
| "isGer": bhajan.isGer, | |
| "isAudio": bhajan.isAudio, | |
| "lyricsBase": "https://huggingface.co/spaces/thejagstudio/MusicStore/raw/main/HTML Files/", | |
| "audioBase": "https://huggingface.co/spaces/thejagstudio/MusicStore/resolve/main/Bhajan Audio/", | |
| } | |
| ) | |
| def eventList(request): | |
| events = Event.objects.all() | |
| eventArr = [] | |
| for event in events: | |
| # convert date to Sept 26,2024 | 8:30 - 9:30 | |
| dateFormatted = ( | |
| event.date.strftime("%b %d, %Y") | |
| + " | " | |
| + event.date.strftime("%I:%M %p") | |
| + " - " | |
| + event.time.strftime("%I:%M %p") | |
| ) | |
| eventArr.append( | |
| { | |
| "title": event.title, | |
| "description": event.description, | |
| "date": dateFormatted, | |
| "day": int(event.date.strftime("%d")), | |
| "month": int(event.date.strftime("%m")), | |
| "year": int(event.date.strftime("%Y")), | |
| "created_by": event.created_by.__str__(), | |
| "region": event.region.name, | |
| "is_approved": event.is_approved, | |
| "color": event.color, | |
| } | |
| ) | |
| return JsonResponse({"events": eventArr}) | |
| def notification(request): | |
| notifications = Notification.objects.all() | |
| notificationArr = [] | |
| for notification in notifications: | |
| notificationArr.append( | |
| { | |
| "sender": notification.sender.__str__(), | |
| "category": notification.sender.user_type, | |
| "title": notification.title, | |
| "content": notification.content, | |
| "timestamp": notification.timestamp.strftime("%b %d, %Y | %I:%M %p"), | |
| "notification_type": notification.notification_type, | |
| } | |
| ) | |
| return JsonResponse({"notifications": notificationArr}) | |
| def send_notification(request): | |
| if request.method == "POST": | |
| content = request.POST.get("content") | |
| recipient_type = request.POST.get("recipient_type") | |
| notification = Notification.objects.create( | |
| sender=request.user, content=content, notification_type="custom" | |
| ) | |
| # Send web push notifications | |
| subscriptions = PushSubscription.objects.all() | |
| for subscription in subscriptions: | |
| send_push_notification( | |
| subscription, | |
| { | |
| "title": "New Notification", | |
| "content": content, | |
| "url": "/notifications", | |
| }, | |
| ) | |
| return JsonResponse({"status": "success"}) | |
| return JsonResponse({"status": "error"}) | |
| def birthday_notifications(): | |
| today = timezone.now().date() | |
| birthday_users = Bhagat.objects.filter( | |
| birthday__month=today.month, birthday__day=today.day | |
| ) | |
| for user in birthday_users: | |
| notification = Notification.objects.create( | |
| sender=Bhagat.objects.get(user_type="superadmin"), | |
| content=f"Happy Birthday to {user.get_full_name()}!", | |
| notification_type="birthday", | |
| ) | |
| notification.recipients.set(Bhagat.objects.all()) | |
| def login(request): | |
| if request.method == "POST": | |
| username = request.POST.get("username") | |
| password = request.POST.get("password") | |
| captcha_response = request.POST.get("captcha_response") | |
| # Verify captcha | |
| result = gCaptchaVerifer(captcha_response) | |
| if not result.get("success"): | |
| return JsonResponse({"error": "Invalid Captcha", "status": "error"}) | |
| # Authenticate user | |
| user = Bhagat.objects.filter(username=username).first() | |
| if user is not None and user.check_password(password): | |
| # Generate tokens | |
| refresh = RefreshToken.for_user(user) | |
| return JsonResponse( | |
| { | |
| "status": "success", | |
| "tokens": { | |
| "access_token": str(refresh.access_token), | |
| "refresh_token": str(refresh), | |
| }, | |
| "user": { | |
| "id": user.id, | |
| "username": user.username, | |
| "first_name": user.first_name, | |
| "last_name": user.last_name, | |
| "email": user.email, | |
| "phone": user.phone, | |
| "region": user.region.name, | |
| "user_type": user.user_type, | |
| "profile_image": user.profile_image.url if user.profile_image else None, | |
| }, | |
| } | |
| ) | |
| return JsonResponse({"error": "Invalid credentials", "status": "error"}) | |
| return JsonResponse({"error": "Invalid Method", "status": "error"}) | |
| def logout(request): | |
| if request.method == "POST": | |
| refresh_token = request.POST.get("refresh_token") | |
| if not refresh_token: | |
| return JsonResponse( | |
| {"error": "Refresh token is required", "status": "error"} | |
| ) | |
| else: | |
| try: | |
| refresh = RefreshToken(refresh_token) | |
| refresh.blacklist() | |
| return JsonResponse( | |
| {"status": "success", "message": "Successfully logged out"} | |
| ) | |
| except Exception as e: | |
| return JsonResponse( | |
| {"error": "Invalid token | " + str(e), "status": "error"} | |
| ) | |
| return JsonResponse({"status": "error", "error": "Invalid Method"}) | |
| def get_user_profile(request): | |
| try: | |
| user = request.user | |
| return JsonResponse( | |
| { | |
| "status": "success", | |
| "user": { | |
| "id": user.id, | |
| "username": user.username, | |
| "first_name": user.first_name, | |
| "last_name": user.last_name, | |
| "email": user.email, | |
| "phone": user.phone, | |
| "region": user.region.name, | |
| "user_type": user.user_type, | |
| "profile_image": user.profile_image.url if user.profile_image else None, | |
| }, | |
| } | |
| ) | |
| except Exception as e: | |
| return JsonResponse({"status": "error", "error": str(e)}) | |
| def profile_updater(request): | |
| if request.method == "POST": | |
| try: | |
| user = request.user | |
| first_name = request.POST.get("first_name") | |
| if first_name: | |
| user.first_name = first_name | |
| last_name = request.POST.get("last_name") | |
| if last_name: | |
| user.last_name = last_name | |
| email = request.POST.get("email") | |
| if email: | |
| user.email = email | |
| phone = request.POST.get("phone") | |
| if phone: | |
| user.phone = phone | |
| region_name = request.POST.get("region") | |
| if region_name: | |
| user.region = Region.objects.get(name=region_name) | |
| birth_date = request.POST.get("birth_date") | |
| if birth_date: | |
| user.birthday = birth_date | |
| street_name = request.POST.get("street_name") | |
| if street_name: | |
| user.streetName = street_name | |
| pincode = request.POST.get("pincode") | |
| if pincode: | |
| user.pincode = pincode | |
| city = request.POST.get("city") | |
| if city: | |
| user.city = city | |
| state = request.POST.get("state") | |
| if state: | |
| user.state = state | |
| country = request.POST.get("country") | |
| if country: | |
| user.country = country | |
| profile_image = request.FILES.get("profile_image") | |
| if profile_image: | |
| user.profile_image = profile_image | |
| user.save() | |
| return JsonResponse( | |
| {"status": "success", "message": "Profile updated successfully"} | |
| ) | |
| except Exception as e: | |
| return JsonResponse({"status": "error", "error": str(e)}) | |
| else: | |
| user = request.user | |
| regions = Region.objects.all() | |
| data = { | |
| "first_name": user.first_name, | |
| "last_name": user.last_name, | |
| "email": user.email, | |
| "phone": user.phone, | |
| "region": user.region.name, | |
| "birth_date": user.birthday, | |
| "street_name": user.streetName, | |
| "pincode": user.pincode, | |
| "city": user.city, | |
| "state": user.state, | |
| "country": user.country, | |
| "profile_image": user.profile_image, | |
| } | |
| return JsonResponse( | |
| { | |
| "status": "success", | |
| "regions": [region.name for region in regions], | |
| "user": data, | |
| } | |
| ) | |
| def bhaktoList(request): | |
| current_user = request.user | |
| bhaktos = Bhagat.objects.filter(assigned_to=current_user).all() | |
| bhaktoArr = [] | |
| for bhakto in bhaktos: | |
| bhaktoArr.append( | |
| { | |
| "id": bhakto.id, | |
| "first_name": bhakto.first_name, | |
| "last_name": bhakto.last_name, | |
| "region": bhakto.region.name, | |
| "user_type": bhakto.user_type, | |
| "profile_image": bhakto.profile_image.url if bhakto.profile_image else None, | |
| } | |
| ) | |
| return JsonResponse({"bhaktos": bhaktoArr}) | |
| def send_otp(request): | |
| try: | |
| data = json.loads(request.body) | |
| phone = data.get("phone") | |
| if not phone: | |
| return JsonResponse( | |
| {"status": "error", "error": "Phone number is required"} | |
| ) | |
| # Check if user exists | |
| user = Bhagat.objects.filter(phone=phone).first() | |
| if not user: | |
| return JsonResponse( | |
| {"status": "error", "error": "No account found with this phone number"} | |
| ) | |
| # Generate dummy OTP (in production, use proper OTP generation and SMS service) | |
| otp = "123456" # Dummy OTP for testing | |
| print(f"Generated OTP for {phone}: {otp}") # This simulates sending OTP | |
| # In production, store OTP with timestamp in database or cache | |
| # For now, we'll just return success | |
| return JsonResponse({"status": "success", "message": "OTP sent successfully"}) | |
| except Exception as e: | |
| return JsonResponse({"status": "error", "error": str(e)}) | |
| def verify_otp(request): | |
| try: | |
| data = json.loads(request.body) | |
| phone = data.get("phone") | |
| otp = data.get("otp") | |
| if not phone or not otp: | |
| return JsonResponse( | |
| {"status": "error", "error": "Phone number and OTP are required"} | |
| ) | |
| # For demo purposes, accept any 6-digit OTP | |
| if otp == "123456": # Dummy verification | |
| return JsonResponse( | |
| {"status": "success", "message": "OTP verified successfully"} | |
| ) | |
| return JsonResponse({"status": "error", "error": "Invalid OTP"}) | |
| except Exception as e: | |
| return JsonResponse({"status": "error", "error": str(e)}) | |
| def change_password(request): | |
| try: | |
| data = json.loads(request.body) | |
| new_password = data.get("new_password") | |
| if not new_password: | |
| return JsonResponse( | |
| { | |
| "status": "error", | |
| "error": "Phone number and new password are required", | |
| } | |
| ) | |
| # Update user's password | |
| user = request.user | |
| if not user: | |
| return JsonResponse({"status": "error", "error": "User not found"}) | |
| user.password = new_password | |
| user.save() | |
| return JsonResponse( | |
| {"status": "success", "message": "Password changed successfully"} | |
| ) | |
| except Exception as e: | |
| return JsonResponse({"status": "error", "error": str(e)}) | |
| def save_push_subscription(request): | |
| try: | |
| subscription_data = json.loads(request.body) | |
| user = request.user | |
| pushUser = PushSubscription.objects.filter(user=user).first() | |
| if pushUser: | |
| pushUser.endpoint = subscription_data["endpoint"] | |
| pushUser.p256dh = subscription_data["keys"]["p256dh"] | |
| pushUser.auth = subscription_data["keys"]["auth"] | |
| pushUser.save() | |
| else: | |
| PushSubscription.objects.create( | |
| user=user, | |
| endpoint=subscription_data["endpoint"], | |
| p256dh=subscription_data["keys"]["p256dh"], | |
| auth=subscription_data["keys"]["auth"], | |
| ) | |
| return JsonResponse({"status": "success"}) | |
| except Exception as e: | |
| return JsonResponse({"status": "error", "message": str(e)}) | |
| def send_push_notification(subscription, message): | |
| try: | |
| webpush( | |
| subscription_info={ | |
| "endpoint": subscription.endpoint, | |
| "keys": {"p256dh": subscription.p256dh, "auth": subscription.auth}, | |
| }, | |
| data=json.dumps(message), | |
| vapid_private_key=settings.WEBPUSH_SETTINGS["VAPID_PRIVATE_KEY"], | |
| vapid_claims={ | |
| "sub": f"mailto:{settings.WEBPUSH_SETTINGS['VAPID_ADMIN_EMAIL']}" | |
| }, | |
| ) | |
| except WebPushException as e: | |
| print(f"Web push failed: {e}") | |
| def polls(request): | |
| if request.method == "GET": | |
| user = request.user | |
| polls = Poll.objects.filter(participants=user) | |
| pollArr = [] | |
| for poll in polls: | |
| # Poll verification: Remove votes from users who are not in poll participants | |
| # This ensures data integrity when displaying poll results | |
| for option in poll.options.all(): | |
| # Get all voters for this option | |
| voters_to_remove = [] | |
| for voter in option.voters.all(): | |
| if voter not in poll.participants.all(): | |
| voters_to_remove.append(voter) | |
| # Remove invalid votes | |
| if voters_to_remove: | |
| option.voters.remove(*voters_to_remove) | |
| # Use the same data structure as the POST endpoint for consistency | |
| poll_data = { | |
| "id": poll.id, | |
| "question": poll.question, | |
| "image": poll.image.url if poll.image else None, | |
| "options": [], | |
| "created_by": { | |
| "id": poll.created_by.id, | |
| "first_name": poll.created_by.first_name, | |
| "last_name": poll.created_by.last_name, | |
| "profile_image": poll.created_by.profile_image.url if poll.created_by.profile_image else None, | |
| }, | |
| "created_at": poll.created_at, | |
| } | |
| total_voters = poll.participants.count() | |
| for option in poll.options.all(): | |
| vote_count = option.voters.count() | |
| percentage = (vote_count / total_voters * 100) if total_voters > 0 else 0 | |
| poll_data["options"].append({ | |
| "id": option.id, | |
| "optionText": option.optionText, | |
| "count": vote_count, | |
| "precentage": percentage, # Note: keeping the typo for consistency | |
| "voters": [ | |
| { | |
| "id": voter.id, | |
| "first_name": voter.first_name, | |
| "last_name": voter.last_name, | |
| "profile_image": voter.profile_image.url if voter.profile_image else None, | |
| } | |
| for voter in option.voters.all() | |
| ] | |
| }) | |
| pollArr.append(poll_data) | |
| return JsonResponse({"data": pollArr}) | |
| if request.method == "POST": | |
| data = json.loads(request.body) | |
| user = request.user | |
| poll_id = data.get("poll_id") | |
| option_id = data.get("option_id") | |
| if not poll_id or not option_id: | |
| return JsonResponse( | |
| {"status": "error", "message": "Poll ID and option ID are required"} | |
| ) | |
| try: | |
| poll = Poll.objects.get(id=poll_id) | |
| option = OptionPoll.objects.get(id=option_id) | |
| # Check if user is a participant in this poll | |
| if user not in poll.participants.all(): | |
| return JsonResponse( | |
| {"status": "error", "message": "You are not a participant in this poll"} | |
| ) | |
| # Poll verification: Remove votes from users who are not in poll participants | |
| # This prevents API spamming and ensures only valid participants can vote | |
| for existing_option in poll.options.all(): | |
| # Get all voters for this option | |
| voters_to_remove = [] | |
| for voter in existing_option.voters.all(): | |
| if voter not in poll.participants.all(): | |
| voters_to_remove.append(voter) | |
| # Remove invalid votes | |
| if voters_to_remove: | |
| existing_option.voters.remove(*voters_to_remove) | |
| # Check if user has already voted for this exact option (prevent duplicate/unnecessary update) | |
| if user in option.voters.all(): | |
| # User already voted for this option, just return current poll data without error | |
| pass | |
| else: | |
| # Remove user's previous votes for this poll (if any) - allows vote changing | |
| for existing_option in poll.options.all(): | |
| if user in existing_option.voters.all(): | |
| existing_option.voters.remove(user) | |
| # Add user to the new option | |
| option.voters.add(user) | |
| # Recalculate percentages and return updated poll data | |
| poll_data = { | |
| "id": poll.id, | |
| "question": poll.question, | |
| "image": poll.image.url if poll.image else None, | |
| "options": [], | |
| "created_by": { | |
| "id": poll.created_by.id, | |
| "first_name": poll.created_by.first_name, | |
| "last_name": poll.created_by.last_name, | |
| "profile_image": poll.created_by.profile_image.url if poll.created_by.profile_image else None, | |
| }, | |
| "created_at": poll.created_at, | |
| } | |
| total_voters = poll.participants.count() | |
| for opt in poll.options.all(): | |
| vote_count = opt.voters.count() | |
| percentage = (vote_count / total_voters * 100) if total_voters > 0 else 0 | |
| poll_data["options"].append({ | |
| "id": opt.id, | |
| "optionText": opt.optionText, | |
| "count": vote_count, | |
| "precentage": percentage, # Note: keeping the typo for consistency | |
| "voters": [ | |
| { | |
| "id": voter.id, | |
| "first_name": voter.first_name, | |
| "last_name": voter.last_name, | |
| "profile_image": voter.profile_image.url if voter.profile_image else None, | |
| } | |
| for voter in opt.voters.all() | |
| ] | |
| }) | |
| return JsonResponse( | |
| { | |
| "status": "success", | |
| "message": "Vote updated successfully", | |
| "poll": poll_data | |
| } | |
| ) | |
| except Poll.DoesNotExist: | |
| return JsonResponse({"status": "error", "message": "Poll not found"}) | |
| except OptionPoll.DoesNotExist: | |
| return JsonResponse({"status": "error", "message": "Option not found"}) | |
| def voterList(request, id): | |
| user = request.user | |
| try: | |
| poll = Poll.objects.filter(participants=user).get(id=id) | |
| # Poll verification: Remove votes from users who are not in poll participants | |
| # This ensures data integrity when displaying voter lists | |
| for option in poll.options.all(): | |
| # Get all voters for this option | |
| voters_to_remove = [] | |
| for voter in option.voters.all(): | |
| if voter not in poll.participants.all(): | |
| voters_to_remove.append(voter) | |
| # Remove invalid votes | |
| if voters_to_remove: | |
| option.voters.remove(*voters_to_remove) | |
| options = poll.options.all() | |
| optionsList = [] | |
| for option in options: | |
| tempOption = {} | |
| tempOption["id"] = option.id | |
| tempOption["optionText"] = option.optionText | |
| tempOption["count"] = option.voters.count() | |
| tempOption["voters"] = [] | |
| for voter in option.voters.all(): | |
| tempOption["voters"].append( | |
| { | |
| "id": voter.id, | |
| "first_name": voter.first_name, | |
| "last_name": voter.last_name, | |
| "profile_image": voter.profile_image.url if voter.profile_image else None, | |
| } | |
| ) | |
| optionsList.append(tempOption) | |
| return JsonResponse({"data": optionsList}) | |
| except Poll.DoesNotExist: | |
| return JsonResponse( | |
| {"error": "Poll may not exist or you may not have access to it"} | |
| ) | |
| def create_poll(request): | |
| try: | |
| user = request.user | |
| # Check if user is authorized to create polls (superadmin, regionadmin or karyakarta) | |
| if user.user_type not in ["superadmin", "regionadmin", "karyakarta"]: | |
| return JsonResponse( | |
| {"status": "error", "message": "You are not authorized to create polls"} | |
| ) | |
| question = request.POST.get("question") | |
| image = request.FILES.get("image") | |
| options = json.loads(request.POST.get("options", "[]")) | |
| participants = json.loads(request.POST.get("participants", "[]")) | |
| delivery_type = request.POST.get("delivery_type", "all") | |
| if not question: | |
| return JsonResponse( | |
| {"status": "error", "message": "Question is required"} | |
| ) | |
| if not options or len(options) < 2: | |
| return JsonResponse( | |
| {"status": "error", "message": "At least 2 options are required"} | |
| ) | |
| # Create the poll | |
| poll = Poll.objects.create( | |
| question=question, | |
| created_by=user, | |
| image=image if image else None | |
| ) | |
| # Add options | |
| for option_text in options: | |
| if option_text.strip(): # Only add non-empty options | |
| option = OptionPoll.objects.create(optionText=option_text.strip()) | |
| poll.options.add(option) | |
| # Determine participants based on delivery_type | |
| participant_users = [] | |
| if delivery_type == "all": | |
| participant_users = Bhagat.objects.all() | |
| elif delivery_type == "region": | |
| region_id = participants[0] if isinstance(participants, list) and len(participants) > 0 else participants | |
| participant_users = Bhagat.objects.filter(region_id=region_id) | |
| elif delivery_type == "usertype": | |
| user_type = participants[0] if isinstance(participants, list) and len(participants) > 0 else participants | |
| participant_users = Bhagat.objects.filter(user_type=user_type) | |
| elif delivery_type == "individualuser": | |
| participant_ids = [p if isinstance(p, int) else p.get('id') for p in participants] | |
| participant_users = Bhagat.objects.filter(id__in=participant_ids) | |
| # Add participants to poll | |
| if participant_users: | |
| poll.participants.set(participant_users) | |
| # Ensure creator is a participant | |
| if user not in poll.participants.all(): | |
| poll.participants.add(user) | |
| poll.save() | |
| return JsonResponse( | |
| { | |
| "status": "success", | |
| "message": "Poll created successfully", | |
| "poll_id": poll.id, | |
| "participants_count": poll.participants.count() | |
| } | |
| ) | |
| except Exception as e: | |
| return JsonResponse({"status": "error", "message": str(e)}) | |
| def edit_poll(request, poll_id): | |
| """ | |
| Edit a poll (only the creator can edit their own poll) | |
| """ | |
| try: | |
| user = request.user | |
| # Get the poll | |
| poll = Poll.objects.get(id=poll_id) | |
| # Check if user is the creator of the poll | |
| if poll.created_by.id != user.id: | |
| return JsonResponse( | |
| {"status": "error", "message": "You are not authorized to edit this poll"} | |
| ) | |
| # Get updated data | |
| question = request.POST.get("question") | |
| image = request.FILES.get("image") | |
| options = json.loads(request.POST.get("options", "[]")) | |
| participants = json.loads(request.POST.get("participants", "[]")) | |
| delivery_type = request.POST.get("delivery_type", "all") | |
| remove_image = request.POST.get("remove_image", "false") == "true" | |
| # Update question | |
| if question: | |
| poll.question = question | |
| # Handle image update/removal | |
| if remove_image and poll.image: | |
| poll.image.delete() | |
| poll.image = None | |
| elif image: | |
| # Delete old image if exists | |
| if poll.image: | |
| poll.image.delete() | |
| poll.image = image | |
| # Update options if provided | |
| if options and len(options) >= 2: | |
| # Get existing options | |
| existing_options = list(poll.options.all()) | |
| # Clear all current options | |
| poll.options.clear() | |
| # Delete old option objects | |
| for old_option in existing_options: | |
| old_option.delete() | |
| # Create new options | |
| for option_text in options: | |
| if option_text.strip(): | |
| option = OptionPoll.objects.create(optionText=option_text.strip()) | |
| poll.options.add(option) | |
| # Update participants if provided | |
| if delivery_type: | |
| participant_users = [] | |
| if delivery_type == "all": | |
| participant_users = Bhagat.objects.all() | |
| elif delivery_type == "region": | |
| region_id = participants[0] if isinstance(participants, list) and len(participants) > 0 else participants | |
| participant_users = Bhagat.objects.filter(region_id=region_id) | |
| elif delivery_type == "usertype": | |
| user_type = participants[0] if isinstance(participants, list) and len(participants) > 0 else participants | |
| participant_users = Bhagat.objects.filter(user_type=user_type) | |
| elif delivery_type == "individualuser": | |
| participant_ids = [p if isinstance(p, int) else p.get('id') for p in participants] | |
| participant_users = Bhagat.objects.filter(id__in=participant_ids) | |
| # Update participants | |
| if participant_users: | |
| poll.participants.set(participant_users) | |
| # Ensure creator is a participant | |
| if user not in poll.participants.all(): | |
| poll.participants.add(user) | |
| poll.save() | |
| # Return updated poll data | |
| poll_data = { | |
| "id": poll.id, | |
| "question": poll.question, | |
| "image": poll.image.url if poll.image else None, | |
| "options": [], | |
| "created_by": { | |
| "id": poll.created_by.id, | |
| "first_name": poll.created_by.first_name, | |
| "last_name": poll.created_by.last_name, | |
| "profile_image": poll.created_by.profile_image.url if poll.created_by.profile_image else None, | |
| }, | |
| "created_at": poll.created_at, | |
| } | |
| total_voters = poll.participants.count() | |
| for opt in poll.options.all(): | |
| vote_count = opt.voters.count() | |
| percentage = (vote_count / total_voters * 100) if total_voters > 0 else 0 | |
| poll_data["options"].append({ | |
| "id": opt.id, | |
| "optionText": opt.optionText, | |
| "count": vote_count, | |
| "precentage": percentage, | |
| "voters": [ | |
| { | |
| "id": voter.id, | |
| "first_name": voter.first_name, | |
| "last_name": voter.last_name, | |
| "profile_image": voter.profile_image.url if voter.profile_image else None, | |
| } | |
| for voter in opt.voters.all() | |
| ] | |
| }) | |
| return JsonResponse( | |
| { | |
| "status": "success", | |
| "message": "Poll updated successfully", | |
| "poll": poll_data | |
| } | |
| ) | |
| except Poll.DoesNotExist: | |
| return JsonResponse({"status": "error", "message": "Poll not found"}) | |
| except Exception as e: | |
| return JsonResponse({"status": "error", "message": str(e)}) | |
| def delete_poll(request, poll_id): | |
| """ | |
| Delete a poll (only the creator can delete their own poll) | |
| """ | |
| try: | |
| user = request.user | |
| # Get the poll | |
| poll = Poll.objects.get(id=poll_id) | |
| # Check if user is the creator of the poll | |
| if poll.created_by.id != user.id: | |
| return JsonResponse( | |
| {"status": "error", "message": "You are not authorized to delete this poll"} | |
| ) | |
| # Delete the poll image if it exists | |
| if poll.image: | |
| poll.image.delete() | |
| # Delete all options associated with the poll | |
| for option in poll.options.all(): | |
| option.delete() | |
| # Delete the poll itself | |
| poll.delete() | |
| return JsonResponse( | |
| { | |
| "status": "success", | |
| "message": "Poll deleted successfully" | |
| } | |
| ) | |
| except Poll.DoesNotExist: | |
| return JsonResponse({"status": "error", "message": "Poll not found"}) | |
| except Exception as e: | |
| return JsonResponse({"status": "error", "message": str(e)}) | |
| def bookList(request): | |
| books = Books.objects.all().order_by("index") | |
| bookArr = [] | |
| for book in books: | |
| bookArr.append( | |
| { | |
| "id": book.id, | |
| "urlId": book.urlId, | |
| "title": book.title, | |
| "author": book.author, | |
| "description": book.description, | |
| "poster": book.poster.url if book.poster else None, | |
| "pdf": book.pdf.url if book.pdf else None, | |
| "isPdf": book.isPdf, | |
| "hasSections": book.hasSections, | |
| } | |
| ) | |
| return JsonResponse({"books": bookArr}) | |
| def bookDetail(request, urlId): | |
| book = Books.objects.filter(urlId=urlId).first() | |
| if not book: | |
| return JsonResponse({"error": "Book not found"}, status=404) | |
| sections = [] | |
| if book.hasSections: | |
| bookSections = Sections.objects.filter(book=book) | |
| for section in bookSections: | |
| chapters = [] | |
| bookChapters = Chapters.objects.filter(section=section) | |
| for chapter in bookChapters: | |
| chapters.append( | |
| { | |
| "id": chapter.id, | |
| "urlId": chapter.urlId, | |
| "data": chapter.data, | |
| "title": chapter.title, | |
| } | |
| ) | |
| sections.append( | |
| {"id": section.id, "title": section.title, "chapters": chapters} | |
| ) | |
| return JsonResponse( | |
| { | |
| "book": { | |
| "id": book.id, | |
| "urlId": book.urlId, | |
| "title": book.title, | |
| "author": book.author, | |
| "description": book.description, | |
| "poster": book.poster.url if book.poster else None, | |
| "pdf": book.pdf.url if book.pdf else None, | |
| "isPdf": book.isPdf, | |
| "hasSections": book.hasSections, | |
| "sections": sections if book.hasSections else None, | |
| } | |
| } | |
| ) | |
| def bookChapterDetail(request, urlId, chapterId): | |
| book = Books.objects.filter(urlId=urlId).first() | |
| chapter = Chapters.objects.filter(urlId=chapterId, book=book).first() | |
| if not chapter: | |
| return JsonResponse({"error": "Chapter not found"}, status=404) | |
| return JsonResponse( | |
| { | |
| "chapter": { | |
| "id": chapter.id, | |
| "urlId": chapter.urlId, | |
| "title": chapter.title, | |
| "data": chapter.data, | |
| "book": { | |
| "id": chapter.book.id, | |
| "title": chapter.book.title, | |
| "author": chapter.book.author, | |
| "poster": chapter.book.poster.url if chapter.book.poster else None, | |
| "pdf": chapter.book.pdf.url if chapter.book.pdf else None, | |
| }, | |
| } | |
| } | |
| ) | |
| def data(request): | |
| with open("swamini_vato_data.json", "r", encoding="utf-8") as file: | |
| data = json.load(file) | |
| book = Books.objects.get(id=1) | |
| i = 1 | |
| for section in data: | |
| section_obj = Sections.objects.create(title=section["section_title_gu"], urlId=section["section_title_gu"].lower().replace(" ", "-").replace("(", "").replace(")", "").replace("/", "-"), isPdf=False, book=book, hasChapters=True) | |
| for vato in section["chapter"]: | |
| Chapters.objects.create( | |
| section=section_obj, | |
| book=book, | |
| title=vato["gujarati_title"], | |
| urlId=str(i), | |
| data=vato, | |
| isPdf=False, | |
| ) | |
| i = i + 1 | |
| print(f"Added vato: {vato['gujarati_title']}") | |
| print(f"Added section: {section['section_title_gu']}") | |
| return JsonResponse({"data": ""}) | |
| def gallery_list(request): | |
| """ | |
| Get gallery images for the current user based on their region and user type. | |
| Returns today's images, or if not available, the most recent previous day's images. | |
| """ | |
| user = request.user | |
| today = timezone.now().date() | |
| # Build base query based on user type and region | |
| if user.user_type == "superadmin": | |
| base_query = Gallery.objects.all() | |
| elif user.user_type == "regionadmin": | |
| base_query = Gallery.objects.filter(region=user.region) | |
| else: | |
| # Regular users see images from their region | |
| base_query = Gallery.objects.filter( | |
| Q(region=user.region) | Q(region__name="All") | |
| ) | |
| # First, try to get today's images | |
| gallery_images = base_query.filter(date=today).order_by('-uploaded_at') | |
| # If no images for today, get the most recent previous day's images | |
| if not gallery_images.exists(): | |
| # Get the most recent date with images | |
| latest_date = base_query.values_list('date', flat=True).order_by('-date').first() | |
| if latest_date: | |
| gallery_images = base_query.filter(date=latest_date).order_by('-uploaded_at') | |
| gallery_arr = [] | |
| for image in gallery_images: | |
| gallery_arr.append({ | |
| "id": image.id, | |
| "image": image.image.url if image.image else None, | |
| "date": image.date.strftime("%B %d, %Y"), | |
| "region": image.region.name if image.region else None, | |
| "uploaded_at": image.uploaded_at.strftime("%b %d, %Y | %I:%M %p") | |
| }) | |
| return JsonResponse({"gallery": gallery_arr}) | |
| def gallery_all_list(request): | |
| """ | |
| Get all gallery images for the current user based on their region and user type. | |
| Returns all images in chronological order (newest first). | |
| """ | |
| user = request.user | |
| # Build base query based on user type and region | |
| if user.user_type == "superadmin": | |
| base_query = Gallery.objects.all() | |
| elif user.user_type == "regionadmin": | |
| base_query = Gallery.objects.filter(region=user.region) | |
| else: | |
| # Regular users see images from their region | |
| base_query = Gallery.objects.filter( | |
| Q(region=user.region) | Q(region__name="All") | |
| ) | |
| # Get all images ordered by upload date (newest first) | |
| gallery_images = base_query.order_by('-uploaded_at') | |
| gallery_arr = [] | |
| for image in gallery_images: | |
| gallery_arr.append({ | |
| "id": image.id, | |
| "image": image.image.url if image.image else None, | |
| "date": image.date.strftime("%B %d, %Y"), | |
| "region": image.region.name if image.region else None, | |
| "uploaded_at": image.uploaded_at.strftime("%b %d, %Y | %I:%M %p") | |
| }) | |
| return JsonResponse({"gallery": gallery_arr}) | |
| def upload_gallery_image(request): | |
| """ | |
| Upload new gallery image (only for regionadmin and superadmin) | |
| """ | |
| user = request.user | |
| # Check if user is authorized to upload images | |
| if user.user_type not in ["superadmin", "regionadmin"]: | |
| return JsonResponse({ | |
| "status": "error", | |
| "message": "You are not authorized to upload gallery images" | |
| }) | |
| try: | |
| # Handle bulk image upload | |
| images = request.FILES.getlist('images') | |
| if not images: | |
| return JsonResponse({ | |
| "status": "error", | |
| "message": "At least one image is required" | |
| }) | |
| uploaded_images = [] | |
| today = timezone.now().date() | |
| # Create gallery entries for each image with today's date | |
| for image in images: | |
| gallery_image = Gallery.objects.create( | |
| image=image, | |
| region=user.region, | |
| date=today | |
| ) | |
| uploaded_images.append({ | |
| "id": gallery_image.id, | |
| "image": gallery_image.image.url if gallery_image.image else None, | |
| "date": gallery_image.date.strftime("%B %d, %Y"), | |
| "region": gallery_image.region.name if gallery_image.region else None, | |
| "uploaded_at": gallery_image.uploaded_at.strftime("%b %d, %Y | %I:%M %p") | |
| }) | |
| return JsonResponse({ | |
| "status": "success", | |
| "message": f"Successfully uploaded {len(uploaded_images)} images", | |
| "images": uploaded_images | |
| }) | |
| except Exception as e: | |
| return JsonResponse({ | |
| "status": "error", | |
| "message": str(e) | |
| }) | |
| def delete_gallery_image(request, image_id): | |
| """ | |
| Delete gallery image (only for superadmin or the uploader) | |
| """ | |
| user = request.user | |
| try: | |
| gallery_image = Gallery.objects.get(id=image_id) | |
| # Check permissions: superadmin can delete any, regionadmin can delete their own | |
| if user.user_type != "superadmin" and gallery_image.uploaded_by != user: | |
| return JsonResponse({ | |
| "status": "error", | |
| "message": "You are not authorized to delete this image" | |
| }) | |
| # Delete the image file | |
| if gallery_image.image: | |
| gallery_image.image.delete() | |
| # Delete the gallery entry | |
| gallery_image.delete() | |
| return JsonResponse({ | |
| "status": "success", | |
| "message": "Gallery image deleted successfully" | |
| }) | |
| except Gallery.DoesNotExist: | |
| return JsonResponse({ | |
| "status": "error", | |
| "message": "Gallery image not found" | |
| }) | |
| except Exception as e: | |
| return JsonResponse({ | |
| "status": "error", | |
| "message": str(e) | |
| }) | |
| def wallpaper_list(request): | |
| """ | |
| Get all wallpaper images for the current user based on their region and user type. | |
| Returns all images in chronological order (newest first). | |
| """ | |
| base_query = Wallpaper.objects.all() | |
| # Get all images ordered by upload date (newest first) | |
| wallpaper_images = base_query.order_by('-uploaded_at') | |
| wallpaper_arr = [] | |
| for image in wallpaper_images: | |
| wallpaper_arr.append({ | |
| "id": image.id, | |
| "image": image.image.url if image.image else None, | |
| "uploaded_at": image.uploaded_at.strftime("%b %d, %Y | %I:%M %p") | |
| }) | |
| return JsonResponse({"wallpaper": wallpaper_arr}) |