feat: refactorisation de la gestion du scraping des chapitres en remplaçant les identifiants de manga et de chapitre par un identifiant de chapitre unique, amélioration de la récupération des sources préférées et ajout de la gestion des erreurs pour les échecs de scraping.
This commit is contained in:
parent
e29433bb0c
commit
c9f1771522
@@ -21,15 +21,9 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||
readonly class ScrapeChapterRequest
|
||||
{
|
||||
public function __construct(
|
||||
#[ApiProperty(description: 'ID du manga')]
|
||||
#[ApiProperty(description: 'ID du chapitre à scraper')]
|
||||
#[Assert\NotBlank]
|
||||
public string $mangaId,
|
||||
#[ApiProperty(description: 'Numéro du chapitre')]
|
||||
#[Assert\NotBlank]
|
||||
public string $chapterNumber,
|
||||
#[ApiProperty(description: 'ID de la source')]
|
||||
#[Assert\NotBlank]
|
||||
public string $sourceId,
|
||||
public string $chapterId,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,9 +22,7 @@ final class ScrapeChapterStateProcessor implements ProcessorInterface
|
||||
{
|
||||
$this->commandBus->dispatch(
|
||||
new ScrapeChapter(
|
||||
$data->mangaId,
|
||||
$data->chapterNumber,
|
||||
$data->sourceId
|
||||
$data->chapterId
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,26 @@ readonly class LegacyChapterRepository implements ChapterRepositoryInterface
|
||||
private EntityManagerInterface $entityManager,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Récupère un chapitre par son identifiant
|
||||
*/
|
||||
public function getById(string $id): ?Chapter
|
||||
{
|
||||
$chapterEntity = $this->entityManager->getRepository(EntityChapter::class)->find($id);
|
||||
|
||||
if (!$chapterEntity) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Chapter(
|
||||
id: $chapterEntity->getId(),
|
||||
mangaId: $chapterEntity->getManga()->getId(),
|
||||
chapterNumber: $chapterEntity->getNumber(),
|
||||
volumeNumber: $chapterEntity->getVolume(),
|
||||
cbzPath: $chapterEntity->getCbzPath(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ChapterNotFoundException
|
||||
*/
|
||||
@@ -32,6 +52,7 @@ readonly class LegacyChapterRepository implements ChapterRepositoryInterface
|
||||
mangaId: $chapterEntity->getManga()->getId(),
|
||||
chapterNumber: $chapterEntity->getNumber(),
|
||||
volumeNumber: $chapterEntity->getVolume(),
|
||||
cbzPath: $chapterEntity->getCbzPath(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,13 +19,24 @@ readonly class LegacyMangaRepository implements MangaRepositoryInterface
|
||||
/** @var EntityManga|null $mangaEntity */
|
||||
$mangaEntity = $this->entityManager->getRepository(EntityManga::class)->find($id);
|
||||
|
||||
return $mangaEntity ? new Manga(
|
||||
if (!$mangaEntity) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Récupération des sources préférées
|
||||
$preferredSourceIds = [];
|
||||
foreach ($mangaEntity->getPreferredSources() as $source) {
|
||||
$preferredSourceIds[] = $source->getId();
|
||||
}
|
||||
|
||||
return new Manga(
|
||||
$mangaEntity->getId(),
|
||||
$mangaEntity->getTitle(),
|
||||
$mangaEntity->getSlug(),
|
||||
$mangaEntity->getDescription(),
|
||||
$mangaEntity->getAuthor(),
|
||||
$mangaEntity->getPublicationYear(),
|
||||
) : null;
|
||||
$mangaEntity->getDescription() ?? '',
|
||||
$mangaEntity->getAuthor() ?? '',
|
||||
$mangaEntity->getPublicationYear() ?? '',
|
||||
$preferredSourceIds,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,4 +46,43 @@ readonly class LegacySourceRepository implements SourceRepositoryInterface
|
||||
updatedAt: new DateTimeImmutable()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Source[]
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
/** @var ContentSource[] $sourceEntities */
|
||||
$sourceEntities = $this->entityManager->getRepository(ContentSource::class)->findAll();
|
||||
|
||||
$sources = [];
|
||||
foreach ($sourceEntities as $sourceEntity) {
|
||||
$sources[] = $this->convertEntityToModel($sourceEntity);
|
||||
}
|
||||
|
||||
return $sources;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convertit une entité ContentSource en modèle Source
|
||||
*/
|
||||
private function convertEntityToModel(ContentSource $source): Source
|
||||
{
|
||||
return new Source(
|
||||
id: new SourceId($source->getId()),
|
||||
name: $source->getCleanBaseUrl(),
|
||||
description: 'Legacy Source: ' . $source->getBaseUrl(),
|
||||
baseUrl: $source->getBaseUrl(),
|
||||
scrappingParameters: [
|
||||
'imageSelector' => $source->getImageSelector(),
|
||||
'nextPageSelector' => $source->getNextPageSelector(),
|
||||
'chapterUrlFormat' => $source->getChapterUrlFormat(),
|
||||
'scrapingType' => $source->getScrapingType(),
|
||||
'chapterSelector' => $source->getChapterSelector()
|
||||
],
|
||||
isActive: true,
|
||||
createdAt: new DateTimeImmutable(),
|
||||
updatedAt: new DateTimeImmutable()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user