Replace HolyManga & HeavenManga (#2950)

This commit is contained in:
Mike 2020-05-01 18:14:36 -04:00 committed by GitHub
parent a22d8efae1
commit b17987b8e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 75 additions and 83 deletions

View File

@ -2,10 +2,10 @@ apply plugin: 'com.android.application'
apply plugin: 'kotlin-android' apply plugin: 'kotlin-android'
ext { ext {
appName = 'Tachiyomi: HolyManga & HeavenManga' appName = 'Tachiyomi: zBulu'
pkgNameSuffix = 'en.holymanga' pkgNameSuffix = 'all.zbulu'
extClass = '.HMangaFactory' extClass = '.ZbuluFactory'
extVersionCode = 3 extVersionCode = 1
libVersion = '1.2' libVersion = '1.2'
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -1,4 +1,4 @@
package eu.kanade.tachiyomi.extension.en.holymanga package eu.kanade.tachiyomi.extension.all.zbulu
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.source.model.Filter import eu.kanade.tachiyomi.source.model.Filter
@ -10,43 +10,54 @@ import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Locale import java.util.Locale
import java.util.concurrent.TimeUnit
import okhttp3.Headers
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
abstract class HManga( abstract class Zbulu(
override val name: String, override val name: String,
override val baseUrl: String override val baseUrl: String,
override val lang: String = "en"
) : ParsedHttpSource() { ) : ParsedHttpSource() {
override val lang = "en"
override val supportsLatest = true override val supportsLatest = true
override val client: OkHttpClient = network.cloudflareClient override val client: OkHttpClient = network.cloudflareClient.newBuilder()
.connectTimeout(1, TimeUnit.MINUTES)
.readTimeout(1, TimeUnit.MINUTES)
.writeTimeout(1, TimeUnit.MINUTES)
.build()
override fun headersBuilder(): Headers.Builder = Headers.Builder()
.add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0")
.add("Content-Encoding", "identity")
// Decreases calls, helps with Cloudflare
private fun String.addTrailingSlash() = if (!this.endsWith("/")) "$this/" else this
// Popular // Popular
// This returns 12 manga or so, main browsing for this source should be through latest
override fun popularMangaRequest(page: Int): Request { override fun popularMangaRequest(page: Int): Request {
return GET(baseUrl, headers) return GET("$baseUrl/manga-list/page-$page/", headers)
} }
override fun popularMangaSelector() = "section#popular div.entry.vertical" override fun popularMangaSelector() = "div.comics-grid > div.entry"
override fun popularMangaFromElement(element: Element): SManga { override fun popularMangaFromElement(element: Element): SManga {
val manga = SManga.create() return SManga.create().apply {
element.select("h2 a").let { element.select("h3 a").let {
manga.setUrlWithoutDomain(it.attr("href")) setUrlWithoutDomain(it.attr("href").addTrailingSlash())
manga.title = it.text() title = it.text()
}
thumbnail_url = element.select("img").first().attr("abs:src")
} }
manga.thumbnail_url = element.select("img").first().attr("src")
return manga
} }
override fun popularMangaNextPageSelector() = "Not needed" override fun popularMangaNextPageSelector() = "a.next:has(i.fa-angle-right)"
// Latest // Latest
@ -54,19 +65,11 @@ abstract class HManga(
return GET("$baseUrl/latest-update/page-$page/", headers) return GET("$baseUrl/latest-update/page-$page/", headers)
} }
override fun latestUpdatesSelector() = "div.comics-grid > div.entry" override fun latestUpdatesSelector() = popularMangaSelector()
override fun latestUpdatesFromElement(element: Element): SManga { override fun latestUpdatesFromElement(element: Element): SManga = popularMangaFromElement(element)
val manga = SManga.create()
element.select("h3 a").let {
manga.setUrlWithoutDomain(it.attr("href"))
manga.title = it.text()
}
manga.thumbnail_url = element.select("img").first().attr("src")
return manga
}
override fun latestUpdatesNextPageSelector() = "a.next:has(i.fa-angle-right)" override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector()
// Search // Search
@ -78,7 +81,7 @@ abstract class HManga(
lateinit var genre: String lateinit var genre: String
filters.forEach { filter -> filters.forEach { filter ->
when (filter) { when (filter) {
is TextField -> { is AuthorField -> {
if (filter.state.isNotBlank()) { if (filter.state.isNotBlank()) {
ret = "$baseUrl/author/${filter.state.replace(" ", "-")}/page-$page" ret = "$baseUrl/author/${filter.state.replace(" ", "-")}/page-$page"
} }
@ -107,15 +110,14 @@ abstract class HManga(
override fun mangaDetailsParse(document: Document): SManga { override fun mangaDetailsParse(document: Document): SManga {
val infoElement = document.select("div.single-comic").first() val infoElement = document.select("div.single-comic").first()
val manga = SManga.create() return SManga.create().apply {
manga.title = infoElement.select("h1").first().text() title = infoElement.select("h1").first().text()
manga.author = infoElement.select("div.author a").text() author = infoElement.select("div.author a").text()
val status = infoElement.select("div.update span[style]").text() status = parseStatus(infoElement.select("div.update span[style]").text())
manga.status = parseStatus(status) genre = infoElement.select("div.genre a").joinToString { it.text() }
manga.genre = infoElement.select("div.genre").text().substringAfter("Genre(s): ") description = infoElement.select("div.comic-description p").text()
manga.description = infoElement.select("div.comic-description p").text() thumbnail_url = infoElement.select("img").attr("abs:src")
manga.thumbnail_url = infoElement.select("img").attr("src") }
return manga
} }
private fun parseStatus(status: String?) = when { private fun parseStatus(status: String?) = when {
@ -131,34 +133,26 @@ abstract class HManga(
override fun chapterListParse(response: Response): List<SChapter> { override fun chapterListParse(response: Response): List<SChapter> {
val chapters = mutableListOf<SChapter>() val chapters = mutableListOf<SChapter>()
var document = response.asJsoup()
var continueParsing = true
// Chapter list is paginated // Chapter list may be paginated, get recursively
while (continueParsing) { fun addChapters(document: Document) {
document.select(chapterListSelector()).map { chapters.add(chapterFromElement(it)) } document.select(chapterListSelector()).map { chapters.add(chapterFromElement(it)) }
// Next page of chapters document.select("${latestUpdatesNextPageSelector()}:not([id])").firstOrNull()
document.select("${latestUpdatesNextPageSelector()}:not([id])").let { ?.let { addChapters(client.newCall(GET(it.attr("abs:href").addTrailingSlash(), headers)).execute().asJsoup()) }
if (it.isNotEmpty()) {
document = client.newCall(GET(it.attr("abs:href"), headers)).execute().asJsoup()
} else {
continueParsing = false
}
}
} }
addChapters(response.asJsoup())
return chapters return chapters
} }
override fun chapterFromElement(element: Element): SChapter { override fun chapterFromElement(element: Element): SChapter {
val chapter = SChapter.create() return SChapter.create().apply {
element.select("a").let { element.select("a").let {
chapter.setUrlWithoutDomain(it.attr("href")) setUrlWithoutDomain(it.attr("href").addTrailingSlash())
chapter.name = it.text() name = it.text()
}
date_upload = element.select("div.chapter-date")?.text()?.let { parseChapterDate(it) } ?: 0
} }
chapter.date_upload = parseChapterDate(element.select("div.chapter-date").text())
return chapter
} }
companion object { companion object {
@ -174,26 +168,22 @@ abstract class HManga(
// Pages // Pages
override fun pageListParse(document: Document): List<Page> { override fun pageListParse(document: Document): List<Page> {
val pages = mutableListOf<Page>() return document.select("div.chapter-content img").mapIndexed { i, img ->
Page(i, "", img.attr("abs:src"))
document.select("div.chapter-content img").forEach {
pages.add(Page(pages.size, "", it.attr("src")))
} }
return pages
} }
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used") override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used")
// Filters // Filters
private class TextField(name: String, val key: String) : Filter.Text(name) private class AuthorField : Filter.Text("Author")
override fun getFilterList() = FilterList( override fun getFilterList() = FilterList(
Filter.Header("Cannot combine search types!"), Filter.Header("Cannot combine search types!"),
Filter.Header("Author name must be exact."), Filter.Header("Author name must be exact."),
Filter.Separator("-----------------"), Filter.Separator("-----------------"),
TextField("Author", "author"), AuthorField(),
GenreFilter() GenreFilter()
) )

View File

@ -0,0 +1,16 @@
package eu.kanade.tachiyomi.extension.all.zbulu
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceFactory
class ZbuluFactory : SourceFactory {
override fun createSources(): List<Source> = listOf(
HolyManga(),
HeavenManga(),
KooManga()
)
}
class HolyManga : Zbulu("HolyManga", "https://w15.holymanga.net")
class HeavenManga : Zbulu("HeavenManga", "http://heaventoon.com")
class KooManga : Zbulu("Koo Manga", "http://ww1.koomanga.com")

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 128 KiB

View File

@ -1,14 +0,0 @@
package eu.kanade.tachiyomi.extension.en.holymanga
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceFactory
class HMangaFactory : SourceFactory {
override fun createSources(): List<Source> = listOf(
HolyManga(),
HeavenManga()
)
}
class HolyManga : HManga("HolyManga", "http://w12.holymanga.net")
class HeavenManga : HManga("HeavenManga", "http://ww8.heavenmanga.org")