| from googleapiclient.discovery import build |
| from datetime import datetime, timedelta |
| from utils.auth import authenticate_google_services |
|
|
| class GoogleCalendar_Agent: |
| def __init__(self, creds=None, timezone="Asia/Taipei"): |
| if not creds: |
| creds = authenticate_google_services() |
| self.service = build("calendar", "v3", credentials=creds) |
| self.timezone = timezone |
|
|
| def list_events(self, n: int=5, queries=None) -> str: |
| now = datetime.utcnow().isoformat() + 'Z' |
| events_result = self.service.events().list( |
| calendarId='primary', |
| timeMin=now, |
| maxResults=n, |
| singleEvents=True, |
| orderBy='startTime' |
| ).execute() |
| events = events_result.get('items', []) |
| if not events: |
| return "🔕 找不到即將到來的行事曆事件。" |
| output = "📅 您接下來的行事曆事件如下:\n" |
| for event in events: |
| start = event['start'].get('dateTime', event['start'].get('date')) |
| summary = event.get('summary', 'No title') |
| output += f"• {summary} at {start}\n" |
| return output |
|
|
| def create_event(self, |
| summary: str, |
| start_time: str, |
| end_time: str, |
| location: str = None, |
| description: str = None, |
| attendees: list = None, |
| reminder_minutes: int = None) -> str: |
| event = { |
| 'summary': summary, |
| 'start': {'dateTime': start_time, 'timeZone': self.timezone}, |
| 'end': {'dateTime': end_time, 'timeZone': self.timezone} |
| } |
| if location: |
| event['location'] = location |
| if description: |
| event['description'] = description |
| if attendees: |
| event['attendees'] = [{'email': email} for email in attendees] |
| if reminder_minutes: |
| event['reminders'] = { |
| 'useDefault': False, |
| 'overrides': [{'method': 'popup', 'minutes': reminder_minutes}] |
| } |
| try: |
| created_event = self.service.events().insert( |
| calendarId='primary', |
| sendUpdates='all', |
| body=event |
| ).execute() |
| return f"""✅ 已成功建立事件:\n標題 : {summary}\n開始時間 : {start_time}\n結束時間 : {end_time}\n地點 : {location or '無'}\n說明 : {description or '無'}\n參與者 : {', '.join(attendees) if attendees else '無'}\n提醒時間 : {reminder_minutes if reminder_minutes is not None else '使用預設提醒'}\n時區 : {self.timezone}\n事件連結 : {created_event.get('htmlLink')}""" |
| except Exception as e: |
| return f"❌ 建立事件失敗,以下是錯誤訊息(英文): {e}" |
|
|
| def find_event(self, query: str,) -> list: |
| now = datetime.utcnow().isoformat() + 'Z' |
| events_result = self.service.events().list( |
| calendarId='primary', |
| timeMin=now, |
| singleEvents=True, |
| orderBy='startTime', |
| q=query |
| ).execute() |
| return events_result.get('items', []) |
|
|
| def update_event(self, query: str, |
| new_summary=None, |
| new_location=None, |
| new_description=None, |
| new_start=None, |
| new_end=None, |
| new_attendees=None, |
| reminder_minutes=None): |
| events = self.find_event(query) |
| if not events: |
| return f"❌ 找不到包含「{query}」的事件" |
| if all(arg is None for arg in [ |
| new_summary, new_location, new_description, |
| new_start, new_end, new_attendees, reminder_minutes |
| ]): |
| return f"⚠️ 沒有指定任何要更新的欄位,未執行更新。" |
| for event in events: |
| event_id = event['id'] |
| try: |
| if new_summary: |
| event['summary'] = new_summary |
| if new_location: |
| event['location'] = new_location |
| if new_description: |
| event['description'] = new_description |
| if new_attendees: |
| event['attendees'] = [{'email': email} for email in new_attendees] |
| if reminder_minutes: |
| event['reminders'] = { |
| 'useDefault': False, |
| 'overrides': [{'method': 'popup', 'minutes': reminder_minutes}] |
| } |
| if new_start or new_end: |
| event['start']['dateTime'] = new_start |
| event['end']['dateTime'] = new_end |
| event['start']['timeZone'] = 'Asia/Taipei' |
| event['end']['timeZone'] = 'Asia/Taipei' |
| updated_event = self.service.events().update( |
| calendarId='primary', |
| eventId=event_id, |
| sendUpdates='all', |
| body=event |
| ).execute() |
| return f"✅ 已成功更新事件:{updated_event['summary']}" |
| except Exception as e: |
| return f"❌ 更新事件失敗,以下是錯誤訊息(英文): {e}" |
|
|
| def delete_event(self, query: str): |
| now = datetime.utcnow().isoformat() + 'Z' |
| event_results = self.find_event(query) |
| if len(event_results) == 0: |
| return f"❌ 找不到包含「{query}」的事件" |
| for event in event_results: |
| target_id = event["id"] |
| try: |
| self.service.events().delete( |
| calendarId='primary', |
| eventId=target_id, |
| sendUpdates='all' |
| ).execute() |
| return f"🗑️ 已刪除事件:{event['summary']}(ID: {target_id})" |
| except Exception as e: |
| return f"❌ 刪除事件失敗(ID: {target_id}),以下是錯誤訊息(英文): {e}" |
|
|
| def get_event_details(self, query: str): |
| events = self.find_event(query) |
| if not events: |
| return f"❌ 找不到符合 '{query}' 的事件!" |
| event = events[0] |
| summary = event.get('summary', 'No Title') |
| start_time = event['start'].get('dateTime', event['start'].get('date')) |
| end_time = event['end'].get('dateTime', event['end'].get('date')) |
| formatted_string = f"事件: {summary}\n開始時間: {start_time}\n結束時間: {end_time}" |
| attendees = event.get('attendees', []) |
| emails = [attendee.get('email') for attendee in attendees if attendee.get('email')] |
| if emails: |
| formatted_string += f"\n參與者: {', '.join(emails)}" |
| else: |
| formatted_string += "\n無參與者" |
| return formatted_string |
|
|
| def get_all_tools(self): |
| LLM_tools = [] |
| LLM_tools.append({ |
| "name": "create_Calendar_event", |
| "description": "Create a new Google Calendar event by specifying summary, start time, and end time, and optionally location, description, attendees, and reminder.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "summary": { |
| "type": "string", |
| "description": "Title or summary of the event (e.g., 'Lunch with Alice')" |
| }, |
| "start_time": { |
| "type": "string", |
| "format": "date-time", |
| "description": "Start time of the event in ISO format (e.g., '2025-07-01T14:00:00')" |
| }, |
| "end_time": { |
| "type": "string", |
| "format": "date-time", |
| "description": "End time of the event in ISO format (e.g., '2025-07-01T15:00:00')" |
| }, |
| "location": { |
| "type": "string", |
| "description": "Location of the event (e.g., 'Taipei 101')" |
| }, |
| "description": { |
| "type": "string", |
| "description": "Detailed description of the event" |
| }, |
| "attendees": { |
| "type": "array", |
| "items": {"type": "string"}, |
| "description": "List of email addresses to invite to the event" |
| }, |
| "reminder_minutes": { |
| "type": "integer", |
| "description": "Number of minutes before the event to trigger a popup reminder" |
| } |
| }, |
| "required": ["summary", "start_time", "end_time"] |
| }, |
| }) |
| LLM_tools.append({ |
| "name": "list_Calendar_events", |
| "description": "List your upcoming Google Calendar events.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "n": { |
| "type": "integer", |
| "default": 5, |
| "description": "Number of upcoming events to list (default: 5)" |
| } |
| } |
| } |
| }) |
| LLM_tools.append({ |
| "name": "update_Calendar_event", |
| "description": "Update a Google Calendar event using a keyword query to find it. You can update summary, location, description, start/end time, attendees, or reminders.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "query": { |
| "type": "string", |
| "description": "Keyword to find the event to update (e.g., 'meeting with Bob')" |
| }, |
| "new_summary": { |
| "type": "string", |
| "description": "New summary/title for the event" |
| }, |
| "new_location": { |
| "type": "string", |
| "description": "New location for the event" |
| }, |
| "new_description": { |
| "type": "string", |
| "description": "New description for the event" |
| }, |
| "new_start": { |
| "type": "string", |
| "format": "date-time", |
| "description": "New start time in ISO format" |
| }, |
| "new_end": { |
| "type": "string", |
| "format": "date-time", |
| "description": "New end time in ISO format" |
| }, |
| "new_attendees": { |
| "type": "array", |
| "items": {"type": "string"}, |
| "description": "New list of attendees (email addresses)" |
| }, |
| "reminder_minutes": { |
| "type": "integer", |
| "description": "Updated popup reminder time in minutes" |
| } |
| }, |
| "required": ["query"] |
| } |
| }) |
| LLM_tools.append({ |
| "name": "delete_Calendar_event", |
| "description": "Delete a Google Calendar event using a keyword query to find it.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "query": { |
| "type": "string", |
| "description": "Keyword to find the event to delete (e.g., 'meeting with Bob')" |
| } |
| }, |
| "required": ["query"] |
| } |
| }) |
| LLM_tools.append({ |
| "name": "get_event_details", |
| "description": "Find the attendee email addresses and the summary of a specific event, based on a keyword.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "query": { |
| "type": "string", |
| "description": "Keyword to find the event and extract attendees and summary of that event." |
| } |
| }, |
| "required": ["query"] |
| } |
| }) |
| return LLM_tools |
|
|