From 8ab4c0b9cfd1b3d6a16dd473fad9b1467f2cb2c3 Mon Sep 17 00:00:00 2001 From: ghost Date: Tue, 10 Oct 2023 04:07:59 +0300 Subject: [PATCH] implement torrent search features --- src/Controller/SearchController.php | 131 +++++++++++++++++-- src/Entity/Torrent.php | 2 + src/Repository/TorrentRepository.php | 17 +++ src/Service/TorrentService.php | 13 +- templates/default/search/index.html.twig | 2 - templates/default/search/module.html.twig | 2 +- templates/default/search/torrent.html.twig | 138 +++++++++++++++++++++ 7 files changed, 293 insertions(+), 12 deletions(-) delete mode 100644 templates/default/search/index.html.twig create mode 100644 templates/default/search/torrent.html.twig diff --git a/src/Controller/SearchController.php b/src/Controller/SearchController.php index 7fea8a6..46ef48f 100644 --- a/src/Controller/SearchController.php +++ b/src/Controller/SearchController.php @@ -3,29 +3,146 @@ namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; + use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Request; +use App\Service\UserService; +use App\Service\PageService; +use App\Service\TorrentService; + class SearchController extends AbstractController { #[Route( '/{_locale}/search', - name: 'search_index' + name: 'search_index', + methods: + [ + 'GET' + ] )] - public function index(Request $request): Response + public function index( + Request $request, + UserService $userService, + PageService $pageService, + TorrentService $torrentService + ): Response { - $query = $request->query->get('query'); + // Init user + $user = $userService->init( + $request->getClientIp() + ); - return $this->render('default/search/index.html.twig', [ - 'query' => $query - ]); + $page = $request->query->get('page') ? (int) $request->query->get('page') : 1; + + switch ($request->query->get('type')) + { + case 'page': + + break; + case 'torrent': + + $torrents = []; + foreach ($torrentService->searchTorrents($request->query->get('query')) as $torrent) + { + // Read file + if (!$file = $torrentService->readTorrentFileByTorrentId($torrent->getId())) + { + continue; // @TODO + } + + // Generate keywords + $keywords = []; + $query = explode(' ', mb_strtolower($request->query->get('query'))); + foreach (explode(',', $torrent->getKeywords()) as $keyword) + { + if (in_array($keyword, $query)) + { + $keywords[] = urlencode($keyword); + } + } + + $torrents[] = + [ + 'id' => $torrent->getId(), + 'added' => $torrent->getAdded(), + 'file' => + [ + 'name' => $file->getName(), + 'size' => $file->getSize(), + ], + 'scrape' => + [ + 'seeders' => (int) $torrent->getSeeders(), + 'peers' => (int) $torrent->getPeers(), + 'leechers' => (int) $torrent->getLeechers(), + ], + 'user' => + [ + 'id' => $torrent->getUserId(), + 'identicon' => $userService->identicon( + $userService->getUser( + $torrent->getUserId() + )->getAddress() + ) + ], + 'keywords' => $keywords, + 'download' => + [ + 'file' => + [ + 'exist' => (bool) $torrentService->findTorrentDownloadFile( + $torrent->getId(), + $user->getId() + ), + 'total' => $torrentService->findTorrentDownloadFilesTotalByTorrentId( + $torrent->getId() + ) + ], + 'magnet' => + [ + 'exist' => (bool) $torrentService->findTorrentDownloadMagnet( + $torrent->getId(), + $user->getId() + ), + 'total' => $torrentService->findTorrentDownloadMagnetsTotalByTorrentId( + $torrent->getId() + ) + ] + ], + 'star' => + [ + 'exist' => (bool) $torrentService->findTorrentStar( + $torrent->getId(), + $user->getId() + ), + 'total' => $torrentService->findTorrentStarsTotalByTorrentId( + $torrent->getId() + ) + ], + ]; + } + + return $this->render('default/search/torrent.html.twig', [ + 'query' => $request->query->get('query'), + 'torrents' => $torrents + ]); + + break; + default: + throw $this->createNotFoundException(); + } } - public function module(string $query = ''): Response + public function module( + ?string $query, + ?string $type + ): Response { return $this->render('default/search/module.html.twig', [ 'query' => $query, + 'type' => $type, ]); } } \ No newline at end of file diff --git a/src/Entity/Torrent.php b/src/Entity/Torrent.php index d551b08..aba75a0 100644 --- a/src/Entity/Torrent.php +++ b/src/Entity/Torrent.php @@ -6,7 +6,9 @@ use App\Repository\TorrentRepository; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; +// @TODO #[ORM\Index(columns: ['keywords'], name: 'keywords_idx', flags: ['fulltext'])] #[ORM\Entity(repositoryClass: TorrentRepository::class)] + class Torrent { #[ORM\Id] diff --git a/src/Repository/TorrentRepository.php b/src/Repository/TorrentRepository.php index 53b6358..0df9bf5 100644 --- a/src/Repository/TorrentRepository.php +++ b/src/Repository/TorrentRepository.php @@ -20,4 +20,21 @@ class TorrentRepository extends ServiceEntityRepository { parent::__construct($registry, Torrent::class); } + + public function searchByKeywords( + array $keywords + ): ?array + { + $query = $this->createQueryBuilder('t'); + + foreach ($keywords as $keyword) + { + $query->orWhere('t.keywords LIKE :query') + ->setParameter('query', "%{$keyword}%"); + } + + return $query->orderBy('t.id', 'ASC') // same as t.added + ->getQuery() + ->getResult(); + } } diff --git a/src/Service/TorrentService.php b/src/Service/TorrentService.php index 32f300c..17d3457 100644 --- a/src/Service/TorrentService.php +++ b/src/Service/TorrentService.php @@ -246,11 +246,11 @@ class TorrentService } // Torrent - public function getTorrent(int $id): ?Torrent + public function getTorrent(int $torrentId): ?Torrent { return $this->entityManagerInterface ->getRepository(Torrent::class) - ->find($id); + ->find($torrentId); } public function addTorrent( @@ -285,6 +285,15 @@ class TorrentService ); } + public function searchTorrents(string $query) : array + { + return $this->entityManagerInterface + ->getRepository(Torrent::class) + ->searchByKeywords( + explode(' ', $query) + ); + } + public function setTorrentsApprovedByUserId( int $userId, bool $value diff --git a/templates/default/search/index.html.twig b/templates/default/search/index.html.twig deleted file mode 100644 index 61d0da3..0000000 --- a/templates/default/search/index.html.twig +++ /dev/null @@ -1,2 +0,0 @@ -{% extends 'default/layout.html.twig' %} -{% block title %}{{ query }} - {{'Search'|trans }} - {{ name }}{% endblock %} \ No newline at end of file diff --git a/templates/default/search/module.html.twig b/templates/default/search/module.html.twig index 706cc51..bf11a50 100644 --- a/templates/default/search/module.html.twig +++ b/templates/default/search/module.html.twig @@ -12,5 +12,5 @@ {% endif %} - + \ No newline at end of file diff --git a/templates/default/search/torrent.html.twig b/templates/default/search/torrent.html.twig new file mode 100644 index 0000000..ff54cb9 --- /dev/null +++ b/templates/default/search/torrent.html.twig @@ -0,0 +1,138 @@ +{% extends 'default/layout.html.twig' %} +{% block title %}{% if query %}{{ query }}{% else %}{{ 'New' | trans }}{% endif %} - {{ 'Torrents' | trans }} - {{ name }}{% endblock %} +{% block main_content %} + {% if torrents %} + {% for torrent in torrents %} +
+ +
+

+ + {{ torrent.file.name }} + +

+ {% if torrent.scrape.leechers == 0 and torrent.scrape.leechers == 0 %} + + {{ 'wanted' | trans }} + + {% endif %} +
+ {% if torrent.keywords %} +
+ {% for keyword in torrent.keywords %} + + #{{ keyword }} + + {% endfor %} +
+ {% endif %} +
+ {# + + {{ torrent.added | format_ago }} + {{ 'by' | trans }} + + {{ 'identicon' | trans }} + + + #} + + + {{ torrent.file.size | format_bytes }} + + + + + + + + {{ torrent.scrape.seeders }} + + + + + + + + {{ torrent.scrape.peers }} + + + + + + + + + {{ torrent.scrape.leechers }} + + + +
+ {% endfor %} + {% else %} +
+
+

+ {{ 'Nothing found' | trans }} +

+
+ {{ '* share new torrent file to change it' | trans }} +
+
+ +
+
+
+ {% endif %} +{% endblock %} \ No newline at end of file