From 8f215b2f6aac7a831625f2ddccb577b53b061aa9 Mon Sep 17 00:00:00 2001 From: Flokami Date: Mon, 18 Apr 2022 22:51:16 +0400 Subject: [PATCH 01/22] Fix : Test pg_escape and pg_unescape exist before executing them --- lib/Tools/DbHelper.php | 7 ++++++- lib/Tools/YoutubeHelper.php | 4 +++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/Tools/DbHelper.php b/lib/Tools/DbHelper.php index 6019864..eabf635 100644 --- a/lib/Tools/DbHelper.php +++ b/lib/Tools/DbHelper.php @@ -132,7 +132,12 @@ class DbHelper public function getExtra($data) { if ($this->getDBType() == "pgsql" && is_resource($data)) { - $extra = pg_unescape_bytea(stream_get_contents($data)); + if (function_exists("pg_unescape_bytea")) { + $extra = pg_unescape_bytea(stream_get_contents($data)); + } + else { + $extra = stream_get_contents($data); + } return unserialize($extra); } return unserialize($data); diff --git a/lib/Tools/YoutubeHelper.php b/lib/Tools/YoutubeHelper.php index 4e9cc8d..fd13af4 100644 --- a/lib/Tools/YoutubeHelper.php +++ b/lib/Tools/YoutubeHelper.php @@ -65,7 +65,9 @@ class YoutubeHelper if ($file) { $extra = serialize($extra); if($this->dbconn->getDBType() == "pgsql"){ - $extra = pg_escape_bytea($extra); + if (function_exists("pg_escape_bytea")) { + $extra = pg_escape_bytea($extra); + } } $data = [ 'uid' => $this->user, From 78487563f33936b1d0446a83096c3336c07a936a Mon Sep 17 00:00:00 2001 From: huangjx Date: Wed, 20 Apr 2022 20:35:21 +0800 Subject: [PATCH 02/22] use [].includes to shorten the long if statement of audio format checking --- src/App.vue | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/App.vue b/src/App.vue index 6f3a35c..2f54172 100644 --- a/src/App.vue +++ b/src/App.vue @@ -62,10 +62,10 @@ export default { formData["audio-only"] = ""; formData["extension"] = ""; if (formData["select-value-extension"] !== "Default") { - formData["extension"] = formData["select-value-extension"]; - if ((formData["select-value-extension"] === "mp3" ) || (formData["select-value-extension"] === "m4a" ) || (formData["select-value-extension"] === "vorbis" ) ) { - formData["audio-only"] = "true"; - } + formData["extension"] = formData["select-value-extension"]; + if (["mp3", "m4a", "vorbis"].includes(formData["select-value-extension"])) { + formData["audio-only"] = "true"; + } } message = helper.t("Download task started!"); } From aa1bf42ccc2f2182bcb08a98cdd19f9b84459a1a Mon Sep 17 00:00:00 2001 From: huangjx Date: Wed, 20 Apr 2022 21:11:09 +0800 Subject: [PATCH 03/22] fixed the issue of rendering url valid when it contains white spaces at its begining --- lib/Controller/MainController.php | 1 + lib/Tools/Helper.php | 8 ++++---- lib/Tools/Youtube.php | 4 ++-- src/App.vue | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/Controller/MainController.php b/lib/Controller/MainController.php index 572447d..d17331e 100644 --- a/lib/Controller/MainController.php +++ b/lib/Controller/MainController.php @@ -15,6 +15,7 @@ use OCP\AppFramework\Http\TemplateResponse; use OCP\IL10N; use OCP\IRequest; use OC_Util; +use OC\Files\Filesystem; class MainController extends Controller { diff --git a/lib/Tools/Helper.php b/lib/Tools/Helper.php index fd6641a..eec2b2f 100644 --- a/lib/Tools/Helper.php +++ b/lib/Tools/Helper.php @@ -10,7 +10,7 @@ class Helper { public const DOWNLOADTYPE = ['ARIA2' => 1, 'YOUTUBE-DL' => 2, 'OTHERS' => 3]; public const STATUS = ['ACTIVE' => 1, 'PAUSED' => 2, 'COMPLETE' => 3, 'WAITING' => 4, 'ERROR' => 5]; - const MAXLEN = 255; + const MAXFILELEN = 255; public static function isUrl($URL) { @@ -61,8 +61,8 @@ class Helper } public static function clipFilename($filename) { - if (($len = strlen($filename)) > 64) { - return substr($filename, $len - 64); + if (($len = strlen($filename)) > self::MAXFILELEN) { + return substr($filename, $len - self::MAXFILELEN); } return $filename; } @@ -73,7 +73,7 @@ class Helper } else { $filename = self::getUrlPath($url); } - return substr($filename, 0, self::MAXLEN); + return substr($filename, 0, self::MAXFILELEN); } public static function formatBytes($size, $precision = 2) { diff --git a/lib/Tools/Youtube.php b/lib/Tools/Youtube.php index 0623d58..0573dfd 100644 --- a/lib/Tools/Youtube.php +++ b/lib/Tools/Youtube.php @@ -104,9 +104,9 @@ class Youtube return $this; } - public static function create() + public static function create($options) { - return new self(); + return new self($options); } public function setDownloadDir($dir) diff --git a/src/App.vue b/src/App.vue index 2f54172..098d5e7 100644 --- a/src/App.vue +++ b/src/App.vue @@ -56,7 +56,7 @@ export default { let element = event.target; let formWrapper = element.closest("form"); let formData = helper.getData(formWrapper); - let inputValue = formData["text-input-value"]; + let inputValue = formData["text-input-value"].trim(); let message; if (formData.type === "youtube-dl") { formData["audio-only"] = ""; From 73d01e558f2845af63a9f4c8f17514a46c8d7025 Mon Sep 17 00:00:00 2001 From: huangjx Date: Fri, 22 Apr 2022 16:47:31 +0800 Subject: [PATCH 04/22] fixed #47;some cleaning up and bugfixes; --- appinfo/application.php | 50 +----------- lib/Controller/MainController.php | 8 +- lib/Controller/YoutubeController.php | 13 +-- lib/Search/Sites/TPB.php | 1 - lib/Search/Sites/bitSearch.php | 1 - lib/Tools/Helper.php | 118 ++++++++++++++++++++++++++- lib/Tools/Youtube.php | 2 +- lib/Tools/folderScan.php | 31 ++----- 8 files changed, 138 insertions(+), 86 deletions(-) diff --git a/appinfo/application.php b/appinfo/application.php index 40694a2..6cd7107 100644 --- a/appinfo/application.php +++ b/appinfo/application.php @@ -19,11 +19,9 @@ class Application extends App public function __construct(array $urlParams = array()) { parent::__construct('ncdownloader', $urlParams); - $user = \OC::$server->getUserSession()->getUser(); + $user = Helper::getUser(); $this->uid = ($user) ? $user->getUID() : ''; $this->settings = new Settings($this->uid); - $this->dataDir = \OC::$server->getSystemConfig()->getValue('datadirectory'); - $this->appPath = \OC::$server->getAppManager()->getAppPath('ncdownloader'); $this->userFolder = Helper::getUserFolder($this->uid); $container = $this->getContainer(); $container->registerService('UserId', function (IContainer $container) { @@ -31,15 +29,11 @@ class Application extends App }); $container->registerService('Aria2', function (IContainer $container) { - return new Aria2($this->getConfig()); + return new Aria2(Helper::getAria2Config($this->uid)); }); $container->registerService('Youtube', function (IContainer $container) { - $config = [ - 'binary' => $this->settings->setType(Settings::TYPE['SYSTEM'])->get("ncd_yt_binary"), - 'downloadDir' => $this->getRealDownloadDir(), - 'settings' => $this->settings->setType(Settings::TYPE['USER'])->getYoutube(), - ]; + $config = Helper::getYoutubeConfig($this->uid); return new Youtube($config); }); @@ -100,42 +94,4 @@ class Application extends App } } - private function getRealDownloadDir() - { - - //relative nextcloud user path - $dir = $this->settings->get('ncd_downloader_dir') ?? "/Downloads"; - return $this->dataDir . $this->userFolder . $dir; - } - private function getRealTorrentsDir() - { - $dir = $this->settings->get('ncd_torrents_dir') ?? "/Torrents"; - return $this->dataDir . $this->userFolder . $dir; - } - - private function getConfig() - { - //$this->config = \OC::$server->getAppConfig(); - $realDownloadDir = $this->getRealDownloadDir(); - $torrentsDir = $this->getRealTorrentsDir(); - $aria2_dir = $this->dataDir . "/aria2"; - $settings['seed_time'] = $this->settings->get("ncd_seed_time"); - $settings['seed_ratio'] = $this->settings->get("ncd_seed_ratio"); - if (is_array($customSettings = $this->settings->getAria2())) { - $settings = array_merge($customSettings, $settings); - } - $token = $this->settings->setType(Settings::TYPE['SYSTEM'])->get('ncd_rpctoken'); - $config = [ - 'dir' => $realDownloadDir, - 'torrents_dir' => $torrentsDir, - 'conf_dir' => $aria2_dir, - 'token' => $token, - 'settings' => $settings, - 'binary' => $this->settings->setType(Settings::TYPE['SYSTEM'])->get('ncd_aria2_binary'), - 'startHook' => $this->appPath . "/hooks/startHook.sh", - 'completeHook' => $this->appPath . "/hooks/completeHook.sh", - ]; - return $config; - } - } diff --git a/lib/Controller/MainController.php b/lib/Controller/MainController.php index d17331e..b0463ed 100644 --- a/lib/Controller/MainController.php +++ b/lib/Controller/MainController.php @@ -11,11 +11,10 @@ use OCA\NCDownloader\Tools\Youtube; use OCP\AppFramework\Controller; use OCP\AppFramework\Http\JSONResponse; use OCP\AppFramework\Http\TemplateResponse; -//use OCP\Files\IRootFolder; use OCP\IL10N; +//use OCP\Files\IRootFolder; use OCP\IRequest; use OC_Util; -use OC\Files\Filesystem; class MainController extends Controller { @@ -57,7 +56,6 @@ class MainController extends Controller // OC_Util::addStyle($this->appName, 'table'); $params = $this->buildParams(); $response = new TemplateResponse($this->appName, 'Index', $params); - return $response; } @@ -125,6 +123,10 @@ class MainController extends Controller */ public function Download() { + $dlDir = $this->aria2->getDownloadDir(); + if (!is_writable($dlDir)) { + return new JSONResponse(['error' => sprintf("%s is not writable", $dlDir)]); + } $url = trim($this->request->getParam('text-input-value')); if (Helper::isMagnet($url)) { if ($this->disable_bt_nonadmin && !($this->isAdmin)) { diff --git a/lib/Controller/YoutubeController.php b/lib/Controller/YoutubeController.php index 549041a..3df4d8c 100644 --- a/lib/Controller/YoutubeController.php +++ b/lib/Controller/YoutubeController.php @@ -76,7 +76,10 @@ class YoutubeController extends Controller */ public function Download() { - $params = array(); + $dlDir = $this->youtube->getDownloadDir(); + if (!is_writable($dlDir)) { + return new JSONResponse(['error' => sprintf("%s is not writable", $dlDir)]); + } $url = trim($this->request->getParam('text-input-value')); $yt = $this->youtube; $yt->audioOnly = (bool) $this->request->getParam('audio-only'); @@ -117,7 +120,7 @@ class YoutubeController extends Controller } $row = $this->dbconn->getByGid($gid); - $data = $this->dbconn->getExtra($value["data"]);; + $data = $this->dbconn->getExtra($row["data"]); if (!isset($data['pid'])) { if ($this->dbconn->deleteByGid($gid)) { $msg = sprintf("%s is deleted from database!", $gid); @@ -193,9 +196,9 @@ class YoutubeController extends Controller private function installYTD() { try { - $filename = Helper::getFileName($yt->installUrl()); - $yt->setDownloadDir($this->dataDir . "/bin"); - $resp = $this->Save($yt->installUrl(), $filename); + $filename = Helper::getFileName($this->installUrl()); + $this->setDownloadDir($this->dataDir . "/bin"); + $resp = $this->Save($this->installUrl(), $filename); return $resp; } catch (\Exception $e) { return ['error' => $e->getMessage()]; diff --git a/lib/Search/Sites/TPB.php b/lib/Search/Sites/TPB.php index d17b1bc..15b265b 100644 --- a/lib/Search/Sites/TPB.php +++ b/lib/Search/Sites/TPB.php @@ -33,7 +33,6 @@ class TPB extends searchBase implements searchInterface if ($this->content) { return $this->content; } - $content; try { $response = $this->client->request('GET', $this->searchUrl); $content = $response->getContent(); diff --git a/lib/Search/Sites/bitSearch.php b/lib/Search/Sites/bitSearch.php index a275f32..8e18002 100644 --- a/lib/Search/Sites/bitSearch.php +++ b/lib/Search/Sites/bitSearch.php @@ -37,7 +37,6 @@ class bitSearch extends searchBase implements searchInterface if ($this->content) { return $this->content; } - $content; try { $response = $this->client->request('GET', $this->searchUrl, ['query' => $this->query]); $content = $response->getContent(); diff --git a/lib/Tools/Helper.php b/lib/Tools/Helper.php index eec2b2f..225d688 100644 --- a/lib/Tools/Helper.php +++ b/lib/Tools/Helper.php @@ -2,9 +2,13 @@ namespace OCA\NCDownloader\Tools; +use Exception; use OCA\NCDownloader\Search\Sites\searchInterface; use OCA\NCDownloader\Tools\aria2Options; +use OCA\NCDownloader\Tools\Settings; +use OCP\IUser; use OC\Files\Filesystem; +use OC_Util; class Helper { @@ -135,6 +139,9 @@ class Helper public static function debug($msg) { + if (is_array($msg)) { + $msg = implode(",", $msg); + } $logger = \OC::$server->getLogger(); $logger->error($msg, ['app' => 'ncdownloader']); } @@ -279,14 +286,13 @@ class Helper ]; return $titles[$type]; } - // the relative home folder of a nextcloud user - public static function getUserFolder($uid = null) + // the relative home folder of a nextcloud user,e.g. /admin/files + public static function getUserFolder($uid = null): string { if (!empty($rootFolder = Filesystem::getRoot())) { return $rootFolder; } else if (isset($uid)) { return "/" . $uid . "/files"; - } return ''; } @@ -374,4 +380,110 @@ class Helper return $sites; } + public static function getMountPoints(): ?array + { + return Filesystem::getMountPoints("/"); + } + + public static function getDataDir(): string + { + return \OC::$server->getSystemConfig()->getValue('datadirectory'); + } + + public static function getLocalFolder(string $path): string + { + //without calling this, filesystem::getLocalFolder doesn't work + OC_Util::setupFS(); + return Filesystem::getLocalFolder($path); + } + + public static function getRealDownloadDir($uid = null): string + { + $uid = $uid ?? self::getUID(); + $settings = new Settings($uid); + $dlDir = $settings->get('ncd_downloader_dir') ?? "/Downloads"; + return self::getLocalFolder($dlDir); + } + public static function getRealTorrentsDir($uid = null): string + { + $uid = $uid ?? self::getUID(); + $settings = new Settings($uid); + $dir = $settings->get('ncd_torrents_dir') ?? "/Torrents"; + return self::getLocalFolder($dir); + } + + public static function getUser(): ?IUser + { + return \OC::$server->getUserSession()->getUser(); + } + + public static function getUID(): string + { + return self::getUser()->getUID(); + } + + public static function getYoutubeConfig($uid = null): array + { + $uid = $uid ?? self::getUID(); + $settings = new Settings($uid); + $config = [ + 'binary' => $settings->setType(Settings::TYPE['SYSTEM'])->get("ncd_yt_binary"), + 'downloadDir' => Helper::getRealDownloadDir(), + 'settings' => $settings->setType(Settings::TYPE['USER'])->getYoutube(), + ]; + return $config; + } + + public static function getAria2Config($uid = null): array + { + $options = []; + $uid = $uid ?? self::getUID(); + $settings = new Settings($uid); + $realDownloadDir = Helper::getRealDownloadDir($uid); + $torrentsDir = Helper::getRealTorrentsDir($uid); + $appPath = self::getAppPath(); + $dataDir = self::getDataDir(); + $aria2_dir = $dataDir . "/aria2"; + $options['seed_time'] = $settings->get("ncd_seed_time"); + $options['seed_ratio'] = $settings->get("ncd_seed_ratio"); + if (is_array($customSettings = $settings->getAria2())) { + $options = array_merge($customSettings, $options); + } + $token = $settings->setType(Settings::TYPE['SYSTEM'])->get('ncd_rpctoken'); + $config = [ + 'dir' => $realDownloadDir, + 'torrents_dir' => $torrentsDir, + 'conf_dir' => $aria2_dir, + 'token' => $token, + 'settings' => $options, + 'binary' => $settings->setType(Settings::TYPE['SYSTEM'])->get('ncd_aria2_binary'), + 'startHook' => $appPath . "/hooks/startHook.sh", + 'completeHook' => $appPath . "/hooks/completeHook.sh", + ]; + return $config; + } + + public static function getAppPath(): string + { + return \OC::$server->getAppManager()->getAppPath('ncdownloader'); + } + public static function folderUpdated(string $dir):bool + { + if (!file_exists($dir)) { + return false; + } + $checkFile = $dir . "/.lastmodified"; + if (!file_exists($checkFile)) { + $time = \filemtime($dir); + file_put_contents($checkFile, $time); + return false; + } + $lastModified = (int) file_get_contents($checkFile); + $time = \filemtime($dir); + if ($time > $lastModified) { + file_put_contents($checkFile, $time); + return true; + } + return false; + } } diff --git a/lib/Tools/Youtube.php b/lib/Tools/Youtube.php index 0573dfd..36b5c0a 100644 --- a/lib/Tools/Youtube.php +++ b/lib/Tools/Youtube.php @@ -116,7 +116,7 @@ class Youtube public function getDownloadDir() { - return $this->getDownloadDir; + return $this->downloadDir; } public function prependOption(string $option) diff --git a/lib/Tools/folderScan.php b/lib/Tools/folderScan.php index b347855..24096d6 100644 --- a/lib/Tools/folderScan.php +++ b/lib/Tools/folderScan.php @@ -10,19 +10,18 @@ class folderScan { private $user; private $path; + private $realDir; public function __construct($path = null, $user = null) { - $this->user = $user ?? \OC::$server->getUserSession()->getUser()->getUID(); + $this->user = $user ?? Helper::getUID(); $this->path = $path ?? $this->getDefaultPath(); - $this->realDir = \OC::$server->getSystemConfig()->getValue('datadirectory') . "/" . $this->path; + $this->realDir = $realDir ?? Helper::getLocalFolder($this->path); } public function getDefaultPath() { $settings = new Settings($this->user); - $rootFolder = Helper::getUserFolder($this->user); - $downloadDir = $settings->get('ncd_downloader_dir') ?? "/Downloads"; - return $rootFolder . "/" . ltrim($downloadDir, '/\\'); + return $settings->get('ncd_downloader_dir') ?? "/Downloads"; } public static function create($path = null, $user = null) { @@ -42,7 +41,7 @@ class folderScan private function update() { - if (!(self::folderUpdated($this->realDir))) { + if (!(Helper::folderUpdated($this->realDir))) { return ['message' => "no change"]; } $this->scan(); @@ -65,25 +64,7 @@ class folderScan return ['status' => $e->getMessage(), 'path' => $this->path]; } - public static function folderUpdated($dir) - { - if (!file_exists($dir)) { - return false; - } - $checkFile = $dir . "/.lastmodified"; - if (!file_exists($checkFile)) { - $time = \filemtime($dir); - file_put_contents($checkFile, $time); - return false; - } - $lastModified = (int) file_get_contents($checkFile); - $time = \filemtime($dir); - if ($time > $lastModified) { - file_put_contents($checkFile, $time); - return true; - } - return false; - } + //update only folder is modified public static function sync($path = null, $user = null) From 49477881a95f15b0e4544e5140e81274a25142b3 Mon Sep 17 00:00:00 2001 From: huangjx Date: Fri, 22 Apr 2022 17:59:44 +0800 Subject: [PATCH 05/22] cleaning up settings class --- lib/Tools/Settings.php | 153 ++++------------------------------------- 1 file changed, 13 insertions(+), 140 deletions(-) diff --git a/lib/Tools/Settings.php b/lib/Tools/Settings.php index 631f499..18e9578 100644 --- a/lib/Tools/Settings.php +++ b/lib/Tools/Settings.php @@ -7,17 +7,19 @@ use OC\AllConfig; class Settings extends AllConfig { //@config OC\AppConfig - private $config; + private $appConfig; //@OC\SystemConfig private $sysConfig; //@OC\AllConfig private $allConfig; - + private $user; + private $appName; //type of settings (system = 1 or app =2) private $type; - public const TYPE = ['SYSTEM' => 0x001, 'USER' => 0x010, 'APP' => 0x100]; + private static $instance = null; + public const TYPE = ['SYSTEM' => 1, 'USER' => 2, 'APP' => 3]; public function __construct($user = null) { $this->appConfig = \OC::$server->getAppConfig(); @@ -29,6 +31,14 @@ class Settings extends AllConfig //$this->connAdapter = \OC::$server->getDatabaseConnection(); //$this->conn = $this->connAdapter->getInner(); } + public static function create($user = null) + { + + if (!self::$instance) { + self::$instance = new static($user); + } + return self::$instance; + } public function setType($type) { $this->type = $type; @@ -104,141 +114,4 @@ class Settings extends AllConfig } return $value; } - -} - -class customSettings -{ - private $name = null; - private $dbType = 0; - private $table = 'ncdownloader_settings'; - private $uid = null; - const PGSQL = 1, MYSQL = 2, SQL = 3; - /* @var OC\DB\ConnectionAdapter */ - private $connAdapter; - /* @var OC\DB\Connection */ - private $conn; - private $type = 2; //personal = 2,admin =1 - - public function __construct() - { - if (\OC::$server->getConfig()->getSystemValue('dbtype') == 'pgsql') { - $this->dbType = PGSQL; - } - $this->connAdapter = \OC::$server->getDatabaseConnection(); - $this->conn = $this->connAdapter->getInner(); - - $this->prefixTable(); - } - - private function prefixTable() - { - $this->table = '*PREFIX*' . $this->table; - return $this->table; - } - - public function set($name, $value) - { - if ($this->have($name)) { - $this->update($name, $value); - } else { - $this->insert($name, $value); - } - } - public function setType($type) - { - $this->type = $type; - } - - public function get($name) - { - - if (isset($this->uid)) { - $sql = sprintf("SELECT value FROM %s WHERE uid = ? AND name = ? LIMIT 1", $this->table); - $query = \OC_DB::prepare($sql); - $result = $query->execute(array($this->uid, $name)); - } else { - $sql = sprintf("SELECT value FROM %s WHERE name = ? LIMIT 1", $this->table); - $query = \OC_DB::prepare($sql); - $result = $query->execute(array($name)); - } - if ($query->rowCount() == 1) { - return $result->fetchOne(); - } - return null; - } - - public function setUID($uid) - { - $this->uid = $uid; - } - - public function setTable($table) - { - $this->table = $table; - } - public function getTable() - { - return $this->table; - } - - public function have($name) - { - if (isset($this->uid)) { - $sql = sprintf("SELECT value FROM %s WHERE uid = ? AND name = ? AND type = ? LIMIT 1", $this->table); - $query = \OC_DB::prepare($sql); - $query->execute(array($name, $this->uid, $this->type)); - } else { - $sql = sprintf("SELECT value FROM %s WHERE name = ? AND type = ? LIMIT 1", $this->table); - $query = \OC_DB::prepare($sql); - $query->execute(array($name, $this->type)); - } - - if ($query->rowCount() == 1) { - return true; - } - return false; - } - - public function getAll() - { - $sql = 'SELECT `name`, `value` FROM `*PREFIX*' . $this->table . '`' - . (!is_null($this->uid) ? ' WHERE `UID` = ?' : ''); - if ($this->DbType == 1) { - $sql = 'SELECT "name", "value" FROM *PREFIX*' . $this->table . '' - . (!is_null($this->uid) ? ' WHERE "uid" = ?' : ''); - } - $query = \OC_DB::prepare($sql); - - if (!is_null($this->uid)) { - return $query->execute(array($this->uid)); - } else { - return $query->execute(); - } - } - - public function update($value) - { - if (isset($this->uid)) { - $sql = sprintf("UPDATE %s SET value = ? WHERE name = ? AND type = ? AND uid = ?", $this->table); - //OCP\DB\IPreparedStatement - $query = \OC_DB::prepare($sql); - $query->execute(array($value, $name, $this->type, $this->uid)); - } else { - $sql = sprintf("UPDATE %s SET value = ? WHERE name = ? AND type = ?", $this->table); - //OCP\DB\IPreparedStatement - $query = \OC_DB::prepare($sql); - $query->execute(array($value, $name, $this->type)); - } - - } - - public function insert($name, $value) - { - $sql = sprintf("INSERT INTO %s (name,value,type,uid) VALUES(?,?,?,?)", $this->table); - //OCP\DB\IPreparedStatement - $query = \OC_DB::prepare($sql); - $query->execute(array($name, $value, $this->type, $this->uid)); - - } } From 5ae16850447db9ae34f68a59002b568e8fbe6dce Mon Sep 17 00:00:00 2001 From: huangjx Date: Fri, 22 Apr 2022 18:29:21 +0800 Subject: [PATCH 06/22] new helper function to retrieve settings --- lib/Controller/Aria2Controller.php | 3 +-- lib/Controller/MainController.php | 5 ++-- lib/Controller/SettingsController.php | 2 +- lib/Controller/YoutubeController.php | 4 +--- lib/Settings/Personal.php | 2 +- lib/Tools/Helper.php | 34 +++++++++++++++++---------- lib/Tools/folderScan.php | 3 +-- 7 files changed, 29 insertions(+), 24 deletions(-) diff --git a/lib/Controller/Aria2Controller.php b/lib/Controller/Aria2Controller.php index 1951872..e5a8675 100644 --- a/lib/Controller/Aria2Controller.php +++ b/lib/Controller/Aria2Controller.php @@ -32,8 +32,7 @@ class Aria2Controller extends Controller $this->l10n = $IL10N; $this->rootFolder = $rootFolder; $this->urlGenerator = \OC::$server->getURLGenerator(); - $this->settings = new Settings($UserId); - $this->downloadDir = $this->settings->get('ncd_downloader_dir') ?? "/Downloads"; + $this->downloadDir = Helper::getDownloadDir(); OC_Util::setupFS(); //$this->config = \OC::$server->getAppConfig(); $this->aria2 = $aria2; diff --git a/lib/Controller/MainController.php b/lib/Controller/MainController.php index b0463ed..dbbb991 100644 --- a/lib/Controller/MainController.php +++ b/lib/Controller/MainController.php @@ -38,10 +38,9 @@ class MainController extends Controller $this->dbconn = new DbHelper(); $this->counters = new Counters($aria2, $this->dbconn, $UserId); $this->youtube = $youtube; - $this->settings = new Settings($this->uid); $this->isAdmin = \OC_User::isAdminUser($this->uid); - $this->hideError = $this->settings->get("ncd_hide_errors", false); - $this->disable_bt_nonadmin = $this->settings->setType($this->settings::TYPE['SYSTEM'])->get("ncd_disable_bt", false); + $this->hideError = Helper::getSettings("ncd_hide_errors", false); + $this->disable_bt_nonadmin = Helper::getSettings("ncd_disable_bt", false, Settings::TYPE["SYSTEM"]); $this->accessDenied = $this->l10n->t("Sorry,only admin users can download files via BT!"); } /** diff --git a/lib/Controller/SettingsController.php b/lib/Controller/SettingsController.php index 91f4a89..06c8af4 100644 --- a/lib/Controller/SettingsController.php +++ b/lib/Controller/SettingsController.php @@ -111,7 +111,7 @@ class SettingsController extends Controller { $saved = json_decode($this->settings->get("custom_youtube_dl_settings"), 1); $params = $this->request->getParams(); - foreach ($data as $key => $value) { + foreach ($params as $key => $value) { unset($saved[$key]); } $resp = $this->settings->save("custom_youtube_dl_settings", json_encode($saved)); diff --git a/lib/Controller/YoutubeController.php b/lib/Controller/YoutubeController.php index 3df4d8c..d87bab3 100644 --- a/lib/Controller/YoutubeController.php +++ b/lib/Controller/YoutubeController.php @@ -5,7 +5,6 @@ use OCA\NCDownloader\Tools\Aria2; use OCA\NCDownloader\Tools\DbHelper; use OCA\NCDownloader\Tools\folderScan; use OCA\NCDownloader\Tools\Helper; -use OCA\NCDownloader\Tools\Settings; use OCA\NCDownloader\Tools\Youtube; use OCP\AppFramework\Controller; use OCP\AppFramework\Http\JSONResponse; @@ -26,8 +25,7 @@ class YoutubeController extends Controller $this->uid = $UserId; $this->urlGenerator = \OC::$server->getURLGenerator(); $this->l10n = $IL10N; - $this->settings = new Settings($UserId); - $this->downloadDir = $this->settings->get('ncd_downloader_dir') ?? "/Downloads"; + $this->downloadDir = Helper::getDownloadDir(); $this->dbconn = new DbHelper(); $this->youtube = $youtube; $this->aria2 = $aria2; diff --git a/lib/Settings/Personal.php b/lib/Settings/Personal.php index c289834..3293be5 100644 --- a/lib/Settings/Personal.php +++ b/lib/Settings/Personal.php @@ -34,7 +34,7 @@ class Personal implements ISettings { */ public function getForm() { $parameters = [ - "ncd_downloader_dir" => $this->settings->get("ncd_downloader_dir"), + "ncd_downloader_dir" => Helper::getDownloadDir(), "ncd_torrents_dir" => $this->settings->get("ncd_torrents_dir"), "ncd_seed_ratio" => $this->settings->get("ncd_seed_ratio"), 'ncd_seed_time_unit' => $this->settings->get("ncd_seed_time_unit"), diff --git a/lib/Tools/Helper.php b/lib/Tools/Helper.php index 225d688..6941290 100644 --- a/lib/Tools/Helper.php +++ b/lib/Tools/Helper.php @@ -399,16 +399,12 @@ class Helper public static function getRealDownloadDir($uid = null): string { - $uid = $uid ?? self::getUID(); - $settings = new Settings($uid); - $dlDir = $settings->get('ncd_downloader_dir') ?? "/Downloads"; + $dlDir = self::getDownloadDir();; return self::getLocalFolder($dlDir); } public static function getRealTorrentsDir($uid = null): string { - $uid = $uid ?? self::getUID(); - $settings = new Settings($uid); - $dir = $settings->get('ncd_torrents_dir') ?? "/Torrents"; + $dir = self::getSettings('ncd_torrents_dir', "/Torrents"); return self::getLocalFolder($dir); } @@ -422,14 +418,24 @@ class Helper return self::getUser()->getUID(); } - public static function getYoutubeConfig($uid = null): array + public static function getSettings($key, $default = null, int $type = Settings::TYPE['USER']) + { + $settings = self::newSettings(); + return $settings->setType($type)->get($key, $default); + } + + public static function newSettings($uid = null) { $uid = $uid ?? self::getUID(); - $settings = new Settings($uid); + return Settings::create($uid); + } + + public static function getYoutubeConfig($uid = null): array + { $config = [ - 'binary' => $settings->setType(Settings::TYPE['SYSTEM'])->get("ncd_yt_binary"), + 'binary' => self::getSettings("ncd_yt_binary", null, Settings::TYPE['SYSTEM']), 'downloadDir' => Helper::getRealDownloadDir(), - 'settings' => $settings->setType(Settings::TYPE['USER'])->getYoutube(), + 'settings' => self::newSettings()->getYoutube(), ]; return $config; } @@ -438,7 +444,7 @@ class Helper { $options = []; $uid = $uid ?? self::getUID(); - $settings = new Settings($uid); + $settings = self::newSettings($uid); $realDownloadDir = Helper::getRealDownloadDir($uid); $torrentsDir = Helper::getRealTorrentsDir($uid); $appPath = self::getAppPath(); @@ -467,7 +473,7 @@ class Helper { return \OC::$server->getAppManager()->getAppPath('ncdownloader'); } - public static function folderUpdated(string $dir):bool + public static function folderUpdated(string $dir): bool { if (!file_exists($dir)) { return false; @@ -486,4 +492,8 @@ class Helper } return false; } + public static function getDownloadDir(): string + { + return self::getSettings('ncd_downloader_dir', "/Downloads"); + } } diff --git a/lib/Tools/folderScan.php b/lib/Tools/folderScan.php index 24096d6..ba3e9d3 100644 --- a/lib/Tools/folderScan.php +++ b/lib/Tools/folderScan.php @@ -20,8 +20,7 @@ class folderScan public function getDefaultPath() { - $settings = new Settings($this->user); - return $settings->get('ncd_downloader_dir') ?? "/Downloads"; + return Helper::getDownloadDir(); } public static function create($path = null, $user = null) { From d0598e71fd4a7d6c1ff3a2c2c69976dcbbf5bdfe Mon Sep 17 00:00:00 2001 From: huangjx Date: Sat, 23 Apr 2022 00:09:16 +0800 Subject: [PATCH 07/22] list youtube-dl downloads in descending order --- lib/Tools/DbHelper.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Tools/DbHelper.php b/lib/Tools/DbHelper.php index eabf635..143f452 100644 --- a/lib/Tools/DbHelper.php +++ b/lib/Tools/DbHelper.php @@ -67,6 +67,7 @@ class DbHelper ->andWhere('type = :type') ->setParameter('uid', $uid) ->setParameter('type', Helper::DOWNLOADTYPE['YOUTUBE-DL']) + ->orderBy('id', 'DESC') ->execute(); return $qb->fetchAll(); } From 384cd08330e2d726da30023a814050bbda824cde Mon Sep 17 00:00:00 2001 From: huangjx Date: Sat, 23 Apr 2022 00:13:49 +0800 Subject: [PATCH 08/22] fixed some duplicate code --- lib/Tools/Aria2.php | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/Tools/Aria2.php b/lib/Tools/Aria2.php index 14dda87..c7b08ae 100644 --- a/lib/Tools/Aria2.php +++ b/lib/Tools/Aria2.php @@ -97,10 +97,14 @@ class Aria2 private function configure() { - if (!is_dir($this->confDir)) { + if ($this->confDir && !is_dir($this->confDir)) { mkdir($this->confDir, 0755, true); } - if (!is_dir($dir = $this->getDownloadDir())) { + $dir = ""; + if ($dir = $this->getDownloadDir() && !is_dir($dir)) { + mkdir($dir, 0755, true); + } + if ($dir = $this->getTorrentsDir() && !is_dir($dir)) { mkdir($dir, 0755, true); } $this->followTorrent(true); @@ -123,9 +127,6 @@ class Aria2 public function setTorrentsDir($dir) { $this->torrentsDir = $dir; - if (!is_dir($dir)) { - mkdir($dir, 0755, true); - } return $this; } public function getTorrentsDir() @@ -136,9 +137,6 @@ class Aria2 { $this->setOption('dir', $dir); $this->downloadDir = $dir; - if (!is_dir($dir)) { - mkdir($dir, 0755, true); - } return $this; } public function getDownloadDir() From 31b7068b75412b65bc48d9bcc542684baecaf97f Mon Sep 17 00:00:00 2001 From: huangjx Date: Sat, 23 Apr 2022 00:16:24 +0800 Subject: [PATCH 09/22] guard against internal errors when user is not logged in --- lib/Controller/MainController.php | 1 + lib/Tools/Helper.php | 14 +++++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/Controller/MainController.php b/lib/Controller/MainController.php index dbbb991..0e049bc 100644 --- a/lib/Controller/MainController.php +++ b/lib/Controller/MainController.php @@ -27,6 +27,7 @@ class MainController extends Controller public function __construct($appName, IRequest $request, $UserId, IL10N $IL10N, Aria2 $aria2, Youtube $youtube) { + parent::__construct($appName, $request); $this->appName = $appName; $this->uid = $UserId; diff --git a/lib/Tools/Helper.php b/lib/Tools/Helper.php index 6941290..dfb7af3 100644 --- a/lib/Tools/Helper.php +++ b/lib/Tools/Helper.php @@ -392,14 +392,16 @@ class Helper public static function getLocalFolder(string $path): string { - //without calling this, filesystem::getLocalFolder doesn't work - OC_Util::setupFS(); - return Filesystem::getLocalFolder($path); + if (self::getUID()) { + OC_Util::setupFS(); + return Filesystem::getLocalFolder($path); + } + return ""; } public static function getRealDownloadDir($uid = null): string { - $dlDir = self::getDownloadDir();; + $dlDir = self::getDownloadDir(); return self::getLocalFolder($dlDir); } public static function getRealTorrentsDir($uid = null): string @@ -415,7 +417,9 @@ class Helper public static function getUID(): string { - return self::getUser()->getUID(); + $user = self::getUser(); + $uid = $user ? $user->getUID() : ""; + return $uid; } public static function getSettings($key, $default = null, int $type = Settings::TYPE['USER']) From faa1b355d4bf01879b3874efa0a1ee6b249a5aeb Mon Sep 17 00:00:00 2001 From: huangjx Date: Sun, 24 Apr 2022 10:55:06 +0800 Subject: [PATCH 10/22] fixed path not found error when scanning; --- lib/Tools/folderScan.php | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/lib/Tools/folderScan.php b/lib/Tools/folderScan.php index ba3e9d3..8159acb 100644 --- a/lib/Tools/folderScan.php +++ b/lib/Tools/folderScan.php @@ -2,7 +2,6 @@ namespace OCA\NCDownloader\Tools; use OCA\NCDownloader\Tools\Helper; -use OCA\NCDownloader\Tools\Settings; use OC\Files\Utils\Scanner; use \OCP\EventDispatcher\IEventDispatcher; @@ -20,7 +19,7 @@ class folderScan public function getDefaultPath() { - return Helper::getDownloadDir(); + return Helper::getUserFolder() . Helper::getDownloadDir(); } public static function create($path = null, $user = null) { @@ -53,18 +52,15 @@ class folderScan $this->scanner = new Scanner($this->user, \OC::$server->getDatabaseConnection(), \OC::$server->query(IEventDispatcher::class), $this->logger); try { $this->scanner->scan($this->path); - return ['status' => 'OK', 'path' => $this->path]; + return ['status' => true, 'path' => $this->path]; } catch (ForbiddenException $e) { $this->logger->warning("Make sure you're running the scan command only as the user the web server runs as"); } catch (\Exception $e) { - $this->logger->warning("Exception during scan: " . $e->getMessage() . $e->getTraceAsString()); } - return ['status' => $e->getMessage(), 'path' => $this->path]; - + return ['status' => false, 'path' => $this->path]; } - //update only folder is modified public static function sync($path = null, $user = null) { From 43a5907a139e2ce1d6152979a231e0bede11ee5c Mon Sep 17 00:00:00 2001 From: huangjx Date: Sun, 24 Apr 2022 11:38:08 +0800 Subject: [PATCH 11/22] fixed novice mistakes --- lib/Tools/Aria2.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/Tools/Aria2.php b/lib/Tools/Aria2.php index c7b08ae..af730d7 100644 --- a/lib/Tools/Aria2.php +++ b/lib/Tools/Aria2.php @@ -101,10 +101,10 @@ class Aria2 mkdir($this->confDir, 0755, true); } $dir = ""; - if ($dir = $this->getDownloadDir() && !is_dir($dir)) { + if (($dir = $this->getDownloadDir()) && !is_dir($dir)) { mkdir($dir, 0755, true); } - if ($dir = $this->getTorrentsDir() && !is_dir($dir)) { + if (($dir = $this->getTorrentsDir()) && !is_dir($dir)) { mkdir($dir, 0755, true); } $this->followTorrent(true); @@ -129,7 +129,7 @@ class Aria2 $this->torrentsDir = $dir; return $this; } - public function getTorrentsDir() + public function getTorrentsDir(): string { return $this->torrentsDir; } @@ -139,7 +139,7 @@ class Aria2 $this->downloadDir = $dir; return $this; } - public function getDownloadDir() + public function getDownloadDir(): string { return $this->downloadDir; } From 5935f6e77cad406064e86b3f232591e0baa59918 Mon Sep 17 00:00:00 2001 From: huangjx Date: Sun, 24 Apr 2022 11:39:31 +0800 Subject: [PATCH 12/22] added polling class --- src/lib/polling.ts | 49 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/lib/polling.ts diff --git a/src/lib/polling.ts b/src/lib/polling.ts new file mode 100644 index 0000000..fb04bc3 --- /dev/null +++ b/src/lib/polling.ts @@ -0,0 +1,49 @@ +type callback = (...args: any[]) => void + +class Polling { + private static instance: Polling; + private timeoutID: number; + private delay: number = 1000; + private enabled: boolean = false; + constructor() { + this.enabled = false; + } + static create(): Polling { + this.instance = this.instance || new Polling(); + return this.instance; + } + + enable() { + this.enabled = true; + return this; + } + disable() { + this.enabled = false; + return this; + } + isEnabled() { + return this.enabled; + } + setDelay(time: number): Polling { + this.delay = time; + return this; + } + + run(callback: callback, ...args: any[]) { + this.clear().enable() + callback(...args); + let timeoutHandler = () => { + if (this.enabled) { + this.run(callback, ...args); + } + } + this.timeoutID = window.setTimeout(timeoutHandler, this.delay); + } + clear() { + if (this.timeoutID) + window.clearTimeout(this.timeoutID); + return this; + } +} + +export default Polling; \ No newline at end of file From 4714817d8768680bea0d957700aa6e9e7f55306c Mon Sep 17 00:00:00 2001 From: huangjx Date: Sun, 24 Apr 2022 11:50:03 +0800 Subject: [PATCH 13/22] renamed folder-scanning method and url --- appinfo/routes.php | 2 +- lib/Controller/Aria2Controller.php | 10 ---------- lib/Controller/MainController.php | 11 +++++++++++ 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/appinfo/routes.php b/appinfo/routes.php index 700fc17..c6a5ec2 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -7,7 +7,7 @@ return [ ['name' => 'main#Download', 'url' => '/new', 'verb' => 'POST'], ['name' => 'Aria2#Action', 'url' => '/aria2/{path}', 'verb' => 'POST'], ['name' => 'Aria2#getStatus', 'url' => '/status/{path}', 'verb' => 'POST'], - ['name' => 'Aria2#Update', 'url' => '/update', 'verb' => 'GET'], + ['name' => 'Main#scanFolder', 'url' => '/scanfolder', 'verb' => 'GET'], ['name' => 'Youtube#Index', 'url' => '/youtube/get', 'verb' => 'POST'], ['name' => 'Youtube#Download', 'url' => '/youtube/new', 'verb' => 'POST'], ['name' => 'Youtube#Delete', 'url' => '/youtube/delete', 'verb' => 'POST'], diff --git a/lib/Controller/Aria2Controller.php b/lib/Controller/Aria2Controller.php index e5a8675..8c03e68 100644 --- a/lib/Controller/Aria2Controller.php +++ b/lib/Controller/Aria2Controller.php @@ -6,7 +6,6 @@ use OCA\NCDownloader\Tools\Counters; use OCA\NCDownloader\Tools\DbHelper; use OCA\NCDownloader\Tools\folderScan; use OCA\NCDownloader\Tools\Helper; -use OCA\NCDownloader\Tools\Settings; use OCP\AppFramework\Controller; use OCP\AppFramework\Http\JSONResponse; use OCP\Files\IRootFolder; @@ -121,15 +120,6 @@ class Aria2Controller extends Controller $data = $this->aria2->start(); return $data; } - /** - * @NoAdminRequired - * @NoCSRFRequired - */ - public function Update() - { - $resp = folderScan::create()->scan(); - return new JSONResponse($resp); - } private function createActionItem($name, $path) { diff --git a/lib/Controller/MainController.php b/lib/Controller/MainController.php index 0e049bc..066926c 100644 --- a/lib/Controller/MainController.php +++ b/lib/Controller/MainController.php @@ -15,6 +15,7 @@ use OCP\IL10N; //use OCP\Files\IRootFolder; use OCP\IRequest; use OC_Util; +use OCA\NCDownloader\Tools\folderScan; class MainController extends Controller { @@ -195,4 +196,14 @@ class MainController extends Controller return new JSONResponse($resp); } + /** + * @NoAdminRequired + * @NoCSRFRequired + */ + public function scanFolder() + { + $resp = folderScan::create()->scan(); + return new JSONResponse($resp); + } + } From c796cade4e55e4730cbe31833b3a258fb32a3a82 Mon Sep 17 00:00:00 2001 From: huangjx Date: Sun, 24 Apr 2022 12:03:13 +0800 Subject: [PATCH 14/22] cleaning up polling code --- src/App.vue | 2 +- src/actions/updatePage.js | 33 +++++++++----------- src/utils/helper.js | 66 +++++++++++++++++++++++---------------- 3 files changed, 54 insertions(+), 47 deletions(-) diff --git a/src/App.vue b/src/App.vue index 098d5e7..85ed990 100644 --- a/src/App.vue +++ b/src/App.vue @@ -94,7 +94,7 @@ export default { vm.$data.loading = 0; return; } - helper.enabledPolling = 0; + helper.disablePolling(); contentTable.getInstance().loading(); let url = formWrapper.getAttribute("action"); diff --git a/src/actions/updatePage.js b/src/actions/updatePage.js index 4aea671..97fad37 100644 --- a/src/actions/updatePage.js +++ b/src/actions/updatePage.js @@ -1,7 +1,5 @@ import helper from '../utils/helper' import eventHandler from '../lib/eventHandler'; -import Http from '../lib/http' - const basePath = "/apps/ncdownloader/status/"; const tableContainer = ".table"; export default { @@ -18,33 +16,30 @@ export default { } let name = type + "-downloads"; //avoid repeated click - if (currentType === name && helper.enabledPolling) { + if (currentType === name && helper.isPolling()) { return; } - helper.enabledPolling = 1; - //$(tableContainer).removeClass().addClass("table " + name); container.setAttribute("type", name); container.className = "table " + name; let delay = 15000; if (['active', 'youtube-dl'].includes(type)) { delay = 1500; } - helper.loop(helper.refresh, delay, ...[path]) + helper.polling(delay, path); }; - eventHandler.add("click",".waiting-downloads a",event => clickHandler(event, 'waiting')); - eventHandler.add("click",".complete-downloads a",event => clickHandler(event, 'complete')); - eventHandler.add("click",".active-downloads a",event => clickHandler(event, 'active')); - eventHandler.add("click",".fail-downloads a",event => clickHandler(event, 'fail')); - eventHandler.add("click",".youtube-dl-downloads a",event => clickHandler(event, 'youtube-dl')); - eventHandler.add("click", "#ncdownloader-table-wrapper",".download-file-folder", function (event) { + eventHandler.add("click", ".waiting-downloads a", event => clickHandler(event, 'waiting')); + eventHandler.add("click", ".complete-downloads a", event => clickHandler(event, 'complete')); + eventHandler.add("click", ".active-downloads a", event => clickHandler(event, 'active')); + eventHandler.add("click", ".fail-downloads a", event => clickHandler(event, 'fail')); + eventHandler.add("click", ".youtube-dl-downloads a", event => clickHandler(event, 'youtube-dl')); + eventHandler.add("click", "#ncdownloader-table-wrapper", ".download-file-folder", function (event) { event.stopPropagation(); - const path = "/apps/ncdownloader/update"; - let url = helper.generateUrl(path); - Http.getInstance(url).setMethod('GET').send(); + event.preventDefault(); + let ele = event.target; + let url = ele.getAttribute("href"); + helper.scanFolder().then(() => { + helper.redirect(url); + }); }); - helper.polling(function (url) { - url = helper.generateUrl(url); - Http.getInstance(url).setMethod('GET').send(); - }, 60000, "/apps/ncdownloader/update"); } } \ No newline at end of file diff --git a/src/utils/helper.js b/src/utils/helper.js index aba3181..9ba6948 100644 --- a/src/utils/helper.js +++ b/src/utils/helper.js @@ -6,6 +6,7 @@ import "toastify-js/src/toastify.css" import { translate as t, translatePlural as n } from '@nextcloud/l10n' import contentTable from '../lib/contentTable'; import Http from '../lib/http' +import Polling from "../lib/polling"; const helper = { vue: {}, @@ -16,12 +17,42 @@ const helper = { return helper.vue[name]; }, generateUrl: generateUrl, - loop(callback, delay, ...args) { - callback(...args); - clearTimeout(helper.timeoutID); - this.polling(callback, delay, ...args); + isPolling() { + return Polling.create().isEnabled(); + }, + enabePolling() { + Polling.create().enable(); + }, + disablePolling() { + Polling.create().disable().clear(); + }, + polling(delay = 1000, path) { + Polling.create().setDelay(delay).run(helper.refresh, path); + }, + scanFolder(path = "/apps/ncdownloader/scanfolder") { + let url = helper.generateUrl(path); + return new Promise((resolve) => { + Http.getInstance(url).setMethod('GET').setHandler(function (data) { + resolve(data.status); + }).send(); + }); + }, + pollingFolder(delay = 1000) { + Polling.create().setDelay(delay).run(helper.scanFolder); + }, + refresh(path) { + path = path || "/apps/ncdownloader/status/active"; + let url = helper.generateUrl(path); + Http.getInstance(url).setHandler(function (data) { + if (data && data.row) { + contentTable.getInstance(data.title, data.row).create(); + } else { + contentTable.getInstance().noData(); + } + if (data.counter) + helper.updateCounter(data.counter); + }).send(); }, - enabledPolling: 0, trim(string, char) { return string.split(char).filter(Boolean).join(char) }, @@ -32,15 +63,6 @@ const helper = { ucfirst(string) { return string.charAt(0).toUpperCase() + string.slice(1) }, - polling(callback, delay, ...args) { - self = this; - helper.timeoutID = setTimeout(function () { - if (self.enabledPolling) { - callback(...args); - self.polling(callback, delay, ...args); - } - }, delay); - }, isURL(url) { let regex = '^((https?|ftp)://)([a-z0-9-]+\.)?(?:[-a-zA-Z0-9()@:%_\+.~#?&/=]+)$'; const pattern = new RegExp(regex, 'i'); @@ -115,19 +137,6 @@ const helper = { counter.innerHTML = '
' + data[key] + '
'; } }, - refresh(path) { - path = path || "/apps/ncdownloader/status/active"; - let url = helper.generateUrl(path); - Http.getInstance(url).setHandler(function (data) { - if (data && data.row) { - contentTable.getInstance(data.title, data.row).create(); - } else { - contentTable.getInstance().noData(); - } - if (data.counter) - helper.updateCounter(data.counter); - }).send(); - }, html2DOM: function (htmlString) { const parser = new window.DOMParser(); let doc = parser.parseFromString(htmlString, "text/html") @@ -253,6 +262,9 @@ const helper = { resetSearch: function (vm) { vm.$data.loading = 0; contentTable.getInstance([], []).clear(); + }, + redirect(url) { + window.location.href = url; } } From 37a3bfdfa12ef2858fe7a553372b253e8558880a Mon Sep 17 00:00:00 2001 From: Pavel Artsishevsky Date: Thu, 21 Apr 2022 18:55:56 +0300 Subject: [PATCH 15/22] fix excluding files while packaging build artifacts --- Makefile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index efe5ae6..ae9e224 100644 --- a/Makefile +++ b/Makefile @@ -113,20 +113,21 @@ dist: source: rm -rf $(source_build_directory) mkdir -p $(source_build_directory) - tar cvzf $(source_package_name).tar.gz ../$(app_name) \ + tar cvzf $(source_package_name).tar.gz \ --exclude-vcs \ --exclude="../$(app_name)/build" \ --exclude="../$(app_name)/js/node_modules" \ --exclude="../$(app_name)/node_modules" \ --exclude="../$(app_name)/*.log" \ --exclude="../$(app_name)/js/*.log" \ + ../$(app_name) # Builds the source package for the app store, ignores php and js tests .PHONY: appstore appstore: rm -rf $(appstore_build_directory) mkdir -p $(appstore_build_directory) - tar cvzf $(appstore_package_name).tar.gz ../$(app_name) \ + tar cvzf $(appstore_package_name).tar.gz \ --exclude-vcs \ --exclude="../$(app_name)/build" \ --exclude="../$(app_name)/tests" \ @@ -142,12 +143,14 @@ appstore: --exclude="../$(app_name)/js/bower.json" \ --exclude="../$(app_name)/js/karma.*" \ --exclude="../$(app_name)/js/protractor.*" \ + --exclude="../$(app_name)/node_modules" \ --exclude="../$(app_name)/package.json" \ --exclude="../$(app_name)/bower.json" \ --exclude="../$(app_name)/karma.*" \ --exclude="../$(app_name)/protractor\.*" \ --exclude="../$(app_name)/.*" \ --exclude="../$(app_name)/js/.*" \ + ../$(app_name) .PHONY: test test: composer From 1cf4f4a00bd4503bb1607f101f9d9050c326c66e Mon Sep 17 00:00:00 2001 From: Pavel Artsishevsky Date: Fri, 22 Apr 2022 21:59:22 +0300 Subject: [PATCH 16/22] merged errors handling from polter-rnd --- lib/Tools/folderScan.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/Tools/folderScan.php b/lib/Tools/folderScan.php index 8159acb..98c2d4a 100644 --- a/lib/Tools/folderScan.php +++ b/lib/Tools/folderScan.php @@ -53,8 +53,10 @@ class folderScan try { $this->scanner->scan($this->path); return ['status' => true, 'path' => $this->path]; - } catch (ForbiddenException $e) { + } catch (\OCP\Files\ForbiddenException $e) { $this->logger->warning("Make sure you're running the scan command only as the user the web server runs as"); + } catch (\OCP\Files\NotFoundException $e) { + $this->logger->warning("Path for the scan command not found: " . $e->getMessage()); } catch (\Exception $e) { $this->logger->warning("Exception during scan: " . $e->getMessage() . $e->getTraceAsString()); } From 0a9bcb606d013523418717de24c9dab5702ded9b Mon Sep 17 00:00:00 2001 From: huangjx Date: Sun, 24 Apr 2022 14:00:46 +0800 Subject: [PATCH 17/22] changed default polling interval to 1.5s;added wrapper function for polling youtube downloads --- src/actions/updatePage.js | 15 ++++++++------- src/lib/polling.ts | 4 ++-- src/utils/helper.js | 8 +++++--- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/actions/updatePage.js b/src/actions/updatePage.js index 97fad37..21d0c30 100644 --- a/src/actions/updatePage.js +++ b/src/actions/updatePage.js @@ -11,9 +11,6 @@ export default { let container = document.querySelector(tableContainer); let currentType = container.getAttribute("type"); let path = basePath + type; - if (type === "youtube-dl") { - path = "/apps/ncdownloader/youtube/get"; - } let name = type + "-downloads"; //avoid repeated click if (currentType === name && helper.isPolling()) { @@ -21,11 +18,15 @@ export default { } container.setAttribute("type", name); container.className = "table " + name; - let delay = 15000; - if (['active', 'youtube-dl'].includes(type)) { - delay = 1500; + let delay; + if (!['active', 'youtube-dl'].includes(type)) { + delay = 15000; + } + if (type === "youtube-dl") { + helper.pollingYoutube(); + } else { + helper.polling(delay, path); } - helper.polling(delay, path); }; eventHandler.add("click", ".waiting-downloads a", event => clickHandler(event, 'waiting')); eventHandler.add("click", ".complete-downloads a", event => clickHandler(event, 'complete')); diff --git a/src/lib/polling.ts b/src/lib/polling.ts index fb04bc3..0b4dedf 100644 --- a/src/lib/polling.ts +++ b/src/lib/polling.ts @@ -3,7 +3,7 @@ type callback = (...args: any[]) => void class Polling { private static instance: Polling; private timeoutID: number; - private delay: number = 1000; + private delay: number = 1500; private enabled: boolean = false; constructor() { this.enabled = false; @@ -24,7 +24,7 @@ class Polling { isEnabled() { return this.enabled; } - setDelay(time: number): Polling { + setDelay(time: number = 1500): Polling { this.delay = time; return this; } diff --git a/src/utils/helper.js b/src/utils/helper.js index 9ba6948..5361490 100644 --- a/src/utils/helper.js +++ b/src/utils/helper.js @@ -7,7 +7,6 @@ import { translate as t, translatePlural as n } from '@nextcloud/l10n' import contentTable from '../lib/contentTable'; import Http from '../lib/http' import Polling from "../lib/polling"; - const helper = { vue: {}, addVue(name, object) { @@ -26,7 +25,7 @@ const helper = { disablePolling() { Polling.create().disable().clear(); }, - polling(delay = 1000, path) { + polling(delay = 1500, path) { Polling.create().setDelay(delay).run(helper.refresh, path); }, scanFolder(path = "/apps/ncdownloader/scanfolder") { @@ -37,9 +36,12 @@ const helper = { }).send(); }); }, - pollingFolder(delay = 1000) { + pollingFolder(delay = 1500) { Polling.create().setDelay(delay).run(helper.scanFolder); }, + pollingYoutube(delay = 1500) { + Polling.create().setDelay(delay).run(helper.refresh, "/apps/ncdownloader/youtube/get"); + }, refresh(path) { path = path || "/apps/ncdownloader/status/active"; let url = helper.generateUrl(path); From 71a015e10e67028ef1982d14230dc7dc8fa91af5 Mon Sep 17 00:00:00 2001 From: huangjx Date: Sun, 24 Apr 2022 15:28:34 +0800 Subject: [PATCH 18/22] improved eventHandler.ts --- src/lib/eventHandler.ts | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/lib/eventHandler.ts b/src/lib/eventHandler.ts index bebabcd..81ad419 100644 --- a/src/lib/eventHandler.ts +++ b/src/lib/eventHandler.ts @@ -14,23 +14,26 @@ const eventHandler = { }); return; } - let el = document.querySelector(target); - if (!el) { + let items = document.querySelectorAll(target); + if (!items) { return; } - el.addEventListener(eventType, function (e) { - let element = e.target as HTMLElement; - if (element === this && selector === target) { - callback.call(element, e); - return; - } - for (; element && element != this; element = element.parentElement) { - if (typeof selector === "string" && element.matches(selector)) { + items.forEach(el => { + el.addEventListener(eventType, function (e) { + let element = e.target as HTMLElement; + if (element === this && selector === target) { callback.call(element, e); - break; + return; } - } - }); + for (; element && element != this; element = element.parentElement) { + if (typeof selector === "string" && element.matches(selector)) { + callback.call(element, e); + break; + } + } + }); + }) + }, remove: function (element: target, eventType: string, callback: callback) { From 507b43ca3be29ba9d1ecd8fe9aff2c0f042c55e7 Mon Sep 17 00:00:00 2001 From: huangjx Date: Sun, 24 Apr 2022 15:38:09 +0800 Subject: [PATCH 19/22] removed duplicate code related to download queue --- src/actions/updatePage.js | 26 ++++++-------- src/utils/helper.js | 9 +++++ templates/Navigation.php | 71 ++++++++------------------------------- 3 files changed, 33 insertions(+), 73 deletions(-) diff --git a/src/actions/updatePage.js b/src/actions/updatePage.js index 21d0c30..eda88fc 100644 --- a/src/actions/updatePage.js +++ b/src/actions/updatePage.js @@ -1,38 +1,32 @@ import helper from '../utils/helper' import eventHandler from '../lib/eventHandler'; -const basePath = "/apps/ncdownloader/status/"; -const tableContainer = ".table"; export default { run: function () { - const clickHandler = (event, type) => { + const clickHandler = (event) => { + event.stopPropagation(); event.preventDefault(); + let element = event.target; helper.hideDownload(); - let container = document.querySelector(tableContainer); - let currentType = container.getAttribute("type"); - let path = basePath + type; - let name = type + "-downloads"; + let currentType = helper.getContentTableType(); + let path = element.getAttribute("path"); + let name = element.getAttribute("id"); //avoid repeated click if (currentType === name && helper.isPolling()) { return; } - container.setAttribute("type", name); - container.className = "table " + name; + helper.setContentTableType(name); let delay; - if (!['active', 'youtube-dl'].includes(type)) { + if (!['active-downloads', 'youtube-dl-downloads'].includes(name)) { delay = 15000; } - if (type === "youtube-dl") { + if (name === "youtube-dl-downloads") { helper.pollingYoutube(); } else { helper.polling(delay, path); } }; - eventHandler.add("click", ".waiting-downloads a", event => clickHandler(event, 'waiting')); - eventHandler.add("click", ".complete-downloads a", event => clickHandler(event, 'complete')); - eventHandler.add("click", ".active-downloads a", event => clickHandler(event, 'active')); - eventHandler.add("click", ".fail-downloads a", event => clickHandler(event, 'fail')); - eventHandler.add("click", ".youtube-dl-downloads a", event => clickHandler(event, 'youtube-dl')); + eventHandler.add("click", ".download-queue a", event => clickHandler(event)); eventHandler.add("click", "#ncdownloader-table-wrapper", ".download-file-folder", function (event) { event.stopPropagation(); event.preventDefault(); diff --git a/src/utils/helper.js b/src/utils/helper.js index 5361490..f343a21 100644 --- a/src/utils/helper.js +++ b/src/utils/helper.js @@ -267,6 +267,15 @@ const helper = { }, redirect(url) { window.location.href = url; + }, + getContentTableType() { + let container = document.getElementById("ncdownloader-table-wrapper"); + return container.getAttribute("type"); + }, + setContentTableType(name) { + let container = document.getElementById("ncdownloader-table-wrapper"); + container.setAttribute("type", name); + container.className = "table " + name; } } diff --git a/templates/Navigation.php b/templates/Navigation.php index 643b931..e23ef4d 100644 --- a/templates/Navigation.php +++ b/templates/Navigation.php @@ -1,5 +1,12 @@ "active", "label" => "Active Downloads", "id" => "active-downloads", "path" => "/apps/ncdownloader/status/active"], + ["name" => "waiting", "label" => "Waiting Downloads", "id" => "waiting-downloads", "path" => "/apps/ncdownloader/status/waiting"], + ["name" => "fail", "label" => "Failed Downloads", "id" => "failed-downloads", "path" => "/apps/ncdownloader/status/fail"], + ["name" => "complete", "label" => "Complete Downloads", "id" => "complete-downloads", "path" => "/apps/ncdownloader/status/complete"], + ["name" => "youtube-dl", "label" => "Youtube-dl Downloads", "id" => "youtube-dl-downloads", "path" => "/apps/ncdownloader/youtube/get"], +]; ?>
@@ -33,71 +40,21 @@ extract($_);
From 58a0be23198af55ddceadb221e9e90e27559c575 Mon Sep 17 00:00:00 2001 From: huangjx Date: Sun, 24 Apr 2022 15:50:09 +0800 Subject: [PATCH 20/22] start polling once downloads initiated --- src/App.vue | 13 +++++++++---- src/actions/updatePage.js | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/App.vue b/src/App.vue index 85ed990..c6a535d 100644 --- a/src/App.vue +++ b/src/App.vue @@ -58,6 +58,10 @@ export default { let formData = helper.getData(formWrapper); let inputValue = formData["text-input-value"].trim(); let message; + if (!helper.isURL(inputValue) && !helper.isMagnetURI(inputValue)) { + helper.error(t("ncdownloader", inputValue + " is Invalid")); + return; + } if (formData.type === "youtube-dl") { formData["audio-only"] = ""; formData["extension"] = ""; @@ -68,10 +72,11 @@ export default { } } message = helper.t("Download task started!"); - } - if (!helper.isURL(inputValue) && !helper.isMagnetURI(inputValue)) { - helper.error(t("ncdownloader", inputValue + " is Invalid")); - return; + helper.pollingYoutube(); + helper.setContentTableType("youtube-dl-downloads"); + } else { + helper.polling(); + helper.setContentTableType("active-downloads"); } if (message) { helper.info(message); diff --git a/src/actions/updatePage.js b/src/actions/updatePage.js index eda88fc..3b584ec 100644 --- a/src/actions/updatePage.js +++ b/src/actions/updatePage.js @@ -7,7 +7,7 @@ export default { event.stopPropagation(); event.preventDefault(); let element = event.target; - helper.hideDownload(); + //helper.hideDownload(); let currentType = helper.getContentTableType(); let path = element.getAttribute("path"); let name = element.getAttribute("id"); From 1e8e4500f69715efa79e8f23acb8b909bd5c58ef Mon Sep 17 00:00:00 2001 From: huangjx Date: Sun, 24 Apr 2022 15:56:56 +0800 Subject: [PATCH 21/22] fixed no index error --- lib/Controller/Aria2Controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Controller/Aria2Controller.php b/lib/Controller/Aria2Controller.php index 8c03e68..2fa121b 100644 --- a/lib/Controller/Aria2Controller.php +++ b/lib/Controller/Aria2Controller.php @@ -224,7 +224,7 @@ class Aria2Controller extends Controller $tmp = []; $actions = []; $filename = sprintf('%s', $folderLink, $filename); - $fileInfo = sprintf(' %s | %s', $extra ? $extra['link'] : 'nolink', $total, date("Y-m-d H:i:s", $timestamp)); + $fileInfo = sprintf(' %s | %s', $extra["link"] ?? 'nolink', $total, date("Y-m-d H:i:s", $timestamp)); $tmp['filename'] = array($filename, $fileInfo); if ($this->aria2->methodName === "tellStopped") { From 5ef0adc7376ddc9286931d9bb5ddf851f1ff5976 Mon Sep 17 00:00:00 2001 From: huangjx Date: Sun, 24 Apr 2022 16:01:51 +0800 Subject: [PATCH 22/22] bumped version to 0.9.16 --- appinfo/info.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appinfo/info.xml b/appinfo/info.xml index b592c1f..20a6df6 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -8,7 +8,7 @@ Search for torrents within the app from mutiple BT sites; Control Aria2 and manage download tasks from the web; download videos from 700+ video sites(youtube,youku,vimo,dailymotion,twitter,facebook and the likes - 0.9.1 + 0.9.16 agpl jiaxinhuang NCDownloader