Compare commits
6 Commits
87a229f791
...
master
Author | SHA1 | Date | |
---|---|---|---|
f939127a0c | |||
056779f7d2 | |||
fec09edb88 | |||
45cd71cc4b | |||
1a5700e9a0 | |||
183bf60fc0 |
129
__init__.py
129
__init__.py
@ -8,6 +8,7 @@ from google_auth_oauthlib.flow import InstalledAppFlow
|
||||
from google.auth.transport.requests import Request
|
||||
|
||||
from server import db
|
||||
from database.models import Calendar as dbCalendar
|
||||
|
||||
# If modifying these scopes, delete the file token.pickle.
|
||||
SCOPES = ["https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile", "https://www.googleapis.com/auth/calendar.readonly", "openid"]
|
||||
@ -15,8 +16,9 @@ API_SERVICE_NAME = 'calendar'
|
||||
API_VERSION = 'v3'
|
||||
|
||||
class Calendar:
|
||||
def __init__(self, name, calendarId, toggle='False', color="#000000"):
|
||||
def __init__(self, name, calendarId, calType, toggle='False', color="#000000"):
|
||||
self.name = name
|
||||
self.calType = calType
|
||||
self.color = color
|
||||
self.toggle=toggle
|
||||
self.calendarId = calendarId
|
||||
@ -24,9 +26,7 @@ class Calendar:
|
||||
class Event:
|
||||
def __init__(self, name_, start_, end_):
|
||||
self.name = name_
|
||||
self.eventColorId = 0
|
||||
self.calendarColorId = None
|
||||
self.naturalColorId = 0
|
||||
self.eventColorId = None
|
||||
self.start = start_
|
||||
self.end = end_
|
||||
self.colorHex = '#adfff5'
|
||||
@ -65,44 +65,12 @@ class Event:
|
||||
def print(self):
|
||||
if self.allDay:
|
||||
print(self.name + "All Day")
|
||||
else:
|
||||
print(self.name + ": " + self.naturalColorId)
|
||||
|
||||
|
||||
|
||||
def calendarCredentials(token = None):
|
||||
creds = None
|
||||
# The file token.pickle stores the user's access and refresh tokens, and is
|
||||
# created automatically when the authorization flow completes for the first
|
||||
# time.
|
||||
|
||||
if token == None:
|
||||
if os.path.exists('token.pickle'):
|
||||
with open('token.pickle', 'rb') as token:
|
||||
token.seek(0)
|
||||
creds = pickle.load(token)
|
||||
|
||||
else:
|
||||
creds = pickle.load(token)
|
||||
|
||||
# If there are no (valid) credentials available, let the user log in.
|
||||
if not creds or not creds.valid:
|
||||
if creds and creds.expired and creds.refresh_token:
|
||||
creds.refresh(Request())
|
||||
else:
|
||||
flow = InstalledAppFlow.from_client_secrets_file(
|
||||
'credentials.json', SCOPES)
|
||||
creds = flow.run_local_server(port=1234)
|
||||
# Save the credentials for the next run
|
||||
with open('token.pickle', 'wb') as token:
|
||||
pickle.dump(creds, token)
|
||||
|
||||
service = build('calendar', 'v3', credentials=creds)
|
||||
|
||||
return service
|
||||
|
||||
def updateCalendars(user, calendars, colors):
|
||||
|
||||
if user == None or calendars == None or colors == None:
|
||||
return
|
||||
COLORS_FILE = os.path.join(os.path.dirname(__file__), 'colors.json')
|
||||
with open(COLORS_FILE) as f:
|
||||
colormap = json.load(f)
|
||||
@ -113,12 +81,13 @@ def updateCalendars(user, calendars, colors):
|
||||
for calendar in calendars:
|
||||
if not user.hasCalendar(calendar.calendarId):
|
||||
color = fromColorIdGetColor(calendar.color, colormap, colors)
|
||||
c = dbCalendar(calendar_id=calendar.calendarId,
|
||||
name = calendar.summary,
|
||||
c = dbCalendar(calendar_id = calendar.calendarId,
|
||||
calendar_type = calendar.calType,
|
||||
name = calendar.name,
|
||||
toggle = "False",
|
||||
color = color)
|
||||
db.session.add(c)
|
||||
current_user.calendars.append(c)
|
||||
user.calendars.append(c)
|
||||
|
||||
db.session.commit()
|
||||
|
||||
@ -129,12 +98,13 @@ def calendarsFromDb(user):
|
||||
calendarId = calendar.calendar_id
|
||||
toggle = calendar.toggle
|
||||
color = calendar.color
|
||||
calType = calendar.calendar_type
|
||||
|
||||
pyCalendars.append(Calendar(name, calendarId, toggle, color))
|
||||
pyCalendars.append(Calendar(name, calendarId, calType, toggle, color))
|
||||
|
||||
return pyCalendars
|
||||
|
||||
|
||||
# removes not visible calendars from the list of all calendars
|
||||
def purgeCalendars(calendars, visibleCalendars):
|
||||
purged = []
|
||||
for calendar in calendars:
|
||||
@ -142,48 +112,8 @@ def purgeCalendars(calendars, visibleCalendars):
|
||||
purged.append(calendar)
|
||||
return purged
|
||||
|
||||
def getCalendarEvents(service, userCalendars, startDate, endDate):
|
||||
|
||||
|
||||
visualCals = []
|
||||
for calendar in userCalendars:
|
||||
if calendar.toggle == 'True':
|
||||
visualCals.append(calendar.calendar_id)
|
||||
|
||||
calendars = getCalendars(service)
|
||||
calendars = purgeCalendars(calendars, visualCals)
|
||||
|
||||
all_events = []
|
||||
|
||||
|
||||
for calendar in calendars:
|
||||
events_result = service.events().list(calendarId=calendar.calendarId, timeMin=startDate,
|
||||
timeMax=endDate,
|
||||
maxResults=10, singleEvents=True,
|
||||
orderBy='startTime').execute()
|
||||
for event in events_result.get('items', []):
|
||||
|
||||
# create simple event
|
||||
name = event.get('summary', '(no Title)')
|
||||
start = event['start'].get('dateTime')
|
||||
end = event['end'].get('dateTime')
|
||||
newEvent = Event(name, start, end)
|
||||
|
||||
# handle weird colors from google
|
||||
color = event.get('colorId')
|
||||
if color == None:
|
||||
for userCalendar in userCalendars:
|
||||
if userCalendar.calendar_id == calendar.calendarId:
|
||||
newEvent.calendarHex = userCalendar.color
|
||||
newEvent.calendarColorId = calendar.color
|
||||
else:
|
||||
newEvent.eventColorId = color
|
||||
|
||||
|
||||
all_events.append(newEvent)
|
||||
|
||||
return all_events
|
||||
|
||||
# remaps a event color id to a calendar color id
|
||||
# for google calendars
|
||||
def toCalendarColorId(colormap, colorId):
|
||||
for remap in colormap['eventRemap']:
|
||||
if remap['from'] == colorId:
|
||||
@ -192,6 +122,8 @@ def toCalendarColorId(colormap, colorId):
|
||||
print(f"failed with {colorId}")
|
||||
return colorId
|
||||
|
||||
# remaps a calendar color ID to its natural color
|
||||
# for google calendars
|
||||
def toNaturalColor(colormap, orgColor):
|
||||
for remap in colormap['colors']:
|
||||
if remap['api'] == orgColor:
|
||||
@ -200,28 +132,31 @@ def toNaturalColor(colormap, orgColor):
|
||||
print(f"failed with {orgColor}")
|
||||
return orgColor
|
||||
|
||||
def colorizeEvents(events, colors):
|
||||
# uses the event color id to convert it to a hex color
|
||||
# does this for every event in events
|
||||
# this is used for Google Calendars
|
||||
def colorizeGoogleEvents(events, colors):
|
||||
COLORS_FILE = os.path.join(os.path.dirname(__file__), 'colors.json')
|
||||
with open(COLORS_FILE) as f:
|
||||
colormap = json.load(f)
|
||||
|
||||
|
||||
for event in events:
|
||||
if event.calendarColorId != None:
|
||||
if event.eventColorId != None:
|
||||
event.colorHex = forEventGetColor(event, colormap, colors)
|
||||
|
||||
# this function is only used once for calendar generation stuff
|
||||
# returns a color for a specific calendar color id
|
||||
# for google calendars
|
||||
def fromColorIdGetColor(color, colormap, colors):
|
||||
return toNaturalColor(colormap, colors['calendar'][color]['background'])
|
||||
|
||||
# generates the natural color for a event color id
|
||||
# for google calendars
|
||||
def forEventGetColor(event, colormap, colors):
|
||||
if event.calendarColorId != 0:
|
||||
bg = colors['calendar'][event.calendarColorId]['background']
|
||||
else:
|
||||
calColorId = toCalendarColorId(colormap, event.eventColorId)
|
||||
bg = colors['calendar'][calColorId]['background']
|
||||
return toNaturalColor(colormap, bg)
|
||||
|
||||
# exports all events into a jsonable format (excluding all day events)
|
||||
def toJson(events):
|
||||
data = {}
|
||||
data['kind'] = 'calendar#events'
|
||||
@ -241,30 +176,32 @@ def toJson(events):
|
||||
|
||||
return data
|
||||
|
||||
# debug functions which prints color names
|
||||
def printColors(colors):
|
||||
for i in range(1, 25):
|
||||
col = colors['event'][str(i)]['background']
|
||||
print(f"{i}: {col}")
|
||||
|
||||
def main():
|
||||
generateJsonFromCalendarEntries()
|
||||
return
|
||||
|
||||
|
||||
def getTimeStamps():
|
||||
|
||||
# define today and tomorrow
|
||||
now = datetime.datetime.now(datetime.timezone.utc).astimezone()
|
||||
today = now.replace(hour=0, minute=0, second = 0).isoformat()
|
||||
today = now.replace(hour=0, minute=0, second = 0)
|
||||
tomorrow = now.replace(hour=23, minute=59, second=59).isoformat() # + '+01:00'
|
||||
twodaysfromnow = datetime.datetime.today() + datetime.timedelta(days=2)
|
||||
twodaysfromnow = twodaysfromnow.replace(hour=23, minute=59, second=59).astimezone().isoformat()
|
||||
twodaysfromnow = twodaysfromnow.replace(hour=23, minute=59, second=59).astimezone()
|
||||
|
||||
return today, twodaysfromnow
|
||||
|
||||
def generateJsonFromCalendarEntries(events, colors):
|
||||
|
||||
# fix all colors in events that have a different event color
|
||||
colorizeEvents(events, colors)
|
||||
if colors != None:
|
||||
colorizeGoogleEvents(events, colors)
|
||||
# if not events:
|
||||
# print('No upcoming events found.')
|
||||
|
||||
|
68
icalHandler.py
Normal file
68
icalHandler.py
Normal file
@ -0,0 +1,68 @@
|
||||
from server import db
|
||||
from database.models import Calendar as dbCalendar
|
||||
from backend import Event as bEvent
|
||||
from ics import Calendar as iCalendar
|
||||
import requests
|
||||
|
||||
def icalToCalendarDb(url, name, user):
|
||||
try:
|
||||
c = iCalendar(requests.get(url).text)
|
||||
except:
|
||||
return False
|
||||
|
||||
|
||||
c = dbCalendar(calendar_id = url,
|
||||
calendar_type = 'ical',
|
||||
name = name,
|
||||
toggle = "False",
|
||||
color = "#000000")
|
||||
db.session.add(c)
|
||||
user.calendars.append(c)
|
||||
db.session.commit()
|
||||
|
||||
def fetchCalendarEvents(calendars, startDate, endDate):
|
||||
|
||||
all_events = []
|
||||
for calendar in calendars:
|
||||
if calendar.toggle == "True" and calendar.calendar_type == "ical":
|
||||
ical = iCalendar(requests.get(calendar.calendar_id).text)
|
||||
for event in ical.events:
|
||||
event = fitEventToCalendarTimezone(event, ical)
|
||||
name = event.name
|
||||
start = event.begin.format()
|
||||
end = event.end.format()
|
||||
|
||||
newEvent = bEvent(name, start, end)
|
||||
|
||||
|
||||
if eventWithinStartEnd(startDate, endDate, event):
|
||||
if not eventAllDay(event):
|
||||
|
||||
print(start, flush=True)
|
||||
all_events.append(newEvent)
|
||||
|
||||
return all_events
|
||||
|
||||
def fitEventToCalendarTimezone(event, calendar):
|
||||
event.begin = event.begin.to(next(iter(calendar._timezones)))
|
||||
event.end = event.end.to(next(iter(calendar._timezones)))
|
||||
return event
|
||||
|
||||
# converts everything to epoch seconds and utc
|
||||
# and then checks if at either event start or event end
|
||||
# is is within startDate and endDate
|
||||
def eventWithinStartEnd(startDate, endDate, event):
|
||||
if((startDate.timestamp() <= event.begin.timestamp and
|
||||
event.begin.timestamp <= endDate.timestamp()) or
|
||||
startDate.timestamp() <= event.end.timestamp and
|
||||
event.end.timestamp <= endDate.timestamp()):
|
||||
return True
|
||||
return False
|
||||
|
||||
def eventAllDay(event):
|
||||
beginDay = event.begin.replace(hour=0, minute=0, second=0)
|
||||
endDay = event.end.replace(hour=0, minute=0, second=0)
|
||||
delta = endDay - beginDay
|
||||
if delta.days >= 2:
|
||||
return True
|
||||
return False
|
Reference in New Issue
Block a user