132 lines
5.0 KiB
Python
Executable File
132 lines
5.0 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# Script to import a timetable from the app ClassTime into a google calendar.
|
|
# Calendar ID is found in the calendar's settings, DB file can be exported through the share button in the app.
|
|
# Only works with A/B timetables, which are exported separately.
|
|
|
|
import json, datetime, pickle, os.path, sys, argparse
|
|
from googleapiclient.discovery import build
|
|
from google_auth_oauthlib.flow import InstalledAppFlow
|
|
from google.auth.transport.requests import Request
|
|
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("timetable", help="filename of .timetable db.")
|
|
parser.add_argument("-tz", "--timezone", help="Timezone in TZ database format. Defaults to Europe/London.")
|
|
parser.add_argument("-c", "--calendar", help="ID of the calendar you are adding to. Found under the settings on calendar.google.com.")
|
|
try:
|
|
args = parser.parse_args()
|
|
calendar_id = args.calendar
|
|
dbfile = args.timetable
|
|
if not args.timezone:
|
|
timeZone = "Europe/London"
|
|
else:
|
|
timeZone = args.timezone
|
|
except FileNotFoundError:
|
|
print("No filename supplied.")
|
|
sys.exit()
|
|
|
|
print("This script only works for A/B week timetables, each being loaded seperately.")
|
|
choice = input("Is this timetable made for this week? [y/n]: ").lower()
|
|
if choice == "y":
|
|
today = datetime.datetime.today()
|
|
elif choice == "n":
|
|
today = datetime.datetime.today() + datetime.timedelta(days=7)
|
|
else:
|
|
sys.exit()
|
|
|
|
days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
|
|
|
|
class Lesson:
|
|
def __init__(self, name, startDelta, endDelta, teacher, room, day):
|
|
self.summary = name
|
|
if teacher != "":
|
|
self.description = "Teacher: {}".format(teacher)
|
|
self.location = "Room: {}".format(room)
|
|
currentDay = days.index(today.strftime("%A"))
|
|
lessonDay = days.index(day)
|
|
dayDelta = lessonDay - currentDay
|
|
applyDate = (today + datetime.timedelta(days=dayDelta)).day
|
|
# the .timetable file stores lesson start & end times as minutes from 00:00, so they are converted here
|
|
self.start = {
|
|
"dateTime": datetime.datetime(today.year, today.month, applyDate, int(startDelta/60), int(startDelta%60)).isoformat(),
|
|
"timeZone": timeZone
|
|
}
|
|
self.end = {
|
|
"dateTime": datetime.datetime(today.year, today.month, applyDate, int(endDelta/60), int(endDelta%60)).isoformat(),
|
|
"timeZone": timeZone
|
|
}
|
|
# Change this if you have the same timetable each week
|
|
self.recurrence = ["RRULE:FREQ=WEEKLY;INTERVAL=2"]
|
|
|
|
|
|
|
|
lessons = []
|
|
try:
|
|
with open(dbfile, "r") as raw:
|
|
db = json.load(raw)
|
|
for d in range(1,6):
|
|
try:
|
|
for l in range(1,6):
|
|
name = db["LESSON_{}_{}".format(d,l)]
|
|
startDelta = db["LESSON_START_TIME_{}_{}".format(d,l)]
|
|
endDelta = db["LESSON_END_TIME_{}_{}".format(d,l)]
|
|
teacher = db["TEACHER_{}_{}".format(d,l)]
|
|
room = db["ROOM_{}_{}".format(d,l)]
|
|
day = days[d-1]
|
|
if name != "":
|
|
lessons.append(Lesson(name, startDelta, endDelta, teacher, room, day))
|
|
except:
|
|
pass
|
|
except FileNotFoundError:
|
|
print("File not found.")
|
|
sys.exit()
|
|
|
|
print("Lessons imported. Do these look right?")
|
|
for l in lessons:
|
|
try:
|
|
d = l.description+", "
|
|
except:
|
|
d = ""
|
|
print("{}: {}, {}{}".format(l.start["dateTime"], l.summary, d, l.location))
|
|
if input(":) ? [y/n]: ").lower() != "y":
|
|
sys.exit()
|
|
|
|
# Copyright 2018 Google LLC
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
# borrowed from https://github.com/gsuitedevs/python-samples/blob/master/drive/quickstart/quickstart.py
|
|
# Removed unnecessary libraries, comments, and changed scope.
|
|
SCOPES = ['https://www.googleapis.com/auth/calendar']
|
|
|
|
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)
|
|
# Save the credentials for the next run
|
|
with open('token.pickle', 'wb') as token:
|
|
pickle.dump(creds, token)
|
|
|
|
service = build('calendar', 'v3', credentials=creds)
|
|
|
|
for l in lessons:
|
|
event = json.loads(json.dumps(l.__dict__))
|
|
event = service.events().insert(calendarId=calendar_id, body=event).execute()
|
|
print("Events Added. Refresh your calendar to see classes.")
|