-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Anantha Halmuttur
committed
Jul 16, 2021
1 parent
9f357ca
commit 398e09b
Showing
10 changed files
with
452 additions
and
66 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
1626366631 | ||
1626437261 |
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
from __future__ import print_function | ||
import datetime | ||
import os.path | ||
from googleapiclient.discovery import build | ||
from google_auth_oauthlib.flow import InstalledAppFlow | ||
from google.auth.transport.requests import Request | ||
from google.oauth2.credentials import Credentials | ||
|
||
from colorama import Fore, Back, Style | ||
|
||
from datetime import datetime, timedelta | ||
|
||
import time | ||
|
||
import packet, secrets | ||
|
||
# The script needs userinfo.profile, for auth | ||
SCOPES = ['https://www.googleapis.com/auth/calendar.events', 'https://www.googleapis.com/auth/calendar', 'https://www.googleapis.com/auth/userinfo.profile'] | ||
|
||
def create_event(time_start, time_end, name, service_handler, colorId=7): | ||
|
||
formdate = '-'.join(str(datetime.now().strftime("%Y-%D-%M")).replace("/", "-").split("-")[0:3]) | ||
|
||
GMT_OFF = '+02:00' | ||
|
||
|
||
GMT_OFF = '+02:00' | ||
EVENT = { | ||
'summary': name, | ||
'colorId':colorId, | ||
'start': {'dateTime': formdate + "T" + str(timedelta(seconds=time_start+60*60)) + GMT_OFF}, | ||
'end': {'dateTime': formdate + "T" + str(timedelta(seconds=time_end+60*60)) + GMT_OFF}, | ||
} | ||
|
||
|
||
event = service_handler.events().insert(calendarId='primary', body=EVENT).execute() | ||
|
||
def minute_passed(oldepoch): | ||
return time.time() - oldepoch >= 60*60 | ||
|
||
|
||
def main(): | ||
|
||
sduiPackage = packet.Wrapper(TABLE_ID=305516, TIME_DELTA=0, TOKEN=secrets.token) | ||
|
||
"""Shows basic usage of the Google Calendar API. | ||
Prints the start and name of the next 10 events on the user's calendar. | ||
""" | ||
creds = None | ||
# The file token.json stores the user's access and refresh tokens, and is | ||
# created automatically when the authorization flow completes for the first | ||
# time. | ||
if os.path.exists('token.json'): | ||
creds = Credentials.from_authorized_user_file('token.json', SCOPES) | ||
# 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=0) | ||
# Save the credentials for the next run | ||
with open('token.json', 'w') as token: | ||
token.write(creds.to_json()) | ||
|
||
service = build('calendar', 'v3', credentials=creds) | ||
|
||
last_epoch = time.time() | ||
|
||
firstrun = True | ||
|
||
while True: | ||
if minute_passed(last_epoch) or firstrun: | ||
last_epoch = time.time() | ||
lessons = sduiPackage.get_lessons_for_day(3) | ||
combilist = [] | ||
combilist_timesort = [] | ||
|
||
|
||
|
||
for i in lessons[0]: | ||
combilist.append(i) | ||
|
||
for i in lessons[1]: | ||
flag = False | ||
|
||
for ix in combilist: | ||
if ix["subject"] == i["subject"]: | ||
try: | ||
ix["oftype"] | ||
except: | ||
pass | ||
else: | ||
flag=True | ||
if not flag: | ||
combilist.append(i) | ||
|
||
|
||
|
||
combilist = sorted(combilist, key=lambda x: x["beginn"]) | ||
|
||
|
||
for i in combilist: | ||
t=0 | ||
try: i["oftype"] | ||
except: | ||
|
||
t+=1 | ||
print(Fore.BLACK + Style.BRIGHT + Back.LIGHTGREEN_EX + | ||
"[ HOUR " + str(t) + " ]" + " ✔ Unchanged: " + Style.RESET_ALL) | ||
print(Fore.BLACK + Style.BRIGHT + Back.LIGHTGREEN_EX + | ||
" |-> " + i["subject"] + Style.RESET_ALL) | ||
|
||
create_event(i["beginn"], i["end"], i["subject"], service) | ||
|
||
else: | ||
t += 1 | ||
if i["oftype"] == "SUB": | ||
print(Fore.WHITE + Style.BRIGHT + Back.RED + "[ HOUR " + str(t) + " ]" + " ✖ Changed: " + Style.RESET_ALL) | ||
print(Fore.BLACK + Style.BRIGHT + Back.CYAN + " |->" + i["subject"] + Style.RESET_ALL) | ||
print(Fore.BLACK + Style.BRIGHT + Back.CYAN + " |--> To Teacher " + i["teacher"] + Style.RESET_ALL) | ||
|
||
create_event(i["beginn"], i["end"], i["subject"] + " --- Sub Teacher " + i["teacher"], service, colorId=4) | ||
|
||
|
||
|
||
elif i['oftype'] == "CANCLED": | ||
print(Fore.WHITE + Style.BRIGHT + Back.RED + "[ HOUR " + str(t) + " ]" + " ✖ Cancled: " + Style.RESET_ALL) | ||
print(Fore.WHITE + Style.BRIGHT + Back.LIGHTBLACK_EX + " |-> " + i["subject"] + " Cancled!" + Style.RESET_ALL) | ||
|
||
create_event(i["beginn"], i["end"], i["subject"] + " Cancled!", service, colorId=11) | ||
|
||
elif i["oftype"] == "CHANGE": | ||
print(Fore.WHITE + Style.BRIGHT + Back.RED + "[ HOUR " + str(t) + " ]" + " ✖ Changed: " + Style.RESET_ALL) | ||
print(Fore.BLACK + Style.BRIGHT + Back.CYAN + " |->" + i["subject"] + Style.RESET_ALL) | ||
print(Fore.BLACK + Style.BRIGHT + Back.MAGENTA + " |--> To Room " + i["room"] + Style.RESET_ALL) | ||
create_event(i["beginn"], i["end"], i["subject"] + " --- New Room " + i["room"], service,colorId=3) | ||
|
||
t=0 | ||
firstrun = False | ||
|
||
if __name__ == '__main__': | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
import os | ||
from datetime import datetime, date, timedelta | ||
from colorama import Fore, Back, Style | ||
import time | ||
import calendar | ||
import json | ||
import secrets | ||
import requests | ||
|
||
|
||
class Wrapper: | ||
def __init__(self, DEBUG: bool = False, MAX_DATA_LIFETIME: int = 3600, TABLE_ID: int = None, TIME_DELTA: int = 0, TOKEN: str = None): | ||
""" | ||
Wrapper class | ||
`DEBUG` enable debugging, default: False | ||
`MAX_DATA_LIFETIME` max lifetime of data file in seconds, will be automatically re-downloaded, default: 3600 | ||
`TABLE_ID` your table id, default: None | ||
`TIME_DELTA` difference in data in days, default: 0 | ||
`TOKEN` your bearer token, default: None | ||
:returns: [[changes to default schedule], []] | ||
""" | ||
self.DEBUG = DEBUG | ||
self.MAX_DATA_LIFETIME = MAX_DATA_LIFETIME | ||
self.TABLE_ID = TABLE_ID | ||
self.TIME_DELTA = TIME_DELTA | ||
self.TOKEN = TOKEN | ||
|
||
def unix2dt(self, ts): | ||
""" | ||
Convert unix timestamp to datetime | ||
""" | ||
return datetime.utcfromtimestamp(int(ts)).strftime('%Y-%m-%d %H:%M:%S') | ||
|
||
|
||
def dt2unix(self, dt): | ||
""" | ||
Convert datetime to unix timestamp | ||
""" | ||
return calendar.timegm(dt.utctimetuple()) | ||
|
||
# TABLES: AnnikenYT:305870 BigBoy32:305516 | ||
|
||
|
||
def load_data(self): | ||
""" | ||
Load data from downloaded data | ||
""" | ||
if not os.path.exists('LAST_DOWNLOAD'): | ||
self.get_data() | ||
with open("LAST_DOWNLOAD", "r") as file: | ||
last_download = file.read() | ||
if last_download.strip() != "": | ||
last_download = self.unix2dt(last_download) | ||
last = datetime.strptime(last_download, "%Y-%m-%d %H:%M:%S") | ||
diff = datetime.now() - last | ||
if diff.total_seconds() >= self.MAX_DATA_LIFETIME: | ||
self.get_data(self.TABLE_ID) | ||
return json.load(open("data.json", "r")) | ||
else: | ||
return json.load(open("data.json", "r")) | ||
else: | ||
self.get_data(self.TABLE_ID) | ||
return json.load(open("data.json", "r")) | ||
|
||
|
||
def get_data(self): | ||
""" | ||
Download data to file | ||
""" | ||
with open("LAST_DOWNLOAD", "w+") as file: | ||
file.seek(0) | ||
file.write(str(self.dt2unix(datetime.now()))) | ||
print(Fore.RED + "Data too old, downloading new data." + Style.RESET_ALL) | ||
url = f'https://api.sdui.app/v1/users/{str(self.TABLE_ID)}/timetable' | ||
headers = { | ||
"authorization": self.TOKEN, | ||
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36" | ||
} | ||
r = requests.get(url, headers=headers) | ||
json.dump(r.json(), open("data.json", "w+")) | ||
|
||
|
||
def cleanlist(self, lst): | ||
fixed_list = [] | ||
broken_list = [] | ||
|
||
for i in lst: | ||
if str(i) not in broken_list and i != []: | ||
broken_list.append(str(i)) | ||
fixed_list.append(i) | ||
return fixed_list | ||
|
||
def get_lessons_for_day(self, delta: int = 0): | ||
""" | ||
Get lessons for a specific day | ||
""" | ||
self.TIME_DELTA = delta | ||
datetoday=datetime.now().replace( | ||
hour=22, minute=0, second=0)-timedelta(self.TIME_DELTA+1) | ||
print(Fore.CYAN + Style.BRIGHT + | ||
f"Checking lessons for {datetoday.date()+timedelta(1)}" + Style.RESET_ALL) | ||
|
||
try: | ||
jdata = self.load_data() | ||
lessons = jdata["data"]["lessons"] | ||
except: | ||
print(Fore.RED + "Something seems to be wrong with your JSON file. Redownloading..." + Style.RESET_ALL) | ||
os.remove("LAST_DOWNLOAD") | ||
jdata = self.load_data() | ||
lessons = jdata["data"]["lessons"] | ||
skip = [] | ||
found = [] | ||
|
||
for i in lessons: | ||
if lessons[i] is not None: | ||
|
||
for d in lessons[i]["dates"]: | ||
unixtoday = self.dt2unix(datetoday) | ||
checkdate = unixtoday | ||
lessondate = d | ||
|
||
if lessons[i]["substituted_target_lessons"] != []: | ||
for targets in lessons[i]["substituted_target_lessons"]: | ||
for targetdate in targets["dates"]: | ||
if targetdate == checkdate: | ||
if targets["kind"] == "SUBSTITUTION": | ||
skip.append({"subject":targets["subject"]["meta"]["displayname"], "oftype":"SUB", "teacher":targets["teachers"][0]["name"],"beginn":targets["time_begins_at"], "end":targets["time_ends_at"],}) | ||
elif targets["kind"] == "CANCLED": | ||
skip.append({"subject":targets["course"]["meta"]["displayname"], "oftype":"CANCLED", "beginn":targets["time_begins_at"], "end":targets["time_ends_at"]}) | ||
else: | ||
pass | ||
if self.DEBUG: | ||
print(Fore.BLACK + Style.DIM + | ||
f"Checking date: {lessondate} against today's date {checkdate}" + Style.RESET_ALL) | ||
if lessondate == checkdate: | ||
found.append({"subject":lessons[i]["meta"]["displayname"], "beginn":lessons[i]["time_begins_at"], "end":lessons[i]["time_ends_at"]}) | ||
|
||
else: | ||
if self.DEBUG: | ||
print(Fore.BLACK + Style.BRIGHT + Back.RED + | ||
"✖ Nothing Found" + Style.RESET_ALL) | ||
|
||
return [self.cleanlist(skip), found] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
global token | ||
token = "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiIxMDAwNyIsImp0aSI6ImU2ZDAzOWQyN2I3YTdhZGM2NjNkZDRkNWQwNjQyOTVmMTZhYzBmZjEzNDFkYzUxNzdlNTY0NThhN2EzYzc1NDc1ZDlhZGVmNDJiNzg1NTQ5IiwiaWF0IjoxNjI2MTU1MTY3LCJuYmYiOjE2MjYxNTUxNjcsImV4cCI6MTY1NzY5MTE2Nywic3ViIjoiMzA1NTE2Iiwic2NvcGVzIjpbXX0.x2-faEeKqfB_djBzvzONYsRhkr5M-A73KYUzSJAIuk0U3bDNFPQeJp0yW73aZDFJSHUySj2IsV02kMNRomcBO3PyPK2G5pAJ0jaRtdHmCJLPB7b9DB9Hh58O3fZ-LTiYSeVUael1e-ySh5jpdKLfvgy2C1MGE-fwTfrV16tQZbA-L2VjQ4-yc73rufeifVsK8ni_JZAFjR_9L7R1Yn6loMWQaFagSQ18jT6CF2mUrkdYf2R_n_5lelHwb4WSXnLtDLNkxaKNG1Z5VmtdyllYXuPDw80pO5xcO0eR7p4SpKtUaNA0ydII__kTkauEH6nWXGpCpvgMRq8XcmreXhZpGOIDiLvTwjltdZg6vER_TZJRnvTizyXsFxTa9qzYOa5PlOU7Z--rj5_GASfOrIO0-YWWcidqwievtb5E6EtUM3jM2PGFUryy08gtY0jjj0_lTxhw-zi4k56XWJS3iMP7Ed6kAIfz3hvygZwt5zVhPJC66fKFIqYiKKLlRYhh4nQRyrErWeO63mnayYxw89PR3ep_VvZhqhk6hcYkPBIw8a8_OXSj8HJfPuVArl1fB1w4giGHG9Uv8NSNack-WeuZSuP9IDT6qEYJWKrcVRTd7gkXkv3uCE3umQFlYOUvgkyHz-Lt4KxUAKqH3uuYrIyAdQGyLcQ2l37JFsR1KyVkZvE" |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.