Implement Mangafox and Mangahere with the new source
This commit is contained in:
parent
dd5692bb2d
commit
015257fe75
@ -8,6 +8,8 @@ import eu.kanade.tachiyomi.data.source.base.Source
|
|||||||
import eu.kanade.tachiyomi.data.source.base.YamlOnlineSource
|
import eu.kanade.tachiyomi.data.source.base.YamlOnlineSource
|
||||||
import eu.kanade.tachiyomi.data.source.online.english.Batoto
|
import eu.kanade.tachiyomi.data.source.online.english.Batoto
|
||||||
import eu.kanade.tachiyomi.data.source.online.english.Kissmanga
|
import eu.kanade.tachiyomi.data.source.online.english.Kissmanga
|
||||||
|
import eu.kanade.tachiyomi.data.source.online.english.Mangafox
|
||||||
|
import eu.kanade.tachiyomi.data.source.online.english.Mangahere
|
||||||
import org.yaml.snakeyaml.Yaml
|
import org.yaml.snakeyaml.Yaml
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@ -36,6 +38,8 @@ open class SourceManager(private val context: Context) {
|
|||||||
private fun createSource(id: Int): Source? = when (id) {
|
private fun createSource(id: Int): Source? = when (id) {
|
||||||
BATOTO -> Batoto(context, id)
|
BATOTO -> Batoto(context, id)
|
||||||
KISSMANGA -> Kissmanga(context, id)
|
KISSMANGA -> Kissmanga(context, id)
|
||||||
|
MANGAHERE -> Mangahere(context, id)
|
||||||
|
MANGAFOX -> Mangafox(context, id)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,6 +202,7 @@ class Batoto(context: Context, override val id: Int) : ParsedOnlineSource(contex
|
|||||||
for ((i, element) in selectElement.select("option").withIndex()) {
|
for ((i, element) in selectElement.select("option").withIndex()) {
|
||||||
pages.add(Page(i, element.attr("value")))
|
pages.add(Page(i, element.attr("value")))
|
||||||
}
|
}
|
||||||
|
pages.getOrNull(0)?.imageUrl = imageUrlParse(document)
|
||||||
} else {
|
} else {
|
||||||
// For webtoons in one page
|
// For webtoons in one page
|
||||||
for ((i, element) in document.select("div > img").withIndex()) {
|
for ((i, element) in document.select("div > img").withIndex()) {
|
||||||
|
@ -40,6 +40,8 @@ class Kissmanga(context: Context, override val id: Int) : ParsedOnlineSource(con
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun popularMangaNextPageSelector() = "li > a:contains(› Next)"
|
||||||
|
|
||||||
override fun searchMangaRequest(page: MangasPage, query: String): Request {
|
override fun searchMangaRequest(page: MangasPage, query: String): Request {
|
||||||
if (page.page == 1) {
|
if (page.page == 1) {
|
||||||
page.url = searchMangaInitialUrl(query)
|
page.url = searchMangaInitialUrl(query)
|
||||||
@ -55,7 +57,7 @@ class Kissmanga(context: Context, override val id: Int) : ParsedOnlineSource(con
|
|||||||
return post(page.url, headers, form)
|
return post(page.url, headers, form)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun popularMangaNextPageSelector() = "li > a:contains(› Next)"
|
override fun searchMangaInitialUrl(query: String) = "$baseUrl/AdvanceSearch"
|
||||||
|
|
||||||
override fun searchMangaSelector() = popularMangaSelector()
|
override fun searchMangaSelector() = popularMangaSelector()
|
||||||
|
|
||||||
@ -65,26 +67,20 @@ class Kissmanga(context: Context, override val id: Int) : ParsedOnlineSource(con
|
|||||||
|
|
||||||
override fun searchMangaNextPageSelector() = null
|
override fun searchMangaNextPageSelector() = null
|
||||||
|
|
||||||
override fun searchMangaInitialUrl(query: String) = "$baseUrl/AdvanceSearch"
|
|
||||||
|
|
||||||
override fun mangaDetailsParse(document: Document, manga: Manga) {
|
override fun mangaDetailsParse(document: Document, manga: Manga) {
|
||||||
val infoElement = document.select("div.barContent").first()
|
val infoElement = document.select("div.barContent").first()
|
||||||
|
|
||||||
manga.author = infoElement.select("p:has(span:contains(Author:)) > a").first()?.text()
|
manga.author = infoElement.select("p:has(span:contains(Author:)) > a").first()?.text()
|
||||||
manga.genre = infoElement.select("p:has(span:contains(Genres:)) > *:gt(0)").text()
|
manga.genre = infoElement.select("p:has(span:contains(Genres:)) > *:gt(0)").text()
|
||||||
manga.description = infoElement.select("p:has(span:contains(Summary:)) ~ p").text()
|
manga.description = infoElement.select("p:has(span:contains(Summary:)) ~ p").text()
|
||||||
manga.status = parseStatus(infoElement.select("p:has(span:contains(Status:))").first()?.text())
|
manga.status = infoElement.select("p:has(span:contains(Status:))").first()?.text().orEmpty().let { parseStatus(it)}
|
||||||
manga.thumbnail_url = document.select(".rightBox:eq(0) img").first()?.attr("src")
|
manga.thumbnail_url = document.select(".rightBox:eq(0) img").first()?.attr("src")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun parseStatus(status: String?): Int {
|
fun parseStatus(status: String) = when {
|
||||||
if (status != null) {
|
status.contains("Ongoing") -> Manga.ONGOING
|
||||||
when {
|
status.contains("Completed") -> Manga.COMPLETED
|
||||||
status.contains("Ongoing") -> return Manga.ONGOING
|
else -> Manga.UNKNOWN
|
||||||
status.contains("Completed") -> return Manga.COMPLETED
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Manga.UNKNOWN
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun chapterListSelector() = "table.listing tr:gt(1)"
|
override fun chapterListSelector() = "table.listing tr:gt(1)"
|
||||||
@ -102,7 +98,8 @@ class Kissmanga(context: Context, override val id: Int) : ParsedOnlineSource(con
|
|||||||
override fun pageListRequest(chapter: Chapter) = post(baseUrl + chapter.url, headers)
|
override fun pageListRequest(chapter: Chapter) = post(baseUrl + chapter.url, headers)
|
||||||
|
|
||||||
override fun pageListParse(response: Response, pages: MutableList<Page>) {
|
override fun pageListParse(response: Response, pages: MutableList<Page>) {
|
||||||
val p = Pattern.compile("lstImages.push\\(\"(.+?)\"")
|
//language=RegExp
|
||||||
|
val p = Pattern.compile("""lstImages.push\("(.+?)"""")
|
||||||
val m = p.matcher(response.body().string())
|
val m = p.matcher(response.body().string())
|
||||||
|
|
||||||
var i = 0
|
var i = 0
|
||||||
|
@ -0,0 +1,122 @@
|
|||||||
|
package eu.kanade.tachiyomi.data.source.online.english
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
|
import eu.kanade.tachiyomi.data.source.EN
|
||||||
|
import eu.kanade.tachiyomi.data.source.Language
|
||||||
|
import eu.kanade.tachiyomi.data.source.base.ParsedOnlineSource
|
||||||
|
import eu.kanade.tachiyomi.data.source.model.Page
|
||||||
|
import okhttp3.Response
|
||||||
|
import org.jsoup.Jsoup
|
||||||
|
import org.jsoup.nodes.Document
|
||||||
|
import org.jsoup.nodes.Element
|
||||||
|
import java.text.ParseException
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class Mangafox(context: Context, override val id: Int) : ParsedOnlineSource(context) {
|
||||||
|
|
||||||
|
override val name = "Mangafox"
|
||||||
|
|
||||||
|
override val baseUrl = "http://mangafox.me"
|
||||||
|
|
||||||
|
override val lang: Language get() = EN
|
||||||
|
|
||||||
|
override fun popularMangaInitialUrl() = "$baseUrl/directory/"
|
||||||
|
|
||||||
|
override fun popularMangaSelector() = "div#mangalist > ul.list > li"
|
||||||
|
|
||||||
|
override fun popularMangaFromElement(element: Element, manga: Manga) {
|
||||||
|
element.select("a.title").first().let {
|
||||||
|
manga.setUrl(it.attr("href"))
|
||||||
|
manga.title = it.text()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun popularMangaNextPageSelector() = "a:has(span.next)"
|
||||||
|
|
||||||
|
override fun searchMangaInitialUrl(query: String) =
|
||||||
|
"$baseUrl/search.php?name_method=cw&advopts=1&order=za&sort=views&name=$query&page=1"
|
||||||
|
|
||||||
|
override fun searchMangaSelector() = "table#listing > tbody > tr:gt(0)"
|
||||||
|
|
||||||
|
override fun searchMangaFromElement(element: Element, manga: Manga) {
|
||||||
|
element.select("a.series_preview").first().let {
|
||||||
|
manga.setUrl(it.attr("href"))
|
||||||
|
manga.title = it.text()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun searchMangaNextPageSelector() = "a:has(span.next)"
|
||||||
|
|
||||||
|
override fun mangaDetailsParse(document: Document, manga: Manga) {
|
||||||
|
val infoElement = document.select("div#title").first()
|
||||||
|
val rowElement = infoElement.select("table > tbody > tr:eq(1)").first()
|
||||||
|
val sideInfoElement = document.select("#series_info").first()
|
||||||
|
|
||||||
|
manga.author = rowElement.select("td:eq(1)").first()?.text()
|
||||||
|
manga.artist = rowElement.select("td:eq(2)").first()?.text()
|
||||||
|
manga.genre = rowElement.select("td:eq(3)").first()?.text()
|
||||||
|
manga.description = infoElement.select("p.summary").first()?.text()
|
||||||
|
manga.status = sideInfoElement.select(".data").first()?.text().orEmpty().let { parseStatus(it) }
|
||||||
|
manga.thumbnail_url = sideInfoElement.select("div.cover > img").first()?.attr("src")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parseStatus(status: String) = when {
|
||||||
|
status.contains("Ongoing") -> Manga.ONGOING
|
||||||
|
status.contains("Completed") -> Manga.COMPLETED
|
||||||
|
else -> Manga.UNKNOWN
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun chapterListSelector() = "div#chapters li div"
|
||||||
|
|
||||||
|
override fun chapterFromElement(element: Element, chapter: Chapter) {
|
||||||
|
val urlElement = element.select("a.tips").first()
|
||||||
|
|
||||||
|
chapter.setUrl(urlElement.attr("href"))
|
||||||
|
chapter.name = urlElement.text()
|
||||||
|
chapter.date_upload = element.select("span.date").first()?.text()?.let { parseChapterDate(it) } ?: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parseChapterDate(date: String): Long {
|
||||||
|
return if ("Today" in date || " ago" in date) {
|
||||||
|
Calendar.getInstance().apply {
|
||||||
|
set(Calendar.HOUR_OF_DAY, 0)
|
||||||
|
set(Calendar.MINUTE, 0)
|
||||||
|
set(Calendar.SECOND, 0)
|
||||||
|
set(Calendar.MILLISECOND, 0)
|
||||||
|
}.timeInMillis
|
||||||
|
} else if ("Yesterday" in date) {
|
||||||
|
Calendar.getInstance().apply {
|
||||||
|
add(Calendar.DATE, -1)
|
||||||
|
set(Calendar.HOUR_OF_DAY, 0)
|
||||||
|
set(Calendar.MINUTE, 0)
|
||||||
|
set(Calendar.SECOND, 0)
|
||||||
|
set(Calendar.MILLISECOND, 0)
|
||||||
|
}.timeInMillis
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH).parse(date).time
|
||||||
|
} catch (e: ParseException) {
|
||||||
|
0L
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun pageListParse(response: Response, pages: MutableList<Page>) {
|
||||||
|
val document = Jsoup.parse(response.body().string())
|
||||||
|
|
||||||
|
val url = response.request().url().toString().substringBeforeLast('/')
|
||||||
|
document.select("select.m").first().select("option:not([value=0])").forEach {
|
||||||
|
pages.add(Page(pages.size, "$url/${it.attr("value")}.html"))
|
||||||
|
}
|
||||||
|
pages.getOrNull(0)?.imageUrl = imageUrlParse(document)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not used, overrides parent.
|
||||||
|
override fun pageListParse(document: Document, pages: MutableList<Page>) {}
|
||||||
|
|
||||||
|
override fun imageUrlParse(document: Document) = document.getElementById("image").attr("src")
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,113 @@
|
|||||||
|
package eu.kanade.tachiyomi.data.source.online.english
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
|
import eu.kanade.tachiyomi.data.source.EN
|
||||||
|
import eu.kanade.tachiyomi.data.source.Language
|
||||||
|
import eu.kanade.tachiyomi.data.source.base.ParsedOnlineSource
|
||||||
|
import eu.kanade.tachiyomi.data.source.model.Page
|
||||||
|
import org.jsoup.nodes.Document
|
||||||
|
import org.jsoup.nodes.Element
|
||||||
|
import java.text.ParseException
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class Mangahere(context: Context, override val id: Int) : ParsedOnlineSource(context) {
|
||||||
|
|
||||||
|
override val name = "Mangahere"
|
||||||
|
|
||||||
|
override val baseUrl = "http://www.mangahere.co"
|
||||||
|
|
||||||
|
override val lang: Language get() = EN
|
||||||
|
|
||||||
|
override fun popularMangaInitialUrl() = "$baseUrl/directory/"
|
||||||
|
|
||||||
|
override fun popularMangaSelector() = "div.directory_list > ul > li"
|
||||||
|
|
||||||
|
override fun popularMangaFromElement(element: Element, manga: Manga) {
|
||||||
|
element.select("div.title > a").first().let {
|
||||||
|
manga.setUrl(it.attr("href"))
|
||||||
|
manga.title = it.text()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun popularMangaNextPageSelector() = "div.next-page > a.next"
|
||||||
|
|
||||||
|
override fun searchMangaInitialUrl(query: String) =
|
||||||
|
"$baseUrl/search.php?name=$query&page=1&sort=views&order=za"
|
||||||
|
|
||||||
|
override fun searchMangaSelector() = "div.result_search > dl"
|
||||||
|
|
||||||
|
override fun searchMangaFromElement(element: Element, manga: Manga) {
|
||||||
|
element.select("a.manga_info").first().let {
|
||||||
|
manga.setUrl(it.attr("href"))
|
||||||
|
manga.title = it.text()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun searchMangaNextPageSelector() = "div.next-page > a.next"
|
||||||
|
|
||||||
|
override fun mangaDetailsParse(document: Document, manga: Manga) {
|
||||||
|
val detailElement = document.select(".manga_detail_top").first()
|
||||||
|
val infoElement = detailElement.select(".detail_topText").first()
|
||||||
|
|
||||||
|
manga.author = infoElement.select("a[href^=http://www.mangahere.co/author/]").first()?.text()
|
||||||
|
manga.artist = infoElement.select("a[href^=http://www.mangahere.co/artist/]").first()?.text()
|
||||||
|
manga.genre = infoElement.select("li:eq(3)").first()?.text()?.substringAfter("Genre(s):")
|
||||||
|
manga.description = infoElement.select("#show").first()?.text()?.substringBeforeLast("Show less")
|
||||||
|
manga.status = infoElement.select("li:eq(6)").first()?.text().orEmpty().let { parseStatus(it) }
|
||||||
|
manga.thumbnail_url = detailElement.select("img.img").first()?.attr("src")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parseStatus(status: String) = when {
|
||||||
|
status.contains("Ongoing") -> Manga.ONGOING
|
||||||
|
status.contains("Completed") -> Manga.COMPLETED
|
||||||
|
else -> Manga.UNKNOWN
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun chapterListSelector() = ".detail_list > ul:not([class]) > li"
|
||||||
|
|
||||||
|
override fun chapterFromElement(element: Element, chapter: Chapter) {
|
||||||
|
val urlElement = element.select("a").first()
|
||||||
|
|
||||||
|
chapter.setUrl(urlElement.attr("href"))
|
||||||
|
chapter.name = urlElement.text()
|
||||||
|
chapter.date_upload = element.select("span.right").first()?.text()?.let { parseChapterDate(it) } ?: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parseChapterDate(date: String): Long {
|
||||||
|
return if ("Today" in date) {
|
||||||
|
Calendar.getInstance().apply {
|
||||||
|
set(Calendar.HOUR_OF_DAY, 0)
|
||||||
|
set(Calendar.MINUTE, 0)
|
||||||
|
set(Calendar.SECOND, 0)
|
||||||
|
set(Calendar.MILLISECOND, 0)
|
||||||
|
}.timeInMillis
|
||||||
|
} else if ("Yesterday" in date) {
|
||||||
|
Calendar.getInstance().apply {
|
||||||
|
add(Calendar.DATE, -1)
|
||||||
|
set(Calendar.HOUR_OF_DAY, 0)
|
||||||
|
set(Calendar.MINUTE, 0)
|
||||||
|
set(Calendar.SECOND, 0)
|
||||||
|
set(Calendar.MILLISECOND, 0)
|
||||||
|
}.timeInMillis
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH).parse(date).time
|
||||||
|
} catch (e: ParseException) {
|
||||||
|
0L
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun pageListParse(document: Document, pages: MutableList<Page>) {
|
||||||
|
document.select("select.wid60").first().getElementsByTag("option").forEach {
|
||||||
|
pages.add(Page(pages.size, it.attr("value")))
|
||||||
|
}
|
||||||
|
pages.getOrNull(0)?.imageUrl = imageUrlParse(document)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun imageUrlParse(document: Document) = document.getElementById("image").attr("src")
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user