您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
An Ed-Puzzle Hack with a LOT of Features!!!!!!!
// ==UserScript== // @name ED-Puzzle Hack // @namespace https://github.com/longkidkoolstar // @description An Ed-Puzzle Hack with a LOT of Features!!!!!!! // @author longkidkoolstar // @version 0.2.1 // @icon https://th.bing.com/th/id/OIP.3LKllA9fA7DTJ4Kb92LbowHaHa?rs=1&pid=ImgDetMain // @match *://edpuzzle.com/lti/* // @match *://edpuzzle.com/assignments/* // @match *://edpuzzle.com/media/* // @match *://youtube.com/embed* // @match *://youtube-nocookie.com/embed* // @grant none // @license GPL // ==/UserScript== /* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. */ //Copyright (C) [2024] [longkidkoolstar] // This script is based on the original code from the edpuzzle-answers project by ading2210 // See: https://github.com/ading2210/edpuzzle-answers var popup = null; var base_url; if (typeof document.dev_env != "undefined") { base_url = document.dev_env; } else { //get resources off of github to not inflate the jsdelivr stats base_url = "https://raw.githubusercontent.com/ading2210/edpuzzle-answers/main"; } function http_get(url, callback, headers=[], method="GET", content=null) { var request = new XMLHttpRequest(); request.addEventListener("load", callback); request.open(method, url, true); if (window.__EDPUZZLE_DATA__ && window.__EDPUZZLE_DATA__.token) { headers.push(["authorization", window.__EDPUZZLE_DATA__.token]); } for (const header of headers) { request.setRequestHeader(header[0], header[1]); } request.send(content); } function createActivationButton() { // Create a button element var activationButton = document.createElement("button"); // Set the button text activationButton.textContent = "Activate Edpuzzle Script"; // Add a click event listener to the button activationButton.addEventListener("click", function () { // Call the init function to activate the Edpuzzle script init(); }); // Create a style for the button var buttonStyle = ` background-color: #00ADEF; color: #FFFFFF; padding: 10px 20px; font-size: 16px; border: none; cursor: pointer; transition: opacity 0.3s ease-in-out; /* Add a smooth transition effect */ `; // Apply the style to the button activationButton.style.cssText = buttonStyle; // Add a hover effect activationButton.addEventListener("mouseover", function () { activationButton.style.opacity = 0.8; // Adjust the opacity as needed }); // Restore the original opacity on mouseout activationButton.addEventListener("mouseout", function () { activationButton.style.opacity = 1; }); // Append the button to the body of the document document.body.appendChild(activationButton); } // Call the function to create the activation button createActivationButton(); function init() { if (window.location.hostname == "edpuzzle.hs.vc") { alert("To use this, drag this button into your bookmarks bar. Then, run it when you're on an Edpuzzle assignment."); } else if ((/https{0,1}:\/\/edpuzzle.com\/assignments\/[a-f0-9]{1,30}\/watch/).test(window.location.href)) { getAssignment(); } else if (window.canvasReadyState) { handleCanvasURL(); } else if (window.schoologyMoreLess) { handleSchoologyURL(); } else { alert("Please run this script on an Edpuzzle assignment. For reference, the URL should look like this:\nhttps://edpuzzle.com/assignments/{ASSIGNMENT_ID}/watch"); } } function handleCanvasURL() { let location_split = window.location.href.split("/"); let url = `/api/v1/courses/${location_split[4]}/assignments/${location_split[6]}`; http_get(url, function(){ let data = JSON.parse(this.responseText); let url2 = data.url; http_get(url2, function() { let data = JSON.parse(this.responseText); let url3 = data.url; alert(`Please re-run this script in the newly opened tab. If nothing happens, then allow popups on Canvas and try again.`); open(url3); }); }); } function handleSchoologyURL() { let assignment_id = window.location.href.split("/")[4]; let url = `/external_tool/${assignment_id}/launch/iframe`; http_get(url, function() { alert(`Please re-run this script in the newly opened tab. If nothing happens, then allow popups on Schoology and try again.`); //strip js tags from response and add to dom let html = this.responseText.replace(/<script[\s\S]+?<\/script>/, ""); let div = document.createElement("div"); div.innerHTML = html; let form = div.querySelector("form"); let input = document.createElement("input") input.setAttribute("type", "hidden"); input.setAttribute("name", "ext_submit"); input.setAttribute("value", "Submit"); form.append(input); document.body.append(div); //submit form in new tab form.setAttribute("target", "_blank"); form.submit(); div.remove(); }); } function getAssignment(callback) { var assignment_id = window.location.href.split("/")[4]; if (typeof assignment_id == "undefined") { alert("Error: Could not infer the assignment ID. Are you on the correct URL?"); return; } var url1 = "https://edpuzzle.com/api/v3/assignments/"+assignment_id; http_get(url1, function(){ var assignment = JSON.parse(this.responseText); if ((""+this.status)[0] == "2") { openPopup(assignment); } else { alert(`Error: Status code ${this.status} recieved when attempting to fetch the assignment data.`) } }); } function openPopup(assignment) { var media = assignment.medias[0]; var teacher_assignment = assignment.teacherAssignments[0]; var assigned_date = new Date(teacher_assignment.preferences.startDate); var date = new Date(media.createdAt); thumbnail = media.thumbnailURL; if (thumbnail.startsWith("/")) { thumbnail = "https://"+window.location.hostname+thumbnail; } var deadline_text; if (teacher_assignment.preferences.dueDate == "") { deadline_text = "no due date" } else { deadline_text = "due on "+(new Date(teacher_assignment.preferences.dueDate)).toDateString(); } var base_html = ` <!DOCTYPE html> <head> <style> * {font-family: Arial} </style> <script> var base_url = "${base_url}"; function http_get(url, callback) { var request = new XMLHttpRequest(); request.addEventListener("load", callback); request.open("GET", url, true); request.send(); } function get_tag(tag, url) { console.log("Loading "+url); http_get(url, function(){ if ((""+this.status)[0] == "2") { var element = document.createElement(tag); element.innerHTML = this.responseText; document.getElementsByTagName("head")[0].appendChild(element); } else { console.error("Could not fetch "+url); } }); } get_tag("style", base_url+"/app/popup.css"); get_tag("script", base_url+"/app/popup.js"); get_tag("script", base_url+"/app/videooptions.js"); get_tag("script", base_url+"/app/videospeed.js"); </script> <title>Answers for: ${media.title}</title> </head> <div id="header_div"> <div> <img src="${thumbnail}" height="108px"> </div> <div id="title_div"> <p style="font-size: 16px"><b>${media.title}</b></h2> <p style="font-size: 12px">Uploaded by ${media.user.name} on ${date.toDateString()}</p> <p style="font-size: 12px">Assigned on ${assigned_date.toDateString()}, ${deadline_text}</p> <p style="font-size: 12px">Correct choices are <u>underlined</u>.</p> <input id="skipper" type="button" value="Skip Video" onclick="skip_video();" disabled/> <input id="answers_button" type="button" value="Answer Questions" onclick="answer_questions();" disabled/> <div id="speed_container" hidden> <label style="font-size: 12px" for="speed_dropdown">Video speed:</label> <select name="speed_dropdown" id="speed_dropdown" onchange="video_speed()"> <option value="0.25">0.25</option> <option value="0.5">0.5</option> <option value="0.75">0.75</option> <option value="1" selected>Normal</option> <option value="1.25">1.25</option> <option value="1.5">1.5</option> <option value="1.75">1.75</option> <option value="2">2</option> <option value="-1">Custom</option> </select> <label id="custom_speed_label" style="font-size: 12px" for="custom_speed"></label> <input type="range" id="custom_speed" name="custom_speed" value="1" min="0.1" max="16" step="0.1" oninput="video_speed()" hidden> </div> <div id="options_container"> <label for="pause_on_focus" style="font-size: 12px">Don't pause on unfocus: </label> <input type="checkbox" id="pause_on_focus" name="pause_on_focus" onchange="toggle_unfocus();"> </div> </div> </div> <hr> <div id="content"> <p style="font-size: 12px" id="loading_text"></p> </div> <hr> `; popup = window.open("about:blank", "", "width=600, height=400"); popup.document.write(base_html); popup.document.assignment = assignment; popup.document.dev_env = document.dev_env; popup.document.edpuzzle_data = window.__EDPUZZLE_DATA__; getMedia(assignment); } function getMedia(assignment) { var text = popup.document.getElementById("loading_text"); text.innerHTML = `Fetching assignments...`; var media_id = assignment.teacherAssignments[0].contentId; var url2 = `https://edpuzzle.com/api/v3/media/${media_id}`; fetch(url2, {credentials: "omit"}) .then(response => { if (!response.ok) { var text = popup.document.getElementById("loading_text"); var content = popup.document.getElementById("content"); popup.document.questions = questions; text.remove(); content.innerHTML += `Error: Status code ${response.status} received when attempting to fetch the answers.`; } else return response.json(); }) .then(media => { parseQuestions(media.questions); }) } function parseQuestions(questions) { var text = popup.document.getElementById("loading_text"); var content = popup.document.getElementById("content"); popup.document.questions = questions; text.remove(); if (questions == null) { content.innerHTML += `<p style="font-size: 12px">Error: Could not get the media for this assignment. </p>`; return; } var question; var counter = 0; var counter2 = 0; for (let i=0; i<questions.length; i++) { for (let j=0; j<questions.length-i-1; j++) { if (questions[j].time > questions[j+1].time){ let question_old = questions[j]; questions[j] = questions[j + 1]; questions[j+1] = question_old; } } } for (let i=0; i<questions.length; i++) { question = questions[i]; let choices_lines = []; if (typeof question.choices != "undefined") { let min = Math.floor(question.time/60).toString(); let secs = Math.floor(question.time%60).toString(); if (secs.length == 1) { secs = "0"+secs; } let timestamp = min+":"+secs; let question_content; if (question.body[0].text != "") { question_content = `<p>${question.body[0].text}</p>`; } else { question_content = question.body[0].html; } let answer_exists = false; for (let j=0; j<question.choices.length; j++) { let choice = question.choices[j]; if (typeof choice.body != "undefined") { counter++; let item_html; if (choice.body[0].text != "") { item_html = `<p>${choice.body[0].text}</p>`; } else { item_html = `${choice.body[0].html}`; } if (choice.isCorrect == true) { choices_lines.push(`<li class="choice choice-correct">${item_html}</li>`); answer_exists = true; } else { choices_lines.push(`<li class="choice">${item_html}</li>`); } } } if (!answer_exists) continue; let choices_html = choices_lines.join("\n"); let table = `` if (counter2 != 0) { table += `<hr>`; } table += ` <table> <tr class="header no_vertical_margin"> <td class="timestamp_div no_vertical_margin"> <p>[${timestamp}]</p> </td> <td class="question"> ${question_content} </td> </tr> <tr> <td></td> <td> <ul style="margin-top: 6px; margin-bottom: 0px; padding-left: 18px;"> ${choices_html} </ul> </td> </tr> </table> `; content.innerHTML += table; counter2++; } } popup.document.getElementById("skipper").disabled = false; if (counter == 0 || counter2 == 0) { content.innerHTML += `<p style="font-size: 12px">No valid multiple choice questions were found.</p>`; } else { popup.document.getElementById("answers_button").disabled = false; } popup.questions = questions; }