Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 9.1 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 49 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 8.6 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 65 KiB |
After Width: | Height: | Size: 6.3 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 282 KiB |
After Width: | Height: | Size: 6.3 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 282 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 7.0 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 95 KiB |
After Width: | Height: | Size: 4.7 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 6.1 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 68 KiB |
|
@ -0,0 +1,17 @@
|
|||
package eu.kanade.tachiyomi.extension.en.mangabat
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.mangabox.MangaBox
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import okhttp3.Request
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class Mangabat : MangaBox("Mangabat", "https://mangabat.com", "en", SimpleDateFormat("MMM dd,yy", Locale.ENGLISH)) {
|
||||
override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/manga-list-all/$page?type=topview", headers)
|
||||
override fun popularMangaSelector() = "div.list-story-item"
|
||||
override val latestUrlPath = "manga-list-all/"
|
||||
override fun searchMangaSelector() = "div.list-story-item"
|
||||
override fun getAdvancedGenreFilters(): List<AdvGenre> = getGenreFilters()
|
||||
.drop(1)
|
||||
.map { AdvGenre(it.first, it.second) }
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package eu.kanade.tachiyomi.extension.en.mangairo
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.mangabox.MangaBox
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import okhttp3.Request
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class Mangairo : MangaBox("Mangairo", "https://m.mangairo.com", "en", SimpleDateFormat("MMM-dd-yy", Locale.ENGLISH)) {
|
||||
override val popularUrlPath = "manga-list/type-topview/ctg-all/state-all/page-"
|
||||
override fun popularMangaSelector() = "div.story-item"
|
||||
override val latestUrlPath = "manga-list/type-latest/ctg-all/state-all/page-"
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||
return GET("$baseUrl/$simpleQueryPath${normalizeSearchQuery(query)}?page=$page", headers)
|
||||
}
|
||||
|
||||
override fun searchMangaSelector() = "div.story-item"
|
||||
override fun searchMangaFromElement(element: Element): SManga = mangaFromElement(element, "h2 a")
|
||||
override fun searchMangaNextPageSelector() = "div.group-page a.select + a:not(.go-p-end)"
|
||||
override val mangaDetailsMainSelector = "${super.mangaDetailsMainSelector}, div.story_content"
|
||||
override val thumbnailSelector = "${super.thumbnailSelector}, div.story_info_left img"
|
||||
override val descriptionSelector = "${super.descriptionSelector}, div#story_discription p"
|
||||
override fun chapterListSelector() = "${super.chapterListSelector()}, div#chapter_list li"
|
||||
override val alternateChapterDateSelector = "p"
|
||||
override val pageListSelector = "${super.pageListSelector}, div.panel-read-story img"
|
||||
|
||||
// will have to write a separate searchMangaRequest to get filters working for this source
|
||||
override fun getFilterList() = FilterList()
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package eu.kanade.tachiyomi.extension.en.mangakakalot
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.mangabox.MangaBox
|
||||
import okhttp3.Headers
|
||||
|
||||
class Mangakakalot : MangaBox("Mangakakalot", "https://mangakakalot.com", "en") {
|
||||
override fun headersBuilder(): Headers.Builder = super.headersBuilder().set("Referer", "https://manganelo.com") // for covers
|
||||
override val simpleQueryPath = "search/story/"
|
||||
override fun searchMangaSelector() = "${super.searchMangaSelector()}, div.list-truyen-item-wrap"
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package eu.kanade.tachiyomi.extension.en.mangakakalots
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.mangabox.MangaBox
|
||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import okhttp3.Response
|
||||
|
||||
|
||||
class Mangakakalots : MangaBox("Mangakakalots (unoriginal)", "https://mangakakalots.com", "en") {
|
||||
override fun searchMangaSelector(): String = "${super.searchMangaSelector()}, div.list-truyen-item-wrap"
|
||||
override fun searchMangaParse(response: Response): MangasPage {
|
||||
val document = response.asJsoup()
|
||||
val mangas = document.select(searchMangaSelector()).map { mangaFromElement(it) }
|
||||
val hasNextPage = !response.request().url().toString()
|
||||
.contains(document.select(searchMangaNextPageSelector()).attr("href"))
|
||||
|
||||
return MangasPage(mangas, hasNextPage)
|
||||
}
|
||||
override fun searchMangaNextPageSelector() = "div.group_page a:last-of-type"
|
||||
override fun getStatusFilters(): Array<Pair<String?, String>> = arrayOf(
|
||||
Pair("all", "ALL"),
|
||||
Pair("Completed", "Completed"),
|
||||
Pair("Ongoing", "Ongoing")
|
||||
)
|
||||
override fun getGenreFilters(): Array<Pair<String?, String>> = arrayOf(
|
||||
Pair("all", "ALL"),
|
||||
Pair("Action", "Action"),
|
||||
Pair("Adult", "Adult"),
|
||||
Pair("Adventure", "Adventure"),
|
||||
Pair("Comedy", "Comedy"),
|
||||
Pair("Cooking", "Cooking"),
|
||||
Pair("Doujinshi", "Doujinshi"),
|
||||
Pair("Drama", "Drama"),
|
||||
Pair("Ecchi", "Ecchi"),
|
||||
Pair("Fantasy", "Fantasy"),
|
||||
Pair("Gender bender", "Gender bender"),
|
||||
Pair("Harem", "Harem"),
|
||||
Pair("Historical", "Historical"),
|
||||
Pair("Horror", "Horror"),
|
||||
Pair("Isekai", "Isekai"),
|
||||
Pair("Josei", "Josei"),
|
||||
Pair("Manhua", "Manhua"),
|
||||
Pair("Manhwa", "Manhwa"),
|
||||
Pair("Martial arts", "Martial arts"),
|
||||
Pair("Mature", "Mature"),
|
||||
Pair("Mecha", "Mecha"),
|
||||
Pair("Medical", "Medical"),
|
||||
Pair("Mystery", "Mystery"),
|
||||
Pair("One shot", "One shot"),
|
||||
Pair("Psychological", "Psychological"),
|
||||
Pair("Romance", "Romance"),
|
||||
Pair("School life", "School life"),
|
||||
Pair("Sci fi", "Sci fi"),
|
||||
Pair("Seinen", "Seinen"),
|
||||
Pair("Shoujo", "Shoujo"),
|
||||
Pair("Shoujo ai", "Shoujo ai"),
|
||||
Pair("Shounen", "Shounen"),
|
||||
Pair("Shounen ai", "Shounen ai"),
|
||||
Pair("Slice of life", "Slice of life"),
|
||||
Pair("Smut", "Smut"),
|
||||
Pair("Sports", "Sports"),
|
||||
Pair("Supernatural", "Supernatural"),
|
||||
Pair("Tragedy", "Tragedy"),
|
||||
Pair("Webtoons", "Webtoons"),
|
||||
Pair("Yaoi", "Yaoi"),
|
||||
Pair("Yuri", "Yuri")
|
||||
)
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package eu.kanade.tachiyomi.extension.en.manganelo
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.mangabox.MangaBox
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import okhttp3.Request
|
||||
|
||||
|
||||
class Manganelo : MangaBox("Manganelo", "https://manganelo.com", "en") {
|
||||
// Nelo's date format is part of the base class
|
||||
override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/genre-all/$page?type=topview", headers)
|
||||
override fun popularMangaSelector() = "div.content-genres-item"
|
||||
override val latestUrlPath = "genre-all/"
|
||||
override val simpleQueryPath = "search/story/"
|
||||
override fun searchMangaSelector() = "div.search-story-item, div.content-genres-item"
|
||||
override fun getAdvancedGenreFilters(): List<AdvGenre> = getGenreFilters()
|
||||
.drop(1)
|
||||
.map { AdvGenre(it.first, it.second) }
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package eu.kanade.tachiyomi.extension.all.mangabox
|
||||
package eu.kanade.tachiyomi.multisrc.mangabox
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import eu.kanade.tachiyomi.network.GET
|
|
@ -0,0 +1,29 @@
|
|||
package eu.kanade.tachiyomi.multisrc.mangabox
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.ThemeSourceGenerator
|
||||
import eu.kanade.tachiyomi.multisrc.ThemeSourceGenerator.Companion.ThemeSourceData.SingleLang
|
||||
|
||||
|
||||
class MangaBoxGenerator : ThemeSourceGenerator {
|
||||
|
||||
override val themePkg = "mangabox"
|
||||
|
||||
override val themeClass = "MangaBox"
|
||||
|
||||
override val baseVersionCode: Int = 1
|
||||
|
||||
override val sources = listOf(
|
||||
SingleLang("Mangakakalot", "https://mangakakalot.com", "en"),
|
||||
SingleLang("Manganelo", "https://manganelo.com", "en"),
|
||||
SingleLang("Mangabat", "https://mangabat.com", "en"),
|
||||
SingleLang("Mangakakalots (unoriginal)", "https://mangakakalots.com", "en", className = "Mangakakalots", pkgName = "mangakakalots"),
|
||||
SingleLang("Mangairo", "https://m.mangairo.com", "en"),
|
||||
)
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun main(args: Array<String>) {
|
||||
MangaBoxGenerator().createAll()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="eu.kanade.tachiyomi.extension" />
|
|
@ -1,12 +0,0 @@
|
|||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
ext {
|
||||
extName = 'MangaBox (Mangakakalot and others)'
|
||||
pkgNameSuffix = 'all.mangabox'
|
||||
extClass = '.MangaBoxFactory'
|
||||
extVersionCode = 24
|
||||
libVersion = '1.2'
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
|
@ -1,134 +0,0 @@
|
|||
package eu.kanade.tachiyomi.extension.all.mangabox
|
||||
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.source.SourceFactory
|
||||
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.Headers
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class MangaBoxFactory : SourceFactory {
|
||||
override fun createSources(): List<Source> = listOf(
|
||||
Mangakakalot(),
|
||||
Manganelo(),
|
||||
Mangabat(),
|
||||
OtherMangakakalot(),
|
||||
Mangairo()
|
||||
)
|
||||
}
|
||||
|
||||
class Mangakakalot : MangaBox("Mangakakalot", "https://mangakakalot.com", "en") {
|
||||
override fun headersBuilder(): Headers.Builder = super.headersBuilder().set("Referer", "https://manganelo.com") // for covers
|
||||
override val simpleQueryPath = "search/story/"
|
||||
override fun searchMangaSelector() = "${super.searchMangaSelector()}, div.list-truyen-item-wrap"
|
||||
}
|
||||
|
||||
class Manganelo : MangaBox("Manganelo", "https://manganelo.com", "en") {
|
||||
// Nelo's date format is part of the base class
|
||||
override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/genre-all/$page?type=topview", headers)
|
||||
override fun popularMangaSelector() = "div.content-genres-item"
|
||||
override val latestUrlPath = "genre-all/"
|
||||
override val simpleQueryPath = "search/story/"
|
||||
override fun searchMangaSelector() = "div.search-story-item, div.content-genres-item"
|
||||
override fun getAdvancedGenreFilters(): List<AdvGenre> = getGenreFilters()
|
||||
.drop(1)
|
||||
.map { AdvGenre(it.first, it.second) }
|
||||
}
|
||||
|
||||
class Mangabat : MangaBox("Mangabat", "https://mangabat.com", "en", SimpleDateFormat("MMM dd,yy", Locale.ENGLISH)) {
|
||||
override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/manga-list-all/$page?type=topview", headers)
|
||||
override fun popularMangaSelector() = "div.list-story-item"
|
||||
override val latestUrlPath = "manga-list-all/"
|
||||
override fun searchMangaSelector() = "div.list-story-item"
|
||||
override fun getAdvancedGenreFilters(): List<AdvGenre> = getGenreFilters()
|
||||
.drop(1)
|
||||
.map { AdvGenre(it.first, it.second) }
|
||||
}
|
||||
|
||||
class OtherMangakakalot : MangaBox("Mangakakalots (unoriginal)", "https://mangakakalots.com", "en") {
|
||||
override fun searchMangaSelector(): String = "${super.searchMangaSelector()}, div.list-truyen-item-wrap"
|
||||
override fun searchMangaParse(response: Response): MangasPage {
|
||||
val document = response.asJsoup()
|
||||
val mangas = document.select(searchMangaSelector()).map { mangaFromElement(it) }
|
||||
val hasNextPage = !response.request().url().toString()
|
||||
.contains(document.select(searchMangaNextPageSelector()).attr("href"))
|
||||
|
||||
return MangasPage(mangas, hasNextPage)
|
||||
}
|
||||
override fun searchMangaNextPageSelector() = "div.group_page a:last-of-type"
|
||||
override fun getStatusFilters(): Array<Pair<String?, String>> = arrayOf(
|
||||
Pair("all", "ALL"),
|
||||
Pair("Completed", "Completed"),
|
||||
Pair("Ongoing", "Ongoing")
|
||||
)
|
||||
override fun getGenreFilters(): Array<Pair<String?, String>> = arrayOf(
|
||||
Pair("all", "ALL"),
|
||||
Pair("Action", "Action"),
|
||||
Pair("Adult", "Adult"),
|
||||
Pair("Adventure", "Adventure"),
|
||||
Pair("Comedy", "Comedy"),
|
||||
Pair("Cooking", "Cooking"),
|
||||
Pair("Doujinshi", "Doujinshi"),
|
||||
Pair("Drama", "Drama"),
|
||||
Pair("Ecchi", "Ecchi"),
|
||||
Pair("Fantasy", "Fantasy"),
|
||||
Pair("Gender bender", "Gender bender"),
|
||||
Pair("Harem", "Harem"),
|
||||
Pair("Historical", "Historical"),
|
||||
Pair("Horror", "Horror"),
|
||||
Pair("Isekai", "Isekai"),
|
||||
Pair("Josei", "Josei"),
|
||||
Pair("Manhua", "Manhua"),
|
||||
Pair("Manhwa", "Manhwa"),
|
||||
Pair("Martial arts", "Martial arts"),
|
||||
Pair("Mature", "Mature"),
|
||||
Pair("Mecha", "Mecha"),
|
||||
Pair("Medical", "Medical"),
|
||||
Pair("Mystery", "Mystery"),
|
||||
Pair("One shot", "One shot"),
|
||||
Pair("Psychological", "Psychological"),
|
||||
Pair("Romance", "Romance"),
|
||||
Pair("School life", "School life"),
|
||||
Pair("Sci fi", "Sci fi"),
|
||||
Pair("Seinen", "Seinen"),
|
||||
Pair("Shoujo", "Shoujo"),
|
||||
Pair("Shoujo ai", "Shoujo ai"),
|
||||
Pair("Shounen", "Shounen"),
|
||||
Pair("Shounen ai", "Shounen ai"),
|
||||
Pair("Slice of life", "Slice of life"),
|
||||
Pair("Smut", "Smut"),
|
||||
Pair("Sports", "Sports"),
|
||||
Pair("Supernatural", "Supernatural"),
|
||||
Pair("Tragedy", "Tragedy"),
|
||||
Pair("Webtoons", "Webtoons"),
|
||||
Pair("Yaoi", "Yaoi"),
|
||||
Pair("Yuri", "Yuri")
|
||||
)
|
||||
}
|
||||
|
||||
class Mangairo : MangaBox("Mangairo", "https://m.mangairo.com", "en", SimpleDateFormat("MMM-dd-yy", Locale.ENGLISH)) {
|
||||
override val popularUrlPath = "manga-list/type-topview/ctg-all/state-all/page-"
|
||||
override fun popularMangaSelector() = "div.story-item"
|
||||
override val latestUrlPath = "manga-list/type-latest/ctg-all/state-all/page-"
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||
return GET("$baseUrl/$simpleQueryPath${normalizeSearchQuery(query)}?page=$page", headers)
|
||||
}
|
||||
override fun searchMangaSelector() = "div.story-item"
|
||||
override fun searchMangaFromElement(element: Element): SManga = mangaFromElement(element, "h2 a")
|
||||
override fun searchMangaNextPageSelector() = "div.group-page a.select + a:not(.go-p-end)"
|
||||
override val mangaDetailsMainSelector = "${super.mangaDetailsMainSelector}, div.story_content"
|
||||
override val thumbnailSelector = "${super.thumbnailSelector}, div.story_info_left img"
|
||||
override val descriptionSelector = "${super.descriptionSelector}, div#story_discription p"
|
||||
override fun chapterListSelector() = "${super.chapterListSelector()}, div#chapter_list li"
|
||||
override val alternateChapterDateSelector = "p"
|
||||
override val pageListSelector = "${super.pageListSelector}, div.panel-read-story img"
|
||||
// will have to write a separate searchMangaRequest to get filters working for this source
|
||||
override fun getFilterList() = FilterList()
|
||||
}
|