Skip to content

Commit

Permalink
initial
Browse files Browse the repository at this point in the history
  • Loading branch information
little-brother committed Mar 22, 2024
0 parents commit 1e4290d
Show file tree
Hide file tree
Showing 5 changed files with 261 additions and 0 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Simple search plugin for [Synology Download Station](https://www.synology.com/en-global/dsm/packages/DownloadStation) with auth/cookies.

There are two problems:
1. The tracker requires auth cookies to download a torrent file;
2. The tracker may not be directly accessible.

The solution is the search plugin have to rewrite download links to a mediator that supports requests with cookies and can use a proxy to access to the tracker.
The repository contains a [DLM-plugin](https://github.com/little-brother/ds-search-plugin/tree/master/bt-rutracker) for [rutracker.org](https://rutracker.org) as an example and the [mediator app](https://github.com/little-brother/ds-search-plugin/tree/master/get-proxy) as a docker container. Check [Wiki](https://github.com/little-brother/ds-search-plugin/wiki) for details.
12 changes: 12 additions & 0 deletions bt-rutracker/INFO
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "bt-rutracker",
"displayname": "RuTracker",
"description": "RuTracker plugin",
"version": "1.0",
"site": "http://rutracker.org",
"hostprefix": "rutracker.org",
"accountsupport": true,
"module": "SynoDLMSearchRuTracker.php",
"type": "search",
"class": "SynoDLMSearchRuTracker"
}
128 changes: 128 additions & 0 deletions bt-rutracker/SynoDLMSearchRuTracker.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
<?php
class SynoDLMSearchRuTracker {
private $proxy = 'http://127.0.0.1:54321/?q=';
private $url = 'https://rutracker.org/forum/';
private $login_uri = 'login.php';
private $query_uri = 'tracker.php?nm=%s';
private $torrent_uri = 'dl.php?t=%s';
private $cookie = '/tmp/rutracker.cookie';

public function prepare($curl, $query, $login, $password) {
// Login
$opts = [
'url' => $this->url . $this->login_uri,
'method' => 'POST',
'postfields' => 'login_username=' . urlencode($login) . '&login_password='. urlencode($password) . '&login=%C2%F5%EE%E4',
'cookiejar' => $this->cookie,
'proxy' => true
];

$ch = curl_init($this->proxy . $this->encode($opts));
curl_exec($ch);
curl_close($ch);


// Query torrent list
$opts = [
'url' => sprintf($this->url . $this->query_uri, urlencode($query)),
'cookiefile' => $this->cookie,
'proxy' => true
];
curl_setopt($curl, CURLOPT_URL, $this->proxy . $this->encode($opts));

return true;
}

public function parse($plugin, $response) {
$input = iconv('cp1251', 'UTF-8', $response);

$regexp2 = "<tr.*class=\"tCenter hl-tr\" data-topic_id=\"[0-9]+\">(.*)<\/tr>";
$regexp_category = "<a.*tracker.php\?f=([0-9]+)\">(.*)<\/a>";
$regexp_title = "<a.*(viewtopic.php\?t=[0-9]+)\">(.*)<\/a>";
$regexp_download = "dl.php?\?t=([0-9]+)\"";
$regexp_size = "tor-size\" data-ts_text=\"([0-9]+)\"";
$regexp_datetime = "2px;\".*data-ts_text=\"([0-9]+)\"";
$regexp_seeds = "<b class=\"seedmed\">([0-9]+)<";
$regexp_leechs = "<td.*\"row4 leechmed.*>([0-9]+)<";

$res = 0;
if(preg_match_all("/$regexp2/siU", $input, $matches2, PREG_SET_ORDER)) {
foreach($matches2 as $match2) {
$title = 'Unknown title';
$download = 'Unknown download';
$size = 0;
$datetime = '1970-01-01';
$page = 'Default page';
$hash = 'Hash unknown';
$seeds = 0;
$leechs = 0;
$category = 'Unknown category';

if(preg_match_all("/$regexp_category/siU", $match2[0], $matches, PREG_SET_ORDER)) {
foreach($matches as $match) {
$category = $match[2];
}
}

if(preg_match_all("/$regexp_title/siU", $match2[0], $matches, PREG_SET_ORDER)) {
foreach($matches as $match) {
$page = $this->url.$match[1];
$title = str_replace('<wbr>', '', $match[2]);
$hash = md5($res.$title);
}
}

if(preg_match_all("/$regexp_download/siU", $match2[0], $matches, PREG_SET_ORDER)) {
foreach($matches as $match) {
$opts = [
'url' => sprintf($this->url . $this->torrent_uri, $match[1]),
'filename' => 'Loading...',
'mime' => 'application/x-bittorrent',
'cookiefile' => $this->cookie,
'useragent' => DOWNLOAD_STATION_USER_AGENT,
'proxy' => true
];

$download = $this->proxy . $this->encode($opts);
}
}

if(preg_match_all("/$regexp_size/siU", $match2[0], $matches, PREG_SET_ORDER)) {
foreach($matches as $match) {
$size = $match[1];
}
}

if(preg_match_all("/$regexp_datetime/siU", $match2[0], $matches, PREG_SET_ORDER)) {
foreach($matches as $match) {
$datetime = date('Y-m-d H:i',$match[1]);
}
}

if(preg_match_all("/$regexp_seeds/siU", $match2[0], $matches, PREG_SET_ORDER)) {
foreach($matches as $match) {
$seeds = $match[1];
}
}

if(preg_match_all("/$regexp_leechs/siU", $match2[0], $matches, PREG_SET_ORDER)) {
foreach($matches as $match) {
$leechs = $match[1];
}
}

if ($title != 'Unknown title') {
$plugin->addResult($title, $download, $size, $datetime, $page, $hash, $seeds, $leechs, $category);
$res++;
}
}
}

return $res;
}

protected function encode($opts) {
return urlencode(base64_encode(serialize($opts)));
}
}
?>
20 changes: 20 additions & 0 deletions get-proxy/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
FROM alpine:3.15.4

LABEL description = "GET-proxy server for search plugins of Synology Download Station"

ENV PROXY_IP=192.168.0.11
ENV PROXY_PORT=9050
ENV PROXY_TYPE=socks5
ENV PROXY_ATTEMPTS=3

RUN apk -U upgrade && \
apk -v add --no-cache php8 php8-curl && \
rm -rf /var/cache/apk/* && \
mkdir -p /var/www

COPY index.php /var/www/
WORKDIR "/var/www/"

CMD php8 -S 0.0.0.0:80

EXPOSE 80/tcp
93 changes: 93 additions & 0 deletions get-proxy/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php
$GET = unserialize(base64_decode($_GET['q'] ?? ''));

$url = $GET['url'] ?? '';
$useragent = $GET['useragent'] ?? 'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0';
$method = $GET['method'] ?? 'GET';
$postfields = $GET['postfields'] ?? false;
$encoding = $GET['encoding'] ?? '';
$filename = $GET['filename'] ?? false;
$mime = $GET['mime'] ?? 'application/octet-stream';

$header = $GET['header'] ?? false;
$cookie = $GET['cookie'] ?? false;
$cookiejar = $GET['cookiejar'] ?? false;
$cookiefile = $GET['cookiefile'] ?? false;

$proxy = isset($GET['proxy']);
$proxy_ip = getenv('PROXY_IP') ?? false;
$proxy_port = intval(getenv('PROXY_PORT') ?? 0);
$proxy_type = [
'http' => CURLPROXY_HTTP,
'https' => CURLPROXY_HTTPS,
'socks4' => CURLPROXY_SOCKS4,
'socks4a' => CURLPROXY_SOCKS4A,
'socks5' => CURLPROXY_SOCKS5,
'socks5_hostname' => CURLPROXY_SOCKS5_HOSTNAME
][strtolower(getenv('PROXY_TYPE') ?? 'socks5')] ?? CURLPROXY_SOCKS5;
$attemptCount = intval(getenv('PROXY_ATTEMPTS') ?? 3);

$options = [
CURLOPT_URL => $url,
CURLOPT_USERAGENT => $useragent,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_ENCODING => $encoding,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60
];

if ($proxy && $proxy_ip && $proxy_port) {
$options[CURLOPT_PROXYTYPE] = $proxy_type;
$options[CURLOPT_PROXY] = "{$proxy_ip}:{$proxy_port}";
}

if ($header)
$options[CURLOPT_HTTPHEADER] = $header;

if ($cookie)
$options[CURLOPT_HTTPHEADER] = array("Cookie: {$cookie}");

if ($cookiejar)
$options[CURLOPT_COOKIEJAR] = $cookiejar;

if ($cookiefile)
$options[CURLOPT_COOKIEFILE] = $cookiefile;

if ($postfields)
$options[CURLOPT_POSTFIELDS] = $postfields;

$res = false;
$error = false;
$attemptNo = 0;
while ($attemptNo < $attemptCount && !$res) {
$ch = curl_init();
curl_setopt_array($ch, $options);
$res = curl_exec($ch);
if (!$res) {
$error = curl_error($ch);
sleep(3);
}
curl_close($ch);

$attemptNo++;
}

if ($res) {
if ($filename) {
header("Content-Type: {$mime}");
header('Content-Disposition: attachment; filename="' . rawurlencode($filename) . '"');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . strlen($res));
header('Expires: 0');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Pragma: public');
header('Pragma: no-cache');
}

if ($_SERVER['REQUEST_METHOD'] != 'HEAD')
echo $res;
} else {
echo $error ?? '';
}
?>

0 comments on commit 1e4290d

Please sign in to comment.