ghost
1 year ago
5 changed files with 309 additions and 1 deletions
@ -1,2 +1,129 @@ |
|||||||
# yggtracker-wanted-torrents-receiver |
# yggtracker-wanted-torrents-receiver |
||||||
Crontab script that allows to receive wanted torrents from multiple YGGtracker nodes |
|
||||||
|
Crontab script that allows to receive wanted torrents from multiple [YGGtracker](https://github.com/YGGverse/YGGtracker) nodes |
||||||
|
|
||||||
|
#### Install |
||||||
|
|
||||||
|
Latest version of toolkit could be installed with single command: |
||||||
|
|
||||||
|
`git clone https://github.com/YGGverse/yggtracker-wanted-torrents-receiver.git` |
||||||
|
|
||||||
|
#### Config |
||||||
|
|
||||||
|
All configuration files placed at `/config` folder |
||||||
|
|
||||||
|
##### local.json |
||||||
|
|
||||||
|
``` |
||||||
|
{ |
||||||
|
"import": |
||||||
|
{ |
||||||
|
// Common rules for FTP connections |
||||||
|
"ftp": |
||||||
|
{ |
||||||
|
// How many of seconds wait for each provider response |
||||||
|
"timeout":5, |
||||||
|
// Which of remote folders grab to |
||||||
|
// array of target directories for each provider, eg. all, sensitive/no, locale/en, etc |
||||||
|
"directories": |
||||||
|
[ |
||||||
|
"all" |
||||||
|
] |
||||||
|
}, |
||||||
|
// Requirements filter before import something from providers |
||||||
|
"require": |
||||||
|
{ |
||||||
|
// Require approved torrents import only (according to provide.approved option in remote.json for each provider) |
||||||
|
"approved":true |
||||||
|
}, |
||||||
|
// Local storage settings for imported content |
||||||
|
"storage": |
||||||
|
{ |
||||||
|
// Storage directory by default, feel free to change like `/home/qbittorrent-nox/import` |
||||||
|
"directory":"storage", |
||||||
|
|
||||||
|
// Copy all torrents imported from providers folders to the storage/_common/{hash}.torrent |
||||||
|
// This mode check files MD5 hash sum to prevent duplicates in single folder from different providers |
||||||
|
// Useful when bittorrent client does not support support listening of multiple folders, recursive mode |
||||||
|
"common":true |
||||||
|
} |
||||||
|
}, |
||||||
|
"update": |
||||||
|
{ |
||||||
|
"config": |
||||||
|
{ |
||||||
|
// This option allows to auto-update remote.json file on the fly without updating codebase with git clone |
||||||
|
"remote": |
||||||
|
{ |
||||||
|
// If disabled, local file will not be updated, but manually |
||||||
|
"enabled": true, |
||||||
|
|
||||||
|
// Don't worry, just this repository |
||||||
|
"repository":"https://raw.githubusercontent.com/YGGverse/yggtracker-wanted-torrents-receiver/main/config/remote.json", |
||||||
|
|
||||||
|
// How many seconds to wait before ask repository for remote.json updates (after last file write) |
||||||
|
"cache":86400 |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
##### remote.json |
||||||
|
|
||||||
|
The remote configuration contains available YGGtracker providers. |
||||||
|
|
||||||
|
File also could be auto-updated from this repository when owner enabled `update.config.remote.enabled` option in `local.json` |
||||||
|
that makes registry actualization simpler for recipients and providers, as update details without `git pull`. |
||||||
|
|
||||||
|
``` |
||||||
|
[ |
||||||
|
{ |
||||||
|
"description": |
||||||
|
{ |
||||||
|
"name":"YGGtracker", // Used as storage subfolder |
||||||
|
"description":"YGGtracker official node", // Just provider description |
||||||
|
"url":"http://[201:23b4:991a:634d:8359:4521:5576:15b7]/yggtracker/" // Provider's website |
||||||
|
}, |
||||||
|
"ftp": |
||||||
|
{ |
||||||
|
"host":"201:23b4:991a:634d:8359:4521:5576:15b7", // Connection host |
||||||
|
"port":21, // Connection port |
||||||
|
"passive":true, // Recommended passive mode for better compatibility |
||||||
|
"username":"anonymous", // YGGtracker instances usually provides public FTP access |
||||||
|
"password":"anonymous", |
||||||
|
"directory":"/yggtracker/torrents/wanted" // Directory where wanted torrent files placed |
||||||
|
}, |
||||||
|
"provide": |
||||||
|
{ |
||||||
|
"approved":true // Tells to receiver that node administrator check the torrents before send to API |
||||||
|
} |
||||||
|
} |
||||||
|
], |
||||||
|
... |
||||||
|
``` |
||||||
|
|
||||||
|
#### Usage |
||||||
|
|
||||||
|
`php src/receiver.php` |
||||||
|
|
||||||
|
or add to crontab: |
||||||
|
|
||||||
|
`* * * * * /usr/bin/php src/receiver.php > /dev/null 2>&1` |
||||||
|
|
||||||
|
#### Bash, python? |
||||||
|
|
||||||
|
Feel free to contribute! |
||||||
|
|
||||||
|
#### Add new YGGtracker node |
||||||
|
|
||||||
|
Just send PR to nodes.json file |
||||||
|
|
||||||
|
#### Feedback |
||||||
|
|
||||||
|
Any questions and bug reports, please send to the [Issues](https://github.com/YGGverse/yggtracker-wanted-torrents-receiver/issues)! |
||||||
|
|
||||||
|
#### See also |
||||||
|
|
||||||
|
* [YGGtracker - BitTorrent Network for Yggdrasil](https://github.com/YGGverse/YGGtracker) |
||||||
|
* [YGGtracker Search Plugin for qBittorrent](https://github.com/YGGverse/qbittorrent-yggtracker-search-plugin) |
@ -0,0 +1,34 @@ |
|||||||
|
{ |
||||||
|
"import": |
||||||
|
{ |
||||||
|
"ftp": |
||||||
|
{ |
||||||
|
"timeout":5, |
||||||
|
"directories": |
||||||
|
[ |
||||||
|
"all" |
||||||
|
] |
||||||
|
}, |
||||||
|
"require": |
||||||
|
{ |
||||||
|
"approved":true |
||||||
|
}, |
||||||
|
"storage": |
||||||
|
{ |
||||||
|
"directory":"storage", |
||||||
|
"common":true |
||||||
|
} |
||||||
|
}, |
||||||
|
"update": |
||||||
|
{ |
||||||
|
"config": |
||||||
|
{ |
||||||
|
"remote": |
||||||
|
{ |
||||||
|
"enabled": true, |
||||||
|
"repository":"https://raw.githubusercontent.com/YGGverse/yggtracker-wanted-torrents-receiver/main/config/remote.json", |
||||||
|
"cache":86400 |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,23 @@ |
|||||||
|
[ |
||||||
|
{ |
||||||
|
"description": |
||||||
|
{ |
||||||
|
"name":"YGGtracker", |
||||||
|
"description":"YGGtracker official node", |
||||||
|
"url":"http://[201:23b4:991a:634d:8359:4521:5576:15b7]/yggtracker/" |
||||||
|
}, |
||||||
|
"ftp": |
||||||
|
{ |
||||||
|
"host":"201:23b4:991a:634d:8359:4521:5576:15b7", |
||||||
|
"port":21, |
||||||
|
"passive":true, |
||||||
|
"username":"anonymous", |
||||||
|
"password":"anonymous", |
||||||
|
"directory":"/yggtracker/torrents/wanted" |
||||||
|
}, |
||||||
|
"provide": |
||||||
|
{ |
||||||
|
"approved":true |
||||||
|
} |
||||||
|
} |
||||||
|
] |
@ -0,0 +1,122 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
// Init PHP |
||||||
|
declare(strict_types=1); |
||||||
|
|
||||||
|
ini_set('display_errors', 1); |
||||||
|
ini_set('display_startup_errors', 1); |
||||||
|
error_reporting(E_ALL); |
||||||
|
|
||||||
|
// Prevent multi-thread execution |
||||||
|
$semaphore = sem_get(crc32('yggtracker-wanted-torrents-receiver'), 1); |
||||||
|
|
||||||
|
if (false === sem_acquire($semaphore, true)) |
||||||
|
{ |
||||||
|
exit; |
||||||
|
} |
||||||
|
|
||||||
|
// Init local config |
||||||
|
$local = json_decode( |
||||||
|
file_get_contents(__DIR__ . '/../config/local.json') |
||||||
|
); |
||||||
|
|
||||||
|
// Init remote config |
||||||
|
if ($local->update->config->remote->enabled) |
||||||
|
{ |
||||||
|
// Reset remote config cache |
||||||
|
if ($local->update->config->remote->cache + (int) filectime(__DIR__ . '/../config/remote.json') < time()) |
||||||
|
{ |
||||||
|
// Cache results |
||||||
|
if ($result = @file_get_contents($local->update->config->remote->repository)) |
||||||
|
{ |
||||||
|
file_put_contents( |
||||||
|
__DIR__ . '/../config/remote.json', |
||||||
|
$result |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Sync remotes |
||||||
|
foreach ( |
||||||
|
json_decode( |
||||||
|
file_get_contents(__DIR__ . '/../config/remote.json') |
||||||
|
) as $remote) |
||||||
|
{ |
||||||
|
// Apply approved filters |
||||||
|
if ($local->import->require->approved && !$remote->provide->approved) |
||||||
|
{ |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
// Connect remote |
||||||
|
if (!$connection = ftp_connect($remote->ftp->host, $remote->ftp->port, $local->import->ftp->timeout)) |
||||||
|
{ |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
// Login |
||||||
|
if (!ftp_login($connection, $remote->ftp->username, $remote->ftp->password)) |
||||||
|
{ |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
// Apply passive mode if required |
||||||
|
if (!ftp_pasv($connection, $remote->ftp->passive)) |
||||||
|
{ |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
// Navigate to wanted directory |
||||||
|
if (!ftp_chdir($connection, $remote->ftp->directory)) |
||||||
|
{ |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
// Scan directories |
||||||
|
foreach ($local->import->ftp->directories as $directory) |
||||||
|
{ |
||||||
|
// Get torrents |
||||||
|
foreach (ftp_nlist($connection, $directory) as $torrent) |
||||||
|
{ |
||||||
|
// Init provider directory |
||||||
|
@mkdir( |
||||||
|
$local->import->storage->directory . '/' . $remote->description->name . '/' . $directory, |
||||||
|
0755, |
||||||
|
true |
||||||
|
); |
||||||
|
|
||||||
|
// Save torrents |
||||||
|
ftp_get( |
||||||
|
$connection, |
||||||
|
$local->import->storage->directory . '/' . $remote->description->name . '/' . $torrent, |
||||||
|
$torrent |
||||||
|
); |
||||||
|
|
||||||
|
// Common storage mode enabled |
||||||
|
if ($local->import->storage->common) |
||||||
|
{ |
||||||
|
// Init common folder |
||||||
|
@mkdir( |
||||||
|
$local->import->storage->directory . '/_common', |
||||||
|
0755, |
||||||
|
true |
||||||
|
); |
||||||
|
|
||||||
|
// Prevent same file duplicates from different providers |
||||||
|
$hash = md5_file( |
||||||
|
$local->import->storage->directory . '/' . $remote->description->name . '/' . $torrent |
||||||
|
); |
||||||
|
|
||||||
|
// Copy torrent file into the common directory if not exists yet |
||||||
|
if (!file_exists($local->import->storage->directory . '/_common/' . $hash . '.torrent')) |
||||||
|
{ |
||||||
|
copy( |
||||||
|
$local->import->storage->directory . '/' . $remote->description->name . '/' . $torrent, |
||||||
|
$local->import->storage->directory . '/_common/' . $hash . '.torrent' |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue