Skip to content

Commit

Permalink
Implement access token retrieval
Browse files Browse the repository at this point in the history
  • Loading branch information
PhongT16 committed Jul 20, 2023
1 parent 85457a7 commit 4a7b1e8
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 53 deletions.
54 changes: 27 additions & 27 deletions OutlookCalendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,14 @@ def get_individual_calendars(self, start_date, end_date, access_token):

#utils.send_email(self.user_client, self.get_access_token(), error)

print(response.json())
#print(response.json())

#response = self.user_client.post('/me/calendar/getSchedule', data=json.dumps(payload), headers=header)
# if (response.status_code == 200):
# return response.json()
# else:
# utils.send_email(self.user_client, utils.acquire_access_token(self.app, self.scopes), "Unable to retrieve individual calendars")
# raise Exception(response.json())
if (response.status_code == 200):
return response.json()
else:
#utils.send_email(self.user_client, utils.acquire_access_token(self.app, self.scopes), "Unable to retrieve individual calendars")
raise Exception(response.json())

def get_shared_calendar(self, start_date, end_date, access_token):
"""
Expand All @@ -126,7 +126,9 @@ def get_shared_calendar(self, start_date, end_date, access_token):
'Authorization': str(access_token),
'Content-Type': 'application/json'
}
response = self.user_client.get('/me/calendars', headers=header)
endpoint = "https://graph.microsoft.com/v1.0/me/calendars"
response = requests.get(endpoint, headers=header)
#response = self.user_client.get('/me/calendars', headers=header)

# Loop through all the calendars available to the user, and find the one indicated in the yaml file and retrieve its calendar ID
#print(response.json())
Expand All @@ -147,13 +149,19 @@ def get_shared_calendar(self, start_date, end_date, access_token):
# Include events that:
# start between start_date and end_date (includes start_date)
# The exception is if the event start on the end_date. That event will not be included in the response.json()

request = '/me/calendars/' + self.shared_calendar_id +'/events' + '?$select=subject,body,start,end,showAs&$top=100&$filter=start/dateTime ge ' + '\''+ start_date + '\'' + ' and start/dateTime lt ' + '\'' + end_date + '\''
response = self.user_client.get(request, headers=header)
# response = self.user_client.get(request, headers=header)


endpoint = "https://graph.microsoft.com/v1.0" + request
response = requests.get(endpoint, headers=header)
#print("Shared calendar:")
#print(response.json())
if (response.status_code == 200):
return response.json()
else:
utils.send_email(self.user_client, access_token, "Unable to retrieve shared calendar")
#utils.send_email(self.user_client, access_token, "Unable to retrieve shared calendar")
raise Exception(response.json())


Expand All @@ -169,7 +177,7 @@ def process_individual_calendars(self, calendar, user_start_date, user_end_date)
list: A list of SimpleEvent objects
"""

#print(calendar)
filtered_events = []
for member in calendar['value']:
net_id = member['scheduleId'].split('@')[0]
Expand Down Expand Up @@ -263,24 +271,16 @@ def sanitize_input(start_date, end_date):
def debug(configs):
print("In debug mode")
calendar = OutlookCalendar(configs)
days_out = timedelta(days=3)
start_date = datetime(year=2023, month=7, day=17)
days_out = timedelta(days=7)
start_date = datetime(year=2023, month=8, day=21)
end_date = start_date + days_out

access_token = utils.acquire_access_token(calendar.app, calendar.scopes)

count = 0

while count <= 5:
access_token = utils.acquire_access_token(calendar.app, calendar.scopes)
print(count)
individual_calendars = calendar.get_individual_calendars(start_date, end_date, access_token)
shared_calendar = calendar.get_shared_calendar(start_date, end_date, access_token)
print("""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""")
time.sleep(180)

#individual_calendars = calendar.process_individual_calendars(calendar.get_individual_calendars(start_date, end_date), start_date, end_date)
#shared_calendar_events, event_ids = calendar.process_shared_calendar(calendar.get_shared_calendar(start_date, end_date))
#SharedCalendar.update_shared_calendar(individual_calendars, shared_calendar_events, event_ids, calendar.shared_calendar_id, calendar , calendar.user_client)
individual_calendars = calendar.process_individual_calendars(calendar.get_individual_calendars(start_date, end_date, access_token), start_date, end_date)
shared_calendar_events, event_ids = calendar.process_shared_calendar(calendar.get_shared_calendar(start_date, end_date, access_token))
SharedCalendar.update_shared_calendar(individual_calendars, shared_calendar_events, event_ids, calendar.shared_calendar_id, access_token)
#utils.get_groups_belonging_to_user(access_token)

#utils.send_email(calendar.user_client, calendar.get_access_token(), "test")

Expand All @@ -305,7 +305,7 @@ def main(configs):
individual_calendar_events = calendar.process_individual_calendars(calendar.get_individual_calendars(start_date, end_date), start_date, end_date)
shared_calendar_events, event_ids = calendar.process_shared_calendar(calendar.get_shared_calendar(start_date, end_date))

SharedCalendar.update_shared_calendar(individual_calendar_events, shared_calendar_events, event_ids, calendar.shared_calendar_id, access_token, calendar.user_client)
SharedCalendar.update_shared_calendar(individual_calendar_events, shared_calendar_events, event_ids, calendar.shared_calendar_id, access_token)

count = count + 1
time.sleep(calendar.update_interval)
Expand All @@ -320,7 +320,7 @@ def main(configs):
end_date = dates[1]
individual_calendar_events = calendar.process_individual_calendars(calendar.get_individual_calendars(start_date, end_date), start_date, end_date)
shared_calendar_events, event_ids = calendar.process_shared_calendar(calendar.get_shared_calendar(start_date, end_date))
SharedCalendar.update_shared_calendar(individual_calendar_events, shared_calendar_events, event_ids, calendar.shared_calendar_id, access_token, calendar.user_client)
SharedCalendar.update_shared_calendar(individual_calendar_events, shared_calendar_events, event_ids, calendar.shared_calendar_id, access_token)

if __name__ == '__main__':
configs = utils.retrieve_from_yaml()
Expand Down
50 changes: 28 additions & 22 deletions SharedCalendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,36 @@
import logging
import math
import utils
import requests

MAX_REQUESTS_PER_BATCH = 20

# This logger is a child of the __main__ logger located in OutlookCalendar.py
logger = logging.getLogger("__main__." + __name__)

def update_shared_calendar(individual_calendars, shared_calendar, event_ids, shared_calendar_id, access_token, user_client):
def update_shared_calendar(individual_calendars, shared_calendar, event_ids, shared_calendar_id, access_token):
"""
Update the specified shared calendar by adding and deleting events from it
Args:
individual_calendars (list): A list of SimpleEvents from each member's calendars
shared_calendar: A list of SimpleEvents obtained from the shared calendar
shared_calendar_id (str): The associated id to the shared calendar
access_token (int): The access token for the project
access_token (str): The access token for the project
user_client (GraphClient Object)
"""

individual_events = set(create_tuple(individual_calendars))
shared_events = set(create_tuple(shared_calendar))

events_to_add = individual_events.difference(shared_events)
events_to_delete = shared_events.difference(individual_events)

batches = create_batches_for_adding_events(events_to_add, access_token, shared_calendar_id)
post_batch(user_client, access_token, batches)
post_batch(access_token, batches)

batches, deleted_event_info = create_batches_for_deleting_events(events_to_delete, access_token, shared_calendar_id, event_ids)
post_batch(user_client, access_token, batches, deleted_event_info)

post_batch(access_token, batches, deleted_event_info)

def create_tuple(calendar):
"""
Expand Down Expand Up @@ -66,6 +66,7 @@ def create_batches_for_deleting_events(events, access_token, calendar_id, event_
Returns:
A list of dictionaries (batches)
"""

batches = []
deleted_events_info = []

Expand Down Expand Up @@ -133,7 +134,7 @@ def create_batches_for_adding_events(events, access_token, calendar_id):

batch_counter = 0
id_counter = 1

for event in events:
start_date_time = event[2] + "T00:00:00.0000000"
end_date = datetime.datetime.strptime(event[2],"%Y-%m-%d") + timedelta(days=1)
Expand All @@ -157,7 +158,7 @@ def create_batches_for_adding_events(events, access_token, calendar_id):
"categories": ["vacation"]
},
"headers": {
"Authorization": str(access_token),
"Authorization": access_token,
'Content-type': 'application/json'
}
}
Expand All @@ -170,9 +171,10 @@ def create_batches_for_adding_events(events, access_token, calendar_id):

return batches

def check_add_response(batch, batch_responses, user_client, access_token):
def check_add_response(batch, batch_responses, access_token):
message = ""
for response in batch_responses:

if response["status"] == 201: # 201 is the response for Created
logger.info("Event {subject} on {date} was successfully added".format(subject=response['body']['subject'], date=response['body']['start']['dateTime']))
else:
Expand All @@ -183,10 +185,10 @@ def check_add_response(batch, batch_responses, user_client, access_token):
logger.error("Error: {response['body']['error']}")
message = message + f"Event {subject} on {date} was unccessfully added\n"

if (len(message) != 0):
utils.send_email(user_client, access_token, message)
# if (len(message) != 0):
# utils.send_email(user_client, access_token, message)

def check_deleted_response(batch, batch_responses, user_client, access_token, info):
def check_deleted_response(batch, batch_responses, access_token, info):
for response in batch_responses:
id = response["id"]
event = info[id]
Expand All @@ -197,30 +199,34 @@ def check_deleted_response(batch, batch_responses, user_client, access_token, in
logger.error(f"Error: {response['body']['error']}")


def post_batch(user_client, access_token, batches, info=None):
def post_batch(access_token, batches, info=None):
"""
Create the batches for events being deleted from the shared_calendar using the format indicated by the Microsoft Graph API for batch
Args:
user_client (Graph Client Object) : msgraph.core._graph_client.GraphClient
batches (list): A list of dictionaries (batches)
"""
endpoint = 'https://graph.microsoft.com/v1.0/$batch'
endpoint = "https://graph.microsoft.com/v1.0/$batch"

header = {
'Content-type': 'application/json'
'Accept': 'application/json',
'Content-type': 'application/json',
"Authorization": access_token
}
#counter = 0

for count, batch in enumerate(batches):
response = user_client.post(endpoint,data=json.dumps(batch), headers=header)
if response.status_code == 400:
response = requests.post(endpoint, data=json.dumps(batch), headers=header)
#print(batch)
if "error" in response:
message = "Unable to post batch \n" + str(response.json()["error"])
utils.send_email(user_client, access_token, message)
#utils.send_email(user_client, access_token, message)
logger.error(response.json()["error"])
#counter = counter + 1
continue

if info:
check_deleted_response(batch, response.json()["responses"], user_client, access_token, info[count])
check_deleted_response(batch, response.json()["responses"], access_token, info[count])
else:
check_add_response(batch, response.json()["responses"], user_client, access_token)

check_add_response(batch, response.json()["responses"], access_token)

21 changes: 17 additions & 4 deletions utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,19 @@
import subprocess
from msal import PublicClientApplication
import os.path
import requests

SUBJECT = "Vacation Calendar Sync Error Notification"

def init_device_code_flow(app, scopes):
flow = app.initiate_device_flow(scopes=scopes)
print(flow)
print(flow["message"])
result = app.acquire_token_by_device_flow(flow)
return result


def acquire_access_token(app, scopes):
# Note access_token usually lasts for a little bit over an hour
result = None
accounts = app.get_accounts()
if accounts:
Expand All @@ -28,8 +30,6 @@ def acquire_access_token(app, scopes):
refresh_token = file.readline()

result = app.acquire_token_by_refresh_token(refresh_token, scopes)

#print(result)

if not result or "error" in result:
result = init_device_code_flow(app, scopes)
Expand Down Expand Up @@ -69,7 +69,6 @@ def send_mail_using_host(message):
subprocess.run(f"sendmail {recipient_email} < email.txt", shell=True)



def send_email(user_client, access_token, message):

toRecipients = []
Expand Down Expand Up @@ -110,3 +109,17 @@ def send_email(user_client, access_token, message):





def get_groups_belonging_to_user(access_token):
endpoint = "https://graph.microsoft.com/v1.0/me/memberOf"
endpoint_three = "https://graph.microsoft.com/v1.0/groups?$filter=displayName eq 'NCSA-Org-ICI'"
header = {
"Authorization": str(access_token),
}

endpoint_two = "https://graph.microsoft.com/v1.0/groups?$select=displayName"
response = requests.get(endpoint_two, headers=header)
print(response.json())


0 comments on commit 4a7b1e8

Please sign in to comment.