--- /dev/null
+from __future__ import print_function
+import pickle
+import os.path
+from googleapiclient.discovery import build
+from google_auth_oauthlib.flow import InstalledAppFlow
+from google.auth.transport.requests import Request
+
+"""
+Resource to update Google Calendar using credentials.json in Working Directory.
+
+A token.pickle file will be created for permissions to Google Calendar.
+
+Author: Nils Forssén, Jämtland County, Sweden
+"""
+
+EVENT_COLORIDS = {
+ "blue": 1,
+ "green": 2,
+ "purple": 3,
+ "red": 4,
+ "yellow": 5,
+ "orange": 6,
+ "turquoise": 7,
+ "gray": 8,
+ "b_blue": 9,
+ "b_green": 10,
+ "b_red": 11
+}
+
+
+# Give accesss to complete Google Calendar
+SCOPES = ["https://www.googleapis.com/auth/calendar.events"]
+
+def getCredentials():
+ """
+ Get the current credentials from the pickle file,
+ If not available, create new file with credentials
+ """
+
+ creds = None
+ if os.path.exists("token.pickle"):
+ with open("token.pickle", "rb") as token:
+ creds = pickle.load(token)
+
+ 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=0)
+ with open("token.pickle", "wb") as token:
+ pickle.dump(creds, token)
+
+ return creds
+
+
+service = build('calendar', 'v3', credentials=getCredentials())
+
+def createEvent(event):
+ """
+ Create google calendar event using the standard event formatting
+ """
+
+ event = service.events().insert(calendarId="primary", body=event).execute()
+
+ return event
+
+
+def deleteEvent(eventId):
+ """
+ Delete event with given id from google calendar
+ """
+
+ service.events().delete(calendarId="primary", eventId=eventId).execute()
+
+
+def listEvents(**kwargs):
+ """
+ Return list of all google calendar events
+ """
+
+ events_result = service.events().list(calendarId="primary", singleEvents=True, orderBy='startTime', **kwargs).execute()
+
+ events = events_result.get('items', [])
+
+ return events
--- /dev/null
+#!/usr/bin/env python3
+
+import requests
+from bs4 import BeautifulSoup
+import datetime
+from dataclasses import dataclass
+import re
+import googleCalendar
+
+headers = {
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.122 Safari/537.36"
+}
+
+TIMEEDIT_URLS = ["https://cloud.timeedit.net/liu/web/schema/ri167XQQ618Z50Qm07060gZ6y6Y7509Q6Y95Y2.html"]
+
+
+@dataclass
+class event:
+ summary: str
+ description: str
+ start: datetime.datetime
+ end: datetime.datetime
+ t_offset: str = "+01:00"
+
+ def get_gc_event(self):
+ event = {
+ "summary": self.summary,
+ "description": self.description,
+ "start": {
+ "dateTime": "{0}T{1}{2}".format(
+ self.start.date(), self.start.time(), self.t_offset
+ )
+ },
+ "end": {
+ "dateTime": "{0}T{1}{2}".format(
+ self.end.date(), self.end.time(), self.t_offset
+ )
+ },
+ "reminders": {
+ "useDefault": False,
+ "overrides": [], # Reminders would drive me crazy
+ },
+ "colorId": googleCalendar.EVENT_COLORIDS["blue"],
+ }
+
+ return event
+
+
+def get_timeedit_events(session):
+ for schedule_URL in TIMEEDIT_URLS:
+ data = session.get(
+ schedule_URL,
+ headers=headers,
+ verify=False
+ )
+
+ soup = BeautifulSoup(data.content, features="lxml")
+ table = soup.find("table", attrs={"class": "restable"})
+ rows = table.find_all("tr")
+
+ schedule = []
+ active_day = ""
+ for row in rows[2:]:
+ date = row.find("td", attrs={"class": "headline t"})
+ if date is not None:
+ match = re.search(r"\d{4}-\d{2}-\d{2}", date.text.strip())
+ active_day = match.group()
+ else:
+ try:
+ time = row.find("td", attrs={"class": "time tt c-1"})
+ if time is not None:
+ info = [
+ col.text.strip()
+ for col in row.find_all("td")
+ if "columnLine" in col["class"]
+ ]
+ summary = f"{info[0]} - {info[1]}, {info[2]}"
+ description = f"{info[0]}, {info[1]}, {info[2]}, {info[3]}, {info[5]}, {info[5]}\nautogen_nils\nCreated: {datetime.datetime.now()}"
+ active_time = time.text.strip()
+ start = datetime.datetime.strptime(
+ active_day + active_time[:5], "%Y-%m-%d%H:%M"
+ )
+ end = datetime.datetime.strptime(
+ active_day + active_time[8:], "%Y-%m-%d%H:%M"
+ )
+ schedule.append(event(summary, description, start, end))
+ except Exception as e:
+ print(e)
+ else:
+ print(f"strange row: {row.content}")
+ return schedule
+
+
+def reset_gc_events(schedule):
+ for c_event in googleCalendar.listEvents(
+ **{
+ "timeMin": "{0}T{1}{2}".format(
+ schedule[0].start.date(), schedule[0].start.time(), schedule[0].t_offset
+ )
+ }
+ ):
+ try:
+ if f"\nautogen_nils" in c_event["description"]:
+ googleCalendar.deleteEvent(c_event["id"])
+ except KeyError:
+ pass
+
+ for n_event in schedule:
+ googleCalendar.createEvent(n_event.get_gc_event())
+ print(f"Created: {n_event}\n")
+
+
+if __name__ == "__main__":
+
+ with requests.session() as session:
+
+ timeedit_schedule = get_timeedit_events(session)
+
+ reset_gc_events(timeedit_schedule)