MDC

 avatar
unknown
python
a month ago
7.3 kB
2
Indexable
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options
from twilio.rest import Client
import time
import os
from dotenv import load_dotenv

load_dotenv()

# Configuration
PORTAL_URL = os.getenv('PORTAL_URL')
USERNAME = os.getenv('USERNAME')
PASSWORD = os.getenv('PASSWORD')

# Twilio configuration
account_sid = os.getenv('TWILIO_ACCOUNT_SID')
auth_token = os.getenv('TWILIO_AUTH_TOKEN')
twilio_phone = os.getenv('TWILIO_PHONE_NUMBER')
your_phone = os.getenv('MY_PHONE_NUMBER')


def setup_driver():
    """
    Set up and return a headless Chrome WebDriver instance.

    This function creates a new instance of a Chrome WebDriver configured with
    options for headless operation. This is particularly useful for running tests
    or web scraping tasks in environments without a graphical interface.

    :return: A configured instance of `webdriver.Chrome` with headless options.
    :rtype: selenium.webdriver.Chrome
    """
    chrome_options = Options()
    chrome_options.add_argument('--headless')
    return webdriver.Chrome(options=chrome_options)


def check_portal_status(driver):
    """
    Checks the status of an application portal by verifying the presence and content
    of specific elements on the web page within a specified timeout period. This
    method is designed for use with Selenium WebDriver.

    :param driver:
        The Selenium WebDriver instance used to interact with the web page.
    :return:
        A boolean indicating the status of the portal. Returns ``False`` if
        applications are closed or in case of an error. Returns ``True`` otherwise.

    :raises:
        This function does not explicitly declare raised exceptions, but any
        exceptions encountered during execution will be logged and handled internally.
    """
    try:
        # Check for closed message
        error_element = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.CSS_SELECTOR, "b.text-danger"))
        )
        # Get the inner text of the element
        element_text = error_element.text

        # Log the text of the element and return the portal status
        print(f"Portal status message: {element_text}")
        return "Applications are closed" not in error_element.text
    except Exception as e:
        print(f"Error checking portal status: {e}")
        return False


def initial_login(driver):
    """
    Performs the initial login process for the medical portal using the provided
    web driver. This function handles the navigation to the portal, selecting the
    appropriate user type, entering credentials, submitting the login form, and
    navigating to the housemanship application section. Returns a success status
    as a boolean value.

    :param driver: The Selenium WebDriver instance used to perform actions on the
        web application.
    :return: A boolean flag indicating whether the login operation was successful
        (True) or failed (False).
    """
    try:
        driver.get(PORTAL_URL)
        doctor_radio = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located(
                (By.XPATH, "//input[@type='radio' and following-sibling::text()[contains(., 'Doctor')]]"))
        )
        doctor_radio.click()

        username_field = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.CSS_SELECTOR, "input[name='username']"))
        )
        username_field.send_keys(USERNAME)

        password_field = driver.find_element(By.CSS_SELECTOR, "input[name='password']")
        password_field.send_keys(PASSWORD)

        submit_button = driver.find_element(By.CSS_SELECTOR, "button.btn-primary")
        submit_button.click()

        housemanship_link = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.CSS_SELECTOR, "a[href='#/housemanship-application']"))
        )
        housemanship_link.click()

        time.sleep(2)
        return True
    except Exception as e:
        print(f"Login failed: {e}")
        return False


def refresh_page(driver):
    """
    Refreshes the current page by locating and clicking on the refresh button. The method
    waits until the refresh button is located within a defined timeout and then performs the
    click operation. After triggering the refresh, it waits briefly to allow the operation
    to complete. If the operation fails at any point, it logs the failure and returns a
    failure status.

    :param driver:
        The Selenium WebDriver instance used to interact with the browser.
    :return:
        A boolean value indicating the success or failure of the refresh operation.
    """
    try:
        refresh_button = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.XPATH, "//button[contains(@class, 'btn-primary')]//i[contains(@class, 'fa-refresh')]/.."))
        )
        refresh_button.click()
        time.sleep(2)  # Wait for refresh to complete
        return True
    except Exception as e:
        print(f"Refresh failed: {e}")
        return False


def send_sms():
    """
    Send an SMS message using the Twilio API client.

    This function initializes a Twilio client with the provided credentials
    (`account_sid` and `auth_token`) and sends a pre-defined SMS message
    to the recipient's phone number (`your_phone`) from the specified Twilio
    phone number (`twilio_phone`). The content of the message notifies users
    about the opening of the housemanship portal.

    The function prints the unique SID of the sent message as confirmation.

    :rtype: None
    :return: This function does not return a value.
    """
    client = Client(account_sid, auth_token)
    message = client.messages.create(
        body="🏥 Housemanship portal is now OPEN! Login immediately!",
        from_=twilio_phone,
        to=your_phone
    )
    print(f"SMS sent: {message.sid}")


def main():
    print("Starting portal monitor...")
    check_interval = 30
    max_retries = 3
    driver = None

    try:
        driver = setup_driver()

        if not initial_login(driver):
            print("Initial login failed. Exiting...")
            return

        while True:
            if check_portal_status(driver):
                print("Portal is open!")
                send_sms()
                break

            print(f"Portal still closed. Refreshing in {check_interval} seconds...")
            time.sleep(check_interval)

            retries = 0
            while retries < max_retries:
                if refresh_page(driver):
                    break
                retries += 1
                print(f"Refresh attempt {retries} failed. Retrying...")
                time.sleep(5)

            if retries == max_retries:
                print("Multiple refresh attempts failed. Attempting to re-login...")
                if not initial_login(driver):
                    print("Re-login failed. Exiting...")
                    break

    except Exception as e:
        print(f"Unexpected error: {e}")
    finally:
        if driver:
            driver.quit()


if __name__ == "__main__":
    main()
Leave a Comment