diff --git a/.env.example b/.env.example index 35655b8..c7ef4e9 100644 --- a/.env.example +++ b/.env.example @@ -2,9 +2,8 @@ TELEGRAM_BOT_TOKEN= OWNER_CHAT_ID= ADMIN_CHAT_IDS= TEAM_CHAT_IDS= -GOOGLE_CLIENT_ID= -GOOGLE_CLIENT_SECRET= -GOOGLE_REFRESH_TOKEN= +GOOGLE_SERVICE_ACCOUNT_FILE= +CALENDAR_ID= N8N_WEBHOOK_URL= OPENAI_API_KEY= TIMEZONE=America/Mexico_City diff --git a/app/calendar.py b/app/calendar.py index 6071028..a90662b 100644 --- a/app/calendar.py +++ b/app/calendar.py @@ -1,17 +1,91 @@ # app/calendar.py -def get_available_slots(): - """ - Fetches available calendar slots. - """ - print("Fetching available slots from Google Calendar...") - # TODO: Implement Google Calendar API integration - return [] +import datetime +from google.oauth2 import service_account +from googleapiclient.discovery import build +from googleapiclient.errors import HttpError +from app.config import GOOGLE_SERVICE_ACCOUNT_FILE, CALENDAR_ID -def create_event(summary, start_time, end_time, attendees): +# Set up the Calendar API +SCOPES = ["https://www.googleapis.com/auth/calendar"] +creds = service_account.Credentials.from_service_account_file( + GOOGLE_SERVICE_ACCOUNT_FILE, scopes=SCOPES +) +service = build("calendar", "v3", credentials=creds) + + +def get_available_slots( + start_time, end_time, duration_minutes=30, calendar_id=CALENDAR_ID +): + """ + Fetches available calendar slots within a given time range. + """ + try: + time_min = start_time.isoformat() + time_max = end_time.isoformat() + + freebusy_query = { + "timeMin": time_min, + "timeMax": time_max, + "timeZone": "UTC", + "items": [{"id": calendar_id}], + } + + freebusy_result = service.freebusy().query(body=freebusy_query).execute() + busy_slots = freebusy_result["calendars"][calendar_id]["busy"] + + # Create a list of all potential slots + potential_slots = [] + current_time = start_time + while current_time + datetime.timedelta(minutes=duration_minutes) <= end_time: + potential_slots.append( + ( + current_time, + current_time + datetime.timedelta(minutes=duration_minutes), + ) + ) + current_time += datetime.timedelta(minutes=duration_minutes) + + # Filter out busy slots + available_slots = [] + for slot_start, slot_end in potential_slots: + is_busy = False + for busy in busy_slots: + busy_start = datetime.datetime.fromisoformat(busy["start"]) + busy_end = datetime.datetime.fromisoformat(busy["end"]) + if max(slot_start, busy_start) < min(slot_end, busy_end): + is_busy = True + break + if not is_busy: + available_slots.append((slot_start, slot_end)) + + return available_slots + except HttpError as error: + print(f"An error occurred: {error}") + return [] + + +def create_event(summary, start_time, end_time, attendees, calendar_id=CALENDAR_ID): """ Creates a new event in the calendar. """ - print(f"Creating event: {summary}") - # TODO: Implement Google Calendar API integration - return None + event = { + "summary": summary, + "start": { + "dateTime": start_time.isoformat(), + "timeZone": "UTC", + }, + "end": { + "dateTime": end_time.isoformat(), + "timeZone": "UTC", + }, + "attendees": [{"email": email} for email in attendees], + } + try: + created_event = ( + service.events().insert(calendarId=calendar_id, body=event).execute() + ) + return created_event + except HttpError as error: + print(f"An error occurred: {error}") + return None diff --git a/app/config.py b/app/config.py index ecd6848..c8d9c9b 100644 --- a/app/config.py +++ b/app/config.py @@ -5,9 +5,8 @@ TELEGRAM_BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN") OWNER_CHAT_ID = os.getenv("OWNER_CHAT_ID") ADMIN_CHAT_IDS = os.getenv("ADMIN_CHAT_IDS", "").split(",") TEAM_CHAT_IDS = os.getenv("TEAM_CHAT_IDS", "").split(",") -GOOGLE_CLIENT_ID = os.getenv("GOOGLE_CLIENT_ID") -GOOGLE_CLIENT_SECRET = os.getenv("GOOGLE_CLIENT_SECRET") -GOOGLE_REFRESH_TOKEN = os.getenv("GOOGLE_REFRESH_TOKEN") +GOOGLE_SERVICE_ACCOUNT_FILE = os.getenv("GOOGLE_SERVICE_ACCOUNT_FILE") +CALENDAR_ID = os.getenv("CALENDAR_ID") N8N_WEBHOOK_URL = os.getenv("N8N_WEBHOOK_URL") OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") TIMEZONE = os.getenv("TIMEZONE", "America/Mexico_City") diff --git a/tasks.md b/tasks.md index 8428e7a..0dbd977 100644 --- a/tasks.md +++ b/tasks.md @@ -29,7 +29,7 @@ This file tracks the development tasks for the TalĂ­a project. ## Phase 4: Integrations -- [ ] Implement `calendar.py` for Google Calendar integration. +- [x] Implement `calendar.py` for Google Calendar integration. - [ ] Implement `llm.py` for AI-powered responses. - [ ] Implement `scheduler.py` for daily summaries.