added one more bt site;added the option for choosing a site to search torrents
This commit is contained in:
@@ -5,12 +5,16 @@ namespace OCA\NCDownloader\AppInfo;
|
|||||||
use OCA\NCDownloader\Controller\Aria2Controller;
|
use OCA\NCDownloader\Controller\Aria2Controller;
|
||||||
use OCA\NCDownloader\Controller\MainController;
|
use OCA\NCDownloader\Controller\MainController;
|
||||||
use OCA\NCDownloader\Controller\YoutubeController;
|
use OCA\NCDownloader\Controller\YoutubeController;
|
||||||
|
use OCA\NCDownloader\Search\Sites\bitSearch;
|
||||||
|
use OCA\NCDownloader\Search\Sites\TPB;
|
||||||
use OCA\NCDownloader\Tools\Aria2;
|
use OCA\NCDownloader\Tools\Aria2;
|
||||||
use OCA\NCDownloader\Tools\Helper;
|
use OCA\NCDownloader\Tools\Helper;
|
||||||
use OCA\NCDownloader\Tools\Settings;
|
use OCA\NCDownloader\Tools\Settings;
|
||||||
use OCA\NCDownloader\Tools\Youtube;
|
use OCA\NCDownloader\Tools\Youtube;
|
||||||
use OCP\AppFramework\App;
|
use OCP\AppFramework\App;
|
||||||
use OCP\IContainer;
|
use OCP\IContainer;
|
||||||
|
use Symfony\Component\DomCrawler\Crawler;
|
||||||
|
use Symfony\Component\HttpClient\HttpClient;
|
||||||
|
|
||||||
class Application extends App
|
class Application extends App
|
||||||
{
|
{
|
||||||
@@ -71,6 +75,22 @@ class Application extends App
|
|||||||
$container->query('Youtube')
|
$container->query('Youtube')
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
$container->registerService('crawler', function () {
|
||||||
|
return new Crawler();
|
||||||
|
});
|
||||||
|
$container->registerService('httpClient', function () {
|
||||||
|
return HttpClient::create();
|
||||||
|
});
|
||||||
|
$container->registerService(TPB::class, function (IContainer $container) {
|
||||||
|
$crawler = $container->query('crawler');
|
||||||
|
$client = $container->query('httpClient');
|
||||||
|
return new TPB($crawler, $client);
|
||||||
|
});
|
||||||
|
$container->registerService(bitSearch::class, function (IContainer $container) {
|
||||||
|
$crawler = $container->query('crawler');
|
||||||
|
$client = $container->query('httpClient');
|
||||||
|
return new bitSearch($crawler, $client);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getRealDownloadDir()
|
private function getRealDownloadDir()
|
||||||
|
|||||||
@@ -7,6 +7,15 @@ a {
|
|||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ncdownloader-form-wrapper .form-input-wrapper {
|
||||||
|
display : flex;
|
||||||
|
flex-flow: row nowrap;
|
||||||
|
}
|
||||||
|
#ncdownloader-form-wrapper .form-input-wrapper select,
|
||||||
|
#ncdownloader-form-wrapper .form-input-wrapper input {
|
||||||
|
justify-content: left;
|
||||||
|
}
|
||||||
|
|
||||||
a:hover,
|
a:hover,
|
||||||
a:focus {
|
a:focus {
|
||||||
color : #23527c;
|
color : #23527c;
|
||||||
@@ -17,11 +26,6 @@ a:focus {
|
|||||||
outline : 5px auto -webkit-focus-ring-color;
|
outline : 5px auto -webkit-focus-ring-color;
|
||||||
outline-offset: -2px;
|
outline-offset: -2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ncdownloader-form-wrapper input {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
div .number {
|
div .number {
|
||||||
background : none repeat scroll 0 0 #5f5853;
|
background : none repeat scroll 0 0 #5f5853;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
@@ -37,7 +41,7 @@ div .number {
|
|||||||
|
|
||||||
#ncdownloader-form-wrapper input[type=text] {
|
#ncdownloader-form-wrapper input[type=text] {
|
||||||
padding: 0px 5px;
|
padding: 0px 5px;
|
||||||
width : 100%;
|
flex:auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ncdownloader-table-data .table-cell {
|
#ncdownloader-table-data .table-cell {
|
||||||
@@ -51,9 +55,11 @@ div .number {
|
|||||||
.icon-purge {
|
.icon-purge {
|
||||||
background-image: url('../img/trash.svg');
|
background-image: url('../img/trash.svg');
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-unpause {
|
.icon-unpause {
|
||||||
background-image: url('../img/play.svg');
|
background-image: url('../img/play.svg');
|
||||||
}
|
}
|
||||||
|
|
||||||
#ncdownloader-action-links-container {
|
#ncdownloader-action-links-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,11 +134,11 @@ class Aria2Controller extends Controller
|
|||||||
if (isset($resp['error'])) {
|
if (isset($resp['error'])) {
|
||||||
return new JSONResponse($resp);
|
return new JSONResponse($resp);
|
||||||
}
|
}
|
||||||
$data = $this->prepareResp($resp);
|
$data = $this->transformResp($resp);
|
||||||
$data['counter'] = $counter;
|
$data['counter'] = $counter;
|
||||||
return new JSONResponse($data);
|
return new JSONResponse($data);
|
||||||
}
|
}
|
||||||
private function prepareResp($resp)
|
private function transformResp($resp)
|
||||||
{
|
{
|
||||||
|
|
||||||
$data = [];
|
$data = [];
|
||||||
@@ -191,7 +191,9 @@ class Aria2Controller extends Controller
|
|||||||
$left = Helper::formatInterval($remaining);
|
$left = Helper::formatInterval($remaining);
|
||||||
|
|
||||||
$numSeeders = $value['numSeeders'] ?? 0;
|
$numSeeders = $value['numSeeders'] ?? 0;
|
||||||
$extraInfo = "Seeders: $numSeeders";
|
$upload = $value['uploadLength'] ?? 0;
|
||||||
|
$upload = Helper::formatBytes($upload);
|
||||||
|
$extraInfo = "Seeders: $numSeeders|Up:$upload";
|
||||||
// $numPeers = isset($peers['result']) ? count($peers['result']) : 0;
|
// $numPeers = isset($peers['result']) ? count($peers['result']) : 0;
|
||||||
$value['progress'] = array(sprintf("%s(%.2f%%)", $completed, $percentage), $extraInfo);
|
$value['progress'] = array(sprintf("%s(%.2f%%)", $completed, $percentage), $extraInfo);
|
||||||
$timestamp = $timestamp ?? 0;
|
$timestamp = $timestamp ?? 0;
|
||||||
|
|||||||
@@ -19,12 +19,15 @@ class SearchController extends Controller
|
|||||||
$this->appName = $appName;
|
$this->appName = $appName;
|
||||||
$this->uid = $UserId;
|
$this->uid = $UserId;
|
||||||
$this->urlGenerator = \OC::$server->getURLGenerator();
|
$this->urlGenerator = \OC::$server->getURLGenerator();
|
||||||
|
$this->search = new torrentSearch();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function execute()
|
public function execute()
|
||||||
{
|
{
|
||||||
$keyword = trim($this->request->getParam('form_input_text'));
|
$keyword = trim($this->request->getParam('form_input_text'));
|
||||||
$data = torrentSearch::go($keyword);
|
$site = trim($this->request->getParam('select-value-search'));
|
||||||
|
$this->search->setSite($site);
|
||||||
|
$data = $this->search->go($keyword);
|
||||||
$resp['title'] = ['title', 'seeders', 'info', 'actions'];
|
$resp['title'] = ['title', 'seeders', 'info', 'actions'];
|
||||||
$resp['row'] = $data;
|
$resp['row'] = $data;
|
||||||
return new JSONResponse($resp);
|
return new JSONResponse($resp);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
namespace OCA\NCDownloader\Search\Sites;
|
namespace OCA\NCDownloader\Search\Sites;
|
||||||
|
|
||||||
//The Piratebay
|
//The Piratebay
|
||||||
class TPB
|
class TPB implements searchBase
|
||||||
{
|
{
|
||||||
//html content
|
//html content
|
||||||
private $content = null;
|
private $content = null;
|
||||||
|
|||||||
65
lib/Search/Sites/bitSearch.php
Normal file
65
lib/Search/Sites/bitSearch.php
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace OCA\NCDownloader\Search\Sites;
|
||||||
|
|
||||||
|
//bitsearch.to
|
||||||
|
class bitSearch implements searchBase
|
||||||
|
{
|
||||||
|
//html content
|
||||||
|
private $content = null;
|
||||||
|
public $baseUrl = "https://bitsearch.to/search";
|
||||||
|
private $query = null;
|
||||||
|
|
||||||
|
public function __construct($crawler, $client)
|
||||||
|
{
|
||||||
|
$this->client = $client;
|
||||||
|
$this->crawler = $crawler;
|
||||||
|
}
|
||||||
|
public function search($keyword)
|
||||||
|
{
|
||||||
|
$this->query = ['q' => trim($keyword), 'sort' => 'seeders'];
|
||||||
|
$this->searchUrl = $this->baseUrl;
|
||||||
|
//$this->setContent(file_get_contents(__DIR__ . "/BitSearch.html"));
|
||||||
|
$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, ['query' => $this->query]);
|
||||||
|
return $response->getContent();
|
||||||
|
}
|
||||||
|
public function parse()
|
||||||
|
{
|
||||||
|
|
||||||
|
$data = $this->crawler->filter(".w3-col.s12.mt-4 .search-result")->each(function ($node, $i) {
|
||||||
|
|
||||||
|
if ($node->getNode(0)) {
|
||||||
|
try {
|
||||||
|
$title = $node->filter(".info h5.title")->text();
|
||||||
|
$infoNode = $node->filter(".info .stats div");
|
||||||
|
$count = $infoNode->count();
|
||||||
|
$info = [];
|
||||||
|
for ($i = 0; $i < $count; $i++) {
|
||||||
|
$name = strtolower($infoNode->filter("img")->eq($i)->attr("alt"));
|
||||||
|
$info[$name] = trim($infoNode->eq($i)->text());
|
||||||
|
}
|
||||||
|
$seeders = $info['seeder'];
|
||||||
|
$info = sprintf("%s on %s", $info['size'], $info['date']);
|
||||||
|
$magnetLink = $node->filter(".links.center-flex a:nth-child(2)")->attr("href");
|
||||||
|
return ['title' => $title, 'data-link' => $magnetLink, 'seeders' => $seeders, 'info' => $info];
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
//echo $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
}
|
||||||
10
lib/Search/Sites/searchBase.php
Normal file
10
lib/Search/Sites/searchBase.php
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace OCA\NCDownloader\Search\Sites;
|
||||||
|
|
||||||
|
interface searchBase
|
||||||
|
{
|
||||||
|
public function search($keyword);
|
||||||
|
public function parse();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3,25 +3,35 @@
|
|||||||
namespace OCA\NCDownloader\Search;
|
namespace OCA\NCDownloader\Search;
|
||||||
|
|
||||||
require __DIR__ . "/../../vendor/autoload.php";
|
require __DIR__ . "/../../vendor/autoload.php";
|
||||||
use OCA\NCDownloader\Search\Sites\TPB;
|
use OCP\IServerContainer;
|
||||||
use OCA\NCDownloader\Tools\Helper;
|
|
||||||
use Symfony\Component\DomCrawler\Crawler;
|
|
||||||
use Symfony\Component\HttpClient\HttpClient;
|
|
||||||
|
|
||||||
class torrentSearch
|
class torrentSearch
|
||||||
{
|
{
|
||||||
|
public $container;
|
||||||
public static function go($keyword)
|
private $site = null;
|
||||||
|
public function __construct()
|
||||||
{
|
{
|
||||||
$client = HttpClient::create();
|
$this->container = \OC::$server->query(IServerContainer::class);
|
||||||
$crawler = new Crawler();
|
$this->site = __NAMESPACE__ . '\Sites\TPB';
|
||||||
$tpb = new TPB($crawler, $client);
|
}
|
||||||
$data = $tpb->search($keyword);
|
public function go($keyword)
|
||||||
self::addAction($data);
|
{
|
||||||
|
$siteInst = $this->container->query($this->site);
|
||||||
|
$data = $siteInst->search($keyword);
|
||||||
|
$this->addAction($data);
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function addAction(&$data)
|
public function setSite($site)
|
||||||
|
{
|
||||||
|
if (strpos($site, '\\') !== false) {
|
||||||
|
$this->site = $site;
|
||||||
|
} else {
|
||||||
|
$this->site = __NAMESPACE__ . '\Sites\\' . $site;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function addAction(&$data)
|
||||||
{
|
{
|
||||||
foreach ($data as $key => &$value) {
|
foreach ($data as $key => &$value) {
|
||||||
if (!$value) {
|
if (!$value) {
|
||||||
|
|||||||
@@ -36,7 +36,10 @@ const createInputBox = (event, type) => {
|
|||||||
}
|
}
|
||||||
let container;
|
let container;
|
||||||
if (type === 'search') {
|
if (type === 'search') {
|
||||||
container = inputBox.getInstance(name, type, path).create().addSpinner();
|
let selectOptions = [];
|
||||||
|
selectOptions.push({name:'bitSearch',label:'BITSEARCH',default:0});
|
||||||
|
selectOptions.push({name:'TPB',label:'THEPIRATEBAY',selected:1});
|
||||||
|
container = inputBox.getInstance(name, type, path).createOptions(selectOptions).create().addSpinner();
|
||||||
//container.appendChild(inputBox.createLoading());
|
//container.appendChild(inputBox.createLoading());
|
||||||
} else {
|
} else {
|
||||||
container = inputBox.getInstance(name, type, path).create().getContainer();
|
container = inputBox.getInstance(name, type, path).create().getContainer();
|
||||||
@@ -63,6 +66,8 @@ const inputHandler = (event) => {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
let element = event.target;
|
let element = event.target;
|
||||||
toggleSpinner(element);
|
toggleSpinner(element);
|
||||||
|
let formWrapper = element.closest('form');
|
||||||
|
|
||||||
let inputData = helper.getData('form-input-wrapper');
|
let inputData = helper.getData('form-input-wrapper');
|
||||||
let inputValue = inputData.form_input_text;
|
let inputValue = inputData.form_input_text;
|
||||||
if (inputData.type !== 'search' && !helper.isURL(inputValue) && !helper.isMagnetURI(inputValue)) {
|
if (inputData.type !== 'search' && !helper.isURL(inputValue) && !helper.isMagnetURI(inputValue)) {
|
||||||
@@ -82,7 +87,7 @@ const inputHandler = (event) => {
|
|||||||
if (data !== null && data.hasOwnProperty("file")) {
|
if (data !== null && data.hasOwnProperty("file")) {
|
||||||
helper.message(t("ncdownloader", "Downloading" + " " + data.file));
|
helper.message(t("ncdownloader", "Downloading" + " " + data.file));
|
||||||
}
|
}
|
||||||
toggleSpinner(element);
|
toggleSpinner(element);
|
||||||
if (data && data.title) {
|
if (data && data.title) {
|
||||||
const tableInst = nctable.getInstance(data.title, data.row);
|
const tableInst = nctable.getInstance(data.title, data.row);
|
||||||
tableInst.actionLink = false;
|
tableInst.actionLink = false;
|
||||||
@@ -90,7 +95,7 @@ const inputHandler = (event) => {
|
|||||||
tableInst.create();
|
tableInst.create();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const path = inputData.path || basePath + "/new";
|
const path = formWrapper.dataset.path || basePath + "/new";
|
||||||
let url = helper.generateUrl(path);
|
let url = helper.generateUrl(path);
|
||||||
Http.getInstance(url).setData(inputData).setHandler(function (data) {
|
Http.getInstance(url).setData(inputData).setHandler(function (data) {
|
||||||
successCallback(data, element);
|
successCallback(data, element);
|
||||||
|
|||||||
@@ -4,43 +4,78 @@ import helper from './helper'
|
|||||||
|
|
||||||
class inputBox {
|
class inputBox {
|
||||||
path;
|
path;
|
||||||
constructor(name, id, path = null) {
|
selectOptions = [];
|
||||||
this.name = name;
|
constructor(btnName, id, path = null) {
|
||||||
|
this.btnName = btnName;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.path = path;
|
this.path = path;
|
||||||
}
|
}
|
||||||
static getInstance(name, id, path = null) {
|
static getInstance(btnName, id, path = null) {
|
||||||
return new inputBox(name, id, path);
|
return new inputBox(btnName, id, path);
|
||||||
}
|
}
|
||||||
create() {
|
create() {
|
||||||
this.container = this._createForm();
|
this.formContainer = this._createForm();
|
||||||
this.textInput = this._createTextInput(this.id);
|
this.textInput = this._createTextInput(this.id);
|
||||||
this.controlsContainer = this._createControlsContainer();
|
this.buttonContainer = this._createButtonContainer();
|
||||||
this.container.appendChild(this.textInput);
|
this.formContainer.appendChild(this.textInput);
|
||||||
this.controlsContainer.appendChild(this._createControls());
|
if (this.selectOptions.length !== 0) {
|
||||||
this.container.appendChild(this.controlsContainer);
|
this.formContainer.appendChild(this._createSelect());
|
||||||
|
}
|
||||||
|
this.buttonContainer.appendChild(this._createButton());
|
||||||
|
this.formContainer.appendChild(this.buttonContainer);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
getContainer() {
|
getContainer() {
|
||||||
return this.container;
|
return this.formContainer;
|
||||||
}
|
}
|
||||||
setPath(path) {
|
setPath(path) {
|
||||||
this.path = path;
|
this.path = path;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
_createControlsContainer() {
|
_createButtonContainer() {
|
||||||
let div = document.createElement("div");
|
let div = document.createElement("div");
|
||||||
|
|
||||||
div.classList.add("controls-container");
|
div.classList.add("button-container");
|
||||||
return div;
|
return div;
|
||||||
}
|
}
|
||||||
_createForm() {
|
_createForm() {
|
||||||
let container = document.createElement("form");
|
let container = document.createElement("form");
|
||||||
container.classList.add("form-input-wrapper");
|
container.classList.add("form-input-wrapper");
|
||||||
container.setAttribute('id', 'form-input-wrapper');
|
container.setAttribute('id', 'form-input-wrapper');
|
||||||
|
if (this.path) {
|
||||||
|
container.setAttribute('data-path', this.path);
|
||||||
|
}
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
_createSelect(id) {
|
||||||
|
id = id || this.id;
|
||||||
|
let select = document.createElement('select');
|
||||||
|
select.setAttribute('id', "select-value-" + id);
|
||||||
|
select.setAttribute('value', '');
|
||||||
|
select.classList.add('form-select');
|
||||||
|
this.selectOptions.forEach(element => {
|
||||||
|
select.appendChild(element);
|
||||||
|
});
|
||||||
|
return select;
|
||||||
|
}
|
||||||
|
|
||||||
|
createOptions(data) {
|
||||||
|
if (!data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
data.forEach(element => {
|
||||||
|
let option = document.createElement('option');
|
||||||
|
option.setAttribute('value', element.name);
|
||||||
|
let text = document.createTextNode(element.label);
|
||||||
|
option.appendChild(text);
|
||||||
|
if (element.selected) {
|
||||||
|
option.setAttribute("selected", "selected");
|
||||||
|
}
|
||||||
|
this.selectOptions.push(option);
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
}
|
||||||
_createTextInput(id) {
|
_createTextInput(id) {
|
||||||
id = id || 'general';
|
id = id || 'general';
|
||||||
let textInput = document.createElement('input');
|
let textInput = document.createElement('input');
|
||||||
@@ -48,18 +83,15 @@ class inputBox {
|
|||||||
textInput.setAttribute('id', "form_input_text");
|
textInput.setAttribute('id', "form_input_text");
|
||||||
textInput.setAttribute('data-type', id);
|
textInput.setAttribute('data-type', id);
|
||||||
textInput.setAttribute('value', '');
|
textInput.setAttribute('value', '');
|
||||||
if (this.path) {
|
|
||||||
textInput.setAttribute('data-path', this.path);
|
|
||||||
}
|
|
||||||
textInput.classList.add('form-input-text');
|
textInput.classList.add('form-input-text');
|
||||||
return textInput;
|
return textInput;
|
||||||
}
|
}
|
||||||
_createControls() {
|
_createButton() {
|
||||||
let button = document.createElement('button');
|
let button = document.createElement('button');
|
||||||
button.setAttribute('type', this.name);
|
button.setAttribute('type', this.btnName);
|
||||||
button.setAttribute('id', 'form-input-button');
|
button.setAttribute('id', 'form-input-button');
|
||||||
//buttonInput.setAttribute('value', t('ncdownloader', helper.ucfirst(name)));
|
//buttonInput.setAttribute('value', t('ncdownloader', helper.ucfirst(btnName)));
|
||||||
let text = document.createTextNode(t('ncdownloader', helper.ucfirst(this.name)));
|
let text = document.createTextNode(t('ncdownloader', helper.ucfirst(this.btnName)));
|
||||||
button.appendChild(text);
|
button.appendChild(text);
|
||||||
return button;
|
return button;
|
||||||
}
|
}
|
||||||
@@ -69,8 +101,8 @@ class inputBox {
|
|||||||
let doc = parser.parseFromString(htmlString, "text/html")
|
let doc = parser.parseFromString(htmlString, "text/html")
|
||||||
let element = doc.querySelector(".bs-spinner");
|
let element = doc.querySelector(".bs-spinner");
|
||||||
element.style.display = 'none';
|
element.style.display = 'none';
|
||||||
this.controlsContainer.appendChild(element);
|
this.buttonContainer.appendChild(element);
|
||||||
return this.container;
|
return this.formContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user