File size: 12,531 Bytes
c74033b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
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