seria/src/Torrents/TorrentInfoRouting.php
2024-03-30 00:38:44 +00:00

190 lines
6.4 KiB
PHP

<?php
namespace Seria\Torrents;
use RuntimeException;
use Index\Http\Routing\{HttpGet,HttpMiddleware,HttpPost,RouteHandler};
use Index\Security\CSRFP;
use Sasae\SasaeEnvironment;
use Syokuhou\IConfig;
use Seria\Auth\AuthInfo;
use Seria\Users\UsersContext;
class TorrentInfoRouting extends RouteHandler {
private ?TorrentInfo $torrentInfo = null;
public function __construct(
private IConfig $config,
private AuthInfo $authInfo,
private TorrentsContext $torrentsCtx,
private UsersContext $usersCtx,
private CSRFP $csrfp,
private ?SasaeEnvironment $templating
) {}
#[HttpGet('/download/([0-9]+)')]
public function getDownload($response, $request, string $torrentId) {
try {
$torrentInfo = $this->torrentsCtx->getTorrents()->getTorrent($torrentId);
} catch(RuntimeException $ex) {
$response->setStatusCode(404);
return 'Download not found.';
}
$canDownload = $this->torrentsCtx->canDownloadTorrent($torrentInfo, $this->authInfo->getUserInfo());
if($canDownload !== '') {
$response->setStatusCode(403);
return match($canDownload) {
'inactive' => 'This download is inactive.',
'private' => 'You must be logged in for this download.',
'pending' => 'This download is pending approval.',
default => $canDownload,
};
}
$trackerUrl = '';
if($this->authInfo->isLoggedIn()) {
$userInfo = $this->authInfo->getUserInfo();
$passKey = $userInfo->hasPassKey()
? $userInfo->getPassKey()
: $this->usersCtx->getUsers()->updatePassKey($userInfo);
$trackerUrl = sprintf($this->config->getString('url:user'), $passKey);
} else
$trackerUrl = $this->config->getString('url:anon');
$response->setContentType('application/x-bittorrent');
$response->setFileName(htmlspecialchars($torrentInfo->getName()) . '.torrent');
return $this->torrentsCtx->encodeTorrent($torrentInfo, $trackerUrl);
}
private function getTorrentInfo(string $torrentId): int {
if($this->torrentInfo?->getId() === $torrentId)
return 0;
try {
$this->torrentInfo = $this->torrentsCtx->getTorrents()->getTorrent($torrentId);
} catch(RuntimeException $ex) {
return 404;
}
$canDownload = $this->torrentsCtx->canDownloadTorrent($this->torrentInfo, $this->authInfo->getUserInfo());
if($canDownload !== '')
return 403;
return 0;
}
#[HttpGet('/info/([0-9]+)')]
public function getInfo($response, $request, string $torrentId) {
$error = $this->getTorrentInfo($torrentId);
if($error > 0) return $error;
if($this->torrentInfo->hasUser()) {
$users = $this->usersCtx->getUsers();
$userInfo = $users->getUser($this->torrentInfo->getUserId(), 'id');
} else $userInfo = null;
$peers = $this->torrentsCtx->getPeers();
$completePeers = $peers->countCompletePeers($this->torrentInfo);
$incompletePeers = $peers->countIncompletePeers($this->torrentInfo);
$files = $this->torrentsCtx->getFiles();
$totalFileSize = $files->countTotalSize($this->torrentInfo);
$fileList = $files->getFiles($this->torrentInfo);
return $this->templating->render('info', [
'torrent_info' => $this->torrentInfo,
'torrent_user' => $userInfo,
'torrent_total_size' => $totalFileSize,
'torrent_complete_peers' => $completePeers,
'torrent_incomplete_peers' => $incompletePeers,
'torrent_files' => $fileList,
]);
}
#[HttpMiddleware('/info/([0-9]+)/rehash')]
#[HttpMiddleware('/info/([0-9]+)/approve')]
#[HttpMiddleware('/info/([0-9]+)/deny')]
public function verifyRequest($response, $request, string $torrentId) {
if(!$this->authInfo->isLoggedIn())
return 401;
if(!$request->isFormContent())
return 400;
$content = $request->getContent();
if(!$this->csrfp->verifyToken((string)$content->getParam('_csrfp')))
return 403;
$error = $this->getTorrentInfo($torrentId);
if($error > 0) return $error;
}
#[HttpPost('/info/([0-9]+)/rehash')]
public function postRehash($response, $request, string $torrentId) {
$error = $this->getTorrentInfo($torrentId);
if($error > 0) return $error;
if(!$this->authInfo->getUserInfo()->canRecalculateInfoHash())
return 403;
$builder = TorrentBuilder::import(
$this->torrentInfo,
$this->torrentsCtx->getPieces()->getPieces($this->torrentInfo),
$this->torrentsCtx->getFiles()->getFiles($this->torrentInfo)
);
$infoHash = $builder->calculateInfoHash();
$this->torrentsCtx->getTorrents()->updateTorrentInfoHash($this->torrentInfo, $infoHash);
return [
'hash' => base64_encode($infoHash),
];
}
#[HttpPost('/info/([0-9]+)/approve')]
public function postApprove($response, $request, string $torrentId) {
$error = $this->getTorrentInfo($torrentId);
if($error > 0) return $error;
if(!$this->authInfo->getUserInfo()->canApproveTorrents())
return 403;
$this->torrentsCtx->getTorrents()->approveTorrent($this->torrentInfo);
return 204;
}
#[HttpPost('/info/([0-9]+)/deny')]
public function postDeny($response, $request, string $torrentId) {
$error = $this->getTorrentInfo($torrentId);
if($error > 0) return $error;
if(!$this->authInfo->getUserInfo()->canApproveTorrents())
return 403;
$this->torrentsCtx->getTorrents()->deleteTorrent($this->torrentInfo);
return 204;
}
#[HttpGet('/info.php')]
public function getInfoPHP($response, $request) {
$torrentId = (int)$request->getParam('id', FILTER_SANITIZE_NUMBER_INT);
if($torrentId < 1)
return 404;
$response->redirect(sprintf('/info/%d', $torrentId), true);
}
#[HttpGet('/download.php')]
public function getDownloadPHP($response, $request) {
$torrentId = (int)$request->getParam('id', FILTER_SANITIZE_NUMBER_INT);
if($torrentId < 1)
return 404;
$response->redirect(sprintf('/download/%d', $torrentId), true);
}
}