Skip to content

Instantly share code, notes, and snippets.

@Gummibeer
Created November 17, 2022 08:56
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save Gummibeer/aa00ec08fe1ccb1cb3f5da673e2f80b9 to your computer and use it in GitHub Desktop.
const YAML = require('yaml');
const fs = require('fs-extra');
const path = require('path');
const glob = require('glob');
const fetch = require('node-fetch');
const puppeteer = require('puppeteer');
const slugify = require('slugify');
const { exec } = require("child_process");
const nunjucks = require('nunjucks');
const config = YAML.parse(fs.readFileSync(path.resolve(path.join(process.cwd(), 'config.yml')), 'utf8'));
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await handlers.login(page);
await page.waitForNavigation();
let courses = await handlers.courses(page);
fs.writeFileSync(path.join(process.cwd(), 'data', 'courses.json'), JSON.stringify(courses));
for(const c of courses) {
let course = await handlers.course(page, c.uuid);
fs.writeFileSync(path.join(process.cwd(), 'data', `${course.slug}.json`), JSON.stringify(course));
let courseDir = path.join(process.cwd(), 'courses', course.slug);
fs.ensureDirSync(courseDir);
fs.writeFileSync(
path.join(courseDir, 'course.md'),
nunjucks.renderString(
"![](teaser.jpg)\n\n# {{title}}\n\n{{description}}\n\n> {{quotation}}\n\n## {{cook.name}}\n\n{{cook.description}}\n\n## Videos\n\n{% for section in videoSection %}### {{section.title}}\n\n{% for video in section.videos %}* {{video.title}}\n{% endfor %}\n{% endfor %}",
course
)
);
await handlers.download(course.teaserImage.url, path.join(courseDir, 'teaser.jpg'));
await handlers.download(course.downloadRecipes?.url, path.join(courseDir, 'recipes.pdf'));
await handlers.download(course.downloadCourseBook?.url, path.join(courseDir, 'coursebook.pdf'));
for (const section of course.videoSection) {
let sectionDir = path.join(courseDir, slugify(section.title, {strict:true,lower:true}));
fs.ensureDirSync(sectionDir);
for(const video of section.videos) {
let m3u8File = path.join(sectionDir, `${slugify(video.title, {strict:true,lower:true})}.m3u8`);
await handlers.download(`https://strapi-prod.7hauben.com/${course.id}/${video.id}/playlist.m3u8`, m3u8File);
}
}
}
await browser.close();
})();
const handlers = {
login: async function (page) {
await page.goto('https://7hauben.com');
let menu = await page.$('#menu:not(.d-none)');
let button = (await menu.$x("//button[contains(text(), 'Login')]"))[1];
await button.click();
await page.waitForSelector('div[role="dialog"][aria-label="Login Modal"]');
let modal = await page.$('div[role="dialog"][aria-label="Login Modal"]');
let emailButton = (await modal.$x("//button[contains(text(), 'Mit E-Mail einloggen')]"))[0];
await emailButton.click();
await page.waitForSelector('div[role="dialog"][aria-label="Login Modal"] form');
await page.type('div[role="dialog"][aria-label="Login Modal"] form input[name="email"]', config.email, { delay: 100 });
await page.type('div[role="dialog"][aria-label="Login Modal"] form input[name="password"]', config.password, { delay: 100 });
await (await modal.$('form button')).click();
},
courses: async function (page) {
let script = await page.$('script#__NEXT_DATA__');
let data = JSON.parse(await page.evaluate(el => el.textContent, script));
return data.props.pageProps.courses;
},
course: async function (page, uuid) {
await page.goto(`https://www.7hauben.com/kochkurs-enrolled/${uuid}`);
let script = await page.$('script#__NEXT_DATA__');
let data = JSON.parse(await page.evaluate(el => el.textContent, script));
return data.props.pageProps.courseDetail;
},
download: function (url, filepath) {
if (!url) {
return;
}
if(fs.existsSync(filepath)) {
return;
}
return fetch(url).then(res => {
const stream = fs.createWriteStream(filepath);
res.body.pipe(stream);
});
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment