FMReader - add SayTruyen (#2632)

* FMReader - add SayTruyen

* Update build.gradle
This commit is contained in:
Mike 2020-04-10 09:30:26 -04:00 committed by GitHub
parent bee6c44417
commit 5de4e42929
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 64 deletions

View File

@ -5,7 +5,7 @@ ext {
appName = 'Tachiyomi: FMReader (multiple aggregators)' appName = 'Tachiyomi: FMReader (multiple aggregators)'
pkgNameSuffix = 'all.fmreader' pkgNameSuffix = 'all.fmreader'
extClass = '.FMReaderFactory' extClass = '.FMReaderFactory'
extVersionCode = 7 extVersionCode = 8
libVersion = '1.2' libVersion = '1.2'
} }

View File

@ -32,7 +32,7 @@ abstract class FMReader(
override val client: OkHttpClient = network.cloudflareClient override val client: OkHttpClient = network.cloudflareClient
override fun headersBuilder() = Headers.Builder().apply { override fun headersBuilder() = Headers.Builder().apply {
add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64) Gecko/20100101 Firefox/69.0") add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64) Gecko/20100101 Firefox/75.0")
add("Referer", baseUrl) add("Referer", baseUrl)
} }
@ -65,9 +65,9 @@ abstract class FMReader(
url.addQueryParameter("ungenre", ungenre) url.addQueryParameter("ungenre", ungenre)
} }
is SortBy -> { is SortBy -> {
url.addQueryParameter("sort", when { url.addQueryParameter("sort", when (filter.state?.index) {
filter.state?.index == 0 -> "name" 0 -> "name"
filter.state?.index == 1 -> "views" 1 -> "views"
else -> "last_update" else -> "last_update"
}) })
if (filter.state?.ascending == true) if (filter.state?.ascending == true)
@ -109,21 +109,15 @@ abstract class FMReader(
override fun searchMangaSelector() = popularMangaSelector() override fun searchMangaSelector() = popularMangaSelector()
override fun popularMangaFromElement(element: Element): SManga { override fun popularMangaFromElement(element: Element): SManga {
val manga = SManga.create() return SManga.create().apply {
element.select("h3 a").let { element.select("h3 a").let {
manga.setUrlWithoutDomain(it.attr("abs:href")) setUrlWithoutDomain(it.attr("abs:href"))
manga.title = it.text() title = it.text()
} }
manga.thumbnail_url = element.select("img").let { thumbnail_url = element.select("img").let {
if (it.hasAttr("src")) { if (it.hasAttr("src")) it.attr("abs:src") else it.attr("abs:data-original")
it.attr("abs:src")
} else {
it.attr("abs:data-original")
} }
} }
return manga
} }
override fun latestUpdatesFromElement(element: Element): SManga = popularMangaFromElement(element) override fun latestUpdatesFromElement(element: Element): SManga = popularMangaFromElement(element)
@ -142,24 +136,28 @@ abstract class FMReader(
override fun searchMangaNextPageSelector() = popularMangaNextPageSelector() override fun searchMangaNextPageSelector() = popularMangaNextPageSelector()
override fun mangaDetailsParse(document: Document): SManga { override fun mangaDetailsParse(document: Document): SManga {
val manga = SManga.create()
val infoElement = document.select("div.row").first() val infoElement = document.select("div.row").first()
manga.author = infoElement.select("li a.btn-info").text() return SManga.create().apply {
manga.genre = infoElement.select("li a.btn-danger").joinToString { it.text() } author = infoElement.select("li a.btn-info").text()
manga.status = parseStatus(infoElement.select("li a.btn-success").first().text()) genre = infoElement.select("li a.btn-danger").joinToString { it.text() }
manga.description = document.select("div.row ~ div.row p").text().trim() status = parseStatus(infoElement.select("li a.btn-success").first()?.text())
manga.thumbnail_url = infoElement.select("img.thumbnail").attr("abs:src") description = document.select("div.row ~ div.row p").text().trim()
thumbnail_url = infoElement.select("img.thumbnail").attr("abs:src")
return manga }
} }
// languages: en, vi, tr // languages: en, vi, tr
fun parseStatus(status: String): Int = when (status.toLowerCase()) { fun parseStatus(status: String?): Int {
"completed", "complete", "incomplete", "đã hoàn thành", "tamamlandı" -> SManga.COMPLETED val completedWords = setOf("completed", "complete", "incomplete", "đã hoàn thành", "tamamlandı", "hoàn thành")
"ongoing", "on going", "updating", "chưa hoàn thành", "đang cập nhật", "devam ediyor" -> SManga.ONGOING val ongoingWords = setOf("ongoing", "on going", "updating", "chưa hoàn thành", "đang cập nhật", "devam ediyor", "Đang tiến hành")
return when {
status == null -> SManga.UNKNOWN
completedWords.any { it.equals(status, ignoreCase = true) } -> SManga.COMPLETED
ongoingWords.any { it.equals(status, ignoreCase = true) } -> SManga.ONGOING
else -> SManga.UNKNOWN else -> SManga.UNKNOWN
} }
}
override fun chapterListSelector() = "div#list-chapters p, table.table tr" override fun chapterListSelector() = "div#list-chapters p, table.table tr"
@ -168,15 +166,13 @@ abstract class FMReader(
open val chapterTimeSelector = "time" open val chapterTimeSelector = "time"
override fun chapterFromElement(element: Element): SChapter { override fun chapterFromElement(element: Element): SChapter {
val chapter = SChapter.create() return SChapter.create().apply {
element.select(chapterUrlSelector).first().let { element.select(chapterUrlSelector).first().let {
chapter.setUrlWithoutDomain(it.attr("abs:href")) setUrlWithoutDomain(it.attr("abs:href"))
chapter.name = it.text() name = it.text()
}
date_upload = element.select(chapterTimeSelector).let { if (it.hasText()) parseChapterDate(it.text()) else 0 }
} }
chapter.date_upload = element.select(chapterTimeSelector).let { if (it.hasText()) parseChapterDate(it.text()) else 0 }
return chapter
} }
// gets the number from "1 day ago" // gets the number from "1 day ago"

View File

@ -30,7 +30,6 @@ class FMReaderFactory : SourceFactory {
MangaTiki(), MangaTiki(),
MangaBone(), MangaBone(),
YoloManga(), YoloManga(),
AiLoveManga(),
ReadComicOnlineOrg(), ReadComicOnlineOrg(),
HanaScan(), HanaScan(),
RawLH(), RawLH(),
@ -41,7 +40,8 @@ class FMReaderFactory : SourceFactory {
Comicastle(), Comicastle(),
Manhwa18Net(), Manhwa18Net(),
Manhwa18NetRaw(), Manhwa18NetRaw(),
MangaBorn() MangaBorn(),
SayTruyen()
) )
} }
@ -58,30 +58,6 @@ class YoloManga : FMReader("Yolo Manga", "https://yolomanga.ca", "es") {
override fun chapterListSelector() = "div#tab-chapper ~ div#tab-chapper table tr" override fun chapterListSelector() = "div#tab-chapper ~ div#tab-chapper table tr"
} }
class AiLoveManga : FMReader("AiLoveManga", "https://ailovemanga.com", "vi") {
override val requestPath = "danh-sach-truyen.html"
// TODO: could add a genre search (different URL paths for genres)
override fun getFilterList() = FilterList()
// I don't know why, but I have to override searchMangaRequest to make it work for this source
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = GET("$baseUrl/$requestPath?name=$query&page=$page")
override fun chapterListSelector() = "div#tab-chapper table tr"
override fun mangaDetailsParse(document: Document): SManga {
val manga = SManga.create()
val infoElement = document.select("div.container:has(img)").first()
manga.author = infoElement.select("a.btn-info").first().text()
manga.artist = infoElement.select("a.btn-info + a").text()
manga.genre = infoElement.select("a.btn-danger").joinToString { it.text() }
manga.status = parseStatus(infoElement.select("a.btn-success").text())
manga.description = document.select("div.col-sm-8 p").text().trim()
manga.thumbnail_url = infoElement.select("img").attr("abs:src")
return manga
}
}
class ReadComicOnlineOrg : FMReader("ReadComicOnline.org", "https://readcomiconline.org", "en") { class ReadComicOnlineOrg : FMReader("ReadComicOnline.org", "https://readcomiconline.org", "en") {
override val client: OkHttpClient = network.cloudflareClient.newBuilder() override val client: OkHttpClient = network.cloudflareClient.newBuilder()
.addInterceptor { requestIntercept(it) } .addInterceptor { requestIntercept(it) }
@ -337,3 +313,24 @@ class MangaBorn : FMReader("MangaBorn", "https://hellxlight.com", "en") {
override val pageListImageSelector = "div.panel-read-story img" override val pageListImageSelector = "div.panel-read-story img"
override fun getFilterList() = FilterList() override fun getFilterList() = FilterList()
} }
class SayTruyen : FMReader("Say Truyen", "https://saytruyen.com", "vi") {
override fun mangaDetailsParse(document: Document): SManga {
val info = document.select("div.row").first()
return SManga.create().apply {
author = info.select("div.row li:has(b:contains(Tác giả)) small").text()
genre = info.select("div.row li:has(b:contains(Thể loại)) small a").joinToString { it.text() }
status = parseStatus(info.select("div.row li:has(b:contains(Tình trạng)) a").text())
description = document.select("div.description").text()
thumbnail_url = info.select("img.thumbnail").attr("abs:src")
}
}
override fun chapterListParse(response: Response): List<SChapter> {
return response.asJsoup().let { document ->
document.select(chapterListSelector()).map { chapterFromElement(it).apply {
scanlator = document.select("div.row li:has(b:contains(Nhóm dịch)) small").text()
} }
}
}
override fun pageListParse(document: Document): List<Page> = super.pageListParse(document).onEach { it.imageUrl!!.trim() }
}