Add hooks and refactor skills to use resources pattern
Phase 1 of plugin-structure refactor: - Add hooks/hooks.json for SessionStart automation - Refactor gmail skill: - Extract inline scripts to scripts/check_unread.py, check_urgent.py, search.py - Add references/query-patterns.md for query documentation - Simplify SKILL.md to reference scripts instead of inline code - Add gcal/scripts/agenda.py for direct calendar access - Make all scripts executable This follows the "Skill with Bundled Resources" pattern from developing-claude-code-plugins best practices. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
104
skills/gcal/scripts/agenda.py
Executable file
104
skills/gcal/scripts/agenda.py
Executable file
@@ -0,0 +1,104 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Get calendar agenda for a time range."""
|
||||
import os
|
||||
import sys
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
# Set credentials path
|
||||
os.environ.setdefault('GMAIL_CREDENTIALS_PATH', os.path.expanduser('~/.gmail-mcp/credentials.json'))
|
||||
|
||||
from gmail_mcp.utils.GCP.gmail_auth import get_calendar_service
|
||||
|
||||
def format_event(event):
|
||||
"""Format a single event for display."""
|
||||
start = event['start'].get('dateTime', event['start'].get('date'))
|
||||
end = event['end'].get('dateTime', event['end'].get('date'))
|
||||
|
||||
# Parse datetime
|
||||
if 'T' in start:
|
||||
start_dt = datetime.fromisoformat(start.replace('Z', '+00:00'))
|
||||
end_dt = datetime.fromisoformat(end.replace('Z', '+00:00'))
|
||||
time_str = start_dt.strftime('%I:%M %p').lstrip('0')
|
||||
duration = end_dt - start_dt
|
||||
if duration.seconds >= 3600:
|
||||
dur_str = f"{duration.seconds // 3600}h"
|
||||
else:
|
||||
dur_str = f"{duration.seconds // 60}m"
|
||||
else:
|
||||
time_str = "All day"
|
||||
dur_str = ""
|
||||
|
||||
summary = event.get('summary', '(No title)')
|
||||
location = event.get('location', '')
|
||||
|
||||
line = f" {time_str:>10} {summary}"
|
||||
if dur_str:
|
||||
line += f" ({dur_str})"
|
||||
if location:
|
||||
line += f"\n 📍 {location}"
|
||||
|
||||
return line
|
||||
|
||||
def main():
|
||||
mode = sys.argv[1] if len(sys.argv) > 1 else 'today'
|
||||
|
||||
service = get_calendar_service()
|
||||
now = datetime.utcnow()
|
||||
|
||||
if mode == 'today':
|
||||
start = now.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
end = start + timedelta(days=1)
|
||||
title = f"Today — {start.strftime('%A, %b %d')}"
|
||||
elif mode == 'tomorrow':
|
||||
start = (now + timedelta(days=1)).replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
end = start + timedelta(days=1)
|
||||
title = f"Tomorrow — {start.strftime('%A, %b %d')}"
|
||||
elif mode == 'week':
|
||||
start = now.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
end = start + timedelta(days=7)
|
||||
title = f"This Week — {start.strftime('%b %d')}-{end.strftime('%d')}"
|
||||
else:
|
||||
start = now
|
||||
end = now + timedelta(days=7)
|
||||
title = "Upcoming"
|
||||
|
||||
events_result = service.events().list(
|
||||
calendarId='primary',
|
||||
timeMin=start.isoformat() + 'Z',
|
||||
timeMax=end.isoformat() + 'Z',
|
||||
singleEvents=True,
|
||||
orderBy='startTime',
|
||||
maxResults=50
|
||||
).execute()
|
||||
|
||||
events = events_result.get('items', [])
|
||||
|
||||
print(f"📅 {title}\n")
|
||||
|
||||
if not events:
|
||||
print("No events scheduled.")
|
||||
return
|
||||
|
||||
if mode == 'week':
|
||||
# Group by day
|
||||
by_day = {}
|
||||
for event in events:
|
||||
start_str = event['start'].get('dateTime', event['start'].get('date'))
|
||||
day = start_str[:10]
|
||||
if day not in by_day:
|
||||
by_day[day] = []
|
||||
by_day[day].append(event)
|
||||
|
||||
for day, day_events in sorted(by_day.items()):
|
||||
day_dt = datetime.fromisoformat(day)
|
||||
print(f"━━━ {day_dt.strftime('%A, %b %d')} ━━━")
|
||||
for event in day_events:
|
||||
print(format_event(event))
|
||||
print()
|
||||
else:
|
||||
for event in events:
|
||||
print(format_event(event))
|
||||
print("\nNo more events" + (" today." if mode == 'today' else "."))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user