EroMuse split (#5708)

* split eromuse

* revert EroMuse

* add nsfw annotation
This commit is contained in:
Aria Moradi
2021-02-08 14:53:17 -08:00
committed by GitHub
parent 975b311637
commit b14b910407
12 changed files with 37 additions and 27 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1006 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

View File

@ -0,0 +1,9 @@
package eu.kanade.tachiyomi.extension.en.eightmuses
import eu.kanade.tachiyomi.annotations.Nsfw
import eu.kanade.tachiyomi.multisrc.eromuse.EroMuse
import kotlin.ExperimentalStdlibApi
@ExperimentalStdlibApi
@Nsfw
class EightMuses : EroMuse("8Muses", "https://comics.8muses.com")

View File

@ -0,0 +1,167 @@
package eu.kanade.tachiyomi.extension.en.erofus
import eu.kanade.tachiyomi.annotations.Nsfw
import eu.kanade.tachiyomi.multisrc.eromuse.EroMuse
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.HttpUrl
import okhttp3.Response
import rx.Observable
@ExperimentalStdlibApi
@Nsfw
class Erofus : EroMuse("Erofus", "https://www.erofus.com") {
override val albumSelector = "a.a-click"
override val topLevelPathSegment = "comics"
override fun fetchPopularManga(page: Int): Observable<MangasPage> = fetchManga("$baseUrl/comics/various-authors?sort=viewed&page=1", page, "viewed")
override fun fetchLatestUpdates(page: Int): Observable<MangasPage> = fetchManga("$baseUrl/comics/various-authors?sort=recent&page=1", page, "recent")
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
if (page == 1) {
pageStack.clear()
val filterList = if (filters.isEmpty()) getFilterList() else filters
currentSortingMode = filterList.filterIsInstance<SortFilter>().first().toQueryValue()
if (query.isNotBlank()) {
// TODO possibly add genre search if a decent list of them can be built
pageStack.addLast(StackItem("$baseUrl/?search=$query&sort=$currentSortingMode&page=1", SEARCH_RESULTS_OR_BASE))
} else {
val albumFilter = filterList.filterIsInstance<AlbumFilter>().first().selection()
val url = HttpUrl.parse(baseUrl + albumFilter.pathSegments)!!.newBuilder()
.addQueryParameter("sort", currentSortingMode)
.addQueryParameter("page", "1")
pageStack.addLast(StackItem(url.toString(), albumFilter.pageType))
}
}
return client.newCall(stackRequest())
.asObservableSuccess()
.map { response -> parseManga(response.asJsoup()) }
}
override fun mangaDetailsParse(response: Response): SManga {
return SManga.create().apply {
with(response.asJsoup()) {
setUrlWithoutDomain(response.request().url().toString())
thumbnail_url = select("$albumSelector img").firstOrNull()?.imgAttr()
author = when (getAlbumType(url)) {
AUTHOR -> {
// eg. https://www.erofus.com/comics/witchking00-comics/adventure-time
// eg. https://www.erofus.com/comics/mcc-comics/bearing-gifts/bearing-gifts-issue-1
select("div.navigation-breadcrumb li:nth-child(3)").text()
}
VARIOUS_AUTHORS -> {
// eg. https://www.erofus.com/comics/various-authors/artdude41/bat-vore
select("div.navigation-breadcrumb li:nth-child(5)").text()
}
else -> null
}
genre = select("div.album-tag-container a").joinToString { it.text() }
}
}
}
override val linkedChapterSelector = "a.a-click:has(img)[href^=/comics/]"
override val pageThumbnailSelector = "a.a-click:has(img)[href*=/pic/] img"
override val pageThumbnailPathSegment = "/thumb/"
override val pageFullSizePathSegment = "/medium/"
override fun getAlbumList() = arrayOf(
Triple("All Authors", "", SEARCH_RESULTS_OR_BASE),
Triple("Various Authors", "/comics/various-authors", VARIOUS_AUTHORS),
Triple("Hentai and Manga English", "/comics/hentai-and-manga-english", VARIOUS_AUTHORS),
Triple("TabooLicious.xxx Comics", "/comics/taboolicious_xxx-comics", AUTHOR),
Triple("IllustratedInterracial.com Comics", "/comics/illustratedinterracial_com-comics", AUTHOR),
Triple("ZZZ Comics", "/comics/zzz-comics", AUTHOR),
Triple("JohnPersons.com Comics", "/comics/johnpersons_com-comics", AUTHOR),
Triple("For members only", "/", AUTHOR),
Triple("PalComix Comics", "/comics/palcomix-comics", AUTHOR),
Triple("Melkormancin.com Comics", "/comics/melkormancin_com-comics", AUTHOR),
Triple("TG Comics", "/comics/tg-comics", AUTHOR),
Triple("ShadBase Comics", "/comics/shadbase-comics", AUTHOR),
Triple("Filthy Figments Comics", "/comics/filthy-figments-comics", AUTHOR),
Triple("Witchking00 Comics", "/comics/witchking00-comics", AUTHOR),
Triple("Tease Comix", "/comics/tease-comix", AUTHOR),
Triple("PrismGirls Comics", "/comics/prismgirls-comics", AUTHOR),
Triple("Croc Comics", "/comics/croc-comics", AUTHOR),
Triple("CRAZYXXX3DWORLD Comics", "/comics/crazyxxx3dworld-comics", AUTHOR),
Triple("Moiarte Comics", "/comics/moiarte-comics", AUTHOR),
Triple("Nicole Heat Comics", "/comics/nicole-heat-comics", AUTHOR),
Triple("Expansion Comics", "/comics/expansion-comics", AUTHOR),
Triple("DizzyDills Comics", "/comics/dizzydills-comics", AUTHOR),
Triple("Hustler Cartoons", "/comics/hustler-cartoons", AUTHOR),
Triple("ArtOfJaguar Comics", "/comics/artofjaguar-comics", AUTHOR),
Triple("Grow Comics", "/comics/grow-comics", AUTHOR),
Triple("Bimbo Story Club Comics", "/comics/bimbo-story-club-comics", AUTHOR),
Triple("HentaiTNA.com Comics", "/comics/hentaitna_com-comics", AUTHOR),
Triple("ZZomp Comics", "/comics/zzomp-comics", AUTHOR),
Triple("Seiren.com.br Comics", "/comics/seiren_com_br-comics", AUTHOR),
Triple("DukesHardcoreHoneys.com Comics", "/comics/dukeshardcorehoneys_com-comics", AUTHOR),
Triple("Frozen Parody Comics", "/comics/frozen-parody-comics", AUTHOR),
Triple("Giantess Club Comics", "/comics/giantess-club-comics", AUTHOR),
Triple("Ultimate3DPorn Comics", "/comics/ultimate3dporn-comics", AUTHOR),
Triple("Sean Harrington Comics", "/comics/sean-harrington-comics", AUTHOR),
Triple("Central Comics", "/comics/central-comics", AUTHOR),
Triple("Mana World Comics", "/comics/mana-world-comics", AUTHOR),
Triple("The Foxxx Comics", "/comics/the-foxxx-comics", AUTHOR),
Triple("Bloody Sugar Comics", "/comics/bloody-sugar-comics", AUTHOR),
Triple("Deuce Comics", "/comics/deuce-comics", AUTHOR),
Triple("Adult Empire Comics", "/comics/adult-empire-comics", AUTHOR),
Triple("SuperHeroineComixxx", "/comics/superheroinecomixxx", AUTHOR),
Triple("Sluttish Comics", "/comics/sluttish-comics", AUTHOR),
Triple("Damn3D Comics", "/comics/damn3d-comics", AUTHOR),
Triple("Fake Celebrities Sex Pictures", "/comics/fake-celebrities-sex-pictures", AUTHOR),
Triple("Secret Chest Comics", "/comics/secret-chest-comics", AUTHOR),
Triple("Project Bellerophon Comics", "/comics/project-bellerophon-comics", AUTHOR),
Triple("Smudge Comics", "/comics/smudge-comics", AUTHOR),
Triple("Superheroine Central Comics", "/comics/superheroine-central-comics", AUTHOR),
Triple("Jay Marvel Comics", "/comics/jay-marvel-comics", AUTHOR),
Triple("Fred Perry Comics", "/comics/fred-perry-comics", AUTHOR),
Triple("Seduced Amanda Comics", "/comics/seduced-amanda-comics", AUTHOR),
Triple("VGBabes Comics", "/comics/vgbabes-comics", AUTHOR),
Triple("SodomSluts.com Comics", "/comics/sodomsluts_com-comics", AUTHOR),
Triple("AKABUR Comics", "/comics/akabur-comics", AUTHOR),
Triple("eBluberry Comics", "/comics/ebluberry-comics", AUTHOR),
Triple("InterracialComicPorn.com Comics", "/comics/interracialcomicporn_com-comics", AUTHOR),
Triple("Dubh3d-Dubhgilla Comics", "/comics/dubh3d-dubhgilla-comics", AUTHOR),
Triple("Gush Bomb Comix", "/comics/gush-bomb-comix", AUTHOR),
Triple("Chiyoji Tomo Comics", "/comics/chiyoji-tomo-comics", AUTHOR),
Triple("Mangrowing Comics", "/comics/mangrowing-comics", AUTHOR),
Triple("eAdultComics Collection", "/comics/eadultcomics-collection", AUTHOR),
Triple("Skulltitti Comics", "/comics/skulltitti-comics", AUTHOR),
Triple("James Lemay Comics", "/comics/james-lemay-comics", AUTHOR),
Triple("TalesOfPleasure.com Comics", "/comics/talesofpleasure_com-comics", AUTHOR),
Triple("Eden Comics", "/comics/eden-comics", AUTHOR),
Triple("WorldOfPeach Comics", "/comics/worldofpeach-comics", AUTHOR),
Triple("Daniel40 Comics", "/comics/daniel40-comics", AUTHOR),
Triple("DontFapGirl Comics", "/comics/dontfapgirl-comics", AUTHOR),
Triple("Wingbird Comics", "/comics/wingbird-comics", AUTHOR),
Triple("Intrigue3d.com Comics", "/comics/intrigue3d_com-comics", AUTHOR),
Triple("Hentaikey Comics", "/comics/hentaikey-comics", AUTHOR),
Triple("Kamina1978 Comics", "/comics/kamina1978-comics", AUTHOR),
Triple("3DPerils Comics", "/comics/3dperils-comics", AUTHOR),
Triple("Tracy Scops Comics", "/comics/tracy-scops-comics", AUTHOR),
Triple("Shemale3D Comics", "/comics/shemale3d-comics", AUTHOR),
Triple("InterracialSex3D.com Comics", "/comics/Interracialsex3d-Com-Comix", AUTHOR),
Triple("MyHentaiGrid Comics", "/comics/myhentaigrid-comics", AUTHOR),
Triple("Magnifire Comics", "/comics/magnifire-comics", AUTHOR),
Triple("Reptileye Comics", "/comics/reptileye-comics", AUTHOR),
Triple("ProjectPinkXXX.com Comics", "/comics/projectpinkxxx_com-comics", AUTHOR),
Triple("CallMePlisskin Comics", "/comics/callmeplisskin-comics", AUTHOR)
)
override fun getSortList() = arrayOf(
Pair("Viewed", "viewed"),
Pair("Liked", "liked"),
Pair("Date", "recent"),
Pair("A-Z", "az")
)
}

View File

@ -0,0 +1,438 @@
package eu.kanade.tachiyomi.multisrc.eromuse
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.asObservableSuccess
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.online.HttpSource
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.HttpUrl
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import rx.Observable
@ExperimentalStdlibApi
open class EroMuse(override val name: String, override val baseUrl: String) : HttpSource() {
override val lang = "en"
override val supportsLatest = true
override val client: OkHttpClient = network.cloudflareClient
/**
* Browse, search, and latest all run through an ArrayDeque of requests that acts as a stack we push and pop to/from
* For the fetch functions, we only need to worry about pushing the first page to the stack because subsequent pages
* get pushed to the stack during parseManga(). Page 1's URL must include page=1 if the next page would be page=2,
* if page 2 is path_to/2, nothing special needs to be done.
*/
// the stack - shouldn't need to touch these except for visibility
protected data class StackItem(val url: String, val pageType: Int)
private lateinit var stackItem: StackItem
protected val pageStack = ArrayDeque<StackItem>()
companion object {
const val VARIOUS_AUTHORS = 0
const val AUTHOR = 1
const val SEARCH_RESULTS_OR_BASE = 2
}
protected lateinit var currentSortingMode: String
private val albums = getAlbumList()
// might need to override for new sources
private val nextPageSelector = ".pagination span.current + span a"
protected open val albumSelector = "a.c-tile:has(img):not(:has(.members-only))"
protected open val topLevelPathSegment = "comics/album"
private val pageQueryRegex = Regex("""page=\d+""")
private fun Document.nextPageOrNull(): String? {
val url = this.location()
return this.select(nextPageSelector).firstOrNull()?.text()?.toIntOrNull()?.let { int ->
if (url.contains(pageQueryRegex)) {
url.replace(pageQueryRegex, "page=$int")
} else {
val httpUrl = HttpUrl.parse(url)!!
val builder = if (httpUrl.pathSegments().last().toIntOrNull() is Int) {
httpUrl.newBuilder().removePathSegment(httpUrl.pathSegments().lastIndex)
} else {
httpUrl.newBuilder()
}
builder.addPathSegment(int.toString()).toString()
}
}
}
private fun Document.addNextPageToStack() {
this.nextPageOrNull()?.let { pageStack.add(StackItem(it, stackItem.pageType)) }
}
protected fun Element.imgAttr(): String = if (this.hasAttr("data-src")) this.attr("abs:data-src") else this.attr("abs:src")
private fun mangaFromElement(element: Element): SManga {
return SManga.create().apply {
setUrlWithoutDomain(element.attr("href"))
title = element.text()
thumbnail_url = element.select("img").firstOrNull()?.imgAttr()
}
}
protected fun getAlbumType(url: String, default: Int = AUTHOR): Int {
return albums.filter { it.third != SEARCH_RESULTS_OR_BASE && url.contains(it.second, true) }
.getOrElse(0) { Triple(null, null, default) }.third
}
protected fun parseManga(document: Document): MangasPage {
fun internalParse(internalDocument: Document): List<SManga> {
val authorDocument = if (stackItem.pageType == VARIOUS_AUTHORS) {
internalDocument.select(albumSelector)?.let {
elements ->
elements.reversed().map { pageStack.addLast(StackItem(it.attr("abs:href"), AUTHOR)) }
}
client.newCall(stackRequest()).execute().asJsoup()
} else {
internalDocument
}
authorDocument.addNextPageToStack()
return authorDocument.select(albumSelector).map { mangaFromElement(it) }
}
if (stackItem.pageType in listOf(VARIOUS_AUTHORS, SEARCH_RESULTS_OR_BASE)) document.addNextPageToStack()
val mangas = when (stackItem.pageType) {
VARIOUS_AUTHORS -> {
document.select(albumSelector)?.let {
elements ->
elements.reversed().map { pageStack.addLast(StackItem(it.attr("abs:href"), AUTHOR)) }
}
internalParse(document)
}
AUTHOR -> {
internalParse(document)
}
SEARCH_RESULTS_OR_BASE -> {
val searchMangas = mutableListOf<SManga>()
document.select(albumSelector)
.map { element ->
val url = element.attr("abs:href")
val depth = url.removePrefix("$baseUrl/$topLevelPathSegment/").split("/").count()
when (getAlbumType(url)) {
VARIOUS_AUTHORS -> {
when (depth) {
1 -> { // eg. /comics/album/Fakku-Comics
pageStack.addLast(StackItem(url, VARIOUS_AUTHORS))
if (searchMangas.isEmpty()) searchMangas += internalParse(client.newCall(stackRequest()).execute().asJsoup()) else null
}
2 -> { // eg. /comics/album/Fakku-Comics/Bosshi
pageStack.addLast(StackItem(url, AUTHOR))
if (searchMangas.isEmpty()) searchMangas += internalParse(client.newCall(stackRequest()).execute().asJsoup()) else null
}
else -> {
// eg. 3 -> /comics/album/Fakku-Comics/Bosshi/After-Summer-After
// eg. 5 -> /comics/album/Various-Authors/Firollian/Reward/Reward-22/ElfAlfie
// eg. 6 -> /comics/album/Various-Authors/Firollian/Area69/Area69-no_1/SamusAran/001_Dialogue
searchMangas.add(mangaFromElement(element))
}
}
}
AUTHOR -> {
if (depth == 1) { // eg. /comics/album/ShadBase-Comics
pageStack.addLast(StackItem(url, AUTHOR))
if (searchMangas.isEmpty()) searchMangas += internalParse(client.newCall(stackRequest()).execute().asJsoup()) else null
} else {
// eg. 2 -> /comics/album/ShadBase-Comics/RickMorty
// eg. 3 -> /comics/album/Incase-Comics/Comic/Alfie
searchMangas.add(mangaFromElement(element))
}
}
else -> null // SEARCH_RESULTS_OR_BASE shouldn't be a case
}
}
searchMangas
}
else -> emptyList()
}
return MangasPage(mangas, pageStack.isNotEmpty())
}
protected fun stackRequest(): Request {
stackItem = pageStack.removeLast()
val url = if (stackItem.pageType == AUTHOR && currentSortingMode.isNotEmpty() && !stackItem.url.contains("sort")) {
HttpUrl.parse(stackItem.url)!!.newBuilder().addQueryParameter("sort", currentSortingMode).toString()
} else {
stackItem.url
}
return GET(url, headers)
}
// Popular
protected fun fetchManga(url: String, page: Int, sortingMode: String): Observable<MangasPage> {
if (page == 1) {
pageStack.clear()
pageStack.addLast(StackItem(url, VARIOUS_AUTHORS))
currentSortingMode = sortingMode
}
return client.newCall(stackRequest())
.asObservableSuccess()
.map { response -> parseManga(response.asJsoup()) }
}
override fun fetchPopularManga(page: Int): Observable<MangasPage> = fetchManga("$baseUrl/comics/album/Various-Authors", page, "")
override fun popularMangaRequest(page: Int): Request = throw UnsupportedOperationException("Not used")
override fun popularMangaParse(response: Response): MangasPage = throw UnsupportedOperationException("Not used")
// Latest
override fun fetchLatestUpdates(page: Int): Observable<MangasPage> = fetchManga("$baseUrl/comics/album/Various-Authors?sort=date", page, "date")
override fun latestUpdatesRequest(page: Int): Request = throw UnsupportedOperationException("Not used")
override fun latestUpdatesParse(response: Response): MangasPage = throw UnsupportedOperationException("Not used")
// Search
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
if (page == 1) {
pageStack.clear()
val filterList = if (filters.isEmpty()) getFilterList() else filters
currentSortingMode = filterList.filterIsInstance<SortFilter>().first().toQueryValue()
if (query.isNotBlank()) {
val url = HttpUrl.parse("$baseUrl/search?q=$query")!!.newBuilder().apply {
if (currentSortingMode.isNotEmpty()) addQueryParameter("sort", currentSortingMode)
addQueryParameter("page", "1")
}
pageStack.addLast(StackItem(url.toString(), SEARCH_RESULTS_OR_BASE))
} else {
val albumFilter = filterList.filterIsInstance<AlbumFilter>().first().selection()
val url = HttpUrl.parse("$baseUrl/comics/${albumFilter.pathSegments}")!!.newBuilder().apply {
if (currentSortingMode.isNotEmpty()) addQueryParameter("sort", currentSortingMode)
if (albumFilter.pageType != AUTHOR) addQueryParameter("page", "1")
}
pageStack.addLast(StackItem(url.toString(), albumFilter.pageType))
}
}
return client.newCall(stackRequest())
.asObservableSuccess()
.map { response -> parseManga(response.asJsoup()) }
}
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request = throw UnsupportedOperationException("Not used")
override fun searchMangaParse(response: Response): MangasPage = throw UnsupportedOperationException("Not used")
// Details
override fun mangaDetailsParse(response: Response): SManga {
return SManga.create().apply {
with(response.asJsoup()) {
setUrlWithoutDomain(response.request().url().toString())
thumbnail_url = select("$albumSelector img").firstOrNull()?.imgAttr()
author = when (getAlbumType(url)) {
AUTHOR -> {
// eg. https://comics.8muses.com/comics/album/ShadBase-Comics/RickMorty
// eg. https://comics.8muses.com/comics/album/Incase-Comics/Comic/Alfie
select("div.top-menu-breadcrumb li:nth-child(2)").text()
}
VARIOUS_AUTHORS -> {
// eg. https://comics.8muses.com/comics/album/Various-Authors/NLT-Media/A-Sunday-Schooling
select("div.top-menu-breadcrumb li:nth-child(3)").text()
}
else -> null
}
}
}
}
// Chapters
protected open val linkedChapterSelector = "a.c-tile:has(img)[href*=/comics/album/]"
protected open val pageThumbnailSelector = "a.c-tile:has(img)[href*=/comics/picture/] img"
override fun chapterListParse(response: Response): List<SChapter> {
fun parseChapters(document: Document, isFirstPage: Boolean, chapters: ArrayDeque<SChapter>): List<SChapter> {
// Linked chapters
document.select(linkedChapterSelector)
.mapNotNull {
chapters.addFirst(
SChapter.create().apply {
name = it.text()
setUrlWithoutDomain(it.attr("href"))
}
)
}
if (isFirstPage) {
// Self
document.select(pageThumbnailSelector).firstOrNull()?.let {
chapters.add(
SChapter.create().apply {
name = "Chapter"
setUrlWithoutDomain(response.request().url().toString())
}
)
}
}
document.nextPageOrNull()?.let { url -> parseChapters(client.newCall(GET(url, headers)).execute().asJsoup(), false, chapters) }
return chapters
}
return parseChapters(response.asJsoup(), true, ArrayDeque())
}
// Pages
protected open val pageThumbnailPathSegment = "/th/"
protected open val pageFullSizePathSegment = "/fl/"
override fun pageListParse(response: Response): List<Page> {
fun parsePages(
document: Document,
nestedChapterDocuments: ArrayDeque<Document> = ArrayDeque(),
pages: ArrayList<Page> = ArrayList()
): List<Page> {
// Nested chapters aka folders
document.select(linkedChapterSelector)
.mapNotNull {
nestedChapterDocuments.add(
client.newCall(GET(it.attr("abs:href"), headers)).execute().asJsoup()
)
}
var lastPage: Int = pages.size
pages.addAll(
document.select(pageThumbnailSelector).mapIndexed { i, img ->
Page(lastPage + i, "", img.imgAttr().replace(pageThumbnailPathSegment, pageFullSizePathSegment))
}
)
document.nextPageOrNull()?.let {
url ->
pages.addAll(parsePages(client.newCall(GET(url, headers)).execute().asJsoup(), nestedChapterDocuments, pages))
}
while (!nestedChapterDocuments.isEmpty()) {
pages.addAll(parsePages(nestedChapterDocuments.removeFirst()))
}
return pages
}
return parsePages(response.asJsoup())
}
override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException("Not used")
// Filters
override fun getFilterList(): FilterList {
return FilterList(
Filter.Header("Text search only combines with sort!"),
Filter.Separator(),
AlbumFilter(getAlbumList()),
SortFilter(getSortList())
)
}
protected class AlbumFilter(private val vals: Array<Triple<String, String, Int>>) : Filter.Select<String>("Album", vals.map { it.first }.toTypedArray()) {
fun selection() = AlbumFilterData(vals[state].second, vals[state].third)
data class AlbumFilterData(val pathSegments: String, val pageType: Int)
}
protected open fun getAlbumList() = arrayOf(
Triple("All Authors", "", SEARCH_RESULTS_OR_BASE),
Triple("Various Authors", "album/Various-Authors", VARIOUS_AUTHORS),
Triple("Fakku Comics", "album/Fakku-Comics", VARIOUS_AUTHORS),
Triple("Hentai and Manga English", "album/Hentai-and-Manga-English", VARIOUS_AUTHORS),
Triple("Fake Celebrities Sex Pictures", "album/Fake-Celebrities-Sex-Pictures", AUTHOR),
Triple("MilfToon Comics", "album/MilfToon-Comics", AUTHOR),
Triple("BE Story Club Comics", "album/BE-Story-Club-Comics", AUTHOR),
Triple("ShadBase Comics", "album/ShadBase-Comics", AUTHOR),
Triple("ZZZ Comics", "album/ZZZ-Comics", AUTHOR),
Triple("PalComix Comics", "album/PalComix-Comics", AUTHOR),
Triple("MCC Comics", "album/MCC-Comics", AUTHOR),
Triple("Expansionfan Comics", "album/Expansionfan-Comics", AUTHOR),
Triple("JAB Comics", "album/JAB-Comics", AUTHOR),
Triple("Giantess Fan Comics", "album/Giantess-Fan-Comics", AUTHOR),
Triple("Renderotica Comics", "album/Renderotica-Comics", AUTHOR),
Triple("IllustratedInterracial.com Comics", "album/IllustratedInterracial_com-Comics", AUTHOR),
Triple("Giantess Club Comics", "album/Giantess-Club-Comics", AUTHOR),
Triple("Innocent Dickgirls Comics", "album/Innocent-Dickgirls-Comics", AUTHOR),
Triple("Locofuria Comics", "album/Locofuria-Comics", AUTHOR),
Triple("PigKing - CrazyDad Comics", "album/PigKing-CrazyDad-Comics", AUTHOR),
Triple("Cartoon Reality Comics", "album/Cartoon-Reality-Comics", AUTHOR),
Triple("Affect3D Comics", "album/Affect3D-Comics", AUTHOR),
Triple("TG Comics", "album/TG-Comics", AUTHOR),
Triple("Melkormancin.com Comics", "album/Melkormancin_com-Comics", AUTHOR),
Triple("Seiren.com.br Comics", "album/Seiren_com_br-Comics", AUTHOR),
Triple("Tracy Scops Comics", "album/Tracy-Scops-Comics", AUTHOR),
Triple("Fred Perry Comics", "album/Fred-Perry-Comics", AUTHOR),
Triple("Witchking00 Comics", "album/Witchking00-Comics", AUTHOR),
Triple("8muses Comics", "album/8muses-Comics", AUTHOR),
Triple("KAOS Comics", "album/KAOS-Comics", AUTHOR),
Triple("Vaesark Comics", "album/Vaesark-Comics", AUTHOR),
Triple("Fansadox Comics", "album/Fansadox-Comics", AUTHOR),
Triple("DreamTales Comics", "album/DreamTales-Comics", AUTHOR),
Triple("Croc Comics", "album/Croc-Comics", AUTHOR),
Triple("Jay Marvel Comics", "album/Jay-Marvel-Comics", AUTHOR),
Triple("JohnPersons.com Comics", "album/JohnPersons_com-Comics", AUTHOR),
Triple("MuscleFan Comics", "album/MuscleFan-Comics", AUTHOR),
Triple("Taboolicious.xxx Comics", "album/Taboolicious_xxx-Comics", AUTHOR),
Triple("MongoBongo Comics", "album/MongoBongo-Comics", AUTHOR),
Triple("Slipshine Comics", "album/Slipshine-Comics", AUTHOR),
Triple("Everfire Comics", "album/Everfire-Comics", AUTHOR),
Triple("PrismGirls Comics", "album/PrismGirls-Comics", AUTHOR),
Triple("Abimboleb Comics", "album/Abimboleb-Comics", AUTHOR),
Triple("Y3DF - Your3DFantasy.com Comics", "album/Y3DF-Your3DFantasy_com-Comics", AUTHOR),
Triple("Grow Comics", "album/Grow-Comics", AUTHOR),
Triple("OkayOkayOKOk Comics", "album/OkayOkayOKOk-Comics", AUTHOR),
Triple("Tufos Comics", "album/Tufos-Comics", AUTHOR),
Triple("Cartoon Valley", "album/Cartoon-Valley", AUTHOR),
Triple("3DMonsterStories.com Comics", "album/3DMonsterStories_com-Comics", AUTHOR),
Triple("Kogeikun Comics", "album/Kogeikun-Comics", AUTHOR),
Triple("The Foxxx Comics", "album/The-Foxxx-Comics", AUTHOR),
Triple("Theme Collections", "album/Theme-Collections", AUTHOR),
Triple("Interracial-Comics", "album/Interracial-Comics", AUTHOR),
Triple("Expansion Comics", "album/Expansion-Comics", AUTHOR),
Triple("Moiarte Comics", "album/Moiarte-Comics", AUTHOR),
Triple("Incognitymous Comics", "album/Incognitymous-Comics", AUTHOR),
Triple("DizzyDills Comics", "album/DizzyDills-Comics", AUTHOR),
Triple("DukesHardcoreHoneys.com Comics", "album/DukesHardcoreHoneys_com-Comics", AUTHOR),
Triple("Stormfeder Comics", "album/Stormfeder-Comics", AUTHOR),
Triple("Bimbo Story Club Comics", "album/Bimbo-Story-Club-Comics", AUTHOR),
Triple("Smudge Comics", "album/Smudge-Comics", AUTHOR),
Triple("Dollproject Comics", "album/Dollproject-Comics", AUTHOR),
Triple("SuperHeroineComixxx", "album/SuperHeroineComixxx", AUTHOR),
Triple("Karmagik Comics", "album/Karmagik-Comics", AUTHOR),
Triple("Blacknwhite.com Comics", "album/Blacknwhite_com-Comics", AUTHOR),
Triple("ArtOfJaguar Comics", "album/ArtOfJaguar-Comics", AUTHOR),
Triple("Kirtu.com Comics", "album/Kirtu_com-Comics", AUTHOR),
Triple("UberMonkey Comics", "album/UberMonkey-Comics", AUTHOR),
Triple("DarkSoul3D Comics", "album/DarkSoul3D-Comics", AUTHOR),
Triple("Markydaysaid Comics", "album/Markydaysaid-Comics", AUTHOR),
Triple("Central Comics", "album/Central-Comics", AUTHOR),
Triple("Frozen Parody Comics", "album/Frozen-Parody-Comics", AUTHOR),
Triple("Blacknwhitecomics.com Comix", "album/Blacknwhitecomics_com-Comix", AUTHOR)
)
protected class SortFilter(private val vals: Array<Pair<String, String>>) : Filter.Select<String>("Sort Order", vals.map { it.first }.toTypedArray()) {
fun toQueryValue() = vals[state].second
}
protected open fun getSortList() = arrayOf(
Pair("Views", ""),
Pair("Likes", "like"),
Pair("Date", "date"),
Pair("A-Z", "az")
)
}

View File

@ -0,0 +1,25 @@
package eu.kanade.tachiyomi.multisrc.eromuse
import eu.kanade.tachiyomi.multisrc.ThemeSourceData.SingleLang
import eu.kanade.tachiyomi.multisrc.ThemeSourceGenerator
class EroMuseGenerator : ThemeSourceGenerator {
override val themePkg = "eromuse"
override val themeClass = "EroMuse"
override val baseVersionCode: Int = 1
override val sources = listOf(
SingleLang("8Muses", "https://comics.8muses.com", "en", className = "EightMuses"),
SingleLang("Erofus", "https://www.erofus.com", "en")
)
companion object {
@JvmStatic
fun main(args: Array<String>) {
EroMuseGenerator().createAll()
}
}
}