import datetime from django.shortcuts import get_object_or_404 from django.utils import timezone from django_filters.rest_framework import DjangoFilterBackend import googlemaps from rest_framework import status, generics, mixins from rest_framework.views import APIView from django.conf import settings from accounts import resource_action from accounts.models import IAmPrincipalLocation from goodtimes import constants from django.db.models import Q, Count from taggit.models import Tag from django.utils.dateparse import parse_date from goodtimes import services from goodtimes.services import FacebookAPI, FacebookPoster, GoogleMapsservice, InstagramAPI, InstagramPoster, TwitterAPI, TwitterPoster from goodtimes.utils import ApiResponse, CapacityError from rest_framework.permissions import IsAuthenticated from rest_framework_simplejwt.authentication import JWTAuthentication from manage_cms.api.serializers import TagSerializer from manage_events.api.serializers import ( AgeGroupsSerializer, EventDateRangeSerializer, EventMasterSearchSerializer, EventMasterSerializer, CreateEventSerializer, CreateVenueSerializer, EventCategorySerializer, EventDetailSerializer, EventReviewSerializer, FreeUsageFeatureLimitSerializer, IAmPrincipalLocationSerializer, PrincipalPreferenceSerializer, VenueSerializer, EventListSerializer, ) from manage_events.models import ( AgeGroups, EventInteractionType, EventMaster, Event, EventCategory, EventPrincipalInteraction, EventReview, EventShare, EventView, Favorites, FreeUsageFeatureLimit, PrincipalPreference, Venue, ) import requests from manage_events.utils import haversine_one, update_principal_location from manage_subscriptions.models import PrincipalSubscription from .filters import EventFilter class FreeUsageFeatureLimitView(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] model = FreeUsageFeatureLimit serializer_class = FreeUsageFeatureLimitSerializer def get(self, request): obj = self.model.objects.first() serializer = self.serializer_class(obj) return ApiResponse.success( status=status.HTTP_200_OK, message=constants.SUCCESS, data=serializer.data, ) class CreateEventApi(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] def post(self, request): print("Data: ", request.data) serializer = CreateEventSerializer(data=request.data) serializer.is_valid(raise_exception=True) serializer.save(created_by=self.request.user, principal=self.request.user) # Add additional logic for handling other relationships (e.g., Venue) return ApiResponse.success( status=status.HTTP_201_CREATED, message=constants.SUCCESS, data=serializer.data, ) class EventEditAPIView(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] """ Retrieve, update or delete a event instance. """ def get_object(self, pk): try: return Event.objects.get(pk=pk) except Event.DoesNotExist: return ApiResponse.error( status=status.HTTP_400_BAD_REQUEST, message=constants.FAILURE, errors="Event not found", ) def get(self, request, pk, format=None): event = self.get_object(pk) serializer = EventDetailSerializer(event) return ApiResponse.success( status=status.HTTP_200_OK, message=constants.SUCCESS, data=serializer.data, ) def patch(self, request, pk, format=None): event = self.get_object(pk) serializer = CreateEventSerializer(event, data=request.data, partial=True) if serializer.is_valid(): serializer.save() return ApiResponse.success( status=status.HTTP_200_OK, message=constants.SUCCESS, data=serializer.data, ) return ApiResponse.error( status=status.HTTP_400_BAD_REQUEST, message=constants.FAILURE, errors=serializer.errors, ) class CreateVenueApi(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] def post(self, request): data = request.data.copy() print("prindata is ", data) # Convert latitude and longitude to float and round to 8 decimal places data["latitude"] = round(float(data["latitude"]), 8) data["longitude"] = round(float(data["longitude"]), 8) serializer = VenueSerializer(data=data, context={"request": request}) serializer.is_valid(raise_exception=True) serializer.save( created_by=self.request.user, principal=self.request.user, active=True ) # Add additional logic for handling other relationships (e.g., Venue) return ApiResponse.success( status=status.HTTP_201_CREATED, message=constants.SUCCESS, data=serializer.data, ) # # Prepare the email # subject = f"Your Event Report for {start_date.month} {start_date.year}." # body = f"Please find attached the event report for {start_date.month} {start_date.month}." # email_service = EmailService( # subject="Good Times - Report", # to=[user.email], # from_email=settings.DEFAULT_FROM_EMAIL, # ) # email_service.attach(filename, buffer.getvalue(), "application/pdf") # # Send the email # email_service.send() class VenueDeleteAPIView(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] """ API view to set a venue's 'deleted' to True and 'active' to False. """ def patch(self, request, pk): try: venue = Venue.objects.get(pk=pk) venue.deleted = True venue.active = False venue.save() return ApiResponse.success( status=status.HTTP_200_OK, message=constants.SUCCESS, data="Venue deleted successfully", ) except Venue.DoesNotExist: return ApiResponse.error( status=status.HTTP_400_BAD_REQUEST, message=constants.FAILURE, errors="Venue not found", ) class MyEventsAPIView(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] def get(self, request, *args, **kwargs): filter_type = request.query_params.get("filter", None) user = request.user params = [ "draft", "active", "active_past", "draft_past", ] if filter_type not in params: return ApiResponse.error( status=status.HTTP_400_BAD_REQUEST, message=constants.FAILURE, errors="No filter found", ) if filter_type == "draft": events = services.MyEventFilterService.filter_my_events_draft(user) elif filter_type == "active": events = services.MyEventFilterService.filter_my_events_active(user) elif filter_type == "active_past": events = services.MyEventFilterService.filter_my_events_active_past(user) elif filter_type == "draft_past": events = services.MyEventFilterService.filter_my_events_draft_past(user) else: return ApiResponse.error( status=status.HTTP_400_BAD_REQUEST, message=constants.FAILURE, errors="Invalid filter parameter", ) serializer = EventDetailSerializer( events, context={"request": request}, many=True ) # serializer = EventListSerializer( # events, context={"request": request}, many=True # ) return ApiResponse.success( status=status.HTTP_200_OK, message=constants.SUCCESS, data=serializer.data, ) class PrinciaplPreferenceEventsAPIView(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] def get(self, request, *args, **kwargs): today = timezone.now().date() try: preferences = PrincipalPreference.objects.get(principal=request.user) preferred_categories_ids = preferences.preferred_categories.values_list( "id", flat=True ) # Filter events based on user preferences and that are upcoming or ongoing events = Event.objects.filter( category__in=preferred_categories_ids, end_date__gte=today ).distinct() if not events.exists(): # If no events found based on preferences, get future events events = Event.objects.filter(start_date__gt=today) serializer = EventDetailSerializer(events, many=True) return ApiResponse.success( status=status.HTTP_200_OK, message=constants.SUCCESS, data=serializer.data, ) except PrincipalPreference.DoesNotExist: # If the user has no preferences, default to future events events = Event.objects.filter(start_date__gt=today) class EventDetailAPIView(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] def get(self, request, pk): try: event = Event.objects.get(pk=pk) interaction = services.InteractionCalculator(event) interactions = interaction.calculate() # Serialize your event data here event_data = EventDetailSerializer(event, context={"request": request}).data event_data["interactions"] = interactions return ApiResponse.success( status=status.HTTP_200_OK, message=constants.SUCCESS, data=event_data, ) except Event.DoesNotExist: return ApiResponse.error( status=status.HTTP_404_NOT_FOUND, message=constants.FAILURE, errors=constants.RECORD_NOT_FOUND, ) except CapacityError as e: return ApiResponse.error( status=status.HTTP_405_METHOD_NOT_ALLOWED, message=constants.FAILURE, errors=str(e), ) class VenueListView(generics.ListAPIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] serializer_class = VenueSerializer def get_queryset(self): # Ensures that a user sees only their venues return Venue.objects.filter( created_by=self.request.user, deleted=False, active=True ) def list(self, request, *args, **kwargs): queryset = self.get_queryset() serializer = self.get_serializer(queryset, many=True) # Customizing the response format return ApiResponse.success( status=status.HTTP_200_OK, message=constants.SUCCESS, data=serializer.data, ) class VenueDetailView(generics.RetrieveUpdateDestroyAPIView): queryset = Venue.objects.all() serializer_class = VenueSerializer authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] def get_queryset(self): # This ensures a user can only access their own venues return self.queryset.filter( created_by=self.request.user, deleted=False, active=True ) class GeocodeAPIView(APIView): authentication_classes = [] permission_classes = [] """ API View to fetch latitude and longitude for a given address using the Google Maps Geocoding API. """ def get(self, request, *args, **kwargs): # Extract 'address' from query parameters address = request.query_params.get("address") print("address: ", address) if not address: return ApiResponse.error( {"error": "Address parameter is missing."}, status=status.HTTP_400_BAD_REQUEST, ) # Call the get_lat_long method lat_long = self.get_lat_long(address) if lat_long: return ApiResponse.success( {"latitude": lat_long[0], "longitude": lat_long[1]} ) else: return ApiResponse.error( {"error": "Failed to fetch latitude and longitude."}, status=status.HTTP_404_NOT_FOUND, ) def get_lat_long(self, address): """ Fetches latitude and longitude for a given address using the Google Maps Geocoding API. """ url = "https://maps.googleapis.com/maps/api/geocode/json?" params = { "address": address, # "key": settings.GOOGLE_MAPS_API_KEY, # Replace with your actual API key "key": "AIzaSyCQv-Cfzkh3cXerrui55oId7CDHhuIImhc", # Replace with your actual API key } response = requests.get(url, params=params) if response.status_code == 200: data = response.json() if data["status"] == "OK": location = data["results"][0]["geometry"]["location"] latitude = location["lat"] longitude = location["lng"] return latitude, longitude else: print(f"Geocoding failed: {data['status']}") return None else: print(f"API request failed with status code: {response.status_code}") return None class EventCategoryListAPIView(generics.ListAPIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] queryset = EventCategory.objects.all() serializer_class = EventCategorySerializer class IAmPrincipalLocationAPIView(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] def get(self, request, *args, **kwargs): # Assuming there's a UserLocation model that stores user locations, # and it has a ForeignKey to the user model. try: user_location = IAmPrincipalLocation.objects.filter( principal=request.user ).last() print("user_location: ", user_location) serializer = IAmPrincipalLocationSerializer(user_location) return ApiResponse.success( status=status.HTTP_200_OK, message=constants.SUCCESS, data=serializer.data, ) except IAmPrincipalLocation.DoesNotExist: return ApiResponse.error( status=status.HTTP_404_NOT_FOUND, message="Location not found for the user.", errors="No location data available for the current user.", ) def post(self, request, *args, **kwargs): data = request.data.copy() # Convert latitude and longitude to float and round to 8 decimal places latitude = round(float(data["latitude"]), 15) longitude = round(float(data["longitude"]), 15) try: principal = request.user location = IAmPrincipalLocation.objects.get(principal=principal) # Update existing location location.latitude = latitude location.longitude = longitude location.save() # Update principal fields using the utility function update_principal_location(principal, latitude, longitude) serializer = IAmPrincipalLocationSerializer( location, context={"request": request} ) return ApiResponse.success( status=status.HTTP_200_OK, message=constants.SUCCESS, data=serializer.data, ) except IAmPrincipalLocation.DoesNotExist: # Create a new location object location = IAmPrincipalLocation.objects.create( principal=principal, latitude=latitude, longitude=longitude ) # Update principal fields using the utility function update_principal_location(principal, latitude, longitude) serializer = IAmPrincipalLocationSerializer( location, context={"request": request} ) return ApiResponse.success( status=status.HTTP_201_CREATED, message=constants.SUCCESS, data=serializer.data, ) except Exception as e: print(f"Error occurred while saving location: {e}") return ApiResponse.error( status=status.HTTP_500_INTERNAL_SERVER_ERROR, message=constants.FAILURE, errors=str(e), ) class PrincipalPreferenceView(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] def post(self, request, *args, **kwargs): principal = request.user # Check if the principal has a subscription if not PrincipalSubscription.has_principal_subscription(principal): # Get the preferred categories from the request data preferred_categories = request.data.get("preferred_categories", []) # Get the category limit for free usage category_limit = FreeUsageFeatureLimit.get_category_limit() # Check if the principal is an event user and has exceeded the category limit if principal.principal_type.name == resource_action.PRINCIPAL_TYPE_EVENT_USER and len(preferred_categories) > category_limit: # Create an error message indicating that a paid subscription is required error_message = f"Upgrade to paid subscription to select more than {category_limit} categories." return ApiResponse.error( status=status.HTTP_400_BAD_REQUEST, message=error_message, errors=error_message, ) serializer = PrincipalPreferenceSerializer( data=request.data, context={"request": request} ) if serializer.is_valid(): serializer.save() return ApiResponse.success( message=constants.SUCCESS, data=serializer.data, status=status.HTTP_201_CREATED, ) return ApiResponse.error( message=constants.FAILURE, errors=serializer.errors, status=status.HTTP_400_BAD_REQUEST, ) class PrincipalPreferenceDetailView(generics.RetrieveAPIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] serializer_class = PrincipalPreferenceSerializer def get_object(self): # Attempt to retrieve the authenticated user's preferences user = self.request.user obj, created = PrincipalPreference.objects.get_or_create(principal=user) return obj def retrieve(self, request, *args, **kwargs): instance = self.get_object() serializer = self.get_serializer(instance) return ApiResponse.success( data=serializer.data, message=constants.SUCCESS, status=status.HTTP_200_OK, ) class EventPreferencesView(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] model = EventCategory serializer_class = EventCategorySerializer def get(self, request, *args, **kwargs): """Get all event categories for the authenticated user.""" obj = self.model.objects.filter(active=True, deleted=False) serializer = self.serializer_class(obj, many=True, context={"request": request}) return ApiResponse.success( data=serializer.data, message=constants.SUCCESS, status=status.HTTP_200_OK ) class EventMasterSearchAPIView(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] def post(self, request, *args, **kwargs): serializer = EventMasterSearchSerializer(data=request.data) if serializer.is_valid(): title = serializer.validated_data.get("title") # Search for existing brands existing_event_master = EventMaster.objects.filter(title__icontains=title) if existing_event_master.exists(): # Return existing brands return ApiResponse.success( data=EventMasterSerializer(existing_event_master, many=True).data, message=constants.SUCCESS, status=status.HTTP_200_OK, ) else: # No brand found, return an empty list return ApiResponse.success( data=[], message="No related EventMaster Found", status=status.HTTP_200_OK, ) return ApiResponse.error( message=constants.FAILURE, errors=serializer.errors, status=status.HTTP_400_BAD_REQUEST, ) class ToggleFavoriteView(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] def post(self, request, event_id, format=None): principal = request.user event = get_object_or_404(Event, pk=event_id) favorite, created = Favorites.objects.get_or_create( principal=principal, event=event ) if not created: favorite.delete() return ApiResponse.success( data="removed", message=constants.SUCCESS, status=status.HTTP_200_OK, ) return ApiResponse.success( data="added", message=constants.SUCCESS, status=status.HTTP_201_CREATED, ) class EventStatusUpdateAPIView(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] def post(self, request, event_id): principal = ( request.user ) # Assuming you're using some form of user authentication event = get_object_or_404(Event, pk=event_id) status_requested = request.data.get("status") # 'going' or 'interested' if status_requested not in EventInteractionType.values: return ApiResponse.error( message=constants.FAILURE, errors="Invalid status provided.", status=status.HTTP_400_BAD_REQUEST, ) interaction, created = EventPrincipalInteraction.objects.update_or_create( principal=principal, event=event, defaults={"status": status_requested}, ) if created: return ApiResponse.success( data=status_requested, message=f"Marked as {status_requested}.", status=status.HTTP_201_CREATED, ) else: return ApiResponse.success( data=status_requested, message=f"Updated status to {status_requested}.", status=status.HTTP_200_OK, ) # Filter Events within 10 KMs class EventFilterByLocationAPIView(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] def get(self, request, *args, **kwargs): principal = request.user today = timezone.now().date() # Fetching user location from IAmPrincipalLocation try: user_location = IAmPrincipalLocation.objects.filter( principal=principal ).last() print("user_location: ", user_location) print("principal_user_location: ", user_location.principal) user_lat = user_location.latitude user_lon = user_location.longitude except IAmPrincipalLocation.DoesNotExist: return ApiResponse.error( errors=constants.FAILURE, message="User location not set.", status=status.HTTP_400_BAD_REQUEST, ) max_distance_km = 10 # Set your desired maximum distance current_and_future_events_query = Q( active=True, deleted=False, draft=False, created_by__is_active=True, ) & (Q(end_date__gte=today)) # Get the queryset based on the filter conditions events_queryset = Event.objects.filter(current_and_future_events_query) venue_ids = events_queryset.values_list("venue", flat=True).distinct() venues = Venue.objects.filter(id__in=venue_ids) print("venues: ", venues) venues_within_range = [] for venue in venues: if venue.longitude is None or venue.latitude is None: continue # Skip this venue if longitude or latitude is missing distance = haversine_one( user_lon, user_lat, venue.longitude, venue.latitude ) print("distance: ", distance) if distance <= max_distance_km: print( venue ) # This will print the venue object, or whatever __str__ returns for the venue model venues_within_range.append(venue.id) print("venues_within_range: ", venues_within_range) # venues_data = [venue_to_dict(venue) for venue in venues_within_range] events = events_queryset.filter(venue__id__in=venues_within_range) # Serialize and return the filtered events serializer = EventDetailSerializer( events, context={"request": request}, many=True ) return ApiResponse.success( data=serializer.data, message=constants.SUCCESS, status=status.HTTP_200_OK, ) # Filter Principal's Favorites Events class FavoriteEventsList(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] def get(self, request, *args, **kwargs): principal = request.user events = Event.objects.filter( id__in=Favorites.objects.filter(principal=principal) .select_related("event") .values_list("event_id", flat=True), deleted=False, active=True, draft=False, ) serializer = EventDetailSerializer( events, context={"request": request}, many=True ) return ApiResponse.success( data=serializer.data, message=constants.SUCCESS, status=status.HTTP_200_OK, ) class EventDateRangeAPIView(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] def get(self, request, *args, **kwargs): start_date_str = request.query_params.get("start_date") end_date_str = request.query_params.get("end_date") # Attempt to parse the dates from the query parameters start_date = parse_date(start_date_str) end_date = parse_date(end_date_str) # Validate the parsed dates if not start_date or not end_date: return ApiResponse.error( errors={ "start_date": "Invalid or missing", "end_date": "Invalid or missing", }, message=constants.FAILURE, status=status.HTTP_400_BAD_REQUEST, ) events = Event.objects.filter( Q(end_date__gte=start_date) & Q(start_date__lte=end_date) & Q(deleted=False) & Q(active=True) & Q(draft=False) ) serializer = EventDetailSerializer( events, context={"request": request}, many=True ) return ApiResponse.success( data=serializer.data, message=constants.SUCCESS, status=status.HTTP_200_OK, ) class EventReviewCreateAPIView(mixins.CreateModelMixin, generics.GenericAPIView): queryset = EventReview.objects.filter(active=True, deleted=False) serializer_class = EventReviewSerializer def post(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) if serializer.is_valid(): self.perform_create(serializer) headers = self.get_success_headers(serializer.data) return ApiResponse.success( "Review created successfully.", data=serializer.data, status=status.HTTP_201_CREATED, ) else: return ApiResponse.error( "Validation error.", errors=serializer.errors, status=status.HTTP_400_BAD_REQUEST, ) class CheckPrincipalPreference(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] def get(self, request, *args, **kwargs): try: principal = request.user exists = PrincipalPreference.objects.filter(principal=principal).exists() return ApiResponse.success( message=constants.SUCCESS, data=exists, status=status.HTTP_200_OK, ) except Exception as e: return ApiResponse.error( message=constants.FAILURE, errors=str(e), status=status.HTTP_400_BAD_REQUEST, ) # class PrincipalEventsInteractionView(APIView): # authentication_classes = [JWTAuthentication] # permission_classes = [IsAuthenticated] # def get(self, request, *args, **kwargs): # principal = self.request.user # interactions = EventPrincipalInteraction.objects.filter( # principal=principal # ).prefetch_related("event") # # Prefetch related events, sorting them by start_date # events = Event.objects.filter( # id__in=[interaction.event_id for interaction in interactions] # ).order_by("-start_date") # serializer = EventDetailSerializer( # events, context={"request": request}, many=True # ) # return ApiResponse.success( # message=constants.SUCCESS, # data=serializer.data, # status=status.HTTP_200_OK, # ) class PrincipalEventsInteractionView(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] def get(self, request, *args, **kwargs): principal = self.request.user interactions = EventPrincipalInteraction.objects.filter( principal=principal ).prefetch_related("event") favorite_events = Favorites.objects.filter( principal=principal ).prefetch_related("event") event_ids = set(interaction.event.id for interaction in interactions) | set( favorite.event.id for favorite in favorite_events ) events = Event.objects.filter(id__in=event_ids).order_by("-start_date") events = list( events ) # To ensure that the queryset is evaluated and we don't send a QuerySet object in the serializer context serializer = EventDetailSerializer( events, context={"request": request}, many=True ) return ApiResponse.success( message=constants.SUCCESS, data=serializer.data, status=status.HTTP_200_OK, ) class TagListView(generics.ListAPIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] serializer_class = TagSerializer def get_queryset(self): return Tag.objects.all().distinct() def list(self, request, *args, **kwargs): queryset = self.get_queryset() serializer = self.get_serializer(queryset, many=True) return ApiResponse.success( message=constants.SUCCESS, data=serializer.data, status=status.HTTP_200_OK, ) class CaptureEventViewAPIView(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] def post(self, request, pk): try: event = Event.objects.get(pk=pk) user = request.user location_parts = [user.city, user.state, user.country] location = " ".join(part for part in location_parts if part) EventView.objects.create(event=event, principal=user, location=location) return ApiResponse.success( message=constants.SUCCESS, data="Event view recorded successfully.", status=status.HTTP_200_OK, ) except Event.DoesNotExist: return ApiResponse.error( message=constants.FAILURE, errors="Event not found.", status=status.HTTP_400_BAD_REQUEST, ) class EventShareView(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] def post(self, request, pk): try: event = Event.objects.get(id=pk) except Event.DoesNotExist: return ApiResponse.error( message=constants.FAILURE, errors="Event not found.", status=status.HTTP_400_BAD_REQUEST, ) # Incrementing the social media shares count event.increment_shares() user = request.user # Assuming the user is authenticated EventShare.objects.create(principal=user, event=event) return ApiResponse.success( message=constants.SUCCESS, data="Event shared successfully.", status=status.HTTP_200_OK, ) class AgeGroupListView(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] serializer_class = AgeGroupsSerializer model = AgeGroups def get(self, request): queryset = self.model.objects.filter(active=True) serializer = self.serializer_class(queryset, many=True) return ApiResponse.success(message=constants.SUCCESS, data=serializer.data) class EventsCalenderAPIView(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] def get(self, request, *args, **kwargs): try: principal = request.user queryset = Event.objects.filter( active=True, draft=False, deleted=False, end_date__gte=timezone.now().date() ) # queryset = Event.objects.filter( # ((Q(active=True) & Q(draft=False) & Q(deleted=False) & Q(end_date__gte=timezone.now().date()))) # ) preferences = PrincipalPreference.objects.get(principal=principal) preferred_categories_ids = preferences.preferred_categories.values_list("id", flat=True) # Filter the queryset to only include events in the user's preferred categories queryset = queryset.filter(Q(category__in=preferred_categories_ids) | Q(principal=principal)) serializer = EventListSerializer( queryset, context={"request": request}, many=True ) return ApiResponse.success( status=status.HTTP_200_OK, message=constants.SUCCESS, data=serializer.data, ) except Exception as e: return ApiResponse.error( status=status.HTTP_400_BAD_REQUEST, message=constants.FAILURE, errors=str(e), ) class EventListView(generics.ListAPIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] serializer_class = EventListSerializer filter_backends = [DjangoFilterBackend] filterset_class = EventFilter def get_queryset(self): """ Returns a queryset of events filtered by the user's preferences and subscription status. """ principal = self.request.user # Filter the base queryset to only include active, non-draft, non-deleted events with an end date in the future queryset = Event.objects.filter( active=True, draft=False, deleted=False, end_date__gte=timezone.now().date() ) # If no filter is applied and the user does not have a subscription, # only show events that match the user's preferred categories if not self.request.query_params or not PrincipalSubscription.has_principal_subscription(principal): # Get the user's preferred categories preferences = PrincipalPreference.objects.get(principal=principal) preferred_categories_ids = preferences.preferred_categories.values_list("id", flat=True) # Filter the queryset to only include events in the user's preferred categories queryset = queryset.filter(category__in=preferred_categories_ids).order_by("start_date") return queryset def filter_queryset(self, queryset): queryset = super().filter_queryset(queryset) # Get query parameters latitude = self.request.query_params.get("latitude", "") longitude = self.request.query_params.get("longitude", "") ordering = self.request.query_params.get("sort", "") # Handle nearest location sorting if latitude and longitude and "nearest" in ordering: queryset = self.apply_nearest_filter(queryset, latitude, longitude) # Handle popularity and latest sorting queryset = self.apply_sorting(queryset, ordering) return queryset def apply_nearest_filter(self, queryset, latitude, longitude): gmaps_service = GoogleMapsservice() return gmaps_service.get_nearest_events(queryset, float(latitude), float(longitude)) def apply_sorting(self, queryset, ordering): # Split ordering fields and process each field ordering_fields = [field.lstrip("-") for field in ordering.split(",")] # Remove 'nearest' from ordering as it's handled separately if "nearest" in ordering_fields: ordering_fields.remove("nearest") ordering = ordering.replace("nearest", "") # Annotate with popularity and order it if requested if "popularity" in ordering_fields: queryset = queryset.annotate(popularity=Count("interaction_event")).order_by("-popularity") # order latest record and by default sorting if "latest" in ordering_fields: queryset = queryset.order_by("start_date") if "price" in ordering_fields: queryset = queryset.order_by('entry_fee') return queryset def get(self, request, *args, **kwargs): queryset = self.filter_queryset(self.get_queryset()) page = self.paginate_queryset(queryset) if page is not None: serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data) serializer = self.get_serializer(queryset, many=True) return ApiResponse.success(message=constants.SUCCESS, data=serializer.data) from rest_framework.response import Response class SocialMediaPostView(APIView): def get(self, request, *args, **kwargs): platform = request.query_params.get("platform", "") event_id = kwargs.get("id") print(platform, event_id) errors = [] success_messages = [] try: event = Event.objects.get(id=event_id) except Event.DoesNotExist: errors.append("Event does not exist") return Response({ 'message': "Error in posting to social media", 'errors': errors, 'success_messages': success_messages }, status=400) if not event.active: errors.append("Event is not active") return Response({ 'message': "Error in posting to social media", 'errors': errors, 'success_messages': success_messages }, status=400) caption = f"{event.title}\nDuration: {event.start_date} to {event.end_date}\nAddress: {event.venue.address}" if platform in ['instagram', 'facebook', 'twitter', 'all']: if platform in ['twitter', 'all']: image_url = event.image.path twitter_api = TwitterAPI() twitter_poster = TwitterPoster(twitter_api) result = twitter_poster.post_image_with_caption(image_url, caption) if result['success']: success_messages.append("Posted to Twitter successfully") else: errors.append("Fail to post on Twitter") image_url = request.build_absolute_uri(event.image.url) if platform in ['facebook', 'all']: facebook_api = FacebookAPI() facebook_poster = FacebookPoster(facebook_api) result = facebook_poster.post_photo(image_url, caption) if result["success"]: success_messages.append("Posted to Facebook successfully") else: errors.append("Fail to post on Facebook") if platform in ['instagram', 'all']: instagram_api = InstagramAPI() instagram_poster = InstagramPoster(instagram_api) result = instagram_poster.post_image_with_caption(image_url, caption) if result["success"]: success_messages.append("Posted to Instagram successfully") else: errors.append("Fail to post on Instagram") if not errors: return Response({'message': 'Post Successful', 'errors': errors, 'success_messages': success_messages}) if errors and success_messages: return Response({ 'message': 'Some posts succeeded while others failed', 'errors': errors, 'success_messages': success_messages }, status=200) return Response({ 'message': 'Error in posting to social media', 'errors': errors, 'success_messages': success_messages }, status=400)