Improve morning report collectors and add section toggling
- Add is_section_enabled() to support per-section enable/disable in config - Update Python path from 3.13 to 3.14 for gmail venv - Disable tasks section by default (enabled: false in config) - Apply code formatting improvements (black/ruff style) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -9,11 +9,13 @@ from pathlib import Path
|
||||
|
||||
def fetch_events(mode: str = "today") -> list:
|
||||
"""Fetch calendar events directly using gmail_mcp library."""
|
||||
os.environ.setdefault('GMAIL_CREDENTIALS_PATH', os.path.expanduser('~/.gmail-mcp/credentials.json'))
|
||||
os.environ.setdefault(
|
||||
"GMAIL_CREDENTIALS_PATH", os.path.expanduser("~/.gmail-mcp/credentials.json")
|
||||
)
|
||||
|
||||
try:
|
||||
# Add gmail venv to path
|
||||
venv_site = Path.home() / ".claude/mcp/gmail/venv/lib/python3.13/site-packages"
|
||||
venv_site = Path.home() / ".claude/mcp/gmail/venv/lib/python3.14/site-packages"
|
||||
if str(venv_site) not in sys.path:
|
||||
sys.path.insert(0, str(venv_site))
|
||||
|
||||
@@ -22,26 +24,32 @@ def fetch_events(mode: str = "today") -> list:
|
||||
service = get_calendar_service()
|
||||
now = datetime.utcnow()
|
||||
|
||||
if mode == 'today':
|
||||
if mode == "today":
|
||||
start = now.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
end = start + timedelta(days=1)
|
||||
elif mode == 'tomorrow':
|
||||
start = (now + timedelta(days=1)).replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
elif mode == "tomorrow":
|
||||
start = (now + timedelta(days=1)).replace(
|
||||
hour=0, minute=0, second=0, microsecond=0
|
||||
)
|
||||
end = start + timedelta(days=1)
|
||||
else:
|
||||
start = now
|
||||
end = now + timedelta(days=7)
|
||||
|
||||
events_result = service.events().list(
|
||||
calendarId='primary',
|
||||
timeMin=start.isoformat() + 'Z',
|
||||
timeMax=end.isoformat() + 'Z',
|
||||
singleEvents=True,
|
||||
orderBy='startTime',
|
||||
maxResults=20
|
||||
).execute()
|
||||
events_result = (
|
||||
service.events()
|
||||
.list(
|
||||
calendarId="primary",
|
||||
timeMin=start.isoformat() + "Z",
|
||||
timeMax=end.isoformat() + "Z",
|
||||
singleEvents=True,
|
||||
orderBy="startTime",
|
||||
maxResults=20,
|
||||
)
|
||||
.execute()
|
||||
)
|
||||
|
||||
return events_result.get('items', [])
|
||||
return events_result.get("items", [])
|
||||
|
||||
except Exception as e:
|
||||
return [{"error": str(e)}]
|
||||
@@ -62,7 +70,9 @@ def format_events(today_events: list, tomorrow_events: list = None) -> str:
|
||||
|
||||
if "dateTime" in start:
|
||||
# Timed event
|
||||
dt = datetime.fromisoformat(start["dateTime"].replace("Z", "+00:00"))
|
||||
dt = datetime.fromisoformat(
|
||||
start["dateTime"].replace("Z", "+00:00")
|
||||
)
|
||||
time_str = dt.strftime("%I:%M %p").lstrip("0")
|
||||
elif "date" in start:
|
||||
time_str = "All day"
|
||||
@@ -73,13 +83,19 @@ def format_events(today_events: list, tomorrow_events: list = None) -> str:
|
||||
# Calculate duration if end time available
|
||||
end = event.get("end", {})
|
||||
if "dateTime" in start and "dateTime" in end:
|
||||
start_dt = datetime.fromisoformat(start["dateTime"].replace("Z", "+00:00"))
|
||||
end_dt = datetime.fromisoformat(end["dateTime"].replace("Z", "+00:00"))
|
||||
start_dt = datetime.fromisoformat(
|
||||
start["dateTime"].replace("Z", "+00:00")
|
||||
)
|
||||
end_dt = datetime.fromisoformat(
|
||||
end["dateTime"].replace("Z", "+00:00")
|
||||
)
|
||||
mins = int((end_dt - start_dt).total_seconds() / 60)
|
||||
if mins >= 60:
|
||||
hours = mins // 60
|
||||
remaining = mins % 60
|
||||
duration = f" ({hours}h{remaining}m)" if remaining else f" ({hours}h)"
|
||||
duration = (
|
||||
f" ({hours}h{remaining}m)" if remaining else f" ({hours}h)"
|
||||
)
|
||||
else:
|
||||
duration = f" ({mins}m)"
|
||||
|
||||
@@ -92,17 +108,23 @@ def format_events(today_events: list, tomorrow_events: list = None) -> str:
|
||||
|
||||
# Tomorrow preview
|
||||
if tomorrow_events is not None:
|
||||
if tomorrow_events and (len(tomorrow_events) == 0 or "error" not in tomorrow_events[0]):
|
||||
if tomorrow_events and (
|
||||
len(tomorrow_events) == 0 or "error" not in tomorrow_events[0]
|
||||
):
|
||||
count = len(tomorrow_events)
|
||||
if count > 0:
|
||||
first = tomorrow_events[0]
|
||||
start = first.get("start", {})
|
||||
if "dateTime" in start:
|
||||
dt = datetime.fromisoformat(start["dateTime"].replace("Z", "+00:00"))
|
||||
dt = datetime.fromisoformat(
|
||||
start["dateTime"].replace("Z", "+00:00")
|
||||
)
|
||||
first_time = dt.strftime("%I:%M %p").lstrip("0")
|
||||
else:
|
||||
first_time = "All day"
|
||||
lines.append(f"Tomorrow: {count} event{'s' if count > 1 else ''}, first at {first_time}")
|
||||
lines.append(
|
||||
f"Tomorrow: {count} event{'s' if count > 1 else ''}, first at {first_time}"
|
||||
)
|
||||
else:
|
||||
lines.append("Tomorrow: No events")
|
||||
|
||||
@@ -126,7 +148,7 @@ def collect(config: dict) -> dict:
|
||||
"icon": "📅",
|
||||
"content": formatted,
|
||||
"raw": {"today": today_events, "tomorrow": tomorrow_events},
|
||||
"error": today_events[0].get("error") if has_error else None
|
||||
"error": today_events[0].get("error") if has_error else None,
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user