Skip to content

Instantly share code, notes, and snippets.

@cuylerstuwe
Last active March 5, 2022 00:35
Show Gist options
  • Save cuylerstuwe/4044adc4eeb708b25c705444e45dc55b to your computer and use it in GitHub Desktop.
Save cuylerstuwe/4044adc4eeb708b25c705444e45dc55b to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name Download Egghead Courses
// @namespace salembeats
// @version 1.61
// @description For Pro users -- works with lessons (downloads individual MP4 files) and courses (downloads zip files). Append "#dl" to the end of the URL to download.
// @author Cuyler Stuwe (salembeats)
// @include https://egghead.io/*
// @grant GM_xmlhttpRequest
// @grant GM_download
// @grant GM_openInTab
// ==/UserScript==
async function getDownloadUrl(courseStub, type) {
if(!type) {return undefined;}
// What Egghead refers to as "courses" in the public-facing URL are
// actually referred to as "series" in the Egghead API.
// This accounts for these and potential future naming inconsistencies.
const typeRoutes = {
"courses": "series",
"lessons": "lessons"
};
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
url: `https://egghead.io/api/v1/${typeRoutes[type]}/${courseStub}`,
method: "GET",
onload: function(response) {
const jsonResponse = JSON.parse(response.responseText);
const downloadUrl = jsonResponse.download_url;
// The "download" property in the Egghead API points
// directly to the ZIP file to download when it comes to downloading courses.
// However, when it comes to lessons, this property is simply another
// level of indirection, pointing instead to an API route which has
// the "real" file download route.
if(type === "courses") {
resolve(downloadUrl);
}
else if(type === "lessons") {
GM_xmlhttpRequest({
url: downloadUrl,
method: "GET",
onload: function(response) {
resolve(response.responseText);
}
}); // GM_xmlhttpRequest
} // if(type === lessons)
} // onload
}); // GM_xmlhttpRequest
}); // return new Promise
}
function getCourseStub() {
const courseStub = (window.location.href.match(/egghead.io\/courses\/([^/?#]*)/) || [null,null])[1];
return courseStub;
}
function getLessonStub() {
const lessonStub = (window.location.href.match(/egghead.io\/lessons\/([^/?#]*)/) || [null,null])[1];
return lessonStub;
}
async function downloadCourse() {
const courseStub = getCourseStub();
const lessonStub = getLessonStub();
let downloadType;
if(courseStub) {
downloadType = "courses";
}
else if(lessonStub) {
downloadType = "lessons";
}
const downloadStub = courseStub || lessonStub;
const downloadUrl = await getDownloadUrl(downloadStub, downloadType);
GM_openInTab(downloadUrl, true);
}
function pollHash(e) {
if(window.location.hash.startsWith("#dl")) { downloadCourse(); }
}
// The entry point in initiating a download is checking for #dl in the URL
// on intial load and on each hash change event.
async function main() {
pollHash();
window.addEventListener("hashchange", pollHash);
}
main();
@Austinmac56
Copy link

should i enter this code in the console because is not downloading. what should i do

@cuylerstuwe
Copy link
Author

cuylerstuwe commented Apr 24, 2020 via email

@cuylerstuwe
Copy link
Author

Screen Shot 2020-07-08 at 2 39 25 PM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment