Browse Source

implement torrent/magnet download feature

main
ghost 1 year ago
parent
commit
62ad522286
  1. 300
      src/Controller/TorrentController.php
  2. 72
      src/Entity/TorrentDownloadFile.php
  3. 72
      src/Entity/TorrentDownloadMagnet.php
  4. 53
      src/Repository/TorrentDownloadFileRepository.php
  5. 53
      src/Repository/TorrentDownloadMagnetRepository.php
  6. 357
      src/Service/TorrentService.php
  7. 40
      templates/default/torrent/info.html.twig

300
src/Controller/TorrentController.php

@ -59,15 +59,38 @@ class TorrentController extends AbstractController @@ -59,15 +59,38 @@ class TorrentController extends AbstractController
'added' => $torrent->getAdded(),
'locales' => $torrentService->findLastTorrentLocales($torrent->getId()),
'sensitive' => $torrentService->findLastTorrentSensitive($torrent->getId())->isValue(),
'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()
)
]
],
'bookmark' =>
[
'active' => (bool) $torrentService->findTorrentBookmark(
'exist' => (bool) $torrentService->findTorrentBookmark(
$torrent->getId(),
$user->getId()
),
'total' => $torrentService->findTorrentBookmarksTotalByTorrentId(
$torrent->getId()
),
)
],
'pages' => []
],
@ -235,62 +258,6 @@ class TorrentController extends AbstractController @@ -235,62 +258,6 @@ class TorrentController extends AbstractController
);
}
// Torrent bookmark
#[Route(
'/{_locale}/torrent/{torrentId}/bookmark/toggle',
name: 'torrent_bookmark_toggle',
requirements:
[
'torrentId' => '\d+',
],
methods:
[
'GET'
]
)]
public function toggleBookmark(
Request $request,
TranslatorInterface $translator,
UserService $userService,
TorrentService $torrentService
): Response
{
// Init user
$user = $userService->init(
$request->getClientIp()
);
if (!$user->isStatus())
{
// @TODO
throw new \Exception(
$translator->trans('Access denied')
);
}
// Init torrent
if (!$torrent = $torrentService->getTorrent($request->get('torrentId')))
{
throw $this->createNotFoundException();
}
// Update
$torrentService->toggleTorrentBookmark(
$torrent->getId(),
$user->getId(),
time()
);
// Redirect to info page created
return $this->redirectToRoute(
'torrent_info',
[
'_locale' => $request->get('_locale'),
'torrentId' => $torrent->getId()
]
);
}
// Torrent locales
#[Route(
'/{_locale}/torrent/{torrentId}/edit/locales/{torrentLocalesId}',
@ -888,4 +855,221 @@ class TorrentController extends AbstractController @@ -888,4 +855,221 @@ class TorrentController extends AbstractController
]
);
}
// Torrent bookmark
#[Route(
'/{_locale}/torrent/{torrentId}/bookmark/toggle',
name: 'torrent_bookmark_toggle',
requirements:
[
'torrentId' => '\d+',
],
methods:
[
'GET'
]
)]
public function toggleBookmark(
Request $request,
TranslatorInterface $translator,
UserService $userService,
TorrentService $torrentService
): Response
{
// Init user
$user = $userService->init(
$request->getClientIp()
);
if (!$user->isStatus())
{
// @TODO
throw new \Exception(
$translator->trans('Access denied')
);
}
// Init torrent
if (!$torrent = $torrentService->getTorrent($request->get('torrentId')))
{
throw $this->createNotFoundException();
}
// Update
$torrentService->toggleTorrentBookmark(
$torrent->getId(),
$user->getId(),
time()
);
// Redirect to info page created
return $this->redirectToRoute(
'torrent_info',
[
'_locale' => $request->get('_locale'),
'torrentId' => $torrent->getId()
]
);
}
// Torrent download file
#[Route(
'/{_locale}/torrent/{torrentId}/download/file',
name: 'torrent_download_file',
requirements:
[
'torrentId' => '\d+',
],
methods:
[
'GET'
]
)]
public function downloadFile(
Request $request,
TranslatorInterface $translator,
UserService $userService,
TorrentService $torrentService
): Response
{
// Init user
$user = $userService->init(
$request->getClientIp()
);
if (!$user->isStatus())
{
// @TODO
throw new \Exception(
$translator->trans('Access denied')
);
}
// Init torrent
if (!$torrent = $torrentService->getTorrent($request->get('torrentId')))
{
throw $this->createNotFoundException();
}
if (!$file = $torrentService->readTorrentFileByTorrentId($torrent->getId()))
{
// @TODO
throw new \Exception(
$translator->trans('File not found')
);
}
// Register download
$torrentService->registerTorrentDownloadFile(
$torrent->getId(),
$user->getId(),
time()
);
// Filter trackers
$file->setAnnounceList(
[
explode('|', $this->getParameter('app.trackers'))
]
);
$data = $file->dumpToString();
// Set headers
$response = new Response();
$response->headers->set(
'Content-type',
'application/x-bittorrent'
);
$response->headers->set(
'Content-length',
strlen($data)
);
$response->headers->set(
'Content-Disposition',
sprintf(
'attachment; filename="%s.%s.%s.torrent";',
$this->getParameter('app.name'),
$torrent->getId(),
mb_strtolower(
$file->getName()
)
)
);
$response->sendHeaders();
// Return file content
return $response->setContent($data);
}
// Torrent download magnet
#[Route(
'/{_locale}/torrent/{torrentId}/download/magnet',
name: 'torrent_download_magnet',
requirements:
[
'torrentId' => '\d+',
],
methods:
[
'GET'
]
)]
public function getMagnet(
Request $request,
TranslatorInterface $translator,
UserService $userService,
TorrentService $torrentService
): Response
{
// Init user
$user = $userService->init(
$request->getClientIp()
);
if (!$user->isStatus())
{
// @TODO
throw new \Exception(
$translator->trans('Access denied')
);
}
// Init torrent
if (!$torrent = $torrentService->getTorrent($request->get('torrentId')))
{
throw $this->createNotFoundException();
}
if (!$file = $torrentService->readTorrentFileByTorrentId($torrent->getId()))
{
// @TODO
throw new \Exception(
$translator->trans('File not found')
);
}
// Register download
$torrentService->registerTorrentDownloadMagnet(
$torrent->getId(),
$user->getId(),
time()
);
// Filter trackers
$file->setAnnounceList(
[
explode('|', $this->getParameter('app.trackers'))
]
);
// Return magnet link
return $this->redirect(
$file->getMagnetLink()
);
}
}

72
src/Entity/TorrentDownloadFile.php

@ -0,0 +1,72 @@ @@ -0,0 +1,72 @@
<?php
namespace App\Entity;
use App\Repository\TorrentDownloadFileRepository;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: TorrentDownloadFileRepository::class)]
class TorrentDownloadFile
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column]
private ?int $torrentId = null;
#[ORM\Column]
private ?int $userId = null;
#[ORM\Column]
private ?int $added = null;
public function getId(): ?int
{
return $this->id;
}
public function setId(string $id): static
{
$this->id = $id;
return $this;
}
public function getTorrentId(): ?int
{
return $this->torrentId;
}
public function setTorrentId(int $torrentId): static
{
$this->torrentId = $torrentId;
return $this;
}
public function getUserId(): ?int
{
return $this->userId;
}
public function setUserId(int $userId): static
{
$this->userId = $userId;
return $this;
}
public function getAdded(): ?int
{
return $this->added;
}
public function setAdded(int $added): static
{
$this->added = $added;
return $this;
}
}

72
src/Entity/TorrentDownloadMagnet.php

@ -0,0 +1,72 @@ @@ -0,0 +1,72 @@
<?php
namespace App\Entity;
use App\Repository\TorrentDownloadMagnetRepository;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: TorrentDownloadMagnetRepository::class)]
class TorrentDownloadMagnet
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column]
private ?int $torrentId = null;
#[ORM\Column]
private ?int $userId = null;
#[ORM\Column]
private ?int $added = null;
public function getId(): ?int
{
return $this->id;
}
public function setId(string $id): static
{
$this->id = $id;
return $this;
}
public function getTorrentId(): ?int
{
return $this->torrentId;
}
public function setTorrentId(int $torrentId): static
{
$this->torrentId = $torrentId;
return $this;
}
public function getUserId(): ?int
{
return $this->userId;
}
public function setUserId(int $userId): static
{
$this->userId = $userId;
return $this;
}
public function getAdded(): ?int
{
return $this->added;
}
public function setAdded(int $added): static
{
$this->added = $added;
return $this;
}
}

53
src/Repository/TorrentDownloadFileRepository.php

@ -0,0 +1,53 @@ @@ -0,0 +1,53 @@
<?php
namespace App\Repository;
use App\Entity\TorrentDownloadFile;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<TorrentDownloadFile>
*
* @method TorrentDownloadFile|null find($id, $lockMode = null, $lockVersion = null)
* @method TorrentDownloadFile|null findOneBy(array $criteria, array $orderBy = null)
* @method TorrentDownloadFile[] findAll()
* @method TorrentDownloadFile[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class TorrentDownloadFileRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, TorrentDownloadFile::class);
}
public function findTorrentDownloadFile(
int $torrentId,
int $userId
): ?TorrentDownloadFile
{
return $this->createQueryBuilder('tdf')
->where('tdf.torrentId = :torrentId')
->andWhere('tdf.userId = :userId')
->setParameter('torrentId', $torrentId)
->setParameter('userId', $userId)
->orderBy('tdf.id', 'DESC') // same to ts.added
->setMaxResults(1)
->getQuery()
->getOneOrNullResult()
;
}
public function findTorrentDownloadFilesTotalByTorrentId(
int $torrentId
): int
{
return $this->createQueryBuilder('tdf')
->select('count(tdf.id)')
->where('tdf.torrentId = :torrentId')
->setParameter('torrentId', $torrentId)
->getQuery()
->getSingleScalarResult()
;
}
}

53
src/Repository/TorrentDownloadMagnetRepository.php

@ -0,0 +1,53 @@ @@ -0,0 +1,53 @@
<?php
namespace App\Repository;
use App\Entity\TorrentDownloadMagnet;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<TorrentDownloadMagnet>
*
* @method TorrentDownloadMagnet|null find($id, $lockMode = null, $lockVersion = null)
* @method TorrentDownloadMagnet|null findOneBy(array $criteria, array $orderBy = null)
* @method TorrentDownloadMagnet[] findAll()
* @method TorrentDownloadMagnet[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class TorrentDownloadMagnetRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, TorrentDownloadMagnet::class);
}
public function findTorrentDownloadMagnet(
int $torrentId,
int $userId
): ?TorrentDownloadMagnet
{
return $this->createQueryBuilder('tdm')
->where('tdm.torrentId = :torrentId')
->andWhere('tdm.userId = :userId')
->setParameter('torrentId', $torrentId)
->setParameter('userId', $userId)
->orderBy('tdm.id', 'DESC') // same to ts.added
->setMaxResults(1)
->getQuery()
->getOneOrNullResult()
;
}
public function findTorrentDownloadMagnetsTotalByTorrentId(
int $torrentId
): int
{
return $this->createQueryBuilder('tdm')
->select('count(tdm.id)')
->where('tdm.torrentId = :torrentId')
->setParameter('torrentId', $torrentId)
->getQuery()
->getSingleScalarResult()
;
}
}

357
src/Service/TorrentService.php

@ -6,11 +6,15 @@ use App\Entity\Torrent; @@ -6,11 +6,15 @@ use App\Entity\Torrent;
use App\Entity\TorrentLocales;
use App\Entity\TorrentSensitive;
use App\Entity\TorrentBookmark;
use App\Entity\TorrentDownloadFile;
use App\Entity\TorrentDownloadMagnet;
use App\Repository\TorrentRepository;
use App\Repository\TorrentLocalesRepository;
use App\Repository\TorrentSensitiveRepository;
use App\Repository\TorrentBookmarkRepository;
use App\Repository\TorrentDownloadFileRepository;
use App\Repository\TorrentDownloadMagnetRepository;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Filesystem\Filesystem;
@ -108,7 +112,55 @@ class TorrentService @@ -108,7 +112,55 @@ class TorrentService
);
}
// Getters
public function add(
string $filepath,
int $userId,
int $added,
array $locales,
bool $sensitive,
bool $approved
): ?Torrent
{
$torrent = $this->addTorrent(
$userId,
$added,
$this->generateTorrentKeywordsByTorrentFilepath(
$filepath
),
$approved
);
$filesystem = new Filesystem();
$filesystem->copy(
$filepath,
$this->getStorageFilepathById(
$torrent->getId()
)
);
if (!empty($locales))
{
$this->addTorrentLocales(
$torrent->getId(),
$userId,
$added,
$locales,
$approved
);
}
$this->addTorrentSensitive(
$torrent->getId(),
$userId,
$added,
$sensitive,
$approved
);
return $torrent;
}
// Torrent
public function getTorrent(int $id): ?Torrent
{
return $this->entityManagerInterface
@ -116,7 +168,27 @@ class TorrentService @@ -116,7 +168,27 @@ class TorrentService
->findOneByIdField($id);
}
/// Locales
public function addTorrent(
int $userId,
int $added,
string $keywords,
bool $approved
): ?Torrent
{
$torrent = new Torrent();
$torrent->setUserId($userId);
$torrent->setAdded($added);
$torrent->setKeywords($keywords);
$torrent->setApproved($approved);
$this->entityManagerInterface->persist($torrent);
$this->entityManagerInterface->flush();
return $torrent;
}
// Torrent locale
public function getTorrentLocales(int $id): ?TorrentLocales
{
return $this->entityManagerInterface
@ -138,7 +210,57 @@ class TorrentService @@ -138,7 +210,57 @@ class TorrentService
->findTorrentLocales($torrentId);
}
/// Sensitive
public function toggleTorrentLocalesApproved(
int $id
): ?TorrentLocales
{
$torrentLocales = $this->getTorrentLocales($id);
$torrentLocales->setApproved(
!$torrentLocales->isApproved() // toggle current value
);
$this->entityManagerInterface->persist($torrentLocales);
$this->entityManagerInterface->flush();
return $torrentLocales;
}
public function deleteTorrentLocales(
int $id
): ?TorrentLocales
{
$torrentLocales = $this->getTorrentLocales($id);
$this->entityManagerInterface->remove($torrentLocales);
$this->entityManagerInterface->flush();
return $torrentLocales;
}
public function addTorrentLocales(
int $torrentId,
int $userId,
int $added,
array $value,
bool $approved
): ?TorrentLocales
{
$torrentLocales = new TorrentLocales();
$torrentLocales->setTorrentId($torrentId);
$torrentLocales->setUserId($userId);
$torrentLocales->setAdded($added);
$torrentLocales->setValue($value);
$torrentLocales->setApproved($approved);
$this->entityManagerInterface->persist($torrentLocales);
$this->entityManagerInterface->flush();
return $torrentLocales;
}
// Torrent sensitive
public function getTorrentSensitive(int $id): ?TorrentSensitive
{
return $this->entityManagerInterface
@ -160,68 +282,72 @@ class TorrentService @@ -160,68 +282,72 @@ class TorrentService
->findTorrentSensitive($torrentId);
}
/// Bookmark
public function findTorrentBookmark(
int $torrentId,
int $userId
): ?TorrentBookmark
{
return $this->entityManagerInterface
->getRepository(TorrentBookmark::class)
->findTorrentBookmark($torrentId, $userId);
}
public function findTorrentBookmarksTotalByTorrentId(int $torrentId): int
{
return $this->entityManagerInterface
->getRepository(TorrentBookmark::class)
->findTorrentBookmarksTotalByTorrentId($torrentId);
}
// Update
public function toggleTorrentLocalesApproved(
public function toggleTorrentSensitiveApproved(
int $id
): ?TorrentLocales
): ?TorrentSensitive
{
$torrentLocales = $this->getTorrentLocales($id);
$torrentSensitive = $this->getTorrentSensitive($id);
$torrentLocales->setApproved(
!$torrentLocales->isApproved() // toggle current value
$torrentSensitive->setApproved(
!$torrentSensitive->isApproved() // toggle current value
);
$this->entityManagerInterface->persist($torrentLocales);
$this->entityManagerInterface->persist($torrentSensitive);
$this->entityManagerInterface->flush();
return $torrentLocales;
return $torrentSensitive;
}
public function toggleTorrentSensitiveApproved(
public function deleteTorrentSensitive(
int $id
): ?TorrentSensitive
{
$torrentSensitive = $this->getTorrentSensitive($id);
$torrentSensitive->setApproved(
!$torrentSensitive->isApproved() // toggle current value
);
$this->entityManagerInterface->persist($torrentSensitive);
$this->entityManagerInterface->remove($torrentSensitive);
$this->entityManagerInterface->flush();
return $torrentSensitive;
}
// Delete
public function deleteTorrentLocales(
int $id
): ?TorrentLocales
public function addTorrentSensitive(
int $torrentId,
int $userId,
int $added,
bool $value,
bool $approved
): ?TorrentSensitive
{
$torrentLocales = $this->getTorrentLocales($id);
$torrentSensitive = new TorrentSensitive();
$this->entityManagerInterface->remove($torrentLocales);
$torrentSensitive->setTorrentId($torrentId);
$torrentSensitive->setUserId($userId);
$torrentSensitive->setAdded($added);
$torrentSensitive->setValue($value);
$torrentSensitive->setApproved($approved);
$this->entityManagerInterface->persist($torrentSensitive);
$this->entityManagerInterface->flush();
return $torrentLocales;
return $torrentSensitive;
}
// Torrent bookmark
public function findTorrentBookmark(
int $torrentId,
int $userId
): ?TorrentBookmark
{
return $this->entityManagerInterface
->getRepository(TorrentBookmark::class)
->findTorrentBookmark($torrentId, $userId);
}
public function findTorrentBookmarksTotalByTorrentId(int $torrentId): int
{
return $this->entityManagerInterface
->getRepository(TorrentBookmark::class)
->findTorrentBookmarksTotalByTorrentId($torrentId);
}
public function toggleTorrentBookmark(
@ -249,128 +375,77 @@ class TorrentService @@ -249,128 +375,77 @@ class TorrentService
}
}
public function deleteTorrentSensitive(
int $id
): ?TorrentSensitive
// Torrent download file
public function findTorrentDownloadFile(
int $torrentId,
int $userId
): ?TorrentDownloadFile
{
$torrentSensitive = $this->getTorrentSensitive($id);
$this->entityManagerInterface->remove($torrentSensitive);
$this->entityManagerInterface->flush();
return $torrentSensitive;
return $this->entityManagerInterface
->getRepository(TorrentDownloadFile::class)
->findTorrentDownloadFile($torrentId, $userId);
}
// Setters
public function add(
string $filepath,
int $userId,
int $added,
array $locales,
bool $sensitive,
bool $approved
): ?Torrent
{
$torrent = $this->addTorrent(
$userId,
$added,
$this->generateTorrentKeywordsByTorrentFilepath(
$filepath
),
$approved
);
$filesystem = new Filesystem();
$filesystem->copy(
$filepath,
$this->getStorageFilepathById(
$torrent->getId()
)
);
if (!empty($locales))
public function findTorrentDownloadFilesTotalByTorrentId(int $torrentId): int
{
$this->addTorrentLocales(
$torrent->getId(),
$userId,
$added,
$locales,
$approved
);
}
$this->addTorrentSensitive(
$torrent->getId(),
$userId,
$added,
$sensitive,
$approved
);
return $torrent;
return $this->entityManagerInterface
->getRepository(TorrentDownloadFile::class)
->findTorrentDownloadFilesTotalByTorrentId($torrentId);
}
public function addTorrent(
public function registerTorrentDownloadFile(
int $torrentId,
int $userId,
int $added,
string $keywords,
bool $approved
): ?Torrent
int $added
): void
{
$torrent = new Torrent();
if (!$this->findTorrentDownloadFile($torrentId, $userId))
{
$torrentDownloadFile = new TorrentDownloadFile();
$torrent->setUserId($userId);
$torrent->setAdded($added);
$torrent->setKeywords($keywords);
$torrent->setApproved($approved);
$torrentDownloadFile->setTorrentId($torrentId);
$torrentDownloadFile->setUserId($userId);
$torrentDownloadFile->setAdded($added);
$this->entityManagerInterface->persist($torrent);
$this->entityManagerInterface->persist($torrentDownloadFile);
$this->entityManagerInterface->flush();
return $torrent;
}
}
public function addTorrentLocales(
// Torrent download magnet
public function findTorrentDownloadMagnet(
int $torrentId,
int $userId,
int $added,
array $value,
bool $approved
): ?TorrentLocales
int $userId
): ?TorrentDownloadMagnet
{
$torrentLocales = new TorrentLocales();
$torrentLocales->setTorrentId($torrentId);
$torrentLocales->setUserId($userId);
$torrentLocales->setAdded($added);
$torrentLocales->setValue($value);
$torrentLocales->setApproved($approved);
$this->entityManagerInterface->persist($torrentLocales);
$this->entityManagerInterface->flush();
return $this->entityManagerInterface
->getRepository(TorrentDownloadMagnet::class)
->findTorrentDownloadMagnet($torrentId, $userId);
}
return $torrentLocales;
public function findTorrentDownloadMagnetsTotalByTorrentId(int $torrentId): int
{
return $this->entityManagerInterface
->getRepository(TorrentDownloadMagnet::class)
->findTorrentDownloadMagnetsTotalByTorrentId($torrentId);
}
public function addTorrentSensitive(
public function registerTorrentDownloadMagnet(
int $torrentId,
int $userId,
int $added,
bool $value,
bool $approved
): ?TorrentSensitive
int $added
): void
{
$torrentSensitive = new TorrentSensitive();
if (!$this->findTorrentDownloadMagnet($torrentId, $userId))
{
$torrentDownloadMagnet = new TorrentDownloadMagnet();
$torrentSensitive->setTorrentId($torrentId);
$torrentSensitive->setUserId($userId);
$torrentSensitive->setAdded($added);
$torrentSensitive->setValue($value);
$torrentSensitive->setApproved($approved);
$torrentDownloadMagnet->setTorrentId($torrentId);
$torrentDownloadMagnet->setUserId($userId);
$torrentDownloadMagnet->setAdded($added);
$this->entityManagerInterface->persist($torrentSensitive);
$this->entityManagerInterface->persist($torrentDownloadMagnet);
$this->entityManagerInterface->flush();
return $torrentSensitive;
}
}
}

40
templates/default/torrent/info.html.twig

@ -28,8 +28,36 @@ @@ -28,8 +28,36 @@
{{ 'Torrent'|trans }} #{{ torrent.id }}
</h1>
<div class="float-right ">
<a class="margin-x-4-px" href="{{ path('torrent_bookmark_toggle', {torrentId : torrent.id}) }}" title="{{ 'Bookmark'|trans }}">
{% if torrent.bookmark.active %}
<a class="margin-x-4-px" href="{{ path('torrent_download_magnet', {torrentId : torrent.id}) }}" title="{{ 'Open magnet link' | trans }}">
{% if torrent.download.magnet.exist %}
<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" fill="currentColor" viewBox="0 0 16 16">
<path d="M15 12h-4v3h4v-3ZM5 12H1v3h4v-3ZM0 8a8 8 0 1 1 16 0v8h-6V8a2 2 0 1 0-4 0v8H0V8Z"/>
</svg>
{% else %}
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
<path d="M8 1a7 7 0 0 0-7 7v3h4V8a3 3 0 0 1 6 0v3h4V8a7 7 0 0 0-7-7Zm7 11h-4v3h4v-3ZM5 12H1v3h4v-3ZM0 8a8 8 0 1 1 16 0v8h-6V8a2 2 0 1 0-4 0v8H0V8Z"/>
</svg>
{% endif %}
</a>
<sup class="cursor-default" title="{{ 'Total' | trans }}">
{{ torrent.download.magnet.total }}
</sup>
<a class="margin-x-4-px" href="{{ path('torrent_download_file', {torrentId : torrent.id}) }}" title="{{ 'Download torrent file' | trans }}">
{% if torrent.download.file.exist %}
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8.5 4.5a.5.5 0 0 0-1 0v5.793L5.354 8.146a.5.5 0 1 0-.708.708l3 3a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V4.5z"/>
</svg>
{% else %}
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M1 8a7 7 0 1 0 14 0A7 7 0 0 0 1 8zm15 0A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8.5 4.5a.5.5 0 0 0-1 0v5.793L5.354 8.146a.5.5 0 1 0-.708.708l3 3a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V4.5z"/>
</svg>
{% endif %}
</a>
<sup class="cursor-default" title="{{ 'Total' | trans }}">
{{ torrent.download.file.total }}
</sup>
<a class="margin-x-4-px" href="{{ path('torrent_bookmark_toggle', {torrentId : torrent.id}) }}" title="{{ 'Bookmark' | trans }}">
{% if torrent.bookmark.exist %}
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
<path d="M3.612 15.443c-.386.198-.824-.149-.746-.592l.83-4.73L.173 6.765c-.329-.314-.158-.888.283-.95l4.898-.696L7.538.792c.197-.39.73-.39.927 0l2.184 4.327 4.898.696c.441.062.612.636.282.95l-3.522 3.356.83 4.73c.078.443-.36.79-.746.592L8 13.187l-4.389 2.256z"/>
</svg>
@ -39,16 +67,12 @@ @@ -39,16 +67,12 @@
</svg>
{% endif %}
</a>
<sup>
<sup class="cursor-default" title="{{ 'Total' | trans }}">
{{ torrent.bookmark.total }}
</sup>
</div>
{#
<a class="float-right margin-l-8-px" href="#" title="{{ 'Torrent'|trans }}">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M1 8a7 7 0 1 0 14 0A7 7 0 0 0 1 8zm15 0A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8.5 4.5a.5.5 0 0 0-1 0v5.793L5.354 8.146a.5.5 0 1 0-.708.708l3 3a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V4.5z"/>
</svg>
</a>
<a class="float-right margin-l-8-px" href="#" title="{{ 'Magnet'|trans }}">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
<path d="M8 1a7 7 0 0 0-7 7v3h4V8a3 3 0 0 1 6 0v3h4V8a7 7 0 0 0-7-7Zm7 11h-4v3h4v-3ZM5 12H1v3h4v-3ZM0 8a8 8 0 1 1 16 0v8h-6V8a2 2 0 1 0-4 0v8H0V8Z"/>

Loading…
Cancel
Save