feat(language): add Language entity and update manga chapter language handling
This commit is contained in:
parent
1bb04e5d75
commit
9e44f031d2
@ -3,4 +3,7 @@ package com.magamochi.mangamochi.model.dto;
|
|||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
|
||||||
public record ContentProviderMangaChapterResponseDTO(
|
public record ContentProviderMangaChapterResponseDTO(
|
||||||
@NotBlank String chapterTitle, @NotBlank String chapterUrl, String chapter, String language) {}
|
@NotBlank String chapterTitle,
|
||||||
|
@NotBlank String chapterUrl,
|
||||||
|
String chapter,
|
||||||
|
String languageCode) {}
|
||||||
|
|||||||
@ -0,0 +1,17 @@
|
|||||||
|
package com.magamochi.mangamochi.model.dto;
|
||||||
|
|
||||||
|
import static java.util.Objects.isNull;
|
||||||
|
|
||||||
|
import com.magamochi.mangamochi.model.entity.Language;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
public record LanguageDTO(@NotNull Long id, @NotBlank String code, @NotBlank String name) {
|
||||||
|
public static LanguageDTO from(Language language) {
|
||||||
|
if (isNull(language)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new LanguageDTO(language.getId(), language.getCode(), language.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -8,12 +8,14 @@ public record MangaChapterDTO(
|
|||||||
@NotNull Long id,
|
@NotNull Long id,
|
||||||
@NotBlank String title,
|
@NotBlank String title,
|
||||||
@NotNull Boolean downloaded,
|
@NotNull Boolean downloaded,
|
||||||
@NotNull Boolean isRead) {
|
@NotNull Boolean isRead,
|
||||||
|
LanguageDTO language) {
|
||||||
public static MangaChapterDTO from(MangaChapter mangaChapter) {
|
public static MangaChapterDTO from(MangaChapter mangaChapter) {
|
||||||
return new MangaChapterDTO(
|
return new MangaChapterDTO(
|
||||||
mangaChapter.getId(),
|
mangaChapter.getId(),
|
||||||
mangaChapter.getTitle(),
|
mangaChapter.getTitle(),
|
||||||
mangaChapter.getDownloaded(),
|
mangaChapter.getDownloaded(),
|
||||||
mangaChapter.getRead());
|
mangaChapter.getRead(),
|
||||||
|
LanguageDTO.from(mangaChapter.getLanguage()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,21 @@
|
|||||||
|
package com.magamochi.mangamochi.model.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "languages")
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class Language {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
}
|
||||||
@ -38,7 +38,9 @@ public class MangaChapter {
|
|||||||
@OneToMany(mappedBy = "mangaChapter")
|
@OneToMany(mappedBy = "mangaChapter")
|
||||||
private List<MangaChapterImage> mangaChapterImages;
|
private List<MangaChapterImage> mangaChapterImages;
|
||||||
|
|
||||||
private String language;
|
|
||||||
|
|
||||||
private Integer chapterNumber;
|
private Integer chapterNumber;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(name = "language_id")
|
||||||
|
private Language language;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,9 @@
|
|||||||
|
package com.magamochi.mangamochi.model.repository;
|
||||||
|
|
||||||
|
import com.magamochi.mangamochi.model.entity.Language;
|
||||||
|
import java.util.Optional;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
public interface LanguageRepository extends JpaRepository<Language, Long> {
|
||||||
|
Optional<Language> findByCodeIgnoreCase(String code);
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
package com.magamochi.mangamochi.service;
|
||||||
|
|
||||||
|
import com.magamochi.mangamochi.exception.NotFoundException;
|
||||||
|
import com.magamochi.mangamochi.model.entity.Language;
|
||||||
|
import com.magamochi.mangamochi.model.repository.LanguageRepository;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class LanguageService {
|
||||||
|
public final LanguageRepository languageRepository;
|
||||||
|
|
||||||
|
public Language getOrThrow(String code) {
|
||||||
|
return languageRepository
|
||||||
|
.findByCodeIgnoreCase(code)
|
||||||
|
.orElseThrow(() -> new NotFoundException("Language with code " + code + " not found"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -32,6 +32,7 @@ public class MangaImportService {
|
|||||||
private final ProviderService providerService;
|
private final ProviderService providerService;
|
||||||
private final MangaCreationService mangaCreationService;
|
private final MangaCreationService mangaCreationService;
|
||||||
private final ImageService imageService;
|
private final ImageService imageService;
|
||||||
|
private final LanguageService languageService;
|
||||||
|
|
||||||
private final GenreRepository genreRepository;
|
private final GenreRepository genreRepository;
|
||||||
private final MangaGenreRepository mangaGenreRepository;
|
private final MangaGenreRepository mangaGenreRepository;
|
||||||
@ -76,7 +77,7 @@ public class MangaImportService {
|
|||||||
removeFileExtension(file.getOriginalFilename()),
|
removeFileExtension(file.getOriginalFilename()),
|
||||||
"manual_" + file.getOriginalFilename(),
|
"manual_" + file.getOriginalFilename(),
|
||||||
file.getOriginalFilename(),
|
file.getOriginalFilename(),
|
||||||
"pt-br"));
|
"en-US"));
|
||||||
|
|
||||||
List<MangaChapterImage> allChapterImages = new ArrayList<>();
|
List<MangaChapterImage> allChapterImages = new ArrayList<>();
|
||||||
try (InputStream is = file.getInputStream();
|
try (InputStream is = file.getInputStream();
|
||||||
@ -237,7 +238,9 @@ public class MangaImportService {
|
|||||||
mangaChapter.setMangaProvider(mangaProvider);
|
mangaChapter.setMangaProvider(mangaProvider);
|
||||||
mangaChapter.setTitle(chapter.chapterTitle());
|
mangaChapter.setTitle(chapter.chapterTitle());
|
||||||
mangaChapter.setUrl(chapter.chapterUrl());
|
mangaChapter.setUrl(chapter.chapterUrl());
|
||||||
mangaChapter.setLanguage(chapter.language());
|
|
||||||
|
var language = languageService.getOrThrow(chapter.languageCode());
|
||||||
|
mangaChapter.setLanguage(language);
|
||||||
|
|
||||||
if (nonNull(chapter.chapter())) {
|
if (nonNull(chapter.chapter())) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -33,6 +33,7 @@ public class BatoProvider implements ContentProvider, ManualImportContentProvide
|
|||||||
// Direct selector for chapter links
|
// Direct selector for chapter links
|
||||||
var chapterLinks = document.select("div.scrollable-panel a[href*=/title/]");
|
var chapterLinks = document.select("div.scrollable-panel a[href*=/title/]");
|
||||||
|
|
||||||
|
// TODO: fix chapter and language code
|
||||||
return chapterLinks.stream()
|
return chapterLinks.stream()
|
||||||
.map(
|
.map(
|
||||||
chapterLink ->
|
chapterLink ->
|
||||||
|
|||||||
@ -51,7 +51,7 @@ public class MangaLivreBlogProvider implements ContentProvider, PagedContentProv
|
|||||||
linkElement.getElementsByClass("chapter-number").getFirst();
|
linkElement.getElementsByClass("chapter-number").getFirst();
|
||||||
|
|
||||||
return new ContentProviderMangaChapterResponseDTO(
|
return new ContentProviderMangaChapterResponseDTO(
|
||||||
chapterNumberElement.text(), linkElement.attr("href"), null, null);
|
chapterNumberElement.text(), linkElement.attr("href"), null, "pt-BR");
|
||||||
})
|
})
|
||||||
.toList();
|
.toList();
|
||||||
} catch (IOException | NoSuchElementException e) {
|
} catch (IOException | NoSuchElementException e) {
|
||||||
|
|||||||
@ -50,7 +50,7 @@ public class MangaLivreProvider implements ContentProvider, PagedContentProvider
|
|||||||
var title = linkElement.text();
|
var title = linkElement.text();
|
||||||
|
|
||||||
return new ContentProviderMangaChapterResponseDTO(
|
return new ContentProviderMangaChapterResponseDTO(
|
||||||
title.trim(), url.trim(), null, null);
|
title.trim(), url.trim(), null, "pt-BR");
|
||||||
})
|
})
|
||||||
.toList();
|
.toList();
|
||||||
} catch (NoSuchElementException e) {
|
} catch (NoSuchElementException e) {
|
||||||
|
|||||||
@ -58,7 +58,10 @@ public class PinkRosaScanProvider implements ContentProvider, PagedContentProvid
|
|||||||
.getElementsByClass("text-sm truncate")
|
.getElementsByClass("text-sm truncate")
|
||||||
.getFirst();
|
.getFirst();
|
||||||
return new ContentProviderMangaChapterResponseDTO(
|
return new ContentProviderMangaChapterResponseDTO(
|
||||||
chapterTitleElement.text().trim(), chapterItemElement.attr("href"), null, null);
|
chapterTitleElement.text().trim(),
|
||||||
|
chapterItemElement.attr("href"),
|
||||||
|
null,
|
||||||
|
"pt-BR");
|
||||||
})
|
})
|
||||||
.toList();
|
.toList();
|
||||||
} catch (NoSuchElementException e) {
|
} catch (NoSuchElementException e) {
|
||||||
|
|||||||
40
src/main/resources/db/migration/V0019__CHAPTER_LANGUAGE.sql
Normal file
40
src/main/resources/db/migration/V0019__CHAPTER_LANGUAGE.sql
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS languages
|
||||||
|
(
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
code VARCHAR(12) NOT NULL UNIQUE,
|
||||||
|
name VARCHAR(100) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO languages (code, name)
|
||||||
|
VALUES ('en-US', 'English'),
|
||||||
|
('es', 'Spanish'),
|
||||||
|
('ja-JP', 'Japanese'),
|
||||||
|
('pt-BR', 'Portuguese (Brazil)')
|
||||||
|
ON CONFLICT DO NOTHING;
|
||||||
|
|
||||||
|
ALTER TABLE manga_chapters
|
||||||
|
ADD COLUMN IF NOT EXISTS language_id BIGINT REFERENCES languages (id);
|
||||||
|
|
||||||
|
UPDATE manga_chapters
|
||||||
|
SET language = NULL;
|
||||||
|
|
||||||
|
UPDATE manga_chapters mc
|
||||||
|
SET language_id = (SELECT id FROM languages WHERE code = 'pt-BR')
|
||||||
|
FROM manga_provider mp
|
||||||
|
JOIN providers p ON mp.provider_id = p.id
|
||||||
|
WHERE mc.manga_provider_id = mp.id
|
||||||
|
AND mc.language IS NULL
|
||||||
|
AND p.name ILIKE ANY
|
||||||
|
(ARRAY ['Manga Livre Blog', 'Pink Rosa Scan', 'Manga Livre.to', 'Manga Livre', 'MangaDex', 'Bato', 'Taimu']);
|
||||||
|
|
||||||
|
UPDATE manga_chapters mc
|
||||||
|
SET language_id = (SELECT id FROM languages WHERE code = 'en-US')
|
||||||
|
FROM manga_provider mp
|
||||||
|
JOIN providers p ON mp.provider_id = p.id
|
||||||
|
WHERE mc.manga_provider_id = mp.id
|
||||||
|
AND mc.language IS NULL
|
||||||
|
AND p.name ILIKE ANY
|
||||||
|
(ARRAY ['Manual Import']);
|
||||||
|
|
||||||
|
ALTER TABLE manga_chapters
|
||||||
|
DROP COLUMN IF EXISTS language;
|
||||||
Loading…
x
Reference in New Issue
Block a user