parent
7f742418b6
commit
1c87cf88d3
@ -0,0 +1,13 @@
|
||||
# qbittorrent-clener
|
||||
|
||||
Super basic PHP script which gets all torrents + files associated.
|
||||
It will then list the untracked files (usually extracted files) and ask if you wish to delete them.
|
||||
|
||||
```
|
||||
$ php clean.php "<qbittorrent host>" "<username>" "<password>" "<download path>"
|
||||
```
|
||||
|
||||
For example:
|
||||
```
|
||||
$ php clean.php "http://127.0.0.1:8080" "bob" "super_secure_password" "/home/bob/Downloads"
|
||||
```
|
@ -0,0 +1,144 @@
|
||||
<?php
|
||||
|
||||
// USAGE
|
||||
// php clean.php <webID1> <user2> <pass3> <directory to clear4>
|
||||
|
||||
global $host, $cookies;
|
||||
$host = $argv[1] ?? '';
|
||||
|
||||
echo 'Querying ' . $host . ' for torrents' . PHP_EOL;
|
||||
|
||||
function login($argv): bool {
|
||||
global $host, $cookies;
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $host . '/api/v2/auth/login');
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_HEADER, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(['username' => $argv[2], 'password' => $argv[3]]));
|
||||
$output = curl_exec($ch);
|
||||
|
||||
preg_match_all('/^Set-Cookie:\s*([^;]*)/mi', $output, $matches);
|
||||
curl_close($ch);
|
||||
|
||||
$cooks = [];
|
||||
foreach($matches[1] as $item) {
|
||||
parse_str($item, $cookie);
|
||||
$cooks = array_merge($cooks, $cookie);
|
||||
}
|
||||
|
||||
$cookies = '';
|
||||
foreach ($cooks as $key => $val) {
|
||||
$cookies = $key . '=' . $val;
|
||||
break;
|
||||
}
|
||||
|
||||
return !empty($cookies);
|
||||
}
|
||||
|
||||
function sendGetRequest(string $endpoint): string
|
||||
{
|
||||
global $host, $cookies;
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $host . $endpoint);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Cookie: ' . $cookies]);
|
||||
|
||||
$output = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
function getDirContents($dir): array
|
||||
{
|
||||
$rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));
|
||||
|
||||
$files = [];
|
||||
foreach ($rii as $file) {
|
||||
if ($file->isDir()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$files[] = $file->getPathname();
|
||||
}
|
||||
|
||||
return $files;
|
||||
}
|
||||
|
||||
/**
|
||||
* START LOGIC!
|
||||
*/
|
||||
|
||||
// Get login cookie
|
||||
login($argv);
|
||||
|
||||
// Get torrent list
|
||||
$responseRaw = sendGetRequest('/api/v2/sync/maindata?rid=0');
|
||||
$i = 0;
|
||||
|
||||
// Sometimes for some dumb reason the cookie it returns gives us a 'Forbidden'
|
||||
// So lets just relog and try again
|
||||
while ($responseRaw === 'Forbidden') {
|
||||
echo $responseRaw . '... Trying again' . PHP_EOL;
|
||||
sleep(1);
|
||||
$i++;
|
||||
if ($i >= 5) {
|
||||
echo '5 failed attempts.. dying.' . PHP_EOL;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Try get new cookie?
|
||||
login($argv);
|
||||
$responseRaw = sendGetRequest('/api/v2/sync/maindata?rid=0');
|
||||
}
|
||||
|
||||
$response = json_decode($responseRaw, true);
|
||||
if (empty($response['torrents'])) {
|
||||
echo 'Error fetching torrents? Dying' . PHP_EOL;
|
||||
echo $responseRaw;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$filesToKeep = [];
|
||||
foreach ($response['torrents'] as $hash => $torrent) {
|
||||
$rootPath = $torrent['save_path'];
|
||||
$filesRaw = sendGetRequest('/api/v2/torrents/files?hash=' . $hash);
|
||||
$files = json_decode($filesRaw, true);
|
||||
foreach ($files as $count => $file) {
|
||||
$filesToKeep[] = $rootPath . $file['name'];
|
||||
}
|
||||
}
|
||||
echo count($filesToKeep) . ' files found in qBitTorrent' . PHP_EOL;
|
||||
|
||||
$existingFiles = getDirContents($argv[4]);
|
||||
echo count($existingFiles) . ' files found in directory' . PHP_EOL;
|
||||
|
||||
$filesToDelete = [];
|
||||
foreach ($existingFiles as $existingFile) {
|
||||
if (!in_array($existingFile, $filesToKeep)) {
|
||||
$filesToDelete[] = $existingFile;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($filesToDelete)) {
|
||||
echo 'No files to remove \o/' . PHP_EOL;
|
||||
}
|
||||
|
||||
echo count($filesToDelete) . ' files to delete!' . PHP_EOL;
|
||||
echo print_r($filesToDelete) . PHP_EOL;
|
||||
|
||||
echo 'Press Y to confirm deletion:';
|
||||
$handle = fopen ('php://stdin','r');
|
||||
$line = fgets($handle);
|
||||
if(trim($line) != 'y'){
|
||||
echo 'ABORTING!' . PHP_EOL;
|
||||
exit(0);
|
||||
}
|
||||
fclose($handle);
|
||||
|
||||
foreach ($filesToDelete as $filePath) {
|
||||
unlink($filePath);
|
||||
}
|
||||
|
||||
echo 'Done!' . PHP_EOL;
|
Loading…
Reference in new issue