|
- #!/usr/bin/env python3
-
- import csv
- import argparse
- import configparser
- from datetime import datetime, timedelta
- from O365 import (Account, Connection, FileSystemTokenBackend,
- MSOffice365Protocol)
-
-
- parser = argparse.ArgumentParser(prog='seatingplan', description="Script to generate a seating plan via Office365 Calendars")
- parser.add_argument("-i", "--client-id", type=str, dest='client_id', default="",
- help='Client ID for registered azure application')
- parser.add_argument("-s", "--client-secret", type=str, dest='client_secret', default="",
- help='Client secret for registered azure application')
- parser.add_argument("-t", "--tenant-id", type=str, dest='tenant_id', default="",
- help='Tenant ID for registered azure application')
- parser.add_argument("-c", "--config", type=str, dest="config_path", default="",
- help="Path to a config file to read settings from.")
- # TODO: DATETIME FORMATTING, MAKE THIS AVALIABLE FOR THE OUTPUT PATH SO THAT YOU CAN DO THE COOL SCRIPT THINGS
- parser.add_argument("-o", "--output", type=str, dest="output_path", default="Seating Plan.csv",
- help="Path of the outputted csv file.")
-
- # TODO: Setup providing config file via commandline args
-
-
- def read_config_file(config_path):
- """
- Reads config file and sets up variables foo
- :return: credentials: ('client_id', 'client_secret') and tenant: str
- """
- config = configparser.ConfigParser()
- config.read(config_path)
-
- credentials = (config["client"]["id"], config["client"]["secret"])
- tenant = config["client"]["tenant"]
-
- return credentials, tenant
-
-
- def parse_args():
- """
- Parses arguments from the commandline.
- :return: args, a name space with variables you can find out about with the -h flag
- """
- # TODO: Maybe the prints before exit could be a lil better at explaining the error.
- args = parser.parse_args()
- using_args = False
- using_conf = False
- if args.client_id and args.tenant_id and args.client_secret:
- using_args = True
- if args.config_path:
- using_conf = True
-
- if using_args and using_conf:
- # Using both types of config input. Confusing so dump it
- print("Cannot use both command-line arguments and config file. Please only use one.")
- exit(1)
- elif using_conf:
- # Read the file provided and return the required config
- credentials, tenant = read_config_file(args.config_path)
- args.client_id = credentials[0]
- args.client_secret = credentials[1]
- args.tenant_id = tenant
- return args
- elif using_args:
- # Just grab the config from the command line args
- return args
- else:
- # If the code has gotten here, then a config can't be parsed so we must close the program
- print("Cannot login. No config/partial was provided.")
- exit(1)
-
-
- def create_session(credentials, tenant_id):
- """
- Create a session with the API and save the token for later use.
- :param credentials: tuple of (client_id, client_secret)
- :param tentant_id: str of tenant_id
- :return: Account class and email: str
- """
- my_protocol = MSOffice365Protocol(api_version='v2.0')
- token_backend = FileSystemTokenBackend(token_filename='access_token')
- return Account(
- credentials,
- protocol=my_protocol,
- tenant_id=tenant_id,
- token_backend=token_backend
- )
-
-
- def authenticate_session(session: Account):
- """
- Authenticates account session object with oauth. Uses the default auth flow that comes with the library
-
- It could be merged with oauth wrapper but this works too.
- :param session: Account object
- :return:
- """
- try:
- session.con.oauth_request("https://outlook.office.com/api/v2.0/me/calendar", "get")
- except RuntimeError: # Not authenticated. Need to ask user for url
- session.authenticate(scopes=['basic', 'address_book', 'users', 'calendar_shared'])
- session.con.oauth_request("https://outlook.office.com/api/v2.0/me/calendar", "get")
-
-
- def oauth_request(connection: Connection, url: str):
- """
- Wrapper for Connection.oauth_request to provide some error handling
- :param connection:
- :param url:
- :return:
- """
- request = connection.oauth_request(url, "get")
- if request.status_code != 200:
- print(f"Request failed: GET request to {url} failed with {request.status_code} error")
- else:
- return request
-
-
- def get_week_datetime():
- """
- Gets the current week's Monday and Friday to be used to filter a calendar.
-
- If this script is ran during the work week (Monday-Friday), it will be the current week. If it is ran on the weekend, it will generate for next week.
- :return: Monday and Friday: Datetime object
- """
- today = datetime.now()
- weekday = today.weekday()
- # If this script is run during the week
- if weekday <= 4: # 0 = Monday, 6 = Sunday
- monday = today - timedelta(days=weekday) # Monday = 0-0, Friday = 4-4
- friday = today + timedelta(days=4 - weekday) # Fri to Fri 4 + (4 - 4), Tues to Fri = 2 + (4 - 2)
- return monday, friday
- else:
- monday = today - timedelta(days=weekday) + timedelta(days=7) # Monday = 0-0, Friday = 4-4
- friday = today + timedelta(days=4 - weekday) + timedelta(
- days=7) # Fri to Fri 4 + (4 - 4), Tues to Fri = 2 + (4 - 2)
- return monday, friday
-
-
- def create_csv(output_path):
- with open(output_path, 'w', newline='', encoding='utf-8') as csvfile:
- fieldnames = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
- writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
- pass
- # TODO: https://docs.python.org/3.7/library/csv.html#csv.DictWriter Need to finish this when we actually get some data to input.
-
-
- def main():
- """
- Main function that is ran on start up. Script is ran from here.
- """
- args = parse_args()
- session = create_session((args.client_id, args.client_secret), args.tenant_id)
- authenticate_session(session)
-
- r = session.con.oauth_request("https://outlook.office.com/api/v2.0/users/{email}/calendar/events", "get")
-
- # request = account.con.oauth_request("https://outlook.office.com/api/v2.0/users/EMAIL/calendar/events?$filter=Start/DateTime ge '2019-09-04T08:00' AND End/Datetime le '2019-09-05T08:00'&$top=50", "get")
- print(r.text)
-
- # setup csv
- # API request events from out of office email
- # loop over events
- # find out who the event is talking about
- # insert into csv
- # output csv
-
- monday, friday = get_week_datetime()
- print(f"Monday is {monday}, Friday is {friday}")
-
- create_csv(args.output_path)
-
-
- if __name__ == "__main__":
- # This is for running the file in testing, rather than installing via pip
- main()
|