import base64 from datetime import datetime import json import os import threading import time import schedule from dotenv import load_dotenv from selenium import webdriver from selenium.webdriver.common.by import By from selenium.common.exceptions import NoSuchElementException load_dotenv() def check_exists_by_xpath(self, xpath): try: self.driver.find_element(By.XPATH, xpath) except NoSuchElementException: return False return True class Bot: def __init__(self): dt = datetime.now() # saturday, sunday if dt.isoweekday() == 6 or dt.isoweekday() == 7: print("No request required today") return options = webdriver.ChromeOptions() if os.environ.get("browserDebug") == "false": options.add_argument('--no-sandbox') options.add_argument('--headless') options.add_argument('--disable-gpu') options.add_argument('--window-size=1920x1080') self.driver = webdriver.Chrome(options=options, executable_path=os.path.dirname(os.path.realpath(__file__)) + "/chromedriver") self.driver.get(os.environ.get("schoolUrl")) time.sleep(1) # fill user login fields username_input = self.driver.find_element(By.XPATH, '/html/body/div[2]/div[5]/div/div[4]/div[4]/div[' '1]/div/div/form/a/div[2]/div/input[1]') username_input.send_keys(os.environ.get("username")) password_input = self.driver.find_element(By.XPATH, '/html/body/div[2]/div[5]/div/div[4]/div[4]/div[' '1]/div/div/form/a/div[3]/div/input') password_input.send_keys(os.environ.get("password")) # click on login button login_button = self.driver.find_element(By.XPATH, '/html/body/div[2]/div[5]/div/div[4]/div[4]/div[' '1]/div/div/form/div/div/a[1]/button') login_button.submit() # wait for login redirecting time.sleep(2) # open representation schedule self.driver.get('https://start.schulportal.hessen.de/vertretungsplan.php') time.sleep(2) # today - table primary table_no_entries_alert_warning = check_exists_by_xpath(self, '/html/body/div[1]/div[5]/div[' '2]/div/div/div[2]/div[2]/div[1]/div[' '2]/div[2]/table/tbody/tr/td/div') today_school_day = [] if table_no_entries_alert_warning is False: # there are entries print('today - there are entries') table_tr = self.driver.find_elements(By.XPATH, '/html/body/div[1]/div[5]/div[2]/div/div/div[2]/div[' '2]/div[1]/div[2]/div[2]/table/tbody/tr') for tr in table_tr: td = tr.find_elements(By.TAG_NAME, 'td') data = { 'hour': td[0].text, 'class': td[1].text, 'representative': td[2].text, 'teacher': td[3].text, 'subject': td[4].text, 'room': td[5].text, 'note': td[6].text } today_school_day.append(data) else: # there are no entries print('today - no entries') # next school day next_school_day = [] button_next_day = self.driver.find_element(By.XPATH, '/html/body/div[1]/div[5]/div[2]/div/div/div[1]/div/button[2]') button_next_day.click() time.sleep(2) table_no_entries_alert_warning = check_exists_by_xpath(self, '/html/body/div[1]/div[5]/div[' '2]/div/div/div[3]/div[2]/div[1]/div[' '2]/div[2]/table/tbody/tr/td/div') if table_no_entries_alert_warning is False: # there are entries print('next day - there are entries') table_tr = self.driver.find_elements(By.XPATH, '/html/body/div[1]/div[5]/div[2]/div/div/div[3]/div[2]/div[1]/div[2]/div[2]/table/tbody/tr') for tr in table_tr: td = tr.find_elements(By.TAG_NAME, 'td') data = { 'hour': td[0].text, 'class': td[1].text, 'representative': td[2].text, 'teacher': td[3].text, 'subject': td[4].text, 'room': td[5].text, 'note': td[6].text } next_school_day.append(data) else: # there are no entries print('next day - no entries') todayEncodedBytes = base64.b64encode(json.dumps(today_school_day).encode("utf-8")) nextDayEncodedBytes = base64.b64encode(json.dumps(next_school_day).encode("utf-8")) txt = "../school-portal-substitution-plan-matrix-chat-bot/main {} {}".format(str(todayEncodedBytes, "utf-8"), str(nextDayEncodedBytes, "utf-8")) self.driver.close() os.popen(txt) time.sleep(5) def run_threaded(job_func): job_thread = threading.Thread(target=job_func) job_thread.start() def start_bot(): bot = Bot() schedule.every().day.at("05:00").do(run_threaded, start_bot) schedule.every().day.at("19:00").do(run_threaded, start_bot) while True: schedule.run_pending() time.sleep(1)