|
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 |
|
|