Initial commit
authorNils ForssÃén <forssennils@gmail.com>
Tue, 5 Dec 2023 01:24:55 +0000 (02:24 +0100)
committerNils ForssÃén <forssennils@gmail.com>
Tue, 5 Dec 2023 01:24:55 +0000 (02:24 +0100)
googleCalendar.py [new file with mode: 0755]
main.py [new file with mode: 0755]

diff --git a/googleCalendar.py b/googleCalendar.py
new file mode 100755 (executable)
index 0000000..e87cf64
--- /dev/null
@@ -0,0 +1,87 @@
+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
diff --git a/main.py b/main.py
new file mode 100755 (executable)
index 0000000..2429f03
--- /dev/null
+++ b/main.py
@@ -0,0 +1,119 @@
+#!/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)