2025-01-17 16:50:01 -05:00
from rest_framework import viewsets
from rest_framework . decorators import action
from rest_framework . permissions import IsAuthenticated
from rest_framework . response import Response
from worldtravel . models import Region , City , VisitedRegion , VisitedCity
from adventures . models import Adventure
from adventures . serializers import AdventureSerializer
import requests
2025-05-22 20:05:13 -04:00
from adventures . geocoding import reverse_geocode
2025-05-23 12:15:44 -04:00
from adventures . geocoding import extractIsoCode
2025-05-24 14:59:58 -04:00
from django . conf import settings
from adventures . geocoding import search_google , search_osm
2025-01-17 16:50:01 -05:00
class ReverseGeocodeViewSet ( viewsets . ViewSet ) :
permission_classes = [ IsAuthenticated ]
@action ( detail = False , methods = [ ' get ' ] )
def reverse_geocode ( self , request ) :
lat = request . query_params . get ( ' lat ' , ' ' )
lon = request . query_params . get ( ' lon ' , ' ' )
2025-05-22 20:05:13 -04:00
if not lat or not lon :
return Response ( { " error " : " Latitude and longitude are required " } , status = 400 )
2025-01-17 16:50:01 -05:00
try :
2025-05-22 20:05:13 -04:00
lat = float ( lat )
lon = float ( lon )
except ValueError :
return Response ( { " error " : " Invalid latitude or longitude " } , status = 400 )
data = reverse_geocode ( lat , lon , self . request . user )
if ' error ' in data :
2025-05-23 23:13:31 -04:00
return Response ( { " error " : " An internal error occurred while processing the request " } , status = 400 )
2025-05-22 20:05:13 -04:00
return Response ( data )
2025-05-24 14:12:06 -04:00
@action ( detail = False , methods = [ ' get ' ] )
def search ( self , request ) :
query = request . query_params . get ( ' query ' , ' ' )
if not query :
return Response ( { " error " : " Query parameter is required " } , status = 400 )
2025-05-24 14:59:58 -04:00
2025-05-24 14:12:06 -04:00
try :
2025-05-24 14:59:58 -04:00
if getattr ( settings , ' GOOGLE_MAPS_API_KEY ' , None ) :
results = search_google ( query )
else :
results = search_osm ( query )
return Response ( results )
2025-05-24 18:08:58 -04:00
except Exception :
return Response ( { " error " : " An internal error occurred while processing the request " } , status = 500 )
2025-01-17 16:50:01 -05:00
@action ( detail = False , methods = [ ' post ' ] )
2025-06-05 14:53:08 -04:00
def mark_visited_region ( self , request ) :
2025-01-17 16:50:01 -05:00
# searches through all of the users adventures, if the serialized data is_visited, is true, runs reverse geocode on the adventures and if a region is found, marks it as visited. Use the extractIsoCode function to get the region
new_region_count = 0
new_regions = { }
new_city_count = 0
new_cities = { }
adventures = Adventure . objects . filter ( user_id = self . request . user )
serializer = AdventureSerializer ( adventures , many = True )
for adventure , serialized_adventure in zip ( adventures , serializer . data ) :
if serialized_adventure [ ' is_visited ' ] == True :
lat = adventure . latitude
lon = adventure . longitude
if not lat or not lon :
continue
2025-06-05 14:53:08 -04:00
2025-05-25 22:13:18 -04:00
# Use the existing reverse_geocode function which handles both Google and OSM
data = reverse_geocode ( lat , lon , self . request . user )
if ' error ' in data :
continue
2025-06-05 14:53:08 -04:00
# data already contains region_id and city_id
if ' region_id ' in data and data [ ' region_id ' ] is not None :
region = Region . objects . filter ( id = data [ ' region_id ' ] ) . first ( )
2025-01-17 16:50:01 -05:00
visited_region = VisitedRegion . objects . filter ( region = region , user_id = self . request . user ) . first ( )
if not visited_region :
visited_region = VisitedRegion ( region = region , user_id = self . request . user )
visited_region . save ( )
new_region_count + = 1
new_regions [ region . id ] = region . name
2025-06-05 14:53:08 -04:00
if ' city_id ' in data and data [ ' city_id ' ] is not None :
city = City . objects . filter ( id = data [ ' city_id ' ] ) . first ( )
visited_city = VisitedCity . objects . filter ( city = city , user_id = self . request . user ) . first ( )
if not visited_city :
visited_city = VisitedCity ( city = city , user_id = self . request . user )
visited_city . save ( )
new_city_count + = 1
new_cities [ city . id ] = city . name
2025-01-17 16:50:01 -05:00
return Response ( { " new_regions " : new_region_count , " regions " : new_regions , " new_cities " : new_city_count , " cities " : new_cities } )