├── .gitignore
├── images
├── 1.jpg
├── 2.jpg
└── 3.jpg
├── package-lock.json
├── package.json
├── readme.md
├── src
├── icons
│ ├── icon.ico
│ ├── loadingscribd.gif
│ └── scribd.png
├── index.css
├── index.html
└── index.js
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | /.vscode
2 | /node_modules
3 | /out
--------------------------------------------------------------------------------
/images/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialguiba/scribd-downloader/91094aaa18006c20e51d256bafd92db493c44b5e/images/1.jpg
--------------------------------------------------------------------------------
/images/2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialguiba/scribd-downloader/91094aaa18006c20e51d256bafd92db493c44b5e/images/2.jpg
--------------------------------------------------------------------------------
/images/3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialguiba/scribd-downloader/91094aaa18006c20e51d256bafd92db493c44b5e/images/3.jpg
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "scribd-downloader",
3 | "productName": "scribd-downloader",
4 | "version": "1.0.0",
5 | "description": "Download documents from scribd",
6 | "main": "src/index.js",
7 | "scripts": {
8 | "start": "electron-forge start",
9 | "package": "electron-forge package",
10 | "make-squirrel": "electron-forge make",
11 | "make-deb": "electron-forge make --targets @electron-forge/maker-deb",
12 | "make-zip": "electron-forge make --targets @electron-forge/maker-zip",
13 | "make-rpm": "electron-forge make --targets @electron-forge/maker-rpm",
14 | "publish": "electron-forge publish",
15 | "lint": "echo \"No linting configured\""
16 | },
17 | "keywords": [],
18 | "author": {
19 | "name": "dialguiba",
20 | "email": "dialguiba@gmail.com"
21 | },
22 | "license": "MIT",
23 | "config": {
24 | "forge": {
25 | "packagerConfig": {},
26 | "makers": [
27 | {
28 | "name": "@electron-forge/maker-squirrel",
29 | "config": {
30 | "name": "scribd_downloader"
31 | }
32 | },
33 | {
34 | "name": "@electron-forge/maker-zip",
35 | "platforms": [
36 | "darwin"
37 | ]
38 | },
39 | {
40 | "name": "@electron-forge/maker-deb",
41 | "config": {}
42 | },
43 | {
44 | "name": "@electron-forge/maker-rpm",
45 | "config": {}
46 | }
47 | ]
48 | }
49 | },
50 | "dependencies": {
51 | "electron-builder": "^22.8.1",
52 | "electron-squirrel-startup": "^1.0.0",
53 | "image-size": "^0.9.1",
54 | "pdfkit": "^0.11.0",
55 | "puppeteer": "^5.3.0",
56 | "puppeteer-cluster": "^0.22.0"
57 | },
58 | "devDependencies": {
59 | "@electron-forge/cli": "^6.0.0-beta.53",
60 | "@electron-forge/maker-deb": "^6.0.0-beta.53",
61 | "@electron-forge/maker-rpm": "^6.0.0-beta.53",
62 | "@electron-forge/maker-squirrel": "^6.0.0-beta.53",
63 | "@electron-forge/maker-zip": "^6.0.0-beta.53",
64 | "electron": "10.1.2"
65 | }
66 | }
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # **SCRIBD DOWNLOADER**
2 |
3 | YOU CAN DOWNLOAD THE APPLICATION FROM HERE
4 | [Download](https://drive.google.com/file/d/1uYsorrljOM7uLkiHN_ylX-ao0B0NtSHd/view?usp=sharing)
5 |
6 | 
7 |
8 | 
9 |
10 | 
11 |
12 | ## **Also, if you want to support me you can do it here :) :**
13 |
14 | [](https://www.buymeacoffee.com/dialguiba)
15 |
--------------------------------------------------------------------------------
/src/icons/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialguiba/scribd-downloader/91094aaa18006c20e51d256bafd92db493c44b5e/src/icons/icon.ico
--------------------------------------------------------------------------------
/src/icons/loadingscribd.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialguiba/scribd-downloader/91094aaa18006c20e51d256bafd92db493c44b5e/src/icons/loadingscribd.gif
--------------------------------------------------------------------------------
/src/icons/scribd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialguiba/scribd-downloader/91094aaa18006c20e51d256bafd92db493c44b5e/src/icons/scribd.png
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica,
3 | Arial, sans-serif;
4 | margin: auto;
5 | max-width: 38rem;
6 | padding: 2rem;
7 | }
8 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Docs Downloader
5 |
9 |
10 |
11 |
18 |
19 |
36 |
37 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | const puppeteer = require("puppeteer");
2 | const { app, BrowserWindow, Menu, ipcMain } = require("electron");
3 | const url = require("url");
4 | const { Cluster } = require("puppeteer-cluster");
5 | const PDFDocument = require("pdfkit");
6 | var sizeOf = require("image-size");
7 | const path = require("path");
8 | const fs = require("fs");
9 | const tempDir = "downloads/temp";
10 | const downloadsDir = "downloads";
11 |
12 | // Handle creating/removing shortcuts on Windows when installing/uninstalling.
13 | if (require("electron-squirrel-startup")) {
14 | // eslint-disable-line global-require
15 | app.quit();
16 | }
17 |
18 | const createWindow = () => {
19 | // Create the browser window.
20 | const mainWindow = new BrowserWindow({
21 | width: 800,
22 | height: 600,
23 | });
24 |
25 | // and load the index.html of the app.
26 | mainWindow.loadFile(path.join(__dirname, "index.html"));
27 |
28 | // Open the DevTools.
29 | mainWindow.webContents.openDevTools();
30 | };
31 |
32 | // This method will be called when Electron has finished
33 | // initialization and is ready to create browser windows.
34 | // Some APIs can only be used after this event occurs.
35 | // Listen for app to be ready
36 | app.on("ready", function () {
37 | // Create new window
38 | mainWindow = new BrowserWindow({
39 | width: 530,
40 | height: 313,
41 | webPreferences: {
42 | nodeIntegration: true,
43 | },
44 | });
45 | // Load html in window
46 | mainWindow.loadURL(
47 | url.format({
48 | pathname: path.join(__dirname, "index.html"),
49 | protocol: "file:",
50 | slashes: true,
51 | })
52 | );
53 | // Quit app when closed
54 | mainWindow.on("closed", function () {
55 | app.quit();
56 | });
57 |
58 | // Build menu from template
59 | const mainMenu = Menu.buildFromTemplate(mainMenuTemplate);
60 | // Insert menu
61 | Menu.setApplicationMenu(mainMenu);
62 | });
63 |
64 | // Catch document:get
65 | ipcMain.on("document:get", function (e, idbook, docName) {
66 | /* let anyError = getDocument(idbook);
67 | anyError.then((e) => {
68 | console.log("finished");
69 | mainWindow.webContents.send("state:finished");
70 | }); */
71 |
72 | getDocument(idbook, docName).then(() => {
73 | mainWindow.webContents.send("state:finished");
74 | });
75 |
76 | //mainWindow.webContents.send("item:add", item);
77 | //addWindow.close();
78 | // Still have a reference to addWindow in memory. Need to reclaim memory (Grabage collection)
79 | //addWindow = null;
80 | });
81 |
82 | // Create menu template
83 | const mainMenuTemplate = [
84 | // Each object is a dropdown
85 | {
86 | label: "File",
87 | submenu: [
88 | {
89 | label: "Quit",
90 | accelerator: process.platform == "darwin" ? "Command+Q" : "Ctrl+Q",
91 | click() {
92 | app.quit();
93 | },
94 | },
95 | ],
96 | },
97 | ];
98 |
99 | // If OSX, add empty object to menu
100 | if (process.platform == "darwin") {
101 | mainMenuTemplate.unshift({});
102 | }
103 |
104 | // Quit when all windows are closed, except on macOS. There, it's common
105 | // for applications and their menu bar to stay active until the user quits
106 | // explicitly with Cmd + Q.
107 | app.on("window-all-closed", () => {
108 | if (process.platform !== "darwin") {
109 | app.quit();
110 | }
111 | });
112 |
113 | app.on("activate", () => {
114 | // On OS X it's common to re-create a window in the app when the
115 | // dock icon is clicked and there are no other windows open.
116 | if (BrowserWindow.getAllWindows().length === 0) {
117 | createWindow();
118 | }
119 | });
120 |
121 | let getDocument = async (idbook, docName) => {
122 | try {
123 | if (!fs.existsSync(downloadsDir)) {
124 | fs.mkdirSync(downloadsDir);
125 | if (!fs.existsSync(tempDir)) {
126 | fs.mkdirSync(tempDir);
127 | }
128 | }
129 | //
130 |
131 | const browser = await puppeteer.launch({
132 | headless: true,
133 | args: ["--no-sandbox", "--disable-setuid-sandbox", "--disable-dev-shm-usage"],
134 | });
135 | const initPage = await browser.newPage();
136 | await initPage.goto(`https://es.scribd.com/embeds/${idbook}/content?start_page=1`);
137 | //!Numero de paginas
138 | const elementPages = await initPage.$(".total_pages");
139 | const textPages = await initPage.evaluate((elementPages) => elementPages.textContent, elementPages);
140 | const pagesNumber = textPages.match(/\d+/)[0];
141 | console.log(pagesNumber);
142 |
143 | // Create a cluster with 2 workers
144 | const cluster = await Cluster.launch({
145 | concurrency: Cluster.CONCURRENCY_CONTEXT,
146 | maxConcurrency: 3,
147 | headless: true,
148 | args: ["--no-sandbox", "--disable-setuid-sandbox", "--disable-dev-shm-usage"],
149 | });
150 |
151 | /* doc.pipe(fs.createWriteStream("output.pdf")); */
152 | // Define a task (in this case: screenshot of page)
153 | await cluster.task(async ({ page, data: url }) => {
154 | await page.setViewport({
155 | width: 800,
156 | height: 800,
157 | deviceScaleFactor: 2.5,
158 | });
159 | await page.goto(url, { waitUntil: "networkidle2" });
160 |
161 | //!Eliminate
162 | await page.evaluate(() => {
163 | let example = document.querySelector(".toolbar_drop");
164 | let example3 = document.querySelector("#fb-root");
165 | let example4 = document.querySelector(".mobile_overlay");
166 | let example5 = document.querySelector("#font_preload_bed");
167 | let example6 = document.querySelector(".osano-cm-window__dialog");
168 |
169 | example.parentNode.removeChild(example);
170 | example3.parentNode.removeChild(example3);
171 | example4.parentNode.removeChild(example4);
172 | example5.parentNode.removeChild(example5);
173 | example6.parentNode.removeChild(example6);
174 | });
175 | //elemento
176 | let actualPage = url.match(/start_page=(\d+)/)[1];
177 | let selector = `#page${actualPage}`;
178 | const rect = await page.evaluate((selector) => {
179 | const element = document.querySelector(selector);
180 | if (!element) {
181 | return null;
182 | }
183 | var { x, y, width, height } = element.getBoundingClientRect();
184 |
185 | return { left: x, top: y, width, height, id: element.id };
186 | }, selector);
187 |
188 | const path = `${tempDir}/${actualPage}.png`;
189 |
190 | await page.waitForSelector(`#page${actualPage}`).then(async () => {
191 | await page.screenshot({
192 | path,
193 | clip: {
194 | x: rect.left,
195 | y: rect.top,
196 | width: rect.width,
197 | height: rect.height,
198 | },
199 | });
200 | });
201 | });
202 |
203 | for (i = 1; i <= pagesNumber; i++) {
204 | cluster.queue(`https://es.scribd.com/embeds/${idbook}/content?start_page=${i}&view_mode=slideshow`);
205 | }
206 |
207 | // Shutdown after everything is done
208 | await cluster.idle();
209 | await cluster.close();
210 |
211 | createPdf(pagesNumber, docName);
212 | deleteTemp();
213 | } catch (e) {
214 | console.log(e);
215 | }
216 | };
217 |
218 | function createPdf(numberPages, fileName) {
219 | var dimensions = sizeOf("downloads/temp/1.png");
220 | let width = dimensions.width;
221 | let height = dimensions.height;
222 | // Create a document
223 | let doc;
224 |
225 | if (width > height) {
226 | doc = new PDFDocument({ layout: "landscape" });
227 | } else {
228 | doc = new PDFDocument({ layout: "portrait" });
229 | }
230 |
231 | // Pipe its output somewhere, like to a file or HTTP response
232 | // See below for browser usage
233 | doc.pipe(fs.createWriteStream(`downloads/${fileName}.pdf`));
234 |
235 | doc.text("").moveDown(8);
236 | doc
237 | .text("Gracias por usar mi programa", {
238 | align: "center",
239 | })
240 | .fontSize(12);
241 | doc.text("Desarrollado por: dialguiba", { align: "center" }).fontSize(12).moveDown(8);
242 |
243 | doc.text("Si este servicio de descarga te sirvió y gustas apoyar puedes hacerlo en:", { align: "center" }).fontSize(15).moveDown(1);
244 | doc
245 | .text(
246 | "https://www.buymeacoffee.com/dialguiba",
247 |
248 | { align: "center" }
249 | )
250 | .fontSize(15)
251 | .moveDown(4);
252 | doc
253 | .text("Si tienes algún problema o sugerencia: dialguiba1994@gmail.com", {
254 | align: "center",
255 | })
256 | .fontSize(15)
257 | .moveDown(1);
258 |
259 | // Add an image, constrain it to a given size, and center it vertically and horizontally
260 | /* if (width > height) {
261 | doc.image("downloads/temp/1.png", {
262 | fit: [680, 460],
263 | //fit: [500, 550],
264 | //width: 800,
265 | align: "center",
266 | valign: "center",
267 | });
268 | } else {
269 | doc.image("downloads/temp/1.png", {
270 | fit: [460, 720],
271 | align: "center",
272 | valign: "center",
273 | });
274 | } */
275 |
276 | //deleteFile("./1.png");
277 |
278 | for (i = 1; i <= numberPages; i++) {
279 | if (width > height) {
280 | doc.addPage().image(`downloads/temp/${i}.png`, {
281 | fit: [680, 460],
282 | //fit: [500, 550],
283 | //width: 800,
284 | align: "center",
285 | valign: "center",
286 | });
287 | } else {
288 | doc.addPage().image(`downloads/temp/${i}.png`, {
289 | fit: [460, 720],
290 | align: "center",
291 | valign: "center",
292 | });
293 | }
294 | }
295 | let finished = "finished";
296 | // Finalize PDF file
297 | doc.save();
298 | doc.end();
299 | return finished;
300 | }
301 |
302 | function deleteTemp() {
303 | const directory = "downloads/temp/";
304 |
305 | fs.readdir(directory, (err, files) => {
306 | if (err) throw err;
307 |
308 | for (const file of files) {
309 | fs.unlink(path.join(directory, file), (err) => {
310 | if (err) throw err;
311 | });
312 | }
313 | });
314 | }
315 |
--------------------------------------------------------------------------------