VCPVMP: Move to multisrc and add ChoChoX (#6356)
* move to multisrc and add chochox * lint * apply suggestions
This commit is contained in:
		
							parent
							
								
									bcf51e8138
								
							
						
					
					
						commit
						aa5804b858
					
				
							
								
								
									
										5
									
								
								lib-multisrc/vercomics/build.gradle.kts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								lib-multisrc/vercomics/build.gradle.kts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| plugins { | ||||
|     id("lib-multisrc") | ||||
| } | ||||
| 
 | ||||
| baseVersionCode = 1 | ||||
| @ -1,4 +1,4 @@ | ||||
| package eu.kanade.tachiyomi.extension.es.vcpvmp | ||||
| package eu.kanade.tachiyomi.multisrc.vercomics | ||||
| 
 | ||||
| import eu.kanade.tachiyomi.network.GET | ||||
| import eu.kanade.tachiyomi.source.model.Filter | ||||
| @ -8,45 +8,79 @@ 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.ParsedHttpSource | ||||
| import okhttp3.Headers | ||||
| import okhttp3.HttpUrl.Companion.toHttpUrl | ||||
| import okhttp3.Request | ||||
| import org.jsoup.nodes.Document | ||||
| import org.jsoup.nodes.Element | ||||
| import rx.Observable | ||||
| 
 | ||||
| open class VCPVMP(override val name: String, override val baseUrl: String) : ParsedHttpSource() { | ||||
| 
 | ||||
|     override val lang = "es" | ||||
| abstract class VerComics( | ||||
|     override val name: String, | ||||
|     override val baseUrl: String, | ||||
|     override val lang: String, | ||||
| ) : ParsedHttpSource() { | ||||
| 
 | ||||
|     override val supportsLatest: Boolean = false | ||||
| 
 | ||||
|     override fun headersBuilder(): Headers.Builder { | ||||
|         return Headers.Builder() | ||||
|             .add("Referer", "$baseUrl/") | ||||
|     } | ||||
|     protected open val urlSuffix = "" | ||||
|     protected open val genreSuffix = "" | ||||
|     protected open val useSuffixOnSearch = true | ||||
| 
 | ||||
|     override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException() | ||||
| 
 | ||||
|     override fun latestUpdatesSelector() = throw UnsupportedOperationException() | ||||
| 
 | ||||
|     override fun latestUpdatesFromElement(element: Element) = throw UnsupportedOperationException() | ||||
| 
 | ||||
|     override fun latestUpdatesNextPageSelector() = throw UnsupportedOperationException() | ||||
|     override fun headersBuilder() = super.headersBuilder() | ||||
|         .add("Referer", "$baseUrl/") | ||||
| 
 | ||||
|     override fun popularMangaRequest(page: Int) = GET("$baseUrl/$urlSuffix/page/$page", headers) | ||||
| 
 | ||||
|     override fun popularMangaSelector() = "div.blog-list-items > div.entry" | ||||
|     override fun popularMangaSelector() = "header:has(h1) ~ * .entry" | ||||
| 
 | ||||
|     override fun popularMangaNextPageSelector() = "div.wp-pagenavi > span.current + a" | ||||
| 
 | ||||
|     override fun popularMangaFromElement(element: Element) = SManga.create().apply { | ||||
|         element.select("a.popimg").first()!!.let { | ||||
|             setUrlWithoutDomain(it.attr("href")) | ||||
|             title = it.select("img").attr("alt") | ||||
|             thumbnail_url = it.select("img:not(noscript img)").attr("abs:data-src") | ||||
|             thumbnail_url = it.selectFirst("img:not(noscript img)")?.imgAttr() | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun popularMangaNextPageSelector() = "div.wp-pagenavi > span.current + a" | ||||
|     override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { | ||||
|         var url = baseUrl.toHttpUrl().newBuilder() | ||||
| 
 | ||||
|         if (query.isNotBlank()) { | ||||
|             url = baseUrl.toHttpUrl().newBuilder() | ||||
|             if (useSuffixOnSearch) { | ||||
|                 url.addPathSegments(urlSuffix) | ||||
|             } | ||||
|             url.addPathSegments("page") | ||||
|             url.addPathSegments(page.toString()) | ||||
|             url.addQueryParameter("s", query) | ||||
| 
 | ||||
|             return GET(url.build(), headers) | ||||
|         } | ||||
| 
 | ||||
|         filters.forEach { filter -> | ||||
|             when (filter) { | ||||
|                 is Genre -> { | ||||
|                     if (filter.toUriPart().isNotEmpty()) { | ||||
|                         url.addPathSegments(genreSuffix) | ||||
|                         url.addPathSegments(filter.toUriPart()) | ||||
| 
 | ||||
|                         url.addPathSegments("page") | ||||
|                         url.addPathSegments(page.toString()) | ||||
|                     } | ||||
|                 } | ||||
|                 else -> {} | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return GET(url.build(), headers) | ||||
|     } | ||||
| 
 | ||||
|     override fun searchMangaSelector() = popularMangaSelector() | ||||
| 
 | ||||
|     override fun searchMangaNextPageSelector() = popularMangaNextPageSelector() | ||||
| 
 | ||||
|     override fun searchMangaFromElement(element: Element) = popularMangaFromElement(element) | ||||
| 
 | ||||
|     override fun mangaDetailsParse(document: Document) = SManga.create().apply { | ||||
|         document.select("div.tax_post").let { | ||||
| @ -81,50 +115,13 @@ open class VCPVMP(override val name: String, override val baseUrl: String) : Par | ||||
|     override fun chapterListSelector() = throw UnsupportedOperationException() | ||||
|     override fun chapterFromElement(element: Element) = throw UnsupportedOperationException() | ||||
| 
 | ||||
|     protected open val pageListSelector = "div.wp-content p > img:not(noscript img)" | ||||
|     protected open val pageListSelector = | ||||
|         "div.wp-content p > img:not(noscript img), " + | ||||
|             "div.wp-content div#lector > img:not(noscript img), " + | ||||
|             "div.wp-content > figure img:not(noscript img)" | ||||
| 
 | ||||
|     override fun pageListParse(document: Document): List<Page> = document.select(pageListSelector) | ||||
|         .mapIndexed { i, img -> Page(i, "", img.attr("abs:data-src")) } | ||||
| 
 | ||||
|     override fun imageUrlParse(document: Document) = throw UnsupportedOperationException() | ||||
| 
 | ||||
|     protected open val urlSuffix = "" | ||||
|     protected open val genreSuffix = "" | ||||
| 
 | ||||
|     override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { | ||||
|         var url = baseUrl.toHttpUrl().newBuilder() | ||||
| 
 | ||||
|         if (query.isNotBlank()) { | ||||
|             url = "$baseUrl/$urlSuffix".toHttpUrl().newBuilder() | ||||
|             url.addPathSegments("page") | ||||
|             url.addPathSegments(page.toString()) | ||||
|             url.addQueryParameter("s", query) | ||||
| 
 | ||||
|             return GET(url.build(), headers) | ||||
|         } | ||||
| 
 | ||||
|         filters.forEach { filter -> | ||||
|             when (filter) { | ||||
|                 is Genre -> { | ||||
|                     if (filter.toUriPart().isNotEmpty()) { | ||||
|                         url.addPathSegments(genreSuffix) | ||||
|                         url.addPathSegments(filter.toUriPart()) | ||||
| 
 | ||||
|                         url.addPathSegments("page") | ||||
|                         url.addPathSegments(page.toString()) | ||||
|                     } | ||||
|                 } | ||||
|                 else -> {} | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return GET(url.build(), headers) | ||||
|     } | ||||
| 
 | ||||
|     override fun searchMangaSelector() = popularMangaSelector() | ||||
| 
 | ||||
|     override fun searchMangaFromElement(element: Element) = popularMangaFromElement(element) | ||||
| 
 | ||||
|     override fun searchMangaNextPageSelector() = popularMangaNextPageSelector() | ||||
|         .mapIndexed { i, img -> Page(i, imageUrl = img.imgAttr()) } | ||||
| 
 | ||||
|     protected open var genres = arrayOf(Pair("Ver todos", "")) | ||||
| 
 | ||||
| @ -138,11 +135,45 @@ open class VCPVMP(override val name: String, override val baseUrl: String) : Par | ||||
|         return FilterList(filters) | ||||
|     } | ||||
| 
 | ||||
|     // Array.from(document.querySelectorAll('div.tagcloud a.tag-cloud-link')).map(a => `Pair("${a.innerText}", "${a.href.replace('https://vercomicsporno.com/etiquetas/', '')}")`).join(',\n') | ||||
|     // from https://vercomicsporno.com/ | ||||
|     protected open fun Element.imgAttr(): String? { | ||||
|         return when { | ||||
|             this.hasAttr("data-src") -> this.attr("abs:data-src") | ||||
|             this.hasAttr("data-lazy-src") -> this.attr("abs:data-lazy-src") | ||||
|             this.hasAttr("srcset") -> this.attr("abs:srcset").getSrcSetImage() | ||||
|             this.hasAttr("data-cfsrc") -> this.attr("abs:data-cfsrc") | ||||
|             else -> this.attr("abs:src") | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private class Genre(genres: Array<Pair<String, String>>) : UriPartFilter( | ||||
|     private fun String.getSrcSetImage(): String? { | ||||
|         return this.split(" ") | ||||
|             .filter(URL_REGEX::matches) | ||||
|             .maxOfOrNull(String::toString) | ||||
|     } | ||||
| 
 | ||||
|     // Replace the baseUrl and genreSuffix in the following string | ||||
|     // Array.from(document.querySelectorAll('div.tagcloud a.tag-cloud-link')).map(a => `Pair("${a.innerText}", "${a.href.replace('$baseUrl/genreSuffix/', '')}")`).join(',\n') | ||||
|     class Genre(genres: Array<Pair<String, String>>) : UriPartFilter( | ||||
|         "Filtrar por género", | ||||
|         genres, | ||||
|     ) | ||||
| 
 | ||||
|     override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException() | ||||
| 
 | ||||
|     override fun latestUpdatesSelector() = throw UnsupportedOperationException() | ||||
| 
 | ||||
|     override fun latestUpdatesNextPageSelector() = throw UnsupportedOperationException() | ||||
| 
 | ||||
|     override fun latestUpdatesFromElement(element: Element) = throw UnsupportedOperationException() | ||||
| 
 | ||||
|     override fun imageUrlParse(document: Document) = throw UnsupportedOperationException() | ||||
| 
 | ||||
|     companion object { | ||||
|         val URL_REGEX = """^(https?://[^\s/$.?#].[^\s]*)${'$'}""".toRegex() | ||||
|     } | ||||
| 
 | ||||
|     open class UriPartFilter(displayName: String, private val vals: Array<Pair<String, String>>) : | ||||
|         Filter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) { | ||||
|         fun toUriPart() = vals[state].second | ||||
|     } | ||||
| } | ||||
							
								
								
									
										9
									
								
								src/es/chochox/build.gradle
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/es/chochox/build.gradle
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| ext { | ||||
|     extName = 'ChoChoX' | ||||
|     extClass = '.Chochox' | ||||
|     themePkg = 'vercomics' | ||||
|     overrideVersionCode = 0 | ||||
|     isNsfw = true | ||||
| } | ||||
| 
 | ||||
| apply from: "$rootDir/common.gradle" | ||||
							
								
								
									
										
											BIN
										
									
								
								src/es/chochox/res/mipmap-hdpi/ic_launcher.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/es/chochox/res/mipmap-hdpi/ic_launcher.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 4.2 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/es/chochox/res/mipmap-mdpi/ic_launcher.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/es/chochox/res/mipmap-mdpi/ic_launcher.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 2.4 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/es/chochox/res/mipmap-xhdpi/ic_launcher.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/es/chochox/res/mipmap-xhdpi/ic_launcher.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 6.0 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/es/chochox/res/mipmap-xxhdpi/ic_launcher.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/es/chochox/res/mipmap-xxhdpi/ic_launcher.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 11 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/es/chochox/res/mipmap-xxxhdpi/ic_launcher.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/es/chochox/res/mipmap-xxxhdpi/ic_launcher.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 16 KiB | 
| @ -0,0 +1,35 @@ | ||||
| package eu.kanade.tachiyomi.extension.es.chochox | ||||
| 
 | ||||
| import eu.kanade.tachiyomi.multisrc.vercomics.VerComics | ||||
| 
 | ||||
| class Chochox : VerComics("ChoChoX", "https://chochox.com", "es") { | ||||
| 
 | ||||
|     override val urlSuffix = "porno" | ||||
|     override val genreSuffix = "tag" | ||||
|     override val useSuffixOnSearch = false | ||||
| 
 | ||||
|     override var genres = | ||||
|         arrayOf( | ||||
|             Pair("Ver todos", ""), | ||||
|             Pair("Anal", "anal-xxx-comics"), | ||||
|             Pair("Comics Porno 3D", "comics-3d"), | ||||
|             Pair("Culonas", "culonas-comicsporno-xxx"), | ||||
|             Pair("Dragon Ball", "dragon-ball-porno"), | ||||
|             Pair("Full Color", "full-color"), | ||||
|             Pair("Furry Hentai", "furry-hentai-comics"), | ||||
|             Pair("Futanari", "futanari-comics"), | ||||
|             Pair("Hinata XXX", "hinata-xxx"), | ||||
|             Pair("Lesbianas", "lesbianas"), | ||||
|             Pair("Mamadas", "mamadas-comics-porno"), | ||||
|             Pair("Milfs", "milfs-porno-comics"), | ||||
|             Pair("My Hero Academia XXX", "my-hero-academia-xxx"), | ||||
|             Pair("Naruto Hentai XXX", "naruto-hentai-xxx"), | ||||
|             Pair("Parodia Porno", "parodia-porno"), | ||||
|             Pair("Parodias Porno", "parodias-porno-comics-porno"), | ||||
|             Pair("Series TV Porno", "series-tv-xxx-comics-porno"), | ||||
|             Pair("Sonic", "sonic"), | ||||
|             Pair("Steven Universe", "steven-universe-xxx"), | ||||
|             Pair("Tetonas", "tetonas-comics"), | ||||
|             Pair("Vaginal", "vaginal-comics-porno"), | ||||
|         ) | ||||
| } | ||||
| @ -1,7 +1,8 @@ | ||||
| ext { | ||||
|     extName = 'VCPVMP' | ||||
|     extClass = '.VCPVMPFactory' | ||||
|     extVersionCode = 9 | ||||
|     themePkg = 'vercomics' | ||||
|     overrideVersionCode = 9 | ||||
|     isNsfw = true | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -1,8 +1,8 @@ | ||||
| package eu.kanade.tachiyomi.extension.es.vcpvmp | ||||
| 
 | ||||
| import eu.kanade.tachiyomi.multisrc.vercomics.VerComics | ||||
| import eu.kanade.tachiyomi.source.Source | ||||
| import eu.kanade.tachiyomi.source.SourceFactory | ||||
| import eu.kanade.tachiyomi.source.model.Filter | ||||
| 
 | ||||
| class VCPVMPFactory : SourceFactory { | ||||
|     override fun createSources(): List<Source> = listOf( | ||||
| @ -11,68 +11,63 @@ class VCPVMPFactory : SourceFactory { | ||||
|     ) | ||||
| } | ||||
| 
 | ||||
| class VCP : VCPVMP("VCP", "https://vercomicsporno.com") { | ||||
| class VCP : VerComics("VCP", "https://vercomicsporno.com", "es") { | ||||
| 
 | ||||
|     override val urlSuffix = "comics-porno" | ||||
|     override val genreSuffix = "etiquetas" | ||||
|     override var genres = | ||||
|         arrayOf( | ||||
|             Pair("Ver todos", ""), | ||||
|             Pair("Anales", "anales"), | ||||
|             Pair("Anime", "anime"), | ||||
|             Pair("Aprobado por c1b3r3y3", "aprobado-por-c1b3r3y3"), | ||||
|             Pair("Comics Incesto", "incesto-xxx"), | ||||
|             Pair("Anal", "anal"), | ||||
|             Pair("Big Ass", "big-ass"), | ||||
|             Pair("Big Breasts", "big-breasts"), | ||||
|             Pair("Big Cock", "big-cock"), | ||||
|             Pair("Big Penis", "big-penis"), | ||||
|             Pair("Big Tits", "big-tits"), | ||||
|             Pair("Blowjob", "blowjob"), | ||||
|             Pair("Culonas", "culonas"), | ||||
|             Pair("Furry", "furry-3"), | ||||
|             Pair("Futanari", "futanari-2"), | ||||
|             Pair("Lesbianas", "lesbianas"), | ||||
|             Pair("Madre Hijo", "madre-hijo"), | ||||
|             Pair("Cum", "cum"), | ||||
|             Pair("Dark Skin", "dark-skin"), | ||||
|             Pair("Furry", "furry"), | ||||
|             Pair("Hot Girls", "hot-girls"), | ||||
|             Pair("Incest", "incest"), | ||||
|             Pair("Mamadas", "mamadas"), | ||||
|             Pair("Manga Hentai", "manga-hentai-3"), | ||||
|             Pair("Masturbaciones", "madre-hijo"), | ||||
|             Pair("Milfs", "milfs-xxx"), | ||||
|             Pair("Orgias", "orgias"), | ||||
|             Pair("Parodias Porno", "parodias-porno-xxx"), | ||||
|             Pair("Rubias", "rubias"), | ||||
|             Pair("Milf", "milf"), | ||||
|             Pair("Muscle", "muscle"), | ||||
|             Pair("Nakadashi", "nakadashi"), | ||||
|             Pair("Sole Female", "sole-female"), | ||||
|             Pair("Sole Male", "sole-male"), | ||||
|             Pair("Tetonas", "tetonas"), | ||||
|             Pair("Trios", "trios"), | ||||
|             Pair("Videojuegos", "videojuegos-2"), | ||||
|             Pair("Yuri", "yuri-xxx"), | ||||
|         ) | ||||
| } | ||||
| 
 | ||||
| class VMP : VCPVMP("VMP", "https://vermangasporno.com") { | ||||
| class VMP : VerComics("VMP", "https://vermangasporno.com", "es") { | ||||
| 
 | ||||
|     override val urlSuffix = "xxx" | ||||
|     override val genreSuffix = "genero" | ||||
|     override val genreSuffix = "tag" | ||||
| 
 | ||||
|     override var genres = | ||||
|         arrayOf( | ||||
|             Pair("Ver todos", ""), | ||||
|             Pair("Ahegao", "ahegao"), | ||||
|             Pair("Anal", "anal"), | ||||
|             Pair("Big Ass", "big-ass"), | ||||
|             Pair("Big Breasts", "big-breasts"), | ||||
|             Pair("Blowjob", "blowjob"), | ||||
|             Pair("Cheating", "cheating"), | ||||
|             Pair("Big Penis", "big-penis"), | ||||
|             Pair("BlowJob", "blowjob"), | ||||
|             Pair("Creampie", "creampie"), | ||||
|             Pair("Cum", "cum"), | ||||
|             Pair("Group", "group"), | ||||
|             Pair("Hairy", "hairy"), | ||||
|             Pair("Kissing", "kissing"), | ||||
|             Pair("Incest", "incest"), | ||||
|             Pair("Manga Hentai", "manga-hentai"), | ||||
|             Pair("Milf", "milf"), | ||||
|             Pair("Mosaic Censorship", "mosaic-censorship"), | ||||
|             Pair("Nakadashi", "nakadashi"), | ||||
|             Pair("Paizuri", "paizuri"), | ||||
|             Pair("Schoolgirl Uniform", "schoolgirl-uniform"), | ||||
|             Pair("Sin Censura", "sin-censura"), | ||||
|             Pair("Sole Female", "sole-female"), | ||||
|             Pair("Sole Male", "sole-male"), | ||||
|             Pair("Squirting", "squirting"), | ||||
|             Pair("Stockings", "stockings"), | ||||
|             Pair("Student", "student"), | ||||
|             Pair("Unusual Pupils", "unusual-pupils"), | ||||
|         ) | ||||
| } | ||||
| 
 | ||||
| open class UriPartFilter(displayName: String, private val vals: Array<Pair<String, String>>) : | ||||
|     Filter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) { | ||||
|     fun toUriPart() = vals[state].second | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 bapeey
						bapeey