Implement Mangafox and Mangahere with the new source
This commit is contained in:
parent
dd5692bb2d
commit
015257fe75
5 changed files with 250 additions and 13 deletions
|
@ -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.online.english.Batoto
|
||||
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 timber.log.Timber
|
||||
import java.io.File
|
||||
|
@ -36,6 +38,8 @@ open class SourceManager(private val context: Context) {
|
|||
private fun createSource(id: Int): Source? = when (id) {
|
||||
BATOTO -> Batoto(context, id)
|
||||
KISSMANGA -> Kissmanga(context, id)
|
||||
MANGAHERE -> Mangahere(context, id)
|
||||
MANGAFOX -> Mangafox(context, id)
|
||||
else -> null
|
||||
}
|
||||
|
||||
|
|
|
@ -202,6 +202,7 @@ class Batoto(context: Context, override val id: Int) : ParsedOnlineSource(contex
|
|||
for ((i, element) in selectElement.select("option").withIndex()) {
|
||||
pages.add(Page(i, element.attr("value")))
|
||||
}
|
||||
pages.getOrNull(0)?.imageUrl = imageUrlParse(document)
|
||||
} else {
|
||||
// For webtoons in one page
|
||||
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 {
|
||||
if (page.page == 1) {
|
||||
page.url = searchMangaInitialUrl(query)
|
||||
|
@ -55,7 +57,7 @@ class Kissmanga(context: Context, override val id: Int) : ParsedOnlineSource(con
|
|||
return post(page.url, headers, form)
|
||||
}
|
||||
|
||||
override fun popularMangaNextPageSelector() = "li > a:contains(› Next)"
|
||||
override fun searchMangaInitialUrl(query: String) = "$baseUrl/AdvanceSearch"
|
||||
|
||||
override fun searchMangaSelector() = popularMangaSelector()
|
||||
|
||||
|
@ -65,26 +67,20 @@ class Kissmanga(context: Context, override val id: Int) : ParsedOnlineSource(con
|
|||
|
||||
override fun searchMangaNextPageSelector() = null
|
||||
|
||||
override fun searchMangaInitialUrl(query: String) = "$baseUrl/AdvanceSearch"
|
||||
|
||||
override fun mangaDetailsParse(document: Document, manga: Manga) {
|
||||
val infoElement = document.select("div.barContent").first()
|
||||
|
||||
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.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")
|
||||
}
|
||||
|
||||
fun parseStatus(status: String?): Int {
|
||||
if (status != null) {
|
||||
when {
|
||||
status.contains("Ongoing") -> return Manga.ONGOING
|
||||
status.contains("Completed") -> return Manga.COMPLETED
|
||||
}
|
||||
}
|
||||
return Manga.UNKNOWN
|
||||
fun parseStatus(status: String) = when {
|
||||
status.contains("Ongoing") -> Manga.ONGOING
|
||||
status.contains("Completed") -> Manga.COMPLETED
|
||||
else -> Manga.UNKNOWN
|
||||
}
|
||||
|
||||
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 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())
|
||||
|
||||
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")
|
||||
|
||||
}
|
Reference in a new issue