Misc code cleanup

This commit is contained in:
Eugene
2019-10-27 15:41:40 -04:00
parent 170c382b15
commit 40de8b9723
32 changed files with 777 additions and 691 deletions

View File

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

View File

@ -1,17 +1,27 @@
package eu.kanade.tachiyomi.extension.all.fmreader
// For sites based on the Flat-Manga CMS
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.source.model.*
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.Headers
import okhttp3.HttpUrl
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.*
import java.util.*
import java.util.Calendar
abstract class FMReader (
/**
* For sites based on the Flat-Manga CMS
*/
abstract class FMReader(
override val name: String,
override val baseUrl: String,
override val lang: String
@ -43,10 +53,8 @@ abstract class FMReader (
}
is TextField -> url.addQueryParameter(filter.key, filter.state)
is GenreList -> {
var genre = String()
var ungenre = String()
filter.state.forEach {
if (it.isIncluded()) genre += ",${it.name}"
if (it.isExcluded()) ungenre += ",${it.name}"
@ -79,7 +87,7 @@ abstract class FMReader (
val mangas = mutableListOf<SManga>()
var hasNextPage = true
document.select(popularMangaSelector()).map{ mangas.add(popularMangaFromElement(it)) }
document.select(popularMangaSelector()).map { mangas.add(popularMangaFromElement(it)) }
// check if there's a next page
document.select(popularMangaNextPageSelector()).first().text().split(" ").let {
@ -108,7 +116,7 @@ abstract class FMReader (
manga.setUrlWithoutDomain(it.attr("abs:href"))
manga.title = it.text()
}
manga.thumbnail_url = element.select("img").let{
manga.thumbnail_url = element.select("img").let {
if (it.hasAttr("src")) {
it.attr("abs:src")
} else {
@ -160,11 +168,11 @@ abstract class FMReader (
override fun chapterFromElement(element: Element): SChapter {
val chapter = SChapter.create()
element.select(chapterUrlSelector).first().let{
element.select(chapterUrlSelector).first().let {
chapter.setUrlWithoutDomain(it.attr("abs:href"))
chapter.name = it.text()
}
chapter.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
}
@ -177,7 +185,7 @@ abstract class FMReader (
private fun parseChapterDate(date: String): Long {
val value = date.split(' ')[dateValueIndex].toInt()
val dateWord = date.split(' ')[dateWordIndex].let{
val dateWord = date.split(' ')[dateWordIndex].let {
if (it.contains("(")) {
it.substringBefore("(")
} else {
@ -227,7 +235,7 @@ abstract class FMReader (
val pages = mutableListOf<Page>()
document.select("img.chapter-img").forEachIndexed { i, img ->
pages.add(Page(i, "", img.attr("abs:data-src").let{ if (it.isNotEmpty()) it else img.attr("abs:src") }))
pages.add(Page(i, "", img.attr("abs:data-src").let { if (it.isNotEmpty()) it else img.attr("abs:src") }))
}
return pages
}

View File

@ -5,9 +5,17 @@ import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceFactory
import eu.kanade.tachiyomi.source.model.*
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.util.asJsoup
import okhttp3.*
import okhttp3.FormBody
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import rx.Observable
@ -40,6 +48,7 @@ class FMReaderFactory : SourceFactory {
* most likely the fix is to override popularMangaNextPageSelector() */
class LHTranslation : FMReader("LHTranslation", "https://lhtranslation.net", "en")
class MangaHato : FMReader("MangaHato", "https://mangahato.com", "ja")
class ManhwaScan : FMReader("ManhwaScan", "https://manhwascan.com", "en")
class MangaTiki : FMReader("MangaTiki", "https://mangatiki.com", "ja")
@ -47,16 +56,20 @@ class MangaBone : FMReader("MangaBone", "https://mangabone.com", "en")
class YoloManga : FMReader("Yolo Manga", "https://yolomanga.ca", "es") {
override fun chapterListSelector() = "div#tab-chapper ~ div#tab-chapper table tr"
}
class MangaLeer : FMReader("MangaLeer", "https://mangaleer.com", "es") {
override val dateValueIndex = 1
override val dateWordIndex = 2
}
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()
@ -72,10 +85,12 @@ class AiLoveManga : FMReader("AiLoveManga", "https://ailovemanga.com", "vi") {
return manga
}
}
class ReadComicOnlineOrg : FMReader("ReadComicOnline.org", "https://readcomiconline.org", "en") {
override val client: OkHttpClient = network.cloudflareClient.newBuilder()
.addInterceptor { requestIntercept(it) }
.build()
private fun requestIntercept(chain: Interceptor.Chain): Response {
val request = chain.request()
val response = chain.proceed(request)
@ -85,46 +100,55 @@ class ReadComicOnlineOrg : FMReader("ReadComicOnline.org", "https://readcomiconl
.add("dqh_firewall", "%2F")
.build()
val cookie = mutableListOf<String>()
response.headers("set-cookie").map{ cookie.add(it.substringBefore(" ")) }
response.headers("set-cookie").map { cookie.add(it.substringBefore(" ")) }
headers.newBuilder().add("Cookie", cookie.joinToString { " " }).build()
client.newCall(POST(request.url().toString(), headers, body)).execute()
} else {
response
}
}
override val requestPath = "comic-list.html"
override fun pageListParse(document: Document): List<Page> {
val pages = mutableListOf<Page>()
document.select("div#divImage > select:first-of-type option").forEachIndexed{ i, imgPage ->
document.select("div#divImage > select:first-of-type option").forEachIndexed { i, imgPage ->
pages.add(Page(i, imgPage.attr("value"), ""))
}
return pages.dropLast(1) // last page is a comments page
}
override fun imageUrlRequest(page: Page): Request = GET(baseUrl + page.url, headers)
override fun imageUrlParse(document: Document): String = document.select("img.chapter-img").attr("abs:src").trim()
override fun getGenreList() = getComicsGenreList()
}
class MangaWeek : FMReader("MangaWeek", "https://mangaweek.com", "en")
class HanaScan : FMReader("HanaScan (RawQQ)", "http://rawqq.com", "ja") {
override fun popularMangaNextPageSelector() = "div.col-md-8 button"
}
class RawLH : FMReader("RawLH", "https://lhscan.net", "ja") {
override fun popularMangaNextPageSelector() = "div.col-md-8 button"
}
class Manhwa18 : FMReader("Manhwa18", "https://manhwa18.com", "en") {
override fun getGenreList() = getAdultGenreList()
}
class TruyenTranhLH : FMReader("TruyenTranhLH", "https://truyentranhlh.net", "vi") {
override val requestPath = "danh-sach-truyen.html"
}
class EighteenLHPlus : FMReader("18LHPlus", "https://18lhplus.com", "en") {
override fun getGenreList() = getAdultGenreList()
}
class MangaTR : FMReader("Manga-TR", "https://manga-tr.com", "tr") {
override fun popularMangaNextPageSelector() = "div.btn-group:not(div.btn-block) button.btn-info"
// TODO: genre search possible but a bit of a pain
override fun getFilterList() = FilterList()
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request = GET("$baseUrl/arama.html?icerik=$query", headers)
override fun searchMangaParse(response: Response): MangasPage {
val mangas = mutableListOf<SManga>()
@ -135,6 +159,7 @@ class MangaTR : FMReader("Manga-TR", "https://manga-tr.com", "tr") {
return MangasPage(mangas, false)
}
override fun searchMangaFromElement(element: Element): SManga {
val manga = SManga.create()
@ -143,6 +168,7 @@ class MangaTR : FMReader("Manga-TR", "https://manga-tr.com", "tr") {
return manga
}
override fun mangaDetailsParse(document: Document): SManga {
val manga = SManga.create()
val infoElement = document.select("div#tab1").first()
@ -156,6 +182,7 @@ class MangaTR : FMReader("Manga-TR", "https://manga-tr.com", "tr") {
return manga
}
override fun chapterListSelector() = "tr.table-bordered"
override val chapterUrlSelector = "td[align=left] > a"
override val chapterTimeSelector = "td[align=right]"
@ -172,6 +199,7 @@ class MangaTR : FMReader("Manga-TR", "https://manga-tr.com", "tr") {
Observable.error(Exception("Licensed - No chapters to show"))
}
}
private fun chapterListParse(response: Response, requestUrl: String): List<SChapter> {
val chapters = mutableListOf<SChapter>()
var document = response.asJsoup()
@ -180,7 +208,7 @@ class MangaTR : FMReader("Manga-TR", "https://manga-tr.com", "tr") {
// chapters are paginated
while (moreChapters) {
document.select(chapterListSelector()).map{ chapters.add(chapterFromElement(it)) }
document.select(chapterListSelector()).map { chapters.add(chapterFromElement(it)) }
if (document.select("a[data-page=$nextPage]").isNotEmpty()) {
val body = FormBody.Builder()
.add("page", nextPage.toString())
@ -193,21 +221,25 @@ class MangaTR : FMReader("Manga-TR", "https://manga-tr.com", "tr") {
}
return chapters
}
override fun pageListRequest(chapter: SChapter): Request = GET("$baseUrl/${chapter.url.substringAfter("cek/")}", headers)
override fun pageListParse(document: Document): List<Page> {
val pages = mutableListOf<Page>()
document.select("div.chapter-content select:first-of-type option").forEachIndexed{ i, imgPage ->
document.select("div.chapter-content select:first-of-type option").forEachIndexed { i, imgPage ->
pages.add(Page(i, "$baseUrl/${imgPage.attr("value")}", ""))
}
return pages.dropLast(1) // last page is a comments page
}
override fun imageUrlParse(document: Document): String = document.select("img.chapter-img").attr("abs:src").trim()
}
class Comicastle : FMReader("Comicastle", "https://www.comicastle.org", "en") {
override val requestPath = "comic-dir"
// this source doesn't have the "page x of y" element
override fun popularMangaNextPageSelector() = "li:contains(»)"
override fun popularMangaParse(response: Response) = defaultMangaParse(response)
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request = GET("$baseUrl/comic-dir?q=$query", headers)
override fun searchMangaParse(response: Response): MangasPage = defaultMangaParse(response)
@ -224,39 +256,43 @@ class Comicastle : FMReader("Comicastle", "https://www.comicastle.org", "en") {
return manga
}
override fun chapterListSelector() = "div.col-md-9 table:last-of-type tr"
override fun chapterListParse(response: Response): List<SChapter> = super.chapterListParse(response).reversed()
override fun pageListParse(document: Document): List<Page> {
val pages = mutableListOf<Page>()
document.select("div.text-center select option").forEachIndexed{ i, imgPage ->
document.select("div.text-center select option").forEachIndexed { i, imgPage ->
pages.add(Page(i, imgPage.attr("value"), ""))
}
return pages
}
override fun imageUrlParse(document: Document): String = document.select("img.chapter-img").attr("abs:src").trim()
override fun getGenreList() = getComicsGenreList()
}
class Manhwa18Net : FMReader("Manhwa18.net", "https://manhwa18.net", "en") {
override fun popularMangaRequest(page: Int): Request =
GET("$baseUrl/$requestPath?listType=pagination&page=$page&sort=views&sort_type=DESC&ungenre=raw", headers)
override fun latestUpdatesRequest(page: Int): Request =
GET("$baseUrl/$requestPath?listType=pagination&page=$page&sort=last_update&sort_type=DESC&ungenre=raw", headers)
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val noRawsUrl = super.searchMangaRequest(page, query, filters).url().newBuilder().addQueryParameter("ungenre", "raw").toString()
return GET(noRawsUrl, headers)
}
override fun getGenreList() = getAdultGenreList()
}
class Manhwa18NetRaw : FMReader("Manhwa18.net Raw", "https://manhwa18.net", "ko") {
override val requestPath = "manga-list-genre-raw.html"
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val onlyRawsUrl = super.searchMangaRequest(page, query, filters).url().newBuilder().addQueryParameter("genre", "raw").toString()
return GET(onlyRawsUrl, headers)
}
override fun getFilterList() = FilterList(super.getFilterList().filterNot { it == GenreList(getGenreList()) })
}