first commit
This commit is contained in:
96
lib/Command/Aria2Command.php
Normal file
96
lib/Command/Aria2Command.php
Normal file
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
||||
*
|
||||
* @author Joas Schilling <coding@schilljs.com>
|
||||
* @author Robin Appelman <robin@icewind.nl>
|
||||
*
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
namespace OCA\NcDownloader\Command;
|
||||
|
||||
use OCA\NcDownloader\Tools\Aria2;
|
||||
use OCA\NcDownloader\Tools\DBConn;
|
||||
use OCA\NcDownloader\Tools\File;
|
||||
use OCA\NcDownloader\Tools\Helper;
|
||||
use OC\Core\Command\Base;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class Aria2Command extends base
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->conn = new DBConn();
|
||||
$this->aria2 = new Aria2();
|
||||
parent::__construct();
|
||||
}
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('aria2')
|
||||
->setDescription('Aria2 hooks')
|
||||
->addArgument(
|
||||
'action',
|
||||
InputArgument::OPTIONAL,
|
||||
'Aria2 hook names: start,complete,error'
|
||||
)->addOption(
|
||||
'gid',
|
||||
'g',
|
||||
InputOption::VALUE_REQUIRED,
|
||||
'Aria2 gid'
|
||||
)->addOption(
|
||||
'path',
|
||||
'p',
|
||||
InputOption::VALUE_OPTIONAL,
|
||||
'Downloaded file path',
|
||||
)->addOption(
|
||||
'number',
|
||||
'N',
|
||||
InputOption::VALUE_OPTIONAL,
|
||||
'Number of Files',
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
|
||||
if (!$action = $input->getArgument('action')) {
|
||||
$action = 'start';
|
||||
}
|
||||
$gid = $input->getOption('gid');
|
||||
$path = $input->getOption('path');
|
||||
$numFile = $input->getOption('number');
|
||||
if (!$gid) {
|
||||
return 1;
|
||||
}
|
||||
$parent_gid = $this->aria2->getFollowingGid($gid); // $this->conn->getAll();
|
||||
if ($parent_gid) {
|
||||
$tablename = $this->conn->queryBuilder->getTableName("ncdownloader_info");
|
||||
$sql = sprintf("UPDATE %s set followedby = ? WHERE gid = ?", $tablename);
|
||||
// $data = serialize(['followedby' => "82140bd962946ae0"]);
|
||||
$this->conn->execute($sql, [$gid, $parent_gid]);
|
||||
}
|
||||
|
||||
$result = $this->conn->getByGid($parent_gid);
|
||||
//$data = unserialize($result['data']);
|
||||
$output->writeln(print_r($result, true));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
220
lib/Controller/Aria2Controller.php
Normal file
220
lib/Controller/Aria2Controller.php
Normal file
@@ -0,0 +1,220 @@
|
||||
<?php
|
||||
namespace OCA\NcDownloader\Controller;
|
||||
|
||||
use OCA\NcDownloader\Tools\Aria2;
|
||||
use OCA\NcDownloader\Tools\DBConn;
|
||||
use OCA\NcDownloader\Tools\File;
|
||||
use OCA\NcDownloader\Tools\Helper;
|
||||
use OCA\NcDownloader\Tools\Settings;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http\JSONResponse;
|
||||
use OCP\Files\IRootFolder;
|
||||
use OCP\IL10N;
|
||||
use OCP\IRequest;
|
||||
use OC_Util;
|
||||
use \OC\Files\Filesystem;
|
||||
|
||||
class Aria2Controller extends Controller
|
||||
{
|
||||
private $userId;
|
||||
private $settings = null;
|
||||
//@config OC\AppConfig
|
||||
private $config;
|
||||
private $aria2Opts;
|
||||
private $l10n;
|
||||
|
||||
public function __construct($appName, IRequest $request, $UserId, IL10N $IL10N, IRootFolder $rootFolder, Aria2 $aria2)
|
||||
{
|
||||
parent::__construct($appName, $request);
|
||||
$this->appName = $appName;
|
||||
$this->uid = $UserId;
|
||||
$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";
|
||||
OC_Util::setupFS();
|
||||
//$this->config = \OC::$server->getAppConfig();
|
||||
|
||||
$this->aria2 = $aria2;
|
||||
|
||||
$this->aria2->init();
|
||||
$this->dbconn = new DBConn();
|
||||
}
|
||||
|
||||
public function Action($path)
|
||||
{
|
||||
$path = strtolower(trim($path));
|
||||
|
||||
if (!in_array($path, ['start', 'check']) && !($gid = $this->request->getParam('gid'))) {
|
||||
return new JSONResponse(['error' => "no gid value is received!"]);
|
||||
}
|
||||
switch (strtolower($path)) {
|
||||
case "check":
|
||||
$resp = $this->aria2->isRunning();
|
||||
break;
|
||||
case "start":
|
||||
$resp = $this->Start();
|
||||
break;
|
||||
case "pause":
|
||||
$resp = $this->aria2->pause($gid);
|
||||
break;
|
||||
case "remove":
|
||||
$resp = $this->aria2->remove($gid);
|
||||
break;
|
||||
case "unpause":
|
||||
$resp = $this->aria2->unpause($gid);
|
||||
break;
|
||||
case "get":
|
||||
$resp = $this->aria2->tellStatus($gid);
|
||||
break;
|
||||
case 'purge':
|
||||
$resp = $this->aria2->removeDownloadResult($gid);
|
||||
}
|
||||
return new JSONResponse($resp);
|
||||
}
|
||||
private function Start()
|
||||
{
|
||||
if ($this->aria2->isRunning()) {
|
||||
$data = ['status' => (bool) $this->aria2->stop()];
|
||||
return $data;
|
||||
}
|
||||
$data = $this->aria2->start();
|
||||
return $data;
|
||||
}
|
||||
public function Update()
|
||||
{
|
||||
File::syncFolder($this->downloadDir);
|
||||
return new JSONResponse([]);
|
||||
}
|
||||
|
||||
private function createActionItem($name, $path)
|
||||
{
|
||||
return array(
|
||||
'name' => $name,
|
||||
'path' => $this->urlGenerator->linkToRoute('ncdownloader.Aria2.Action', ['path' => $path]),
|
||||
);
|
||||
}
|
||||
public function getStatus($path)
|
||||
{
|
||||
//$path = $this->request->getRequestUri();
|
||||
$counter = $this->aria2->getCounters();
|
||||
switch (strtolower($path)) {
|
||||
case "active":
|
||||
$resp = $this->aria2->tellActive();
|
||||
break;
|
||||
case "waiting":
|
||||
$resp = $this->aria2->tellWaiting([0, 999]);
|
||||
break;
|
||||
case "complete":
|
||||
$resp = $this->aria2->tellStopped([0, 999]);
|
||||
break;
|
||||
case "fail":
|
||||
$resp = $this->aria2->tellFail([0, 999]);
|
||||
break;
|
||||
default:
|
||||
$resp = $this->aria2->tellActive();
|
||||
}
|
||||
if (isset($resp['error'])) {
|
||||
return new JSONResponse($resp);
|
||||
}
|
||||
$data = $this->prepareResp($resp);
|
||||
$data['counter'] = $counter;
|
||||
return new JSONResponse($data);
|
||||
}
|
||||
private function prepareResp($resp)
|
||||
{
|
||||
|
||||
$data = [];
|
||||
if (empty($resp)) {
|
||||
return $data;
|
||||
}
|
||||
$data['row'] = [];
|
||||
|
||||
foreach ($resp as $value) {
|
||||
|
||||
$gid = $value['following'] ?? $value['gid'];
|
||||
if ($row = $this->dbconn->getByGid($gid)) {
|
||||
$filename = $row['filename'];
|
||||
$timestamp = $row['timestamp'];
|
||||
} else if (isset($value['files'][0]['path'])) {
|
||||
$parts = explode("/", ($path = $value['files'][0]['path']));
|
||||
if (count($parts) > 1) {
|
||||
$filename = basename(dirname($path));
|
||||
} else {
|
||||
$filename = basename($path);
|
||||
}
|
||||
} else {
|
||||
$filename = "Unknown";
|
||||
}
|
||||
if (!isset($value['completedLength'])) {
|
||||
continue;
|
||||
}
|
||||
//internal nextcloud absolute path for nodeExists
|
||||
//$file = $this->userFolder . $this->downloadDir . "/" . $filename;
|
||||
// $dir = $this->rootFolder->nodeExists($file) ? $this->downloadDir . "/" . $filename : $this->downloadDir;
|
||||
$file = $this->downloadDir . "/" . $filename;
|
||||
$params = ['dir' => $this->downloadDir];
|
||||
$fileInfo = Filesystem::getFileInfo($file);
|
||||
if ($fileInfo) {
|
||||
$fileType = $fileInfo->getType();
|
||||
if ($fileType === "dir") {
|
||||
$params = ['dir' => $file];
|
||||
}
|
||||
}
|
||||
$folderLink = $this->urlGenerator->linkToRoute('files.view.index', $params);
|
||||
//$peers = ($this->getPeers($info['gid']));
|
||||
$completed = Helper::formatBytes($value['completedLength']);
|
||||
$percentage = $value['completedLength'] ? 100 * ($value['completedLength'] / $value['totalLength']) : 0;
|
||||
$completed = Helper::formatBytes($value['completedLength']);
|
||||
|
||||
$total = Helper::formatBytes($value['totalLength']);
|
||||
|
||||
$remaining = (int) $value['totalLength'] - (int) $value['completedLength'];
|
||||
$remaining = ($value['downloadSpeed'] > 0) ? ($remaining / $value['downloadSpeed']) : 0;
|
||||
$left = Helper::formatInterval($remaining);
|
||||
|
||||
$numSeeders = $value['numSeeders'] ?? 0;
|
||||
$extraInfo = "Seeders: $numSeeders";
|
||||
// $numPeers = isset($peers['result']) ? count($peers['result']) : 0;
|
||||
$value['progress'] = array(sprintf("%s(%.2f%%)", $completed, $percentage), $extraInfo);
|
||||
$timestamp = $timestamp ?? 0;
|
||||
//$prefix = $value['files'][0]['path'];
|
||||
$filename = sprintf('<a class="download-file-folder" href="%s">%s</a>', $folderLink, $filename);
|
||||
$fileInfo = sprintf("%s | %s", $total, date("Y-m-d H:i:s", $timestamp));
|
||||
|
||||
$tmp = [];
|
||||
$actions = [];
|
||||
if ($this->aria2->methodName === "tellStopped") {
|
||||
$actions[] = $this->createActionItem('purge', 'purge');
|
||||
} else {
|
||||
$actions[] = $this->createActionItem('delete', 'remove');
|
||||
}
|
||||
if ($this->aria2->methodName === "tellWaiting") {
|
||||
$actions[] = $this->createActionItem('unpause', 'unpause');
|
||||
}
|
||||
$tmp['filename'] = array($filename, $fileInfo);
|
||||
if ($this->aria2->methodName === "tellActive") {
|
||||
$speed = [Helper::formatBytes($value['downloadSpeed']), $left . " left"];
|
||||
$tmp['speed'] = $speed;
|
||||
$tmp['progress'] = $value['progress'];
|
||||
$actions[] = $this->createActionItem('pause', 'pause');
|
||||
}
|
||||
if (strtolower($value['status']) === 'error') {
|
||||
$tmp['status'] = $value['errorMessage'];
|
||||
} else if ($this->aria2->methodName !== "tellActive") {
|
||||
$tmp['status'] = $value['status'];
|
||||
}
|
||||
$tmp['data_gid'] = $value['gid'] ?? 0;
|
||||
$tmp['actions'] = $actions;
|
||||
//$tmp['actions'] = '';
|
||||
array_push($data['row'], $tmp);
|
||||
}
|
||||
if ($this->aria2->methodName === "tellActive") {
|
||||
$data['title'] = Helper::getTableTitles('active');
|
||||
} else {
|
||||
$data['title'] = Helper::getTableTitles();
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
135
lib/Controller/MainController.php
Normal file
135
lib/Controller/MainController.php
Normal file
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
namespace OCA\NcDownloader\Controller;
|
||||
|
||||
use OCA\NcDownloader\Search\torrentSearch;
|
||||
use OCA\NcDownloader\Tools\Aria2;
|
||||
use OCA\NcDownloader\Tools\DBConn;
|
||||
use OCA\NcDownloader\Tools\Helper;
|
||||
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\IRequest;
|
||||
use OC_Util;
|
||||
use \OCP\AppFramework\Http\StrictContentSecurityPolicy;
|
||||
|
||||
class MainController extends Controller
|
||||
{
|
||||
|
||||
private $settings = null;
|
||||
//@config OC\AppConfig
|
||||
private $config;
|
||||
private $aria2Opts;
|
||||
private $l10n;
|
||||
|
||||
public function __construct($appName, IRequest $request, $UserId, IL10N $IL10N, IRootFolder $rootFolder, Aria2 $aria2)
|
||||
{
|
||||
parent::__construct($appName, $request);
|
||||
$this->appName = $appName;
|
||||
$this->uid = $UserId;
|
||||
$this->l10n = $IL10N;
|
||||
$this->rootFolder = $rootFolder;
|
||||
OC_Util::setupFS();
|
||||
$this->urlGenerator = \OC::$server->getURLGenerator();
|
||||
$this->aria2 = $aria2;
|
||||
$this->aria2->init();
|
||||
$this->youtube = new Youtube();
|
||||
$this->dbconn = new DBConn();
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
*/
|
||||
public function Index()
|
||||
{
|
||||
// $str = \OC::$server->getDatabaseConnection()->getInner()->getPrefix();
|
||||
//$config = \OC::$server->getAppConfig();
|
||||
OC_Util::addScript($this->appName, 'app');
|
||||
OC_Util::addStyle($this->appName, 'style');
|
||||
OC_Util::addStyle($this->appName, 'table');
|
||||
$params = array();
|
||||
$params['aria2_running'] = $this->aria2->isRunning();
|
||||
$params['aria2_installed'] = $this->aria2->isInstalled();
|
||||
$params['youtube_installed'] = $this->youtube->isInstalled();
|
||||
|
||||
$response = new TemplateResponse($this->appName, 'Index', $params);
|
||||
|
||||
$csp = new StrictContentSecurityPolicy();
|
||||
$csp->allowEvalScript();
|
||||
$csp->allowInlineStyle();
|
||||
|
||||
$response->setContentSecurityPolicy($csp);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function newDownload()
|
||||
{
|
||||
$params = array();
|
||||
$inputValue = trim($this->request->getParam('form_input_text'));
|
||||
$type = trim($this->request->getParam('type'));
|
||||
if ($type == 'ytdl') {
|
||||
$yt = $this->youtube;
|
||||
if (!$yt->isInstalled()) {
|
||||
try {
|
||||
$filename = Helper::getFileName($yt->installUrl());
|
||||
$this->aria2->setDownloadDir($this->dataDir . "/bin");
|
||||
$resp = $this->Save($yt->installUrl(), $filename);
|
||||
return new JSONResponse($resp);
|
||||
} catch (\Exception $e) {
|
||||
return new JSONResponse(['error' => $e->getMessage()]);
|
||||
}
|
||||
|
||||
return new JSONResponse(['error' => $this->l10n->t("Youtube-dl NOT installed!")]);
|
||||
}
|
||||
if (Helper::isGetUrlSite($inputValue)) {
|
||||
if ($data = $yt->forceIPV4()->getDownloadUrl($inputValue)) {
|
||||
$this->Save($data['url'], $data['filename']);
|
||||
return new JSONResponse(['yt' => $data]);
|
||||
} else {
|
||||
return new JSONResponse(['error' => $this->l10n->t("failed to get any url!")]);
|
||||
}
|
||||
} else {
|
||||
$yt->setDownloadDir($this->realDownloadDir);
|
||||
return new JSONResponse(['yt' => $yt->download($inputValue)]);
|
||||
}
|
||||
} else if ($type === 'search') {
|
||||
$data = torrentSearch::go($inputValue);
|
||||
$resp['title'] = ['title', 'seeders', 'info', 'actions'];
|
||||
$resp['row'] = $data;
|
||||
return new JSONResponse($resp);
|
||||
}
|
||||
|
||||
$filename = Helper::getFileName($inputValue);
|
||||
$resp = $this->Save($inputValue, $filename);
|
||||
return new JSONResponse($resp);
|
||||
}
|
||||
|
||||
private function Save($url, $filename = null)
|
||||
{
|
||||
if (isset($filename)) {
|
||||
$this->aria2->setFileName($filename);
|
||||
}
|
||||
//$this->aria2->setDownloadDir("/tmp/downloads");
|
||||
$result = $this->aria2->addUri([$url]);
|
||||
$gid = $result['result'];
|
||||
if (!is_string($gid)) {
|
||||
return ['error' => 'Failed to add download task! ' . $result['error']];
|
||||
} else {
|
||||
$data = [
|
||||
'uid' => $this->uid,
|
||||
'gid' => $gid,
|
||||
'type' => 1,
|
||||
'filename' => $filename ?? 'unknown',
|
||||
'timestamp' => time(),
|
||||
'data' => serialize(['link' => $url]),
|
||||
];
|
||||
$this->dbconn->save($data);
|
||||
}
|
||||
return ['gid' => $gid, 'file' => $filename, 'result' => $gid];
|
||||
}
|
||||
}
|
||||
83
lib/Controller/SettingsController.php
Normal file
83
lib/Controller/SettingsController.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace OCA\NcDownloader\Controller;
|
||||
|
||||
use OCA\NcDownloader\Tools\Helper;
|
||||
use OCA\NcDownloader\Tools\Settings;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http\JSONResponse;
|
||||
use OCP\IRequest;
|
||||
use OC_Util;
|
||||
|
||||
class SettingsController extends Controller
|
||||
{
|
||||
/*@ OC\AppFramework\Http\Request*/
|
||||
//private $request;
|
||||
|
||||
//@config OC\AppConfig
|
||||
private $config;
|
||||
public function __construct($AppName, IRequest $Request, $UserId) //, IL10N $L10N)
|
||||
|
||||
{
|
||||
parent::__construct($AppName, $Request);
|
||||
$this->UserId = $UserId;
|
||||
//$this->L10N = $L10N;
|
||||
$this->settings = new Settings($UserId);
|
||||
//$this->config = \OC::$server->getAppConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
*/
|
||||
public function personal()
|
||||
{
|
||||
$params = $this->request->getParams();
|
||||
foreach ($params as $key => $value) {
|
||||
if (substr($key, 0, 1) == '_') {
|
||||
continue;
|
||||
}
|
||||
$this->save($key, $value);
|
||||
}
|
||||
}
|
||||
public function aria2Get()
|
||||
{
|
||||
$data = json_decode($this->settings->get("custom_aria2_settings"));
|
||||
return new JSONResponse($data);
|
||||
}
|
||||
|
||||
public function admin()
|
||||
{
|
||||
$this->settings->setType($this->settings::SYSTEM);
|
||||
$params = $this->request->getParams();
|
||||
foreach ($params as $key => $value) {
|
||||
if (substr($key, 0, 1) == '_') {
|
||||
continue;
|
||||
}
|
||||
$this->save($key, $value);
|
||||
}
|
||||
|
||||
}
|
||||
public function aria2Save()
|
||||
{
|
||||
$params = $this->request->getParams();
|
||||
$data = Helper::filterData($params, Helper::aria2Options());
|
||||
$this->settings->save("custom_aria2_settings", json_encode($data));
|
||||
}
|
||||
public function aria2Delete()
|
||||
{
|
||||
$saved = json_decode($this->settings->get("custom_aria2_settings"),1);
|
||||
$params = $this->request->getParams();
|
||||
$data = Helper::filterData($params, Helper::aria2Options());
|
||||
foreach ($data as $key => $value) {
|
||||
unset($saved[$key]);
|
||||
}
|
||||
$this->settings->save("custom_aria2_settings", json_encode($saved));
|
||||
return new JSONResponse($saved);
|
||||
}
|
||||
public function save($key, $value)
|
||||
{
|
||||
$this->settings->save($key, $value);
|
||||
}
|
||||
|
||||
}
|
||||
95
lib/Migration/Version00001date20210807.php
Normal file
95
lib/Migration/Version00001date20210807.php
Normal file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace OCA\NcDownloader\Migration;
|
||||
|
||||
use Closure;
|
||||
use OCP\DB\ISchemaWrapper;
|
||||
use OCP\Migration\IOutput;
|
||||
use OCP\Migration\SimpleMigrationStep;
|
||||
|
||||
/**
|
||||
* Auto-generated migration step: Please modify to your needs!
|
||||
*/
|
||||
class Version00001date20210807 extends SimpleMigrationStep
|
||||
{
|
||||
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||
* @param array $options
|
||||
*/
|
||||
public function preSchemaChange(IOutput $output, Closure $schemaClosure, array $options)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||
* @param array $options
|
||||
* @return null|ISchemaWrapper
|
||||
*/
|
||||
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options)
|
||||
{
|
||||
/** @var ISchemaWrapper $schema */
|
||||
$schema = $schemaClosure();
|
||||
|
||||
if (!$schema->hasTable('ncdownloader_info')) {
|
||||
$table = $schema->createTable('ncdownloader_info');
|
||||
$table->addColumn('id', 'integer', [
|
||||
'autoincrement' => true,
|
||||
'notnull' => true,
|
||||
'length' => 10,
|
||||
]);
|
||||
$table->addColumn('uid', 'string', [
|
||||
'notnull' => false,
|
||||
'length' => 64,
|
||||
]);
|
||||
$table->addColumn('gid', 'string', [
|
||||
'notnull' => true,
|
||||
'length' => 32,
|
||||
]);
|
||||
$table->addColumn('filename', 'string', [
|
||||
'notnull' => true,
|
||||
'length' => 255,
|
||||
]);
|
||||
$table->addColumn('type', 'smallint', [
|
||||
'notnull' => true,
|
||||
'length' => 4,
|
||||
'default' => 1,
|
||||
'comment' => "Download Type(Aria2 = 1,Youtube = 2,Others = 3)",
|
||||
]);
|
||||
$table->addColumn('status', 'smallint', [
|
||||
'notnull' => true,
|
||||
'length' => 1,
|
||||
'default' => 1,
|
||||
]);
|
||||
$table->addColumn('followedby', 'string', [
|
||||
'notnull' => true,
|
||||
'length' => 16,
|
||||
'default' => 0,
|
||||
]);
|
||||
$table->addColumn('timestamp', 'bigint', [
|
||||
'notnull' => true,
|
||||
'length' => 15,
|
||||
'default' => 0,
|
||||
]);
|
||||
$table->addColumn('data', 'blob', [
|
||||
'notnull' => false,
|
||||
'default' => null,
|
||||
]);
|
||||
$table->setPrimaryKey(['id','gid']);
|
||||
}
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||
* @param array $options
|
||||
*/
|
||||
public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options)
|
||||
{
|
||||
}
|
||||
}
|
||||
56
lib/Search/Sites/TPB.php
Normal file
56
lib/Search/Sites/TPB.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace OCA\NcDownloader\Search\Sites;
|
||||
|
||||
//The Piratebay
|
||||
class TPB
|
||||
{
|
||||
//html content
|
||||
private $content = null;
|
||||
public $baseUrl = "https://piratebay.live/search/";
|
||||
|
||||
public function __construct($crawler, $client)
|
||||
{
|
||||
$this->client = $client;
|
||||
$this->crawler = $crawler;
|
||||
}
|
||||
public function search($keyword)
|
||||
{
|
||||
$this->searchUrl = $this->baseUrl . trim($keyword);
|
||||
$this->crawler->add($this->getContent());
|
||||
return $this->parse();
|
||||
}
|
||||
public function setContent($content)
|
||||
{
|
||||
$this->content = $content;
|
||||
}
|
||||
public function getContent()
|
||||
{
|
||||
if ($this->content) {
|
||||
return $this->content;
|
||||
}
|
||||
$response = $this->client->request('GET', $this->searchUrl);
|
||||
return $response->getContent();
|
||||
}
|
||||
public function parse()
|
||||
{
|
||||
$data = $this->crawler->filter("#searchResult tr")->each(function ($node, $i) {
|
||||
|
||||
if ($node->getNode(0)) {
|
||||
try {
|
||||
$title = $node->filter("a.detLink")->text();
|
||||
$info = $node->filter("font.detDesc")->text();
|
||||
$numSeeders = $node->filter("td:nth-child(3)")->text();
|
||||
$magnetLink = $node->filter("td:nth-child(2) > a:nth-child(2)")->attr("href");
|
||||
$parts = explode(',', $info);
|
||||
$info = $parts[0] . "-" . $parts[1];
|
||||
return ['title' => $title, 'data-link' => $magnetLink, 'seeders' => $numSeeders, 'info' => $info];
|
||||
} catch (\Exception $e) {
|
||||
//echo $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
33
lib/Search/torrentSearch.php
Normal file
33
lib/Search/torrentSearch.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace OCA\NcDownloader\Search;
|
||||
|
||||
require __DIR__ . "/../../vendor/autoload.php";
|
||||
use OCA\NcDownloader\Search\Sites\TPB;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
use Symfony\Component\HttpClient\HttpClient;
|
||||
|
||||
class torrentSearch
|
||||
{
|
||||
|
||||
public static function go($keyword)
|
||||
{
|
||||
$client = HttpClient::create();
|
||||
$crawler = new Crawler();
|
||||
$tpb = new TPB($crawler, $client);
|
||||
$data = $tpb->search($keyword);
|
||||
self::addAction($data);
|
||||
return $data;
|
||||
}
|
||||
|
||||
private static function addAction(&$data)
|
||||
{
|
||||
foreach ($data as $key => &$value) {
|
||||
if (!$value) {
|
||||
continue;
|
||||
}
|
||||
$value['actions'][] = array("name" => 'add', 'path' => '/index.php/apps/ncdownloader/new');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
62
lib/Settings/Admin.php
Normal file
62
lib/Settings/Admin.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace OCA\NcDownloader\Settings;
|
||||
|
||||
use OCP\AppFramework\Http\TemplateResponse;
|
||||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
use OCP\IConfig;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\Settings\ISettings;
|
||||
use OCA\NcDownloader\Tools\Settings;
|
||||
|
||||
class Admin implements ISettings {
|
||||
|
||||
/** @var IDBConnection */
|
||||
private $connection;
|
||||
/** @var ITimeFactory */
|
||||
private $timeFactory;
|
||||
/** @var IConfig */
|
||||
private $config;
|
||||
|
||||
public function __construct(IDBConnection $connection,
|
||||
ITimeFactory $timeFactory,
|
||||
IConfig $config) {
|
||||
$this->connection = $connection;
|
||||
$this->timeFactory = $timeFactory;
|
||||
$this->config = $config;
|
||||
$this->UserId = \OC::$server->getUserSession()->getUser()->getUID();
|
||||
$this->settings = new Settings($this->UserId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TemplateResponse
|
||||
*/
|
||||
public function getForm() {
|
||||
$this->settings->setType($this->settings::SYSTEM);
|
||||
$parameters = [
|
||||
"path" => "/apps/ncdownloader/admin/save",
|
||||
"ncd_yt_binary" => $this->settings->get("ncd_yt_binary"),
|
||||
"ncd_aria2_binary" => $this->settings->get("ncd_aria2_binary"),
|
||||
"ncd_rpctoken" => $this->settings->get("ncd_rpctoken"),
|
||||
];
|
||||
return new TemplateResponse('ncdownloader', 'settings/Admin', $parameters, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the section ID, e.g. 'sharing'
|
||||
*/
|
||||
public function getSection(): string {
|
||||
return 'ncdownloader';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int whether the form should be rather on the top or bottom of
|
||||
* the admin section. The forms are arranged in ascending order of the
|
||||
* priority values. It is required to return a value between 0 and 100.
|
||||
*
|
||||
* E.g.: 70
|
||||
*/
|
||||
public function getPriority(): int {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
39
lib/Settings/AdminSection.php
Normal file
39
lib/Settings/AdminSection.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OCA\NcDownloader\Settings;
|
||||
|
||||
use OCP\IL10N;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\Settings\IIconSection;
|
||||
|
||||
class AdminSection implements IIconSection {
|
||||
|
||||
/** @var IL10N */
|
||||
private $l;
|
||||
|
||||
/** @var IURLGenerator */
|
||||
private $urlGenerator;
|
||||
|
||||
public function __construct(IL10N $l, IURLGenerator $urlGenerator) {
|
||||
$this->l = $l;
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
}
|
||||
|
||||
public function getIcon(): string {
|
||||
return $this->urlGenerator->imagePath('core', 'actions/settings-dark.svg');
|
||||
}
|
||||
|
||||
public function getID(): string {
|
||||
return 'ncdownloader';
|
||||
}
|
||||
|
||||
public function getName(): string {
|
||||
return $this->l->t('Downloader Settings');
|
||||
}
|
||||
|
||||
public function getPriority(): int {
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
68
lib/Settings/Personal.php
Normal file
68
lib/Settings/Personal.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace OCA\NcDownloader\Settings;
|
||||
|
||||
use OCP\AppFramework\Http\TemplateResponse;
|
||||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
use OCP\IConfig;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\Settings\ISettings;
|
||||
use OCA\NcDownloader\Tools\Settings;
|
||||
use OCA\NcDownloader\Tools\Helper;
|
||||
|
||||
class Personal implements ISettings {
|
||||
|
||||
/** @var IDBConnection */
|
||||
private $connection;
|
||||
/** @var ITimeFactory */
|
||||
private $timeFactory;
|
||||
/** @var IConfig */
|
||||
private $config;
|
||||
|
||||
public function __construct(IDBConnection $connection,
|
||||
ITimeFactory $timeFactory,
|
||||
IConfig $config) {
|
||||
$this->connection = $connection;
|
||||
$this->timeFactory = $timeFactory;
|
||||
$this->config = $config;
|
||||
$this->UserId = \OC::$server->getUserSession()->getUser()->getUID();
|
||||
$this->settings = new Settings($this->UserId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TemplateResponse
|
||||
*/
|
||||
public function getForm() {
|
||||
$parameters = [
|
||||
"ncd_downloader_dir" => $this->settings->get("ncd_downloader_dir"),
|
||||
"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"),
|
||||
'ncd_seed_time' => $this->settings->get("ncd_seed_time"),
|
||||
"path" => '/apps/ncdownloader/personal/save',
|
||||
];
|
||||
|
||||
//\OC_Util::addScript($this->appName, 'common');
|
||||
//\OC_Util::addScript($this->appName, 'settings/personal');
|
||||
//file_put_contents("/tmp/re.log",print_r($parameters,true));
|
||||
return new TemplateResponse('ncdownloader', 'settings/Personal', $parameters, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the section ID, e.g. 'sharing'
|
||||
*/
|
||||
public function getSection(): string {
|
||||
return 'ncdownloader';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int whether the form should be rather on the top or bottom of
|
||||
* the admin section. The forms are arranged in ascending order of the
|
||||
* priority values. It is required to return a value between 0 and 100.
|
||||
*
|
||||
* E.g.: 70
|
||||
*/
|
||||
public function getPriority(): int {
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
39
lib/Settings/PersonalSection.php
Normal file
39
lib/Settings/PersonalSection.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OCA\NcDownloader\Settings;
|
||||
|
||||
use OCP\IL10N;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\Settings\IIconSection;
|
||||
|
||||
class PersonalSection implements IIconSection {
|
||||
|
||||
/** @var IL10N */
|
||||
private $l;
|
||||
|
||||
/** @var IURLGenerator */
|
||||
private $urlGenerator;
|
||||
|
||||
public function __construct(IL10N $l, IURLGenerator $urlGenerator) {
|
||||
$this->l = $l;
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
}
|
||||
|
||||
public function getIcon(): string {
|
||||
return $this->urlGenerator->imagePath('core', 'actions/settings-dark.svg');
|
||||
}
|
||||
|
||||
public function getID(): string {
|
||||
return 'ncdownloader';
|
||||
}
|
||||
|
||||
public function getName(): string {
|
||||
return $this->l->t('Downloader Settings');
|
||||
}
|
||||
|
||||
public function getPriority(): int {
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
373
lib/Tools/Aria2.php
Normal file
373
lib/Tools/Aria2.php
Normal file
@@ -0,0 +1,373 @@
|
||||
<?php
|
||||
|
||||
namespace OCA\NcDownloader\Tools;
|
||||
|
||||
//use Symfony\Component\Process\ExecutableFinder;
|
||||
use Symfony\Component\Process\Exception\ProcessFailedException;
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
class Aria2
|
||||
{
|
||||
//extra Aria2 download options
|
||||
private $options = array();
|
||||
//optional token for authenticating with Aria2
|
||||
private $token = null;
|
||||
//the aria2 method being invoked
|
||||
private $method = null;
|
||||
//the aria2c binary path
|
||||
private $bin = null;
|
||||
// return the following items when getting downloads info by default
|
||||
private $dataFilter = array(
|
||||
'status', 'followedBy', 'totalLength', 'errorMessage', 'dir', 'uploadLength', 'completedLength', 'downloadSpeed', 'files', 'numSeeders', 'connections', 'gid', 'following', 'bittorrent',
|
||||
);
|
||||
//whether to filter the response returned by aria2
|
||||
private $filterResponse = true;
|
||||
//absolute download path
|
||||
private $downloadDir;
|
||||
//the path to where hook scripts is stored
|
||||
public function __construct($options = array())
|
||||
{
|
||||
$options += array(
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 6800,
|
||||
'dir' => '/tmp/Downloads',
|
||||
'token' => null,
|
||||
'conf_dir' => '/tmp/aria2',
|
||||
'settings' => [],
|
||||
);
|
||||
//turn keys in $options into variables
|
||||
extract($options);
|
||||
$this->setDownloadDir($dir);
|
||||
if (!empty($settings)) {
|
||||
foreach ($settings as $key => $value) {
|
||||
$this->setOption($key, $value);
|
||||
}
|
||||
}
|
||||
$this->bin = Helper::findBinaryPath('aria2c');
|
||||
$this->rpcUrl = sprintf("http://%s:%s/jsonrpc", $host, $port);
|
||||
$this->tokenString = $token ?? 'ncdownloader123';
|
||||
$this->setToken($this->tokenString);
|
||||
$this->confDir = $conf_dir;
|
||||
$this->sessionFile = $this->confDir . "/aria2.session";
|
||||
$this->confFile = $this->confDir . "/aria2.conf";
|
||||
$this->logFile = $this->confDir . "/aria2.log";
|
||||
}
|
||||
public function init()
|
||||
{
|
||||
$this->ch = curl_init($this->rpcUrl);
|
||||
curl_setopt_array($this->ch, array(
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_HEADER => false,
|
||||
CURLOPT_SSL_VERIFYPEER => false,
|
||||
));
|
||||
$this->configure();
|
||||
}
|
||||
|
||||
public function setonDownloadStart($path)
|
||||
{
|
||||
$this->onDownloadStart = $path;
|
||||
}
|
||||
|
||||
public function reset()
|
||||
{
|
||||
$this->init();
|
||||
}
|
||||
|
||||
private function hasOption($key)
|
||||
{
|
||||
return (bool) isset($this->options[$key]);
|
||||
}
|
||||
|
||||
private function configure()
|
||||
{
|
||||
if (!is_dir($this->confDir)) {
|
||||
mkdir($this->confDir, 0755, true);
|
||||
}
|
||||
if (!file_exists($this->confDir . "/aria2.conf")) {
|
||||
file_put_contents($this->confDir . "/aria2.conf", $this->confTemplate());
|
||||
}
|
||||
if (!is_dir($dir = $this->getDownloadDir())) {
|
||||
mkdir($dir, 0755, true);
|
||||
}
|
||||
$this->followTorrent(true);
|
||||
}
|
||||
public function setToken($token)
|
||||
{
|
||||
$this->token = "token:$token";
|
||||
return $this;
|
||||
}
|
||||
public function setOption($key, $value)
|
||||
{
|
||||
$this->options[$key] = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOptions()
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
public function setDownloadDir($dir)
|
||||
{
|
||||
$this->setOption('dir', $dir);
|
||||
$this->downloadDir = $dir;
|
||||
if (!is_dir($dir)) {
|
||||
mkdir($dir, 0755, true);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
public function getDownloadDir()
|
||||
{
|
||||
return $this->downloadDir;
|
||||
}
|
||||
public function setFileName($file)
|
||||
{
|
||||
$this->options['out'] = $file;
|
||||
return $this;
|
||||
}
|
||||
public function followTorrent($follow)
|
||||
{
|
||||
$this->options['follow-torrent'] = $follow;
|
||||
return $this;
|
||||
}
|
||||
private function request($data)
|
||||
{
|
||||
$this->init();
|
||||
$defaults = array(
|
||||
'jsonrpc' => '2.0',
|
||||
'id' => 'ncdownloader',
|
||||
'method' => 'aria2.addUri',
|
||||
'params' => null,
|
||||
);
|
||||
|
||||
$data += $defaults;
|
||||
$this->content = json_encode($data);
|
||||
|
||||
if (isset($this->content)) {
|
||||
curl_setopt($this->ch, CURLOPT_POSTFIELDS, $this->content);
|
||||
}
|
||||
$resp = curl_exec($this->ch);
|
||||
curl_close($this->ch);
|
||||
return json_decode($resp, 1);
|
||||
}
|
||||
public function getFollowingGid($gid)
|
||||
{
|
||||
$data = $this->tellStatus($gid);
|
||||
if (!is_array($data)) {
|
||||
return 0;
|
||||
}
|
||||
$data = reset($data);
|
||||
return ($data['following'] ?? 0);
|
||||
}
|
||||
public function tellFail($range = [0, 999])
|
||||
{
|
||||
$this->filterResponse = false;
|
||||
$resp = $this->tellStopped($range);
|
||||
$result = $this->sortDownloadsResult($resp['result'], ['complete', 'removed']);
|
||||
$this->filterResponse = true;;
|
||||
return $result;
|
||||
}
|
||||
public function getCounters()
|
||||
{
|
||||
$active = is_array($data = $this->tellActive([])) ? count($data) : 0;
|
||||
$waiting = is_array($data = $this->tellWaiting([0, 999])) ? count($data) : 0;
|
||||
$stopped = is_array($data = $this->tellStopped([0, 999])) ? count($data) : 0;
|
||||
$fail = is_array($data = $this->tellFail([0, 999])) ? count($data) : 0;
|
||||
return ['active' => $active, 'waiting' => $waiting, 'complete' => $stopped, 'fail' => $fail];
|
||||
}
|
||||
public function tellAll()
|
||||
{
|
||||
$this->filterResponse = false;
|
||||
return array_merge($this->tellActive([]), $this->tellWaiting([0, 999]), $this->tellStopped([0, 999]));
|
||||
}
|
||||
public function __call($name, $args)
|
||||
{
|
||||
$this->methodName = $name;
|
||||
$data = array();
|
||||
if (isset($args[0]) && is_array($args[0]) && count($args) == 1 && strtolower($name) !== "adduri") {
|
||||
$args = reset($args);
|
||||
}
|
||||
switch ($name) {
|
||||
case "addUri":
|
||||
array_push($args, $this->options);
|
||||
break;
|
||||
case "tellActive":
|
||||
case "tellWaiting":
|
||||
case "tellStopped":
|
||||
array_push($args, $this->dataFilter);
|
||||
break;
|
||||
case "tellStatus":
|
||||
case "getFiles":
|
||||
array_push($args, $this->dataFilter);
|
||||
break;
|
||||
}
|
||||
if (isset($this->token)) {
|
||||
array_unshift($args, $this->token);
|
||||
}
|
||||
$data = array('params' => $args, 'method' => 'aria2.' . $name);
|
||||
$rawResp = $this->request($data);
|
||||
|
||||
if (!$this->filterResponse) {
|
||||
return $rawResp;
|
||||
}
|
||||
return $this->parseResp($rawResp);
|
||||
}
|
||||
private function sortDownloadsResult($result, $statusFilter = null)
|
||||
{
|
||||
$data = [];
|
||||
if (!isset($statusFilter)) {
|
||||
$statusFilter = ['error'];
|
||||
}
|
||||
if (empty($result)) {
|
||||
return [];
|
||||
}
|
||||
foreach ($result as $info) {
|
||||
$info = Helper::filterData($info);
|
||||
if (isset($info['files'])) {
|
||||
foreach ($info['files'] as $key => &$files) {
|
||||
$files = Helper::filterData($files, array('path', 'length'));
|
||||
}
|
||||
}
|
||||
if (in_array($info['status'], $statusFilter)) {
|
||||
continue;
|
||||
}
|
||||
array_push($data, $info);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
public function parseResp($resp = array())
|
||||
{
|
||||
$data = array();
|
||||
if (isset($resp['error']) && isset($resp['error']['message'])) {
|
||||
$data['error'] = $resp['error']['message'];
|
||||
return $data;
|
||||
}
|
||||
$result = $resp['result'] ?? null;
|
||||
if (!isset($result)) {
|
||||
return $data;
|
||||
}
|
||||
if ($this->methodName === 'tellStatus' && isset($result['files'])) {
|
||||
foreach ($result['files'] as $key => &$files) {
|
||||
$files = Helper::filterData($files, array('path', 'length'));
|
||||
}
|
||||
array_push($data, $result);
|
||||
return $data;
|
||||
}
|
||||
// parse response for tellActive,tellWaiting,and tellStopped
|
||||
if (strpos($this->methodName, "tell") !== false && is_array($result)) {
|
||||
return $this->sortDownloadsResult($result);
|
||||
}
|
||||
return $resp;
|
||||
}
|
||||
public function getStatus($gid)
|
||||
{
|
||||
return $this->tellStatus($gid);
|
||||
}
|
||||
public function restart()
|
||||
{
|
||||
$this->stop();
|
||||
$this->start();
|
||||
}
|
||||
|
||||
public function getDefaults()
|
||||
{
|
||||
return [
|
||||
'--continue',
|
||||
'--daemon=true',
|
||||
'--enable-rpc=true',
|
||||
'--rpc-secret=' . $this->tokenString,
|
||||
'--listen-port=51413',
|
||||
'--save-session=' . $this->sessionFile,
|
||||
'--input-file=' . $this->sessionFile,
|
||||
'--log=' . $this->logFile,
|
||||
'--rpc-listen-port=6800',
|
||||
'--follow-torrent=true',
|
||||
'--enable-dht=true',
|
||||
'--enable-peer-exchange=true',
|
||||
'--peer-id-prefix=-TR2770-',
|
||||
'--user-agent=Transmission/2.77',
|
||||
'--log-level=info',
|
||||
'--seed-ratio=1.0',
|
||||
'--bt-seed-unverified=true',
|
||||
'--max-overall-upload-limit=1M',
|
||||
'--max-overall-download-limit=0',
|
||||
'--max-connection-per-server=4',
|
||||
'--max-concurrent-downloads=5',
|
||||
];
|
||||
}
|
||||
public function start($bin = null)
|
||||
{
|
||||
//aria2c wont't start without any errors when input-file is set but missing
|
||||
if (!file_exists($this->sessionFile)) {
|
||||
file_put_contents($this->sessionFile, '');
|
||||
}
|
||||
|
||||
//$process = new Process([$this->bin, "--conf-path=" . $this->confFile]);
|
||||
$defaults = $this->getDefaults();
|
||||
array_unshift($defaults, $this->bin);
|
||||
$process = new Process($defaults);
|
||||
try {
|
||||
$process->mustRun();
|
||||
$output = $process->getOutput();
|
||||
} catch (ProcessFailedException $exception) {
|
||||
$error = $exception->getMessage();
|
||||
}
|
||||
$resp = [];
|
||||
if (isset($error)) {
|
||||
$resp['error'] = $error;
|
||||
$resp['status'] = false;
|
||||
} else {
|
||||
$resp['status'] = true;
|
||||
}
|
||||
return $resp;
|
||||
}
|
||||
public function isInstalled()
|
||||
{
|
||||
return (bool) isset($this->bin);
|
||||
}
|
||||
public function isRunning()
|
||||
{
|
||||
$resp = $this->getSessionInfo();
|
||||
return (bool) $resp;
|
||||
}
|
||||
public function stop()
|
||||
{
|
||||
$resp = $this->shutdown();
|
||||
return $resp ?? null;
|
||||
}
|
||||
private function confTemplate()
|
||||
{
|
||||
return <<<EOF
|
||||
continue
|
||||
daemon=true
|
||||
#dir=/home/aria2/Downloads
|
||||
#file-allocation=falloc
|
||||
log-level=info
|
||||
max-connection-per-server=4
|
||||
max-concurrent-downloads=5
|
||||
max-overall-download-limit=0
|
||||
min-split-size=5M
|
||||
enable-http-pipelining=true
|
||||
#interface=127.0.0.1
|
||||
enable-rpc=true
|
||||
rpc-secret=$this->tokenString
|
||||
rpc-listen-all=true
|
||||
rpc-listen-port=6800
|
||||
follow-torrent=true
|
||||
listen-port=51413
|
||||
enable-dht=true
|
||||
enable-peer-exchange=true
|
||||
peer-id-prefix=-TR2770-
|
||||
user-agent=Transmission/2.77
|
||||
seed-ratio=0.1
|
||||
bt-seed-unverified=true
|
||||
max-overall-upload-limit=1M
|
||||
#on-download-complete=$this->onDownloadComplete
|
||||
#on-download-error=$this->onDownloadError
|
||||
#on-download-start=$this->onDownloadStart
|
||||
save-session=$this->sessionFile
|
||||
input-file=$this->sessionFile
|
||||
log=$this->logFile
|
||||
EOF;
|
||||
}
|
||||
}
|
||||
90
lib/Tools/DBConn.php
Normal file
90
lib/Tools/DBConn.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
namespace OCA\NcDownloader\Tools;
|
||||
|
||||
class DBConn
|
||||
{
|
||||
//@var OC\DB\ConnectionAdapter
|
||||
private $conn;
|
||||
private $table = "ncdownloader_info";
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->conn = \OC::$server->getDatabaseConnection();
|
||||
$this->queryBuilder = $this->conn->getQueryBuilder();
|
||||
//$container = \OC::$server->query(\OCP\IServerContainer::class);
|
||||
//Helper::debug(get_class($container->query(\OCP\RichObjectStrings\IValidator::class)));
|
||||
//$this->conn = \OC::$server->query(Connection::class);//working only with 22
|
||||
//$this->connAdapter = \OC::$server->getDatabaseConnection();
|
||||
//$this->conn = $this->connAdapter->getInner();
|
||||
}
|
||||
|
||||
public function create($insert)
|
||||
{
|
||||
$inserted = (bool) $this->conn->insertIfNotExist('*PREFIX*' . $this->table, $insert, [
|
||||
'gid',
|
||||
]);
|
||||
return $inserted;
|
||||
}
|
||||
public function getAll()
|
||||
{
|
||||
//OC\DB\QueryBuilder\QueryBuilder
|
||||
$queryBuilder = $this->queryBuilder
|
||||
->select('filename', 'type', 'gid', 'timestamp', 'status')
|
||||
->from($this->table)
|
||||
->execute();
|
||||
return $queryBuilder->fetchAll();
|
||||
}
|
||||
|
||||
public function getByUid($uid)
|
||||
{
|
||||
$queryBuilder = $this->queryBuilder
|
||||
->select('*')
|
||||
->from($this->table)
|
||||
->where('uid = :uid')
|
||||
->setParameter('uid', $uid)
|
||||
->execute();
|
||||
return $queryBuilder->fetchAll();
|
||||
}
|
||||
|
||||
public function getByGid($gid)
|
||||
{
|
||||
$queryBuilder = $this->queryBuilder
|
||||
->select('*')
|
||||
->from($this->table)
|
||||
->where('gid = :gid')
|
||||
->setParameter('gid', $gid)
|
||||
->execute();
|
||||
return $queryBuilder->fetch();
|
||||
}
|
||||
|
||||
public function save(array $keys, $values = array())
|
||||
{
|
||||
return $this->conn->setValues($this->table, $keys, $values);
|
||||
}
|
||||
|
||||
public function deleteByGid($gid)
|
||||
{
|
||||
// $sql = sprintf("DELETE FROM %s WHERE gid = ?",'*PREFIX*'.$this->table);
|
||||
// return $this->conn->executeStatement($sql,array($gid));
|
||||
$qb = $this->queryBuilder
|
||||
->delete($this->table)
|
||||
->where('gid = :gid')
|
||||
->setParameter('gid', $gid);
|
||||
return $qb->execute();
|
||||
}
|
||||
public function execute($sql, $values)
|
||||
{
|
||||
return $this->conn->executeStatement($sql, $values);
|
||||
|
||||
// for some reason this doesn't work
|
||||
$query = $this->queryBuilder;
|
||||
$query->update('ncdownloader_info')
|
||||
->set("data", $query->createNamedParameter($value))
|
||||
->where($query->expr()->eq('gid', $query->createNamedParameter($gid)));
|
||||
// ->setParameter('gid', $gid);
|
||||
// return $query->execute();
|
||||
//return $query->getSQL();
|
||||
return $this->queryBuilder->getSQL();
|
||||
}
|
||||
|
||||
}
|
||||
86
lib/Tools/ExecutableFinder.php
Normal file
86
lib/Tools/ExecutableFinder.php
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace OCA\NcDownloader\Tools;
|
||||
|
||||
/**
|
||||
* Generic executable finder.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
class ExecutableFinder
|
||||
{
|
||||
private $suffixes = ['.exe', '.bat', '.cmd', '.com'];
|
||||
|
||||
/**
|
||||
* Replaces default suffixes of executable.
|
||||
*/
|
||||
public function setSuffixes(array $suffixes)
|
||||
{
|
||||
$this->suffixes = $suffixes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new possible suffix to check for executable.
|
||||
*/
|
||||
public function addSuffix(string $suffix)
|
||||
{
|
||||
$this->suffixes[] = $suffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds an executable by name.
|
||||
*
|
||||
* @param string $name The executable name (without the extension)
|
||||
* @param string|null $default The default to return if no executable is found
|
||||
* @param array $extraDirs Additional dirs to check into
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function find(string $name, string $default = null, array $extraDirs = [])
|
||||
{
|
||||
if (ini_get('open_basedir')) {
|
||||
$searchPath = array_merge(explode(\PATH_SEPARATOR, ini_get('open_basedir')), $extraDirs);
|
||||
$dirs = [];
|
||||
foreach ($searchPath as $path) {
|
||||
// Silencing against https://bugs.php.net/69240
|
||||
if (@is_dir($path)) {
|
||||
$dirs[] = $path;
|
||||
} else {
|
||||
if (basename($path) == $name && @is_executable($path)) {
|
||||
return $path;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$dirs = array_merge(
|
||||
explode(\PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')),
|
||||
$extraDirs
|
||||
);
|
||||
}
|
||||
|
||||
$suffixes = [''];
|
||||
if ('\\' === \DIRECTORY_SEPARATOR) {
|
||||
$pathExt = getenv('PATHEXT');
|
||||
$suffixes = array_merge($pathExt ? explode(\PATH_SEPARATOR, $pathExt) : $this->suffixes, $suffixes);
|
||||
}
|
||||
foreach ($suffixes as $suffix) {
|
||||
foreach ($dirs as $dir) {
|
||||
if (@is_file($file = $dir.\DIRECTORY_SEPARATOR.$name.$suffix) && ('\\' === \DIRECTORY_SEPARATOR || @is_executable($file))) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
}
|
||||
28
lib/Tools/File.php
Normal file
28
lib/Tools/File.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
namespace OCA\NcDownloader\Tools;
|
||||
|
||||
use OCA\NcDownloader\Tools\Helper;
|
||||
use OC\Files\Filesystem;
|
||||
use OC\Files\Utils\Scanner;
|
||||
use \OCP\EventDispatcher\IEventDispatcher;
|
||||
|
||||
class File
|
||||
{
|
||||
public static function syncFolder($dir)
|
||||
{
|
||||
$user = \OC::$server->getUserSession()->getUser()->getUID();
|
||||
$logger = \OC::$server->getLogger();
|
||||
$scanner = new Scanner($user, \OC::$server->getDatabaseConnection(), \OC::$server->query(IEventDispatcher::class), $logger);
|
||||
$path = Filesystem::getRoot() . "/" . ltrim($dir, '/\\');
|
||||
try {
|
||||
$scanner->scan($path);
|
||||
// Helper::debug($logger->getLogPath());
|
||||
//$logger->warning($logger->getLogPath(),['app' =>'Ncdownloader']);
|
||||
} catch (ForbiddenException $e) {
|
||||
$logger->warning("Make sure you're running the scan command only as the user the web server runs as");
|
||||
} catch (\Exception $e) {
|
||||
|
||||
$logger->warning("Exception during scan: " . $e->getMessage() . $e->getTraceAsString());
|
||||
}
|
||||
}
|
||||
}
|
||||
257
lib/Tools/Helper.php
Normal file
257
lib/Tools/Helper.php
Normal file
@@ -0,0 +1,257 @@
|
||||
<?php
|
||||
|
||||
namespace OCA\NcDownloader\Tools;
|
||||
|
||||
use OCA\NcDownloader\Tools\aria2Options;
|
||||
|
||||
class Helper
|
||||
{
|
||||
public static function isUrl($URL)
|
||||
{
|
||||
$URLPattern = '%^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@|\d{1,3}(?:\.\d{1,3}){3}|(?:(?:[a-z\d\x{00a1}-\x{ffff}'
|
||||
. ']+-?)*[a-z\d\x{00a1}-\x{ffff}]+)(?:\.(?:[a-z\d\x{00a1}-\x{ffff}]+-?)*[a-z\d\x{00a1}-\x{ffff}]+)*(?:\.'
|
||||
. '[a-z\x{00a1}-\x{ffff}]{2,6}))(?::\d+)?(?:[^\s]*)?$%iu';
|
||||
|
||||
preg_match($URLPattern, $URL, $Matches);
|
||||
if (count($Matches) === 1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function isMagnet($url)
|
||||
{
|
||||
$scheme = parse_url($url, PHP_URL_SCHEME);
|
||||
return strtolower($scheme) == "magnet";
|
||||
}
|
||||
public static function isHttp($url)
|
||||
{
|
||||
$scheme = parse_url($url, PHP_URL_SCHEME);
|
||||
return (in_array($scheme, array('http', 'https')));
|
||||
}
|
||||
public static function isFtp($url)
|
||||
{
|
||||
$scheme = parse_url($url, PHP_URL_SCHEME);
|
||||
return strtolower($scheme) == "ftp";
|
||||
}
|
||||
public static function isGetUrlSite($url)
|
||||
{
|
||||
$host = parse_url($url, PHP_URL_HOST);
|
||||
$sites = ['twitter.com', 'youtube.com'];
|
||||
return (bool) (in_array($host, $sites));
|
||||
}
|
||||
public static function parseUrl($url)
|
||||
{
|
||||
parse_str(str_replace('tr=', 'tr[]=', parse_url($url, PHP_URL_QUERY)), $query);
|
||||
return $query;
|
||||
}
|
||||
|
||||
public static function getUrlPath($url)
|
||||
{
|
||||
$path = parse_url($url, PHP_URL_PATH);
|
||||
return self::cleanString(basename($path));
|
||||
}
|
||||
public static function getFilename($url)
|
||||
{
|
||||
if (self::isMagnet($url)) {
|
||||
return self::parseUrl($url)['dn'];
|
||||
} else {
|
||||
return self::getUrlPath($url);
|
||||
}
|
||||
}
|
||||
public static function formatBytes($size, $precision = 2)
|
||||
{
|
||||
if ($size < 1) {
|
||||
return '0';
|
||||
}
|
||||
$base = log($size, 1024);
|
||||
$suffixes = array('', 'K', 'M', 'G', 'T');
|
||||
return round(pow(1024, $base - floor($base)), $precision) . ' ' . $suffixes[floor($base)];
|
||||
}
|
||||
|
||||
public static function checkMediaType($url, $type = 'video/mp4')
|
||||
{
|
||||
$result = parse_url($url);
|
||||
if (isset($result['scheme']) && self::isHttp($url)) {
|
||||
if (isset($result['query'])) {
|
||||
parse_str($result['query'], $output);
|
||||
if (!isset($output['mime'])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return (bool) ($output['mime'] == trim($type));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function isYoutubeType($url)
|
||||
{
|
||||
$regex = '%^(?:(?:https?)://)(?:[a-z0-9_]*\.)?(?:twitter|youtube)\.com/%i';
|
||||
return (bool) preg_match($regex, $url);
|
||||
}
|
||||
|
||||
public static function cleanString($string)
|
||||
{
|
||||
$replace = array
|
||||
(
|
||||
'/[áàâãªä]/u' => 'a',
|
||||
'/[ÁÀÂÃÄ]/u' => 'A',
|
||||
'/[ÍÌÎÏ]/u' => 'I',
|
||||
'/[íìîï]/u' => 'i',
|
||||
'/[éèêë]/u' => 'e',
|
||||
'/[ÉÈÊË]/u' => 'E',
|
||||
'/[óòôõºö]/u' => 'o',
|
||||
'/[ÓÒÔÕÖ]/u' => 'O',
|
||||
'/[úùûü]/u' => 'u',
|
||||
'/[ÚÙÛÜ]/u' => 'U',
|
||||
'/ç/' => 'c',
|
||||
'/Ç/' => 'C',
|
||||
'/ñ/' => 'n',
|
||||
'/Ñ/' => 'N',
|
||||
'/–/' => '-', // UTF-8 hyphen to "normal" hyphen
|
||||
'/[’‘‹›‚]/u' => '', // Literally a single quote
|
||||
'/[“”«»„]/u' => '', // Double quote
|
||||
'/ /' => '_', // nonbreaking space(equiv. to 0x160)
|
||||
'/[^a-z0-9_\s.-]/i' => '_',
|
||||
);
|
||||
return preg_replace(array_keys($replace), array_values($replace), $string);
|
||||
}
|
||||
|
||||
public static function debug($msg)
|
||||
{
|
||||
$logger = \OC::$server->getLogger();
|
||||
$logger->debug($msg, ['app' => 'ncdownloader']);
|
||||
}
|
||||
|
||||
public static function log($msg, $file = "/tmp/nc.log")
|
||||
{
|
||||
file_put_contents($file, print_r($msg, true));
|
||||
}
|
||||
public static function filterData($data, $filter = null)
|
||||
{
|
||||
if (!isset($filter)) {
|
||||
$filter = array(
|
||||
'status', 'followedBy', 'totalLength', 'errorMessage', 'dir', 'uploadLength', 'completedLength', 'downloadSpeed', 'files', 'numSeeders', 'connections', 'gid', 'following',
|
||||
);
|
||||
}
|
||||
$value = array_filter($data, function ($k) use ($filter) {
|
||||
return (in_array($k, $filter));
|
||||
}, ARRAY_FILTER_USE_KEY);
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function getFolderName($folder, $prefix)
|
||||
{
|
||||
$folder = ltrim($folder, $prefix);
|
||||
return substr($folder, 0, strpos($folder, '/'));
|
||||
}
|
||||
|
||||
public static function Download($url, $file = null)
|
||||
{
|
||||
if (!isset($file)) {
|
||||
$file = "/tmp/" . self::getFilename($url);
|
||||
}
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_HEADER, 1);
|
||||
curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
|
||||
$result = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
file_put_contents($file, $result);
|
||||
}
|
||||
|
||||
public static function is_function_enabled($function_name)
|
||||
{
|
||||
if (!function_exists($function_name)) {
|
||||
return false;
|
||||
}
|
||||
$ini = \OC::$server->getIniWrapper();
|
||||
$disabled = explode(',', $ini->get('disable_functions') ?: '');
|
||||
$disabled = array_map('trim', $disabled);
|
||||
if (in_array($function_name, $disabled)) {
|
||||
return false;
|
||||
}
|
||||
$disabled = explode(',', $ini->get('suhosin.executor.func.blacklist') ?: '');
|
||||
$disabled = array_map('trim', $disabled);
|
||||
if (in_array($function_name, $disabled)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function findBinaryPath($program)
|
||||
{
|
||||
$memcache = \OC::$server->getMemCacheFactory()->createDistributed('findBinaryPath');
|
||||
if ($memcache->hasKey($program)) {
|
||||
return $memcache->get($program);
|
||||
}
|
||||
$dataPath = \OC::$server->getSystemConfig()->getValue('datadirectory');
|
||||
$paths = ['/usr/local/sbin', '/usr/local/bin', '/usr/sbin', '/usr/bin', '/sbin', '/bin', '/opt/bin', $dataPath . "/bin"];
|
||||
$result = null;
|
||||
if (self::is_function_enabled('exec')) {
|
||||
$exeSniffer = new ExecutableFinder();
|
||||
// Returns null if nothing is found
|
||||
$result = $exeSniffer->find($program, null, $paths);
|
||||
}
|
||||
// store the value for 5 minutes
|
||||
$memcache->set($program, $result, 300);
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function formatInterval($interval, $granularity = 2)
|
||||
{
|
||||
$units = array(
|
||||
'1 year|years' => 31536000,
|
||||
'1 monthmonths' => 2592000,
|
||||
'1 week|weeks' => 604800,
|
||||
'1 day|days' => 86400,
|
||||
'1 hour|hours' => 3600,
|
||||
'1 min|mins' => 60,
|
||||
'1 sec|sec' => 1,
|
||||
);
|
||||
$output = '';
|
||||
foreach ($units as $key => $value) {
|
||||
$key = explode('|', $key);
|
||||
if ($interval >= $value) {
|
||||
$output .= ($output ? ' ' : '') . self::formatPlural(floor($interval / $value), $key[0], $key[1]);
|
||||
$interval %= $value;
|
||||
$granularity--;
|
||||
}
|
||||
if ($granularity == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $output ? $output : '0 sec';
|
||||
}
|
||||
|
||||
public static function formatPlural($count, $singular, $plural)
|
||||
{
|
||||
if ($count == 1) {
|
||||
return $singular;
|
||||
} else {
|
||||
return $count . " " . $plural;
|
||||
}
|
||||
}
|
||||
public static function aria2Options()
|
||||
{
|
||||
return aria2Options::get();
|
||||
}
|
||||
|
||||
public static function getTableTitles($type = null)
|
||||
{
|
||||
$general = ['filename', 'status', 'actions'];
|
||||
if(!isset($type)){
|
||||
return $general;
|
||||
}
|
||||
$titles = [
|
||||
'active' => ['filename', 'speed', 'progress', 'actions'],
|
||||
'waiting' => $general,
|
||||
'fail' => $general,
|
||||
'complete' => $general,
|
||||
];
|
||||
return $titles[$type];
|
||||
}
|
||||
|
||||
}
|
||||
235
lib/Tools/Settings.php
Normal file
235
lib/Tools/Settings.php
Normal file
@@ -0,0 +1,235 @@
|
||||
<?php
|
||||
|
||||
namespace OCA\NcDownloader\Tools;
|
||||
|
||||
use OC\AllConfig;
|
||||
|
||||
class Settings extends AllConfig
|
||||
{
|
||||
//@config OC\AppConfig
|
||||
private $config;
|
||||
|
||||
//@OC\SystemConfig
|
||||
private $sysConfig;
|
||||
|
||||
//@OC\AllConfig
|
||||
private $allConfig;
|
||||
|
||||
//type of settings (system = 1 or app =2)
|
||||
private $type;
|
||||
const SYSTEM = 0x001;
|
||||
const USER = 0x010;
|
||||
const APP = 0x100;
|
||||
public function __construct($user = null)
|
||||
{
|
||||
$this->appConfig = \OC::$server->getAppConfig();
|
||||
$this->sysConfig = \OC::$server->getSystemConfig();
|
||||
$this->appName = 'ncdownloader';
|
||||
$this->type = self::USER;
|
||||
$this->user = $user;
|
||||
$this->allConfig = new AllConfig($this->sysConfig);
|
||||
//$this->connAdapter = \OC::$server->getDatabaseConnection();
|
||||
//$this->conn = $this->connAdapter->getInner();
|
||||
}
|
||||
public function setType($type)
|
||||
{
|
||||
$this->type = $type;
|
||||
return $this;
|
||||
}
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
if ($this->type == self::USER && isset($this->user)) {
|
||||
return $this->allConfig->getUserValue($this->user, $this->appName, $key, $default);
|
||||
} else if ($this->type == self::SYSTEM) {
|
||||
return $this->allConfig->getSystemValue($key, $default);
|
||||
} else {
|
||||
return $this->allConfig->getAppValue($this->appName, $key, $default);
|
||||
}
|
||||
}
|
||||
public function getAria2()
|
||||
{
|
||||
$settings = $this->allConfig->getUserValue($this->user, $this->appName, "custom_aria2_settings", '');
|
||||
return json_decode($settings, 1);
|
||||
}
|
||||
public function getAll()
|
||||
{
|
||||
if ($this->type === self::APP) {
|
||||
return $this->getAllAppValues();
|
||||
} else {
|
||||
$data = $this->getAllUserSettings();
|
||||
return $data;
|
||||
}
|
||||
|
||||
}
|
||||
public function save($key, $value)
|
||||
{
|
||||
if ($this->type == self::USER && isset($this->user)) {
|
||||
return $this->allConfig->setUserValue($this->user, $this->appName, $key, $value);
|
||||
} else if ($this->type == self::SYSTEM) {
|
||||
return $this->allConfig->setSystemValue($key, $value);
|
||||
} else {
|
||||
return $this->allConfig->setAppValue($this->appName, $key, $value);
|
||||
}
|
||||
|
||||
}
|
||||
public function getAllAppValues()
|
||||
{
|
||||
$keys = $this->getAllKeys();
|
||||
$value = [];
|
||||
foreach ($keys as $key) {
|
||||
$value[$key] = $this->allConfig->getAppValue($this->appName, $key);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
public function getAllKeys()
|
||||
{
|
||||
return $this->allConfig->getAppKeys($this->appName);
|
||||
}
|
||||
|
||||
public function getAllUserSettings()
|
||||
{
|
||||
$keys = $this->allConfig->getUserKeys($this->user, $this->appName);
|
||||
$value = [];
|
||||
foreach ($keys as $key) {
|
||||
$value[$key] = $this->allConfig->getUserValue($this->user, $this->appName, $key);
|
||||
}
|
||||
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));
|
||||
|
||||
}
|
||||
}
|
||||
127
lib/Tools/YouTube.php
Normal file
127
lib/Tools/YouTube.php
Normal file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
namespace OCA\NcDownloader\Tools;
|
||||
|
||||
use OCA\NcDownloader\Tools\Helper;
|
||||
use Symfony\Component\Process\Exception\ProcessFailedException;
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
class YouTube
|
||||
{
|
||||
private $ipv4Only;
|
||||
private $audioOnly = 0;
|
||||
private $audioFormat, $videoFormat = 'mp4';
|
||||
private $options = [];
|
||||
public function __construct()
|
||||
{
|
||||
$this->bin = Helper::findBinaryPath('youtube-dl');
|
||||
}
|
||||
|
||||
public function GetUrlOnly()
|
||||
{
|
||||
$this->addOption('--get-filename');
|
||||
$this->addOption('--get-url');
|
||||
return $this;
|
||||
}
|
||||
|
||||
public static function create()
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
|
||||
public function setDownloadDir($dir)
|
||||
{
|
||||
$this->downloadDir = rtrim($dir, '/');
|
||||
}
|
||||
|
||||
public function prependOption($option)
|
||||
{
|
||||
array_unshift($this->options, $option);
|
||||
}
|
||||
|
||||
public function download($url)
|
||||
{
|
||||
$this->downloadDir = $this->downloadDir ?? "/tmp/downloads";
|
||||
$this->prependOption($this->downloadDir . "/%(id)s-%(title)s.%(ext)s");
|
||||
$this->prependOption("-o");
|
||||
$this->setUrl($url);
|
||||
$this->prependOption($this->bin);
|
||||
// $this->buildCMD();
|
||||
$process = new Process($this->options);
|
||||
try {
|
||||
$process->mustRun();
|
||||
$output = $process->getOutput();
|
||||
} catch (ProcessFailedException $exception) {
|
||||
$output = $exception->getMessage();
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
public function getDownloadUrl($url)
|
||||
{
|
||||
$this->setUrl($url);
|
||||
$this->GetUrlOnly();
|
||||
//$process = new Process($this->options);
|
||||
$this->buildCMD();
|
||||
exec($this->cmd, $output, $returnCode);
|
||||
if (count($output) === 1) {
|
||||
return ['url' => reset($output)];
|
||||
}
|
||||
list($url, $filename) = $output;
|
||||
return ['url' => $url, 'filename' => Helper::cleanString($filename)];
|
||||
}
|
||||
|
||||
public function setUrl($url)
|
||||
{
|
||||
$this->addOption('-i');
|
||||
$this->addOption($url);
|
||||
//$index = array_search('-i', $this->options);
|
||||
//array_splice($this->options, $index + 1, 0, $url);
|
||||
}
|
||||
|
||||
public function addOption($option)
|
||||
{
|
||||
array_push($this->options, $option);
|
||||
}
|
||||
|
||||
public function forceIPV4()
|
||||
{
|
||||
$this->addOption('-4');
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setAudioFormat($format)
|
||||
{
|
||||
$this->audioFormat = $format;
|
||||
}
|
||||
|
||||
public function setvideoFormat($format)
|
||||
{
|
||||
$this->videoFormat = $format;
|
||||
}
|
||||
|
||||
private function buildCMD()
|
||||
{
|
||||
$this->cmd = $this->bin;//. " 2>&1";
|
||||
|
||||
foreach ($this->options as $option) {
|
||||
$this->cmd .= " " . $option;
|
||||
}
|
||||
|
||||
}
|
||||
public function isInstalled()
|
||||
{
|
||||
return (bool) isset($this->bin);
|
||||
}
|
||||
public static function install()
|
||||
{
|
||||
$url = $this->installUrl();
|
||||
$path = \OC::$server->getSystemConfig()->getValue('datadirectory');
|
||||
Helper::Download($url, $path . "/youtube-dl");
|
||||
}
|
||||
|
||||
public function installUrl()
|
||||
{
|
||||
return "https://yt-dl.org/downloads/latest/youtube-dl";
|
||||
}
|
||||
|
||||
}
|
||||
11
lib/Tools/aria2Options.php
Normal file
11
lib/Tools/aria2Options.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
namespace OCA\NcDownloader\Tools;
|
||||
|
||||
class aria2Options
|
||||
{
|
||||
|
||||
public static function get()
|
||||
{
|
||||
return ["ca-certificate", "certificate", "dht-file-path", "dht-file-path6", "dir", "input-file", "load-cookies", "log", "metalink-file", "netrc-path", "on-bt-download-complete", "on-download-complete", "on-download-error", "on-download-start", "on-download-stop", "on-download-pause", "out", "private-key", "rpc-certificate", "rpc-private-key", "save-cookies", "save-session", "server-stat-if", "server-stat-of", "torrent-file", "all-proxy", "all-proxy-passwd", "all-proxy-user", "allow-overwrite", "allow-piece-length-change", "always-resume", "async-dns", "auto-file-renaming", "bt-enable-hook-after-hash-check", "bt-enable-lpd", "bt-exclude-tracker", "bt-external-ip", "bt-force-encryption", "bt-hash-check-seed", "bt-load-saved-metadata", "bt-max-peers", "bt-metadata-only", "bt-min-crypto-level", "bt-prioritize-piece", "bt-remove-unselected-file", "bt-request-peer-speed-limit", "bt-require-crypto", "bt-save-metadata", "bt-seed-unverified", "bt-stop-timeout", "bt-tracker", "bt-tracker-connect-timeout", "bt-tracker-interval", "bt-tracker-timeout", "check-integrity", "checksum", "conditional-get", "connect-timeout", "content-disposition-default-utf8", "continue", "dir", "dry-run", "enable-http-keep-alive", "enable-http-pipelining", "enable-mmap", "enable-peer-exchange", "file-allocation", "follow-metalink", "follow-torrent", "force-save", "ftp-passwd", "ftp-pasv", "ftp-proxy", "ftp-proxy-passwd", "ftp-proxy-user", "ftp-reuse-connection", "ftp-type", "ftp-user", "gid", "hash-check-only", "header", "http-accept-gzip", "http-auth-challenge", "http-no-cache", "http-passwd", "http-proxy", "http-proxy-passwd", "http-proxy-user", "http-user", "https-proxy", "https-proxy-passwd", "https-proxy-user", "index-out", "lowest-speed-limit", "max-connection-per-server", "max-download-limit", "max-file-not-found", "max-mmap-limit", "max-resume-failure-tries", "max-tries", "max-upload-limit", "metalink-base-uri", "metalink-enable-unique-protocol", "metalink-language", "metalink-location", "metalink-os", "metalink-preferred-protocol", "metalink-version", "min-split-size", "no-file-allocation-limit", "no-netrc", "no-proxy", "out", "parameterized-uri", "pause", "pause-metadata", "piece-length", "proxy-method", "realtime-chunk-checksum", "referer", "remote-time", "remove-control-file", "retry-wait", "reuse-uri", "rpc-save-upload-metadata", "seed-ratio", "seed-time", "select-file", "split", "ssh-host-key-md", "stream-piece-selector", "timeout", "uri-selector", "use-head", "user-agent", "dry-run", "metalink-base-uri", "parameterized-uri", "pause", "piece-length", "rpc-save-upload-metadata", "bt-max-peers", "bt-request-peer-speed-limit", "bt-remove-unselected-file", "force-save", "max-download-limit", "max-upload-limit", "bt-max-open-files", "download-result", "keep-unfinished-download-result", "log", "log-level", "max-concurrent-downloads", "max-download-result", "max-overall-download-limit", "max-overall-upload-limit", "optimize-concurrent-downloads", "save-cookies", "save-session", "server-stat-of"];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user