proEndreeper / SDSMT Single Sign On Simplifier

// ==UserScript==
// @name         SDSMT Single Sign On Simplifier
// @namespace    https://openuserjs.org/users/proENdreeper
// @run-at       document-idle
// @version      1.0.1
// @description  Autofills/autoselects logins for SDSMT so you don't have to type your email multiple times.
// @author       proEndreeper
// @copyright    2021, proEndreeper (https://openuserjs.org/users/proEndreeper
// @license      GPL-3.0-or-later
// @match        https://adfs.sdbor.edu/*
// @match        https://adfs.sdsmt.edu/*
// @match        https://login.microsoftonline.com/*
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_registerMenuCommand
// @updateURL    https://openuserjs.org/meta/proEndreeper/SDSMT_Single_Sign_On_Simplifier.meta.js
// @downloadURL  https://openuserjs.org/install/proEndreeper/SDSMT_Single_Sign_On_Simplifier.user.js
// ==/UserScript==

;
(function () {
  'use strict';

  GM_registerMenuCommand("Change Email", requestEmailChange, 'c');

  function requestEmailChange() {
    let email = prompt("Please enter your SDBoR assigned email address (e.g. first.lastname@mines.sdsmt.edu)");
    GM_setValue("sdbor-sso-simplifier.email", email);
    return email;
  }

  function getEmail() {
    let email = GM_getValue("sdbor-sso-simplifier.email");
    if (email === undefined) {
      email = requestEmailChange();
    }
    return email;
  }

  function waitForElement(query, timeout = 5000) {
    const startTime = Date.now;
    return new Promise((resolve, reject) => {
      function attempt() {
        var el = document.querySelector(query);
        if (el instanceof Element) {
          resolve(el);
        }
        else {
          if (Date.now - startTime > timeout) // Well, we're out of time here folks.
          {
            reject(new Error("Timed out in trying to find element by query selector"));
          }
          else {
            setTimeout(attempt, 0); // Throw another attempt into the bucket
          }
        }
      }

      attempt();
    });
  }

  async function fillSdborEmail() {
    console.log("Hi SDBoR!");
    (await waitForElement("#emailInput")).value = getEmail();
    (await waitForElement("#submissionArea > input")).click();
  }

  async function fillSdsmtEmail() {
    console.log("Hi SDSMT!");
    (await waitForElement("#userNameInput")).value = getEmail();
    (await waitForElement("#passwordInput")).focus();
  }

  async function microsoftLogin() {
    console.log("Hi Microsoft!");
    var header = (await waitForElement("#loginHeader > div")).innerText;
    (await waitForElement(".tile-container"));
    if (header == "Pick an account") {
      var containers = document.getElementsByClassName("tile-container");
      for (var i = 0, container;
        (container = containers[i]) !== undefined; i++) {
        if (container.innerText.trim().toLowerCase() == getEmail().trim().toLowerCase()) {
          console.log("I found you!");
          container.childNodes[2].childNodes[1].childNodes[1].childNodes[3].click();
        }
      }
    }
    else if (header == "Sign in") {
      (await waitForElement("#i0116")).value = getEmail();
      alert("You need to click Sign in on your own!");
    }
  }

  async function pageLoaded() {
    if (getEmail() === "") {
      var emailPromise = new Promise((resolve, reject) => {
        function attempt() {
          if (getEmail() !== "") {
            resolve();
          }
          setTimeout(attempt, 0);
        }

        attempt();
      });

      await emailPromise; // Let's wait until we have something to work with beyond knowing a user wants to login once.
    }
    console.log(`Page is at host '${window.location.hostname}'`);
    switch (window.location.hostname) {
      case "adfs.sdbor.edu":
        await fillSdborEmail();
        break;
      case "adfs.sdsmt.edu":
        await fillSdsmtEmail();
        break;
      case "login.microsoftonline.com":
        if (document.referrer.substr(0, 23) == "https://adfs.sdbor.edu/") { // Don't try logging in if the login request is not coming from sdbor!
          await microsoftLogin();
        }
        break;
      default:
        break;
    }
  }

  setTimeout(pageLoaded, 1000);
})();