Bye bye Madara ()

* N-Z

* MZuki-N

* kbatch-mzuki

* remove madara

* remove wildcard

* nsfw

* pkg name

already got it from class name

* forgot className

* this too

* fix arangScans chapter and timestamp

* add mangaEffect

* add mangaGreat

* mangazuki.club multiLang

* forgot this line :v
This commit is contained in:
Riztard Lanthorn 2021-02-10 21:05:12 +07:00 committed by GitHub
parent 532ffb1892
commit bd5f42f8cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
88 changed files with 1022 additions and 1407 deletions
multisrc
overrides/madara
arangscans/src
lilymanga/src
lovablesubs/src
manga347/src
manga68/src
mangaaction/src
mangaarabonline/src
mangaarabteam/src
mangabaz/src
mangaclash/src
mangacrimson/src
mangadods/src
mangaeffect/src
mangagreat/src
mangalek/src
mangaonlineco/src
mangaphoenix/src
mangaread/src
mangareadorg/src
mangascantrad/src
mangaspark/src
mangastarz/src
mangasy/src
mangateca/src
mangayosh/src
mangazukiclub/src
manhuabox/src
manhuafast/src
manhuaplus/src
manhuaus/src
martialscans/src
milftoon/src
mixedmanga/src
mundowuxia/src
mysticalmerries/src
nazarickscans/src
neatmanga/src
nekobreaker/src
neoxscanlator/src
nightcomic/src
nijitranslations/src
offscan/src
pmscans/src
pojokmanga/src
projetoscanlator/src
queensmanga/src
randomtranslations/src
rawmangas/src
readmanhua/src
renascans/src
ruyamanga/src
shoujohearts/src
sixiangscans/src
siyahmelek/src
soloscanlation/src
spookyscanlations/src
stagecomics/src
threesixtyfivemanga/src
toongod/src
toonily/src
toonpoint/src
topmanhua/src
truyentranhaudiocom/src
truyentranhaudioonline/src
tsubakinoscan/src
turkcemanga/src
uyuyanbalik/src
voidscans/src
warqueenscan/src
webtoonxyz/src
wescans/src
worldromancetranslation/src
wuxiaworld/src
yaoitoshokan/src
yokaijump/src
yuriverso/src
zinmanga/src
src/main/java/eu/kanade/tachiyomi/multisrc/madara
src/all/madara
AndroidManifest.xmlbuild.gradle
res
src/eu/kanade/tachiyomi/extension/all/madara

@ -6,7 +6,8 @@ import okhttp3.Request
import java.text.SimpleDateFormat
import java.util.Locale
class ArangScans : Madara("Arang Scans", "https://www.arangscans.com", "en", SimpleDateFormat("d MMM yyyy", Locale.US)) {
class ArangScans : Madara("Arang Scans", "https://arangscans.com", "en") {
override val userAgentRandomizer = ""
// has very few manga
override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/manga?m_orderby=views", headers)
override fun popularMangaNextPageSelector(): String? = null

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.en.lilymanga
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class LilyManga : Madara("Lily Manga", "https://lilymanga.com", "en", SimpleDateFormat("yyyy-MM-dd", Locale.US))

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.tr.lovablesubs
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class LovableSubs : Madara("LovableSubs", "https://lovablesubs.com", "tr", SimpleDateFormat("dd MMM yyyy", Locale("tr")))

@ -0,0 +1,9 @@
package eu.kanade.tachiyomi.extension.en.manga347
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class Manga347 : Madara("Manga347", "https://manga347.com", "en", SimpleDateFormat("d MMM, yyyy", Locale.US)) {
override val pageListParseSelector = "li.blocks-gallery-item"
}

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.en.manga68
import eu.kanade.tachiyomi.multisrc.madara.Madara
class Manga68 : Madara("Manga68", "https://manga68.com", "en") {
override val pageListParseSelector = "div.page-break, div.text-left p"
}

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.ar.mangaaction
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class MangaAction : Madara("Manga Action", "https://manga-action.com", "ar", SimpleDateFormat("yyyy-MM-dd", Locale("ar")))

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.ar.mangaarabonline
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class MangaArabOnline : Madara("Manga Arab Online مانجا عرب اون لاين", "https://mangaarabonline.com", "ar", SimpleDateFormat("MMM d, yyyy", Locale.forLanguageTag("ar")))

@ -0,0 +1,14 @@
package eu.kanade.tachiyomi.extension.ar.mangaarabteam
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.source.model.Page
import okhttp3.Request
import java.text.SimpleDateFormat
import java.util.Locale
class MangaArabTeam : Madara("مانجا عرب تيم Manga Arab Team", "https://mangaarabteam.com", "ar", SimpleDateFormat("dd MMM، yyyy", Locale.forLanguageTag("ar"))) {
override fun imageRequest(page: Page): Request {
return GET(page.imageUrl!!.replace("http:", "https:"))
}
}

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.tr.mangabaz
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class MangaBaz : Madara("MangaBaz", "https://mangabaz.com", "tr", SimpleDateFormat("dd MMMM yyyy", Locale.forLanguageTag("tr")))

@ -0,0 +1,12 @@
package eu.kanade.tachiyomi.extension.en.mangaclash
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class MangaClash : Madara(
"Manga Clash",
"https://mangaclash.com",
"en",
dateFormat = SimpleDateFormat("MM/dd/yy", Locale.US)
)

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.tr.mangacrimson
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class MangaCrimson : Madara("Manga Crimson", "https://mangacrimson.com", "tr", SimpleDateFormat("dd MMMM yyyy", Locale("tr")))

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.en.mangadods
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class MangaDods : Madara("MangaDods", "https://www.mangadods.com", "en", SimpleDateFormat("yyyy-MM-dd", Locale.US))

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.en.mangaeffect
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class MangaEffect : Madara("MangaEffect", "https://mangaeffect.com", "en", SimpleDateFormat("dd.MM.yyyy", Locale.US))

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.en.mangagreat
import eu.kanade.tachiyomi.multisrc.madara.Madara
class MangaGreat : Madara("MangaGreat", "https://mangagreat.com", "en") {
override val pageListParseSelector = "li.blocks-gallery-item"
}

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.ar.mangalek
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class Mangalek : Madara("مانجا ليك", "https://mangalek.com", "ar", SimpleDateFormat("MMMM dd, yyyy", Locale("ar")))

@ -0,0 +1,11 @@
package eu.kanade.tachiyomi.extension.th.mangaonlineco
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.source.model.SChapter
import okhttp3.Response
import java.text.SimpleDateFormat
import java.util.Locale
class MangaOnlineCo : Madara("Manga-Online.co", "https://www.manga-online.co", "th", SimpleDateFormat("MMM dd, yyyy", Locale("th"))) {
override fun chapterListParse(response: Response): List<SChapter> = super.chapterListParse(response).reversed()
}

@ -0,0 +1,8 @@
package eu.kanade.tachiyomi.extension.tr.mangaphoenix
import eu.kanade.tachiyomi.multisrc.madara.Madara
class MangaPhoenix : Madara("Manga Diyari", "https://mangadiyari.com", "tr") {
// Formerly "Manga Phoenix"
override val id = 4308007020001642101
}

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.en.mangaread
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class MangaRead : Madara("Manga Read", "https://mangaread.co", "en", SimpleDateFormat("yyyy-MM-dd", Locale.US))

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.en.mangareadorg
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class MangaReadOrg : Madara("MangaRead.org", "https://www.mangaread.org", "en", SimpleDateFormat("dd.MM.yyy", Locale.US))

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.fr.mangascantrad
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class MangaScantrad : Madara("Manga-Scantrad", "https://manga-scantrad.net", "fr", SimpleDateFormat("d MMM yyyy", Locale.FRANCE))

@ -0,0 +1,24 @@
package eu.kanade.tachiyomi.extension.ar.mangaspark
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.source.model.SManga
import org.jsoup.nodes.Element
class MangaSpark : Madara("MangaSpark", "https://mangaspark.com", "ar") {
override fun popularMangaFromElement(element: Element): SManga {
val manga = SManga.create()
with(element) {
select(popularMangaUrlSelector).first()?.let {
manga.setUrlWithoutDomain(it.attr("abs:href"))
manga.title = it.ownText()
}
select("img").first()?.let {
manga.thumbnail_url = imageFromElement(it)?.replace("mangaspark", "mangalek")
}
}
return manga
}
}

@ -0,0 +1,24 @@
package eu.kanade.tachiyomi.extension.ar.mangastarz
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.source.model.SManga
import org.jsoup.nodes.Element
class MangaStarz : Madara("Manga Starz", "https://mangastarz.com", "ar") {
override fun popularMangaFromElement(element: Element): SManga {
val manga = SManga.create()
with(element) {
select(popularMangaUrlSelector).first()?.let {
manga.setUrlWithoutDomain(it.attr("abs:href"))
manga.title = it.ownText()
}
select("img").first()?.let {
manga.thumbnail_url = imageFromElement(it)?.replace("mangastarz", "mangalek")
}
}
return manga
}
}

@ -0,0 +1,12 @@
package eu.kanade.tachiyomi.extension.en.mangasy
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.source.model.Page
import okhttp3.CacheControl
import okhttp3.Request
class MangaSY : Madara("Manga SY", "https://www.mangasy.com", "en") {
override fun imageRequest(page: Page): Request = super.imageRequest(page).newBuilder()
.cacheControl(CacheControl.FORCE_NETWORK)
.build()
}

@ -0,0 +1,35 @@
package eu.kanade.tachiyomi.extension.pt.mangateca
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.source.model.SChapter
import okhttp3.Headers
import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Locale
class MangaTeca : Madara(
"MangaTeca",
"https://www.mangateca.com",
"pt-BR",
SimpleDateFormat("MMMM dd, yyyy", Locale("pt", "BR"))
) {
override fun headersBuilder(): Headers.Builder = Headers.Builder()
.add("User-Agent", USER_AGENT)
.add("Referer", baseUrl)
.add("Origin", baseUrl)
override fun chapterFromElement(element: Element): SChapter {
val parsedChapter = super.chapterFromElement(element)
parsedChapter.date_upload = element.select("img").firstOrNull()?.attr("alt")
?.let { parseChapterDate(it) }
?: parseChapterDate(element.select("span.chapter-release-date i").firstOrNull()?.text())
return parsedChapter
}
companion object {
private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36"
}
}

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.id.mangayosh
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class MangaYosh : Madara("MangaYosh", "https://mangayosh.xyz", "id", SimpleDateFormat("dd MMM yyyy", Locale.US))

@ -0,0 +1,14 @@
package eu.kanade.tachiyomi.extension.all.mangazukiclub
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceFactory
class MangazukiClubFactory : SourceFactory {
override fun createSources(): List<Source> = listOf(
MangazukiClubJP(),
MangazukiClubKO(),
)
}
class MangazukiClubJP : Madara("Mangazuki.club", "https://mangazuki.club", "ja")
class MangazukiClubKO : Madara("Mangazuki.club", "https://mangazuki.club", "ko")

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.en.manhuabox
import eu.kanade.tachiyomi.multisrc.madara.Madara
class ManhuaBox : Madara("ManhuaBox", "https://manhuabox.net", "en") {
override val pageListParseSelector = "div.page-break, div.text-left p img"
}

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.en.manhuafast
import eu.kanade.tachiyomi.multisrc.madara.Madara
class ManhuaFast : Madara("ManhuaFast", "https://manhuafast.com", "en") {
override val pageListParseSelector = "li.blocks-gallery-item"
}

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.en.manhuaplus
import eu.kanade.tachiyomi.multisrc.madara.Madara
class ManhuaPlus : Madara("Manhua Plus", "https://manhuaplus.com", "en") {
override val pageListParseSelector = "li.blocks-gallery-item"
}

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.en.manhuaus
import eu.kanade.tachiyomi.multisrc.madara.Madara
class ManhuaUS : Madara("ManhuaUS", "https://manhuaus.com", "en") {
override val pageListParseSelector = "li.blocks-gallery-item"
}

@ -0,0 +1,26 @@
package eu.kanade.tachiyomi.extension.en.martialscans
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.source.model.SManga
import org.jsoup.nodes.Element
class MartialScans : Madara("Martial Scans", "https://martialscans.com", "en") {
override fun popularMangaFromElement(element: Element): SManga {
val manga = SManga.create()
with(element) {
select(popularMangaUrlSelector).last()?.let {
manga.setUrlWithoutDomain(it.attr("href"))
manga.title = it.ownText()
}
select("img").last()?.let {
manga.thumbnail_url = imageFromElement(it)
}
}
return manga
}
override fun searchMangaFromElement(element: Element): SManga = popularMangaFromElement(element)
}

@ -0,0 +1,10 @@
package eu.kanade.tachiyomi.extension.en.milftoon
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.network.GET
import okhttp3.Request
class Milftoon : Madara("Milftoon", "https://milftoon.xxx", "en") {
override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/page/$page/?m_orderby=views", headers)
override fun latestUpdatesRequest(page: Int): Request = GET("$baseUrl/page/$page/?m_orderby=latest", headers)
}

@ -0,0 +1,10 @@
package eu.kanade.tachiyomi.extension.en.mixedmanga
import eu.kanade.tachiyomi.multisrc.madara.Madara
import okhttp3.Headers
import java.text.SimpleDateFormat
import java.util.Locale
class MixedManga : Madara("Mixed Manga", "https://mixedmanga.com", "en", SimpleDateFormat("d MMM yyyy", Locale.US)) {
override fun headersBuilder(): Headers.Builder = super.headersBuilder().add("Referer", baseUrl)
}

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.es.mundowuxia
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class MundoWuxia : Madara("Mundo Wuxia", "https://mundowuxia.com", "es", SimpleDateFormat("MMMM dd, yyyy", Locale("es")))

@ -0,0 +1,9 @@
package eu.kanade.tachiyomi.extension.en.mysticalmerries
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.network.GET
class MysticalMerries : Madara("Mystical Merries", "https://mysticalmerries.com", "en") {
override fun popularMangaRequest(page: Int) = GET("$baseUrl/genre/manhwa/page/$page/?m_orderby=trending", headers)
override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/genre/manhwa/page/$page/?m_orderby=latest", headers)
}

@ -0,0 +1,11 @@
package eu.kanade.tachiyomi.extension.en.nazarickscans
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.network.GET
class NazarickScans : Madara("Nazarick Scans", "https://nazarickscans.com", "en") {
override fun popularMangaRequest(page: Int) = GET("$baseUrl/manga/page/$page/?m_orderby=trending", headers)
override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/manga/page/$page/?m_orderby=trending", headers)
override fun popularMangaNextPageSelector(): String? = null
override fun latestUpdatesNextPageSelector(): String? = null
}

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.en.neatmanga
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class NeatManga : Madara("NeatManga", "https://neatmanga.com", "en", SimpleDateFormat("dd MMM yyyy", Locale.US))

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.pt.nekobreaker
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class NekoBreaker : Madara("NekoBreaker", "https://nekobreaker.com", "pt-BR", SimpleDateFormat("MMMM dd, yyyy", Locale("pt")))

@ -0,0 +1,34 @@
package eu.kanade.tachiyomi.extension.pt.neoxscanlator
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.source.model.FilterList
import okhttp3.Headers
import okhttp3.OkHttpClient
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.TimeUnit
class NeoxScanlator : Madara(
"Neox Scanlator",
"https://neoxscans.com",
"pt-BR",
SimpleDateFormat("dd/MM/yyyy", Locale("pt", "BR"))
) {
override val client: OkHttpClient = network.cloudflareClient.newBuilder()
.connectTimeout(1, TimeUnit.MINUTES)
.readTimeout(1, TimeUnit.MINUTES)
.build()
override fun headersBuilder(): Headers.Builder = Headers.Builder()
.add("User-Agent", USER_AGENT)
.add("Referer", baseUrl)
.add("Origin", baseUrl)
// Only status and order by filter work.
override fun getFilterList(): FilterList = FilterList(super.getFilterList().slice(3..4))
companion object {
private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"
}
}

@ -0,0 +1,11 @@
package eu.kanade.tachiyomi.extension.en.nightcomic
import eu.kanade.tachiyomi.multisrc.madara.Madara
import okhttp3.Headers
class NightComic : Madara("Night Comic", "https://www.nightcomic.com", "en") {
override val formHeaders: Headers = headersBuilder()
.add("Content-Type", "application/x-www-form-urlencoded")
.add("X-MOD-SBB-CTYPE", "xhr")
.build()
}

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.ar.nijitranslations
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class NijiTranslations : Madara("Niji Translations", "https://niji-translations.com", "ar", SimpleDateFormat("MMMM dd, yyyy", Locale("ar")))

@ -0,0 +1,12 @@
package eu.kanade.tachiyomi.extension.pt.offscan
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class OffScan : Madara(
"Off Scan",
"https://offscan.top",
"pt-BR",
dateFormat = SimpleDateFormat("dd/MM/yy", Locale.US)
)

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.en.pmscans
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class PMScans : Madara("PMScans", "https://www.pmscans.com", "en", SimpleDateFormat("MMM-dd-yy", Locale.US))

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.id.pojokmanga
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class PojokManga : Madara("Pojok Manga", "https://pojokmanga.com", "id", SimpleDateFormat("MMM dd, yyyy", Locale.US))

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.pt.projetoscanlator
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class ProjetoScanlator : Madara("Projeto Scanlator", "https://projetoscanlator.com", "pt-BR", SimpleDateFormat("dd/MM/yyyy", Locale("pt", "BR")))

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.ar.queensmanga
import eu.kanade.tachiyomi.multisrc.madara.Madara
class QueensManga : Madara("QueensManga ملكات المانجا", "https://queensmanga.com", "ar") {
override fun chapterListSelector(): String = "div.listing-chapters_wrap a"
}

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.en.randomtranslations
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class RandomTranslations : Madara("Random Translations", "https://randomtranslations.com", "en", SimpleDateFormat("dd/MM/yyyy", Locale.US))

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.ja.rawmangas
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class RawMangas : Madara("Raw Mangas", "https://rawmangas.net", "ja", SimpleDateFormat("MMMM dd, yyyy", Locale.US))

@ -0,0 +1,12 @@
package eu.kanade.tachiyomi.extension.en.readmanhua
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class ReadManhua : Madara(
"ReadManhua",
"https://readmanhua.net",
"en",
dateFormat = SimpleDateFormat("dd MMM yy", Locale.US)
)

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.en.renascans
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class RenaScans : Madara("Renascence Scans (Renascans)", "https://new.renascans.com", "en", SimpleDateFormat("dd/MM/yyyy", Locale.US))

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.tr.ruyamanga
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class RuyaManga : Madara("Rüya Manga", "https://www.ruyamanga.com", "tr", SimpleDateFormat("dd MMMM yyyy", Locale.forLanguageTag("tr")))

@ -0,0 +1,16 @@
package eu.kanade.tachiyomi.extension.en.shoujohearts
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.network.POST
import okhttp3.CacheControl
import okhttp3.Request
class ShoujoHearts : Madara("ShoujoHearts", "http://shoujohearts.com", "en") {
override fun popularMangaRequest(page: Int): Request =
POST("$baseUrl/reader/wp-admin/admin-ajax.php", formHeaders, formBuilder(page, true).build(), CacheControl.FORCE_NETWORK)
override fun latestUpdatesRequest(page: Int): Request =
POST("$baseUrl/reader/wp-admin/admin-ajax.php", formHeaders, formBuilder(page, false).build(), CacheControl.FORCE_NETWORK)
override fun searchPage(page: Int): String = "reader/page/$page/"
}

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.en.sixiangscans
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class SiXiangScans : Madara("SiXiang Scans", "http://www.sixiangscans.com", "en", SimpleDateFormat("MMMM dd, yyyy", Locale.US))

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.tr.siyahmelek
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class Siyahmelek : Madara("Siyahmelek", "https://siyahmelek.com", "tr", SimpleDateFormat("dd MMM yyyy", Locale("tr")))

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.en.soloscanlation
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class SoloScanlation : Madara("SoloScanlation", "https://soloscanlation.site", "en", SimpleDateFormat("MMMM dd, yyyy", Locale.US))

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.es.spookyscanlations
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class SpookyScanlations : Madara("Spooky Scanlations", "https://spookyscanlations.xyz", "es", SimpleDateFormat("MMMM dd, yyyy", Locale("es")))

@ -0,0 +1,19 @@
package eu.kanade.tachiyomi.extension.pt.stagecomics
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.source.model.SChapter
import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Locale
class StageComics : Madara("StageComics", "https://stagecomics.com", "pt-BR", SimpleDateFormat("MMMM dd, yyyy", Locale("pt"))) {
override fun chapterFromElement(element: Element): SChapter {
val parsedChapter = super.chapterFromElement(element)
parsedChapter.date_upload = element.select("img").firstOrNull()?.attr("alt")
?.let { parseChapterDate(it) }
?: parseChapterDate(element.select("span.chapter-release-date i").firstOrNull()?.text())
return parsedChapter
}
}

@ -0,0 +1,10 @@
package eu.kanade.tachiyomi.extension.en.threesixtyfivemanga
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.network.GET
import okhttp3.Request
class ThreeSixtyFiveManga : Madara("365Manga", "https://365manga.com", "en") {
override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/manga/page/$page/?m_orderby=views", headers)
override fun latestUpdatesRequest(page: Int): Request = GET("$baseUrl/manga/page/$page/?m_orderby=latest", headers)
}

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.en.toongod
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class ToonGod : Madara("ToonGod", "https://www.toongod.com", "en", SimpleDateFormat("dd MMM yyyy", Locale.US))

@ -0,0 +1,37 @@
package eu.kanade.tachiyomi.extension.en.toonily
import eu.kanade.tachiyomi.multisrc.madara.Madara
class Toonily : Madara("Toonily", "https://toonily.com", "en") {
override fun getGenreList(): List<Genre> = listOf(
Genre("Action", "action-webtoon"),
Genre("Adult", "adult-webtoon"),
Genre("Adventure", "adventure-webtoon"),
Genre("Comedy", "comedy-webtoon"),
Genre("Drama", "drama-webtoon"),
Genre("Fantasy", "fantasy-webtoon"),
Genre("Gender Bender", "gender-bender"),
Genre("Gossip", "gossip"),
Genre("Harem", "harem-webtoon"),
Genre("Historical", "webtoon-historical"),
Genre("Horror", "horror-webtoon"),
Genre("Josei", "josei-manga"),
Genre("Mature", "mature-webtoon"),
Genre("Mystery", "mystery-webtoon"),
Genre("NTR", "ntr-webtoon"),
Genre("Psychological", "psychological-webtoon"),
Genre("Romance", "romance-webtoon"),
Genre("School life", "school-life-webtoon"),
Genre("Sci-Fi", "scifi-webtoon"),
Genre("Seinen", "seinen-webtoon"),
Genre("Shoujo", "shoujo"),
Genre("Shounen", "shounen-webtoon"),
Genre("Slice of Life", "sliceoflife-webtoon"),
Genre("Supernatural", "supernatural-webtoon"),
Genre("Thriller", "thriller-webtoon"),
Genre("Tragedy", "tragedy"),
Genre("Vanilla", "vanilla-webtoon"),
Genre("Yaoi", "yaoi-webtoon"),
Genre("Yuri", "yuri-webtoon")
)
}

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.en.toonpoint
import eu.kanade.tachiyomi.multisrc.madara.Madara
class ToonPoint : Madara("ToonPoint", "https://toonpoint.com", "en") {
override val userAgentRandomizer = ""
}

@ -0,0 +1,10 @@
package eu.kanade.tachiyomi.extension.en.topmanhua
import eu.kanade.tachiyomi.multisrc.madara.Madara
import okhttp3.Headers
import java.text.SimpleDateFormat
import java.util.Locale
class TopManhua : Madara("Top Manhua", "https://topmanhua.com", "en", SimpleDateFormat("MM/dd/yy", Locale.US)) {
override fun headersBuilder(): Headers.Builder = super.headersBuilder().add("Referer", baseUrl)
}

@ -0,0 +1,26 @@
package eu.kanade.tachiyomi.extension.vi.truyentranhaudiocom
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SManga
import okhttp3.Request
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Locale
class TruyenTranhAudioCom : Madara("TruyenTranhAudio.com", "https://truyentranhaudio.com", "vi", SimpleDateFormat("dd/MM/yyyy", Locale.getDefault())) {
override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/page/$page?s&post_type=wp-manga&m_orderby=views", headers)
override fun popularMangaSelector() = searchMangaSelector()
override fun popularMangaFromElement(element: Element): SManga = searchMangaFromElement(element)
override fun latestUpdatesRequest(page: Int): Request = GET("$baseUrl/page/$page?s&post_type=wp-manga&m_orderby=latest", headers)
override fun latestUpdatesSelector() = searchMangaSelector()
override fun latestUpdatesFromElement(element: Element): SManga = searchMangaFromElement(element)
override fun pageListParse(document: Document): List<Page> {
return document.select("div.reading-content img").map { it.attr("abs:src") }
.filterNot { it.isNullOrEmpty() }
.distinct()
.mapIndexed { i, url -> Page(i, "", url) }
}
}

@ -0,0 +1,21 @@
package eu.kanade.tachiyomi.extension.vi.truyentranhaudioonline
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.source.model.Page
import okhttp3.Headers
import org.jsoup.nodes.Document
import java.text.SimpleDateFormat
import java.util.Locale
class TruyenTranhAudioOnline : Madara("TruyenTranhAudio.online", "https://truyentranhaudio.online", "vi", SimpleDateFormat("dd/MM/yyyy", Locale.getDefault())) {
override val formHeaders: Headers = headersBuilder()
.add("Content-Type", "application/x-www-form-urlencoded")
.build()
override fun pageListParse(document: Document): List<Page> {
return document.select("div.reading-content img").map { it.attr("abs:src") }
.filterNot { it.isNullOrEmpty() }
.distinct()
.mapIndexed { i, url -> Page(i, "", url) }
}
}

@ -0,0 +1,12 @@
package eu.kanade.tachiyomi.extension.fr.tsubakinoscan
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class TsubakiNoScan : Madara(
"Tsubaki No Scan",
"https://tsubakinoscan.com",
"fr",
dateFormat = SimpleDateFormat("dd/MM/yy", Locale.US)
)

@ -0,0 +1,30 @@
package eu.kanade.tachiyomi.extension.tr.turkcemanga
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
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.Page
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import okhttp3.CacheControl
import okhttp3.Headers
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.TimeUnit
class TurkceManga : Madara("Türkçe Manga", "https://turkcemanga.com", "tr") {
override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/page/$page/?s&post_type=wp-manga&m_orderby=views", headers)
override fun popularMangaSelector() = searchMangaSelector()
override fun popularMangaFromElement(element: Element): SManga = searchMangaFromElement(element)
override fun latestUpdatesRequest(page: Int): Request = GET("$baseUrl/page/$page/?s&post_type=wp-manga&m_orderby=latest", headers)
override fun latestUpdatesSelector() = searchMangaSelector()
override fun latestUpdatesFromElement(element: Element): SManga = searchMangaFromElement(element)
}

@ -0,0 +1,8 @@
package eu.kanade.tachiyomi.extension.tr.uyuyanbalik
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class UyuyanBalik : Madara("Uyuyan Balik", "https://uyuyanbalik.com/", "tr", SimpleDateFormat("dd MMMM yyyy", Locale.US))

@ -0,0 +1,9 @@
package eu.kanade.tachiyomi.extension.en.voidscans
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.source.model.FilterList
class Voidscans : Madara("Void Scans", "https://voidscans.com", "en") {
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = GET("$baseUrl/?s=$query&post_type=wp-manga")
}

@ -0,0 +1,8 @@
package eu.kanade.tachiyomi.extension.pt.warqueenscan
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class WarQueenScan : Madara("War Queen Scan", "https://wqscan.com", "pt-BR", SimpleDateFormat("dd/MM/yyyy", Locale.US))

@ -0,0 +1,11 @@
package eu.kanade.tachiyomi.extension.en.webtoonxyz
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.network.GET
import okhttp3.Request
class WebtoonXYZ : Madara("WebtoonXYZ", "https://www.webtoon.xyz", "en") {
private fun pagePath(page: Int) = if (page > 1) "page/$page/" else ""
override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/webtoons/${pagePath(page)}?m_orderby=views", headers)
override fun latestUpdatesRequest(page: Int): Request = GET("$baseUrl/webtoons/${pagePath(page)}?m_orderby=latest", headers)
}

@ -0,0 +1,15 @@
package eu.kanade.tachiyomi.extension.en.wescans
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.source.model.FilterList
import okhttp3.Request
class WeScans : Madara("WeScans", "https://wescans.xyz", "en") {
override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/manhua/manga/?m_orderby=views", headers)
override fun popularMangaNextPageSelector(): String? = null
override fun latestUpdatesRequest(page: Int): Request = GET("$baseUrl/manhua/manga/?m_orderby=latest", headers)
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = GET("$baseUrl/manhua/?s=$query&post_type=wp-manga")
override fun searchMangaNextPageSelector(): String? = null
override fun getFilterList(): FilterList = FilterList()
}

@ -0,0 +1,8 @@
package eu.kanade.tachiyomi.extension.id.worldromancetranslation
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class WorldRomanceTranslation : Madara("World Romance Translation", "https://wrt.my.id/", "id", SimpleDateFormat("dd MMMM yyyy", Locale("id")))

@ -0,0 +1,13 @@
package eu.kanade.tachiyomi.extension.en.wuxiaworld
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.source.model.FilterList
import okhttp3.Request
class WuxiaWorld : Madara("WuxiaWorld", "https://wuxiaworld.site", "en") {
override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/tag/webcomic/page/$page/?m_orderby=views", headers)
override fun latestUpdatesRequest(page: Int): Request = GET("$baseUrl/tag/webcomic/page/$page/?m_orderby=latest", headers)
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = super.searchMangaRequest(page, "$query comics", filters)
override fun popularMangaNextPageSelector() = "div.nav-previous.float-left"
}

@ -0,0 +1,28 @@
package eu.kanade.tachiyomi.extension.pt.yaoitoshokan
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter
import okhttp3.Response
import org.jsoup.nodes.Document
import java.text.SimpleDateFormat
import java.util.Locale
class YaoiToshokan : Madara("Yaoi Toshokan", "https://yaoitoshokan.com.br", "pt-BR", SimpleDateFormat("dd MMM yyyy", Locale("pt", "BR"))) {
// Page has custom link to scan website.
override val popularMangaUrlSelector = "div.post-title a:not([target])"
// Chapters are listed old to new.
override fun chapterListParse(response: Response): List<SChapter> {
return super.chapterListParse(response).reversed()
}
override fun pageListParse(document: Document): List<Page> {
return document.select(pageListParseSelector)
.mapIndexed { index, element ->
// Had to add trim because of white space in source.
val imageUrl = element.select("img").attr("data-src").trim()
Page(index, document.location(), imageUrl)
}
}
}

@ -0,0 +1,12 @@
package eu.kanade.tachiyomi.extension.fr.yokaijump
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class YokaiJump : Madara(
"Yokai Jump",
"https://yokaijump.fr",
"fr",
dateFormat = SimpleDateFormat("dd/MM/yy", Locale.US)
)

@ -0,0 +1,12 @@
package eu.kanade.tachiyomi.extension.pt.yuriverso
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class YuriVerso : Madara(
"Yuri Verso",
"https://yuri.live",
"pt-BR",
SimpleDateFormat("dd/MM/yyyy", Locale("pt", "BR"))
)

@ -0,0 +1,9 @@
package eu.kanade.tachiyomi.extension.en.zinmanga
import eu.kanade.tachiyomi.multisrc.madara.Madara
import okhttp3.Headers
class ZinManga : Madara("Zin Translator", "https://zinmanga.com", "en") {
override fun headersBuilder(): Headers.Builder = super.headersBuilder()
.add("Referer", "https://zinmanga.com/")
}

@ -1,6 +1,7 @@
package eu.kanade.tachiyomi.multisrc.madara
import eu.kanade.tachiyomi.multisrc.ThemeSourceData.SingleLang
import eu.kanade.tachiyomi.multisrc.ThemeSourceData.MultiLang
import eu.kanade.tachiyomi.multisrc.ThemeSourceGenerator
class MadaraGenerator : ThemeSourceGenerator {
@ -15,25 +16,25 @@ class MadaraGenerator : ThemeSourceGenerator {
SingleLang("Adonis Fansub", "https://manga.adonisfansub.com", "tr"),
SingleLang("AkuManga", "https://akumanga.com", "ar"),
SingleLang("AlianzaMarcial", "https://alianzamarcial.xyz", "es"),
SingleLang("AllPornComic", "https://allporncomic.com", "en"),
SingleLang("AllPornComic", "https://allporncomic.com", "en", isNsfw = true),
SingleLang("Aloalivn", "https://aloalivn.com", "en"),
SingleLang("AniMangaEs", "http://animangaes.com", "en"),
SingleLang("Agent of Change Translations", "https://aoc.moe", "en"),
SingleLang("ApollComics", "https://apollcomics.xyz", "es"),
SingleLang("Arang Scans", "https://www.arangscans.com", "en"),
SingleLang("Arang Scans", "https://arangscans.com", "en", overrideVersionCode = 1),
SingleLang("ArazNovel", "https://www.araznovel.com", "tr"),
SingleLang("Argos Scan", "https://argosscan.com", "pt-BR"),
SingleLang("Asgard Team", "https://www.asgard1team.com", "ar"),
SingleLang("Astral Library", "https://www.astrallibrary.net", "en"),
SingleLang("Atikrost", "https://atikrost.com", "tr"),
SingleLang("ATM-Subs", "https://atm-subs.fr", "fr", className = "ATMSubs", pkgName = "atmsubs"),
SingleLang("ATM-Subs", "https://atm-subs.fr", "fr", className = "ATMSubs"),
SingleLang("Azora", "https://www.azoramanga.com", "ar"),
SingleLang("Bakaman", "https://bakaman.net", "th"),
SingleLang("BestManga", "https://bestmanga.club", "ru"),
SingleLang("BestManhua", "https://bestmanhua.com", "en", overrideVersionCode = 1),
SingleLang("BoysLove", "https://boyslove.me", "en"),
SingleLang("CatOnHeadTranslations", "https://catonhead.com", "en"),
SingleLang("CAT-translator", "https://cat-translator.com", "th", className = "CatTranslator", pkgName = "cattranslator"),
SingleLang("CAT-translator", "https://cat-translator.com", "th", className = "CatTranslator"),
SingleLang("Chibi Manga", "https://www.cmreader.info", "en"),
SingleLang("Clover Manga", "Clover Manga", "tr"),
SingleLang("ComicKiba", "https://comickiba.com", "en"),
@ -78,8 +79,151 @@ class MadaraGenerator : ThemeSourceGenerator {
SingleLang("KlikManga", "https://klikmanga.com", "id"),
SingleLang("Kissmanga.in", "https://kissmanga.in", "en", className= "KissmangaIn"),
SingleLang("Kombatch", "https://kombatch.com", "id"),
SingleLang("KomikGo", "https://komikgo.com", "id"),
SingleLang("Lily Manga", "https://lilymanga.com", "en"),
SingleLang("LovableSubs", "https://lovablesubs.com", "tr"),
SingleLang("Manga18 Fun", "https://manga18.fun", "en"),
SingleLang("Manga347", "https://manga347.com", "en"),
SingleLang("مانجا العاشق", "https://3asq.org", "ar", className = "Manga3asq"),
SingleLang("Manga3S", "https://manga3s.com", "en"),
SingleLang("Manga68", "https://manga68.com", "en"),
SingleLang("Manga Action", "https://manga-action.com", "ar"),
SingleLang("Manga Arab Online مانجا عرب اون لاين", "https://mangaarabonline.com", "ar", className = "MangaArabOnline"),
SingleLang("مانجا عرب تيم Manga Arab Team", "https://mangaarabteam.com", "ar", className = "MangaArabTeam"),
SingleLang("MangaBaz", "https://mangabaz.com", "tr"),
SingleLang("Manga Bin", "https://mangabin.com/", "en"),
SingleLang("MangaBob", "https://mangabob.com", "en"),
SingleLang("Manga Chill", "https://mangachill.com/", "en"),
SingleLang("Manga Clash", "https://mangaclash.com", "en"),
SingleLang("Manga Crimson", "https://mangacrimson.com", "tr"),
SingleLang("MangaCultivator", "https://mangacultivator.com", "en"),
SingleLang("MangaDods", "https://www.mangadods.com", "en"),
SingleLang("MangaEffect", "https://mangaeffect.com", "en"),
SingleLang("MangaGreat", "https://mangagreat.com", "en"),
SingleLang("Manga Hentai", "https://mangahentai.me", "en", isNsfw = true),
SingleLang("Manga Kiss", "https://mangakiss.org", "en"),
SingleLang("MangaKomi", "https://mangakomi.com", "en"),
SingleLang("Manga Land Arabic", "https://mangalandarabic.com", "ar"),
SingleLang("مانجا ليك", "https://mangalek.com", "ar", className = "Mangalek"),
SingleLang("Manga Lord", "https://mangalord.com", "en"),
SingleLang("Manganelo.link", "https://manganelo.link", "en", className = "ManganeloLink"),
SingleLang("Manga Nine", "https://manganine.com", "en"),
SingleLang("Manga-Online.co", "https://www.manga-online.co", "th", className = "MangaOnlineCo"),
SingleLang("Manga Diyari", "https://mangadiyari.com", "tr"),
SingleLang("MangaRave", "http://www.mangarave.com", "en"),
SingleLang("MangaRawr", "https://mangarawr.com", "en"),
SingleLang("Manga Read", "https://mangaread.co", "en"),
SingleLang("MangaRead.org", "https://www.mangaread.org", "en", className = "MangaReadOrg"),
SingleLang("Mangareceh", "https://mangareceh.id", "id"),
SingleLang("Manga Rock Team", "https://mangarockteam.com", "en"),
SingleLang("Manga Rocky", "https://mangarocky.com", "en"),
SingleLang("MangaRoma", "https://mangaroma.com", "en"),
SingleLang("Manga-Scantrad", "https://manga-scantrad.net", "fr", className = "MangaScantrad"),
SingleLang("MangaSco", "https://mangasco.com", "en"),
SingleLang("MangaSpark", "https://mangaspark.com", "ar"),
SingleLang("Manga Starz", "https://mangastarz.com", "ar"),
SingleLang("MangaStein", "https://mangastein.com", "tr"),
SingleLang("Mangasushi", "https://mangasushi.net", "en"),
SingleLang("Manga SY", "https://www.mangasy.com", "en"),
SingleLang("MangaTeca", "https://www.mangateca.com", "pt-BR"),
SingleLang("Manga Turf", "https://mangaturf.com", "en"),
SingleLang("MangaTX", "https://mangatx.com", "en"),
SingleLang("Manga Weebs", "https://mangaweebs.in", "en"),
SingleLang("MangaWT", "https://mangawt.com", "tr"),
SingleLang("MangaYaku", "https://mangayaku.my.id", "id"),
SingleLang("MangaYosh", "https://mangayosh.xyz", "id"),
MultiLang("Mangazuki.club", "https://mangazuki.club", listOf("ja", "ko"),
className = "MangazukiClubFactory"),
SingleLang("Mangazuki.me", "https://mangazuki.me", "en", className = "MangazukiMe"),
SingleLang("Mangazuki.online", "http://mangazukinew.online", "en", className = "MangazukiOnline"),
SingleLang("ManhuaBox", "https://manhuabox.net", "en"),
SingleLang("ManhuaFast", "https://manhuafast.com", "en"),
SingleLang("Manhuaga", "https://manhuaga.com", "en"),
SingleLang("Manhua Plus", "https://manhuaplus.com", "en"),
SingleLang("Manhuas.net", "https://manhuas.net", "en", className = "Manhuasnet"),
SingleLang("Manhuas World", "https://manhuasworld.com", "en"),
SingleLang("Manhua SY", "https://www.manhuasy.com", "en"),
SingleLang("ManhuaUS", "https://manhuaus.com", "en"),
SingleLang("Manhwa Raw", "https://manhwaraw.com", "ko"),
SingleLang("Manhwatop", "https://manhwatop.com", "en"),
SingleLang("Manwahentai.me", "https://manhwahentai.me", "en", className = "ManwahentaiMe", isNsfw = true),
SingleLang("Manwha Club", "https://manhwa.club", "en"),
SingleLang("ManyToon", "https://manytoon.com", "en"),
SingleLang("ManyToonClub", "https://manytoon.club", "ko"),
SingleLang("ManyToon.me", "https://manytoon.me", "en", className = "ManyToonMe"),
SingleLang("Mark Scans", "https://markscans.online", "pt-BR"),
SingleLang("Martial Scans", "https://martialscans.com", "en"),
SingleLang("MG Komik", "https://mgkomik.my.id", "id"),
SingleLang("Milftoon", "https://milftoon.xxx", "en", isNsfw = true),
SingleLang("Miracle Scans", "https://miraclescans.com", "en"),
SingleLang("Mixed Manga", "https://mixedmanga.com", "en"),
SingleLang("MMScans", "https://mm-scans.com/", "en"),
SingleLang("Mundo Wuxia", "https://mundowuxia.com", "es"),
SingleLang("Mystical Merries", "https://mysticalmerries.com", "en"),
SingleLang("Nazarick Scans", "https://nazarickscans.com", "en"),
SingleLang("NeatManga", "https://neatmanga.com", "en"),
SingleLang("NekoBreaker", "https://nekobreaker.com", "pt-BR"),
SingleLang("NekoScan", "https://nekoscan.com", "en"),
SingleLang("Neox Scanlator", "https://neoxscans.com", "pt-BR"),
SingleLang("Night Comic", "https://www.nightcomic.com", "en"),
SingleLang("Niji Translations", "https://niji-translations.com", "ar"),
SingleLang("Ninjavi", "https://ninjavi.com", "ar"),
SingleLang("NTS Void Scans", "https://ntsvoidscans.com", "en"),
SingleLang("Off Scan", "https://offscan.top", "pt-BR"),
SingleLang("مانجا اولاو", "https://olaoe.giize.com", "ar", className = "OlaoeManga"),
SingleLang("OnManga", "https://onmanga.com", "en"),
SingleLang("Origami Orpheans", "https://origami-orpheans.com.br", "pt-BR"),
SingleLang("PMScans", "https://www.pmscans.com", "en"),
SingleLang("Pojok Manga", "https://pojokmanga.com", "id"),
SingleLang("PornComix", "https://www.porncomixonline.net", "en", isNsfw = true),
SingleLang("Prime Manga", "https://primemanga.com", "en"),
SingleLang("Projeto Scanlator", "https://projetoscanlator.com", "pt-BR"),
SingleLang("QueensManga ملكات المانجا", "https://queensmanga.com", "ar", className = "QueensManga"),
SingleLang("Raider Scans", "https://raiderscans.com", "en"),
SingleLang("Random Translations", "https://randomtranslations.com", "en"),
SingleLang("Raw Mangas", "https://rawmangas.net", "ja", isNsfw = true),
SingleLang("ReadManhua", "https://readmanhua.net", "en"),
SingleLang("Renascence Scans (Renascans)", "https://new.renascans.com", "en", className = "RenaScans"),
SingleLang("Rüya Manga", "https://www.ruyamanga.com", "tr", className = "RuyaManga"),
SingleLang("S2Manga", "https://s2manga.com", "en"),
SingleLang("Sekte Doujin", "https://sektedoujin.xyz", "id", isNsfw = true),
SingleLang("ShoujoHearts", "http://shoujohearts.com", "en"),
SingleLang("SiXiang Scans", "http://www.sixiangscans.com", "en"),
SingleLang("Siyahmelek", "https://siyahmelek.com", "tr", isNsfw = true),
SingleLang("Skymanga", "https://skymanga.co", "en"),
SingleLang("SoloScanlation", "https://soloscanlation.site", "en"),
SingleLang("Spooky Scanlations", "https://spookyscanlations.xyz", "es"),
SingleLang("StageComics", "https://stagecomics.com", "pt-BR"),
SingleLang("TheTopComic", "https://thetopcomic.com", "en"),
SingleLang("365Manga", "https://365manga.com", "en", className = "ThreeSixtyFiveManga"),
SingleLang("ToonGod", "https://www.toongod.com", "en"),
SingleLang("Toonily", "https://toonily.com", "en", isNsfw = true),
SingleLang("Toonily.net", "https://toonily.net", "en", isNsfw = true, className = "ToonilyNet"),
SingleLang("ToonPoint", "https://toonpoint.com", "en"),
SingleLang("Top Manhua", "https://topmanhua.com", "en"),
SingleLang("TritiniaScans", "https://tritinia.com", "en"),
SingleLang("TruyenTranhAudio.com", "https://truyentranhaudio.com", "vi", className = "TruyenTranhAudioCom"),
SingleLang("TruyenTranhAudio.online", "https://truyentranhaudio.online", "vi", className = "TruyenTranhAudioOnline"),
SingleLang("Tsubaki No Scan", "https://tsubakinoscan.com", "fr"),
SingleLang("Türkçe Manga", "https://turkcemanga.com", "tr", className = "TurkceManga"),
SingleLang("Twilight Scans", "https://twilightscans.com", "en"),
SingleLang("Uyuyan Balik", "https://uyuyanbalik.com/", "tr"),
SingleLang("Vanguard Bun", "https://vanguardbun.com/", "en"),
SingleLang("Void Scans", "https://voidscans.com", "en"),
SingleLang("Wakascan", "https://wakascan.com", "fr"),
SingleLang("War Queen Scan", "https://wqscan.com", "pt-BR"),
SingleLang("WebNovel", "https://webnovel.live", "en"),
SingleLang("WebToonily", "https://webtoonily.com", "en"),
SingleLang("WebtoonXYZ", "https://www.webtoon.xyz", "en"),
SingleLang("WeScans", "https://wescans.xyz", "en"),
SingleLang("WoopRead", "https://woopread.com", "en"),
SingleLang("World Romance Translation", "https://wrt.my.id/", "id"),
SingleLang("WuxiaWorld", "https://wuxiaworld.site", "en"),
SingleLang("Yaoi Toshokan", "https://yaoitoshokan.com.br", "pt-BR", isNsfw = true),
SingleLang("Yokai Jump", "https://yokaijump.fr", "fr"),
SingleLang("Yuri Verso", "https://yuri.live", "pt-BR"),
SingleLang("Zin Translator", "https://zinmanga.com", "en"),
SingleLang("ZManga", "https://zmanga.org", "es"),
)
companion object {

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="eu.kanade.tachiyomi.extension" />

@ -1,13 +0,0 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
ext {
extName = 'Madara (multiple sources)'
pkgNameSuffix = "all.madara"
extClass = '.MadaraFactory'
extVersionCode = 180
libVersion = '1.2'
containsNsfw = true
}
apply from: "$rootDir/common.gradle"

Binary file not shown.

Before

(image error) Size: 3.0 KiB

Binary file not shown.

Before

(image error) Size: 1.7 KiB

Binary file not shown.

Before

(image error) Size: 4.2 KiB

Binary file not shown.

Before

(image error) Size: 7.5 KiB

Binary file not shown.

Before

(image error) Size: 13 KiB

Binary file not shown.

Before

(image error) Size: 74 KiB

@ -1,525 +0,0 @@
package eu.kanade.tachiyomi.extension.all.madara
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.network.asObservable
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.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.CacheControl
import okhttp3.FormBody
import okhttp3.Headers
import okhttp3.HttpUrl
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody
import okhttp3.Response
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import rx.Observable
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
import java.util.concurrent.TimeUnit
import kotlin.math.absoluteValue
import kotlin.random.Random
abstract class Madara(
override val name: String,
override val baseUrl: String,
override val lang: String,
private val dateFormat: SimpleDateFormat = SimpleDateFormat("MMMM dd, yyyy", Locale.US)
) : ParsedHttpSource() {
override val supportsLatest = true
override val client: OkHttpClient = network.cloudflareClient.newBuilder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build()
// helps with cloudflare for some sources, makes it worse for others; override with empty string if the latter is true
protected open val userAgentRandomizer = " ${Random.nextInt().absoluteValue}"
override fun headersBuilder(): Headers.Builder = Headers.Builder()
.add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:77.0) Gecko/20100101 Firefox/78.0$userAgentRandomizer")
// Popular Manga
override fun popularMangaSelector() = "div.page-item-detail"
open val popularMangaUrlSelector = "div.post-title a"
override fun popularMangaFromElement(element: Element): SManga {
val manga = SManga.create()
with(element) {
select(popularMangaUrlSelector).first()?.let {
manga.setUrlWithoutDomain(it.attr("abs:href"))
manga.title = it.ownText()
}
select("img").first()?.let {
manga.thumbnail_url = imageFromElement(it)
}
}
return manga
}
open fun formBuilder(page: Int, popular: Boolean) = FormBody.Builder().apply {
add("action", "madara_load_more")
add("page", (page - 1).toString())
add("template", "madara-core/content/content-archive")
add("vars[orderby]", "meta_value_num")
add("vars[paged]", "1")
add("vars[posts_per_page]", "20")
add("vars[post_type]", "wp-manga")
add("vars[post_status]", "publish")
add("vars[meta_key]", if (popular) "_wp_manga_views" else "_latest_update")
add("vars[order]", "desc")
add("vars[sidebar]", if (popular) "full" else "right")
add("vars[manga_archives_item_layout]", "big_thumbnail")
}
open val formHeaders: Headers by lazy { headersBuilder().build() }
override fun popularMangaRequest(page: Int): Request {
return POST("$baseUrl/wp-admin/admin-ajax.php", formHeaders, formBuilder(page, true).build(), CacheControl.FORCE_NETWORK)
}
override fun popularMangaNextPageSelector(): String? = "body:not(:has(.no-posts))"
// Latest Updates
override fun latestUpdatesSelector() = popularMangaSelector()
override fun latestUpdatesFromElement(element: Element): SManga {
// Even if it's different from the popular manga's list, the relevant classes are the same
return popularMangaFromElement(element)
}
override fun latestUpdatesRequest(page: Int): Request {
return POST("$baseUrl/wp-admin/admin-ajax.php", formHeaders, formBuilder(page, false).build(), CacheControl.FORCE_NETWORK)
}
override fun latestUpdatesNextPageSelector(): String? = popularMangaNextPageSelector()
override fun latestUpdatesParse(response: Response): MangasPage {
val mp = super.latestUpdatesParse(response)
val mangas = mp.mangas.distinctBy { it.url }
return MangasPage(mangas, mp.hasNextPage)
}
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
return client.newCall(searchMangaRequest(page, query, filters))
.asObservable().doOnNext { response ->
if (!response.isSuccessful) {
response.close()
// Error message for exceeding last page
if (response.code() == 404)
error("Already on the Last Page!")
else throw Exception("HTTP error ${response.code()}")
}
}
.map { response ->
searchMangaParse(response)
}
}
// Search Manga
protected open fun searchPage(page: Int): String = "page/$page/"
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val url = HttpUrl.parse("$baseUrl/${searchPage(page)}")!!.newBuilder()
url.addQueryParameter("s", query)
url.addQueryParameter("post_type", "wp-manga")
filters.forEach { filter ->
when (filter) {
is AuthorFilter -> {
if (filter.state.isNotBlank()) {
url.addQueryParameter("author", filter.state)
}
}
is ArtistFilter -> {
if (filter.state.isNotBlank()) {
url.addQueryParameter("artist", filter.state)
}
}
is YearFilter -> {
if (filter.state.isNotBlank()) {
url.addQueryParameter("release", filter.state)
}
}
is StatusFilter -> {
filter.state.forEach {
if (it.state) {
url.addQueryParameter("status[]", it.id)
}
}
}
is OrderByFilter -> {
if (filter.state != 0) {
url.addQueryParameter("m_orderby", filter.toUriPart())
}
}
is GenreConditionFilter -> {
url.addQueryParameter("op", filter.toUriPart())
}
is GenreList -> {
filter.state
.filter { it.state }
.let { list ->
if (list.isNotEmpty()) { list.forEach { genre -> url.addQueryParameter("genre[]", genre.id) } }
}
}
}
}
return GET(url.toString(), headers)
}
private class AuthorFilter : Filter.Text("Author")
private class ArtistFilter : Filter.Text("Artist")
private class YearFilter : Filter.Text("Year of Released")
private class StatusFilter(status: List<Tag>) : Filter.Group<Tag>("Status", status)
private class OrderByFilter : UriPartFilter(
"Order By",
arrayOf(
Pair("<select>", ""),
Pair("Latest", "latest"),
Pair("A-Z", "alphabet"),
Pair("Rating", "rating"),
Pair("Trending", "trending"),
Pair("Most Views", "views"),
Pair("New", "new-manga")
)
)
private class GenreConditionFilter : UriPartFilter(
"Genre condition",
arrayOf(
Pair("or", ""),
Pair("and", "1")
)
)
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Genres", genres)
class Genre(name: String, val id: String = name) : Filter.CheckBox(name)
open fun getGenreList() = listOf(
Genre("Adventure", "Adventure"),
Genre("Action", "action"),
Genre("Adventure", "adventure"),
Genre("Cars", "cars"),
Genre("4-Koma", "4-koma"),
Genre("Comedy", "comedy"),
Genre("Completed", "completed"),
Genre("Cooking", "cooking"),
Genre("Dementia", "dementia"),
Genre("Demons", "demons"),
Genre("Doujinshi", "doujinshi"),
Genre("Drama", "drama"),
Genre("Ecchi", "ecchi"),
Genre("Fantasy", "fantasy"),
Genre("Game", "game"),
Genre("Gender Bender", "gender-bender"),
Genre("Harem", "harem"),
Genre("Historical", "historical"),
Genre("Horror", "horror"),
Genre("Isekai", "isekai"),
Genre("Josei", "josei"),
Genre("Kids", "kids"),
Genre("Magic", "magic"),
Genre("Manga", "manga"),
Genre("Manhua", "manhua"),
Genre("Manhwa", "manhwa"),
Genre("Martial Arts", "martial-arts"),
Genre("Mature", "mature"),
Genre("Mecha", "mecha"),
Genre("Military", "military"),
Genre("Music", "music"),
Genre("Mystery", "mystery"),
Genre("Old Comic", "old-comic"),
Genre("One Shot", "one-shot"),
Genre("Oneshot", "oneshot"),
Genre("Parodi", "parodi"),
Genre("Parody", "parody"),
Genre("Police", "police"),
Genre("Psychological", "psychological"),
Genre("Romance", "romance"),
Genre("Samurai", "samurai"),
Genre("School", "school"),
Genre("School Life", "school-life"),
Genre("Sci-Fi", "sci-fi"),
Genre("Seinen", "seinen"),
Genre("Shoujo", "shoujo"),
Genre("Shoujo Ai", "shoujo-ai"),
Genre("Shounen", "shounen"),
Genre("Shounen ai", "shounen-ai"),
Genre("Slice of Life", "slice-of-life"),
Genre("Sports", "sports"),
Genre("Super Power", "super-power"),
Genre("Supernatural", "supernatural"),
Genre("Thriller", "thriller"),
Genre("Tragedy", "tragedy"),
Genre("Vampire", "vampire"),
Genre("Webtoons", "webtoons"),
Genre("Yaoi", "yaoi"),
Genre("Yuri", "yuri")
)
override fun getFilterList() = FilterList(
AuthorFilter(),
ArtistFilter(),
YearFilter(),
StatusFilter(getStatusList()),
OrderByFilter(),
Filter.Separator(),
Filter.Header("Genres may not work for all sources"),
GenreConditionFilter(),
GenreList(getGenreList())
)
private fun getStatusList() = listOf(
Tag("end", "Completed"),
Tag("on-going", "Ongoing"),
Tag("canceled", "Canceled"),
Tag("on-hold", "On Hold")
)
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
}
open class Tag(val id: String, name: String) : Filter.CheckBox(name)
override fun searchMangaSelector() = "div.c-tabs-item__content"
override fun searchMangaFromElement(element: Element): SManga {
val manga = SManga.create()
with(element) {
select("div.post-title a").first()?.let {
manga.setUrlWithoutDomain(it.attr("abs:href"))
manga.title = it.ownText()
}
select("img").first()?.let {
manga.thumbnail_url = imageFromElement(it)
}
}
return manga
}
override fun searchMangaNextPageSelector(): String? = "div.nav-previous, nav.navigation-ajax, a.nextpostslink"
// Manga Details Parse
override fun mangaDetailsParse(document: Document): SManga {
val manga = SManga.create()
with(document) {
select("div.post-title h3").first()?.let {
manga.title = it.ownText()
}
select("div.author-content").first()?.let {
manga.author = it.text()
}
select("div.artist-content").first()?.let {
manga.artist = it.text()
}
select("div.description-summary div.summary__content").let {
if (it.select("p").text().isNotEmpty()) {
manga.description = it.select("p").joinToString(separator = "\n\n") { p ->
p.text().replace("<br>", "\n")
}
} else {
manga.description = it.text()
}
}
select("div.summary_image img").first()?.let {
manga.thumbnail_url = imageFromElement(it)
}
select("div.summary-content").last()?.let {
manga.status = when (it.text()) {
// I don't know what's the corresponding for COMPLETED and LICENSED
// There's no support for "Canceled" or "On Hold"
"Completed", "Completo", "Concluído", "Tamamlandı", "Tamamlandı." -> SManga.COMPLETED
"OnGoing", "Продолжается", "Updating", "Em Lançamento", "Em andamento", "Devam Ediyor", "Devam Ediyor." -> SManga.ONGOING
else -> SManga.UNKNOWN
}
}
val genres = mutableListOf<String>()
select("div.genres-content a").forEach { element ->
val genre = element.text()
genres.add(genre)
}
manga.genre = genres.joinToString(", ")
}
return manga
}
protected fun imageFromElement(element: Element): String? {
return when {
element.hasAttr("data-src") -> element.attr("abs:data-src")
element.hasAttr("data-lazy-src") -> element.attr("abs:data-lazy-src")
element.hasAttr("srcset") -> element.attr("abs:srcset").substringBefore(" ")
else -> element.attr("abs:src")
}
}
protected fun getXhrChapters(mangaId: String): Document {
val xhrHeaders = headersBuilder().add("Content-Type: application/x-www-form-urlencoded; charset=UTF-8")
.add("Referer", baseUrl)
.build()
val body = RequestBody.create(null, "action=manga_get_chapters&manga=$mangaId")
return client.newCall(POST("$baseUrl/wp-admin/admin-ajax.php", xhrHeaders, body)).execute().asJsoup()
}
override fun chapterListParse(response: Response): List<SChapter> {
val document = response.asJsoup()
val dataIdSelector = "div[id^=manga-chapters-holder]"
return document.select(chapterListSelector())
.let { elements ->
if (elements.isEmpty() && !document.select(dataIdSelector).isNullOrEmpty())
getXhrChapters(document.select(dataIdSelector).attr("data-id")).select(chapterListSelector())
else elements
}
.map { chapterFromElement(it) }
}
override fun chapterListSelector() = "li.wp-manga-chapter"
open val chapterUrlSelector = "a"
open val chapterUrlSuffix = "?style=list"
open val chapterDatesNewSelector = "img"
override fun chapterFromElement(element: Element): SChapter {
val chapter = SChapter.create()
with(element) {
select(chapterUrlSelector).first()?.let { urlElement ->
chapter.url = urlElement.attr("abs:href").let {
it.substringBefore("?style=paged") + if (!it.endsWith(chapterUrlSuffix)) chapterUrlSuffix else ""
}
chapter.name = urlElement.text()
}
// Dates can be part of a "new" graphic or plain text
chapter.date_upload = select(chapterDatesNewSelector).firstOrNull()?.attr("alt")?.let { parseRelativeDate(it) }
?: parseChapterDate(select("span.chapter-release-date i").firstOrNull()?.text())
}
return chapter
}
open fun parseChapterDate(date: String?): Long {
date ?: return 0
fun SimpleDateFormat.tryParse(string: String): Long {
return try {
parse(string)?.time ?: 0
} catch (_: ParseException) {
0
}
}
return when {
date.endsWith(" ago", ignoreCase = true) -> {
parseRelativeDate(date)
}
// Handle translated 'ago' in Portuguese.
date.endsWith(" atrás", ignoreCase = true) -> {
parseRelativeDate(date)
}
// Handle translated 'ago' in Turkish.
date.endsWith(" önce", ignoreCase = true) -> {
parseRelativeDate(date)
}
// Handle 'yesterday' and 'today', using midnight
date.startsWith("year", ignoreCase = true) -> {
Calendar.getInstance().apply {
add(Calendar.DAY_OF_MONTH, -1) // yesterday
set(Calendar.HOUR_OF_DAY, 0)
set(Calendar.MINUTE, 0)
set(Calendar.SECOND, 0)
set(Calendar.MILLISECOND, 0)
}.timeInMillis
}
date.startsWith("today", ignoreCase = true) -> {
Calendar.getInstance().apply {
set(Calendar.HOUR_OF_DAY, 0)
set(Calendar.MINUTE, 0)
set(Calendar.SECOND, 0)
set(Calendar.MILLISECOND, 0)
}.timeInMillis
}
date.contains(Regex("""\d(st|nd|rd|th)""")) -> {
// Clean date (e.g. 5th December 2019 to 5 December 2019) before parsing it
date.split(" ").map {
if (it.contains(Regex("""\d\D\D"""))) {
it.replace(Regex("""\D"""), "")
} else {
it
}
}
.let { dateFormat.tryParse(it.joinToString(" ")) }
}
else -> dateFormat.tryParse(date)
}
}
// Parses dates in this form:
// 21 horas ago
private fun parseRelativeDate(date: String): Long {
val number = Regex("""(\d+)""").find(date)?.value?.toIntOrNull() ?: return 0
val cal = Calendar.getInstance()
return when {
WordSet("يوم", "hari", "gün", "jour", "día", "dia", "day").anyWordIn(date) -> cal.apply { add(Calendar.DAY_OF_MONTH, -number) }.timeInMillis
WordSet("ساعات", "jam", "saat", "heure", "hora", "hour").anyWordIn(date) -> cal.apply { add(Calendar.HOUR, -number) }.timeInMillis
WordSet("دقيقة", "menit", "dakika", "min", "minute", "minuto").anyWordIn(date) -> cal.apply { add(Calendar.MINUTE, -number) }.timeInMillis
WordSet("detik", "segundo", "second").anyWordIn(date) -> cal.apply { add(Calendar.SECOND, -number) }.timeInMillis
else -> 0
}
}
override fun pageListRequest(chapter: SChapter): Request {
if (chapter.url.startsWith("http")) {
return GET(chapter.url, headers)
}
return super.pageListRequest(chapter)
}
open val pageListParseSelector = "div.page-break"
override fun pageListParse(document: Document): List<Page> {
return document.select(pageListParseSelector).mapIndexed { index, element ->
Page(
index,
document.location(),
element.select("img").first()?.let {
it.absUrl(if (it.hasAttr("data-src")) "data-src" else "src")
}
)
}
}
override fun imageRequest(page: Page): Request {
return GET(page.imageUrl!!, headers.newBuilder().set("Referer", page.url).build())
}
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException("Not used")
}
class WordSet(private vararg val words: String) { fun anyWordIn(dateString: String): Boolean = words.any { dateString.contains(it, ignoreCase = true) } }

@ -1,861 +0,0 @@
package eu.kanade.tachiyomi.extension.all.madara
import eu.kanade.tachiyomi.annotations.Nsfw
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
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.Page
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import okhttp3.CacheControl
import okhttp3.Headers
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.TimeUnit
class MadaraFactory : SourceFactory {
override fun createSources(): List<Source> = listOf(
// AdonisFansub(),
// AkuManga(),
// AlianzaMarcial(),
// AllPornComic(),
// Aloalivn(),
// AniMangaEs(),
// AoCTranslations(),
// ApollComics(),
// ArangScans(),
// ArazNovel(),
// ArgosScan(),
// AsgardTeam(),
// AstralLibrary(),
// Atikrost(),
// ATMSubs(),
// Azora(),
// Bakaman(),
// BestManga(),
// BestManhua(),
// BoysLove(),
// CatOnHeadTranslations(),
// CatTranslator(),
// ChibiManga(),
// CloverManga(),
// ComicKiba(),
// ComicsValley(),
// CopyPasteScan(),
// CutiePie(),
// DarkyuRealm(),
// DecadenceScans(),
// DetectiveConanAr(),
// DiamondFansub(),
// DisasterScans(),
// DoujinHentai(),
// DoujinYosh(),
// DreamManga(),
// DropeScan(),
// EinherjarScan(),
// FdmScan(),
// FirstKissManga(),
// FirstKissManhua(),
// FreeWebtoonCoins(),
// FurioScans(),
// GeceninLordu(),
// GoldenManga(),
// GrazeScans(),
// GourmetScans(),
// GuncelManga(),
// HeroManhua(),
// HerozScanlation(),
// HikariScan(),
// HimeraFansub(),
// Hiperdex(),
// Hscans(),
// HunterFansub(),
// IchirinNoHanaYuri(),
// ImmortalUpdates(),
// IsekaiScanCom(),
// ItsYourRightManhua(),
// JJutsuScans(),
// JustForFun(),
// KingzManga(),
// KisekiManga(),
// KlikManga(),
// Kombatch(),
KomikGo(),
LilyManga(),
LovableSubs(),
Manga18Fun(),
Manga347(),
Manga3asq(),
Manga3S(),
Manga68(),
MangaAction(),
MangaArabOnline(),
MangaArabTeam(),
MangaBaz(),
MangaBin(),
MangaBob(),
MangaChill(),
MangaClash(),
MangaCrimson(),
MangaCultivator(),
MangaDods(),
MangaHentai(),
MangaKiss(),
MangaKomi(),
MangaLandArabic(),
Mangalek(),
MangaLord(),
ManganeloLink(),
MangaNine(),
MangaOnlineCo(),
MangaPhoenix(),
MangaRave(),
MangaRawr(),
MangaRead(),
MangaReadOrg(),
Mangareceh(),
MangaRockTeam(),
MangaRocky(),
MangaRoma(),
MangaScantrad(),
MangaSco(),
MangaSpark(),
MangaStarz(),
MangaStein(),
Mangasushi(),
MangaSY(),
MangaTeca(),
MangaTurf(),
MangaTX(),
MangaWeebs(),
MangaWT(),
MangaYaku(),
MangaYosh(),
MangazukiClubJP(),
MangazukiClubKO(),
MangazukiMe(),
// MangazukiOnline(),
ManhuaBox(),
ManhuaFast(),
Manhuaga(),
ManhuaPlus(),
Manhuasnet(),
ManhuasWorld(),
ManhuaSY(),
ManhuaUS(),
ManhwaRaw(),
ManhwaTop(),
ManwahentaiMe(),
ManwhaClub(),
ManyToon(),
ManyToonClub(),
ManyToonMe(),
MarkScans(),
MartialScans(),
MGKomik(),
Milftoon(),
MiracleScans(),
MixedManga(),
MMScans(),
MundoWuxia(),
MysticalMerries(),
NazarickScans(),
NeatManga(),
NekoBreaker(),
NekoScan(),
NeoxScanlator(),
NightComic(),
NijiTranslations(),
Ninjavi(),
NTSVoidScans(),
OffScan(),
OlaoeManga(),
OnManga(),
OrigamiOrpheans(),
PMScans(),
PojokManga(),
PornComix(),
PrimeManga(),
ProjetoScanlator(),
QueensManga(),
RaiderScans(),
RandomTranslations(),
RawMangas(),
ReadManhua(),
RenaScans(),
RuyaManga(),
S2Manga(),
SekteDoujin(),
ShoujoHearts(),
SiXiangScans(),
Siyahmelek(),
Skymanga(),
SoloScanlation(),
SpookyScanlations(),
StageComics(),
TheTopComic(),
ThreeSixtyFiveManga(),
ToonGod(),
Toonily(),
ToonilyNet(),
ToonPoint(),
TopManhua(),
TritiniaScans(),
TruyenTranhAudioCom(),
TruyenTranhAudioOnline(),
TsubakiNoScan(),
TurkceManga(),
TwilightScans(),
UyuyanBalik(),
VanguardBun(),
Voidscans(),
Wakascan(),
WarQueenScan(),
WebNovel(),
WebToonily(),
WebtoonXYZ(),
WeScans(),
WoopRead(),
WorldRomanceTranslation(),
WuxiaWorld(),
YaoiToshokan(),
YokaiJump(),
YuriVerso(),
ZinManga(),
ZManga(),
// removed because scanlator site and they requested
// AhStudios(),
// KnightNoScanlation(),
)
}
@Nsfw
class RawMangas : Madara("Raw Mangas", "https://rawmangas.net", "ja", SimpleDateFormat("MMMM dd, yyyy", Locale.US))
class SiXiangScans : Madara("SiXiang Scans", "http://www.sixiangscans.com", "en", SimpleDateFormat("MMMM dd, yyyy", Locale.US))
class SoloScanlation : Madara("SoloScanlation", "https://soloscanlation.site", "en", SimpleDateFormat("MMMM dd, yyyy", Locale.US))
class LovableSubs : Madara("LovableSubs", "https://lovablesubs.com", "tr", SimpleDateFormat("dd MMM yyyy", Locale("tr")))
class MangaOnlineCo : Madara("Manga-Online.co", "https://www.manga-online.co", "th", SimpleDateFormat("MMM dd, yyyy", Locale("th"))) {
override fun chapterListParse(response: Response): List<SChapter> = super.chapterListParse(response).reversed()
}
class NeatManga : Madara("NeatManga", "https://neatmanga.com", "en", SimpleDateFormat("dd MMM yyyy", Locale.US))
class WarQueenScan : Madara("War Queen Scan", "https://wqscan.com", "pt-BR", SimpleDateFormat("dd/MM/yyyy", Locale.US))
class StageComics : Madara("StageComics", "https://stagecomics.com", "pt-BR", SimpleDateFormat("MMMM dd, yyyy", Locale("pt"))) {
override fun chapterFromElement(element: Element): SChapter {
val parsedChapter = super.chapterFromElement(element)
parsedChapter.date_upload = element.select("img").firstOrNull()?.attr("alt")
?.let { parseChapterDate(it) }
?: parseChapterDate(element.select("span.chapter-release-date i").firstOrNull()?.text())
return parsedChapter
}
}
class SpookyScanlations : Madara("Spooky Scanlations", "https://spookyscanlations.xyz", "es", SimpleDateFormat("MMMM dd, yyyy", Locale("es")))
class RandomTranslations : Madara("Random Translations", "https://randomtranslations.com", "en", SimpleDateFormat("dd/MM/yyyy", Locale.US))
class ManhuaFast : Madara("ManhuaFast", "https://manhuafast.com", "en") {
override val pageListParseSelector = "li.blocks-gallery-item"
}
class ManhuaSY : Madara("Manhua SY", "https://www.manhuasy.com", "en")
class MangaRave : Madara("MangaRave", "http://www.mangarave.com", "en")
class NekoScan : Madara("NekoScan", "https://nekoscan.com", "en")
class Manga3S : Madara("Manga3S", "https://manga3s.com", "en")
class MGKomik : Madara("MG Komik", "https://mgkomik.my.id", "id")
class MangaSco : Madara("MangaSco", "https://mangasco.com", "en")
class MangaCrimson : Madara("Manga Crimson", "https://mangacrimson.com", "tr", SimpleDateFormat("dd MMMM yyyy", Locale("tr")))
class PrimeManga : Madara("Prime Manga", "https://primemanga.com", "en")
class NekoBreaker : Madara("NekoBreaker", "https://nekobreaker.com", "pt-BR", SimpleDateFormat("MMMM dd, yyyy", Locale("pt")))
class ManganeloLink : Madara("Manganelo.link", "https://manganelo.link", "en")
class MangaRoma : Madara("MangaRoma", "https://mangaroma.com", "en")
class NTSVoidScans : Madara("NTS Void Scans", "https://ntsvoidscans.com", "en")
class ToonGod : Madara("ToonGod", "https://www.toongod.com", "en", SimpleDateFormat("dd MMM yyyy", Locale.US))
class WebToonily : Madara("WebToonily", "https://webtoonily.com", "en")
class Manga18Fun : Madara("Manga18 Fun", "https://manga18.fun", "en")
class MangaYaku : Madara("MangaYaku", "https://mangayaku.my.id", "id")
class RuyaManga : Madara("Rüya Manga", "https://www.ruyamanga.com", "tr", SimpleDateFormat("dd MMMM yyyy", Locale.forLanguageTag("tr")))
class MangaBaz : Madara("MangaBaz", "https://mangabaz.com", "tr", SimpleDateFormat("dd MMMM yyyy", Locale.forLanguageTag("tr")))
class Manhuaga : Madara("Manhuaga", "https://manhuaga.com", "en")
class MangaCultivator : Madara("MangaCultivator", "https://mangacultivator.com", "en")
class OffScan : Madara(
"Off Scan",
"https://offscan.top",
"pt-BR",
dateFormat = SimpleDateFormat("dd/MM/yy", Locale.US)
)
class MangaClash : Madara(
"Manga Clash",
"https://mangaclash.com",
"en",
dateFormat = SimpleDateFormat("MM/dd/yy", Locale.US)
)
class TritiniaScans : Madara("TritiniaScans", "https://tritinia.com", "en")
class CopyPasteScan : Madara("CopyPasteScan", "https://copypastescan.xyz", "es")
class Mangasushi : Madara("Mangasushi", "https://mangasushi.net", "en")
class MangaRawr : Madara("MangaRawr", "https://mangarawr.com", "en")
class ReadManhua : Madara(
"ReadManhua",
"https://readmanhua.net",
"en",
dateFormat = SimpleDateFormat("dd MMM yy", Locale.US)
)
class KomikGo : Madara("KomikGo", "https://komikgo.com", "id")
class TsubakiNoScan : Madara(
"Tsubaki No Scan",
"https://tsubakinoscan.com",
"fr",
dateFormat = SimpleDateFormat("dd/MM/yy", Locale.US)
)
class YokaiJump : Madara(
"Yokai Jump",
"https://yokaijump.fr",
"fr",
dateFormat = SimpleDateFormat("dd/MM/yy", Locale.US)
)
class ZManga : Madara("ZManga", "https://zmanga.org", "es")
class MangazukiMe : Madara("Mangazuki.me", "https://mangazuki.me", "en")
class MangazukiClubJP : Madara("Mangazuki.club", "https://mangazuki.club", "ja")
class MangazukiClubKO : Madara("Mangazuki.club", "https://mangazuki.club", "ko")
class MangaSY : Madara("Manga SY", "https://www.mangasy.com", "en") {
override fun imageRequest(page: Page): Request = super.imageRequest(page).newBuilder()
.cacheControl(CacheControl.FORCE_NETWORK)
.build()
}
class ManwhaClub : Madara("Manwha Club", "https://manhwa.club", "en")
class WuxiaWorld : Madara("WuxiaWorld", "https://wuxiaworld.site", "en") {
override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/tag/webcomic/page/$page/?m_orderby=views", headers)
override fun latestUpdatesRequest(page: Int): Request = GET("$baseUrl/tag/webcomic/page/$page/?m_orderby=latest", headers)
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = super.searchMangaRequest(page, "$query comics", filters)
override fun popularMangaNextPageSelector() = "div.nav-previous.float-left"
}
class ManyToon : Madara("ManyToon", "https://manytoon.com", "en")
class ManyToonMe : Madara("ManyToon.me", "https://manytoon.me", "en")
class BoysLove : Madara("BoysLove", "https://boyslove.me", "en")
class ZinManga : Madara("Zin Translator", "https://zinmanga.com", "en") {
override fun headersBuilder(): Headers.Builder = super.headersBuilder()
.add("Referer", "https://zinmanga.com/")
}
class ManwahentaiMe : Madara("Manwahentai.me", "https://manhwahentai.me", "en")
class Manga3asq : Madara("مانجا العاشق", "https://3asq.org", "ar")
class Milftoon : Madara("Milftoon", "https://milftoon.xxx", "en") {
override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/page/$page/?m_orderby=views", headers)
override fun latestUpdatesRequest(page: Int): Request = GET("$baseUrl/page/$page/?m_orderby=latest", headers)
}
class MangaArabOnline : Madara("Manga Arab Online مانجا عرب اون لاين", "https://mangaarabonline.com", "ar", SimpleDateFormat("MMM d, yyyy", Locale.forLanguageTag("ar")))
class MangaArabTeam : Madara("مانجا عرب تيم Manga Arab Team", "https://mangaarabteam.com", "ar", SimpleDateFormat("dd MMM، yyyy", Locale.forLanguageTag("ar"))) {
override fun imageRequest(page: Page): Request {
return GET(page.imageUrl!!.replace("http:", "https:"))
}
}
class NightComic : Madara("Night Comic", "https://www.nightcomic.com", "en") {
override val formHeaders: Headers = headersBuilder()
.add("Content-Type", "application/x-www-form-urlencoded")
.add("X-MOD-SBB-CTYPE", "xhr")
.build()
}
class Skymanga : Madara("Skymanga", "https://skymanga.co", "en")
@Nsfw
class Toonily : Madara("Toonily", "https://toonily.com", "en") {
override fun getGenreList(): List<Genre> = listOf(
Genre("Action", "action-webtoon"),
Genre("Adult", "adult-webtoon"),
Genre("Adventure", "adventure-webtoon"),
Genre("Comedy", "comedy-webtoon"),
Genre("Drama", "drama-webtoon"),
Genre("Fantasy", "fantasy-webtoon"),
Genre("Gender Bender", "gender-bender"),
Genre("Gossip", "gossip"),
Genre("Harem", "harem-webtoon"),
Genre("Historical", "webtoon-historical"),
Genre("Horror", "horror-webtoon"),
Genre("Josei", "josei-manga"),
Genre("Mature", "mature-webtoon"),
Genre("Mystery", "mystery-webtoon"),
Genre("NTR", "ntr-webtoon"),
Genre("Psychological", "psychological-webtoon"),
Genre("Romance", "romance-webtoon"),
Genre("School life", "school-life-webtoon"),
Genre("Sci-Fi", "scifi-webtoon"),
Genre("Seinen", "seinen-webtoon"),
Genre("Shoujo", "shoujo"),
Genre("Shounen", "shounen-webtoon"),
Genre("Slice of Life", "sliceoflife-webtoon"),
Genre("Supernatural", "supernatural-webtoon"),
Genre("Thriller", "thriller-webtoon"),
Genre("Tragedy", "tragedy"),
Genre("Vanilla", "vanilla-webtoon"),
Genre("Yaoi", "yaoi-webtoon"),
Genre("Yuri", "yuri-webtoon")
)
}
class MangaKomi : Madara("MangaKomi", "https://mangakomi.com", "en")
@Nsfw
class YaoiToshokan : Madara("Yaoi Toshokan", "https://yaoitoshokan.com.br", "pt-BR", SimpleDateFormat("dd MMM yyyy", Locale("pt", "BR"))) {
// Page has custom link to scan website.
override val popularMangaUrlSelector = "div.post-title a:not([target])"
// Chapters are listed old to new.
override fun chapterListParse(response: Response): List<SChapter> {
return super.chapterListParse(response).reversed()
}
override fun pageListParse(document: Document): List<Page> {
return document.select(pageListParseSelector)
.mapIndexed { index, element ->
// Had to add trim because of white space in source.
val imageUrl = element.select("img").attr("data-src").trim()
Page(index, document.location(), imageUrl)
}
}
}
class Mangalek : Madara("مانجا ليك", "https://mangalek.com", "ar", SimpleDateFormat("MMMM dd, yyyy", Locale("ar")))
class AstralLibrary : Madara("Astral Library", "https://www.astrallibrary.net", "en", SimpleDateFormat("d MMM", Locale.US)) {
override fun popularMangaRequest(page: Int): Request {
return GET("$baseUrl/manga-tag/manga/?m_orderby=views&page=$page", headers)
}
override fun latestUpdatesRequest(page: Int): Request {
return GET("$baseUrl/manga-tag/manga/?m_orderby=latest&page=$page", headers)
}
}
class MiracleScans : Madara("Miracle Scans", "https://miraclescans.com", "en")
class Manhuasnet : Madara("Manhuas.net", "https://manhuas.net", "en")
class MangaTX : Madara("MangaTX", "https://mangatx.com", "en")
class OnManga : Madara("OnManga", "https://onmanga.com", "en")
class MangaAction : Madara("Manga Action", "https://manga-action.com", "ar", SimpleDateFormat("yyyy-MM-dd", Locale("ar")))
class NijiTranslations : Madara("Niji Translations", "https://niji-translations.com", "ar", SimpleDateFormat("MMMM dd, yyyy", Locale("ar")))
class LilyManga : Madara("Lily Manga", "https://lilymanga.com", "en", SimpleDateFormat("yyyy-MM-dd", Locale.US))
class MangaBob : Madara("MangaBob", "https://mangabob.com", "en")
class ThreeSixtyFiveManga : Madara("365Manga", "https://365manga.com", "en") {
override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/manga/page/$page/?m_orderby=views", headers)
override fun latestUpdatesRequest(page: Int): Request = GET("$baseUrl/manga/page/$page/?m_orderby=latest", headers)
}
class MangaDods : Madara("MangaDods", "https://www.mangadods.com", "en", SimpleDateFormat("yyyy-MM-dd", Locale.US))
class NeoxScanlator : Madara(
"Neox Scanlator",
"https://neoxscans.com",
"pt-BR",
SimpleDateFormat("dd/MM/yyyy", Locale("pt", "BR"))
) {
override val client: OkHttpClient = network.cloudflareClient.newBuilder()
.connectTimeout(1, TimeUnit.MINUTES)
.readTimeout(1, TimeUnit.MINUTES)
.build()
override fun headersBuilder(): Headers.Builder = Headers.Builder()
.add("User-Agent", USER_AGENT)
.add("Referer", baseUrl)
.add("Origin", baseUrl)
// Only status and order by filter work.
override fun getFilterList(): FilterList = FilterList(super.getFilterList().slice(3..4))
companion object {
private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"
}
}
class MangaLord : Madara("Manga Lord", "https://mangalord.com", "en")
@Nsfw
class PornComix : Madara("PornComix", "https://www.porncomixonline.net", "en")
class PMScans : Madara("PMScans", "https://www.pmscans.com", "en", SimpleDateFormat("MMM-dd-yy", Locale.US))
class MangaRead : Madara("Manga Read", "https://mangaread.co", "en", SimpleDateFormat("yyyy-MM-dd", Locale.US))
class Manga68 : Madara("Manga68", "https://manga68.com", "en") {
override val pageListParseSelector = "div.page-break, div.text-left p"
}
class ManhuaBox : Madara("ManhuaBox", "https://manhuabox.net", "en") {
override val pageListParseSelector = "div.page-break, div.text-left p img"
}
class RaiderScans : Madara("Raider Scans", "https://raiderscans.com", "en")
class PojokManga : Madara("Pojok Manga", "https://pojokmanga.com", "id", SimpleDateFormat("MMM dd, yyyy", Locale.US))
class TopManhua : Madara("Top Manhua", "https://topmanhua.com", "en", SimpleDateFormat("MM/dd/yy", Locale.US)) {
override fun headersBuilder(): Headers.Builder = super.headersBuilder().add("Referer", baseUrl)
}
class ManyToonClub : Madara("ManyToonClub", "https://manytoon.club", "ko")
class ManhuaUS : Madara("ManhuaUS", "https://manhuaus.com", "en") {
override val pageListParseSelector = "li.blocks-gallery-item"
}
class MangaWT : Madara("MangaWT", "https://mangawt.com", "tr")
class MangaRockTeam : Madara("Manga Rock Team", "https://mangarockteam.com", "en")
class MixedManga : Madara("Mixed Manga", "https://mixedmanga.com", "en", SimpleDateFormat("d MMM yyyy", Locale.US)) {
override fun headersBuilder(): Headers.Builder = super.headersBuilder().add("Referer", baseUrl)
}
class ManhuasWorld : Madara("Manhuas World", "https://manhuasworld.com", "en")
class ManhwaRaw : Madara("Manhwa Raw", "https://manhwaraw.com", "ko")
class WeScans : Madara("WeScans", "https://wescans.xyz", "en") {
override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/manhua/manga/?m_orderby=views", headers)
override fun popularMangaNextPageSelector(): String? = null
override fun latestUpdatesRequest(page: Int): Request = GET("$baseUrl/manhua/manga/?m_orderby=latest", headers)
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = GET("$baseUrl/manhua/?s=$query&post_type=wp-manga")
override fun searchMangaNextPageSelector(): String? = null
override fun getFilterList(): FilterList = FilterList()
}
@Nsfw
class MangaHentai : Madara("Manga Hentai", "https://mangahentai.me", "en")
class MangaPhoenix : Madara("Manga Diyari", "https://mangadiyari.com", "tr") {
// Formerly "Manga Phoenix"
override val id = 4308007020001642101
}
class MartialScans : Madara("Martial Scans", "https://martialscans.com", "en") {
override fun popularMangaFromElement(element: Element): SManga {
val manga = SManga.create()
with(element) {
select(popularMangaUrlSelector).last()?.let {
manga.setUrlWithoutDomain(it.attr("href"))
manga.title = it.ownText()
}
select("img").last()?.let {
manga.thumbnail_url = imageFromElement(it)
}
}
return manga
}
override fun searchMangaFromElement(element: Element): SManga = popularMangaFromElement(element)
}
class MangaYosh : Madara("MangaYosh", "https://mangayosh.xyz", "id", SimpleDateFormat("dd MMM yyyy", Locale.US))
class WebtoonXYZ : Madara("WebtoonXYZ", "https://www.webtoon.xyz", "en") {
private fun pagePath(page: Int) = if (page > 1) "page/$page/" else ""
override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/webtoons/${pagePath(page)}?m_orderby=views", headers)
override fun latestUpdatesRequest(page: Int): Request = GET("$baseUrl/webtoons/${pagePath(page)}?m_orderby=latest", headers)
}
class MangaReadOrg : Madara("MangaRead.org", "https://www.mangaread.org", "en", SimpleDateFormat("dd.MM.yyy", Locale.US))
class TurkceManga : Madara("Türkçe Manga", "https://turkcemanga.com", "tr") {
override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/page/$page/?s&post_type=wp-manga&m_orderby=views", headers)
override fun popularMangaSelector() = searchMangaSelector()
override fun popularMangaFromElement(element: Element): SManga = searchMangaFromElement(element)
override fun latestUpdatesRequest(page: Int): Request = GET("$baseUrl/page/$page/?s&post_type=wp-manga&m_orderby=latest", headers)
override fun latestUpdatesSelector() = searchMangaSelector()
override fun latestUpdatesFromElement(element: Element): SManga = searchMangaFromElement(element)
}
class Manga347 : Madara("Manga347", "https://manga347.com", "en", SimpleDateFormat("d MMM, yyyy", Locale.US)) {
override val pageListParseSelector = "li.blocks-gallery-item"
}
class RenaScans : Madara("Renascence Scans (Renascans)", "https://new.renascans.com", "en", SimpleDateFormat("dd/MM/yyyy", Locale.US))
class QueensManga : Madara("QueensManga ملكات المانجا", "https://queensmanga.com", "ar") {
override fun chapterListSelector(): String = "div.listing-chapters_wrap a"
}
class TheTopComic : Madara("TheTopComic", "https://thetopcomic.com", "en")
class WebNovel : Madara("WebNovel", "https://webnovel.live", "en")
class TruyenTranhAudioCom : Madara("TruyenTranhAudio.com", "https://truyentranhaudio.com", "vi", SimpleDateFormat("dd/MM/yyyy", Locale.getDefault())) {
override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/page/$page?s&post_type=wp-manga&m_orderby=views", headers)
override fun popularMangaSelector() = searchMangaSelector()
override fun popularMangaFromElement(element: Element): SManga = searchMangaFromElement(element)
override fun latestUpdatesRequest(page: Int): Request = GET("$baseUrl/page/$page?s&post_type=wp-manga&m_orderby=latest", headers)
override fun latestUpdatesSelector() = searchMangaSelector()
override fun latestUpdatesFromElement(element: Element): SManga = searchMangaFromElement(element)
override fun pageListParse(document: Document): List<Page> {
return document.select("div.reading-content img").map { it.attr("abs:src") }
.filterNot { it.isNullOrEmpty() }
.distinct()
.mapIndexed { i, url -> Page(i, "", url) }
}
}
class TruyenTranhAudioOnline : Madara("TruyenTranhAudio.online", "https://truyentranhaudio.online", "vi", SimpleDateFormat("dd/MM/yyyy", Locale.getDefault())) {
override val formHeaders: Headers = headersBuilder()
.add("Content-Type", "application/x-www-form-urlencoded")
.build()
override fun pageListParse(document: Document): List<Page> {
return document.select("div.reading-content img").map { it.attr("abs:src") }
.filterNot { it.isNullOrEmpty() }
.distinct()
.mapIndexed { i, url -> Page(i, "", url) }
}
}
class MangaTurf : Madara("Manga Turf", "https://mangaturf.com", "en")
class Mangareceh : Madara("Mangareceh", "https://mangareceh.id", "id")
class ToonPoint : Madara("ToonPoint", "https://toonpoint.com", "en") {
override val userAgentRandomizer = ""
}
class MangaScantrad : Madara("Manga-Scantrad", "https://manga-scantrad.net", "fr", SimpleDateFormat("d MMM yyyy", Locale.FRANCE))
class ManhuaPlus : Madara("Manhua Plus", "https://manhuaplus.com", "en") {
override val pageListParseSelector = "li.blocks-gallery-item"
}
@Nsfw
class ToonilyNet : Madara("Toonily.net", "https://toonily.net", "en")
class TwilightScans : Madara("Twilight Scans", "https://twilightscans.com", "en")
// mostly novels
class WoopRead : Madara("WoopRead", "https://woopread.com", "en")
class Ninjavi : Madara("Ninjavi", "https://ninjavi.com", "ar")
class ManhwaTop : Madara("Manhwatop", "https://manhwatop.com", "en")
class Wakascan : Madara("Wakascan", "https://wakascan.com", "fr")
class ShoujoHearts : Madara("ShoujoHearts", "http://shoujohearts.com", "en") {
override fun popularMangaRequest(page: Int): Request =
POST("$baseUrl/reader/wp-admin/admin-ajax.php", formHeaders, formBuilder(page, true).build(), CacheControl.FORCE_NETWORK)
override fun latestUpdatesRequest(page: Int): Request =
POST("$baseUrl/reader/wp-admin/admin-ajax.php", formHeaders, formBuilder(page, false).build(), CacheControl.FORCE_NETWORK)
override fun searchPage(page: Int): String = "reader/page/$page/"
}
class OlaoeManga : Madara("مانجا اولاو", "https://olaoe.giize.com", "ar")
class OrigamiOrpheans : Madara("Origami Orpheans", "https://origami-orpheans.com.br", "pt-BR")
class MangaKiss : Madara("Manga Kiss", "https://mangakiss.org", "en")
class MangaRocky : Madara("Manga Rocky", "https://mangarocky.com", "en")
class S2Manga : Madara("S2Manga", "https://s2manga.com", "en")
class MangaLandArabic : Madara("Manga Land Arabic", "https://mangalandarabic.com", "ar")
class ProjetoScanlator : Madara("Projeto Scanlator", "https://projetoscanlator.com", "pt-BR", SimpleDateFormat("dd/MM/yyyy", Locale("pt", "BR")))
class NazarickScans : Madara("Nazarick Scans", "https://nazarickscans.com", "en") {
override fun popularMangaRequest(page: Int) = GET("$baseUrl/manga/page/$page/?m_orderby=trending", headers)
override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/manga/page/$page/?m_orderby=trending", headers)
override fun popularMangaNextPageSelector(): String? = null
override fun latestUpdatesNextPageSelector(): String? = null
}
class MangaSpark : Madara("MangaSpark", "https://mangaspark.com", "ar") {
override fun popularMangaFromElement(element: Element): SManga {
val manga = SManga.create()
with(element) {
select(popularMangaUrlSelector).first()?.let {
manga.setUrlWithoutDomain(it.attr("abs:href"))
manga.title = it.ownText()
}
select("img").first()?.let {
manga.thumbnail_url = imageFromElement(it)?.replace("mangaspark", "mangalek")
}
}
return manga
}
}
class MangaStarz : Madara("Manga Starz", "https://mangastarz.com", "ar") {
override fun popularMangaFromElement(element: Element): SManga {
val manga = SManga.create()
with(element) {
select(popularMangaUrlSelector).first()?.let {
manga.setUrlWithoutDomain(it.attr("abs:href"))
manga.title = it.ownText()
}
select("img").first()?.let {
manga.thumbnail_url = imageFromElement(it)?.replace("mangastarz", "mangalek")
}
}
return manga
}
}
class MysticalMerries : Madara("Mystical Merries", "https://mysticalmerries.com", "en") {
override fun popularMangaRequest(page: Int) = GET("$baseUrl/genre/manhwa/page/$page/?m_orderby=trending", headers)
override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/genre/manhwa/page/$page/?m_orderby=latest", headers)
}
class MangaNine : Madara("Manga Nine", "https://manganine.com", "en")
class MarkScans : Madara("Mark Scans", "https://markscans.online", "pt-BR")
class YuriVerso : Madara(
"Yuri Verso",
"https://yuri.live",
"pt-BR",
SimpleDateFormat("dd/MM/yyyy", Locale("pt", "BR"))
)
class MangaStein : Madara("MangaStein", "https://mangastein.com", "tr")
class MangaTeca : Madara(
"MangaTeca",
"https://www.mangateca.com",
"pt-BR",
SimpleDateFormat("MMMM dd, yyyy", Locale("pt", "BR"))
) {
override fun headersBuilder(): Headers.Builder = Headers.Builder()
.add("User-Agent", USER_AGENT)
.add("Referer", baseUrl)
.add("Origin", baseUrl)
override fun chapterFromElement(element: Element): SChapter {
val parsedChapter = super.chapterFromElement(element)
parsedChapter.date_upload = element.select("img").firstOrNull()?.attr("alt")
?.let { parseChapterDate(it) }
?: parseChapterDate(element.select("span.chapter-release-date i").firstOrNull()?.text())
return parsedChapter
}
companion object {
private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36"
}
}
class Voidscans : Madara("Void Scans", "https://voidscans.com", "en") {
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = GET("$baseUrl/?s=$query&post_type=wp-manga")
}
class UyuyanBalik : Madara("Uyuyan Balik", "https://uyuyanbalik.com/", "tr", SimpleDateFormat("dd MMMM yyyy", Locale.US))
class MangaWeebs : Madara("Manga Weebs", "https://mangaweebs.in", "en")
class MMScans : Madara("MMScans", "https://mm-scans.com/", "en")
@Nsfw
class Siyahmelek : Madara("Siyahmelek", "https://siyahmelek.com", "tr", SimpleDateFormat("dd MMM yyyy", Locale("tr")))
@Nsfw
class SekteDoujin : Madara("Sekte Doujin", "https://sektedoujin.xyz", "id")
class MundoWuxia : Madara("Mundo Wuxia", "https://mundowuxia.com", "es", SimpleDateFormat("MMMM dd, yyyy", Locale("es")))
class WorldRomanceTranslation : Madara("World Romance Translation", "https://wrt.my.id/", "id", SimpleDateFormat("dd MMMM yyyy", Locale("id")))
class VanguardBun : Madara("Vanguard Bun", "https://vanguardbun.com/", "en")
class MangaBin : Madara("Manga Bin", "https://mangabin.com/", "en")
class MangaChill : Madara("Manga Chill", "https://mangachill.com/", "en")