parent
c0d9d393bf
commit
2ffb53ddbe
|
@ -0,0 +1,12 @@
|
||||||
|
apply plugin: 'com.android.application'
|
||||||
|
apply plugin: 'kotlin-android'
|
||||||
|
|
||||||
|
ext {
|
||||||
|
appName = 'Tachiyomi: TMOHentai'
|
||||||
|
pkgNameSuffix = 'es.tmohentai'
|
||||||
|
extClass = '.TMOHentai'
|
||||||
|
extVersionCode = 1
|
||||||
|
libVersion = '1.2'
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: "$rootDir/common.gradle"
|
Binary file not shown.
After Width: | Height: | Size: 4.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 5.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 9.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
Binary file not shown.
After Width: | Height: | Size: 37 KiB |
|
@ -0,0 +1,199 @@
|
||||||
|
package eu.kanade.tachiyomi.extension.es.tmohentai
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.network.GET
|
||||||
|
import eu.kanade.tachiyomi.source.model.*
|
||||||
|
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||||
|
import okhttp3.*
|
||||||
|
import org.jsoup.nodes.Document
|
||||||
|
import org.jsoup.nodes.Element
|
||||||
|
|
||||||
|
class TMOHentai : ParsedHttpSource() {
|
||||||
|
|
||||||
|
override val name = "TMOHentai"
|
||||||
|
|
||||||
|
override val baseUrl = "https://tmohentai.com"
|
||||||
|
|
||||||
|
override val lang = "es"
|
||||||
|
|
||||||
|
override val supportsLatest = true
|
||||||
|
|
||||||
|
override fun popularMangaRequest(page: Int) = GET("$baseUrl/section/hentai?view=list&page=$page&order=publication_date&order-dir=asc&search%5BsearchText%5D=&search%5BsearchBy%5D=name&type=all", headers)
|
||||||
|
|
||||||
|
override fun popularMangaSelector() = "table > tbody > tr[data-toggle=popover]"
|
||||||
|
|
||||||
|
override fun popularMangaFromElement(element: Element) = SManga.create().apply {
|
||||||
|
element.select("tr").let {
|
||||||
|
title = it.attr("data-title")
|
||||||
|
thumbnail_url = it.attr("data-content").substringAfter("src=\"").substringBeforeLast("\"")
|
||||||
|
setUrlWithoutDomain(it.select("td.text-left > a").attr("href"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun popularMangaNextPageSelector() = "a[rel=next]"
|
||||||
|
|
||||||
|
override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/filter/all?view=list&page=$page")
|
||||||
|
|
||||||
|
override fun latestUpdatesSelector() = popularMangaSelector()
|
||||||
|
|
||||||
|
override fun latestUpdatesFromElement(element: Element) = popularMangaFromElement(element)
|
||||||
|
|
||||||
|
override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector()
|
||||||
|
|
||||||
|
override fun mangaDetailsParse(document: Document) = SManga.create().apply {
|
||||||
|
val parsedInformation = document.select("div.row > div.panel.panel-primary").text()
|
||||||
|
val authorAndArtist = parsedInformation.substringAfter("Groups").substringBefore("Magazines").trim()
|
||||||
|
|
||||||
|
thumbnail_url = document.select("img.content-thumbnail-cover").attr("src")
|
||||||
|
author = authorAndArtist
|
||||||
|
artist = authorAndArtist
|
||||||
|
description = "Sin descripción"
|
||||||
|
status = SManga.UNKNOWN
|
||||||
|
genre = parsedInformation.substringAfter("Genders").substringBefore("Tags").trim().split(" ").joinToString {
|
||||||
|
it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun chapterListSelector() = "div#app > div.container"
|
||||||
|
|
||||||
|
override fun chapterFromElement(element: Element) = SChapter.create().apply {
|
||||||
|
val parsedInformation = element.select("div.row > div.panel.panel-primary").text()
|
||||||
|
|
||||||
|
name = element.select("h3.truncate").text()
|
||||||
|
scanlator = parsedInformation.substringAfter("By").substringBefore("Language").trim()
|
||||||
|
setUrlWithoutDomain(element.select("a.pull-right.btn.btn-primary").attr("href"))
|
||||||
|
// date_upload = no date in the web
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun pageListRequest(chapter: SChapter) = GET(baseUrl + chapter.url.substringBefore("/paginated") + "/cascade", headers) // "/cascade" to get all images
|
||||||
|
|
||||||
|
override fun pageListParse(document: Document): List<Page> = mutableListOf<Page>().apply {
|
||||||
|
document.select("div#content-images > div.row > div.col-xs-12.text-center > img.content-image")?.forEach {
|
||||||
|
add(Page(size, "", baseUrl + it.attr("data-original")))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException("Not used")
|
||||||
|
|
||||||
|
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||||
|
val url = HttpUrl.parse("$baseUrl/section/hentai?view=list")!!.newBuilder()
|
||||||
|
|
||||||
|
url.addQueryParameter("search[searchText]", query)
|
||||||
|
url.addQueryParameter("search[searchBy]", "name")
|
||||||
|
url.addQueryParameter("page", page.toString())
|
||||||
|
|
||||||
|
filters.forEach { filter ->
|
||||||
|
when (filter) {
|
||||||
|
is Types -> {
|
||||||
|
url.addQueryParameter("type", filter.toUriPart())
|
||||||
|
}
|
||||||
|
is OrderBy -> {
|
||||||
|
url.addQueryParameter("order", filter.toUriPart())
|
||||||
|
}
|
||||||
|
is OrderDir -> {
|
||||||
|
url.addQueryParameter("order-dir", filter.toUriPart())
|
||||||
|
}
|
||||||
|
is GenreList -> {
|
||||||
|
filter.state
|
||||||
|
.filter { genre -> genre.state }
|
||||||
|
.forEach { genre -> url.addQueryParameter("genders[]", genre.id) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GET(url.build().toString(), headers)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun searchMangaSelector() = popularMangaSelector()
|
||||||
|
|
||||||
|
override fun searchMangaFromElement(element: Element) = popularMangaFromElement(element)
|
||||||
|
|
||||||
|
override fun searchMangaNextPageSelector() = popularMangaNextPageSelector()
|
||||||
|
|
||||||
|
private class Genre(name: String, val id: String) : Filter.CheckBox(name)
|
||||||
|
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Géneros", genres)
|
||||||
|
|
||||||
|
override fun getFilterList() = FilterList(
|
||||||
|
Types(),
|
||||||
|
Filter.Separator(),
|
||||||
|
OrderBy(),
|
||||||
|
OrderDir(),
|
||||||
|
Filter.Separator(),
|
||||||
|
GenreList(getGenreList())
|
||||||
|
)
|
||||||
|
|
||||||
|
private open class UriPartFilter(displayName: String, val vals: Array<Pair<String, String>>) :
|
||||||
|
Filter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) {
|
||||||
|
fun toUriPart() = vals[state].second
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Types : UriPartFilter("Tipo", arrayOf(
|
||||||
|
Pair("Ver todos", "all"),
|
||||||
|
Pair("Manga", "hentai"),
|
||||||
|
Pair("Light Hentai", "light-hentai"),
|
||||||
|
Pair("Doujinshi", "doujinshi"),
|
||||||
|
Pair("One-shot", "one-shot"),
|
||||||
|
Pair("Other", "otro")
|
||||||
|
))
|
||||||
|
|
||||||
|
private class OrderBy : UriPartFilter("Ordenar por", arrayOf(
|
||||||
|
Pair("Alfabético", "alphabetic"),
|
||||||
|
Pair("Creación", "publication_date"),
|
||||||
|
Pair("Popularidad", "popularity")
|
||||||
|
))
|
||||||
|
|
||||||
|
private class OrderDir : UriPartFilter("Ordenar por", arrayOf(
|
||||||
|
Pair("ASC", "asc"),
|
||||||
|
Pair("DESC", "desc")
|
||||||
|
))
|
||||||
|
|
||||||
|
// Array.from(document.querySelectorAll('#advancedSearch .list-group .list-group-item')).map(a => `Genre("${a.querySelector('span').innerText.replace(' ', '')}", "${a.querySelector('input').value}")`).join(',\n')
|
||||||
|
// https://tmohentai.com/section/hentai
|
||||||
|
private fun getGenreList() = listOf(
|
||||||
|
Genre("Romance", "1"),
|
||||||
|
Genre("Fantasy", "2"),
|
||||||
|
Genre("Comedy", "3"),
|
||||||
|
Genre("Parody", "4"),
|
||||||
|
Genre("Student", "5"),
|
||||||
|
Genre("Adventure", "6"),
|
||||||
|
Genre("Milf", "7"),
|
||||||
|
Genre("Orgy", "8"),
|
||||||
|
Genre("Big Breasts", "9"),
|
||||||
|
Genre("Bondage", "10"),
|
||||||
|
Genre("Tentacles", "11"),
|
||||||
|
Genre("Incest", "12"),
|
||||||
|
Genre("Ahegao", "13"),
|
||||||
|
Genre("Bestiality", "14"),
|
||||||
|
Genre("Futanari", "15"),
|
||||||
|
Genre("Rape", "16"),
|
||||||
|
Genre("Monsters", "17"),
|
||||||
|
Genre("Pregnant", "18"),
|
||||||
|
Genre("Small Breast", "19"),
|
||||||
|
Genre("Bukkake", "20"),
|
||||||
|
Genre("Femdom", "21"),
|
||||||
|
Genre("Fetish", "22"),
|
||||||
|
Genre("Forced", "23"),
|
||||||
|
Genre("3D", "24"),
|
||||||
|
Genre("Furry", "25"),
|
||||||
|
Genre("Adultery", "26"),
|
||||||
|
Genre("Anal", "27"),
|
||||||
|
Genre("FootJob", "28"),
|
||||||
|
Genre("BlowJob", "29"),
|
||||||
|
Genre("Toys", "30"),
|
||||||
|
Genre("Vanilla", "31"),
|
||||||
|
Genre("Colour", "32"),
|
||||||
|
Genre("Uncensored", "33"),
|
||||||
|
Genre("Netorare", "34"),
|
||||||
|
Genre("Virgin", "35"),
|
||||||
|
Genre("Cheating", "36"),
|
||||||
|
Genre("Harem", "37"),
|
||||||
|
Genre("Horror", "38"),
|
||||||
|
Genre("Lolicon", "39"),
|
||||||
|
Genre("Mature", "40"),
|
||||||
|
Genre("Nympho", "41"),
|
||||||
|
Genre("Public Sex", "42"),
|
||||||
|
Genre("Sport", "43"),
|
||||||
|
Genre("Domination", "44"),
|
||||||
|
Genre("Tsundere", "45"),
|
||||||
|
Genre("Yandere", "46")
|
||||||
|
)
|
||||||
|
}
|
Loading…
Reference in New Issue