BroBro87 commited on
Commit
62e41c2
·
verified ·
1 Parent(s): 5646f5c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +108 -51
app.py CHANGED
@@ -2,15 +2,12 @@ from dataclasses import dataclass
2
  from enum import Enum
3
  from typing import Optional, Dict, Any
4
  from composio_llamaindex import ComposioToolSet, App, Action
5
- from llama_index.core.agent import FunctionCallingAgentWorker
6
- from llama_index.core.llms import ChatMessage
7
- from llama_index.llms.openai import OpenAI
8
- from llama_index.llms.gemini import Gemini
9
- from dotenv import load_dotenv
10
  import gradio as gr
11
  import os
12
  import json
13
- from datetime import datetime
14
 
15
  # Load environment variables
16
  load_dotenv()
@@ -37,8 +34,85 @@ class APIResponse:
37
  class CalendarService:
38
  def __init__(self):
39
  self.toolset = ComposioToolSet(api_key=os.getenv('COMPOSIO_API_KEY'))
40
- self.llm = OpenAI(model="gpt-4o", api_key=os.getenv('OPENAI_API_KEY'))
41
  self.connections: Dict[str, Dict[str, Any]] = {}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
 
43
  def initiate_connection(self, entity_id: str, redirect_url: Optional[str] = None) -> APIResponse:
44
  try:
@@ -80,8 +154,6 @@ class CalendarService:
80
  error="No connection found for this entity ID"
81
  )
82
 
83
- # In a real implementation, you would check the actual status
84
- # For now, we'll simulate the status check
85
  connection = self.connections[entity_id]
86
 
87
  return APIResponse(
@@ -100,52 +172,37 @@ class CalendarService:
100
 
101
  def generate_wrapped(self, entity_id: str) -> APIResponse:
102
  try:
103
- tools = self.toolset.get_tools([
104
- Action.GOOGLECALENDAR_GET_CALENDAR,
105
- Action.GOOGLECALENDAR_FIND_EVENT,
106
- ])
107
 
108
- agent = FunctionCallingAgentWorker(
109
- tools=tools,
110
- llm=self.llm,
111
- prefix_messages=[
112
- ChatMessage(
113
- role="system",
114
- content="""
115
- Use all the tools including get calendar and more available to you get factual data then
116
- Generate a creative Google Calendar Wrapped summary including:
117
- 1. Total meetings this year
118
- 2. Overall time spent in meetings
119
- 3. Busiest month
120
- 4. Busiest day
121
- 5. Most frequent meeting participant
122
- 6. Average meeting duration
123
- 7. Most common meeting time
124
-
125
- Be entertaining and witty with the analysis. Conclude by assigning
126
- a Greek god persona based on their meeting patterns.
127
- Search data from last 6 months instead of a year
128
- """
129
- )
130
- ],
131
- max_function_calls=10,
132
- allow_parallel_tool_calls=False,
133
- verbose=True
134
- ).as_agent()
135
 
136
- response = agent.chat(
137
- f"Create a Calendar Wrapped summary for user with entity_id: {entity_id}. "
138
- f"Today's date is {datetime.now().isoformat()}"
139
- "Use the available Google Calendar actions to gather real data about the user's calendar usage."
140
- "calendar id is primary"
141
  )
142
 
143
- return APIResponse(
144
- success=True,
145
- data={
146
- 'wrapped_summary': str(response)
147
- }
148
- )
 
 
 
 
 
149
 
150
  except Exception as e:
151
  return APIResponse(
 
2
  from enum import Enum
3
  from typing import Optional, Dict, Any
4
  from composio_llamaindex import ComposioToolSet, App, Action
5
+ from datetime import datetime, timedelta
6
+ from collections import defaultdict, Counter
 
 
 
7
  import gradio as gr
8
  import os
9
  import json
10
+ from dotenv import load_dotenv
11
 
12
  # Load environment variables
13
  load_dotenv()
 
34
  class CalendarService:
35
  def __init__(self):
36
  self.toolset = ComposioToolSet(api_key=os.getenv('COMPOSIO_API_KEY'))
 
37
  self.connections: Dict[str, Dict[str, Any]] = {}
38
+
39
+ def analyze_calendar_events(self, response_data):
40
+ """
41
+ Analyze calendar events and return statistics about meetings.
42
+ """
43
+ current_year = datetime.now().year
44
+ meetings = []
45
+ participants = []
46
+ meeting_times = []
47
+ total_duration = timedelta()
48
+ monthly_meetings = defaultdict(int)
49
+ daily_meetings = defaultdict(int)
50
+
51
+ events = response_data.get('data', {}).get('event_data', {}).get('event_data', [])
52
+
53
+ for event in events:
54
+ start_data = event.get('start', {})
55
+ end_data = event.get('end', {})
56
+
57
+ try:
58
+ start = datetime.fromisoformat(start_data.get('dateTime').replace('Z', '+00:00'))
59
+ end = datetime.fromisoformat(end_data.get('dateTime').replace('Z', '+00:00'))
60
+
61
+ if start.year == current_year:
62
+ duration = end - start
63
+ total_duration += duration
64
+
65
+ monthly_meetings[start.strftime('%B')] += 1
66
+ daily_meetings[start.strftime('%A')] += 1
67
+ meeting_times.append(start.strftime('%H:%M'))
68
+
69
+ if 'attendees' in event:
70
+ for attendee in event['attendees']:
71
+ if attendee.get('responseStatus') != 'declined':
72
+ participants.append(attendee.get('email'))
73
+
74
+ organizer_email = event.get('organizer', {}).get('email')
75
+ if organizer_email:
76
+ participants.append(organizer_email)
77
+
78
+ meetings.append({
79
+ 'start': start,
80
+ 'duration': duration,
81
+ 'summary': event.get('summary', 'No Title')
82
+ })
83
+ except (ValueError, TypeError, AttributeError) as e:
84
+ print(f"Error processing event: {e}")
85
+ continue
86
+
87
+ total_meetings = len(meetings)
88
+ stats = {
89
+ "total_meetings_this_year": total_meetings
90
+ }
91
+
92
+ if total_meetings > 0:
93
+ stats.update({
94
+ "total_time_spent": str(total_duration),
95
+ "busiest_month": max(monthly_meetings.items(), key=lambda x: x[1])[0] if monthly_meetings else "N/A",
96
+ "busiest_day": max(daily_meetings.items(), key=lambda x: x[1])[0] if daily_meetings else "N/A",
97
+ "most_frequent_participant": Counter(participants).most_common(1)[0][0] if participants else "N/A",
98
+ "average_meeting_duration": str(total_duration / total_meetings),
99
+ "most_common_meeting_time": Counter(meeting_times).most_common(1)[0][0] if meeting_times else "N/A",
100
+ "monthly_breakdown": dict(monthly_meetings),
101
+ "daily_breakdown": dict(daily_meetings)
102
+ })
103
+ else:
104
+ stats.update({
105
+ "total_time_spent": "0:00:00",
106
+ "busiest_month": "N/A",
107
+ "busiest_day": "N/A",
108
+ "most_frequent_participant": "N/A",
109
+ "average_meeting_duration": "0:00:00",
110
+ "most_common_meeting_time": "N/A",
111
+ "monthly_breakdown": {},
112
+ "daily_breakdown": {}
113
+ })
114
+
115
+ return stats
116
 
117
  def initiate_connection(self, entity_id: str, redirect_url: Optional[str] = None) -> APIResponse:
118
  try:
 
154
  error="No connection found for this entity ID"
155
  )
156
 
 
 
157
  connection = self.connections[entity_id]
158
 
159
  return APIResponse(
 
172
 
173
  def generate_wrapped(self, entity_id: str) -> APIResponse:
174
  try:
175
+ # Get current year's start and end dates
176
+ current_year = datetime.now().year
177
+ time_min = f"{current_year},1,1,0,0,0"
178
+ time_max = f"{current_year},12,31,23,59,59"
179
 
180
+ request_params = {
181
+ "calendar_id": "primary",
182
+ "timeMin": time_min,
183
+ "timeMax": time_max,
184
+ "single_events": True,
185
+ "max_results": 2500,
186
+ "order_by": "startTime"
187
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
188
 
189
+ events_response = self.toolset.execute_action(
190
+ action=Action.GOOGLECALENDAR_FIND_EVENT,
191
+ params=request_params,
192
+ entity_id=entity_id
 
193
  )
194
 
195
+ if events_response["successfull"]:
196
+ stats = self.analyze_calendar_events(events_response)
197
+ return APIResponse(
198
+ success=True,
199
+ data=stats
200
+ )
201
+ else:
202
+ return APIResponse(
203
+ success=False,
204
+ error=events_response["error"] or "Failed to fetch calendar events"
205
+ )
206
 
207
  except Exception as e:
208
  return APIResponse(