import os import streamlit as st import requests import msal from datetime import datetime, timedelta # Configuration APPLICATION_ID_KEY = os.getenv('APPLICATION_ID_KEY') CLIENT_SECRET_KEY = os.getenv('CLIENT_SECRET_KEY') AUTHORITY_URL = 'https://login.microsoftonline.com/common' REDIRECT_URI = 'https://huggingface.co/spaces/awacke1/MSGraphAPI' # Define product to scope mapping PRODUCT_SCOPES = { "📧 Outlook": ['Mail.Read', 'Mail.Send'], "📅 Calendar": ['Calendars.ReadWrite'], "📋 Tasks": ['Tasks.ReadWrite'], "🗂️ OneDrive": ['Files.ReadWrite.All'], # ... (other products) } BASE_SCOPES = ['User.Read'] def get_msal_app(): return msal.ConfidentialClientApplication( client_id=APPLICATION_ID_KEY, client_credential=CLIENT_SECRET_KEY, authority=AUTHORITY_URL ) def get_access_token(code): client_instance = get_msal_app() try: result = client_instance.acquire_token_by_authorization_code( code=code, scopes=st.session_state.get('request_scopes', BASE_SCOPES), redirect_uri=REDIRECT_URI ) if 'access_token' in result: return result['access_token'] else: raise Exception(f"Error acquiring token: {result.get('error_description')}") except Exception as e: st.error(f"Exception in get_access_token: {str(e)}") raise def make_api_call(access_token, endpoint, method='GET', data=None): headers = {'Authorization': f'Bearer {access_token}', 'Content-Type': 'application/json'} url = f'https://graph.microsoft.com/v1.0/{endpoint}' if method == 'GET': response = requests.get(url, headers=headers) elif method == 'POST': response = requests.post(url, headers=headers, json=data) else: raise ValueError(f"Unsupported method: {method}") if response.status_code in [200, 201]: return response.json() else: st.error(f"API call failed: {response.status_code} - {response.text}") return None def handle_outlook_integration(access_token): st.subheader("📧 Outlook Integration") emails = make_api_call(access_token, 'me/messages?$top=5&$orderby=receivedDateTime desc') if emails and 'value' in emails: for email in emails['value']: st.write(f"From: {email['from']['emailAddress']['name']}") st.write(f"Subject: {email['subject']}") st.write(f"Received: {email['receivedDateTime']}") st.write("---") else: st.write("No emails found or unable to fetch emails.") def handle_calendar_integration(access_token): st.subheader("📅 Calendar Integration") events = make_api_call(access_token, 'me/events?$top=5&$orderby=start/dateTime') if events and 'value' in events: for event in events['value']: st.write(f"Event: {event['subject']}") st.write(f"Start: {event['start']['dateTime']}") st.write(f"End: {event['end']['dateTime']}") st.write("---") else: st.write("No events found or unable to fetch events.") st.write("Add a new event:") event_subject = st.text_input("Event Subject") event_date = st.date_input("Event Date") event_time = st.time_input("Event Time") if st.button("Add Event"): event_start = datetime.combine(event_date, event_time) event_end = event_start + timedelta(hours=1) new_event = { "subject": event_subject, "start": { "dateTime": event_start.isoformat(), "timeZone": "UTC" }, "end": { "dateTime": event_end.isoformat(), "timeZone": "UTC" } } result = make_api_call(access_token, 'me/events', method='POST', data=new_event) if result: st.success("Event added successfully!") else: st.error("Failed to add event.") def handle_tasks_integration(access_token): st.subheader("📋 Tasks Integration") tasks = make_api_call(access_token, 'me/todo/lists') if tasks and 'value' in tasks: default_list = next((list for list in tasks['value'] if list['wellknownListName'] == 'defaultList'), None) if default_list: tasks = make_api_call(access_token, f"me/todo/lists/{default_list['id']}/tasks") if tasks and 'value' in tasks: for task in tasks['value']: st.write(f"Task: {task['title']}") st.write(f"Status: {'Completed' if task['status'] == 'completed' else 'Not Completed'}") st.write("---") else: st.write("No tasks found or unable to fetch tasks.") else: st.write("Default task list not found.") else: st.write("Unable to fetch task lists.") st.write("Add a new task:") task_title = st.text_input("Task Title") if st.button("Add Task"): new_task = { "title": task_title } result = make_api_call(access_token, f"me/todo/lists/{default_list['id']}/tasks", method='POST', data=new_task) if result: st.success("Task added successfully!") else: st.error("Failed to add task.") def handle_onedrive_integration(access_token): st.subheader("🗂️ OneDrive Integration") files = make_api_call(access_token, 'me/drive/root/children') if files and 'value' in files: for file in files['value']: st.write(f"Name: {file['name']}") st.write(f"Type: {'Folder' if 'folder' in file else 'File'}") st.write(f"Last Modified: {file['lastModifiedDateTime']}") st.write("---") else: st.write("No files found or unable to fetch files.") def main(): st.title("🦄 MS Graph API with AI & Cloud Integration for M365") st.sidebar.title("📝 M365 Products") st.sidebar.write("Select products to integrate:") selected_products = {} for product in PRODUCT_SCOPES.keys(): selected = st.sidebar.checkbox(product) if selected: selected_products[product] = True request_scopes = BASE_SCOPES.copy() for product in selected_products: request_scopes.extend(PRODUCT_SCOPES[product]) request_scopes = list(set(request_scopes)) st.session_state['request_scopes'] = request_scopes if 'access_token' not in st.session_state: client_instance = get_msal_app() auth_url = client_instance.get_authorization_request_url( scopes=request_scopes, redirect_uri=REDIRECT_URI ) st.write('👋 Please [click here]({}) to log in and authorize the app.'.format(auth_url)) query_params = st.query_params if 'code' in query_params: code = query_params.get('code') st.write('🔑 Authorization Code Obtained:', code[:10] + '...') try: access_token = get_access_token(code) st.session_state['access_token'] = access_token st.success("Access token acquired successfully!") st.rerun() except Exception as e: st.error(f"Error acquiring access token: {str(e)}") st.stop() else: access_token = st.session_state['access_token'] user_info = make_api_call(access_token, 'me') if user_info: st.sidebar.write(f"👋 Hello, {user_info.get('displayName', 'User')}!") if selected_products: for product in selected_products: if product == "📧 Outlook": handle_outlook_integration(access_token) elif product == "📅 Calendar": handle_calendar_integration(access_token) elif product == "📋 Tasks": handle_tasks_integration(access_token) elif product == "🗂️ OneDrive": handle_onedrive_integration(access_token) # Add more product integrations here else: st.write("No products selected. Please select products from the sidebar.") if __name__ == "__main__": main()