import os import msal import requests import json from datetime import datetime from dateutil import parser # Read Azure app credentials from environment variables client_id = os.getenv('AZURE_CLIENT_ID') tenant_id = os.getenv('AZURE_TENANT_ID') if not client_id or not tenant_id: raise ValueError("Please set the AZURE_CLIENT_ID and AZURE_TENANT_ID environment variables.") # Authentication authority = f'https://login.microsoftonline.com/{tenant_id}' scopes = ['https://graph.microsoft.com/Calendars.Read'] app = msal.PublicClientApplication(client_id, authority=authority) flow = app.initiate_device_flow(scopes=scopes) if 'user_code' not in flow: raise Exception("Failed to create device flow") print(flow['message']) token_response = app.acquire_token_by_device_flow(flow) if 'access_token' not in token_response: raise Exception("Failed to acquire token") access_token = token_response['access_token'] # Fetch events with pagination and expand recurring events headers = {'Authorization': f'Bearer {access_token}'} events_url = 'https://graph.microsoft.com/v1.0/me/events?$top=100&$expand=instances' events = [] while events_url: response = requests.get(events_url, headers=headers) response_data = response.json() events.extend(response_data.get('value', [])) events_url = response_data.get('@odata.nextLink') # Save events to a file in iCalendar format with open('outlook_events.ics', 'w') as f: f.write("BEGIN:VCALENDAR\nVERSION:2.0\n") for event in events: if 'start' in event and 'end' in event: start = parser.isoparse(event['start']['dateTime']) end = parser.isoparse(event['end']['dateTime']) f.write(f"BEGIN:VEVENT\nSUMMARY:{event['subject']}\n") f.write(f"DTSTART:{start.strftime('%Y%m%dT%H%M%S')}\n") f.write(f"DTEND:{end.strftime('%Y%m%dT%H%M%S')}\n") f.write("END:VEVENT\n") f.write("END:VCALENDAR\n")