FMReader - add SayTruyen (#2632)
* FMReader - add SayTruyen * Update build.gradle
This commit is contained in:
		
							parent
							
								
									bee6c44417
								
							
						
					
					
						commit
						5de4e42929
					
				@ -5,7 +5,7 @@ ext {
 | 
			
		||||
    appName = 'Tachiyomi: FMReader (multiple aggregators)'
 | 
			
		||||
    pkgNameSuffix = 'all.fmreader'
 | 
			
		||||
    extClass = '.FMReaderFactory'
 | 
			
		||||
    extVersionCode = 7
 | 
			
		||||
    extVersionCode = 8
 | 
			
		||||
    libVersion = '1.2'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -32,7 +32,7 @@ abstract class FMReader(
 | 
			
		||||
    override val client: OkHttpClient = network.cloudflareClient
 | 
			
		||||
 | 
			
		||||
    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)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -65,9 +65,9 @@ abstract class FMReader(
 | 
			
		||||
                    url.addQueryParameter("ungenre", ungenre)
 | 
			
		||||
                }
 | 
			
		||||
                is SortBy -> {
 | 
			
		||||
                    url.addQueryParameter("sort", when {
 | 
			
		||||
                        filter.state?.index == 0 -> "name"
 | 
			
		||||
                        filter.state?.index == 1 -> "views"
 | 
			
		||||
                    url.addQueryParameter("sort", when (filter.state?.index) {
 | 
			
		||||
                        0 -> "name"
 | 
			
		||||
                        1 -> "views"
 | 
			
		||||
                        else -> "last_update"
 | 
			
		||||
                    })
 | 
			
		||||
                    if (filter.state?.ascending == true)
 | 
			
		||||
@ -109,21 +109,15 @@ abstract class FMReader(
 | 
			
		||||
    override fun searchMangaSelector() = popularMangaSelector()
 | 
			
		||||
 | 
			
		||||
    override fun popularMangaFromElement(element: Element): SManga {
 | 
			
		||||
        val manga = SManga.create()
 | 
			
		||||
 | 
			
		||||
        element.select("h3 a").let {
 | 
			
		||||
            manga.setUrlWithoutDomain(it.attr("abs:href"))
 | 
			
		||||
            manga.title = it.text()
 | 
			
		||||
        }
 | 
			
		||||
        manga.thumbnail_url = element.select("img").let {
 | 
			
		||||
            if (it.hasAttr("src")) {
 | 
			
		||||
                it.attr("abs:src")
 | 
			
		||||
            } else {
 | 
			
		||||
                it.attr("abs:data-original")
 | 
			
		||||
        return SManga.create().apply {
 | 
			
		||||
            element.select("h3 a").let {
 | 
			
		||||
                setUrlWithoutDomain(it.attr("abs:href"))
 | 
			
		||||
                title = it.text()
 | 
			
		||||
            }
 | 
			
		||||
            thumbnail_url = element.select("img").let {
 | 
			
		||||
                if (it.hasAttr("src")) it.attr("abs:src") else it.attr("abs:data-original")
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return manga
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun latestUpdatesFromElement(element: Element): SManga = popularMangaFromElement(element)
 | 
			
		||||
@ -142,23 +136,27 @@ abstract class FMReader(
 | 
			
		||||
    override fun searchMangaNextPageSelector() = popularMangaNextPageSelector()
 | 
			
		||||
 | 
			
		||||
    override fun mangaDetailsParse(document: Document): SManga {
 | 
			
		||||
        val manga = SManga.create()
 | 
			
		||||
        val infoElement = document.select("div.row").first()
 | 
			
		||||
 | 
			
		||||
        manga.author = infoElement.select("li a.btn-info").text()
 | 
			
		||||
        manga.genre = infoElement.select("li a.btn-danger").joinToString { it.text() }
 | 
			
		||||
        manga.status = parseStatus(infoElement.select("li a.btn-success").first().text())
 | 
			
		||||
        manga.description = document.select("div.row ~ div.row p").text().trim()
 | 
			
		||||
        manga.thumbnail_url = infoElement.select("img.thumbnail").attr("abs:src")
 | 
			
		||||
 | 
			
		||||
        return manga
 | 
			
		||||
        return SManga.create().apply {
 | 
			
		||||
            author = infoElement.select("li a.btn-info").text()
 | 
			
		||||
            genre = infoElement.select("li a.btn-danger").joinToString { it.text() }
 | 
			
		||||
            status = parseStatus(infoElement.select("li a.btn-success").first()?.text())
 | 
			
		||||
            description = document.select("div.row ~ div.row p").text().trim()
 | 
			
		||||
            thumbnail_url = infoElement.select("img.thumbnail").attr("abs:src")
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // languages: en, vi, tr
 | 
			
		||||
    fun parseStatus(status: String): Int = when (status.toLowerCase()) {
 | 
			
		||||
        "completed", "complete", "incomplete", "đã hoàn thành", "tamamlandı" -> SManga.COMPLETED
 | 
			
		||||
        "ongoing", "on going", "updating", "chưa hoàn thành", "đang cập nhật", "devam ediyor" -> SManga.ONGOING
 | 
			
		||||
        else -> SManga.UNKNOWN
 | 
			
		||||
    fun parseStatus(status: String?): Int {
 | 
			
		||||
        val completedWords = setOf("completed", "complete", "incomplete", "đã hoàn thành", "tamamlandı", "hoàn thành")
 | 
			
		||||
        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
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun chapterListSelector() = "div#list-chapters p, table.table tr"
 | 
			
		||||
@ -168,15 +166,13 @@ abstract class FMReader(
 | 
			
		||||
    open val chapterTimeSelector = "time"
 | 
			
		||||
 | 
			
		||||
    override fun chapterFromElement(element: Element): SChapter {
 | 
			
		||||
        val chapter = SChapter.create()
 | 
			
		||||
 | 
			
		||||
        element.select(chapterUrlSelector).first().let {
 | 
			
		||||
            chapter.setUrlWithoutDomain(it.attr("abs:href"))
 | 
			
		||||
            chapter.name = it.text()
 | 
			
		||||
        return SChapter.create().apply {
 | 
			
		||||
            element.select(chapterUrlSelector).first().let {
 | 
			
		||||
                setUrlWithoutDomain(it.attr("abs:href"))
 | 
			
		||||
                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"
 | 
			
		||||
 | 
			
		||||
@ -30,7 +30,6 @@ class FMReaderFactory : SourceFactory {
 | 
			
		||||
        MangaTiki(),
 | 
			
		||||
        MangaBone(),
 | 
			
		||||
        YoloManga(),
 | 
			
		||||
        AiLoveManga(),
 | 
			
		||||
        ReadComicOnlineOrg(),
 | 
			
		||||
        HanaScan(),
 | 
			
		||||
        RawLH(),
 | 
			
		||||
@ -41,7 +40,8 @@ class FMReaderFactory : SourceFactory {
 | 
			
		||||
        Comicastle(),
 | 
			
		||||
        Manhwa18Net(),
 | 
			
		||||
        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"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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") {
 | 
			
		||||
    override val client: OkHttpClient = network.cloudflareClient.newBuilder()
 | 
			
		||||
        .addInterceptor { requestIntercept(it) }
 | 
			
		||||
@ -337,3 +313,24 @@ class MangaBorn : FMReader("MangaBorn", "https://hellxlight.com", "en") {
 | 
			
		||||
    override val pageListImageSelector = "div.panel-read-story img"
 | 
			
		||||
    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() }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user