Compare commits
1 Commits
main
...
feat/hiper
| Author | SHA1 | Date | |
|---|---|---|---|
| 1b7766e681 |
@ -50,6 +50,13 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- mangamochi-network
|
- mangamochi-network
|
||||||
|
|
||||||
|
flare-solverr:
|
||||||
|
image: ghcr.io/flaresolverr/flaresolverr:latest
|
||||||
|
ports:
|
||||||
|
- "8191:8191"
|
||||||
|
volumes:
|
||||||
|
- /var/lib/flaresolver:/config
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
mangamochi-network:
|
mangamochi-network:
|
||||||
driver: bridge
|
driver: bridge
|
||||||
|
|||||||
@ -7,4 +7,5 @@ public class ContentProviders {
|
|||||||
public static final String TAIMU = "Taimu";
|
public static final String TAIMU = "Taimu";
|
||||||
public static final String MANGA_DEX = "MangaDex";
|
public static final String MANGA_DEX = "MangaDex";
|
||||||
public static final String MANUAL_IMPORT = "Manual Import";
|
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