NettruyenCO (unoriginal): update domain and use ajax to fetch chapters (#8709)

* Changes domain of NettruyenCO and update chapter parsing logic (using AJAX)

* GET with headers

Co-authored-by: AwkwardPeak7 <48650614+AwkwardPeak7@users.noreply.github.com>

* * Used `kotlinx.serialization` instead of `org.json.JSONObject`
* Used HttpUrl.Builder to encode
* Used `keiyoushi.utils.tryParse`

* * Replaced jsonPrimitive with better logic
* Remove data keyword
* Passed chapter date into constructor

* Update NetTruyenCO.kt

---------

Co-authored-by: AwkwardPeak7 <48650614+AwkwardPeak7@users.noreply.github.com>
This commit is contained in:
minhngoc25a 2025-05-07 22:26:00 +07:00 committed by Draff
parent c06e206cda
commit 2b26d7b3a6
No known key found for this signature in database
GPG Key ID: E8A89F3211677653
2 changed files with 62 additions and 4 deletions

View File

@ -2,8 +2,8 @@ ext {
extName = 'NetTruyenCO (unoriginal)'
extClass = '.NetTruyenCO'
themePkg = 'wpcomics'
baseUrl = 'https://nettruyenrr.com'
overrideVersionCode = 4
baseUrl = 'https://nettruyener.com'
overrideVersionCode = 5
isNsfw = false
}

View File

@ -1,20 +1,78 @@
package eu.kanade.tachiyomi.extension.vi.nettruyenco
import eu.kanade.tachiyomi.multisrc.wpcomics.WPComics
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import keiyoushi.utils.parseAs
import keiyoushi.utils.tryParse
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
import java.text.SimpleDateFormat
import java.util.Locale
class NetTruyenCO : WPComics(
"NetTruyenCO (unoriginal)",
"https://nettruyenrr.com",
"https://nettruyener.com",
"vi",
dateFormat = SimpleDateFormat("dd/MM/yy", Locale.getDefault()),
dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US),
gmtOffset = null,
) {
override val popularPath = "truyen-tranh-hot"
// Override chapters
// Data class mapping for a single chapter entry from the JSON endpoint
@Serializable
private class ChapterDto(
@SerialName("chapter_id") val chapterId: Int,
@SerialName("chapter_name") val chapterName: String,
@SerialName("chapter_slug") val chapterSlug: String,
@SerialName("updated_at") val updatedAt: String,
@SerialName("chapter_num") val chapterNum: Float,
)
// Wrapper for the JSON response, containing a list of chapters
@Serializable
private class ChaptersData(
val data: List<ChapterDto>,
)
// Build and return the request to fetch all chapters in JSON form
override fun chapterListRequest(manga: SManga): Request {
val slugAndId = manga.url.substringAfterLast("/") // e.g. "slug-12345"
val comicId = slugAndId.substringAfterLast("-").toInt() // 12345
val slug = slugAndId.substringBeforeLast("-") // "slug"
val url = baseUrl.toHttpUrl()
.newBuilder()
.addPathSegments("Comic/Services/ComicService.asmx/ChapterList")
.addQueryParameter("slug", slug)
.addQueryParameter("comicId", comicId.toString())
.build()
return GET(url, headers)
}
// Parse the JSON response into a list of SChapter objects
override fun chapterListParse(response: Response): List<SChapter> {
val chaptersDto = response.parseAs<ChaptersData>().data
val slug = response.request.url.queryParameter("slug")!!
return chaptersDto.map { dto ->
SChapter.create().apply {
name = dto.chapterName
setUrlWithoutDomain("/truyen-tranh/$slug/${dto.chapterSlug}/${dto.chapterId}")
date_upload = dateFormat.tryParse(dto.updatedAt)
chapter_number = dto.chapterNum
}
}
}
override fun chapterListSelector(): String = throw UnsupportedOperationException()
// Details
override fun mangaDetailsParse(document: Document): SManga {
return SManga.create().apply {