Initial commit

This commit is contained in:
FourTOne5
2024-01-09 04:12:39 +06:00
commit 600c345dfe
8593 changed files with 150590 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

View File

@@ -0,0 +1,56 @@
package eu.kanade.tachiyomi.extension.tr.epikmanga
import eu.kanade.tachiyomi.multisrc.fmreader.FMReader
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
import rx.Observable
class EpikManga : FMReader("Epik Manga", "https://www.epikmanga.com", "tr") {
override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/seri-listesi?sorting=views&sorting-type=DESC&Sayfa=$page", headers)
override fun latestUpdatesRequest(page: Int): Request = GET("$baseUrl/seri-listesi?sorting=lastUpdate&sorting-type=DESC&Sayfa=$page", headers)
override fun popularMangaNextPageSelector() = "ul.pagination li.active + li:not(.disabled)"
override val headerSelector = "h4 a"
// search wasn't working on source's website
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
return client.newCall(searchMangaRequest(page, query, filters))
.asObservableSuccess()
.map { response ->
searchMangaParse(response, query)
}
}
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request = GET("$baseUrl/seri-listesi?type=text", headers)
private fun searchMangaParse(response: Response, query: String): MangasPage {
val mangas = response.asJsoup().select("div.char.col-lg-4 a").toList()
.filter { it.text().contains(query, ignoreCase = true) }
.map {
SManga.create().apply {
setUrlWithoutDomain(it.attr("href"))
title = it.text()
}
}
return MangasPage(mangas, false)
}
override fun mangaDetailsParse(document: Document): SManga {
val infoElement = document.select("div.col-md-9 div.row").first()!!
return SManga.create().apply {
status = parseStatus(infoElement.select("h4:contains(Durum:)").firstOrNull()?.ownText())
author = infoElement.select("h4:contains(Yazar:)").firstOrNull()?.ownText()
artist = infoElement.select("h4:contains(Çizer:)").firstOrNull()?.ownText()
genre = infoElement.select("h4:contains(Türler:) a").joinToString { it.text() }
thumbnail_url = infoElement.select("img.thumbnail").imgAttr()
description = document.select("div.col-md-12 p").text()
}
}
override fun chapterListSelector() = "table.table tbody tr"
override fun getFilterList(): FilterList = FilterList()
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

View File

@@ -0,0 +1,80 @@
package eu.kanade.tachiyomi.extension.ja.kisslove
import eu.kanade.tachiyomi.multisrc.fmreader.FMReader
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.Request
import org.jsoup.nodes.Element
import java.util.Calendar
class KissLove : FMReader("KissLove", "https://klz9.com", "ja") {
override fun latestUpdatesRequest(page: Int) =
GET("$baseUrl/manga-list.html?page=$page&sort=last_update")
override fun chapterListRequest(manga: SManga): Request {
val mangaId = MID_URL_REGEX.find(manga.url)
?.groupValues?.get(1)
?: throw Exception("Could not find manga id")
val xhrUrl = "$baseUrl/app/manga/controllers/cont.listChapter.php".toHttpUrl().newBuilder()
.addQueryParameter("slug", mangaId)
.build()
return GET(xhrUrl, headers)
}
override fun chapterFromElement(element: Element, mangaTitle: String): SChapter {
return SChapter.create().apply {
element.select(chapterUrlSelector).first()!!.let {
setUrlWithoutDomain("$baseUrl/${it.attr("href")}")
name = it.attr("title")
}
date_upload = element.select(chapterTimeSelector)
.let { if (it.hasText()) parseChapterDate(it.text()) else 0 }
}
}
private fun parseChapterDate(date: String): Long {
val value = date.split(' ')[dateValueIndex].toInt()
val chapterDate = Calendar.getInstance().apply {
set(Calendar.SECOND, 0)
set(Calendar.MILLISECOND, 0)
}
when (date.split(' ')[dateWordIndex]) {
"mins", "minutes" -> chapterDate.add(Calendar.MINUTE, value * -1)
"hours" -> chapterDate.add(Calendar.HOUR_OF_DAY, value * -1)
"days" -> chapterDate.add(Calendar.DATE, value * -1)
"weeks" -> chapterDate.add(Calendar.DATE, value * 7 * -1)
"months" -> chapterDate.add(Calendar.MONTH, value * -1)
"years" -> chapterDate.add(Calendar.YEAR, value * -1)
else -> return 0
}
return chapterDate.timeInMillis
}
override fun pageListRequest(chapter: SChapter): Request {
val request = super.pageListRequest(chapter)
val response = client.newCall(request).execute()
val document = response.asJsoup()
val chapterId = document.selectFirst("#chapter")
?.`val`()
?: throw Exception("Could not find chapter id")
val xhrUrl = "$baseUrl/app/manga/controllers/cont.listImg.php".toHttpUrl().newBuilder()
.addQueryParameter("cid", chapterId)
.build()
return GET(xhrUrl, headers)
}
companion object {
private val MID_URL_REGEX = "-([^.]+).html".toRegex()
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

View File

@@ -0,0 +1,40 @@
package eu.kanade.tachiyomi.extension.ja.manga1000
import eu.kanade.tachiyomi.multisrc.fmreader.FMReader
import eu.kanade.tachiyomi.source.model.SChapter
import org.jsoup.nodes.Element
import java.util.Calendar
class Manga1000 : FMReader("Manga1000", "https://manga1000.top", "ja") {
override fun chapterFromElement(element: Element, mangaTitle: String): SChapter {
return SChapter.create().apply {
element.let {
setUrlWithoutDomain(it.attr("abs:href"))
name = it.attr("title")
}
date_upload = element.select(chapterTimeSelector)
.let { if (it.hasText()) parseChapterDate(it.text()) else 0 }
}
}
private fun parseChapterDate(date: String): Long {
val value = date.split(' ')[dateValueIndex].toInt()
val chapterDate = Calendar.getInstance().apply {
set(Calendar.SECOND, 0)
set(Calendar.MILLISECOND, 0)
}
when (date.split(' ')[dateWordIndex]) {
"mins", "minutes" -> chapterDate.add(Calendar.MINUTE, value * -1)
"hours" -> chapterDate.add(Calendar.HOUR_OF_DAY, value * -1)
"days" -> chapterDate.add(Calendar.DATE, value * -1)
"weeks" -> chapterDate.add(Calendar.DATE, value * 7 * -1)
"months" -> chapterDate.add(Calendar.MONTH, value * -1)
"years" -> chapterDate.add(Calendar.YEAR, value * -1)
else -> return 0
}
return chapterDate.timeInMillis
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

View File

@@ -0,0 +1,104 @@
package eu.kanade.tachiyomi.extension.tr.mangatr
import eu.kanade.tachiyomi.multisrc.fmreader.FMReader
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.FormBody
import okhttp3.Response
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import rx.Observable
class MangaTR : FMReader("Manga-TR", "https://manga-tr.com", "tr") {
override fun headersBuilder() = super.headersBuilder()
.add("Accept-Language", "en-US,en;q=0.5")
override fun popularMangaNextPageSelector() = "div.btn-group:not(div.btn-block) button.btn-info"
// =============================== Search ===============================
// TODO: genre search possible but a bit of a pain
override fun getFilterList() = FilterList()
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) =
GET("$baseUrl/arama.html?icerik=$query", headers)
override fun searchMangaParse(response: Response): MangasPage {
val mangas = response.use { it.asJsoup() }
.select("div.row a[data-toggle]")
.filterNot { it.siblingElements().text().contains("Novel") }
.map(::searchMangaFromElement)
return MangasPage(mangas, false)
}
override fun searchMangaFromElement(element: Element) = SManga.create().apply {
setUrlWithoutDomain(element.absUrl("href"))
title = element.text()
}
// =========================== Manga Details ============================
override fun mangaDetailsParse(document: Document) = SManga.create().apply {
val infoElement = document.selectFirst("div#tab1")!!
infoElement.selectFirst("table + table tr + tr")?.run {
author = selectFirst("td:nth-child(1) a")?.text()
artist = selectFirst("td:nth-child(2) a")?.text()
genre = selectFirst("td:nth-child(3)")?.text()
}
description = infoElement.selectFirst("div.well")?.ownText()?.trim()
thumbnail_url = document.selectFirst("img.thumbnail")?.absUrl("src")
status = infoElement.selectFirst("tr:contains(Çeviri Durumu) + tr > td:nth-child(2)")
.let { parseStatus(it?.text()) }
}
// ============================== Chapters ==============================
override fun chapterListSelector() = "tr.table-bordered"
override val chapterUrlSelector = "td[align=left] > a"
override val chapterTimeSelector = "td[align=right]"
private val chapterListHeaders by lazy {
headersBuilder().add("X-Requested-With", "XMLHttpRequest").build()
}
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> {
val id = manga.url.substringAfter("manga-").substringBefore(".")
val requestUrl = "$baseUrl/cek/fetch_pages_manga.php?manga_cek=$id"
return client.newCall(GET(requestUrl, chapterListHeaders))
.asObservableSuccess()
.map(::chapterListParse)
}
override fun chapterListParse(response: Response): List<SChapter> {
// chapters are paginated
val chapters = buildList {
val requestUrl = response.request.url.toString()
var nextPage = 2
do {
val doc = when {
isEmpty() -> response
else -> {
val body = FormBody.Builder()
.add("page", nextPage.toString())
.build()
nextPage++
client.newCall(POST(requestUrl, chapterListHeaders, body)).execute()
}
}.use { it.asJsoup() }
addAll(doc.select(chapterListSelector()).map(::chapterFromElement))
} while (doc.selectFirst("a[data-page=$nextPage]") != null)
}
return chapters
}
override fun pageListRequest(chapter: SChapter) =
GET("$baseUrl/${chapter.url.substringAfter("cek/")}", headers)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

View File

@@ -0,0 +1,44 @@
package eu.kanade.tachiyomi.extension.ja.rawlh
import eu.kanade.tachiyomi.multisrc.fmreader.FMReader
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SManga
import okhttp3.Request
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
class WeLoveManga : FMReader("WeLoveManga", "https://weloma.art", "ja") {
// Formerly "RawLH"
override val id = 7595224096258102519
override val chapterUrlSelector = ""
override fun pageListParse(document: Document): List<Page> {
fun Element.decoded(): String {
return this.attr("data-src").trimEnd()
}
return document.select(pageListImageSelector).mapIndexed { i, img ->
Page(i, document.location(), img.decoded())
}
}
// Referer needs to be chapter URL
override fun imageRequest(page: Page): Request = GET(page.imageUrl!!, headersBuilder().set("Referer", page.url).build())
override fun popularMangaFromElement(element: Element): SManga = SManga.create().apply {
element.select(headerSelector).let {
setUrlWithoutDomain(it.attr("abs:href"))
title = it.text()
}
thumbnail_url = element
.select("div.content.img-in-ratio")
.first()!!
.attr("style")
.let { BACKGROUND_IMAGE_REGEX.find(it)?.groups?.get(1)?.value }
}
companion object {
val BACKGROUND_IMAGE_REGEX = Regex("""url\(['"]?(.*?)['"]?\)""")
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

View File

@@ -0,0 +1,32 @@
package eu.kanade.tachiyomi.extension.vi.saytruyen
import eu.kanade.tachiyomi.multisrc.fmreader.FMReader
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.Response
import org.jsoup.nodes.Document
class SayTruyen : FMReader("Say Truyen", "https://saytruyenvip.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() }
}

View File

@@ -0,0 +1,80 @@
package eu.kanade.tachiyomi.extension.ja.welovemangaone
import eu.kanade.tachiyomi.multisrc.fmreader.FMReader
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.Request
import org.jsoup.nodes.Element
import java.util.Calendar
class WeLoveMangaOne : FMReader("WeLoveMangaOne", "https://welovemanga.one", "ja") {
override fun latestUpdatesRequest(page: Int) =
GET("$baseUrl/manga-list.html?page=$page&sort=last_update")
override fun chapterListRequest(manga: SManga): Request {
val mangaId = MID_URL_REGEX.find(manga.url)
?.groupValues?.get(1)
?: throw Exception("Could not find manga id")
val xhrUrl = "$baseUrl/app/manga/controllers/cont.Listchapter.php".toHttpUrl().newBuilder()
.addQueryParameter("mid", mangaId)
.build()
return GET(xhrUrl, headers)
}
override fun chapterFromElement(element: Element, mangaTitle: String): SChapter {
return SChapter.create().apply {
element.let {
setUrlWithoutDomain(it.attr("abs:href"))
name = it.attr("title")
}
date_upload = element.select(chapterTimeSelector)
.let { if (it.hasText()) parseChapterDate(it.text()) else 0 }
}
}
private fun parseChapterDate(date: String): Long {
val value = date.split(' ')[dateValueIndex].toInt()
val chapterDate = Calendar.getInstance().apply {
set(Calendar.SECOND, 0)
set(Calendar.MILLISECOND, 0)
}
when (date.split(' ')[dateWordIndex]) {
"mins", "minutes" -> chapterDate.add(Calendar.MINUTE, value * -1)
"hours" -> chapterDate.add(Calendar.HOUR_OF_DAY, value * -1)
"days" -> chapterDate.add(Calendar.DATE, value * -1)
"weeks" -> chapterDate.add(Calendar.DATE, value * 7 * -1)
"months" -> chapterDate.add(Calendar.MONTH, value * -1)
"years" -> chapterDate.add(Calendar.YEAR, value * -1)
else -> return 0
}
return chapterDate.timeInMillis
}
override fun pageListRequest(chapter: SChapter): Request {
val request = super.pageListRequest(chapter)
val response = client.newCall(request).execute()
val document = response.asJsoup()
val chapterId = document.selectFirst("#chapter")
?.`val`()
?: throw Exception("Could not find chapter id")
val xhrUrl = "$baseUrl/app/manga/controllers/cont.listImg.php".toHttpUrl().newBuilder()
.addQueryParameter("cid", chapterId)
.build()
return GET(xhrUrl, headers)
}
companion object {
private val MID_URL_REGEX = "(\\d+)/".toRegex()
}
}