|
|
|
#TODO: All Google/iCloud Calendar syncing logic here
|
|
|
|
|
|
|
|
import google_auth_oauthlib.flow
|
|
|
|
from google.auth.transport.requests import Request
|
|
|
|
from google.oauth2.credentials import Credentials
|
|
|
|
from googleapiclient.discovery import build
|
|
|
|
from googleapiclient.errors import HttpError
|
|
|
|
import os
|
|
|
|
import json
|
|
|
|
import datetime
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from .database import TodoDatabase
|
|
|
|
|
|
|
|
data = TodoDatabase()
|
|
|
|
|
|
|
|
|
|
|
|
from datetime import datetime, time, timedelta
|
|
|
|
import pytz
|
|
|
|
from zoneinfo import ZoneInfo
|
|
|
|
from datetime import timezone
|
|
|
|
|
|
|
|
def midnight_UTC(offset):
|
|
|
|
|
|
|
|
# Construct a timezone object
|
|
|
|
tz = pytz.timezone('America/Toronto')
|
|
|
|
|
|
|
|
# Work out today/now as a timezone-aware datetime
|
|
|
|
today = datetime.now(tz)
|
|
|
|
|
|
|
|
# Adjust by the offset. Note that that adding 1 day might actually move us 23 or 25
|
|
|
|
# hours into the future, depending on daylight savings. This works because the {today}
|
|
|
|
# variable is timezone aware
|
|
|
|
target_day = today + timedelta(days=1) * offset
|
|
|
|
|
|
|
|
# Discard hours, minutes, seconds and microseconds
|
|
|
|
midnight_aware = tz.localize(
|
|
|
|
datetime.combine(target_day, time(0, 0, 0, 0)), is_dst=None)
|
|
|
|
|
|
|
|
# Convert to UTC
|
|
|
|
midnight_UTC = midnight_aware.astimezone(pytz.utc)
|
|
|
|
|
|
|
|
return midnight_UTC
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class SyncData():
|
|
|
|
def __init__(self):
|
|
|
|
self.SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']
|
|
|
|
self.creds = None
|
|
|
|
|
|
|
|
self.get_new_creds()
|
|
|
|
self.get_calendar_events()
|
|
|
|
|
|
|
|
|
|
|
|
def get_new_creds(self, code=""):
|
|
|
|
"""Returns True if successfully obtains credentials,
|
|
|
|
otherwise throws errors according to functions called, unless
|
|
|
|
code='' in which case if no saved credentials are found, returns False
|
|
|
|
"""
|
|
|
|
if os.path.exists('token.json'):
|
|
|
|
self.creds = Credentials.from_authorized_user_file('token.json', self.SCOPES)
|
|
|
|
# else:
|
|
|
|
# flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
|
|
|
|
# 'client_secret.json',
|
|
|
|
# scopes=['https://www.googleapis.com/auth/calendar.readonly'],
|
|
|
|
# redirect_uri="postmessage"
|
|
|
|
# # state=state
|
|
|
|
# )
|
|
|
|
|
|
|
|
# creds = flow.fetch_token(code=googleCode.code)
|
|
|
|
# print(creds)
|
|
|
|
# with open("token.json", 'w') as token:
|
|
|
|
# token.write(creds.to_json())
|
|
|
|
|
|
|
|
if not self.creds or not self.creds.valid:
|
|
|
|
if self.creds and self.creds.expired and self.creds.refresh_token:
|
|
|
|
self.creds.refresh(Request())
|
|
|
|
else:
|
|
|
|
if code == "":
|
|
|
|
return False
|
|
|
|
# flow = InstalledAppFlow.from_client_secrets_file(
|
|
|
|
# 'credentials.json', SCOPES)
|
|
|
|
# creds = flow.run_local_server(port=0)
|
|
|
|
|
|
|
|
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
|
|
|
|
'client_secret.json',
|
|
|
|
scopes=self.SCOPES,
|
|
|
|
redirect_uri="postmessage"
|
|
|
|
# state=state
|
|
|
|
)
|
|
|
|
flow.fetch_token(code=code)
|
|
|
|
self.creds = flow.credentials
|
|
|
|
# print(creds)
|
|
|
|
|
|
|
|
# Save the credentials for the next run
|
|
|
|
with open('token.json', 'w') as token:
|
|
|
|
token.write(self.creds.to_json())
|
|
|
|
# json.dump(token, creds)
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
def get_calendar_events(self, day=None):
|
|
|
|
self.get_new_creds()
|
|
|
|
|
|
|
|
# now = datetime.now()
|
|
|
|
# if day:
|
|
|
|
# now = datetime.datetime.strptime(day, "%Y-%m-%d")
|
|
|
|
# else:
|
|
|
|
# now = datetime.datetime.now()
|
|
|
|
# day_start = now.replace(hour=0, minute=0, second=0, microsecond=0)
|
|
|
|
# day_end = day_start + datetime.timedelta(hours=24)
|
|
|
|
# day_start = day_start.isoformat() + "Z"
|
|
|
|
# day_end = day_end.isoformat() + "Z"
|
|
|
|
|
|
|
|
if day:
|
|
|
|
pass
|
|
|
|
else:
|
|
|
|
# day_start = midnight_UTC(0).isoformat() + "Z"
|
|
|
|
# day_end = midnight_UTC(1).isoformat() + "Z"
|
|
|
|
day_start = datetime.combine(datetime.now(tz=ZoneInfo("America/Toronto")).date(), time(0, 0), tzinfo=ZoneInfo("America/Toronto"))
|
|
|
|
day_end = day_start + timedelta(hours=23,minutes=59)
|
|
|
|
# day_start_for = day_start.astimezone(ZoneInfo("UTC")).isoformat() + "Z"
|
|
|
|
# day_end_for = day_end.astimezone(ZoneInfo("UTC")).isoformat() + "Z"
|
|
|
|
day_start_for = day_start.astimezone(ZoneInfo("UTC")).strftime('%Y-%m-%dT%H:%M:%S.%fZ')
|
|
|
|
day_end_for = day_end.astimezone(ZoneInfo("UTC")).strftime('%Y-%m-%dT%H:%M:%S.%fZ')
|
|
|
|
|
|
|
|
# print(day_start.tzname())
|
|
|
|
print(day_start)
|
|
|
|
print(day_end)
|
|
|
|
print(day_start.astimezone(ZoneInfo("UTC")).strftime('%Y-%m-%dT%H:%M:%S.%fZ'))
|
|
|
|
print(day_end.astimezone(ZoneInfo("UTC")).strftime('%Y-%m-%dT%H:%M:%S.%fZ'))
|
|
|
|
print(datetime.utcnow().isoformat() + 'Z')
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
service = build('calendar', 'v3', credentials=self.creds)
|
|
|
|
|
|
|
|
# Call the Calendar API
|
|
|
|
# now = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time
|
|
|
|
print('Getting all upcoming events for time range: ' + day_start_for + " to " + day_end_for)
|
|
|
|
events_result = service.events().list(calendarId='primary', timeMin=day_start_for, timeMax=day_end_for,
|
|
|
|
singleEvents=True, orderBy='startTime').execute()
|
|
|
|
events = events_result.get('items', [])
|
|
|
|
|
|
|
|
if not events:
|
|
|
|
print('No upcoming events found.')
|
|
|
|
return
|
|
|
|
|
|
|
|
# Prints the start and name of the next 10 events
|
|
|
|
# event format: {'kind': 'calendar#event', 'etag': '"3386046190326000"', 'id': '0migcv6t729ph1kirhiauej3eh', 'status': 'confirmed', 'htmlLink': 'https://www.google.com/calendar/event?eid=MG1pZ2N2NnQ3MjlwaDFraXJoaWF1ZWozZWggYmFtLmltLnNhbUBt', 'created': '2023-08-26T04:11:35.000Z', 'updated': '2023-08-26T04:11:35.163Z', 'summary': 'test', 'creator': {'email': 'bam.im.sam@gmail.com', 'self': True}, 'organizer': {'email': 'bam.im.sam@gmail.com', 'self': True}, 'start': {'dateTime': '2023-08-27T14:30:00-04:00', 'timeZone': 'America/Toronto'}, 'end': {'dateTime': '2023-08-27T15:30:00-04:00', 'timeZone': 'America/Toronto'}, 'iCalUID': '0migcv6t729ph1kirhiauej3eh@google.com', 'sequence': 0, 'reminders': {'useDefault': True}, 'eventType': 'default'}
|
|
|
|
for event in events:
|
|
|
|
print(event)
|
|
|
|
start = event['start'].get('dateTime', event['start'].get('date'))
|
|
|
|
end = event['end'].get('dateTime', event['end'].get('date'))
|
|
|
|
print(start, "->", end, event['summary'])
|
|
|
|
|
|
|
|
except HttpError as error:
|
|
|
|
print('An error occurred: %s' % error)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#TODO: Obtain calendar data and save to local database, parse into printable content
|