Advertisement
BluAxolotl

PLEASE

May 1st, 2023 (edited)
111
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.43 KB | None | 0 0
  1. var popup = null;
  2. var base_url;
  3. if (typeof document.dev_env != "undefined") {
  4. base_url = document.dev_env;
  5. }
  6. else {
  7. //get resources off of github to not inflate the jsdelivr stats
  8. base_url = "https://raw.githubusercontent.com/ading2210/edpuzzle-answers/main";
  9. }
  10.  
  11. function http_get(url, callback, headers=[], method="GET", content=null) {
  12. var request = new XMLHttpRequest();
  13. request.addEventListener("load", callback);
  14. request.open(method, url, true);
  15.  
  16. if (window.__EDPUZZLE_DATA__ && window.__EDPUZZLE_DATA__.token) {
  17. headers.push(["authorization", window.__EDPUZZLE_DATA__.token]);
  18. }
  19. for (const header of headers) {
  20. request.setRequestHeader(header[0], header[1]);
  21. }
  22.  
  23. request.send(content);
  24. }
  25.  
  26. function init() {
  27. if (window.location.hostname == "edpuzzle.hs.vc") {
  28. alert("To use this, drag this button into your bookmarks bar. Then, run it when you're on an Edpuzzle assignment.");
  29. }
  30. else if ((/https{0,1}:\/\/edpuzzle.com\/assignments\/[a-f0-9]{1,30}\/watch/).test(window.location.href)) {
  31. getAssignment();
  32. }
  33. else if (window.canvasReadyState) {
  34. handleCanvasURL();
  35. }
  36. else if (window.schoologyMoreLess) {
  37. handleSchoologyURL();
  38. }
  39. else {
  40. alert("Please run this script on an Edpuzzle assignment. For reference, the URL should look like this:\nhttps://edpuzzle.com/assignments/{ASSIGNMENT_ID}/watch");
  41. }
  42. }
  43.  
  44. function handleCanvasURL() {
  45. let location_split = window.location.href.split("/");
  46. let url = `/api/v1/courses/${location_split[4]}/assignments/${location_split[6]}`;
  47. http_get(url, function(){
  48. let data = JSON.parse(this.responseText);
  49. let url2 = data.url;
  50.  
  51. http_get(url2, function() {
  52. let data = JSON.parse(this.responseText);
  53. let url3 = data.url;
  54.  
  55. alert(`Please re-run this script in the newly opened tab. If nothing happens, then allow popups on Canvas and try again.`);
  56. open(url3);
  57. });
  58. });
  59. }
  60.  
  61. function handleSchoologyURL() {
  62. let assignment_id = window.location.href.split("/")[4];
  63. let url = `/external_tool/${assignment_id}/launch/iframe`;
  64. http_get(url, function() {
  65. alert(`Please re-run this script in the newly opened tab. If nothing happens, then allow popups on Schoology and try again.`);
  66.  
  67. //strip js tags from response and add to dom
  68. let html = this.responseText.replace(/<script[\s\S]+?<\/script>/, "");
  69. let div = document.createElement("div");
  70. div.innerHTML = html;
  71. let form = div.querySelector("form");
  72.  
  73. let input = document.createElement("input")
  74. input.setAttribute("type", "hidden");
  75. input.setAttribute("name", "ext_submit");
  76. input.setAttribute("value", "Submit");
  77. form.append(input);
  78. document.body.append(div);
  79.  
  80. //submit form in new tab
  81. form.setAttribute("target", "_blank");
  82. form.submit();
  83. div.remove();
  84. });
  85. }
  86.  
  87. function getAssignment(callback) {
  88. var assignment_id = window.location.href.split("/")[4];
  89. if (typeof assignment_id == "undefined") {
  90. alert("Error: Could not infer the assignment ID. Are you on the correct URL?");
  91. return;
  92. }
  93. var url1 = "https://edpuzzle.com/api/v3/assignments/"+assignment_id;
  94.  
  95. http_get(url1, function(){
  96. var assignment = JSON.parse(this.responseText);
  97. if ((""+this.status)[0] == "2") {
  98. openPopup(assignment);
  99. }
  100. else {
  101. alert(`Error: Status code ${this.status} recieved when attempting to fetch the assignment data.`)
  102. }
  103. });
  104. }
  105.  
  106. function openPopup(assignment) {
  107. var media = assignment.medias[0];
  108. var teacher_assignment = assignment.teacherAssignments[0];
  109. var assigned_date = new Date(teacher_assignment.preferences.startDate);
  110. var date = new Date(media.createdAt);
  111. thumbnail = media.thumbnailURL;
  112. if (thumbnail.startsWith("/")) {
  113. thumbnail = "https://"+window.location.hostname+thumbnail;
  114. }
  115.  
  116. var deadline_text;
  117. if (teacher_assignment.preferences.dueDate == "") {
  118. deadline_text = "no due date"
  119. }
  120. else {
  121. deadline_text = "due on "+(new Date(teacher_assignment.preferences.dueDate)).toDateString();
  122. }
  123.  
  124. var base_html = `
  125. <!DOCTYPE html>
  126. <head>
  127. <style>
  128. * {font-family: Arial}
  129. </style>
  130. <script>
  131. var base_url = "${base_url}";
  132. function http_get(url, callback) {
  133. var request = new XMLHttpRequest();
  134. request.addEventListener("load", callback);
  135. request.open("GET", url, true);
  136. request.send();
  137. }
  138. function get_tag(tag, url) {
  139. console.log("Loading "+url);
  140. http_get(url, function(){
  141. if ((""+this.status)[0] == "2") {
  142. var element = document.createElement(tag);
  143. element.innerHTML = this.responseText;
  144. document.getElementsByTagName("head")[0].appendChild(element);
  145. }
  146. else {
  147. console.error("Could not fetch "+url);
  148. }
  149. });
  150. }
  151. get_tag("style", base_url+"/app/popup.css");
  152. get_tag("script", base_url+"/app/popup.js");
  153. get_tag("script", base_url+"/app/videooptions.js");
  154. get_tag("script", base_url+"/app/videospeed.js");
  155. </script>
  156. <title>Answers for: ${media.title}</title>
  157. </head>
  158. <div id="header_div">
  159. <div>
  160. <img src="${thumbnail}" height="108px">
  161. </div>
  162. <div id="title_div">
  163. <p style="font-size: 16px"><b>${media.title}</b></h2>
  164. <p style="font-size: 12px">Uploaded by ${media.user.name} on ${date.toDateString()}</p>
  165. <p style="font-size: 12px">Assigned on ${assigned_date.toDateString()}, ${deadline_text}</p>
  166. <p style="font-size: 12px">Correct choices are <u>underlined</u>.</p>
  167. <input id="skipper" type="button" value="Skip Video" onclick="skip_video();" disabled/>
  168. <input id="answers_button" type="button" value="Answer Questions" onclick="answer_questions();" disabled/>
  169. <div id="speed_container" hidden>
  170. <label style="font-size: 12px" for="speed_dropdown">Video speed:</label>
  171. <select name="speed_dropdown" id="speed_dropdown" onchange="video_speed()">
  172. <option value="0.25">0.25</option>
  173. <option value="0.5">0.5</option>
  174. <option value="0.75">0.75</option>
  175. <option value="1" selected>Normal</option>
  176. <option value="1.25">1.25</option>
  177. <option value="1.5">1.5</option>
  178. <option value="1.75">1.75</option>
  179. <option value="2">2</option>
  180. <option value="-1">Custom</option>
  181. </select>
  182. <label id="custom_speed_label" style="font-size: 12px" for="custom_speed"></label>
  183. <input type="range" id="custom_speed" name="custom_speed" value="1" min="0.1" max="16" step="0.1" oninput="video_speed()" hidden>
  184. </div>
  185. <div id="options_container">
  186. <label for="pause_on_focus" style="font-size: 12px">Don't pause on unfocus: </label>
  187. <input type="checkbox" id="pause_on_focus" name="pause_on_focus" onchange="toggle_unfocus();">
  188. </div>
  189. </div>
  190. </div>
  191. <hr>
  192. <div id="content">
  193. <p style="font-size: 12px" id="loading_text"></p>
  194. </div>
  195. <hr>
  196. <p style="font-size: 12px">Made by: <a target="_blank" href="https://github.com/ading2210">ading2210</a> on Github | Website: <a target="_blank" href="https://edpuzzle.hs.vc">edpuzzle.hs.vc</a> | Source code: <a target="_blank" href="https://github.com/ading2210/edpuzzle-answers">ading2210/edpuzzle-answers</a></p>
  197. <p style="font-size: 12px">Licenced under the <a target="_blank" href="https://github.com/ading2210/edpuzzle-answers/blob/main/LICENSE">GNU GPL v3</a>. Do not reupload or redistribute without abiding by those terms.</p>
  198. <p style="font-size: 12px">Available now from our <a target="_blank" href="https://edpuzzle.hs.vc/discord.html">Discord server</a>: <i> An open beta of a completely overhauled GUI, with proper mobile support, ChatGPT integration for open-ended questions, and more. </i></p>`;
  199. popup = window.open("about:blank", "", "width=600, height=400");
  200. popup.document.write(base_html);
  201.  
  202. popup.document.assignment = assignment;
  203. popup.document.dev_env = document.dev_env;
  204. popup.document.edpuzzle_data = window.__EDPUZZLE_DATA__;
  205.  
  206. getMedia(assignment);
  207. }
  208.  
  209. function getMedia(assignment, needle="", request_count=1) {
  210. var text = popup.document.getElementById("loading_text");
  211. text.innerHTML = `Fetching assignments (page ${request_count})...`;
  212.  
  213. var media_id = assignment.teacherAssignments[0].contentId;
  214. var classroom_id = assignment.teacherAssignments[0].classroom.id;
  215. var url2 = "https://edpuzzle.com/api/v3/assignments/classrooms/"+classroom_id+"/students/?needle="+needle;
  216.  
  217. http_get(url2, function() {
  218. if ((""+this.status)[0] == "2") {
  219. var classroom = JSON.parse(this.responseText);
  220. if (classroom.medias.length == 0) {
  221. parseQuestions(null);
  222. return;
  223. }
  224. var media;
  225. for (let i=0; i<classroom.medias.length; i++) {
  226. media = classroom.medias[i];
  227. if (media._id == media_id) {
  228. parseQuestions(media.questions);
  229. return;
  230. }
  231. }
  232. getMedia(assignment, classroom.teacherAssignments[classroom.teacherAssignments.length-1]._id, request_count+1);
  233. }
  234. else {
  235. var text = popup.document.getElementById("loading_text");
  236. var content = popup.document.getElementById("content");
  237. popup.document.questions = questions;
  238. text.remove();
  239. content.innerHTML += `Error: Status code ${this.status} recieved when attempting to fetch the answers.`;
  240. }
  241. });
  242. }
  243.  
  244. function parseQuestions(questions) {
  245. var text = popup.document.getElementById("loading_text");
  246. var content = popup.document.getElementById("content");
  247. popup.document.questions = questions;
  248. text.remove();
  249.  
  250. if (questions == null) {
  251. content.innerHTML += `<p style="font-size: 12px">Error: Could not get the media for this assignment. </p>`;
  252. return;
  253. }
  254.  
  255. var question;
  256. var counter = 0;
  257. var counter2 = 0;
  258. for (let i=0; i<questions.length; i++) {
  259. for (let j=0; j<questions.length-i-1; j++) {
  260. if (questions[j].time > questions[j+1].time){
  261. let question_old = questions[j];
  262. questions[j] = questions[j + 1];
  263. questions[j+1] = question_old;
  264. }
  265. }
  266. }
  267.  
  268. for (let i=0; i<questions.length; i++) {
  269. question = questions[i];
  270. let choices_lines = [];
  271.  
  272. if (typeof question.choices != "undefined") {
  273. let min = Math.floor(question.time/60).toString();
  274. let secs = Math.floor(question.time%60).toString();
  275. if (secs.length == 1) {
  276. secs = "0"+secs;
  277. }
  278. let timestamp = min+":"+secs;
  279. let question_content;
  280. if (question.body[0].text != "") {
  281. question_content = `<p>${question.body[0].text}</p>`;
  282. }
  283. else {
  284. question_content = question.body[0].html;
  285. }
  286. for (let j=0; j<question.choices.length; j++) {
  287. let choice = question.choices[j];
  288. if (typeof choice.body != "undefined") {
  289. counter++;
  290. let item_html;
  291. if (choice.body[0].text != "") {
  292. item_html = `<p>${choice.body[0].text}</p>`;
  293. }
  294. else {
  295. item_html = `${choice.body[0].html}`;
  296. }
  297. if (choice.isCorrect == true) {
  298. choices_lines.push(`<li class="choice choice-correct">${item_html}</li>`);
  299. }
  300. else {
  301. choices_lines.push(`<li class="choice">${item_html}</li>`);
  302. }
  303. }
  304. }
  305.  
  306. let choices_html = choices_lines.join("\n");
  307. let table = ``
  308. if (counter2 != 0) {
  309. table += `<hr>`;
  310. }
  311. table += `
  312. <table>
  313. <tr class="header no_vertical_margin">
  314. <td class="timestamp_div no_vertical_margin">
  315. <p>[${timestamp}]</p>
  316. </td>
  317. <td class="question">
  318. ${question_content}
  319. </td>
  320. </tr>
  321. <tr>
  322. <td></td>
  323. <td>
  324. <ul style="margin-top: 6px; margin-bottom: 0px; padding-left: 18px;">
  325. ${choices_html}
  326. </ul>
  327. </td>
  328. </tr>
  329. </table>
  330. `;
  331.  
  332. content.innerHTML += table;
  333. counter2++;
  334. }
  335. }
  336. popup.document.getElementById("skipper").disabled = false;
  337. if (counter == 0) {
  338. content.innerHTML += `<p style="font-size: 12px">No valid multiple choice questions were found.</p>`;
  339. }
  340. else {
  341. popup.document.getElementById("answers_button").disabled = false;
  342. }
  343. popup.questions = questions;
  344. }
  345.  
  346. init();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement