Compare commits

...

4 Commits

Author SHA1 Message Date
f939127a0c updates ical output to convert event times to calendar timzone based time 2020-07-25 19:26:49 +02:00
056779f7d2 adds ical url handling
- icalToCalendarDB converts the information the user puts into the form
  on the calendar.html page and pulls the calendar from the url.
  It then passes it into the database.

- fetchCanedarEvents gets all events within a startDate and an endDate
  and removes any all day events. This is currently a bit costly, because
  it takes some time for the ics library to download the entire .ical
  file from the url. Then it goes through every entry ever added to the
  file and saves only the future events.
2020-07-25 18:03:02 +02:00
fec09edb88 adds calendar_type settings to calendar 2020-07-25 11:27:24 +02:00
45cd71cc4b code commenting and cleanup 2020-07-10 10:10:07 +02:00
2 changed files with 94 additions and 43 deletions

View File

@ -16,8 +16,9 @@ API_SERVICE_NAME = 'calendar'
API_VERSION = 'v3' API_VERSION = 'v3'
class Calendar: 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.name = name
self.calType = calType
self.color = color self.color = color
self.toggle=toggle self.toggle=toggle
self.calendarId = calendarId self.calendarId = calendarId
@ -65,37 +66,6 @@ class Event:
if self.allDay: if self.allDay:
print(self.name + "All Day") print(self.name + "All Day")
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): def updateCalendars(user, calendars, colors):
@ -111,7 +81,8 @@ def updateCalendars(user, calendars, colors):
for calendar in calendars: for calendar in calendars:
if not user.hasCalendar(calendar.calendarId): if not user.hasCalendar(calendar.calendarId):
color = fromColorIdGetColor(calendar.color, colormap, colors) color = fromColorIdGetColor(calendar.color, colormap, colors)
c = dbCalendar(calendar_id=calendar.calendarId, c = dbCalendar(calendar_id = calendar.calendarId,
calendar_type = calendar.calType,
name = calendar.name, name = calendar.name,
toggle = "False", toggle = "False",
color = color) color = color)
@ -127,12 +98,13 @@ def calendarsFromDb(user):
calendarId = calendar.calendar_id calendarId = calendar.calendar_id
toggle = calendar.toggle toggle = calendar.toggle
color = calendar.color color = calendar.color
calType = calendar.calendar_type
pyCalendars.append(Calendar(name, calendarId, toggle, color)) pyCalendars.append(Calendar(name, calendarId, calType, toggle, color))
return pyCalendars return pyCalendars
# removes not visible calendars from the list of all calendars
def purgeCalendars(calendars, visibleCalendars): def purgeCalendars(calendars, visibleCalendars):
purged = [] purged = []
for calendar in calendars: for calendar in calendars:
@ -140,7 +112,8 @@ def purgeCalendars(calendars, visibleCalendars):
purged.append(calendar) purged.append(calendar)
return purged return purged
# remaps a event color id to a calendar color id
# for google calendars
def toCalendarColorId(colormap, colorId): def toCalendarColorId(colormap, colorId):
for remap in colormap['eventRemap']: for remap in colormap['eventRemap']:
if remap['from'] == colorId: if remap['from'] == colorId:
@ -149,6 +122,8 @@ def toCalendarColorId(colormap, colorId):
print(f"failed with {colorId}") print(f"failed with {colorId}")
return colorId return colorId
# remaps a calendar color ID to its natural color
# for google calendars
def toNaturalColor(colormap, orgColor): def toNaturalColor(colormap, orgColor):
for remap in colormap['colors']: for remap in colormap['colors']:
if remap['api'] == orgColor: if remap['api'] == orgColor:
@ -157,25 +132,31 @@ def toNaturalColor(colormap, orgColor):
print(f"failed with {orgColor}") print(f"failed with {orgColor}")
return 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') COLORS_FILE = os.path.join(os.path.dirname(__file__), 'colors.json')
with open(COLORS_FILE) as f: with open(COLORS_FILE) as f:
colormap = json.load(f) colormap = json.load(f)
for event in events: for event in events:
print(event.colorHex, flush=True)
if event.eventColorId != None: if event.eventColorId != None:
event.colorHex = forEventGetColor(event, colormap, colors) 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): def fromColorIdGetColor(color, colormap, colors):
return toNaturalColor(colormap, colors['calendar'][color]['background']) return toNaturalColor(colormap, colors['calendar'][color]['background'])
# generates the natural color for a event color id
# for google calendars
def forEventGetColor(event, colormap, colors): def forEventGetColor(event, colormap, colors):
calColorId = toCalendarColorId(colormap, event.eventColorId) calColorId = toCalendarColorId(colormap, event.eventColorId)
bg = colors['calendar'][calColorId]['background'] bg = colors['calendar'][calColorId]['background']
return toNaturalColor(colormap, bg) return toNaturalColor(colormap, bg)
# exports all events into a jsonable format (excluding all day events)
def toJson(events): def toJson(events):
data = {} data = {}
data['kind'] = 'calendar#events' data['kind'] = 'calendar#events'
@ -195,30 +176,32 @@ def toJson(events):
return data return data
# debug functions which prints color names
def printColors(colors): def printColors(colors):
for i in range(1, 25): for i in range(1, 25):
col = colors['event'][str(i)]['background'] col = colors['event'][str(i)]['background']
print(f"{i}: {col}") print(f"{i}: {col}")
def main(): def main():
generateJsonFromCalendarEntries() return
def getTimeStamps(): def getTimeStamps():
# define today and tomorrow # define today and tomorrow
now = datetime.datetime.now(datetime.timezone.utc).astimezone() 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' tomorrow = now.replace(hour=23, minute=59, second=59).isoformat() # + '+01:00'
twodaysfromnow = datetime.datetime.today() + datetime.timedelta(days=2) 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 return today, twodaysfromnow
def generateJsonFromCalendarEntries(events, colors): def generateJsonFromCalendarEntries(events, colors):
# fix all colors in events that have a different event color # fix all colors in events that have a different event color
colorizeEvents(events, colors) if colors != None:
colorizeGoogleEvents(events, colors)
# if not events: # if not events:
# print('No upcoming events found.') # print('No upcoming events found.')

68
icalHandler.py Normal file
View 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