From 333556c305db71186ecbce1fd8f1139e2441020b Mon Sep 17 00:00:00 2001 From: Isaac Abadi Date: Sat, 25 Jul 2020 15:57:10 -0400 Subject: [PATCH] Removed erroneous code and added the ability to kill all downlaods --- backend/app.js | 77 +++++++++++++----------- backend/package.json | 1 + src/app/posts.services.ts | 8 +-- src/app/settings/settings.component.html | 6 +- src/app/settings/settings.component.ts | 31 +++++++++- 5 files changed, 79 insertions(+), 44 deletions(-) diff --git a/backend/app.js b/backend/app.js index 3b3cac0..f7c1ee7 100644 --- a/backend/app.js +++ b/backend/app.js @@ -30,6 +30,7 @@ var subscriptions_api = require('./subscriptions') const CONSTS = require('./consts') const { spawn } = require('child_process') const read_last_lines = require('read-last-lines'); +var ps = require('ps-node'); const is_windows = process.platform === 'win32'; @@ -503,6 +504,43 @@ async function getLatestVersion() { }); } +async function killAllDownloads() { + return new Promise(resolve => { + ps.lookup({ + command: 'youtube-dl', + }, function(err, resultList ) { + if (err) { + // failed to get list of processes + logger.error('Failed to get a list of running youtube-dl processes.'); + logger.error(err); + resolve({ + details: err, + success: false + }); + } + + // processes that contain the string 'youtube-dl' in the name will be looped + resultList.forEach(function( process ){ + if (process) { + ps.kill(process.pid, 'SIGKILL', function( err ) { + if (err) { + // failed to kill, process may have ended on its own + logger.warn(`Failed to kill process with PID ${process.pid}`); + logger.warn(err); + } + else { + logger.verbose(`Process ${process.pid} has been killed!`); + } + }); + } + }); + resolve({ + success: true + }); + }); + }); +} + async function setPortItemFromENV() { return new Promise(resolve => { config_api.setConfigItem('ytdl_port', backendPort.toString()); @@ -1931,42 +1969,9 @@ app.post('/api/tomp4', optionalJwt, async function(req, res) { } }); -// gets the status of the mp3 file that's being downloaded -app.post('/api/fileStatusMp3', function(req, res) { - var name = decodeURIComponent(req.body.name + ""); - var exists = ""; - var fullpath = audioFolderPath + name + ".mp3"; - if (fs.existsSync(fullpath)) { - exists = [basePath + audioFolderPath + name, getFileSizeMp3(name)]; - } - else - { - var percent = 0; - var size = getFileSizeMp3(name); - var downloaded = getAmountDownloadedMp3(name); - if (size > 0) - percent = downloaded/size; - exists = ["failed", getFileSizeMp3(name), percent]; - } - res.send(exists); -}); - -// gets the status of the mp4 file that's being downloaded -app.post('/api/fileStatusMp4', function(req, res) { - var name = decodeURIComponent(req.body.name); - var exists = ""; - var fullpath = videoFolderPath + name + ".mp4"; - if (fs.existsSync(fullpath)) { - exists = [basePath + videoFolderPath + name, getFileSizeMp4(name)]; - } else { - var percent = 0; - var size = getFileSizeMp4(name); - var downloaded = getAmountDownloadedMp4(name); - if (size > 0) - percent = downloaded/size; - exists = ["failed", getFileSizeMp4(name), percent]; - } - res.send(exists); +app.post('/api/killAllDownloads', optionalJwt, async function(req, res) { + const result_obj = await killAllDownloads(); + res.send(result_obj); }); // gets all download mp3s diff --git a/backend/package.json b/backend/package.json index e6f7f52..f015272 100644 --- a/backend/package.json +++ b/backend/package.json @@ -50,6 +50,7 @@ "passport-jwt": "^4.0.0", "passport-local": "^1.0.0", "progress": "^2.0.3", + "ps-node": "^0.1.6", "read-last-lines": "^1.7.2", "shortid": "^2.2.15", "unzipper": "^0.10.10", diff --git a/src/app/posts.services.ts b/src/app/posts.services.ts index b334c1e..64eb15e 100644 --- a/src/app/posts.services.ts +++ b/src/app/posts.services.ts @@ -163,12 +163,8 @@ export class PostsService implements CanActivate { ui_uid: ui_uid}, this.httpOptions); } - getFileStatusMp3(name: string) { - return this.http.post(this.path + 'fileStatusMp3', {name: name}, this.httpOptions); - } - - getFileStatusMp4(name: string) { - return this.http.post(this.path + 'fileStatusMp4', {name: name}, this.httpOptions); + killAllDownloads() { + return this.http.post(this.path + 'killAllDownloads', {}, this.httpOptions); } loadNavItems() { diff --git a/src/app/settings/settings.component.html b/src/app/settings/settings.component.html index b5cf98d..7a0ee52 100644 --- a/src/app/settings/settings.component.html +++ b/src/app/settings/settings.component.html @@ -153,9 +153,13 @@

Note: This setting only applies to downloads on the Home page. If you would like to use youtube-dl archive functionality in subscriptions, head to the Main tab and activate this option there.

-
+
Safe download override
+ +
+ +
diff --git a/src/app/settings/settings.component.ts b/src/app/settings/settings.component.ts index 142be3c..4a7684f 100644 --- a/src/app/settings/settings.component.ts +++ b/src/app/settings/settings.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, EventEmitter } from '@angular/core'; import { PostsService } from 'app/posts.services'; import { isoLangs } from './locales_list'; import { MatSnackBar } from '@angular/material/snack-bar'; @@ -8,6 +8,7 @@ import { ArgModifierDialogComponent } from 'app/dialogs/arg-modifier-dialog/arg- import { CURRENT_VERSION } from 'app/consts'; import { MatCheckboxChange } from '@angular/material/checkbox'; import { CookiesUploaderDialogComponent } from 'app/dialogs/cookies-uploader-dialog/cookies-uploader-dialog.component'; +import { ConfirmDialogComponent } from 'app/dialogs/confirm-dialog/confirm-dialog.component'; @Component({ selector: 'app-settings', @@ -154,6 +155,34 @@ export class SettingsComponent implements OnInit { }); } + killAllDownloads() { + const done = new EventEmitter(); + const dialogRef = this.dialog.open(ConfirmDialogComponent, { + data: { + dialogTitle: 'Kill downloads', + dialogText: 'Are you sure you want to kill all downloads? Any subscription and non-subscription downloads will end immediately, though this operation may take a minute or so to complete.', + submitText: 'Kill all downloads', + doneEmitter: done + } + }); + done.subscribe(confirmed => { + if (confirmed) { + this.postsService.killAllDownloads().subscribe(res => { + if (res['success']) { + dialogRef.close(); + this.postsService.openSnackBar('Successfully killed all downloads!'); + } else { + dialogRef.close(); + this.postsService.openSnackBar('Failed to kill all downloads! Check logs for details.'); + } + }, err => { + dialogRef.close(); + this.postsService.openSnackBar('Failed to kill all downloads! Check logs for details.'); + }); + } + }); + } + // snackbar helper public openSnackBar(message: string, action: string = '') { this.snackBar.open(message, action, {