@WGK*HNagaUca0l4z%E-1%`|2F(8m`
zpMLVGB|t`QylexBMzjhbqu&wb?%bs_TXT&CY%)ZE1*;uV@147~A2IUnz|n{uBU-od
z4Gj=m&M{{;E&OPq>8=dKm}Gz;4X})3=BqPV90>c?u#Cf(@O+~n?6TdvcGIq1yO<%3
zje)WXv*U50t=J|6?-T(=Oy-J#OTdD4M%aXS;o=20jZ#q=zS&ZD9HQ#Rr=_KN=7nKR
zw3P%xCt*b*R2Y_Xs4lq!nFNvm64PM7jQ~PDn7WuWX%d?yA3Ag>TN5qry1)j&W5MbOh^yrcIy5f}WX~nRNgmfC?KBYmKnU^3>^5boJU*_MMrh
zrs}JxMWS5;BzR#u0AXL4)m)gB@n{B+=*F8#AgmTF992l8$Bd?NW5=<@UR)vo02uk$
zb+P}zep>zgY8H_;T12L6Ohe+l^X@xr7j2K8J=lyqpS1&A4WQXo+U5NsgKg?R~(*r|{hW)cXC$FP{JaC9Nfm_CDTBot@kd58fM
zoQoGPW>YR^``L9oBmnf@`|r`)Z@xBzs<>
zCuP)dGk~nTFe89;Jia<38Y*nzLbjYkj!26DA&^*i`G~0ys1gJ@-<CiE#At_PcyYIhC^WK`rjA^WVo6RJUj_&tb0;%e(Q(+4in!54a3kw4%zJ?v6&K%)fhDXfzgtP0Hf~~JhkM2M49Cx`t$+judZ*5vXzrVH*?J(%{EJ@L
zld>mlk^bt{tLYzq{|8;Ve5vUGq#8uAH@yT%r(W*HGcU|!VJLU+JJpuSm*^14jSm4N
zsy`kFk^vHfa$UN1p=nd6F>h?h;2}&>aKjaKVT}%K5-cqH;m04?WHj+Rb5*X81+KN?)6DLk&i_0K2pn3oh)HAgR)5c93
znJokt8-SWEGJ`>mB_@dZ%$zloX3d(#LIL7*S)}K0gikwNDqkv)q=h8P-BM<9%3hr72hppQV0+sJwJ&fCpU*d1NDV1&M2RU3D7>I
z$GU5%NQ4QNEM7uauU=(MGdkX-Q3513TF0mrjc6kY#DNs&!n_1X?qu%9bAYS{0lPF{
z13~R#oiqj=_6t`xC=0IN}8x8qhcGyH*dhn$vnD~Um06>pRA5+EC3Z|m)!AY*ji`^Fp7(z1P
z18|TZzyU-Y)POUBuz3H>=`(fHIgMHZrKYCZ^1?(lhe6|~a{wSjqOq05Y+o4j!j>#$
zD$I@-#%&=E&_^GCWF80Fx{W^h^Cw}m@kWvrkib5{VGDx?4W@xF4y3+)`?Af4Fnl=(
zxL<$?34-7s+KuypVDv&_VYvo7gfq4FC}1((gXlKY*5%8WnNf~o_pprzsu9QE@kn>G
z0!UU193UL71aRat61il+dLRIVX$Ks`)P?8wlq_Bl?Q{=9nrN
zFknD9Kvh-joM;%0I8eaqoMUwqV_=4Ny6l5JeOkyJ2M&hrBm#
z-e8^%_i#jsX(l~nDF+VbQP0aUeN0p}0
zOCY-diE0Bdzzfp_$Sx3e)9XkZS?xKMgsQq!zl-%YY8%K2Ky_}c;ew)m
z08Ise+uxfEK*`C;uDvk%jfJ9`Q+2cqk&cRS0*q?0x=y`1_o9YTsJu@`}!iM6SYg
z8y^-kseR)byPQ6KPV(y3fb6tVC#{<&({5fn>2=b2l}4wZ
zJWdk_NLT8J9j`Osy5;JWrIW^EFm#KHU4UfKZATr*gDvK@6MM3&K6D1!j{4InPj{pv
zlrDAwa`MEhI?3*UL?XRTnL24y_u4?e$2LG-cBGTC?Bww}t)2232o|Giq61J;Qj+7T
z471L%t8T2+oN7Sq)};f3P8wCaqVRik0rK*O-3)-;ypc$6w@fel&P7>G10c7Z?>{2dLxUDa+jcTx)*J=7D1P&jPrUj4=XhvzA4yad
zAH{r410c5p|lb24Hv
zln1YW#9r^mL{v^h=cbwDDWnO!FQ8^|K-^V8L5p0Z@8UQqqoKFxc6umPkCcPRq2L
z&u)5UZ^vK)pU-zC7z~aLofF+)0Hpw+Kp^mWWo6}TFYS>?!Dtr-yXj+)4Xq|6Cnx`_
zqM~BH08mvVB@m8ghXevZX@NjsMny%%|Kcoet=5_(@=E2oQ9aEC7-xiff$2;P%wnzg6H3oq2>f=s+zyGhnU~r5ZfMk2cX<2R{aFf?*dt)FU4zm83h;U-(
zlMq0#f3VF%{i>nor{ied3Tz;J{2__M4C%zg#EE~{M2mj3A6s7_rHBUAA`t9m8j;H
zRK4t0Jvm(oscKgv{T=XpLPTpqs*9^Hcwm4hVgLa+00cFLH;ph`2%m(6gz-L~?;Rp4
z2nK_&lOl4tkr;0BM&xE1zEA*ifQXh7(JvA_c;%rj^@Zl!l|WpLaVZ4j8LABS5I(K`
zpn9;+=X=HH^9>}Twjtm==_)q>xXJ5D=`+i(Jq3=szj&~TUl4*&2v
zoYvK_-QIL+GXjW9Awa{Wj%YO7l0HsUm=S!UVa;LUstbSP07VZ<0D%vO1b?}qEE~+W
z;c*L)n4haD4wLx*xa5f*KrE^veYmO;zjxe1uLf5vM})_Xt>yTp;u-6DK$I#R7!H;A
z*KwD51&|deUf1FHW}9(F86?lTB0jjDb!GD`C=O8b9Cy#|Iu4L$UD-SfiUZU<$KA8L
zjsxUbS2oXr;s7p#8cGujyV7T002ovPDHLk
FV1n(B6w&|y
literal 0
HcmV?d00001
diff --git a/src/all/hentaicosplay/res/mipmap-xxxhdpi/ic_launcher.png b/src/all/hentaicosplay/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000000000000000000000000000000000000..28c6c8b1ab2876c682ede4338f682393b1569f76
GIT binary patch
literal 11683
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
ZuL%|kud~Y1XcYnO!YFDeRLGeJ{Ra_cJ~IFS
literal 0
HcmV?d00001
diff --git a/src/all/hentaicosplay/src/eu/kanade/tachiyomi/extension/all/hentaicosplay/HentaiCosplay.kt b/src/all/hentaicosplay/src/eu/kanade/tachiyomi/extension/all/hentaicosplay/HentaiCosplay.kt
new file mode 100644
index 000000000..30c67c201
--- /dev/null
+++ b/src/all/hentaicosplay/src/eu/kanade/tachiyomi/extension/all/hentaicosplay/HentaiCosplay.kt
@@ -0,0 +1,282 @@
+package eu.kanade.tachiyomi.extension.all.hentaicosplay
+
+import android.util.Log
+import eu.kanade.tachiyomi.network.GET
+import eu.kanade.tachiyomi.source.model.Filter
+import eu.kanade.tachiyomi.source.model.FilterList
+import eu.kanade.tachiyomi.source.model.MangasPage
+import eu.kanade.tachiyomi.source.model.Page
+import eu.kanade.tachiyomi.source.model.SChapter
+import eu.kanade.tachiyomi.source.model.SManga
+import eu.kanade.tachiyomi.source.model.UpdateStrategy
+import eu.kanade.tachiyomi.source.online.HttpSource
+import eu.kanade.tachiyomi.util.asJsoup
+import okhttp3.Request
+import okhttp3.Response
+import org.jsoup.nodes.Document
+import rx.Observable
+import rx.Single
+import rx.schedulers.Schedulers
+import java.lang.UnsupportedOperationException
+import java.text.SimpleDateFormat
+import java.util.Locale
+
+class HentaiCosplay : HttpSource() {
+
+ override val name = "Hentai Cosplay"
+
+ override val baseUrl = "https://hentai-cosplays.com"
+
+ override val lang = "all"
+
+ override val supportsLatest = true
+
+ override val client = network.cloudflareClient
+
+ override fun headersBuilder() = super.headersBuilder()
+ .set("Referer", "$baseUrl/")
+
+ private val dateCache = mutableMapOf()
+
+ override fun fetchPopularManga(page: Int): Observable {
+ fetchFilters()
+ return super.fetchPopularManga(page)
+ }
+
+ override fun popularMangaRequest(page: Int): Request {
+ return GET("$baseUrl/ranking/page/$page/", headers)
+ }
+
+ override fun popularMangaParse(response: Response): MangasPage {
+ val document = response.asJsoup()
+
+ return if (document.selectFirst("div.image-list-item") == null) {
+ parseMobileListing(document)
+ } else {
+ parseDesktopListing(document)
+ }
+ }
+
+ private fun parseMobileListing(document: Document): MangasPage {
+ val entries = document.select("#entry_list > li > a[href*=/image/]")
+ .map { element ->
+ SManga.create().apply {
+ setUrlWithoutDomain(element.absUrl("href"))
+ thumbnail_url = element.selectFirst("img")
+ ?.absUrl("data-original")
+ ?.replace("http://", "https://")
+ title = element.selectFirst("span:not(.posted)")!!.text()
+ element.selectFirst("span.posted")
+ ?.text()?.also { dateCache[url] = it }
+ update_strategy = UpdateStrategy.ONLY_FETCH_ONCE
+ status = SManga.COMPLETED
+ initialized = true
+ }
+ }
+ val hasNextPage = document.selectFirst("a.paginator_page[rel=next]") != null
+
+ return MangasPage(entries, hasNextPage)
+ }
+
+ private fun parseDesktopListing(document: Document): MangasPage {
+ val entries = document.select("div.image-list-item:has(a[href*=/image/])")
+ .map { element ->
+ SManga.create().apply {
+ setUrlWithoutDomain(element.selectFirst("a")!!.absUrl("href"))
+ thumbnail_url = element.selectFirst("img")
+ ?.absUrl("src")
+ ?.replace("http://", "https://")
+ title = element.select(".image-list-item-title").text()
+ element.selectFirst(".image-list-item-regist-date")
+ ?.text()?.also { dateCache[url] = it }
+ update_strategy = UpdateStrategy.ONLY_FETCH_ONCE
+ status = SManga.COMPLETED
+ initialized = true
+ }
+ }
+ val hasNextPage = document.selectFirst("div.wp-pagenavi > a[rel=next]") != null
+
+ return MangasPage(entries, hasNextPage)
+ }
+
+ override fun fetchLatestUpdates(page: Int): Observable {
+ fetchFilters()
+ return super.fetchLatestUpdates(page)
+ }
+
+ override fun latestUpdatesRequest(page: Int): Request {
+ return GET("$baseUrl/recently/page/$page/", headers)
+ }
+
+ override fun latestUpdatesParse(response: Response) = popularMangaParse(response)
+
+ override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable {
+ fetchFilters()
+ return super.fetchSearchManga(page, query, filters)
+ }
+
+ override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
+ if (query.isNotEmpty()) {
+ val keyword = query.trim().replace(" ", "+")
+ return GET("$baseUrl/search/keyword/$keyword/page/$page/", headers)
+ } else {
+ filters.forEach { filter ->
+ when (filter) {
+ is TagFilter -> {
+ if (filter.selected.isNotEmpty()) {
+ return GET("$baseUrl${filter.selected}page/$page/", headers)
+ }
+ }
+ is KeywordFilter -> {
+ if (filter.selected.isNotEmpty()) {
+ return GET("$baseUrl${filter.selected}page/$page/", headers)
+ }
+ }
+ else -> {}
+ }
+ }
+
+ return GET("$baseUrl/search/page/$page/", headers)
+ }
+ }
+
+ override fun searchMangaParse(response: Response) = popularMangaParse(response)
+
+ private var keyWordCache: List> = emptyList()
+ private var tagCache: List> = emptyList()
+
+ private fun fetchFilters() {
+ if (keyWordCache.isEmpty()) fetchKeywords()
+ if (tagCache.isEmpty()) fetchTags()
+ }
+
+ private fun fetchTags() {
+ Single.fromCallable {
+ client.newCall(GET("$baseUrl/ranking-tag/", headers))
+ .execute().asJsoup()
+ .run {
+ tagCache = buildList {
+ add(Pair("", ""))
+ select("#tags a").map {
+ Pair(
+ it.text()
+ .replace(tagNumRegex, "")
+ .trim(),
+ it.attr("href"),
+ ).let(::add)
+ }
+ }
+ }
+ }
+ .subscribeOn(Schedulers.io())
+ .observeOn(Schedulers.io())
+ .subscribe(
+ {},
+ {
+ Log.e(name, it.stackTraceToString())
+ },
+ )
+ }
+
+ private fun fetchKeywords() {
+ Single.fromCallable {
+ client.newCall(GET("$baseUrl/ranking-keyword/", headers))
+ .execute().asJsoup()
+ .run {
+ keyWordCache = buildList {
+ add(Pair("", ""))
+ select("#tags a").map {
+ add(Pair(it.text(), it.attr("href")))
+ }
+ }
+ }
+ }
+ .subscribeOn(Schedulers.io())
+ .observeOn(Schedulers.io())
+ .subscribe(
+ {},
+ {
+ Log.e(name, it.stackTraceToString())
+ },
+ )
+ }
+
+ private abstract class SelectFilter(
+ name: String,
+ private val options: List>,
+ ) : Filter.Select(
+ name,
+ options.map { it.first }.toTypedArray(),
+ ) {
+ val selected get() = options[state].second
+ }
+
+ private class TagFilter(name: String, options: List>) : SelectFilter(name, options)
+ private class KeywordFilter(name: String, options: List>) : SelectFilter(name, options)
+
+ override fun getFilterList(): FilterList {
+ return if (keyWordCache.isEmpty()) {
+ FilterList(Filter.Header("Press reset to attempt to load filters"))
+ } else {
+ FilterList(
+ Filter.Header("Ignored with text search"),
+ Filter.Header("Tag Filtered is preferred over Keyword filter"),
+ Filter.Separator(),
+ TagFilter("Ranked Tags", tagCache),
+ KeywordFilter("Ranked Keywords", keyWordCache),
+ )
+ }
+ }
+
+ override fun fetchMangaDetails(manga: SManga) = Observable.fromCallable {
+ manga.apply { initialized = true }
+ }
+
+ override fun mangaDetailsParse(response: Response) = throw UnsupportedOperationException()
+
+ override fun fetchChapterList(manga: SManga) = Observable.fromCallable {
+ SChapter.create().apply {
+ name = "Gallery"
+ url = manga.url.removeSuffix("/").plus("/attachment/1/")
+ date_upload = runCatching {
+ dateFormat.parse(dateCache[manga.url]!!)!!.time
+ }.getOrDefault(0L)
+ }.let(::listOf)
+ }
+
+ override fun chapterListParse(response: Response) = throw UnsupportedOperationException()
+
+ override fun pageListParse(response: Response): List {
+ val document = response.asJsoup()
+
+ val totalPages = document.selectFirst("#right_sidebar > h3, #title > h2")
+ ?.text()?.trim()
+ ?.run { pagesRegex.find(this)?.groupValues?.get(1) }
+ ?.toIntOrNull()
+ ?: return emptyList()
+
+ val imgUrl = document.selectFirst("#display_image_detail img, #detail_list img")
+ ?.absUrl("src")
+ ?.replace("http://", "https://")
+ ?.run { replace(hdRegex, "/") }
+ ?: return emptyList()
+
+ val imgUrlPrefix = imgUrl.substringBeforeLast("/")
+ val ext = imgUrl.substringAfterLast(".")
+
+ return (1..totalPages).map {
+ Page(it, "", "$imgUrlPrefix/$it.$ext")
+ }
+ }
+
+ override fun imageUrlParse(response: Response) = throw UnsupportedOperationException()
+
+ companion object {
+ private val tagNumRegex = Regex("""(\(\d+\))""")
+ private val pagesRegex = Regex("""\d+/(\d+)${'$'}""")
+ private val hdRegex = Regex("""(/p=\d+x?\d+?/)""")
+ private val dateFormat by lazy {
+ SimpleDateFormat("yyyy/MM/dd", Locale.ENGLISH)
+ }
+ }
+}