UNPKG

tcdown

Version:

Downloader and scraper for teachable.com for members

171 lines (147 loc) 6.65 kB
const path = require('path') const fs = require('fs-extra') const sanitize = require("sanitize-filename"); const { differenceBy } = require('lodash') module.exports = class FileChecker { static logger; static getFilesizeInBytes = filename => { return fs.existsSync(filename) ? fs.statSync(filename)["size"] : 0; }; static createLogger(downloadFolder, fileName = 'videos.txt') { const logFile = path.join(downloadFolder, fileName); /* fs.existsSync(logFile) ? console.log(`File ${logFile} already exists`) : console.log(`File ${logFile} created`);*/ return fs.createWriteStream(logFile, { flags: 'a' }); // this.logger = fs.createWriteStream(logFile, { flags: 'a' }); // return this.logger; }; static write(downFolder, dest) { // console.log('this.isCompletelyDownloaded(downFolder, dest)', this.isCompletelyDownloaded(downFolder, dest)); if (!this.isCompletelyDownloadedWithOutSize(downFolder, dest)) { this.logger.write(`${dest} Size:${this.getFilesizeInBytes(dest)}\n`); } } static writeWithOutSize(downFolder, dest) { // console.log('this.isCompletelyDownloaded(downFolder, dest)', this.isCompletelyDownloaded(downFolder, dest)); if (!this.isCompletelyDownloadedWithOutSize(downFolder, dest)) { // this.createLogger(downFolder) // this.logger.write(`${dest}\n`); const videoLogger = this.createLogger(downFolder, 'videos.txt'); videoLogger.write(`${dest}\n`); } } static findDownloadedVideos = downloadFolder => { const logFile = `${downloadFolder}${path.sep}videos.txt`; if (!fs.existsSync(logFile)) return []; return fs.readFileSync(logFile).toString().split("\n"); } static isCompletelyDownloaded = (downloadFolder, videoName, remoteSize) => { const downloadedVideos = this.findDownloadedVideos(downloadFolder); if (typeof downloadedVideos === 'undefined' || downloadedVideos.length === 0) { return false; } videoName = `${videoName} Size:${remoteSize ?? this.getFilesizeInBytes(videoName)}` for (let downloadedVideoName of downloadedVideos) { // console.log('downloadedVideoName', videoName === downloadedVideoName, videoName, downloadedVideoName); if (videoName === downloadedVideoName) { return downloadedVideoName; } } return false; } static linkFileExists(dest) { const logFile = path.join(dest, 'links.txt') if (!fs.existsSync(logFile)) return []; //fileName example // [ // 'videos/React 18 for Beginners/07-1- What is React.mp4', // 'videos/React 18 for Beginners/133-41- Course Wrap Up.mp4', // ] const fileNames = fs.readFileSync(logFile).toString().split("\n").filter(Boolean); const sanitizeFilenames = fileNames.map(url => ({url}));//fileName.split('/').pop().replace('.mp4', '').replace(/^\d+-/, '') // console.log('sanitizeFilenames:', sanitizeFilenames); return sanitizeFilenames; } static linkFileExistsWithUrl(dest, resourceUrl) { const urls = this.linkFileExists(dest) // console.log('--->', {urls, dest, resourceUrl}); if (urls.length === 0) { return []; } const a = urls.find(resource => resource.url === resourceUrl) ?? []; return a } static writeResourceUrlWithOutSize(downFolder, url) { const a = this.linkFileExistsWithUrl(downFolder, url) // console.log('writeResourceUrlWithOutSize:', a, a.length, a.length===0); if (a.length === 0) { // console.log('usli'); const videoLogger = this.createLogger(downFolder, 'links.txt'); videoLogger.write(`${url}\n`); } } static getDownloadedFilenames(lessons, dest) { // console.log('getDownloadedFilenames:', dest); const urls = this.linkFileExists(dest) if (urls.length === 0) { return lessons; } // console.log('sanitizeFilenames:', sanitizeFilenames.length); //lessons example // { // title: '3- Setting Up the Project', // url: 'https://members.codewithmosh.com/courses/ultimate-react-part1/lectures/45916277', // position: 94 // }, const links = differenceBy(lessons, urls, 'url') // console.log('links:', links.length); return links; } static isCompletelyDownloadedWithOutSize(downloadFolder, videoName) { const downloadedVideos = this.findDownloadedVideos(downloadFolder); if (typeof downloadedVideos === 'undefined' || downloadedVideos.length === 0) { return false; } videoName = `${videoName}` for (let downloadedVideoName of downloadedVideos) { // console.log('downloadedVideoName', videoName === downloadedVideoName, videoName, downloadedVideoName); if (videoName === downloadedVideoName) { return downloadedVideoName; } } return false; } static addPageAsDownloaded(course, opts, index, lesson) { let series = sanitize(course.title) const dest = path.join(opts.dir, series, `${String(index + 1).padStart(2, '0')}-${lesson.title}`) const videoLogger = this.createLogger(path.join(opts.dir, series)); videoLogger.write(`${dest}\n`); } static fileIsDownloaded(course, opts, index, lesson) { let series = sanitize(course.title) const dest = path.join(opts.dir, series, `${String(index + 1).padStart(2, '0')}-${lesson.title}`) let isDownloaded = this.isCompletelyDownloadedWithOutSize(path.join(opts.dir, series), dest) // console.log('isDownloaded', isDownloaded, lesson.title); return isDownloaded; } findNotExistingVideo(videos, downloadFolder) { let i = 0; for (let video of videos) { const name = video.name.toString().replace(/[^A-Za-zА-Яа-я\d\s]/gmi, '').replace('Урок ', ''); let filename = `${downloadFolder}${path.sep}${name}.mp4`; if (fs.existsSync(filename) && isCompletelyDownloaded(name, downloadFolder)) { console.log(`File "${name}" already exists`); i++; } else { break; } } return i; }; } /*module.exports = { findNotExistingVideo, isCompletelyDownloaded, createLogger }*/