231 lines
8.0 KiB
PHP
231 lines
8.0 KiB
PHP
<?php
|
|
|
|
namespace App\Controller;
|
|
|
|
use App\Entity\Manga;
|
|
use App\Repository\MangaRepository;
|
|
use App\Service\MangaExportService;
|
|
use App\Service\LelScansProviderService;
|
|
use App\Service\MangaScraperServiceOld;
|
|
use App\Service\MangaUpdatesMetadataProvider;
|
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
|
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
|
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|
use Symfony\Component\Routing\Annotation\Route;
|
|
use Symfony\Component\String\Slugger\AsciiSlugger;
|
|
|
|
class MangaController extends AbstractController
|
|
{
|
|
public function __construct(
|
|
private readonly MangaScraperServiceOld $mangaScraperService,
|
|
private readonly MangaExportService $mangaExportService,
|
|
private readonly LelScansProviderService $mangaProviderService,
|
|
private readonly MangaRepository $mangaRepository,
|
|
private MangaUpdatesMetadataProvider $mangaUpdatesDbProvider
|
|
)
|
|
{
|
|
}
|
|
|
|
#[Route('/manga', name: 'app_manga')]
|
|
public function index(): Response
|
|
{
|
|
$mangas = $this->mangaRepository->findAll();
|
|
return $this->render('manga/index.html.twig', [
|
|
'controller_name' => 'MangaController',
|
|
'mangas' => $mangas,
|
|
]);
|
|
}
|
|
|
|
#[Route('/manga/{mangaSlug}', name: 'manga_show')]
|
|
public function showChapters(string $mangaSlug): Response
|
|
{
|
|
$manga = $this->mangaRepository->findOneBy(['slug' => $mangaSlug]);
|
|
|
|
if (!$manga) {
|
|
throw new NotFoundHttpException("Le manga demandé n'existe pas.");
|
|
}
|
|
|
|
$chaptersByVolume = [];
|
|
foreach ($manga->getChapters() as $chapter) {
|
|
$volume = $chapter->getVolume() ?? 'Not Found';
|
|
$chaptersByVolume[$volume][] = $chapter;
|
|
}
|
|
|
|
$chaptersByVolume = array_map('array_reverse', array_reverse($chaptersByVolume, true));
|
|
|
|
return $this->render('manga/show_chapters.html.twig', [
|
|
'chapters_by_volume' => $chaptersByVolume,
|
|
'manga' => $manga,
|
|
]);
|
|
}
|
|
|
|
#[Route('/manga/{mangaSlug}/{chapterNumber}/{pageNumber}', name: 'read_chapter_page')]
|
|
public function readChapterPage(string $mangaSlug, float $chapterNumber, int $pageNumber = 0): Response
|
|
{
|
|
$manga = $this->mangaRepository->findOneBy(['slug' => $mangaSlug]);
|
|
if (!$manga) {
|
|
throw $this->createNotFoundException("Le manga demandé n'existe pas.");
|
|
}
|
|
|
|
$chapter = $manga->getChapterByNumber($chapterNumber);
|
|
if (!$chapter) {
|
|
throw $this->createNotFoundException("Le chapitre demandé n'existe pas.");
|
|
}
|
|
|
|
$currentPage = $chapter->getPageByNumber($pageNumber);
|
|
if (!$currentPage) {
|
|
throw $this->createNotFoundException("La page demandée n'existe pas.");
|
|
}
|
|
|
|
return $this->render('manga/manga_reader.html.twig', [
|
|
'manga' => $manga,
|
|
'chapter' => $chapter,
|
|
'pages' => $chapter->getPagesLink(),
|
|
'currentPage' => $currentPage,
|
|
]);
|
|
}
|
|
|
|
#[Route('/addNew/{query}', name: 'add_new_manga')]
|
|
public function addNew(string $query = ''): Response
|
|
{
|
|
return $this->render('manga/add_new.html.twig', [
|
|
'query' => $query,
|
|
]);
|
|
}
|
|
|
|
public function search(string $title): Response
|
|
{
|
|
$mangas = $this->mangaUpdatesDbProvider->search($title);
|
|
|
|
return $this->render('manga/add_new.html.twig', [
|
|
'mangas' => $mangas,
|
|
]);
|
|
}
|
|
|
|
#[Route('/manga/{mangaSlug}/chapter/{chapterNumber}/download', name: 'download_chapter')]
|
|
public function downloadChapter(string $mangaSlug, float $chapterNumber): BinaryFileResponse
|
|
{
|
|
$response = $this->mangaExportService->downloadCbz($this->slugToTitle($mangaSlug), $chapterNumber);
|
|
|
|
if ($response === false) {
|
|
throw $this->createNotFoundException("Le chapitre demandé n'existe pas.");
|
|
}
|
|
|
|
// Définir les en-têtes pour le téléchargement
|
|
$response->headers->set('Content-Type', 'application/x-cbz');
|
|
$response->setContentDisposition(
|
|
ResponseHeaderBag::DISPOSITION_ATTACHMENT,
|
|
"{$mangaSlug}_{$chapterNumber}.cbz"
|
|
);
|
|
|
|
return $response;
|
|
}
|
|
|
|
#[Route('/scrape', name: 'manga_scrape', methods: 'POST')]
|
|
public function scrapeByMangaAndChapter(Request $request): Response
|
|
{
|
|
$mangaSlug = $request->request->get('mangaSlug');
|
|
$chapterNumber = $request->request->get('chapterNumber');
|
|
|
|
$response = $this->scrapeChapter($mangaSlug, $chapterNumber);
|
|
|
|
$manga = $this->mangaRepository->findOneBy(['slug' => $mangaSlug]);
|
|
|
|
$availableChapters = $this->mangaProviderService->getChapterList($mangaSlug);
|
|
|
|
return $this->render('manga/show_chapters.html.twig', [
|
|
'controller_name' => 'MangaController',
|
|
'manga' => $manga,
|
|
'availableChapters' => $availableChapters,
|
|
]);
|
|
}
|
|
|
|
#[Route('/scrapeFrom', name: 'manga_scrape_from_chapter', methods: 'POST')]
|
|
public function scrapeByMangaFromChapter(Request $request): Response
|
|
{
|
|
$mangaSlug = $request->request->get('mangaSlug');
|
|
$chapterNumber = $request->request->get('chapterNumber');
|
|
|
|
do {
|
|
$response = $this->scrapeChapter($mangaSlug, $chapterNumber);
|
|
$chapterNumber++;
|
|
} while ($response !== false);
|
|
|
|
$availableChapters = $this->mangaProviderService->getChapterList($mangaSlug);
|
|
|
|
return $this->redirectToRoute('manga_show', ['mangaSlug' => $mangaSlug, 'availableChapters' => $availableChapters]);
|
|
}
|
|
|
|
#[Route('/manga/exportFrom/{mangaSlug}/{chapterNumber}', name: 'manga_export')]
|
|
public function exportMangaCbz(string $mangaSlug, float $chapterNumber)
|
|
{
|
|
$response = $this->exportCbz($this->slugToTitle($mangaSlug), $chapterNumber);
|
|
|
|
dd($response);
|
|
}
|
|
|
|
#[Route('/getList', name: 'get_manga_list')]
|
|
public function getMangaList()
|
|
{
|
|
$list = $this->mangaProviderService->getMangaList();
|
|
|
|
}
|
|
|
|
private function scrapeChapter(string $mangaSlug, float $chapterNumber): array|bool
|
|
{
|
|
$url = 'https://lelscans.net/scan-' . $mangaSlug . '/' . $chapterNumber;
|
|
|
|
$manga = $this->mangaRepository->findOneBy(['slug' => $mangaSlug]);
|
|
|
|
if (!is_null($manga)) {
|
|
$scrapedManga = $this->mangaScraperService->scrapeMangaChapter($url, $manga->getTitle(), $chapterNumber);
|
|
} else {
|
|
$title = $this->slugToTitle($mangaSlug);
|
|
$manga = new Manga();
|
|
$manga->setTitle($title);
|
|
$manga->setSlug($mangaSlug);
|
|
$this->mangaRepository->save($manga);
|
|
$scrapedManga = $this->mangaScraperService->scrapeMangaChapter($url, $title, $chapterNumber);
|
|
}
|
|
|
|
return $scrapedManga;
|
|
}
|
|
|
|
private function exportCbz(string $mangaSlug, float $chapterNumber): array
|
|
{
|
|
$exported = [];
|
|
do {
|
|
$response = $this->mangaExportService->exportMangaChapter($mangaSlug, $chapterNumber);
|
|
|
|
if ($response === 'already_exported') {
|
|
$exported[] = $mangaSlug . ' - ' . $chapterNumber . ' ' . $response;
|
|
} elseif ($response === true) {
|
|
$exported[] = $mangaSlug . ' - ' . $chapterNumber . ' exported';
|
|
} else {
|
|
$exported[] = $mangaSlug . ' - ' . $chapterNumber . ' something went wrong';
|
|
}
|
|
|
|
$chapterNumber++;
|
|
} while ($response !== false);
|
|
|
|
return $exported;
|
|
}
|
|
|
|
private function slugToTitle(string $slug): string
|
|
{
|
|
$slugger = new AsciiSlugger();
|
|
$title = $slugger->slug($slug)->replace('-', ' ')->title(true)->toString();
|
|
|
|
return $title;
|
|
}
|
|
|
|
private function titleToSlug(string $title): string
|
|
{
|
|
$slugger = new AsciiSlugger();
|
|
return $slugger->slug($title)->lower()->toString();
|
|
}
|
|
}
|