chore(lucida): Improve download flow
This commit is contained in:
		
							parent
							
								
									81b18df1f4
								
							
						
					
					
						commit
						b5dcaaa515
					
				
					 1 changed files with 30 additions and 30 deletions
				
			
		|  | @ -2,7 +2,6 @@ import {DownloadResult, LucidaOptions} from "../types/queue"; | |||
| import {Browser, BrowserContext, Download, firefox, Locator, Page, Response as PResponse} from "playwright"; | ||||
| import path from "node:path"; | ||||
| import {fetchBooklet} from "./booklet"; | ||||
| import * as fs from "node:fs"; | ||||
| 
 | ||||
| class Lucida { | ||||
|     private browser: Browser | null; | ||||
|  | @ -77,18 +76,17 @@ class Lucida { | |||
| 
 | ||||
|     private async saveDownload(download: Download, downloadPath: string): Promise<string> { | ||||
|         const pathName: string = path.join(downloadPath, download.suggestedFilename()); | ||||
|         // await download.saveAs(pathName);
 | ||||
|         // return pathName;
 | ||||
|         await download.saveAs(pathName); | ||||
| 
 | ||||
|         const stream = fs.createWriteStream(pathName); | ||||
|         const response = await download.createReadStream(); | ||||
|         if (response) { | ||||
|             response.pipe(stream); | ||||
|             await new Promise((resolve, reject) => { | ||||
|                 stream.on('finish', resolve); | ||||
|                 stream.on('error', reject); | ||||
|             }); | ||||
|         } | ||||
|         // const stream = fs.createWriteStream(pathName);
 | ||||
|         // const response = await download.createReadStream();
 | ||||
|         // if (response) {
 | ||||
|         //     response.pipe(stream);
 | ||||
|         //     await new Promise((resolve, reject) => {
 | ||||
|         //         stream.on('finish', resolve);
 | ||||
|         //         stream.on('error', reject);
 | ||||
|         //     });
 | ||||
|         // }
 | ||||
| 
 | ||||
|         return pathName; | ||||
|     } | ||||
|  | @ -97,6 +95,7 @@ class Lucida { | |||
|         status: string | ||||
|     }): Promise<DownloadResult> { | ||||
|         let finished: boolean = false; | ||||
|         let started: boolean = true; | ||||
| 
 | ||||
|         let close: boolean = false; | ||||
|         if (this.context === null) { | ||||
|  | @ -123,7 +122,7 @@ class Lucida { | |||
| 
 | ||||
|         // Check for errors
 | ||||
|         const error: string | undefined = await this.getError(downloadPage); | ||||
|         if (error) { | ||||
|         if (error !== undefined) { | ||||
|             await downloadPage.close(); | ||||
|             return { | ||||
|                 success: false, | ||||
|  | @ -138,42 +137,38 @@ class Lucida { | |||
| 
 | ||||
|         // Listen for download
 | ||||
|         downloadPage.once('download', async (download) => { | ||||
|             started = true; | ||||
|             await this.saveDownload(download, downloadPath); | ||||
|             finished = true; | ||||
|             await fetchBooklet(url, downloadPath, this.context); | ||||
| 
 | ||||
|             await downloadPage.close(); | ||||
|             await fetchBooklet(url, downloadPath, this.context); | ||||
|             finished = true; | ||||
| 
 | ||||
|             if (close) { | ||||
|                 await this.destruct(); | ||||
|             } | ||||
| 
 | ||||
|             process.stdout.clearLine(0); | ||||
|             return {success: true}; | ||||
|         }); | ||||
|         // Start download
 | ||||
|         await downloadPage.getByText('download full album').click(); | ||||
| 
 | ||||
|         // Retry file download if it fails
 | ||||
|         const maxRetries: number = 10; | ||||
|         const progressElement: Locator = downloadPage.locator('div[class="loader svelte-1ipdo3f"]'); | ||||
|         while (!finished && retryCount < 10 && (Date.now() - start) < timeout) { | ||||
|         while (!started && retryCount < maxRetries && (Date.now() - start) < timeout) { | ||||
|             const retry: Locator = downloadPage.getByText('Retry'); | ||||
|             const error: string | undefined = finished ? undefined : await this.getError(downloadPage); | ||||
|             const error: string | undefined = started ? undefined : await this.getError(downloadPage); | ||||
| 
 | ||||
|             if (error !== undefined) { | ||||
|                 console.log('Retrying download because of error:', error); | ||||
|                 await retry.click(); | ||||
|                 retryCount++; | ||||
|             } else if (!finished && await progressElement.count() !== 0 && await progressElement.isVisible()) { | ||||
|                 const progress: string = (await progressElement.locator('p').innerText()).trim(); | ||||
|                 status.status = progress; | ||||
|                 process.stdout.clearLine(0); | ||||
|                 process.stdout.write(`\r${progress}`); | ||||
|             } else if (!started && await progressElement.count() !== 0 && await progressElement.isVisible()) { | ||||
|                 status.status = (await progressElement.locator('p').innerText()).trim(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         process.stdout.clearLine(0); | ||||
| 
 | ||||
|         if (!finished) { | ||||
|         if (!started) { | ||||
|             // Cleanup
 | ||||
|             await downloadPage.close(); | ||||
|             if (close) { | ||||
|  | @ -183,8 +178,8 @@ class Lucida { | |||
|             let errorMessage: string; | ||||
|             if (timeout <= (Date.now() - start)) { | ||||
|                 errorMessage = 'Download timed out'; | ||||
|             } else if (retryCount >= 10) { | ||||
|                 errorMessage = 'Download failed after 10 retries'; | ||||
|             } else if (retryCount >= maxRetries) { | ||||
|                 errorMessage = `Download failed after ${maxRetries} retries`; | ||||
|             } else { | ||||
|                 errorMessage = 'Unknown error'; | ||||
|             } | ||||
|  | @ -194,7 +189,12 @@ class Lucida { | |||
|             }; | ||||
|         } | ||||
| 
 | ||||
|         return {success: true}; | ||||
|         // Wait for download to finish
 | ||||
|         await new Promise(resolve => setTimeout(resolve, 30000)); | ||||
|         return { | ||||
|             success: finished, | ||||
|             error: finished ? undefined : 'Save to disk did not finish.' | ||||
|         }; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Reference in a new issue