diff --git a/deismu/Dockerfile b/deismu/Dockerfile new file mode 100644 index 0000000..7c46ccd --- /dev/null +++ b/deismu/Dockerfile @@ -0,0 +1,17 @@ +# Use Python with Alpine Linux base image +FROM python:3.9-alpine + +# Set the working directory in the container +WORKDIR / + +# Install dependencies for headless operation +RUN apk add --no-cache \ + chromium \ + chromium-chromedriver \ + && pip install --no-cache-dir selenium==4.0.0 webdriver_manager + +# Copy the script into the container +COPY verifyCert.py /verifyCert.py + +# Command to run the script +CMD ["python", "/verifyCert.py"] diff --git a/deismu/testDocker.sh b/deismu/testDocker.sh new file mode 100644 index 0000000..a4bed46 --- /dev/null +++ b/deismu/testDocker.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +# URL to test +TEST_URL="https://www.coursera.org/account/accomplishments/verify/GA668424ZUQH" + +# Name of your Docker image +DOCKER_IMAGE="selenium" + +# Run the Docker container and capture the output +output=$(docker run --rm -e TEST_URL="$TEST_URL" "$DOCKER_IMAGE") + +# Check the output +echo "Output received: $output" + +# Parse and check the output here +# Example: using jq to check a JSON output +# echo $output | jq 'Your conditions here' diff --git a/deismu/verifyCert.py b/deismu/verifyCert.py new file mode 100644 index 0000000..5471478 --- /dev/null +++ b/deismu/verifyCert.py @@ -0,0 +1,61 @@ +import json +import os +from selenium import webdriver +from selenium.webdriver.chrome.options import Options +from selenium.webdriver.common.by import By +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC + +# Set up Chrome options for headless operation +chrome_options = Options() +chrome_options.add_argument("--headless") +chrome_options.add_argument("--no-sandbox") +chrome_options.add_argument("--disable-dev-shm-usage") + +def scrape_url(driver, url): + driver.get(url) + name_element = WebDriverWait(driver, 4).until( + EC.presence_of_element_located((By.CSS_SELECTOR, "h3.cds-119 strong")) + ) + name = name_element.text if name_element else "Name not found" + + course_name_element = driver.find_element(By.CSS_SELECTOR, "h2.course-name") + course_name = course_name_element.text if course_name_element else "Course name not found" + + return {'name': name, 'course_name': course_name} + +def lambda_handler(event, context): + results = [] + urls = event.get('urls') + if not urls or not isinstance(urls, list): + return { + 'statusCode': 400, + 'body': json.dumps({'error': 'Missing or invalid URL list'}) + } + + # Initialize the headless browser + with webdriver.Chrome(options=chrome_options) as driver: + for url in urls: + try: + result = scrape_url(driver, url) + results.append(result) + except Exception as e: + results.append({'error': str(e)}) + + return { + 'statusCode': 200, + 'body': json.dumps(results) + } + +# Main execution for direct run +if __name__ == '__main__': + # Get URL from environment variable + test_url = os.environ.get('TEST_URL') + + if test_url: + # Simulate the event structure for direct invocation + event = {'urls': [test_url]} + result = lambda_handler(event, context=None) + print(json.dumps(result, indent=4)) + else: + print("No URL provided.") diff --git a/src/deismu.js b/src/deismu.js index 95b655f..8023be0 100644 --- a/src/deismu.js +++ b/src/deismu.js @@ -1,4 +1,4 @@ -function addURL() { +function addURL(auth0) { // Prompt the user to enter a URL var urlToAdd = prompt( "Please enter the Coursera certificate URL to verify:" @@ -37,6 +37,39 @@ function addURL() { }); } } + +async function getCompletedCourses(auth0) { + try { + // Obtain the JWT token + const token = await auth0.getTokenSilently(); + + // Set up your API endpoint + const apiEndpoint = 'https://your-api-endpoint.com/user-courses'; + + // Make the API request + const response = await fetch(apiEndpoint, { + headers: { + Authorization: `Bearer ${token}` + } + }); + + // Check if the response is successful + if (!response.ok) { + throw new Error('Network response was not ok'); + } + + // Parse the JSON response + const courses = await response.json(); + + return courses; + } catch (error) { + console.error('Error fetching completed courses:', error); + throw error; + } +} + + + function getCurriculum() { fetch("curriculum.json") .then((response) => response.json()) @@ -52,11 +85,14 @@ function getCurriculum() { error.message; }); } + function createExpandableList(data, container) { function createList(itemData, parentElement) { Object.keys(itemData).forEach((key) => { + // Check if the current item has a meta dictionary with a reference list + let hasReference = itemData[key]?.meta?.reference?.length > 0; + if (key !== "meta") { - // Exclude 'meta' nodes if ( typeof itemData[key] === "object" && itemData[key] !== null && @@ -69,9 +105,18 @@ function createExpandableList(data, container) { let sectionTitle = document.createElement("button"); sectionTitle.className = "section-title"; sectionTitle.innerText = key; - sectionTitle.onclick = function () { - this.nextElementSibling.classList.toggle("active"); - }; + + if (hasReference) { + sectionTitle.onclick = function () { + window.open(itemData[key].meta.reference[0], '_blank'); + }; + sectionTitle.style.textDecoration = "underline"; + sectionTitle.style.cursor = "pointer"; + } else { + sectionTitle.onclick = function () { + this.nextElementSibling.classList.toggle("active"); + }; + } let itemList = document.createElement("div"); itemList.className = "item-list"; @@ -86,7 +131,18 @@ function createExpandableList(data, container) { // Create item for non-object data let item = document.createElement("div"); item.className = "item"; - item.innerText = key + ": " + itemData[key]; + + if (hasReference) { + item.onclick = function () { + window.open(itemData.meta.reference[0], '_blank'); + }; + item.style.textDecoration = "underline"; + item.style.cursor = "pointer"; + item.innerText = key + ": " + itemData[key]; + } else { + item.innerText = key + ": " + itemData[key]; + } + parentElement.appendChild(item); } } @@ -96,12 +152,12 @@ function createExpandableList(data, container) { createList(data, container); } -function addListeners(){ +function addListeners(auth0){ document.body.addEventListener('click', function(event) { switch (event.target.id) { case 'btn-verify-certificate': - addURL(); // Function for verifying certificate + addURL(auth0); // Function for verifying certificate break; } }); diff --git a/src/index.html b/src/index.html index 658e3df..7bbdc67 100644 --- a/src/index.html +++ b/src/index.html @@ -9,6 +9,7 @@ rel="stylesheet" /> +