MangaLib: Added scanlator, licensed status, chapters sorting, 18+ content warning (#6477)
* MangaLib: Added scanlator, licensed status, chapters sorting * MangaLib: Added 18+ content warning * MangaLib: Sorting fixes
This commit is contained in:
parent
b2c4ff68ff
commit
277ca48f99
|
@ -5,7 +5,7 @@ ext {
|
||||||
extName = 'MangaLib'
|
extName = 'MangaLib'
|
||||||
pkgNameSuffix = 'ru.libmanga'
|
pkgNameSuffix = 'ru.libmanga'
|
||||||
extClass = '.LibManga'
|
extClass = '.LibManga'
|
||||||
extVersionCode = 34
|
extVersionCode = 35
|
||||||
libVersion = '1.2'
|
libVersion = '1.2'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -152,7 +152,9 @@ class LibManga : ConfigurableSource, HttpSource() {
|
||||||
|
|
||||||
val manga = SManga.create()
|
val manga = SManga.create()
|
||||||
|
|
||||||
if (document.html().contains("Манга удалена по просьбе правообладателей")) {
|
if (document.html().contains("Манга удалена по просьбе правообладателей") ||
|
||||||
|
document.html().contains("Данный тайтл лицензирован на территории РФ.")
|
||||||
|
) {
|
||||||
manga.status = SManga.LICENSED
|
manga.status = SManga.LICENSED
|
||||||
return manga
|
return manga
|
||||||
}
|
}
|
||||||
|
@ -162,7 +164,7 @@ class LibManga : ConfigurableSource, HttpSource() {
|
||||||
|
|
||||||
val category = when {
|
val category = when {
|
||||||
rawCategory == "Комикс западный" -> "комикс"
|
rawCategory == "Комикс западный" -> "комикс"
|
||||||
rawCategory.isNotBlank() -> rawCategory.toLowerCase()
|
rawCategory.isNotBlank() -> rawCategory.toLowerCase(Locale.ROOT)
|
||||||
else -> "манга"
|
else -> "манга"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,7 +175,7 @@ class LibManga : ConfigurableSource, HttpSource() {
|
||||||
manga.status = when (
|
manga.status = when (
|
||||||
body.select("div.media-info-list__title:contains(Статус перевода) + div")
|
body.select("div.media-info-list__title:contains(Статус перевода) + div")
|
||||||
.text()
|
.text()
|
||||||
.toLowerCase()
|
.toLowerCase(Locale.ROOT)
|
||||||
) {
|
) {
|
||||||
"продолжается" -> SManga.ONGOING
|
"продолжается" -> SManga.ONGOING
|
||||||
"завершен" -> SManga.COMPLETED
|
"завершен" -> SManga.COMPLETED
|
||||||
|
@ -195,23 +197,71 @@ class LibManga : ConfigurableSource, HttpSource() {
|
||||||
val data = jsonParser.parse(dataStr).obj
|
val data = jsonParser.parse(dataStr).obj
|
||||||
val chaptersList = data["chapters"]["list"].nullArray
|
val chaptersList = data["chapters"]["list"].nullArray
|
||||||
val slug = data["manga"]["slug"].string
|
val slug = data["manga"]["slug"].string
|
||||||
|
val teams = data["chapters"]["branches"].array.reversed()
|
||||||
|
val sortingList = preferences.getString(SORTING_PREF, "ms_largest")
|
||||||
|
var chapters: List<SChapter>? = null
|
||||||
|
|
||||||
return chaptersList?.map { chapterFromElement(it, slug) } ?: emptyList()
|
if (teams.isNotEmpty() && !sortingList.equals("ms_mixing")) {
|
||||||
|
when (sortingList) {
|
||||||
|
"ms_combining" -> {
|
||||||
|
val tempChaptersList = mutableListOf<SChapter>()
|
||||||
|
for (currentList in teams.withIndex()) {
|
||||||
|
val teamId = teams[currentList.index]["id"].int
|
||||||
|
chapters = chaptersList
|
||||||
|
?.filter { it["branch_id"].int == teamId }
|
||||||
|
?.map { chapterFromElement(it, slug, teamId) }
|
||||||
|
chapters?.let { tempChaptersList.addAll(it) }
|
||||||
|
}
|
||||||
|
chapters = tempChaptersList
|
||||||
|
}
|
||||||
|
"ms_largest" -> {
|
||||||
|
val sizesChaptersLists = mutableListOf<Int>()
|
||||||
|
for (currentList in teams.withIndex()) {
|
||||||
|
val teamId = teams[currentList.index]["id"].int
|
||||||
|
val chapterSize = chaptersList?.filter { it["branch_id"].int == teamId }!!.size
|
||||||
|
sizesChaptersLists.add(chapterSize)
|
||||||
|
}
|
||||||
|
val max = sizesChaptersLists.indexOfFirst { it == sizesChaptersLists.maxOrNull() ?: 0 }
|
||||||
|
val teamId = teams[max]["id"].int
|
||||||
|
chapters = chaptersList?.filter { it["branch_id"].int == teamId }?.map { chapterFromElement(it, slug, teamId) }
|
||||||
|
}
|
||||||
|
"ms_active" -> {
|
||||||
|
for (currentList in teams.withIndex()) {
|
||||||
|
val isActive = teams[currentList.index]["teams"].array
|
||||||
|
for (currentListInternal in isActive.withIndex()) {
|
||||||
|
if (isActive[currentListInternal.index]["is_active"].int == 1) {
|
||||||
|
val teamId = teams[currentList.index]["id"].int
|
||||||
|
chapters = chaptersList?.filter { it["branch_id"].int == teamId }
|
||||||
|
?.map { chapterFromElement(it, slug, teamId) }
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chapters ?: throw Exception("Активный перевод не назначен на сайте")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
chapters = chaptersList?.map { chapterFromElement(it, slug) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun chapterFromElement(chapterItem: JsonElement, slug: String): SChapter {
|
return chapters ?: emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun chapterFromElement(chapterItem: JsonElement, slug: String, teamIdParam: Int? = null): SChapter {
|
||||||
val chapter = SChapter.create()
|
val chapter = SChapter.create()
|
||||||
|
|
||||||
val volume = chapterItem["chapter_volume"].int
|
val volume = chapterItem["chapter_volume"].int
|
||||||
val number = chapterItem["chapter_number"].string
|
val number = chapterItem["chapter_number"].string
|
||||||
|
val teamId = if (teamIdParam != null) "?bid=$teamIdParam" else ""
|
||||||
|
|
||||||
val url = "$baseUrl/$slug/v$volume/c$number"
|
val url = "$baseUrl/$slug/v$volume/c$number$teamId"
|
||||||
|
|
||||||
chapter.setUrlWithoutDomain(url)
|
chapter.setUrlWithoutDomain(url)
|
||||||
|
|
||||||
val nameChapter = chapterItem["chapter_name"].nullString
|
val nameChapter = chapterItem["chapter_name"].nullString
|
||||||
val fullNameChapter = "Том $volume. Глава $number"
|
val fullNameChapter = "Том $volume. Глава $number"
|
||||||
|
|
||||||
|
chapter.scanlator = chapterItem["username"].string
|
||||||
chapter.name = if (nameChapter.isNullOrBlank()) fullNameChapter else "$fullNameChapter - $nameChapter"
|
chapter.name = if (nameChapter.isNullOrBlank()) fullNameChapter else "$fullNameChapter - $nameChapter"
|
||||||
chapter.date_upload = SimpleDateFormat("yyyy-MM-dd", Locale.US)
|
chapter.date_upload = SimpleDateFormat("yyyy-MM-dd", Locale.US)
|
||||||
.parse(chapterItem["chapter_created_at"].string.substringBefore(" "))?.time ?: 0L
|
.parse(chapterItem["chapter_created_at"].string.substringBefore(" "))?.time ?: 0L
|
||||||
|
@ -227,6 +277,10 @@ class LibManga : ConfigurableSource, HttpSource() {
|
||||||
|
|
||||||
override fun pageListParse(response: Response): List<Page> {
|
override fun pageListParse(response: Response): List<Page> {
|
||||||
val document = response.asJsoup()
|
val document = response.asJsoup()
|
||||||
|
|
||||||
|
if (document.html().contains("mangalib.me/register"))
|
||||||
|
throw Exception("Для просмотра 18+ контента необходима авторизация через WebView")
|
||||||
|
|
||||||
val chapInfo = document
|
val chapInfo = document
|
||||||
.select("script:containsData(window.__info)")
|
.select("script:containsData(window.__info)")
|
||||||
.first()
|
.first()
|
||||||
|
@ -583,6 +637,9 @@ class LibManga : ConfigurableSource, HttpSource() {
|
||||||
const val PREFIX_SLUG_SEARCH = "slug:"
|
const val PREFIX_SLUG_SEARCH = "slug:"
|
||||||
private const val SERVER_PREF = "MangaLibImageServer"
|
private const val SERVER_PREF = "MangaLibImageServer"
|
||||||
private const val SERVER_PREF_Title = "Сервер изображений"
|
private const val SERVER_PREF_Title = "Сервер изображений"
|
||||||
|
|
||||||
|
private const val SORTING_PREF = "MangaLibSorting"
|
||||||
|
private const val SORTING_PREF_Title = "Сортировка списков глав"
|
||||||
}
|
}
|
||||||
|
|
||||||
private var server: String? = preferences.getString(SERVER_PREF, null)
|
private var server: String? = preferences.getString(SERVER_PREF, null)
|
||||||
|
@ -601,6 +658,20 @@ class LibManga : ConfigurableSource, HttpSource() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val sortingPref = ListPreference(screen.context).apply {
|
||||||
|
key = SORTING_PREF
|
||||||
|
title = SORTING_PREF_Title
|
||||||
|
entries = arrayOf("Перемешивание списков", "Объединение списков(друг за другом)", "Наибольшее число глав", "Активный перевод")
|
||||||
|
entryValues = arrayOf("ms_mixing", "ms_combining", "ms_largest", "ms_active")
|
||||||
|
summary = "%s"
|
||||||
|
|
||||||
|
setOnPreferenceChangeListener { _, newValue ->
|
||||||
|
val selected = newValue as String
|
||||||
|
preferences.edit().putString(SORTING_PREF, selected).commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
screen.addPreference(sortingPref)
|
||||||
screen.addPreference(serverPref)
|
screen.addPreference(serverPref)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -618,6 +689,20 @@ class LibManga : ConfigurableSource, HttpSource() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val sortingPref = LegacyListPreference(screen.context).apply {
|
||||||
|
key = SORTING_PREF
|
||||||
|
title = SORTING_PREF_Title
|
||||||
|
entries = arrayOf("Перемешивание списков", "Объединение списков(друг за другом)", "Наибольшее число глав", "Активный перевод")
|
||||||
|
entryValues = arrayOf("ms_mixing", "ms_combining", "ms_largest", "ms_active")
|
||||||
|
summary = "%s"
|
||||||
|
|
||||||
|
setOnPreferenceChangeListener { _, newValue ->
|
||||||
|
val selected = newValue as String
|
||||||
|
preferences.edit().putString(SORTING_PREF, selected).commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
screen.addPreference(sortingPref)
|
||||||
screen.addPreference(serverPref)
|
screen.addPreference(serverPref)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue