// VectorLMS // v1.3.1 // Vector Solutions 'SafeSchools' Auto Video Completion Script. Runs, tracks, completes all course_item (i.e. video) on the page.used for vectorlmsedu.com // https://*.vectorlmsedu.com/training/launch/course_work/* // https://pageusd-az.safeschools.com/login // qwestion function asyncWaitSeconds(seconds) { return new Promise((resolve, reject) => { setTimeout(() => { resolve(); }, seconds * 1000); }); } function main() { let TOC_items = document.getElementsByClassName("TOC_item"); let TOC_unwatched_videos = []; let promises = []; // Scrape the page for video data for (let i = 0; i < TOC_items.length; i++) { try { let data_entry = {}; data_entry.element = TOC_items[i]; data_entry.isVideo = TOC_items[i].querySelector(".fa-play") != null; data_entry.href = TOC_items[i].getAttribute("href"); data_entry.title = TOC_items[i].querySelector(".lead").innerText; let len = TOC_items[i].getAttribute("href").split("?")[0].split("/").length; data_entry.work_id = TOC_items[i].getAttribute("href").split("?")[0].split("/")[len - 1]; data_entry.item_id = TOC_items[i].getAttribute("href").split("?")[0].split("/")[len - 2]; if (!data_entry.isVideo) { continue; } data_entry.time_min = parseInt(TOC_items[i].querySelector(".span_link").innerText.split(" ")[1]) + 0.5; data_entry.completed = false; TOC_unwatched_videos.push(data_entry); } catch (err) { console.log("Error scraping TOC item: " + TOC_items[i].innerText); console.log(err); } } // Process each unwatched video let completedCount = 0; for (let i = 0; i < TOC_unwatched_videos.length; i++) { let school_host = window.location.host; let unwatched_video = TOC_unwatched_videos[i]; // Start tracking the video let tracking_start_url = `https://${school_host}/rpc/v2/json/training/tracking_start?course_item_id=${unwatched_video.item_id}&course_work_id=${unwatched_video.work_id}`; let promise = fetch(tracking_start_url) .then(response => response.json()) .then(tracking_start_data => { unwatched_video.work_hist_id = tracking_start_data.course_work_hist_id; console.log("Video time tracking started for video: " + unwatched_video.title); // Wait for the video duration console.log("Waiting for the length of the video, " + unwatched_video.time_min * 60 + " seconds..."); return asyncWaitSeconds(unwatched_video.time_min * 60) .then(() => { // Finish tracking the video let tracking_finish_url = `https://${school_host}/rpc/v2/json/training/tracking_finish?course_work_hist_id=${unwatched_video.work_hist_id}&_=${Date.now() + unwatched_video.time_min * 60 * 1000}`; return fetch(tracking_finish_url) .then(response => response.json()) .then(tracking_finish_data => { unwatched_video.completed = !(tracking_finish_data.tracking_status); if (unwatched_video.completed) { console.log("Completed Video: " + unwatched_video.title); completedCount++; } else { console.log("Failed to Complete Video: " + unwatched_video.title); } }); }); }); promises.push(promise); } // Update the UI only when all videos are completed Promise.all(promises).then(() => { for (let i = 0; i < TOC_unwatched_videos.length; i++) { let unwatched_video = TOC_unwatched_videos[i]; unwatched_video.element.querySelector(".IconSquare").innerHTML = ''; unwatched_video.element.querySelector(".hidden-xs").innerHTML = ' Completed'; } }); } // Call the main function to start the script main();