feat: add Hiperdex content provider
This commit is contained in:
parent
1a41ae2a8d
commit
1b7766e681
@ -50,6 +50,13 @@ services:
|
||||
networks:
|
||||
- mangamochi-network
|
||||
|
||||
flare-solverr:
|
||||
image: ghcr.io/flaresolverr/flaresolverr:latest
|
||||
ports:
|
||||
- "8191:8191"
|
||||
volumes:
|
||||
- /var/lib/flaresolver:/config
|
||||
|
||||
networks:
|
||||
mangamochi-network:
|
||||
driver: bridge
|
||||
|
||||
@ -7,4 +7,5 @@ public class ContentProviders {
|
||||
public static final String TAIMU = "Taimu";
|
||||
public static final String MANGA_DEX = "MangaDex";
|
||||
public static final String MANUAL_IMPORT = "Manual Import";
|
||||
public static final String HIPERDEX = "Hiperdex";
|
||||
}
|
||||
|
||||
@ -0,0 +1,150 @@
|
||||
package com.magamochi.ingestion.providers.impl;
|
||||
|
||||
import com.magamochi.catalog.model.entity.MangaContentProvider;
|
||||
import com.magamochi.common.ContentProviders;
|
||||
import com.magamochi.common.exception.NotFoundException;
|
||||
import com.magamochi.ingestion.model.dto.ContentImageInfoDTO;
|
||||
import com.magamochi.ingestion.model.dto.ContentInfoDTO;
|
||||
import com.magamochi.ingestion.model.dto.MangaInfoDTO;
|
||||
import com.magamochi.ingestion.providers.ContentProvider;
|
||||
import com.magamochi.ingestion.providers.PagedContentProvider;
|
||||
import com.magamochi.ingestion.service.FlareService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static java.util.Objects.nonNull;
|
||||
|
||||
@Log4j2
|
||||
@Service(ContentProviders.HIPERDEX)
|
||||
@RequiredArgsConstructor
|
||||
public class HiperdexProvider implements ContentProvider, PagedContentProvider {
|
||||
private final String url = "https://hiperdex.com/";
|
||||
|
||||
private final FlareService flareService;
|
||||
|
||||
@Override
|
||||
public List<ContentInfoDTO> getAvailableChapters(MangaContentProvider provider) {
|
||||
log.info(
|
||||
"Getting available chapters from {}, manga {}",
|
||||
ContentProviders.HIPERDEX,
|
||||
provider.getManga().getTitle());
|
||||
|
||||
try {
|
||||
var document =
|
||||
flareService.getContentAsJsoupDocument(
|
||||
provider.getUrl(), ContentProviders.HIPERDEX);
|
||||
|
||||
var chapterBoxes =
|
||||
document.select("li.wp-manga-chapter");
|
||||
|
||||
return chapterBoxes.stream()
|
||||
.map(
|
||||
chapterBox -> {
|
||||
var linkElement = chapterBox.selectFirst("a");
|
||||
|
||||
var url = linkElement.attr("href");
|
||||
var title = linkElement.text();
|
||||
|
||||
return new ContentInfoDTO(title.trim(), url.trim(), "en-US");
|
||||
})
|
||||
.toList();
|
||||
} catch (NoSuchElementException e) {
|
||||
log.error("Error parsing mangas from " + ContentProviders.HIPERDEX, e);
|
||||
return List.of();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ContentImageInfoDTO> getContentImages(String chapterUrl) {
|
||||
log.info("Getting images from {}, url {}", ContentProviders.HIPERDEX, chapterUrl);
|
||||
|
||||
try {
|
||||
var document =
|
||||
flareService.getContentAsJsoupDocument(chapterUrl, ContentProviders.HIPERDEX);
|
||||
|
||||
var chapterImagesElements = document.select("div.reading-content img.wp-manga-chapter-img");
|
||||
|
||||
var imageUrls =
|
||||
chapterImagesElements.stream()
|
||||
.map(
|
||||
chapterImagesElement -> {
|
||||
return chapterImagesElement.attr("src");
|
||||
})
|
||||
.toList();
|
||||
|
||||
return IntStream.range(0, imageUrls.size())
|
||||
.boxed()
|
||||
.map(position -> new ContentImageInfoDTO(position, imageUrls.get(position)))
|
||||
.toList();
|
||||
} catch (NoSuchElementException e) {
|
||||
log.error("Error parsing manga images from " + ContentProviders.HIPERDEX, e);
|
||||
return List.of();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MangaInfoDTO> getMangasFromPage(int page) {
|
||||
log.info("Getting mangas from {}, page {}", ContentProviders.HIPERDEX, page);
|
||||
|
||||
try {
|
||||
var document =
|
||||
flareService.getContentAsJsoupDocument(
|
||||
url + "page/" + page, ContentProviders.HIPERDEX);
|
||||
|
||||
var mangaElements = document.select("div.page-item-detail.manga");
|
||||
|
||||
return mangaElements.stream()
|
||||
.map(
|
||||
element -> {
|
||||
var linkElement = element.selectFirst(".item-thumb > a");
|
||||
var url = linkElement.attr("href");
|
||||
|
||||
var title = linkElement.attr("title");
|
||||
|
||||
// Fallback: If 'title' attribute is empty, try the <img> tag's 'alt' or 'title'
|
||||
if (title.isBlank()) {
|
||||
var imgElement = linkElement.selectFirst("img");
|
||||
if (nonNull(imgElement)) {
|
||||
title = imgElement.attr("alt");
|
||||
}
|
||||
}
|
||||
|
||||
return new MangaInfoDTO(title.trim(), url.trim());
|
||||
})
|
||||
.toList();
|
||||
} catch (NoSuchElementException e) {
|
||||
log.error("Error parsing mangas from " + ContentProviders.HIPERDEX, e);
|
||||
return List.of();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTotalPages() {
|
||||
log.info("Getting total pages for {}", ContentProviders.HIPERDEX);
|
||||
|
||||
try {
|
||||
var document = flareService.getContentAsJsoupDocument(url + "mangalist", ContentProviders.HIPERDEX);
|
||||
|
||||
var fullText = document.selectFirst("span.pages").text();
|
||||
|
||||
var pattern = Pattern.compile("(\\d+)$");
|
||||
var matcher = pattern.matcher(fullText.trim());
|
||||
|
||||
if (matcher.find()) {
|
||||
var lastNumber = matcher.group(1);
|
||||
return Integer.parseInt(lastNumber);
|
||||
}
|
||||
|
||||
throw new NotFoundException("Total pages number not found in " + ContentProviders.HIPERDEX);
|
||||
} catch (NoSuchElementException e) {
|
||||
log.error("Error parsing total pages from " + ContentProviders.HIPERDEX, e);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
2
src/main/resources/db/migration/V0012__HIPERDEX.sql
Normal file
2
src/main/resources/db/migration/V0012__HIPERDEX.sql
Normal file
@ -0,0 +1,2 @@
|
||||
INSERT INTO content_providers(name, url, active, supports_content_fetch, manual_import)
|
||||
VALUES ('Hiperdex', 'https://hiperdex.com', TRUE, TRUE, FALSE);
|
||||
Loading…
x
Reference in New Issue
Block a user