2024-04-02 14:59:03 -04:00
import datetime
import logging
import typing
from django . conf import settings
from google . oauth2 . credentials import Credentials
from googleapiclient . discovery import build
2024-05-09 13:16:46 -03:00
from googleapiclient . errors import HttpError
2024-04-02 14:59:03 -04:00
2024-04-02 16:10:16 -04:00
from apps . google import constants , utils
from apps . google . types import GoogleCalendarEvent as GoogleCalendarEventType
2024-04-02 14:59:03 -04:00
logger = logging . getLogger ( __name__ )
logger . setLevel ( logging . DEBUG )
2024-04-02 16:10:16 -04:00
class GoogleCalendarEvent :
def __init__ ( self , event : GoogleCalendarEventType ) :
self . raw_event = event
self . _start_time = utils . datetime_strptime ( event [ " start " ] [ " dateTime " ] )
self . _end_time = utils . datetime_strptime ( event [ " end " ] [ " dateTime " ] )
self . start_time_utc = self . _start_time . astimezone ( datetime . timezone . utc )
self . end_time_utc = self . _end_time . astimezone ( datetime . timezone . utc )
2024-05-09 13:16:46 -03:00
class GoogleCalendarHTTPError ( Exception ) :
def __init__ ( self , http_error ) - > None :
self . error = http_error
2024-04-02 14:59:03 -04:00
class GoogleCalendarAPIClient :
MAX_NUMBER_OF_CALENDAR_EVENTS_TO_FETCH = 250
"""
By default the value is 250 events . The page size can never be larger than 2500 events
"""
CALENDAR_ID = " primary "
"""
for right now we only consider the user ' s primary calendar. If in the future we
want to allow the user to specify a different calendar , we ' d need to [retrieve all their calendars](https://developers.google.com/calendar/v3/reference/calendarList/list)
, display this list to them + perist their choice
See ` calendarId ` under the " Parameters " section [ here ] ( https : / / developers . google . com / calendar / api / v3 / reference / events / list )
"""
def __init__ ( self , access_token : str , refresh_token : str ) :
"""
https : / / developers . google . com / calendar / api / quickstart / python
https : / / google - auth . readthedocs . io / en / stable / reference / google . oauth2 . credentials . html
"""
credentials = Credentials (
token = access_token ,
refresh_token = refresh_token ,
token_uri = " https://www.googleapis.com/oauth2/v3/token " ,
client_id = settings . SOCIAL_AUTH_GOOGLE_OAUTH2_KEY ,
client_secret = settings . SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET ,
)
self . service = build ( " calendar " , " v3 " , credentials = credentials )
def fetch_out_of_office_events ( self ) - > typing . List [ GoogleCalendarEvent ] :
"""
https : / / developers . google . com / calendar / api / v3 / reference / events / list
"""
logger . info (
f " GoogleCalendarAPIClient - Getting the upcoming { self . MAX_NUMBER_OF_CALENDAR_EVENTS_TO_FETCH } "
" out of office events "
)
2024-04-02 16:10:16 -04:00
now = datetime . datetime . now ( datetime . UTC )
time_min = utils . datetime_strftime ( now )
time_max = utils . datetime_strftime (
now + datetime . timedelta ( days = constants . DAYS_IN_FUTURE_TO_CONSIDER_OUT_OF_OFFICE_EVENTS )
)
2024-05-09 13:16:46 -03:00
try :
events_result = (
self . service . events ( )
. list (
calendarId = self . CALENDAR_ID ,
timeMin = time_min ,
timeMax = time_max ,
maxResults = self . MAX_NUMBER_OF_CALENDAR_EVENTS_TO_FETCH ,
singleEvents = True ,
orderBy = " startTime " ,
eventTypes = " outOfOffice " ,
)
. execute ( )
2024-04-02 14:59:03 -04:00
)
2024-05-09 13:16:46 -03:00
except HttpError as e :
logger . error ( f " GoogleCalendarAPIClient - Error fetching out of office events: { e } " )
raise GoogleCalendarHTTPError ( e )
2024-04-02 16:10:16 -04:00
return [ GoogleCalendarEvent ( event ) for event in events_result . get ( " items " , [ ] ) ]