diff --git a/app/src/main/java/org/koitharu/kotatsu/core/model/MangaSource.kt b/app/src/main/java/org/koitharu/kotatsu/core/model/MangaSource.kt index ac67f280d..9d35e9df5 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/model/MangaSource.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/model/MangaSource.kt @@ -30,7 +30,8 @@ enum class MangaSource( // NUDEMOON("Nude-Moon", "ru", NudeMoonRepository::class.java), MANGAREAD("MangaRead", "en", MangareadRepository::class.java), REMANGA("Remanga", "ru", RemangaRepository::class.java), - HENTAILIB("HentaiLib", "ru", HentaiLibRepository::class.java); + HENTAILIB("HentaiLib", "ru", HentaiLibRepository::class.java), + ANIBEL("Anibel", "be", AnibelRepository::class.java); @get:Throws(NoBeanDefFoundException::class) @Deprecated("") diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/ParserModule.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/ParserModule.kt index b5b3f431c..09ae0c43c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/parser/ParserModule.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/ParserModule.kt @@ -24,4 +24,5 @@ val parserModule factory(named(MangaSource.MANGAREAD)) { MangareadRepository(get()) } factory(named(MangaSource.REMANGA)) { RemangaRepository(get()) } factory(named(MangaSource.HENTAILIB)) { HentaiLibRepository(get()) } + factory(named(MangaSource.ANIBEL)) { AnibelRepository(get()) } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/site/AnibelRepository.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/site/AnibelRepository.kt new file mode 100644 index 000000000..574f1a42e --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/site/AnibelRepository.kt @@ -0,0 +1,182 @@ +package org.koitharu.kotatsu.core.parser.site + +import org.koitharu.kotatsu.base.domain.MangaLoaderContext +import org.koitharu.kotatsu.core.exceptions.ParseException +import org.koitharu.kotatsu.core.model.* +import org.koitharu.kotatsu.core.parser.RemoteMangaRepository +import org.koitharu.kotatsu.utils.ext.* +import java.util.* + +class AnibelRepository(loaderContext: MangaLoaderContext) : RemoteMangaRepository(loaderContext) { + + override val source = MangaSource.ANIBEL + + override val defaultDomain = "anibel.net" + + override val sortOrders: Set = EnumSet.of( + SortOrder.UPDATED + ) + + override suspend fun getList( + offset: Int, + query: String?, + sortOrder: SortOrder?, + tag: MangaTag? + ): List { + if (!query.isNullOrEmpty()) { + return if (offset == 0) search(query) else emptyList() + } + val page = (offset / 12).inc() + val tagPage = offset.inc() //TODO Load another pages + val link = buildString { + append("https://") + append(getDomain()) + append("/manga") + if (tag != null) { + append("?genre[]=") + append(tag.key) + append("&page=") + append(tagPage) + } else { + append("?page=") + append(page) + } + } + val doc = loaderContext.httpGet(link).parseHtml() + val root = doc.body().select("div.manga-block") ?: throw ParseException("Cannot find root") + val items = root.select("div.anime-card") + return items.mapNotNull { card -> + val href = card.select("a").attr("href") + val url = buildString { + append("https://") + append(getDomain()) + append("/") + } + val status = card.select("tr")[2].text() + Manga( + id = generateUid(href), + title = card.selectFirst("h1.anime-card-title").text(), + coverUrl = url + card.selectFirst("img").attr("data-src"), + altTitle = null, + author = null, + rating = Manga.NO_RATING, + url = url + href, + publicUrl = "", + state = when (status) { + "выпускаецца" -> MangaState.ONGOING + "завершанае" -> MangaState.FINISHED + else -> null + }, + source = source + ) + } + } + + override suspend fun getDetails(manga: Manga): Manga { + val doc = loaderContext.httpGet(manga.url.withDomain()).parseHtml() + val root = doc.body().select("div.container") ?: throw ParseException("Cannot find root") + return manga.copy( + description = root.select("div.manga-block.grid-12")[2].select("p").text(), + largeCoverUrl = manga.coverUrl, + chapters = root.select("ul.series").flatMap { table -> + table.select("li") + }.map { it.selectFirst("a") }.mapIndexedNotNull { i, a -> + val url = buildString { + append("https://") + append(getDomain()) + } + val href = url + a.select("a").first().attr("href") + MangaChapter( + id = generateUid(href), + name = a.select("a").first().text(), + number = i + 1, + url = href, + source = source + ) + } + ) + } + + override suspend fun getPages(chapter: MangaChapter): List { + val fullUrl = chapter.url.withDomain() + val doc = loaderContext.httpGet(fullUrl).parseHtml() + val scripts = doc.select("script") + for (script in scripts) { + val data = script.html() + val pos = data.indexOf("dataSource") + if (pos == -1) { + continue + } + val json = data.substring(pos).substringAfter('[').substringBefore(']') + val domain = getDomain() + return json.split(",").mapNotNull { + it.trim() + .removeSurrounding('"', '\'') + .toRelativeUrl(domain) + .takeUnless(String::isBlank) + }.map { url -> + MangaPage( + id = generateUid(url), + url = url, + referer = fullUrl, + source = source + ) + } + } + throw ParseException("Pages list not found at ${chapter.url.withDomain()}") + } + + override suspend fun getTags(): Set { + val doc = loaderContext.httpGet("https://${getDomain()}/manga").parseHtml() + val root = doc.body().select("div#tabs-genres").select("ul#list.ul-three-colums") + return root.select("p.menu-tags.tupe").mapToSet { a -> + MangaTag( + title = a.select("a").text().capitalize(Locale.ROOT), + key = a.select("a").attr("data-name"), + source = source + ) + } + } + + private suspend fun search(query: String): List { + val domain = getDomain() + val doc = loaderContext.httpGet("https://$domain/search?q=$query").parseHtml() + val root = doc.body().select("div.manga-block") ?: throw ParseException("Cannot find root") + val items = root.select("div.anime-card") + return items.mapNotNull { card -> + val href = card.select("a").attr("href") + val url = buildString { + append("https://") + append(getDomain()) + } + val status = card.select("tr")[2].text() + Manga( + id = generateUid(href), + title = card.selectFirst("h1.anime-card-title").text(), + coverUrl = url + card.selectFirst("img").attr("src"), + altTitle = null, + author = null, + rating = Manga.NO_RATING, + url = url + href, + publicUrl = "", + tags = runCatching { + card?.select("p.tupe.tag") + ?.mapToSet { + MangaTag( + title = it.select("a").text(), + key = it.attr("href"), + source = source + ) + } + }.getOrNull().orEmpty(), + state = when (status) { + "выпускаецца" -> MangaState.ONGOING + "завершанае" -> MangaState.FINISHED + else -> null + }, + source = source + ) + } + } + +} \ No newline at end of file