159 lines
5.2 KiB
Python
159 lines
5.2 KiB
Python
from ast import FormattedValue
|
|
from googleapiclient.discovery import build
|
|
import datetime
|
|
from datetime import timedelta
|
|
from zoneinfo import ZoneInfo
|
|
import win32com.client
|
|
|
|
from canvas_secrets import GOOGLE_API_KEY
|
|
|
|
# Replace these with your own API key and Calendar ID.
|
|
calendars = {'peter_main':'peter.howell@gmail.com',
|
|
'aly_and_peter':'5qgh1nv9g5on3am4vres9i451c@group.calendar.google.com',
|
|
'tlc':'4aq36obt0q5jjr5p82p244qs7c@group.calendar.google.com',
|
|
'birthdays':'4q73r3ern2k9k83t0orq6iqaac@group.calendar.google.com'}
|
|
|
|
|
|
|
|
def to_my_timezone(d, md_table_format=0):
|
|
# Parse the datetime string into a timezone-aware datetime.
|
|
dt = datetime.datetime.fromisoformat(d)
|
|
|
|
# Convert to Pacific Time.
|
|
dt_pacific = dt.astimezone(ZoneInfo("America/Los_Angeles"))
|
|
|
|
# Format the datetime. Note:
|
|
# - %A: full weekday name (e.g., Thursday)
|
|
# - %B: full month name (e.g., April)
|
|
# - %d: day of the month (with leading zero, so we'll remove it later)
|
|
# - %I: hour in 12-hour format (with leading zero)
|
|
# - %M: minute (with leading zero)
|
|
# - %p: AM/PM indicator (will be in uppercase)
|
|
formatted = dt_pacific.strftime("%A, %B %d | %I:%M%p")
|
|
|
|
# Remove a leading zero from the day and hour if present
|
|
formatted = formatted.replace(" 0", " ")
|
|
|
|
# Convert the AM/PM indicator to lowercase
|
|
formatted = formatted.replace("AM", "am").replace("PM", "pm")
|
|
return formatted
|
|
#return dt_pacific.strftime("%Y-%m-%d %H:%M:%S %Z%z")
|
|
|
|
def in_my_timezone(d, md_table_format=0):
|
|
# Parse the datetime string into a timezone-aware datetime.
|
|
dt = datetime.datetime.fromisoformat(d)
|
|
|
|
# Convert to Pacific Time.
|
|
#dt_pacific = dt.astimezone(ZoneInfo("America/Los_Angeles"))
|
|
|
|
# Format the datetime. Note:
|
|
# - %A: full weekday name (e.g., Thursday)
|
|
# - %B: full month name (e.g., April)
|
|
# - %d: day of the month (with leading zero, so we'll remove it later)
|
|
# - %I: hour in 12-hour format (with leading zero)
|
|
# - %M: minute (with leading zero)
|
|
# - %p: AM/PM indicator (will be in uppercase)
|
|
formatted = dt.strftime("%A, %B %d | %I:%M%p")
|
|
|
|
# Remove a leading zero from the day and hour if present
|
|
formatted = formatted.replace(" 0", " ")
|
|
|
|
# Convert the AM/PM indicator to lowercase
|
|
formatted = formatted.replace("AM", "am").replace("PM", "pm")
|
|
return formatted
|
|
|
|
def gcal():
|
|
# Build the service using the API key.
|
|
service = build('calendar', 'v3', developerKey=GOOGLE_API_KEY)
|
|
n = 30
|
|
|
|
|
|
for name,id in calendars.items():
|
|
# Get the current time in RFC3339 format (UTC).
|
|
now = datetime.datetime.utcnow().isoformat() + 'Z'
|
|
print(f'Getting the upcoming {n} events')
|
|
|
|
events_result = service.events().list(
|
|
calendarId=id,
|
|
timeMin=now,
|
|
maxResults=n,
|
|
singleEvents=True,
|
|
orderBy='startTime'
|
|
).execute()
|
|
events = events_result.get('items', [])
|
|
|
|
if not events:
|
|
print('No upcoming events found.')
|
|
return
|
|
|
|
print(f"| Date | Time | Event | Lead |")
|
|
print(f"|------|------|-------|------|")
|
|
for event in events:
|
|
# Depending on the event, the start time might be a date or dateTime.
|
|
start = event['start'].get('dateTime', event['start'].get('date'))
|
|
print(f"| {to_my_timezone(start,1)} | {event.get('summary', 'No Title')} | | |")
|
|
|
|
|
|
def ocal():
|
|
|
|
|
|
# Initialize Outlook COM object.
|
|
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
|
|
#outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
|
|
|
|
#print(outlook)
|
|
|
|
#print(dir(outlook))
|
|
|
|
#print(dir(outlook.Folders))
|
|
|
|
root_folder = outlook.Folders.Item(1)
|
|
print (f"Root folder: {root_folder.Name}")
|
|
|
|
#And to know the names of the subfolders you have:
|
|
#print("\nFolders:")
|
|
#for folder in root_folder.Folders:
|
|
# print (" " + folder.Name)
|
|
|
|
|
|
|
|
# Get the default calendar folder.
|
|
calendar_folder = outlook.GetDefaultFolder(9) # 9 refers to the Calendar folder
|
|
#print(calendar_folder)
|
|
#print(dir(calendar_folder))
|
|
#print(calendar_folder.Items)
|
|
items = calendar_folder.Items
|
|
print("Total items in Calendar:", items.Count)
|
|
|
|
# Define the time window for which to fetch events.
|
|
n = 14
|
|
now = datetime.datetime.now()
|
|
end = now + timedelta(days=n) # next 7 days
|
|
|
|
# Restrict the calendar items to the time window.
|
|
# The Outlook filter syntax uses dates in "mm/dd/yyyy hh:mm" format.
|
|
filter_start = now.strftime("%m/%d/%Y %H:%M")
|
|
filter_end = end.strftime("%m/%d/%Y %H:%M")
|
|
restriction = f"[Start] >= '{filter_start}' AND [End] <= '{filter_end}'"
|
|
|
|
calendar_items = calendar_folder.Items
|
|
calendar_items.IncludeRecurrences = True
|
|
calendar_items.Sort("[Start]")
|
|
|
|
#print(calendar_items)
|
|
|
|
print(f"Calendar items in next {n} days:")
|
|
restricted_items = calendar_items.Restrict(restriction)
|
|
|
|
for item in restricted_items:
|
|
#for item in calendar_items:
|
|
start_dt = item.Start # a COM datetime object
|
|
start = in_my_timezone(str(start_dt),1)
|
|
subject = item.Subject
|
|
print(f"{start} - {subject}")
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
ocal()
|