mirror of
https://github.com/keiyoushi/extensions-source.git
synced 2024-11-25 11:42:47 +01:00
Rewrite LibGroup to use new api (#3219)
* Rewrote LibGroup to use api instead of parsing document * apply suggestions * quick fixes * change preferences variable to functions * Make getToken sync * safe & load token * return new token when refreshing
This commit is contained in:
parent
95c1fe5c1f
commit
91ef9b6571
@ -15,9 +15,9 @@
|
||||
|
||||
<!-- LibUrlActivity sites can be added here. -->
|
||||
<data
|
||||
android:host="v1.hentailib.org"
|
||||
android:pathPattern="/..*/v..*"
|
||||
android:scheme="https" />
|
||||
android:host="${SOURCEHOST}"
|
||||
android:pathPattern="/ru/manga/..*"
|
||||
android:scheme="${SOURCESCHEME}" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
@ -2,4 +2,4 @@ plugins {
|
||||
id("lib-multisrc")
|
||||
}
|
||||
|
||||
baseVersionCode = 25
|
||||
baseVersionCode = 26
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,285 @@
|
||||
package eu.kanade.tachiyomi.multisrc.libgroup
|
||||
|
||||
import eu.kanade.tachiyomi.source.model.Page
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
class Data<T>(
|
||||
val data: T,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
class Constants(
|
||||
@SerialName("ageRestriction") val ageRestrictions: List<IdLabelSiteType>,
|
||||
@SerialName("format") val formats: List<IdNameSiteType>,
|
||||
val genres: List<IdNameSiteType>,
|
||||
val imageServers: List<ImageServer>,
|
||||
@SerialName("scanlateStatus") val scanlateStatuses: List<IdLabelSiteType>,
|
||||
@SerialName("status") val titleStatuses: List<IdLabelSiteType>,
|
||||
val tags: List<IdNameSiteType>,
|
||||
val types: List<IdLabelSiteType>,
|
||||
) {
|
||||
@Serializable
|
||||
class IdLabelSiteType(
|
||||
val id: Int,
|
||||
val label: String,
|
||||
@SerialName("site_ids") val siteIds: List<Int>,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
class IdNameSiteType(
|
||||
val id: Int,
|
||||
val name: String,
|
||||
@SerialName("site_ids") val siteIds: List<Int>,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
class ImageServer(
|
||||
val id: String,
|
||||
val label: String,
|
||||
val url: String,
|
||||
@SerialName("site_ids") val siteIds: List<Int>,
|
||||
)
|
||||
|
||||
fun getServer(isServers: String?, siteId: Int): ImageServer =
|
||||
if (!isServers.isNullOrBlank()) {
|
||||
imageServers.first { it.id == isServers && it.siteIds.contains(siteId) }
|
||||
} else {
|
||||
imageServers.first { it.siteIds.contains(siteId) }
|
||||
}
|
||||
|
||||
fun getCategories(siteId: Int): List<IdLabelSiteType> = types.filter { it.siteIds.contains(siteId) }
|
||||
fun getFormats(siteId: Int): List<IdNameSiteType> = formats.filter { it.siteIds.contains(siteId) }
|
||||
fun getGenres(siteId: Int): List<IdNameSiteType> = genres.filter { it.siteIds.contains(siteId) }
|
||||
fun getTags(siteId: Int): List<IdNameSiteType> = tags.filter { it.siteIds.contains(siteId) }
|
||||
fun getScanlateStatuses(siteId: Int): List<IdLabelSiteType> = scanlateStatuses.filter { it.siteIds.contains(siteId) }
|
||||
fun getTitleStatuses(siteId: Int): List<IdLabelSiteType> = titleStatuses.filter { it.siteIds.contains(siteId) }
|
||||
fun getAgeRestrictions(siteId: Int): List<IdLabelSiteType> = ageRestrictions.filter { it.siteIds.contains(siteId) }
|
||||
}
|
||||
|
||||
@Serializable
|
||||
class MangasPageDto(
|
||||
val data: List<MangaShort>,
|
||||
val meta: MangaPageMeta,
|
||||
) {
|
||||
@Serializable
|
||||
class MangaPageMeta(
|
||||
@SerialName("has_next_page") val hasNextPage: Boolean,
|
||||
)
|
||||
|
||||
fun mapToSManga(isEng: String): List<SManga> {
|
||||
return this.data.map { it.toSManga(isEng) }
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
class MangaShort(
|
||||
val name: String,
|
||||
@SerialName("rus_name") val rusName: String?,
|
||||
@SerialName("eng_name") val engName: String?,
|
||||
@SerialName("slug_url") val slugUrl: String,
|
||||
val cover: Cover,
|
||||
) {
|
||||
@Serializable
|
||||
data class Cover(
|
||||
val default: String?,
|
||||
)
|
||||
|
||||
fun toSManga(isEng: String) = SManga.create().apply {
|
||||
title = getSelectedLanguage(isEng, rusName, engName, name)
|
||||
thumbnail_url = cover.default.orEmpty()
|
||||
url = "/$slugUrl"
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
class Manga(
|
||||
val type: LabelType,
|
||||
val ageRestriction: LabelType,
|
||||
val rating: Rating,
|
||||
val genres: List<NameType>,
|
||||
val tags: List<NameType>,
|
||||
@SerialName("rus_name") val rusName: String?,
|
||||
@SerialName("eng_name") val engName: String?,
|
||||
val name: String,
|
||||
val cover: MangaShort.Cover,
|
||||
val authors: List<NameType>,
|
||||
val artists: List<NameType>,
|
||||
val status: LabelType,
|
||||
val scanlateStatus: LabelType,
|
||||
@SerialName("is_licensed") val isLicensed: Boolean,
|
||||
val otherNames: List<String>,
|
||||
val summary: String,
|
||||
) {
|
||||
@Serializable
|
||||
class LabelType(
|
||||
val label: String,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
class NameType(
|
||||
val name: String,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
class Rating(
|
||||
val average: Float,
|
||||
val votes: Int,
|
||||
)
|
||||
|
||||
fun toSManga(isEng: String): SManga = SManga.create().apply {
|
||||
title = getSelectedLanguage(isEng, rusName, engName, name)
|
||||
thumbnail_url = cover.default
|
||||
author = authors.joinToString { it.name }
|
||||
artist = artists.joinToString { it.name }
|
||||
status = parseStatus(isLicensed, scanlateStatus.label, this@Manga.status.label)
|
||||
genre = type.label.ifBlank { "Манга" } + ", " + ageRestriction.label + ", " +
|
||||
genres.joinToString { it.name.trim() } + ", " + tags.joinToString { it.name.trim() }
|
||||
description = getOppositeLanguage(isEng, rusName, engName) + rating.average.parseAverage() + " " + rating.average +
|
||||
" (голосов: " + rating.votes + ")\n" + otherNames.joinAltNames() + summary
|
||||
}
|
||||
|
||||
private fun Float.parseAverage(): String {
|
||||
return when {
|
||||
this > 9.5 -> "★★★★★"
|
||||
this > 8.5 -> "★★★★✬"
|
||||
this > 7.5 -> "★★★★☆"
|
||||
this > 6.5 -> "★★★✬☆"
|
||||
this > 5.5 -> "★★★☆☆"
|
||||
this > 4.5 -> "★★✬☆☆"
|
||||
this > 3.5 -> "★★☆☆☆"
|
||||
this > 2.5 -> "★✬☆☆☆"
|
||||
this > 1.5 -> "★☆☆☆☆"
|
||||
this > 0.5 -> "✬☆☆☆☆"
|
||||
else -> "☆☆☆☆☆"
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseStatus(isLicensed: Boolean, statusTranslate: String, statusTitle: String): Int = when {
|
||||
isLicensed -> SManga.LICENSED
|
||||
statusTranslate == "Завершён" && statusTitle == "Приостановлен" || statusTranslate == "Заморожен" || statusTranslate == "Заброшен" -> SManga.ON_HIATUS
|
||||
statusTranslate == "Завершён" && statusTitle == "Выпуск прекращён" -> SManga.CANCELLED
|
||||
statusTranslate == "Продолжается" -> SManga.ONGOING
|
||||
statusTranslate == "Выходит" -> SManga.ONGOING
|
||||
statusTranslate == "Завершён" -> SManga.COMPLETED
|
||||
statusTranslate == "Вышло" -> SManga.PUBLISHING_FINISHED
|
||||
else -> when (statusTitle) {
|
||||
"Онгоинг" -> SManga.ONGOING
|
||||
"Анонс" -> SManga.ONGOING
|
||||
"Завершён" -> SManga.COMPLETED
|
||||
"Приостановлен" -> SManga.ON_HIATUS
|
||||
"Выпуск прекращён" -> SManga.CANCELLED
|
||||
else -> SManga.UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
private fun List<String>.joinAltNames(): String = when {
|
||||
this.isNotEmpty() -> "Альтернативные названия:\n" + this.joinToString(" / ") + "\n\n"
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSelectedLanguage(isEng: String, rusName: String?, engName: String?, name: String): String = when {
|
||||
isEng == "rus" && rusName.orEmpty().isNotEmpty() -> rusName!!
|
||||
isEng == "eng" && engName.orEmpty().isNotEmpty() -> engName!!
|
||||
else -> name
|
||||
}
|
||||
|
||||
private fun getOppositeLanguage(isEng: String, rusName: String?, engName: String?): String = when {
|
||||
isEng == "eng" && rusName.orEmpty().isNotEmpty() -> rusName + "\n"
|
||||
isEng == "rus" && engName.orEmpty().isNotEmpty() -> engName + "\n"
|
||||
else -> ""
|
||||
}
|
||||
|
||||
@Serializable
|
||||
class Chapter(
|
||||
val id: Int,
|
||||
@SerialName("branches_count") val branchesCount: Int,
|
||||
val branches: List<Branch>,
|
||||
val name: String?,
|
||||
val number: String,
|
||||
val volume: String,
|
||||
@SerialName("item_number") val itemNumber: Float?,
|
||||
) {
|
||||
@Serializable
|
||||
class Branch(
|
||||
@SerialName("branch_id") val branchId: Int?,
|
||||
@SerialName("created_at") val createdAt: String,
|
||||
val teams: List<Team>,
|
||||
val user: User,
|
||||
) {
|
||||
@Serializable
|
||||
class Team(
|
||||
val name: String,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
class User(
|
||||
val username: String,
|
||||
)
|
||||
}
|
||||
|
||||
private fun first(branchId: Int? = null): Branch? {
|
||||
return runCatching { if (branchId != null) branches.first { it.branchId == branchId } else branches.first() }.getOrNull()
|
||||
}
|
||||
|
||||
private fun getTeamName(branchId: Int? = null): String? {
|
||||
return runCatching { first(branchId)!!.teams.first().name }.getOrNull()
|
||||
}
|
||||
|
||||
private fun getUserName(branchId: Int? = null): String? {
|
||||
return runCatching { first(branchId)!!.user.username }.getOrNull()
|
||||
}
|
||||
|
||||
fun toSChapter(slugUrl: String, branchId: Int? = null, isScanUser: Boolean): SChapter = SChapter.create().apply {
|
||||
val chapterName = "Том $volume. Глава $number"
|
||||
name = if (this@Chapter.name.isNullOrBlank()) chapterName else "$chapterName - ${this@Chapter.name}"
|
||||
val branchStr = if (branchId != null) "&branch_id=$branchId" else ""
|
||||
url = "/$slugUrl/chapter?$branchStr&volume=$volume&number=$number"
|
||||
scanlator = getTeamName(branchId) ?: if (isScanUser) getUserName(branchId) else null
|
||||
date_upload = runCatching { LibGroup.simpleDateFormat.parse(first(branchId)!!.createdAt)!!.time }.getOrDefault(0L)
|
||||
chapter_number = itemNumber ?: -1f
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
class Branch(
|
||||
val id: Int,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
class Pages(
|
||||
val pages: List<MangaPage>,
|
||||
) {
|
||||
@Serializable
|
||||
class MangaPage(
|
||||
val slug: Int,
|
||||
val url: String,
|
||||
)
|
||||
|
||||
fun toPageList(): List<Page> = pages.map { Page(it.slug, it.url) }
|
||||
}
|
||||
|
||||
@Serializable
|
||||
class AuthToken(
|
||||
private val token: Token,
|
||||
) {
|
||||
@Serializable
|
||||
class Token(
|
||||
val timestamp: Long,
|
||||
@SerialName("expires_in") val expiresIn: Long,
|
||||
@SerialName("token_type") val tokenType: String,
|
||||
@SerialName("access_token") val accessToken: String,
|
||||
)
|
||||
|
||||
fun isExpired(): Boolean {
|
||||
val currentTime = System.currentTimeMillis()
|
||||
val expiresIn = token.timestamp + (token.expiresIn * 1000)
|
||||
return expiresIn < currentTime
|
||||
}
|
||||
|
||||
fun getToken(): String = "${token.tokenType} ${token.accessToken}"
|
||||
}
|
@ -19,7 +19,7 @@ class LibUrlActivity : Activity() {
|
||||
super.onCreate(savedInstanceState)
|
||||
val pathSegments = intent?.data?.pathSegments
|
||||
if (pathSegments != null && pathSegments.size > 0) {
|
||||
val titleid = pathSegments[0]
|
||||
val titleid = pathSegments[2]
|
||||
val mainIntent = Intent().apply {
|
||||
action = "eu.kanade.tachiyomi.SEARCH"
|
||||
putExtra("query", "${LibGroup.PREFIX_SLUG_SEARCH}$titleid")
|
||||
|
@ -5,17 +5,12 @@ import android.content.SharedPreferences
|
||||
import android.widget.Toast
|
||||
import androidx.preference.EditTextPreference
|
||||
import eu.kanade.tachiyomi.multisrc.libgroup.LibGroup
|
||||
import eu.kanade.tachiyomi.network.POST
|
||||
import eu.kanade.tachiyomi.source.model.Filter
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
import okhttp3.Request
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
class HentaiLib : LibGroup("HentaiLib", "https://hentailib.me", "ru") {
|
||||
|
||||
override val id: Long = 6425650164840473547
|
||||
|
||||
private val preferences: SharedPreferences by lazy {
|
||||
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
|
||||
}
|
||||
@ -23,209 +18,17 @@ class HentaiLib : LibGroup("HentaiLib", "https://hentailib.me", "ru") {
|
||||
private var domain: String = preferences.getString(DOMAIN_TITLE, DOMAIN_DEFAULT)!!
|
||||
override val baseUrl: String = domain
|
||||
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||
if (csrfToken.isEmpty()) {
|
||||
val tokenResponse = client.newCall(popularMangaRequest(page)).execute()
|
||||
val resBody = tokenResponse.body.string()
|
||||
csrfToken = "_token\" content=\"(.*)\"".toRegex().find(resBody)!!.groups[1]!!.value
|
||||
}
|
||||
val url = super.searchMangaRequest(page, query, filters).url.newBuilder()
|
||||
(if (filters.isEmpty()) getFilterList() else filters).forEach { filter ->
|
||||
when (filter) {
|
||||
is TagList -> filter.state.forEach { tag ->
|
||||
if (tag.state != Filter.TriState.STATE_IGNORE) {
|
||||
url.addQueryParameter(
|
||||
if (tag.isIncluded()) "tags[include][]" else "tags[exclude][]",
|
||||
tag.id,
|
||||
)
|
||||
}
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
return POST(url.toString(), catalogHeaders())
|
||||
}
|
||||
override val siteId: Int = 4 // Important in api calls
|
||||
|
||||
// Filters
|
||||
private class SearchFilter(name: String, val id: String) : Filter.TriState(name)
|
||||
|
||||
private class TagList(tags: List<SearchFilter>) : Filter.Group<SearchFilter>("Теги", tags)
|
||||
|
||||
override fun getFilterList(): FilterList {
|
||||
val filters = super.getFilterList().toMutableList()
|
||||
filters.add(4, TagList(getTagList()))
|
||||
if (filters.size > 7) {
|
||||
filters.removeAt(7) // AgeList
|
||||
}
|
||||
return FilterList(filters)
|
||||
}
|
||||
|
||||
private fun getTagList() = listOf(
|
||||
SearchFilter("3D", "1"),
|
||||
SearchFilter("Defloration", "287"),
|
||||
SearchFilter("FPP(Вид от первого лица)", "289"),
|
||||
SearchFilter("Footfuck", "5"),
|
||||
SearchFilter("Handjob", "6"),
|
||||
SearchFilter("Lactation", "7"),
|
||||
SearchFilter("Living clothes", "284"),
|
||||
SearchFilter("Mind break", "9"),
|
||||
SearchFilter("Scat", "13"),
|
||||
SearchFilter("Selfcest", "286"),
|
||||
SearchFilter("Shemale", "220"),
|
||||
SearchFilter("Tomboy", "14"),
|
||||
SearchFilter("Unbirth", "283"),
|
||||
SearchFilter("X-Ray", "15"),
|
||||
SearchFilter("Алкоголь", "16"),
|
||||
SearchFilter("Анал", "17"),
|
||||
SearchFilter("Андроид", "18"),
|
||||
SearchFilter("Анилингус", "19"),
|
||||
SearchFilter("Анимация (GIF)", "350"),
|
||||
SearchFilter("Арт", "20"),
|
||||
SearchFilter("Ахэгао", "2"),
|
||||
SearchFilter("БДСМ", "22"),
|
||||
SearchFilter("Бакуню", "21"),
|
||||
SearchFilter("Бара", "293"),
|
||||
SearchFilter("Без проникновения", "336"),
|
||||
SearchFilter("Без текста", "23"),
|
||||
SearchFilter("Без трусиков", "24"),
|
||||
SearchFilter("Без цензуры", "25"),
|
||||
SearchFilter("Беременность", "26"),
|
||||
SearchFilter("Бикини", "27"),
|
||||
SearchFilter("Близнецы", "28"),
|
||||
SearchFilter("Боди-арт", "29"),
|
||||
SearchFilter("Больница", "30"),
|
||||
SearchFilter("Большая грудь", "31"),
|
||||
SearchFilter("Большая попка", "32"),
|
||||
SearchFilter("Борьба", "33"),
|
||||
SearchFilter("Буккакэ", "34"),
|
||||
SearchFilter("В бассейне", "35"),
|
||||
SearchFilter("В ванной", "36"),
|
||||
SearchFilter("В государственном учреждении", "37"),
|
||||
SearchFilter("В общественном месте", "38"),
|
||||
SearchFilter("В очках", "8"),
|
||||
SearchFilter("В первый раз", "39"),
|
||||
SearchFilter("В транспорте", "40"),
|
||||
SearchFilter("Вампиры", "41"),
|
||||
SearchFilter("Вибратор", "42"),
|
||||
SearchFilter("Втроём", "43"),
|
||||
SearchFilter("Гипноз", "44"),
|
||||
SearchFilter("Глубокий минет", "45"),
|
||||
SearchFilter("Горячий источник", "46"),
|
||||
SearchFilter("Групповой секс", "47"),
|
||||
SearchFilter("Гуро", "307"),
|
||||
SearchFilter("Гяру и Гангуро", "48"),
|
||||
SearchFilter("Двойное проникновение", "49"),
|
||||
SearchFilter("Девочки-волшебницы", "50"),
|
||||
SearchFilter("Девушка-туалет", "51"),
|
||||
SearchFilter("Демон", "52"),
|
||||
SearchFilter("Дилдо", "53"),
|
||||
SearchFilter("Домохозяйка", "54"),
|
||||
SearchFilter("Дыра в стене", "55"),
|
||||
SearchFilter("Жестокость", "56"),
|
||||
SearchFilter("Золотой дождь", "57"),
|
||||
SearchFilter("Зомби", "58"),
|
||||
SearchFilter("Зоофилия", "351"),
|
||||
SearchFilter("Зрелые женщины", "59"),
|
||||
SearchFilter("Избиение", "223"),
|
||||
SearchFilter("Измена", "60"),
|
||||
SearchFilter("Изнасилование", "61"),
|
||||
SearchFilter("Инопланетяне", "62"),
|
||||
SearchFilter("Инцест", "63"),
|
||||
SearchFilter("Исполнение желаний", "64"),
|
||||
SearchFilter("Историческое", "65"),
|
||||
SearchFilter("Камера", "66"),
|
||||
SearchFilter("Кляп", "288"),
|
||||
SearchFilter("Колготки", "67"),
|
||||
SearchFilter("Косплей", "68"),
|
||||
SearchFilter("Кримпай", "3"),
|
||||
SearchFilter("Куннилингус", "69"),
|
||||
SearchFilter("Купальники", "70"),
|
||||
SearchFilter("ЛГБТ", "343"),
|
||||
SearchFilter("Латекс и кожа", "71"),
|
||||
SearchFilter("Магия", "72"),
|
||||
SearchFilter("Маленькая грудь", "73"),
|
||||
SearchFilter("Мастурбация", "74"),
|
||||
SearchFilter("Медсестра", "221"),
|
||||
SearchFilter("Мейдочка", "75"),
|
||||
SearchFilter("Мерзкий дядька", "76"),
|
||||
SearchFilter("Милф", "77"),
|
||||
SearchFilter("Много девушек", "78"),
|
||||
SearchFilter("Много спермы", "79"),
|
||||
SearchFilter("Молоко", "80"),
|
||||
SearchFilter("Монашка", "353"),
|
||||
SearchFilter("Монстродевушки", "81"),
|
||||
SearchFilter("Монстры", "82"),
|
||||
SearchFilter("Мочеиспускание", "83"),
|
||||
SearchFilter("На природе", "84"),
|
||||
SearchFilter("Наблюдение", "85"),
|
||||
SearchFilter("Насекомые", "285"),
|
||||
SearchFilter("Небритая киска", "86"),
|
||||
SearchFilter("Небритые подмышки", "87"),
|
||||
SearchFilter("Нетораре", "88"),
|
||||
SearchFilter("Нэтори", "11"),
|
||||
SearchFilter("Обмен телами", "89"),
|
||||
SearchFilter("Обычный секс", "90"),
|
||||
SearchFilter("Огромная грудь", "91"),
|
||||
SearchFilter("Огромный член", "92"),
|
||||
SearchFilter("Омораси", "93"),
|
||||
SearchFilter("Оральный секс", "94"),
|
||||
SearchFilter("Орки", "95"),
|
||||
SearchFilter("Остановка времени", "296"),
|
||||
SearchFilter("Пайзури", "96"),
|
||||
SearchFilter("Парень пассив", "97"),
|
||||
SearchFilter("Переодевание", "98"),
|
||||
SearchFilter("Пирсинг", "308"),
|
||||
SearchFilter("Пляж", "99"),
|
||||
SearchFilter("Повседневность", "100"),
|
||||
SearchFilter("Подвязки", "282"),
|
||||
SearchFilter("Подглядывание", "101"),
|
||||
SearchFilter("Подчинение", "102"),
|
||||
SearchFilter("Похищение", "103"),
|
||||
SearchFilter("Превозмогание", "104"),
|
||||
SearchFilter("Принуждение", "105"),
|
||||
SearchFilter("Прозрачная одежда", "106"),
|
||||
SearchFilter("Проституция", "107"),
|
||||
SearchFilter("Психические отклонения", "108"),
|
||||
SearchFilter("Публично", "109"),
|
||||
SearchFilter("Пытки", "224"),
|
||||
SearchFilter("Пьяные", "110"),
|
||||
SearchFilter("Рабы", "356"),
|
||||
SearchFilter("Рабыни", "111"),
|
||||
SearchFilter("С Сюжетом", "337"),
|
||||
SearchFilter("Сuminside", "4"),
|
||||
SearchFilter("Секс-игрушки", "112"),
|
||||
SearchFilter("Сексуально возбуждённая", "113"),
|
||||
SearchFilter("Сибари", "114"),
|
||||
SearchFilter("Спортивная форма", "117"),
|
||||
SearchFilter("Спортивное тело", "335"),
|
||||
SearchFilter("Спящие", "118"),
|
||||
SearchFilter("Страпон", "119"),
|
||||
SearchFilter("Суккуб", "120"),
|
||||
SearchFilter("Темнокожие", "121"),
|
||||
SearchFilter("Тентакли", "122"),
|
||||
SearchFilter("Толстушки", "123"),
|
||||
SearchFilter("Трагедия", "124"),
|
||||
SearchFilter("Трап", "125"),
|
||||
SearchFilter("Ужасы", "126"),
|
||||
SearchFilter("Униформа", "127"),
|
||||
SearchFilter("Учитель и ученик", "352"),
|
||||
SearchFilter("Ушастые", "128"),
|
||||
SearchFilter("Фантазии", "129"),
|
||||
SearchFilter("Фемдом", "130"),
|
||||
SearchFilter("Фестиваль", "131"),
|
||||
SearchFilter("Фетиш", "132"),
|
||||
SearchFilter("Фистинг", "133"),
|
||||
SearchFilter("Фурри", "134"),
|
||||
SearchFilter("Футанари", "136"),
|
||||
SearchFilter("Футанари имеет парня", "137"),
|
||||
SearchFilter("Цельный купальник", "138"),
|
||||
SearchFilter("Цундэрэ", "139"),
|
||||
SearchFilter("Чикан", "140"),
|
||||
SearchFilter("Чулки", "141"),
|
||||
SearchFilter("Шлюха", "142"),
|
||||
SearchFilter("Эксгибиционизм", "143"),
|
||||
SearchFilter("Эльф", "144"),
|
||||
SearchFilter("Юные", "145"),
|
||||
SearchFilter("Яндэрэ", "146"),
|
||||
)
|
||||
|
||||
override fun setupPreferenceScreen(screen: androidx.preference.PreferenceScreen) {
|
||||
super.setupPreferenceScreen(screen)
|
||||
EditTextPreference(screen.context).apply {
|
||||
@ -234,7 +37,7 @@ class HentaiLib : LibGroup("HentaiLib", "https://hentailib.me", "ru") {
|
||||
summary = domain
|
||||
this.setDefaultValue(DOMAIN_DEFAULT)
|
||||
dialogTitle = DOMAIN_TITLE
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
setOnPreferenceChangeListener { _, _ ->
|
||||
val warning = "Для смены домена необходимо перезапустить приложение с полной остановкой."
|
||||
Toast.makeText(screen.context, warning, Toast.LENGTH_LONG).show()
|
||||
true
|
||||
@ -243,8 +46,6 @@ class HentaiLib : LibGroup("HentaiLib", "https://hentailib.me", "ru") {
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val PREFIX_SLUG_SEARCH = "slug:"
|
||||
|
||||
private const val DOMAIN_TITLE = "Домен"
|
||||
private const val DOMAIN_DEFAULT = "https://hentailib.me"
|
||||
}
|
||||
|
@ -1,28 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<application>
|
||||
<activity
|
||||
android:name="eu.kanade.tachiyomi.multisrc.libgroup.LibUrlActivity"
|
||||
android:excludeFromRecents="true"
|
||||
android:exported="true"
|
||||
android:theme="@android:style/Theme.NoDisplay">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<!-- LibUrlActivity sites can be added here. -->
|
||||
<data
|
||||
android:host="mangalib.me"
|
||||
android:pathPattern="/..*/v..*"
|
||||
android:scheme="https" />
|
||||
<data
|
||||
android:host="mangalib.org"
|
||||
android:pathPattern="/..*/v..*"
|
||||
android:scheme="https" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
@ -3,206 +3,41 @@ package eu.kanade.tachiyomi.extension.ru.mangalib
|
||||
import android.app.Application
|
||||
import android.content.SharedPreferences
|
||||
import android.widget.Toast
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.PreferenceScreen
|
||||
import androidx.preference.EditTextPreference
|
||||
import eu.kanade.tachiyomi.multisrc.libgroup.LibGroup
|
||||
import eu.kanade.tachiyomi.network.POST
|
||||
import eu.kanade.tachiyomi.source.model.Filter
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
import okhttp3.Request
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
class MangaLib : LibGroup("MangaLib", "https://mangalib.me", "ru") {
|
||||
|
||||
override val id: Long = 6111047689498497237
|
||||
|
||||
private val preferences: SharedPreferences by lazy {
|
||||
Injekt.get<Application>().getSharedPreferences("source_${id}_2", 0x0000)
|
||||
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
|
||||
}
|
||||
|
||||
private val baseOrig: String = "https://mangalib.me"
|
||||
private val baseMirr: String = "https://mangalib.org"
|
||||
private var domain: String? = preferences.getString(DOMAIN_PREF, baseOrig)
|
||||
override val baseUrl: String = domain.toString()
|
||||
private var domain: String = preferences.getString(DOMAIN_PREF, DOMAIN_DEFAULT)!!
|
||||
override val baseUrl: String = domain
|
||||
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||
if (csrfToken.isEmpty()) {
|
||||
val tokenResponse = client.newCall(popularMangaRequest(page)).execute()
|
||||
val resBody = tokenResponse.body.string()
|
||||
csrfToken = "_token\" content=\"(.*)\"".toRegex().find(resBody)!!.groups[1]!!.value
|
||||
}
|
||||
val url = super.searchMangaRequest(page, query, filters).url.newBuilder()
|
||||
(if (filters.isEmpty()) getFilterList() else filters).forEach { filter ->
|
||||
when (filter) {
|
||||
is AgeList -> filter.state.forEach { age ->
|
||||
if (age.state != Filter.TriState.STATE_IGNORE) {
|
||||
url.addQueryParameter(
|
||||
if (age.isIncluded()) "caution[include][]" else "caution[exclude][]",
|
||||
age.id,
|
||||
)
|
||||
}
|
||||
}
|
||||
is TagList -> filter.state.forEach { tag ->
|
||||
if (tag.state != Filter.TriState.STATE_IGNORE) {
|
||||
url.addQueryParameter(
|
||||
if (tag.isIncluded()) "tags[include][]" else "tags[exclude][]",
|
||||
tag.id,
|
||||
)
|
||||
}
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
return POST(url.toString(), catalogHeaders())
|
||||
}
|
||||
override val siteId: Int = 1 // Important in api calls
|
||||
|
||||
// Filters
|
||||
private class SearchFilter(name: String, val id: String) : Filter.TriState(name)
|
||||
|
||||
private class TagList(tags: List<SearchFilter>) : Filter.Group<SearchFilter>("Теги", tags)
|
||||
private class AgeList(ages: List<SearchFilter>) : Filter.Group<SearchFilter>("Возрастное ограничение", ages)
|
||||
|
||||
override fun getFilterList(): FilterList {
|
||||
val filters = super.getFilterList().toMutableList()
|
||||
filters.add(4, TagList(getTagList()))
|
||||
filters.add(7, AgeList(getAgeList()))
|
||||
return FilterList(filters)
|
||||
}
|
||||
|
||||
private fun getTagList() = listOf(
|
||||
SearchFilter("Азартные игры", "304"),
|
||||
SearchFilter("Алхимия", "225"),
|
||||
SearchFilter("Ангелы", "226"),
|
||||
SearchFilter("Антигерой", "175"),
|
||||
SearchFilter("Антиутопия", "227"),
|
||||
SearchFilter("Апокалипсис", "228"),
|
||||
SearchFilter("Армия", "229"),
|
||||
SearchFilter("Артефакты", "230"),
|
||||
SearchFilter("Боги", "215"),
|
||||
SearchFilter("Бои на мечах", "231"),
|
||||
SearchFilter("Борьба за власть", "231"),
|
||||
SearchFilter("Брат и сестра", "233"),
|
||||
SearchFilter("Будущее", "234"),
|
||||
SearchFilter("Ведьма", "338"),
|
||||
SearchFilter("Вестерн", "235"),
|
||||
SearchFilter("Видеоигры", "185"),
|
||||
SearchFilter("Виртуальная реальность", "195"),
|
||||
SearchFilter("Владыка демонов", "236"),
|
||||
SearchFilter("Военные", "179"),
|
||||
SearchFilter("Война", "237"),
|
||||
SearchFilter("Волшебники / маги", "281"),
|
||||
SearchFilter("Волшебные существа", "239"),
|
||||
SearchFilter("Воспоминания из другого мира", "240"),
|
||||
SearchFilter("Выживание", "193"),
|
||||
SearchFilter("ГГ женщина", "243"),
|
||||
SearchFilter("ГГ имба", "291"),
|
||||
SearchFilter("ГГ мужчина", "244"),
|
||||
SearchFilter("Геймеры", "241"),
|
||||
SearchFilter("Гильдии", "242"),
|
||||
SearchFilter("Глупый ГГ", "297"),
|
||||
SearchFilter("Гоблины", "245"),
|
||||
SearchFilter("Горничные", "169"),
|
||||
SearchFilter("Гяру", "178"),
|
||||
SearchFilter("Демоны", "151"),
|
||||
SearchFilter("Драконы", "246"),
|
||||
SearchFilter("Дружба", "247"),
|
||||
SearchFilter("Жестокий мир", "249"),
|
||||
SearchFilter("Животные компаньоны", "250"),
|
||||
SearchFilter("Завоевание мира", "251"),
|
||||
SearchFilter("Зверолюди", "162"),
|
||||
SearchFilter("Злые духи", "252"),
|
||||
SearchFilter("Зомби", "149"),
|
||||
SearchFilter("Игровые элементы", "253"),
|
||||
SearchFilter("Империи", "254"),
|
||||
SearchFilter("Квесты", "255"),
|
||||
SearchFilter("Космос", "256"),
|
||||
SearchFilter("Кулинария", "152"),
|
||||
SearchFilter("Культивация", "160"),
|
||||
SearchFilter("Легендарное оружие", "257"),
|
||||
SearchFilter("Лоли", "187"),
|
||||
SearchFilter("Магическая академия", "258"),
|
||||
SearchFilter("Магия", "168"),
|
||||
SearchFilter("Мафия", "172"),
|
||||
SearchFilter("Медицина", "153"),
|
||||
SearchFilter("Месть", "259"),
|
||||
SearchFilter("Монстр Девушки", "188"),
|
||||
SearchFilter("Монстры", "189"),
|
||||
SearchFilter("Музыка", "190"),
|
||||
SearchFilter("Навыки / способности", "260"),
|
||||
SearchFilter("Насилие / жестокость", "262"),
|
||||
SearchFilter("Наёмники", "261"),
|
||||
SearchFilter("Нежить", "263"),
|
||||
SearchFilter("Ниндая", "180"),
|
||||
SearchFilter("Обратный Гарем", "191"),
|
||||
SearchFilter("Огнестрельное оружие", "264"),
|
||||
SearchFilter("Офисные Работники", "181"),
|
||||
SearchFilter("Пародия", "265"),
|
||||
SearchFilter("Пираты", "340"),
|
||||
SearchFilter("Подземелья", "266"),
|
||||
SearchFilter("Политика", "267"),
|
||||
SearchFilter("Полиция", "182"),
|
||||
SearchFilter("Преступники / Криминал", "186"),
|
||||
SearchFilter("Призраки / Духи", "177"),
|
||||
SearchFilter("Путешествие во времени", "194"),
|
||||
SearchFilter("Разумные расы", "268"),
|
||||
SearchFilter("Ранги силы", "248"),
|
||||
SearchFilter("Реинкарнация", "148"),
|
||||
SearchFilter("Роботы", "269"),
|
||||
SearchFilter("Рыцари", "270"),
|
||||
SearchFilter("Самураи", "183"),
|
||||
SearchFilter("Система", "271"),
|
||||
SearchFilter("Скрытие личности", "273"),
|
||||
SearchFilter("Спасение мира", "274"),
|
||||
SearchFilter("Спортивное тело", "334"),
|
||||
SearchFilter("Средневековье", "173"),
|
||||
SearchFilter("Стимпанк", "272"),
|
||||
SearchFilter("Супергерои", "275"),
|
||||
SearchFilter("Традиционные игры", "184"),
|
||||
SearchFilter("Умный ГГ", "302"),
|
||||
SearchFilter("Учитель / ученик", "276"),
|
||||
SearchFilter("Философия", "277"),
|
||||
SearchFilter("Хикикомори", "166"),
|
||||
SearchFilter("Холодное оружие", "278"),
|
||||
SearchFilter("Шантаж", "279"),
|
||||
SearchFilter("Эльфы", "216"),
|
||||
SearchFilter("Якудза", "164"),
|
||||
SearchFilter("Япония", "280"),
|
||||
|
||||
)
|
||||
|
||||
private fun getAgeList() = listOf(
|
||||
SearchFilter("Отсутствует", "0"),
|
||||
SearchFilter("16+", "1"),
|
||||
SearchFilter("18+", "2"),
|
||||
)
|
||||
|
||||
companion object {
|
||||
const val PREFIX_SLUG_SEARCH = "slug:"
|
||||
private const val DOMAIN_PREF = "MangaLibDomain"
|
||||
private const val DOMAIN_PREF_Title = "Выбор домена"
|
||||
}
|
||||
|
||||
override fun setupPreferenceScreen(screen: PreferenceScreen) {
|
||||
override fun setupPreferenceScreen(screen: androidx.preference.PreferenceScreen) {
|
||||
super.setupPreferenceScreen(screen)
|
||||
ListPreference(screen.context).apply {
|
||||
EditTextPreference(screen.context).apply {
|
||||
key = DOMAIN_PREF
|
||||
title = DOMAIN_PREF_Title
|
||||
entries = arrayOf("Основной (mangalib.me)", "Зеркало (mangalib.org)")
|
||||
entryValues = arrayOf(baseOrig, baseMirr)
|
||||
summary = "%s"
|
||||
setDefaultValue(baseOrig)
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
try {
|
||||
val res = preferences.edit().putString(DOMAIN_PREF, newValue as String).commit()
|
||||
val warning = "Для смены домена необходимо перезапустить приложение с полной остановкой."
|
||||
Toast.makeText(screen.context, warning, Toast.LENGTH_LONG).show()
|
||||
res
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
false
|
||||
}
|
||||
this.title = DOMAIN_TITLE
|
||||
summary = domain
|
||||
this.setDefaultValue(DOMAIN_DEFAULT)
|
||||
dialogTitle = DOMAIN_TITLE
|
||||
setOnPreferenceChangeListener { _, _ ->
|
||||
val warning = "Для смены домена необходимо перезапустить приложение с полной остановкой."
|
||||
Toast.makeText(screen.context, warning, Toast.LENGTH_LONG).show()
|
||||
true
|
||||
}
|
||||
}.let(screen::addPreference)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val DOMAIN_PREF = "MangaLibDomain"
|
||||
private const val DOMAIN_TITLE = "Домен"
|
||||
private const val DOMAIN_DEFAULT = "https://test-front.mangalib.me"
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<application>
|
||||
<activity
|
||||
android:name="eu.kanade.tachiyomi.multisrc.libgroup.LibUrlActivity"
|
||||
android:excludeFromRecents="true"
|
||||
android:exported="true"
|
||||
android:theme="@android:style/Theme.NoDisplay">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<!-- LibUrlActivity sites can be added here. -->
|
||||
<data
|
||||
android:host="v2.slashlib.me"
|
||||
android:pathPattern="/..*/v..*"
|
||||
android:scheme="https" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
@ -2,7 +2,7 @@ ext {
|
||||
extName = 'YaoiLib'
|
||||
extClass = '.YaoiLib'
|
||||
themePkg = 'libgroup'
|
||||
baseUrl = 'https://v2.slashlib.me'
|
||||
baseUrl = 'https://slashlib.me'
|
||||
overrideVersionCode = 4
|
||||
isNsfw = true
|
||||
}
|
||||
|
@ -5,14 +5,10 @@ import android.content.SharedPreferences
|
||||
import android.widget.Toast
|
||||
import androidx.preference.EditTextPreference
|
||||
import eu.kanade.tachiyomi.multisrc.libgroup.LibGroup
|
||||
import eu.kanade.tachiyomi.network.POST
|
||||
import eu.kanade.tachiyomi.source.model.Filter
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
import okhttp3.Request
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
class YaoiLib : LibGroup("YaoiLib", "https://v2.slashlib.me", "ru") {
|
||||
class YaoiLib : LibGroup("YaoiLib", "https://slashlib.me", "ru") {
|
||||
|
||||
private val preferences: SharedPreferences by lazy {
|
||||
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
|
||||
@ -21,156 +17,7 @@ class YaoiLib : LibGroup("YaoiLib", "https://v2.slashlib.me", "ru") {
|
||||
private var domain: String = preferences.getString(DOMAIN_TITLE, DOMAIN_DEFAULT)!!
|
||||
override val baseUrl: String = domain
|
||||
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||
if (csrfToken.isEmpty()) {
|
||||
val tokenResponse = client.newCall(popularMangaRequest(page)).execute()
|
||||
val resBody = tokenResponse.body.string()
|
||||
csrfToken = "_token\" content=\"(.*)\"".toRegex().find(resBody)!!.groups[1]!!.value
|
||||
}
|
||||
val url = super.searchMangaRequest(page, query, filters).url.newBuilder()
|
||||
(if (filters.isEmpty()) getFilterList() else filters).forEach { filter ->
|
||||
when (filter) {
|
||||
is AgeList -> filter.state.forEach { age ->
|
||||
if (age.state != Filter.TriState.STATE_IGNORE) {
|
||||
url.addQueryParameter(
|
||||
if (age.isIncluded()) "caution[include][]" else "caution[exclude][]",
|
||||
age.id,
|
||||
)
|
||||
}
|
||||
}
|
||||
is TagList -> filter.state.forEach { tag ->
|
||||
if (tag.state != Filter.TriState.STATE_IGNORE) {
|
||||
url.addQueryParameter(
|
||||
if (tag.isIncluded()) "tags[include][]" else "tags[exclude][]",
|
||||
tag.id,
|
||||
)
|
||||
}
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
return POST(url.toString(), catalogHeaders())
|
||||
}
|
||||
|
||||
// Filters
|
||||
private class SearchFilter(name: String, val id: String) : Filter.TriState(name)
|
||||
|
||||
private class TagList(tags: List<SearchFilter>) : Filter.Group<SearchFilter>("Теги", tags)
|
||||
private class AgeList(ages: List<SearchFilter>) : Filter.Group<SearchFilter>("Возрастное ограничение", ages)
|
||||
|
||||
override fun getFilterList(): FilterList {
|
||||
val filters = super.getFilterList().toMutableList()
|
||||
filters.add(4, TagList(getTagList()))
|
||||
filters.add(7, AgeList(getAgeList()))
|
||||
return FilterList(filters)
|
||||
}
|
||||
|
||||
private fun getTagList() = listOf(
|
||||
SearchFilter("Азартные игры", "304"),
|
||||
SearchFilter("Алхимия", "225"),
|
||||
SearchFilter("Ангелы", "226"),
|
||||
SearchFilter("Антигерой", "175"),
|
||||
SearchFilter("Антиутопия", "227"),
|
||||
SearchFilter("Апокалипсис", "228"),
|
||||
SearchFilter("Армия", "229"),
|
||||
SearchFilter("Артефакты", "230"),
|
||||
SearchFilter("Боги", "215"),
|
||||
SearchFilter("Бои на мечах", "231"),
|
||||
SearchFilter("Борьба за власть", "231"),
|
||||
SearchFilter("Брат и сестра", "233"),
|
||||
SearchFilter("Будущее", "234"),
|
||||
SearchFilter("Ведьма", "338"),
|
||||
SearchFilter("Вестерн", "235"),
|
||||
SearchFilter("Видеоигры", "185"),
|
||||
SearchFilter("Виртуальная реальность", "195"),
|
||||
SearchFilter("Владыка демонов", "236"),
|
||||
SearchFilter("Военные", "179"),
|
||||
SearchFilter("Война", "237"),
|
||||
SearchFilter("Волшебники / маги", "281"),
|
||||
SearchFilter("Волшебные существа", "239"),
|
||||
SearchFilter("Воспоминания из другого мира", "240"),
|
||||
SearchFilter("Выживание", "193"),
|
||||
SearchFilter("ГГ женщина", "243"),
|
||||
SearchFilter("ГГ имба", "291"),
|
||||
SearchFilter("ГГ мужчина", "244"),
|
||||
SearchFilter("Геймеры", "241"),
|
||||
SearchFilter("Гильдии", "242"),
|
||||
SearchFilter("Глупый ГГ", "297"),
|
||||
SearchFilter("Гоблины", "245"),
|
||||
SearchFilter("Горничные", "169"),
|
||||
SearchFilter("Гяру", "178"),
|
||||
SearchFilter("Демоны", "151"),
|
||||
SearchFilter("Драконы", "246"),
|
||||
SearchFilter("Дружба", "247"),
|
||||
SearchFilter("Жестокий мир", "249"),
|
||||
SearchFilter("Животные компаньоны", "250"),
|
||||
SearchFilter("Завоевание мира", "251"),
|
||||
SearchFilter("Зверолюди", "162"),
|
||||
SearchFilter("Злые духи", "252"),
|
||||
SearchFilter("Зомби", "149"),
|
||||
SearchFilter("Игровые элементы", "253"),
|
||||
SearchFilter("Империи", "254"),
|
||||
SearchFilter("Квесты", "255"),
|
||||
SearchFilter("Космос", "256"),
|
||||
SearchFilter("Кулинария", "152"),
|
||||
SearchFilter("Культивация", "160"),
|
||||
SearchFilter("Легендарное оружие", "257"),
|
||||
SearchFilter("Лоли", "187"),
|
||||
SearchFilter("Магическая академия", "258"),
|
||||
SearchFilter("Магия", "168"),
|
||||
SearchFilter("Мафия", "172"),
|
||||
SearchFilter("Медицина", "153"),
|
||||
SearchFilter("Месть", "259"),
|
||||
SearchFilter("Монстр Девушки", "188"),
|
||||
SearchFilter("Монстры", "189"),
|
||||
SearchFilter("Музыка", "190"),
|
||||
SearchFilter("Навыки / способности", "260"),
|
||||
SearchFilter("Насилие / жестокость", "262"),
|
||||
SearchFilter("Наёмники", "261"),
|
||||
SearchFilter("Нежить", "263"),
|
||||
SearchFilter("Ниндая", "180"),
|
||||
SearchFilter("Обратный Гарем", "191"),
|
||||
SearchFilter("Огнестрельное оружие", "264"),
|
||||
SearchFilter("Офисные Работники", "181"),
|
||||
SearchFilter("Пародия", "265"),
|
||||
SearchFilter("Пираты", "340"),
|
||||
SearchFilter("Подземелья", "266"),
|
||||
SearchFilter("Политика", "267"),
|
||||
SearchFilter("Полиция", "182"),
|
||||
SearchFilter("Преступники / Криминал", "186"),
|
||||
SearchFilter("Призраки / Духи", "177"),
|
||||
SearchFilter("Путешествие во времени", "194"),
|
||||
SearchFilter("Разумные расы", "268"),
|
||||
SearchFilter("Ранги силы", "248"),
|
||||
SearchFilter("Реинкарнация", "148"),
|
||||
SearchFilter("Роботы", "269"),
|
||||
SearchFilter("Рыцари", "270"),
|
||||
SearchFilter("Самураи", "183"),
|
||||
SearchFilter("Система", "271"),
|
||||
SearchFilter("Скрытие личности", "273"),
|
||||
SearchFilter("Спасение мира", "274"),
|
||||
SearchFilter("Спортивное тело", "334"),
|
||||
SearchFilter("Средневековье", "173"),
|
||||
SearchFilter("Стимпанк", "272"),
|
||||
SearchFilter("Супергерои", "275"),
|
||||
SearchFilter("Традиционные игры", "184"),
|
||||
SearchFilter("Умный ГГ", "302"),
|
||||
SearchFilter("Учитель / ученик", "276"),
|
||||
SearchFilter("Философия", "277"),
|
||||
SearchFilter("Хикикомори", "166"),
|
||||
SearchFilter("Холодное оружие", "278"),
|
||||
SearchFilter("Шантаж", "279"),
|
||||
SearchFilter("Эльфы", "216"),
|
||||
SearchFilter("Якудза", "164"),
|
||||
SearchFilter("Япония", "280"),
|
||||
|
||||
)
|
||||
|
||||
private fun getAgeList() = listOf(
|
||||
SearchFilter("Отсутствует", "0"),
|
||||
SearchFilter("16+", "1"),
|
||||
SearchFilter("18+", "2"),
|
||||
)
|
||||
override val siteId: Int = 2 // Important in api calls
|
||||
|
||||
override fun setupPreferenceScreen(screen: androidx.preference.PreferenceScreen) {
|
||||
super.setupPreferenceScreen(screen)
|
||||
@ -180,7 +27,7 @@ class YaoiLib : LibGroup("YaoiLib", "https://v2.slashlib.me", "ru") {
|
||||
summary = domain
|
||||
this.setDefaultValue(DOMAIN_DEFAULT)
|
||||
dialogTitle = DOMAIN_TITLE
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
setOnPreferenceChangeListener { _, _ ->
|
||||
val warning = "Для смены домена необходимо перезапустить приложение с полной остановкой."
|
||||
Toast.makeText(screen.context, warning, Toast.LENGTH_LONG).show()
|
||||
true
|
||||
@ -189,9 +36,7 @@ class YaoiLib : LibGroup("YaoiLib", "https://v2.slashlib.me", "ru") {
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val PREFIX_SLUG_SEARCH = "slug:"
|
||||
|
||||
private const val DOMAIN_TITLE = "Домен"
|
||||
private const val DOMAIN_DEFAULT = "https://v2.slashlib.me"
|
||||
private const val DOMAIN_DEFAULT = "https://test-front.slashlib.me"
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user