backend/src/main/java/com/magamochi/service/MangaImportService.java

439 lines
16 KiB
Java

// package com.magamochi.service;
//
// import static java.util.Objects.isNull;
// import static java.util.Objects.nonNull;
//
// import com.google.common.util.concurrent.RateLimiter;
// import com.magamochi.catalog.model.entity.Genre;
// import com.magamochi.catalog.model.repository.GenreRepository;
// import com.magamochi.catalog.client.AniListClient;
// import com.magamochi.catalog.client.JikanClient;
// import com.magamochi.common.exception.NotFoundException;
// import com.magamochi.ingestion.model.entity.ContentProvider;
// import com.magamochi.model.dto.ContentProviderMangaChapterResponseDTO;
// import com.magamochi.model.entity.*;
// import com.magamochi.model.repository.*;
// import com.magamochi.catalog.util.DoubleUtil;
// import java.io.*;
// import java.net.URI;
// import java.net.URISyntaxException;
// import java.net.URL;
// import java.time.OffsetDateTime;
// import java.time.ZoneOffset;
// import java.util.ArrayList;
// import java.util.Comparator;
// import java.util.List;
// import java.util.stream.IntStream;
// import java.util.zip.ZipEntry;
// import java.util.zip.ZipInputStream;
// import lombok.RequiredArgsConstructor;
// import lombok.extern.log4j.Log4j2;
// import org.apache.commons.lang3.StringUtils;
// import org.springframework.stereotype.Service;
// import org.springframework.web.multipart.MultipartFile;
//
// @Log4j2
//// @Service
// @RequiredArgsConstructor
// public class MangaImportService {
// private final ProviderService providerService;
// private final MangaCreationService mangaCreationService;
// private final ImageService imageService;
// private final LanguageService languageService;
//
// private final GenreRepository genreRepository;
// private final MangaGenreRepository mangaGenreRepository;
// private final MangaContentProviderRepository mangaContentProviderRepository;
// private final AuthorRepository authorRepository;
// private final MangaAuthorRepository mangaAuthorRepository;
// private final MangaChapterRepository mangaChapterRepository;
// private final MangaRepository mangaRepository;
//
// private final JikanClient jikanClient;
// private final AniListClient aniListClient;
// private final MangaChapterImageRepository mangaChapterImageRepository;
// private final MangaAlternativeTitlesRepository mangaAlternativeTitlesRepository;
//
// private final RateLimiter jikanRateLimiter;
//
// public void importMangaFiles(String malId, List<MultipartFile> files) {
// log.info("Importing manga files for MAL ID {}", malId);
// var provider = providerService.getOrCreateProvider("Manual Import", false);
//
// jikanRateLimiter.acquire();
// var mangaData = jikanClient.getMangaById(Long.parseLong(malId));
//
// var mangaProvider = getOrCreateMangaProvider(mangaData.data().title(), provider);
//
// var sortedFiles =
// files.stream().sorted(Comparator.comparing(MultipartFile::getName)).toList();
//
// IntStream.rangeClosed(1, sortedFiles.size())
// .forEach(
// fileIndex -> {
// var file = sortedFiles.get(fileIndex - 1);
// log.info(
// "Importing file {}/{}: {}, for Mangá {}",
// fileIndex,
// sortedFiles.size(),
// file.getOriginalFilename(),
// mangaProvider.getManga().getTitle());
//
// var chapter =
// persistMangaChapter(
// mangaProvider,
// new ContentProviderMangaChapterResponseDTO(
// removeFileExtension(file.getOriginalFilename()),
// "manual_" + file.getOriginalFilename(),
// file.getOriginalFilename(),
// "en-US"));
//
// List<MangaChapterImage> allChapterImages = new ArrayList<>();
// try (InputStream is = file.getInputStream();
// ZipInputStream zis = new ZipInputStream(is)) {
// ZipEntry entry;
// var position = 0;
//
// while ((entry = zis.getNextEntry()) != null) {
// if (entry.isDirectory()) {
// continue;
// }
//
// var os = new ByteArrayOutputStream();
// zis.transferTo(os);
// var bytes = os.toByteArray();
//
// var image =
// imageService.uploadImage(bytes, "image/jpeg", "chapter/" + chapter.getId());
//
// var chapterImage =
// MangaChapterImage.builder()
// .position(position++)
// .image(image)
// .mangaChapter(chapter)
// .build();
//
// allChapterImages.add(chapterImage);
// zis.closeEntry();
// }
//
// log.info("Chapter images added for chapter {}", chapter.getTitle());
// } catch (IOException e) {
// throw new RuntimeException(e);
// }
//
// mangaChapterImageRepository.saveAll(allChapterImages);
// chapter.setDownloaded(true);
// mangaChapterRepository.save(chapter);
// });
//
// log.info("Import manga files for MAL ID {} completed.", malId);
// }
//
// public void updateMangaData(Long mangaId) {
// var manga =
// mangaRepository
// .findById(mangaId)
// .orElseThrow(() -> new NotFoundException("Manga not found for ID: " + mangaId));
//
// updateMangaData(manga);
// }
//
// public void updateMangaData(Manga manga) {
// log.info("Updating manga {}", manga.getTitle());
//
// if (nonNull(manga.getMalId())) {
// try {
// updateFromJikan(manga);
// return;
// } catch (Exception e) {
// log.warn(
// "Error updating manga data from Jikan for manga {}. Trying AniList... Error: {}",
// manga.getTitle(),
// e.getMessage());
// }
// }
//
// if (nonNull(manga.getAniListId())) {
// try {
// updateFromAniList(manga);
// return;
// } catch (Exception e) {
// log.warn(
// "Error updating manga data from AniList for manga {}. Error: {}",
// manga.getTitle(),
// e.getMessage());
// }
// }
//
// log.warn(
// "Could not update manga data for {}. No provider data available/found.",
// manga.getTitle());
// }
//
// private void updateFromJikan(Manga manga) throws IOException, URISyntaxException {
// jikanRateLimiter.acquire();
// var mangaData = jikanClient.getMangaById(manga.getMalId());
//
// manga.setSynopsis(mangaData.data().synopsis());
// manga.setStatus(mangaData.data().status());
// manga.setScore(DoubleUtil.round((double) mangaData.data().score(), 2));
// manga.setPublishedFrom(mangaData.data().published().from());
// manga.setPublishedTo(mangaData.data().published().to());
// manga.setChapterCount(mangaData.data().chapters());
//
// var authors =
// mangaData.data().authors().stream()
// .map(
// authorData ->
// authorRepository
// .findByMalId(authorData.mal_id())
// .orElseGet(
// () ->
// authorRepository.save(
// Author.builder()
// .malId(authorData.mal_id())
// .name(authorData.name())
// .build())))
// .toList();
//
// updateMangaAuthors(manga, authors);
//
// var genres =
// mangaData.data().genres().stream()
// .map(
// genreData ->
// genreRepository
// .findByMalId(genreData.mal_id())
// .orElseGet(
// () ->
// genreRepository.save(
// Genre.builder()
// .malId(genreData.mal_id())
// .name(genreData.name())
// .build())))
// .toList();
//
// updateMangaGenres(manga, genres);
//
// if (isNull(manga.getCoverImage())) {
// downloadCoverImage(manga, mangaData.data().images().jpg().large_image_url());
// }
//
// var mangaEntity = mangaRepository.save(manga);
// var alternativeTitles =
// mangaData.data().title_synonyms().stream()
// .map(at -> MangaAlternativeTitle.builder().manga(mangaEntity).title(at).build())
// .toList();
// mangaAlternativeTitlesRepository.saveAll(alternativeTitles);
// }
//
// private void updateFromAniList(Manga manga) throws IOException, URISyntaxException {
// var query =
// """
// query ($id: Int) {
// Media (id: $id, type: MANGA) {
// startDate { year month day }
// endDate { year month day }
// description
// status
// averageScore
// chapters
// coverImage { large }
// genres
// staff {
// edges {
// role
// node {
// name {
// full
// }
// }
// }
// }
// }
// }
// """;
// var request =
// new AniListClient.GraphQLRequest(
// query, new AniListClient.GraphQLRequest.Variables(manga.getAniListId()));
// var media = aniListClient.getManga(request).data().Media();
//
// manga.setSynopsis(media.description());
// manga.setStatus(mapAniListStatus(media.status()));
// manga.setScore(DoubleUtil.round((double) media.averageScore() / 10, 2)); // 0-100 -> 0-10
// manga.setPublishedFrom(convertFuzzyDate(media.startDate()));
// manga.setPublishedTo(convertFuzzyDate(media.endDate()));
// manga.setChapterCount(media.chapters());
//
// var authors =
// media.staff().edges().stream()
// .filter(edge -> isAuthorRole(edge.role()))
// .map(edge -> edge.node().name().full())
// .distinct()
// .map(
// name ->
// authorRepository
// .findByName(name)
// .orElseGet(
// () -> authorRepository.save(Author.builder().name(name).build())))
// .toList();
//
// updateMangaAuthors(manga, authors);
//
// var genres =
// media.genres().stream()
// .map(
// name ->
// genreRepository
// .findByName(name)
// .orElseGet(() ->
// genreRepository.save(Genre.builder().name(name).build())))
// .toList();
//
// updateMangaGenres(manga, genres);
//
// if (isNull(manga.getCoverImage())) {
// downloadCoverImage(manga, media.coverImage().large());
// }
//
// mangaRepository.save(manga);
// }
//
// private boolean isAuthorRole(String role) {
// return role.equalsIgnoreCase("Story & Art")
// || role.equalsIgnoreCase("Story")
// || role.equalsIgnoreCase("Art");
// }
//
// private String mapAniListStatus(String status) {
// return switch (status) {
// case "RELEASING" -> "Publishing";
// case "FINISHED" -> "Finished";
// case "NOT_YET_RELEASED" -> "Not yet published";
// default -> "Unknown";
// };
// }
//
// private OffsetDateTime convertFuzzyDate(AniListClient.MangaResponse.Manga.FuzzyDate date) {
// if (isNull(date) || isNull(date.year())) {
// return null;
// }
// return OffsetDateTime.of(
// date.year(),
// isNull(date.month()) ? 1 : date.month(),
// isNull(date.day()) ? 1 : date.day(),
// 0,
// 0,
// 0,
// 0,
// ZoneOffset.UTC);
// }
//
// private void updateMangaAuthors(Manga manga, List<Author> authors) {
// var mangaAuthors =
// authors.stream()
// .map(
// author ->
// mangaAuthorRepository
// .findByMangaAndAuthor(manga, author)
// .orElseGet(
// () ->
// mangaAuthorRepository.save(
// MangaAuthor.builder().manga(manga).author(author).build())))
// .toList();
// manga.setMangaAuthors(mangaAuthors);
// }
//
// private void updateMangaGenres(Manga manga, List<Genre> genres) {
// var mangaGenres =
// genres.stream()
// .map(
// genre ->
// mangaGenreRepository
// .findByMangaAndGenre(manga, genre)
// .orElseGet(
// () ->
// mangaGenreRepository.save(
// MangaGenre.builder().manga(manga).genre(genre).build())))
// .toList();
// manga.setMangaGenres(mangaGenres);
// }
//
// private void downloadCoverImage(Manga manga, String imageUrl)
// throws IOException, URISyntaxException {
// var inputStream =
// new BufferedInputStream(new URL(new URI(imageUrl).toASCIIString()).openStream());
//
// var bytes = inputStream.readAllBytes();
//
// inputStream.close();
// var image = imageService.uploadImage(bytes, "image/jpeg", "cover");
//
// manga.setCoverImage(image);
// }
//
// public MangaChapter persistMangaChapter(
// MangaContentProvider mangaContentProvider, ContentProviderMangaChapterResponseDTO chapter) {
// var mangaChapter =
// mangaChapterRepository
// .findByMangaContentProviderAndUrlIgnoreCase(mangaContentProvider,
// chapter.url())
// .orElseGet(MangaChapter::new);
//
// mangaChapter.setMangaContentProvider(mangaContentProvider);
// mangaChapter.setTitle(chapter.title());
// mangaChapter.setUrl(chapter.url());
//
// var language = languageService.getOrThrow(chapter.languageCode());
// mangaChapter.setLanguage(language);
//
// if (nonNull(chapter.chapter())) {
// try {
// mangaChapter.setChapterNumber(Integer.parseInt(chapter.chapter()));
// } catch (NumberFormatException e) {
// log.warn(
// "Could not parse chapter number {} from manga {}",
// chapter.chapter(),
// mangaContentProvider.getManga().getTitle());
// }
// }
//
// return mangaChapterRepository.save(mangaChapter);
// }
//
// private MangaContentProvider getOrCreateMangaProvider(
// String title, ContentProvider contentProvider) {
// return mangaContentProviderRepository
// .findByMangaTitleIgnoreCaseAndContentProvider(title, contentProvider)
// .orElseGet(
// () -> {
// jikanRateLimiter.acquire();
// var manga = mangaCreationService.getOrCreateManga(title, "manual", contentProvider);
//
// return mangaContentProviderRepository.save(
// MangaContentProvider.builder()
// .manga(manga)
// .mangaTitle(manga.getTitle())
// .contentProvider(contentProvider)
// .url("manual")
// .build());
// });
// }
//
// private String removeFileExtension(String filename) {
// if (StringUtils.isBlank(filename)) {
// return filename;
// }
//
// int lastDotIndex = filename.lastIndexOf('.');
//
// // No dot, or dot is the first character (like .gitignore)
// if (lastDotIndex <= 0) {
// return filename;
// }
//
// return filename.substring(0, lastDotIndex);
// }
// }