Created
November 17, 2022 08:56
-
-
Save Gummibeer/aa00ec08fe1ccb1cb3f5da673e2f80b9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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( | |
"\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