mirror of
https://github.com/Dark25/aniyomi-extensions.git
synced 2024-10-27 23:59:36 +01:00
Update dependencies and some linting (#1631)
This commit is contained in:
parent
60eb7a9262
commit
3a8120cb59
161 changed files with 982 additions and 1003 deletions
|
@ -10,3 +10,6 @@ insert_final_newline = true
|
|||
trim_trailing_whitespace = true
|
||||
ij_kotlin_allow_trailing_comma = true
|
||||
ij_kotlin_allow_trailing_comma_on_call_site = true
|
||||
ktlint_experimental = enabled
|
||||
ktlint_experimental_argument-list-wrapping = disabled # Doesn't play well with Android Studio
|
||||
ktlint_experimental_comment-wrapping = disabled
|
||||
|
|
2
.github/workflows/batch_close_issues.yml
vendored
2
.github/workflows/batch_close_issues.yml
vendored
|
@ -12,7 +12,7 @@ jobs:
|
|||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v7
|
||||
- uses: actions/stale@v8
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# Close everything older than ~6 months
|
||||
|
|
6
.github/workflows/build_pull_request.yml
vendored
6
.github/workflows/build_pull_request.yml
vendored
|
@ -33,7 +33,7 @@ jobs:
|
|||
- name: Set up JDK
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: 11
|
||||
java-version: 17
|
||||
distribution: adopt
|
||||
|
||||
- id: get-changed-files
|
||||
|
@ -107,7 +107,7 @@ jobs:
|
|||
- name: Set up JDK
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: 11
|
||||
java-version: 17
|
||||
distribution: adopt
|
||||
|
||||
- name: Generate sources from the multi-source library
|
||||
|
@ -141,7 +141,7 @@ jobs:
|
|||
- name: Set up JDK
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: 11
|
||||
java-version: 17
|
||||
distribution: adopt
|
||||
|
||||
- name: Build extensions (chunk ${{ matrix.chunk }})
|
||||
|
|
8
.github/workflows/build_push.yml
vendored
8
.github/workflows/build_push.yml
vendored
|
@ -48,7 +48,7 @@ jobs:
|
|||
- name: Set up JDK
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: 11
|
||||
java-version: 17
|
||||
distribution: adopt
|
||||
|
||||
- name: Generate multisrc sources
|
||||
|
@ -97,7 +97,7 @@ jobs:
|
|||
- name: Set up JDK
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: 11
|
||||
java-version: 17
|
||||
distribution: adopt
|
||||
|
||||
- name: Prepare signing key
|
||||
|
@ -148,7 +148,7 @@ jobs:
|
|||
- name: Set up JDK
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: 11
|
||||
java-version: 17
|
||||
distribution: adopt
|
||||
|
||||
- name: Prepare signing key
|
||||
|
@ -193,7 +193,7 @@ jobs:
|
|||
- name: Set up JDK
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: 11
|
||||
java-version: 17
|
||||
distribution: adopt
|
||||
|
||||
- name: Checkout master branch
|
||||
|
|
2
.github/workflows/issue_moderator.yml
vendored
2
.github/workflows/issue_moderator.yml
vendored
|
@ -11,7 +11,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Moderate issues
|
||||
uses: tachiyomiorg/issue-moderator-action@v1
|
||||
uses: tachiyomiorg/issue-moderator-action@v2
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
duplicate-check-enabled: true
|
||||
|
|
|
@ -8,3 +8,11 @@ plugins {
|
|||
tasks.register<Delete>("clean") {
|
||||
delete(rootProject.buildDir)
|
||||
}
|
||||
|
||||
allprojects {
|
||||
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
|
||||
kotlinOptions {
|
||||
jvmTarget = JavaVersion.VERSION_1_8.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,14 +82,6 @@ android {
|
|||
jvmTarget = JavaVersion.VERSION_1_8.toString()
|
||||
freeCompilerArgs += "-opt-in=kotlinx.serialization.ExperimentalSerializationApi"
|
||||
}
|
||||
|
||||
kotlinter {
|
||||
experimentalRules = true
|
||||
disabledRules = [
|
||||
"experimental:argument-list-wrapping", // Doesn't play well with Android Studio
|
||||
"experimental:comment-wrapping",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
@ -100,7 +92,7 @@ dependencies {
|
|||
configurations.all {
|
||||
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
|
||||
if (details.requested.group == 'org.jetbrains.kotlin' && details.requested.name == 'kotlin-stdlib-jdk8' && details.requested.version == '1.7.0') {
|
||||
details.useVersion '1.7.21'
|
||||
details.useVersion '1.8.21'
|
||||
details.because 'Fix problems with dev.datlag JsUnpacker'
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
[versions]
|
||||
agp_version = "7.4.1"
|
||||
coroutines_version = "1.6.4"
|
||||
kotlin_version = "1.7.21"
|
||||
serialization_version = "1.4.0"
|
||||
agp_version = "8.0.1"
|
||||
coroutines_version = "1.7.1"
|
||||
kotlin_version = "1.8.21"
|
||||
serialization_version = "1.5.1"
|
||||
|
||||
[libraries]
|
||||
aniyomi-lib = { module = "com.github.jmir1:extensions-lib", version = "a2f1874" }
|
||||
|
@ -17,7 +17,7 @@ coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-androi
|
|||
injekt-core = { module = "com.github.inorichi.injekt:injekt-core", version = "65b0440" }
|
||||
rxandroid = { module = "io.reactivex:rxandroid", version = "1.2.1" }
|
||||
rxjava = { module = "io.reactivex:rxjava", version = "1.3.8" }
|
||||
jsoup = { module = "org.jsoup:jsoup", version = "1.15.3" }
|
||||
jsoup = { module = "org.jsoup:jsoup", version = "1.16.1" }
|
||||
okhttp = { module = "com.squareup.okhttp3:okhttp", version = "5.0.0-alpha.11" }
|
||||
quickjs = { module = "app.cash.quickjs:quickjs-android", version = "0.9.2" }
|
||||
|
||||
|
@ -28,6 +28,6 @@ reactivex = ["rxandroid"]
|
|||
[plugins]
|
||||
android-application = { id = "com.android.application", version.ref = "agp_version" }
|
||||
android-library = { id = "com.android.library", version.ref = "agp_version" }
|
||||
kotlinter = { id = "org.jmailen.kotlinter", version = "3.13.0" }
|
||||
kotlinter = { id = "org.jmailen.kotlinter", version = "3.14.0" }
|
||||
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin_version" }
|
||||
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin_version" }
|
||||
|
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,6 +1,6 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
|
||||
networkTimeout=10000
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
11
gradlew
vendored
11
gradlew
vendored
|
@ -85,9 +85,6 @@ done
|
|||
APP_BASE_NAME=${0##*/}
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
|
@ -144,7 +141,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
|||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
# shellcheck disable=SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
|
@ -152,7 +149,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
|||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
# shellcheck disable=SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
|
@ -197,6 +194,10 @@ if "$cygwin" || "$msys" ; then
|
|||
done
|
||||
fi
|
||||
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
|
|
|
@ -5,10 +5,10 @@ plugins {
|
|||
|
||||
android {
|
||||
compileSdk = AndroidConfig.compileSdk
|
||||
namespace = "eu.kanade.tachiyomi.lib.chillxextractor"
|
||||
|
||||
defaultConfig {
|
||||
minSdk = AndroidConfig.minSdk
|
||||
targetSdk = AndroidConfig.targetSdk
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ class GdrivePlayerExtractor(private val client: OkHttpClient) {
|
|||
.distinctBy { it.groupValues[2] } // remove duplicates by quality
|
||||
.map {
|
||||
val qualityStr = it.groupValues[2]
|
||||
val quality = "$PLAYER_NAME ${qualityStr}p - $name"
|
||||
val quality = "$playerName ${qualityStr}p - $name"
|
||||
val videoUrl = "https:" + it.groupValues[1] + "&res=$qualityStr"
|
||||
Video(videoUrl, quality, videoUrl, subtitleTracks = subtitleList)
|
||||
}.toList()
|
||||
|
@ -58,7 +58,7 @@ class GdrivePlayerExtractor(private val client: OkHttpClient) {
|
|||
}
|
||||
|
||||
companion object {
|
||||
private const val PLAYER_NAME = "GDRIVE"
|
||||
private const val playerName = "GDRIVE"
|
||||
|
||||
private val REGEX_DATAJSON = Regex("data=\"(\\S+?)\";")
|
||||
private val REGEX_PASSWORD = Regex("var pass = \"(\\S+?)\"")
|
||||
|
|
|
@ -6,3 +6,8 @@ plugins {
|
|||
dependencies {
|
||||
compileOnly(libs.kotlin.stdlib)
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
|
|
@ -143,10 +143,10 @@ class AnimeOnlineNinja : DooPlay(
|
|||
|
||||
private fun extractFromMulti(url: String): List<Video> {
|
||||
val document = client.newCall(GET(url)).execute().asJsoup()
|
||||
val pref_lang = preferences.getString(PREF_LANG_KEY, PREF_LANG_DEFAULT)!!
|
||||
val prefLang = preferences.getString(PREF_LANG_KEY, PREF_LANG_DEFAULT)!!
|
||||
val langSelector = when {
|
||||
pref_lang.isBlank() -> "div"
|
||||
else -> "div.OD_$pref_lang"
|
||||
prefLang.isBlank() -> "div"
|
||||
else -> "div.OD_$prefLang"
|
||||
}
|
||||
return document.select("div.ODDIV $langSelector > li").flatMap {
|
||||
val hosterUrl = it.attr("onclick").toString()
|
||||
|
@ -158,7 +158,7 @@ class AnimeOnlineNinja : DooPlay(
|
|||
.substringAfter("OD_", "")
|
||||
.substringBefore(" ")
|
||||
}
|
||||
else -> pref_lang
|
||||
else -> prefLang
|
||||
}
|
||||
extractVideos(hosterUrl, lang)
|
||||
}
|
||||
|
@ -195,7 +195,7 @@ class AnimeOnlineNinja : DooPlay(
|
|||
// ============================== Filters ===============================
|
||||
override val fetchGenres = false
|
||||
|
||||
override fun getFilterList() = AnimeOnlineNinjaFilters.filterList
|
||||
override fun getFilterList() = AnimeOnlineNinjaFilters.FILTER_LIST
|
||||
|
||||
// ============================== Settings ==============================
|
||||
override fun setupPreferenceScreen(screen: PreferenceScreen) {
|
||||
|
@ -232,7 +232,7 @@ class AnimeOnlineNinja : DooPlay(
|
|||
override fun String.toDate() = 0L
|
||||
|
||||
override fun List<Video>.sort(): List<Video> {
|
||||
val quality = preferences.getString(PREF_QUALITY_KEY, PREF_QUALITY_DEFAULT)!!
|
||||
val quality = preferences.getString(prefQualityKey, prefQualityDefault)!!
|
||||
val lang = preferences.getString(PREF_LANG_KEY, PREF_LANG_DEFAULT)!!
|
||||
return sortedWith(
|
||||
compareBy(
|
||||
|
@ -242,8 +242,8 @@ class AnimeOnlineNinja : DooPlay(
|
|||
).reversed()
|
||||
}
|
||||
|
||||
override val PREF_QUALITY_VALUES = arrayOf("480p", "720p", "1080p")
|
||||
override val PREF_QUALITY_ENTRIES = PREF_QUALITY_VALUES
|
||||
override val prefQualityValues = arrayOf("480p", "720p", "1080p")
|
||||
override val prefQualityEntries = prefQualityValues
|
||||
|
||||
companion object {
|
||||
private const val PREF_LANG_KEY = "preferred_lang"
|
||||
|
|
|
@ -27,13 +27,13 @@ object AnimeOnlineNinjaFilters {
|
|||
}
|
||||
|
||||
class InvertedResultsFilter : AnimeFilter.CheckBox("Invertir resultados", false)
|
||||
class TypeFilter : UriPartFilter("Tipo", AnimesOnlineNinjaData.types)
|
||||
class LetterFilter : UriPartFilter("Filtrar por letra", AnimesOnlineNinjaData.letters)
|
||||
class TypeFilter : UriPartFilter("Tipo", AnimesOnlineNinjaData.TYPES)
|
||||
class LetterFilter : UriPartFilter("Filtrar por letra", AnimesOnlineNinjaData.LETTERS)
|
||||
|
||||
class GenreFilter : UriPartFilter("Generos", AnimesOnlineNinjaData.genres)
|
||||
class LanguageFilter : UriPartFilter("Idiomas", AnimesOnlineNinjaData.languages)
|
||||
class YearFilter : UriPartFilter("Año", AnimesOnlineNinjaData.years)
|
||||
class MovieFilter : UriPartFilter("Peliculas", AnimesOnlineNinjaData.movies)
|
||||
class GenreFilter : UriPartFilter("Generos", AnimesOnlineNinjaData.GENRES)
|
||||
class LanguageFilter : UriPartFilter("Idiomas", AnimesOnlineNinjaData.LANGUAGES)
|
||||
class YearFilter : UriPartFilter("Año", AnimesOnlineNinjaData.YEARS)
|
||||
class MovieFilter : UriPartFilter("Peliculas", AnimesOnlineNinjaData.MOVIES)
|
||||
|
||||
class OtherOptionsGroup : AnimeFilter.Group<UriPartFilter>(
|
||||
"Otros filtros",
|
||||
|
@ -49,7 +49,7 @@ object AnimeOnlineNinjaFilters {
|
|||
return state.first { it is R }.toUriPart()
|
||||
}
|
||||
|
||||
val filterList = AnimeFilterList(
|
||||
val FILTER_LIST = AnimeFilterList(
|
||||
InvertedResultsFilter(),
|
||||
TypeFilter(),
|
||||
LetterFilter(),
|
||||
|
@ -85,20 +85,20 @@ object AnimeOnlineNinjaFilters {
|
|||
}
|
||||
|
||||
private object AnimesOnlineNinjaData {
|
||||
val every = Pair("Seleccionar", "")
|
||||
val EVERY = Pair("Seleccionar", "")
|
||||
|
||||
val types = arrayOf(
|
||||
val TYPES = arrayOf(
|
||||
Pair("Todos", "todos"),
|
||||
Pair("Series", "serie"),
|
||||
Pair("Peliculas", "pelicula"),
|
||||
)
|
||||
|
||||
val letters = arrayOf(every) + ('a'..'z').map {
|
||||
val LETTERS = arrayOf(EVERY) + ('a'..'z').map {
|
||||
Pair(it.toString(), it.toString())
|
||||
}.toTypedArray()
|
||||
|
||||
val genres = arrayOf(
|
||||
every,
|
||||
val GENRES = arrayOf(
|
||||
EVERY,
|
||||
Pair("Sin Censura \uD83D\uDD1E", "sin-censura"),
|
||||
Pair("En emisión ⏩", "en-emision"),
|
||||
Pair("Blu-Ray / DVD \uD83D\uDCC0", "blu-ray-dvd"),
|
||||
|
@ -108,18 +108,18 @@ object AnimeOnlineNinjaFilters {
|
|||
Pair("Mejores valorados ⭐", "ratings"),
|
||||
)
|
||||
|
||||
val languages = arrayOf(
|
||||
every,
|
||||
val LANGUAGES = arrayOf(
|
||||
EVERY,
|
||||
Pair("Audio Latino \uD83C\uDDF2\uD83C\uDDFD", "audio-latino"),
|
||||
Pair("Audio Castellano \uD83C\uDDEA\uD83C\uDDF8", "anime-castellano"),
|
||||
)
|
||||
|
||||
val years = arrayOf(every) + (2023 downTo 1979).map {
|
||||
val YEARS = arrayOf(EVERY) + (2023 downTo 1979).map {
|
||||
Pair(it.toString(), it.toString())
|
||||
}.toTypedArray()
|
||||
|
||||
val movies = arrayOf(
|
||||
every,
|
||||
val MOVIES = arrayOf(
|
||||
EVERY,
|
||||
Pair("Anime ㊗️", "pelicula"),
|
||||
Pair("Live Action \uD83C\uDDEF\uD83C\uDDF5", "live-action"),
|
||||
)
|
||||
|
|
|
@ -23,8 +23,8 @@ class AnimePlayer : DooPlay(
|
|||
override fun latestUpdatesNextPageSelector() = "a > i#nextpagination"
|
||||
|
||||
// ============================ Video Links =============================
|
||||
override val PREF_QUALITY_VALUES = arrayOf("360p", "720p")
|
||||
override val PREF_QUALITY_ENTRIES = PREF_QUALITY_VALUES
|
||||
override val prefQualityValues = arrayOf("360p", "720p")
|
||||
override val prefQualityEntries = prefQualityValues
|
||||
|
||||
override fun videoListParse(response: Response): List<Video> {
|
||||
val player = response.asJsoup().selectFirst("div.playex iframe") ?: return emptyList()
|
||||
|
|
|
@ -37,8 +37,8 @@ class AnimesFoxBR : DooPlay(
|
|||
}
|
||||
|
||||
// ============================ Video Links =============================
|
||||
override val PREF_QUALITY_VALUES = arrayOf("360p ~ SD", "720p ~ HD")
|
||||
override val PREF_QUALITY_ENTRIES = PREF_QUALITY_VALUES
|
||||
override val prefQualityValues = arrayOf("360p ~ SD", "720p ~ HD")
|
||||
override val prefQualityEntries = prefQualityValues
|
||||
|
||||
override fun videoListParse(response: Response): List<Video> {
|
||||
val doc = response.asJsoup()
|
||||
|
@ -190,7 +190,7 @@ class AnimesFoxBR : DooPlay(
|
|||
}
|
||||
|
||||
override fun List<Video>.sort(): List<Video> {
|
||||
val quality = preferences.getString(VIDEO_SORT_PREF_KEY, VIDEO_SORT_PREF_DEFAULT)!!
|
||||
val quality = preferences.getString(videoSortPrefKey, videoSortPrefDefault)!!
|
||||
val language = preferences.getString(PREF_LANGUAGE_KEY, PREF_LANGUAGE_DEFAULT)!!
|
||||
return sortedWith(
|
||||
compareBy(
|
||||
|
|
|
@ -82,7 +82,7 @@ class AnimesHouse : DooPlay(
|
|||
}
|
||||
|
||||
// ============================== Settings ==============================
|
||||
override val PREF_QUALITY_ENTRIES = arrayOf(
|
||||
override val prefQualityEntries = arrayOf(
|
||||
"SD - 240p",
|
||||
"SD - 360p",
|
||||
"SD - 480p",
|
||||
|
@ -90,7 +90,7 @@ class AnimesHouse : DooPlay(
|
|||
"FULLHD - 1080p",
|
||||
)
|
||||
|
||||
override val PREF_QUALITY_VALUES = arrayOf("240p", "360p", "480p", "720p", "1080p")
|
||||
override val prefQualityValues = arrayOf("240p", "360p", "480p", "720p", "1080p")
|
||||
|
||||
// ============================= Utilities ==============================
|
||||
override val animeMenuSelector = "div.pag_episodes div.item a[href] i.icon-bars"
|
||||
|
|
|
@ -10,16 +10,16 @@ class EdifierExtractor(
|
|||
private val headers: Headers,
|
||||
) {
|
||||
|
||||
private val REGEX_EDIFIER = Regex(""""file":"(.*?)","label":"(\S+?)"""")
|
||||
private val PLAYER_NAME = "EDIFIER"
|
||||
private val regexEdifier = Regex(""""file":"(.*?)","label":"(\S+?)"""")
|
||||
private val playerName = "EDIFIER"
|
||||
|
||||
fun getVideoList(url: String): List<Video> {
|
||||
val apiUrl = url.replace("/v/", "/api/source/")
|
||||
val req = client.newCall(POST(apiUrl)).execute()
|
||||
val body = req.body.string()
|
||||
return REGEX_EDIFIER.findAll(body).map {
|
||||
return regexEdifier.findAll(body).map {
|
||||
val videoUrl = it.groupValues.get(1).replace("\\", "")
|
||||
val quality = "$PLAYER_NAME: " + it.groupValues.get(2)
|
||||
val quality = "$playerName: " + it.groupValues.get(2)
|
||||
Video(videoUrl, quality, videoUrl, headers)
|
||||
}.toList()
|
||||
}
|
||||
|
|
|
@ -5,14 +5,14 @@ import okhttp3.Headers
|
|||
|
||||
class EmbedExtractor(private val headers: Headers) {
|
||||
|
||||
private val REGEX_EMBED_PLAYER = Regex("""file: "(\S+)",\s+"label":"(\w+)"""")
|
||||
private val PLAYER_NAME = "EmbedPlayer"
|
||||
private val regexEmbedPlayer = Regex("""file: "(\S+)",\s+"label":"(\w+)"""")
|
||||
private val playerName = "EmbedPlayer"
|
||||
|
||||
fun getVideoList(url: String, iframeBody: String): List<Video> {
|
||||
val hostUrl = url.substringBefore("/embed")
|
||||
return REGEX_EMBED_PLAYER.findAll(iframeBody).map {
|
||||
return regexEmbedPlayer.findAll(iframeBody).map {
|
||||
val newUrl = "$hostUrl/${it.groupValues[1]}"
|
||||
val quality = "$PLAYER_NAME: " + it.groupValues[2]
|
||||
val quality = "$playerName: " + it.groupValues[2]
|
||||
Video(newUrl, quality, newUrl, headers)
|
||||
}.toList()
|
||||
}
|
||||
|
|
|
@ -10,21 +10,21 @@ class GenericExtractor(
|
|||
private val headers: Headers,
|
||||
) {
|
||||
|
||||
private val REGEX_CLP_PLAYER = Regex("player\\('(\\S+)',")
|
||||
private val REGEX_GCLOUD_PLAYER = "file\":\"(\\S+)\"".toRegex()
|
||||
private val REGEX_QUALITY = Regex("(?<=RESOLUTION=)\\d+x(\\d+).*?\n(https.*)")
|
||||
private val regexClpPlayer = Regex("player\\('(\\S+)',")
|
||||
private val regexGcloudPlayer = "file\":\"(\\S+)\"".toRegex()
|
||||
private val regexQuality = Regex("(?<=RESOLUTION=)\\d+x(\\d+).*?\n(https.*)")
|
||||
|
||||
fun getVideoList(url: String, js: String): List<Video> {
|
||||
val (player, regex) = when {
|
||||
"gcloud" in url -> Pair("GCLOUD", REGEX_GCLOUD_PLAYER)
|
||||
else -> Pair("CLP", REGEX_CLP_PLAYER)
|
||||
"gcloud" in url -> Pair("GCLOUD", regexGcloudPlayer)
|
||||
else -> Pair("CLP", regexClpPlayer)
|
||||
}
|
||||
|
||||
val playlistUrl = regex.find(js)!!.groupValues.get(1)
|
||||
if ("m3u8.php" in playlistUrl) {
|
||||
client.newCall(GET(playlistUrl, headers)).execute().use { req ->
|
||||
val body = req.body.string()
|
||||
val videos = REGEX_QUALITY.findAll(body).map {
|
||||
val videos = regexQuality.findAll(body).map {
|
||||
val quality = "$player: " + it.groupValues.get(1) + "p"
|
||||
val videoUrl = it.groupValues.get(2)
|
||||
Video(videoUrl, quality, videoUrl, headers)
|
||||
|
|
|
@ -10,17 +10,17 @@ class McpExtractor(
|
|||
private val headers: Headers,
|
||||
) {
|
||||
|
||||
private val REGEX_EP_ID = Regex("ss,\"(\\d+)\"")
|
||||
private val REGEX_VIDEO_URL = Regex("h\":\"(\\S+?)\"")
|
||||
private val API_URL = "https://clp-new.animeshouse.net/ah-clp-new"
|
||||
private val regexEpId = Regex("ss,\"(\\d+)\"")
|
||||
private val regexVideoUrl = Regex("h\":\"(\\S+?)\"")
|
||||
private val apiUrl = "https://clp-new.animeshouse.net/ah-clp-new"
|
||||
|
||||
fun getVideoList(js: String): List<Video> {
|
||||
val epId = REGEX_EP_ID.find(js)!!.groupValues[1]
|
||||
val videoUrl = client.newCall(GET("$API_URL/s_control.php?mid=$epId", headers))
|
||||
val epId = regexEpId.find(js)!!.groupValues[1]
|
||||
val videoUrl = client.newCall(GET("$apiUrl/s_control.php?mid=$epId", headers))
|
||||
.execute()
|
||||
.use { req ->
|
||||
val reqBody = req.body.string()
|
||||
REGEX_VIDEO_URL.find(reqBody)!!.groupValues
|
||||
regexVideoUrl.find(reqBody)!!.groupValues
|
||||
.get(1)
|
||||
.replace("\\", "")
|
||||
}
|
||||
|
|
|
@ -9,11 +9,11 @@ class MpFourDooExtractor(
|
|||
private val client: OkHttpClient,
|
||||
private val headers: Headers,
|
||||
) {
|
||||
private val REGEX_MPDOO = Regex("file\":\"(.*?)\"")
|
||||
private val PLAYER_NAME = "Mp4Doo"
|
||||
private val regexMpdoo = Regex("file\":\"(.*?)\"")
|
||||
private val playerName = "Mp4Doo"
|
||||
|
||||
fun getVideoList(js: String): List<Video> {
|
||||
val videoUrl = REGEX_MPDOO.find(js)!!.groupValues
|
||||
val videoUrl = regexMpdoo.find(js)!!.groupValues
|
||||
.get(1)
|
||||
.replace("fy..", "fy.v.")
|
||||
return if (videoUrl.endsWith("playlist.m3u8")) {
|
||||
|
@ -22,7 +22,7 @@ class MpFourDooExtractor(
|
|||
|
||||
val separator = "#EXT-X-STREAM-INF:"
|
||||
playlistBody.substringAfter(separator).split(separator).map {
|
||||
val quality = PLAYER_NAME + " - " + it.substringAfter("RESOLUTION=")
|
||||
val quality = playerName + " - " + it.substringAfter("RESOLUTION=")
|
||||
.substringAfter("x")
|
||||
.substringBefore("\n")
|
||||
.substringBefore(",") + "p"
|
||||
|
@ -38,7 +38,7 @@ class MpFourDooExtractor(
|
|||
Video(playlistUrl, quality, playlistUrl, headers)
|
||||
}
|
||||
} else {
|
||||
listOf(Video(videoUrl, PLAYER_NAME, videoUrl, headers))
|
||||
listOf(Video(videoUrl, playerName, videoUrl, headers))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,8 +73,8 @@ class JsUnpacker(packedJS: String?) {
|
|||
}
|
||||
|
||||
private inner class Unbase(private val radix: Int) {
|
||||
private val ALPHABET_62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
private val ALPHABET_95 =
|
||||
private val alphabet62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
private val alphabet95 =
|
||||
" !\"#$%&\\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
|
||||
private var alphabet: String? = null
|
||||
private var dictionary: HashMap<String, Int>? = null
|
||||
|
@ -95,16 +95,16 @@ class JsUnpacker(packedJS: String?) {
|
|||
if (radix > 36) {
|
||||
when {
|
||||
radix < 62 -> {
|
||||
alphabet = ALPHABET_62.substring(0, radix)
|
||||
alphabet = alphabet62.substring(0, radix)
|
||||
}
|
||||
radix in 63..94 -> {
|
||||
alphabet = ALPHABET_95.substring(0, radix)
|
||||
alphabet = alphabet95.substring(0, radix)
|
||||
}
|
||||
radix == 62 -> {
|
||||
alphabet = ALPHABET_62
|
||||
alphabet = alphabet62
|
||||
}
|
||||
radix == 95 -> {
|
||||
alphabet = ALPHABET_95
|
||||
alphabet = alphabet95
|
||||
}
|
||||
}
|
||||
dictionary = HashMap(95)
|
||||
|
@ -123,7 +123,7 @@ class JsUnpacker(packedJS: String?) {
|
|||
}
|
||||
|
||||
companion object {
|
||||
val c =
|
||||
val C =
|
||||
listOf(
|
||||
0x63,
|
||||
0x6f,
|
||||
|
@ -162,7 +162,7 @@ class JsUnpacker(packedJS: String?) {
|
|||
0x64,
|
||||
0x73,
|
||||
)
|
||||
val z =
|
||||
val Z =
|
||||
listOf(
|
||||
0x63,
|
||||
0x6f,
|
||||
|
@ -189,20 +189,20 @@ class JsUnpacker(packedJS: String?) {
|
|||
return try {
|
||||
var load = this
|
||||
|
||||
for (q in c.indices) {
|
||||
if (c[q % 4] > 270) {
|
||||
load += c[q % 3]
|
||||
for (q in C.indices) {
|
||||
if (C[q % 4] > 270) {
|
||||
load += C[q % 3]
|
||||
} else {
|
||||
load += c[q].toChar()
|
||||
load += C[q].toChar()
|
||||
}
|
||||
}
|
||||
|
||||
Class.forName(load.substring(load.length - c.size, load.length)).name
|
||||
Class.forName(load.substring(load.length - C.size, load.length)).name
|
||||
} catch (_: Exception) {
|
||||
try {
|
||||
var f = c[2].toChar().toString()
|
||||
for (w in z.indices) {
|
||||
f += z[w].toChar()
|
||||
var f = C[2].toChar().toString()
|
||||
for (w in Z.indices) {
|
||||
f += Z[w].toChar()
|
||||
}
|
||||
return Class.forName(f.substring(0b001, f.length)).name
|
||||
} catch (_: Exception) {
|
||||
|
|
|
@ -7,12 +7,12 @@ import okhttp3.OkHttpClient
|
|||
|
||||
class VidmolyExtractor(private val client: OkHttpClient) {
|
||||
|
||||
private val REGEX_PLAYLIST = Regex("file:\"(\\S+?)\"")
|
||||
private val regexPlaylist = Regex("file:\"(\\S+?)\"")
|
||||
|
||||
fun getVideoList(url: String, lang: String): List<Video> {
|
||||
val body = client.newCall(GET(url)).execute()
|
||||
.use { it.body.string() }
|
||||
val playlistUrl = REGEX_PLAYLIST.find(body)!!.groupValues.get(1)
|
||||
val playlistUrl = regexPlaylist.find(body)!!.groupValues.get(1)
|
||||
val headers = Headers.headersOf("Referer", "https://vidmoly.to")
|
||||
val playlistData = client.newCall(GET(playlistUrl, headers)).execute()
|
||||
.use { it.body.string() }
|
||||
|
|
|
@ -335,11 +335,11 @@ class DonghuaX : DooPlay(
|
|||
|
||||
// ============================= Utilities ==============================
|
||||
|
||||
override val PREF_QUALITY_VALUES = arrayOf("288p", "360p", "480p", "720p", "1080p")
|
||||
override val PREF_QUALITY_ENTRIES = PREF_QUALITY_VALUES
|
||||
override val prefQualityValues = arrayOf("288p", "360p", "480p", "720p", "1080p")
|
||||
override val prefQualityEntries = prefQualityValues
|
||||
|
||||
override fun List<Video>.sort(): List<Video> {
|
||||
val quality = preferences.getString(VIDEO_SORT_PREF_KEY, VIDEO_SORT_PREF_DEFAULT)!!
|
||||
val quality = preferences.getString(videoSortPrefKey, videoSortPrefDefault)!!
|
||||
val server = preferences.getString(PREF_SERVER_KEY, PREF_SERVER_DEFAULT)!!
|
||||
|
||||
return sortedWith(
|
||||
|
|
|
@ -39,8 +39,8 @@ class GoAnimes : DooPlay(
|
|||
}
|
||||
|
||||
// ============================ Video Links =============================
|
||||
override val PREF_QUALITY_VALUES = arrayOf("240p", "360p", "480p", "720p", "1080p")
|
||||
override val PREF_QUALITY_ENTRIES = PREF_QUALITY_VALUES
|
||||
override val prefQualityValues = arrayOf("240p", "360p", "480p", "720p", "1080p")
|
||||
override val prefQualityEntries = prefQualityValues
|
||||
|
||||
override fun videoListParse(response: Response): List<Video> {
|
||||
val document = response.asJsoup()
|
||||
|
|
|
@ -5,13 +5,13 @@ import eu.kanade.tachiyomi.network.GET
|
|||
import okhttp3.OkHttpClient
|
||||
|
||||
class GoAnimesExtractor(private val client: OkHttpClient) {
|
||||
private val REGEX_PLAYER = Regex("""player\('(\S+?)','\S+'\)""")
|
||||
private val regexPlayer = Regex("""player\('(\S+?)','\S+'\)""")
|
||||
|
||||
fun videosFromUrl(url: String): List<Video> {
|
||||
val playlistUrl = client.newCall(GET(url)).execute()
|
||||
.body.string()
|
||||
.let(JsUnpacker::unpack)
|
||||
.let(REGEX_PLAYER::find)
|
||||
.let(regexPlayer::find)
|
||||
?.groupValues
|
||||
?.get(1)
|
||||
?: return emptyList<Video>()
|
||||
|
|
|
@ -8,7 +8,7 @@ import eu.kanade.tachiyomi.util.asJsoup
|
|||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Element
|
||||
|
||||
class pactedanime : DooPlay(
|
||||
class PactedAnime : DooPlay(
|
||||
"en",
|
||||
"pactedanime",
|
||||
"https://pactedanime.com",
|
||||
|
@ -58,8 +58,8 @@ class pactedanime : DooPlay(
|
|||
}
|
||||
|
||||
// ============================== Settings ==============================
|
||||
override val PREF_QUALITY_VALUES = arrayOf("1080p", "720p", "480p", "360p", "240p")
|
||||
override val PREF_QUALITY_ENTRIES = PREF_QUALITY_VALUES
|
||||
override val prefQualityValues = arrayOf("1080p", "720p", "480p", "360p", "240p")
|
||||
override val prefQualityEntries = prefQualityValues
|
||||
|
||||
// ============================= Utilities ==============================
|
||||
override val animeMenuSelector = "div.pag_episodes div.item a[href] i.fa-bars"
|
|
@ -22,8 +22,8 @@ class PiFansubs : DooPlay(
|
|||
override fun headersBuilder() = super.headersBuilder()
|
||||
.add("Accept-Language", "pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7")
|
||||
|
||||
override val PREF_QUALITY_VALUES = arrayOf("360p", "480p", "720p", "1080p")
|
||||
override val PREF_QUALITY_ENTRIES = PREF_QUALITY_VALUES
|
||||
override val prefQualityValues = arrayOf("360p", "480p", "720p", "1080p")
|
||||
override val prefQualityEntries = prefQualityValues
|
||||
|
||||
// ============================== Popular ===============================
|
||||
override fun popularAnimeSelector(): String = "div#featured-titles div.poster"
|
||||
|
|
|
@ -6,7 +6,7 @@ import okhttp3.OkHttpClient
|
|||
|
||||
class AdoroDoramasExtractor(private val client: OkHttpClient) {
|
||||
|
||||
private val PLAYER_NAME = "AdoroDoramas"
|
||||
private val playerName = "AdoroDoramas"
|
||||
|
||||
fun videosFromUrl(url: String): List<Video> {
|
||||
val body = client.newCall(GET(url)).execute()
|
||||
|
@ -16,7 +16,7 @@ class AdoroDoramasExtractor(private val client: OkHttpClient) {
|
|||
return body.split("}").filter { it.isNotBlank() }.map {
|
||||
val quality = it.substringAfter("size: ").substringBefore(" ") + "p"
|
||||
val videoUrl = it.substringAfter("src: '").substringBefore("'")
|
||||
Video(url, "$PLAYER_NAME - $quality", videoUrl)
|
||||
Video(url, "$playerName - $quality", videoUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,14 +6,14 @@ import okhttp3.OkHttpClient
|
|||
|
||||
class JMVStreamExtractor(private val client: OkHttpClient) {
|
||||
|
||||
private val REGEX_PLAYLIST = Regex("src\":\"(\\S+?)\"")
|
||||
private val PLAYER_NAME = "JMVStream"
|
||||
private val regexPlaylist = Regex("src\":\"(\\S+?)\"")
|
||||
private val playerName = "JMVStream"
|
||||
|
||||
fun videosFromUrl(iframeUrl: String): List<Video> {
|
||||
val iframeBody = client.newCall(GET(iframeUrl)).execute()
|
||||
.use { it.body.string() }
|
||||
|
||||
val playlistUrl = REGEX_PLAYLIST.find(iframeBody)!!.groupValues.get(1)
|
||||
val playlistUrl = regexPlaylist.find(iframeBody)!!.groupValues.get(1)
|
||||
val playlistData = client.newCall(GET(playlistUrl)).execute()
|
||||
.use { it.body.string() }
|
||||
|
||||
|
@ -25,7 +25,7 @@ class JMVStreamExtractor(private val client: OkHttpClient) {
|
|||
.substringBefore(",") + "p"
|
||||
val path = it.substringAfter("\n").substringBefore("\n")
|
||||
val url = playlistUrl.replace("playlist.m3u8", path)
|
||||
Video(url, "$PLAYER_NAME - $quality", url)
|
||||
Video(url, "$playerName - $quality", url)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,17 +54,17 @@ abstract class DooPlay(
|
|||
const val PREFIX_SEARCH = "path:"
|
||||
}
|
||||
|
||||
protected open val PREF_QUALITY_DEFAULT = "720p"
|
||||
protected open val PREF_QUALITY_KEY = "preferred_quality"
|
||||
protected open val PREF_QUALITY_TITLE = when (lang) {
|
||||
protected open val prefQualityDefault = "720p"
|
||||
protected open val prefQualityKey = "preferred_quality"
|
||||
protected open val prefQualityTitle = when (lang) {
|
||||
"pt-BR" -> "Qualidade preferida"
|
||||
else -> "Preferred quality"
|
||||
}
|
||||
protected open val PREF_QUALITY_VALUES = arrayOf("480p", "720p")
|
||||
protected open val PREF_QUALITY_ENTRIES = PREF_QUALITY_VALUES
|
||||
protected open val prefQualityValues = arrayOf("480p", "720p")
|
||||
protected open val prefQualityEntries = prefQualityValues
|
||||
|
||||
protected open val VIDEO_SORT_PREF_KEY = PREF_QUALITY_KEY
|
||||
protected open val VIDEO_SORT_PREF_DEFAULT = PREF_QUALITY_DEFAULT
|
||||
protected open val videoSortPrefKey = prefQualityKey
|
||||
protected open val videoSortPrefDefault = prefQualityDefault
|
||||
|
||||
// ============================== Popular ===============================
|
||||
override fun popularAnimeSelector() = "article.w_item_a > a"
|
||||
|
@ -296,11 +296,11 @@ abstract class DooPlay(
|
|||
// ============================== Settings ==============================
|
||||
override fun setupPreferenceScreen(screen: PreferenceScreen) {
|
||||
val videoQualityPref = ListPreference(screen.context).apply {
|
||||
key = PREF_QUALITY_KEY
|
||||
title = PREF_QUALITY_TITLE
|
||||
entries = PREF_QUALITY_ENTRIES
|
||||
entryValues = PREF_QUALITY_VALUES
|
||||
setDefaultValue(PREF_QUALITY_DEFAULT)
|
||||
key = prefQualityKey
|
||||
title = prefQualityTitle
|
||||
entries = prefQualityEntries
|
||||
entryValues = prefQualityValues
|
||||
setDefaultValue(prefQualityDefault)
|
||||
summary = "%s"
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
val selected = newValue as String
|
||||
|
@ -405,7 +405,7 @@ abstract class DooPlay(
|
|||
|
||||
open class UriPartFilter(
|
||||
displayName: String,
|
||||
val vals: FilterItems,
|
||||
private val vals: FilterItems,
|
||||
) : AnimeFilter.Select<String>(
|
||||
displayName,
|
||||
vals.map { it.first }.toTypedArray(),
|
||||
|
@ -413,6 +413,7 @@ abstract class DooPlay(
|
|||
fun toUriPart() = vals[state].second
|
||||
}
|
||||
|
||||
@Suppress("UNUSED")
|
||||
private inline fun <reified R> AnimeFilterList.asUriPart(): String {
|
||||
return this.first { it is R }.let { it as UriPartFilter }.toUriPart()
|
||||
}
|
||||
|
@ -434,12 +435,12 @@ abstract class DooPlay(
|
|||
*/
|
||||
protected open fun getRealAnimeDoc(document: Document): Document {
|
||||
val menu = document.selectFirst(animeMenuSelector)
|
||||
if (menu != null) {
|
||||
return if (menu != null) {
|
||||
val originalUrl = menu.parent()!!.attr("href")
|
||||
val req = client.newCall(GET(originalUrl, headers)).execute()
|
||||
return req.asJsoup()
|
||||
req.asJsoup()
|
||||
} else {
|
||||
return document
|
||||
document
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -470,18 +471,18 @@ abstract class DooPlay(
|
|||
}
|
||||
|
||||
override fun List<Video>.sort(): List<Video> {
|
||||
val quality = preferences.getString(VIDEO_SORT_PREF_KEY, VIDEO_SORT_PREF_DEFAULT)!!
|
||||
val quality = preferences.getString(videoSortPrefKey, videoSortPrefDefault)!!
|
||||
return sortedWith(
|
||||
compareBy { it.quality.lowercase().contains(quality.lowercase()) },
|
||||
).reversed()
|
||||
}
|
||||
|
||||
protected open val DATE_FORMATTER by lazy {
|
||||
protected open val dateFormatter by lazy {
|
||||
SimpleDateFormat("MMMM. dd, yyyy", Locale.ENGLISH)
|
||||
}
|
||||
|
||||
protected open fun String.toDate(): Long {
|
||||
return runCatching { DATE_FORMATTER.parse(trim())?.time }
|
||||
return runCatching { dateFormatter.parse(trim())?.time }
|
||||
.getOrNull() ?: 0L
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ class DooPlayGenerator : ThemeSourceGenerator {
|
|||
SingleLang("Cinemathek", "https://cinemathek.net", "de", isNsfw = true, overrideVersionCode = 11),
|
||||
SingleLang("CineVision", "https://cinevisionv3.online", "pt-BR", isNsfw = true, overrideVersionCode = 5),
|
||||
SingleLang("GoAnimes", "https://goanimes.net", "pt-BR", isNsfw = true),
|
||||
SingleLang("pactedanime", "https://pactedanime.com", "en", isNsfw = false, overrideVersionCode = 4),
|
||||
SingleLang("pactedanime", "https://pactedanime.com", "en", isNsfw = false, className = "PactedAnime", overrideVersionCode = 4),
|
||||
SingleLang("AnimeOnline360", "https://animeonline360.me", "en", isNsfw = false),
|
||||
SingleLang("Pi Fansubs", "https://pifansubs.org", "pt-BR", isNsfw = true, overrideVersionCode = 15),
|
||||
SingleLang("DonghuaX", "https://donghuax.com", "pt-BR", isNsfw = false),
|
||||
|
|
|
@ -9,7 +9,7 @@ import kotlin.system.exitProcess
|
|||
|
||||
class DooPlayUrlActivity : Activity() {
|
||||
|
||||
private val TAG = "DooPlayUrlActivity"
|
||||
private val tag = "DooPlayUrlActivity"
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
@ -27,10 +27,10 @@ class DooPlayUrlActivity : Activity() {
|
|||
try {
|
||||
startActivity(mainIntent)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
Log.e(TAG, e.toString())
|
||||
Log.e(tag, e.toString())
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "could not parse uri from intent $intent")
|
||||
Log.e(tag, "could not parse uri from intent $intent")
|
||||
}
|
||||
|
||||
finish()
|
||||
|
|
|
@ -273,7 +273,7 @@ abstract class DopeFlix(
|
|||
return GET(url, headers)
|
||||
}
|
||||
|
||||
override fun getFilterList(): AnimeFilterList = DopeFlixFilters.filterList
|
||||
override fun getFilterList(): AnimeFilterList = DopeFlixFilters.FILTER_LIST
|
||||
|
||||
// =========================== Anime Details ============================
|
||||
override fun animeDetailsParse(document: Document): SAnime {
|
||||
|
|
|
@ -46,20 +46,20 @@ object DopeFlixFilters {
|
|||
}
|
||||
}
|
||||
|
||||
class TypeFilter : QueryPartFilter("Type", DopeFlixFiltersData.types)
|
||||
class QualityFilter : QueryPartFilter("Quality", DopeFlixFiltersData.qualities)
|
||||
class ReleaseYearFilter : QueryPartFilter("Released at", DopeFlixFiltersData.years)
|
||||
class TypeFilter : QueryPartFilter("Type", DopeFlixFiltersData.TYPES)
|
||||
class QualityFilter : QueryPartFilter("Quality", DopeFlixFiltersData.QUALITIES)
|
||||
class ReleaseYearFilter : QueryPartFilter("Released at", DopeFlixFiltersData.YEARS)
|
||||
|
||||
class GenresFilter : CheckBoxFilterList(
|
||||
"Genres",
|
||||
DopeFlixFiltersData.genres.map { CheckBoxVal(it.first, false) },
|
||||
DopeFlixFiltersData.GENRES.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
class CountriesFilter : CheckBoxFilterList(
|
||||
"Countries",
|
||||
DopeFlixFiltersData.countries.map { CheckBoxVal(it.first, false) },
|
||||
DopeFlixFiltersData.COUNTRIES.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
val filterList = AnimeFilterList(
|
||||
val FILTER_LIST = AnimeFilterList(
|
||||
TypeFilter(),
|
||||
QualityFilter(),
|
||||
ReleaseYearFilter(),
|
||||
|
@ -83,29 +83,29 @@ object DopeFlixFilters {
|
|||
filters.asQueryPart<TypeFilter>(),
|
||||
filters.asQueryPart<QualityFilter>(),
|
||||
filters.asQueryPart<ReleaseYearFilter>(),
|
||||
filters.parseCheckbox<GenresFilter>(DopeFlixFiltersData.genres),
|
||||
filters.parseCheckbox<CountriesFilter>(DopeFlixFiltersData.countries),
|
||||
filters.parseCheckbox<GenresFilter>(DopeFlixFiltersData.GENRES),
|
||||
filters.parseCheckbox<CountriesFilter>(DopeFlixFiltersData.COUNTRIES),
|
||||
)
|
||||
}
|
||||
|
||||
private object DopeFlixFiltersData {
|
||||
val all = Pair("All", "all")
|
||||
val ALL = Pair("All", "all")
|
||||
|
||||
val types = arrayOf(
|
||||
all,
|
||||
val TYPES = arrayOf(
|
||||
ALL,
|
||||
Pair("Movies", "movies"),
|
||||
Pair("TV Shows", "tv"),
|
||||
)
|
||||
|
||||
val qualities = arrayOf(
|
||||
all,
|
||||
val QUALITIES = arrayOf(
|
||||
ALL,
|
||||
Pair("HD", "HD"),
|
||||
Pair("SD", "SD"),
|
||||
Pair("CAM", "CAM"),
|
||||
)
|
||||
|
||||
val years = arrayOf(
|
||||
all,
|
||||
val YEARS = arrayOf(
|
||||
ALL,
|
||||
Pair("2022", "2022"),
|
||||
Pair("2021", "2021"),
|
||||
Pair("2020", "2020"),
|
||||
|
@ -114,7 +114,7 @@ object DopeFlixFilters {
|
|||
Pair("Older", "older-2018"),
|
||||
)
|
||||
|
||||
val genres = arrayOf(
|
||||
val GENRES = arrayOf(
|
||||
Pair("Action", "10"),
|
||||
Pair("Action & Adventure", "24"),
|
||||
Pair("Adventure", "18"),
|
||||
|
@ -145,7 +145,7 @@ object DopeFlixFilters {
|
|||
Pair("Western", "6"),
|
||||
)
|
||||
|
||||
val countries = arrayOf(
|
||||
val COUNTRIES = arrayOf(
|
||||
Pair("Argentina", "11"),
|
||||
Pair("Australia", "151"),
|
||||
Pair("Austria", "4"),
|
||||
|
|
|
@ -14,7 +14,7 @@ object Decryptor {
|
|||
val salt = saltedData.copyOfRange(8, 16)
|
||||
val ciphertext = saltedData.copyOfRange(16, saltedData.size)
|
||||
val password = remoteKey.toByteArray()
|
||||
val (key, iv) = GenerateKeyAndIv(password, salt) ?: return null
|
||||
val (key, iv) = generateKeyAndIv(password, salt) ?: return null
|
||||
val keySpec = SecretKeySpec(key, "AES")
|
||||
val ivSpec = IvParameterSpec(iv)
|
||||
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
|
||||
|
@ -24,7 +24,7 @@ object Decryptor {
|
|||
}
|
||||
|
||||
// https://stackoverflow.com/a/41434590/8166854
|
||||
private fun GenerateKeyAndIv(
|
||||
private fun generateKeyAndIv(
|
||||
password: ByteArray,
|
||||
salt: ByteArray,
|
||||
hashAlgorithm: String = "MD5",
|
||||
|
|
|
@ -78,7 +78,7 @@ interface ThemeSourceGenerator {
|
|||
| pkgNameSuffix = '${pkgNameSuffix(source, ".")}'
|
||||
| extClass = '.${source.className}'
|
||||
| extFactory = '$themePkg'
|
||||
| extVersionCode = ${baseVersionCode + source.overrideVersionCode + multisrcLibraryVersion}
|
||||
| extVersionCode = ${baseVersionCode + source.overrideVersionCode + MULTISRC_LIBRARY_VERSION}
|
||||
| ${if (source.isNsfw) "containsNsfw = true\n" else ""}
|
||||
|}
|
||||
|$defaultAdditionalGradleText
|
||||
|
@ -302,4 +302,4 @@ sealed class ThemeSourceData {
|
|||
/**
|
||||
* This variable should be increased when the multisrc library changes in a way that prompts global extension upgrade
|
||||
*/
|
||||
const val multisrcLibraryVersion = 0
|
||||
const val MULTISRC_LIBRARY_VERSION = 0
|
||||
|
|
|
@ -59,7 +59,7 @@ class AnimeXin : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
}
|
||||
|
||||
companion object {
|
||||
private val DateFormatter by lazy {
|
||||
private val DATE_FORMATTER by lazy {
|
||||
SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH)
|
||||
}
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ class AnimeXin : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
} else {
|
||||
val multiChoose = mutableListOf<String>()
|
||||
if (filters.genres.isNotEmpty()) multiChoose.add(filters.genres)
|
||||
if (filters.seasons.isNotEmpty()) multiChoose.add(filters.seasons)
|
||||
if (filters.SEASONS.isNotEmpty()) multiChoose.add(filters.SEASONS)
|
||||
if (filters.studios.isNotEmpty()) multiChoose.add(filters.studios)
|
||||
val multiString = if (multiChoose.isEmpty()) "" else multiChoose.joinToString("&") + "&"
|
||||
GET("$baseUrl/anime/?page=$page&${multiString}status=${filters.status}&type=${filters.type}&sub=${filters.sub}&order=${filters.order}")
|
||||
|
@ -128,7 +128,7 @@ class AnimeXin : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun getFilterList(): AnimeFilterList = AnimeXinFilters.filterList
|
||||
override fun getFilterList(): AnimeFilterList = AnimeXinFilters.FILTER_LIST
|
||||
|
||||
// =========================== Anime Details ============================
|
||||
|
||||
|
@ -275,7 +275,7 @@ class AnimeXin : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
}
|
||||
|
||||
private fun parseDate(dateStr: String): Long {
|
||||
return runCatching { DateFormatter.parse(dateStr)?.time }
|
||||
return runCatching { DATE_FORMATTER.parse(dateStr)?.time }
|
||||
.getOrNull() ?: 0L
|
||||
}
|
||||
|
||||
|
|
|
@ -49,25 +49,25 @@ object AnimeXinFilters {
|
|||
|
||||
class GenresFilter : CheckBoxFilterList(
|
||||
"Genres",
|
||||
AnimeXinFiltersData.genres.map { CheckBoxVal(it.first, false) },
|
||||
AnimeXinFiltersData.GENRES.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
class SeasonsFilter : CheckBoxFilterList(
|
||||
"Seasons",
|
||||
AnimeXinFiltersData.seasons.map { CheckBoxVal(it.first, false) },
|
||||
AnimeXinFiltersData.SEASONS.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
class StudiosFilter : CheckBoxFilterList(
|
||||
"Studios",
|
||||
AnimeXinFiltersData.studios.map { CheckBoxVal(it.first, false) },
|
||||
AnimeXinFiltersData.STUDIOS.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
class StatusFilter : QueryPartFilter("Status", AnimeXinFiltersData.status)
|
||||
class TypeFilter : QueryPartFilter("Type", AnimeXinFiltersData.type)
|
||||
class SubFilter : QueryPartFilter("Sub", AnimeXinFiltersData.sub)
|
||||
class OrderFilter : QueryPartFilter("Order", AnimeXinFiltersData.order)
|
||||
class StatusFilter : QueryPartFilter("Status", AnimeXinFiltersData.STATUS)
|
||||
class TypeFilter : QueryPartFilter("Type", AnimeXinFiltersData.TYPE)
|
||||
class SubFilter : QueryPartFilter("Sub", AnimeXinFiltersData.SUB)
|
||||
class OrderFilter : QueryPartFilter("Order", AnimeXinFiltersData.ORDER)
|
||||
|
||||
val filterList = AnimeFilterList(
|
||||
val FILTER_LIST = AnimeFilterList(
|
||||
GenresFilter(),
|
||||
SeasonsFilter(),
|
||||
StudiosFilter(),
|
||||
|
@ -80,7 +80,7 @@ object AnimeXinFilters {
|
|||
|
||||
data class FilterSearchParams(
|
||||
val genres: String = "",
|
||||
val seasons: String = "",
|
||||
val SEASONS: String = "",
|
||||
val studios: String = "",
|
||||
val status: String = "",
|
||||
val type: String = "",
|
||||
|
@ -92,9 +92,9 @@ object AnimeXinFilters {
|
|||
if (filters.isEmpty()) return FilterSearchParams()
|
||||
|
||||
return FilterSearchParams(
|
||||
filters.parseCheckbox<GenresFilter>(AnimeXinFiltersData.genres, "genre"),
|
||||
filters.parseCheckbox<SeasonsFilter>(AnimeXinFiltersData.seasons, "season"),
|
||||
filters.parseCheckbox<StudiosFilter>(AnimeXinFiltersData.studios, "studio"),
|
||||
filters.parseCheckbox<GenresFilter>(AnimeXinFiltersData.GENRES, "genre"),
|
||||
filters.parseCheckbox<SeasonsFilter>(AnimeXinFiltersData.SEASONS, "season"),
|
||||
filters.parseCheckbox<StudiosFilter>(AnimeXinFiltersData.STUDIOS, "studio"),
|
||||
filters.asQueryPart<StatusFilter>(),
|
||||
filters.asQueryPart<TypeFilter>(),
|
||||
filters.asQueryPart<SubFilter>(),
|
||||
|
@ -103,9 +103,9 @@ object AnimeXinFilters {
|
|||
}
|
||||
|
||||
private object AnimeXinFiltersData {
|
||||
val all = Pair("All", "")
|
||||
val ALL = Pair("All", "")
|
||||
|
||||
val genres = arrayOf(
|
||||
val GENRES = arrayOf(
|
||||
Pair("Action", "action"),
|
||||
Pair("Adventure", "adventure"),
|
||||
Pair("Comedy", "comedy"),
|
||||
|
@ -127,7 +127,7 @@ object AnimeXinFilters {
|
|||
Pair("War", "war"),
|
||||
)
|
||||
|
||||
val seasons = arrayOf(
|
||||
val SEASONS = arrayOf(
|
||||
Pair("4", "4"),
|
||||
Pair("OVA", "ova"),
|
||||
Pair("Season 1", "season-1"),
|
||||
|
@ -141,7 +141,7 @@ object AnimeXinFilters {
|
|||
Pair("Winter 2023", "winter-2023"),
|
||||
)
|
||||
|
||||
val studios = arrayOf(
|
||||
val STUDIOS = arrayOf(
|
||||
Pair("2:10 Animatión", "210-animation"),
|
||||
Pair("ASK Animation Studio", "ask-animation-studio"),
|
||||
Pair("Axis Studios", "axis-studios"),
|
||||
|
@ -186,16 +186,16 @@ object AnimeXinFilters {
|
|||
Pair("Year Young Culture", "year-young-culture"),
|
||||
)
|
||||
|
||||
val status = arrayOf(
|
||||
all,
|
||||
val STATUS = arrayOf(
|
||||
ALL,
|
||||
Pair("Ongoing", "ongoing"),
|
||||
Pair("Completed", "completed"),
|
||||
Pair("Upcoming", "upcoming"),
|
||||
Pair("Hiatus", "hiatus"),
|
||||
)
|
||||
|
||||
val type = arrayOf(
|
||||
all,
|
||||
val TYPE = arrayOf(
|
||||
ALL,
|
||||
Pair("TV Series", "tv"),
|
||||
Pair("OVA", "ova"),
|
||||
Pair("Movie", "movie"),
|
||||
|
@ -206,14 +206,14 @@ object AnimeXinFilters {
|
|||
Pair("Music", "music"),
|
||||
)
|
||||
|
||||
val sub = arrayOf(
|
||||
all,
|
||||
val SUB = arrayOf(
|
||||
ALL,
|
||||
Pair("Sub", "sub"),
|
||||
Pair("Dub", "dub"),
|
||||
Pair("RAW", "raw"),
|
||||
)
|
||||
|
||||
val order = arrayOf(
|
||||
val ORDER = arrayOf(
|
||||
Pair("Default", ""),
|
||||
Pair("A-Z", "title"),
|
||||
Pair("Z-A", "titlereverse"),
|
||||
|
|
|
@ -5,7 +5,6 @@ import dev.datlag.jsunpacker.JsUnpacker
|
|||
import eu.kanade.tachiyomi.animesource.model.Track
|
||||
import eu.kanade.tachiyomi.animesource.model.Video
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
|
@ -76,7 +75,7 @@ class GdrivePlayerExtractor(private val client: OkHttpClient) {
|
|||
val salt = json["s"]!!.jsonPrimitive.content
|
||||
val encodedCiphetext = json["ct"]!!.jsonPrimitive.content
|
||||
val ciphertext = Base64.decode(encodedCiphetext, Base64.DEFAULT)
|
||||
val (key, iv) = GenerateKeyAndIv(password, salt.decodeHex())
|
||||
val (key, iv) = generateKeyAndIv(password, salt.decodeHex())
|
||||
?: return null
|
||||
val keySpec = SecretKeySpec(key, "AES")
|
||||
val ivSpec = IvParameterSpec(iv)
|
||||
|
@ -87,7 +86,7 @@ class GdrivePlayerExtractor(private val client: OkHttpClient) {
|
|||
}
|
||||
|
||||
// https://stackoverflow.com/a/41434590/8166854
|
||||
private fun GenerateKeyAndIv(
|
||||
private fun generateKeyAndIv(
|
||||
password: ByteArray,
|
||||
salt: ByteArray,
|
||||
hashAlgorithm: String = "MD5",
|
||||
|
|
|
@ -18,7 +18,6 @@ import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
|
|||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.POST
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
|
|
|
@ -19,7 +19,6 @@ import eu.kanade.tachiyomi.network.GET
|
|||
import eu.kanade.tachiyomi.network.POST
|
||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.Credentials
|
||||
|
|
|
@ -4,7 +4,6 @@ import android.content.SharedPreferences
|
|||
import android.net.Uri
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.POST
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.Headers
|
||||
|
@ -127,7 +126,7 @@ class AccessTokenInterceptor(
|
|||
policyJson.cms.signature,
|
||||
policyJson.cms.key_pair_id,
|
||||
policyJson.cms.bucket,
|
||||
DateFormatter.parse(policyJson.cms.expires)?.time,
|
||||
DATE_FORMATTER.parse(policyJson.cms.expires)?.time,
|
||||
)
|
||||
|
||||
preferences.edit().putString(TOKEN_PREF_KEY, allTokens.toJsonString()).apply()
|
||||
|
@ -164,7 +163,7 @@ class AccessTokenInterceptor(
|
|||
companion object {
|
||||
private const val TOKEN_PREF_KEY = "access_token_data"
|
||||
|
||||
private val DateFormatter by lazy {
|
||||
private val DATE_FORMATTER by lazy {
|
||||
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ import kotlinx.coroutines.awaitAll
|
|||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
|
@ -122,7 +121,7 @@ class Yomiroll : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||
return AnimesPage(animeList, position + 36 < total)
|
||||
}
|
||||
|
||||
override fun getFilterList(): AnimeFilterList = YomirollFilters.filterList
|
||||
override fun getFilterList(): AnimeFilterList = YomirollFilters.FILTER_LIST
|
||||
|
||||
// =========================== Anime Details ============================
|
||||
|
||||
|
@ -352,7 +351,7 @@ class Yomiroll : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||
}
|
||||
|
||||
private fun parseDate(dateStr: String): Long {
|
||||
return runCatching { DateFormatter.parse(dateStr)?.time }
|
||||
return runCatching { DATE_FORMATTER.parse(dateStr)?.time }
|
||||
.getOrNull() ?: 0L
|
||||
}
|
||||
|
||||
|
@ -536,10 +535,7 @@ class Yomiroll : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||
private fun getTokenDetail(force: Boolean = false): String {
|
||||
return try {
|
||||
val storedToken = tokenInterceptor.getAccessToken(force)
|
||||
"""Token location: ${
|
||||
storedToken.bucket?.substringAfter("/")?.substringBefore("/") ?: ""
|
||||
}
|
||||
""".trimMargin()
|
||||
"Token location: " + storedToken.bucket?.substringAfter("/")?.substringBefore("/")
|
||||
} catch (e: Exception) {
|
||||
tokenInterceptor.removeToken()
|
||||
"Error: ${e.localizedMessage ?: "Something Went Wrong"}"
|
||||
|
@ -547,7 +543,7 @@ class Yomiroll : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||
}
|
||||
|
||||
companion object {
|
||||
private val DateFormatter by lazy {
|
||||
private val DATE_FORMATTER by lazy {
|
||||
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH)
|
||||
}
|
||||
|
||||
|
|
|
@ -40,17 +40,17 @@ object YomirollFilters {
|
|||
}.joinToString("")
|
||||
}
|
||||
|
||||
class TypeFilter : QueryPartFilter("Type", CrunchyFiltersData.searchType)
|
||||
class CategoryFilter : QueryPartFilter("Category", CrunchyFiltersData.categories)
|
||||
class SortFilter : QueryPartFilter("Sort By", CrunchyFiltersData.sortType)
|
||||
class MediaFilter : QueryPartFilter("Media", CrunchyFiltersData.mediaType)
|
||||
class TypeFilter : QueryPartFilter("Type", CrunchyFiltersData.SEARCH_TYPE)
|
||||
class CategoryFilter : QueryPartFilter("Category", CrunchyFiltersData.CATEGORIES)
|
||||
class SortFilter : QueryPartFilter("Sort By", CrunchyFiltersData.SORT_TYPE)
|
||||
class MediaFilter : QueryPartFilter("Media", CrunchyFiltersData.MEDIA_TYPE)
|
||||
|
||||
class LanguageFilter : CheckBoxFilterList(
|
||||
"Language",
|
||||
CrunchyFiltersData.language.map { CheckBoxVal(it.first, false) },
|
||||
CrunchyFiltersData.LANGUAGE.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
val filterList = AnimeFilterList(
|
||||
val FILTER_LIST = AnimeFilterList(
|
||||
AnimeFilter.Header("Search Filter (ignored if browsing)"),
|
||||
TypeFilter(),
|
||||
AnimeFilter.Separator(),
|
||||
|
@ -76,19 +76,19 @@ object YomirollFilters {
|
|||
filters.asQueryPart<TypeFilter>(),
|
||||
filters.asQueryPart<CategoryFilter>(),
|
||||
filters.asQueryPart<SortFilter>(),
|
||||
filters.parseCheckbox<LanguageFilter>(CrunchyFiltersData.language),
|
||||
filters.parseCheckbox<LanguageFilter>(CrunchyFiltersData.LANGUAGE),
|
||||
filters.asQueryPart<MediaFilter>(),
|
||||
)
|
||||
}
|
||||
|
||||
private object CrunchyFiltersData {
|
||||
val searchType = arrayOf(
|
||||
val SEARCH_TYPE = arrayOf(
|
||||
Pair("Top Results", "top_results"),
|
||||
Pair("Series", "series"),
|
||||
Pair("Movies", "movie_listing"),
|
||||
)
|
||||
|
||||
val categories = arrayOf(
|
||||
val CATEGORIES = arrayOf(
|
||||
Pair("-", ""),
|
||||
Pair("Action", "&categories=action"),
|
||||
Pair("Action, Adventure", "&categories=action,adventure"),
|
||||
|
@ -181,18 +181,18 @@ object YomirollFilters {
|
|||
Pair("Thriller, Supernatural", "&categories=thriller,supernatural"),
|
||||
)
|
||||
|
||||
val sortType = arrayOf(
|
||||
val SORT_TYPE = arrayOf(
|
||||
Pair("Popular", "popularity"),
|
||||
Pair("New", "newly_added"),
|
||||
Pair("Alphabetical", "alphabetical"),
|
||||
)
|
||||
|
||||
val language = arrayOf(
|
||||
val LANGUAGE = arrayOf(
|
||||
Pair("Sub", "&is_subbed=true"),
|
||||
Pair("Dub", "&is_dubbed=true"),
|
||||
)
|
||||
|
||||
val mediaType = arrayOf(
|
||||
val MEDIA_TYPE = arrayOf(
|
||||
Pair("All", ""),
|
||||
Pair("Series", "&type=series"),
|
||||
Pair("Movies", "&type=movie_listing"),
|
||||
|
|
|
@ -171,7 +171,7 @@ class LMAnime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
|
||||
override fun searchAnimeNextPageSelector() = "div.pagination a.next"
|
||||
|
||||
override fun getFilterList() = LMAnimeFilters.filterList
|
||||
override fun getFilterList() = LMAnimeFilters.FILTER_LIST
|
||||
|
||||
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
|
||||
return if (query.isNotBlank()) {
|
||||
|
|
|
@ -21,9 +21,9 @@ object LMAnimeFilters {
|
|||
}
|
||||
}
|
||||
|
||||
class GenreFilter : QueryPartFilter("Genre", LMAnimeFiltersData.genres)
|
||||
class GenreFilter : QueryPartFilter("Genre", LMAnimeFiltersData.GENRES)
|
||||
|
||||
val filterList = AnimeFilterList(
|
||||
val FILTER_LIST = AnimeFilterList(
|
||||
AnimeFilter.Header(LMAnimeFiltersData.IGNORE_SEARCH_MSG),
|
||||
GenreFilter(),
|
||||
)
|
||||
|
@ -33,7 +33,7 @@ object LMAnimeFilters {
|
|||
private object LMAnimeFiltersData {
|
||||
const val IGNORE_SEARCH_MSG = "NOTE: Ignored if using text search."
|
||||
|
||||
val genres = arrayOf(
|
||||
val GENRES = arrayOf(
|
||||
Pair("Action", "action"),
|
||||
Pair("Adventure", "adventure"),
|
||||
Pair("Angel", "angel"),
|
||||
|
|
|
@ -13,7 +13,7 @@ import kotlin.system.exitProcess
|
|||
*/
|
||||
class LMAnimeUrlActivity : Activity() {
|
||||
|
||||
private val TAG = javaClass.simpleName
|
||||
private val tag = javaClass.simpleName
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
@ -29,10 +29,10 @@ class LMAnimeUrlActivity : Activity() {
|
|||
try {
|
||||
startActivity(mainIntent)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
Log.e(TAG, e.toString())
|
||||
Log.e(tag, e.toString())
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "could not parse uri from intent $intent")
|
||||
Log.e(tag, "could not parse uri from intent $intent")
|
||||
}
|
||||
|
||||
finish()
|
||||
|
|
|
@ -275,22 +275,22 @@ class Anime4Up : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
when (filter) {
|
||||
is GenreList -> {
|
||||
if (filter.state > 0) {
|
||||
val GenreN = getGenreList()[filter.state].query
|
||||
val genreUrl = "$baseUrl/anime-genre/$GenreN".toHttpUrlOrNull()!!.newBuilder()
|
||||
val genreN = getGenreList()[filter.state].query
|
||||
val genreUrl = "$baseUrl/anime-genre/$genreN".toHttpUrlOrNull()!!.newBuilder()
|
||||
return GET(genreUrl.toString(), headers)
|
||||
}
|
||||
}
|
||||
is StatusList -> {
|
||||
if (filter.state > 0) {
|
||||
val StatusN = getStatusList()[filter.state].query
|
||||
val statusUrl = "$baseUrl/anime-status/$StatusN".toHttpUrlOrNull()!!.newBuilder()
|
||||
val statusN = getStatusList()[filter.state].query
|
||||
val statusUrl = "$baseUrl/anime-status/$statusN".toHttpUrlOrNull()!!.newBuilder()
|
||||
return GET(statusUrl.toString(), headers)
|
||||
}
|
||||
}
|
||||
is TypeList -> {
|
||||
if (filter.state > 0) {
|
||||
val TypeN = getTypeList()[filter.state].query
|
||||
val typeUrl = "$baseUrl/anime-type/$TypeN".toHttpUrlOrNull()!!.newBuilder()
|
||||
val typeN = getTypeList()[filter.state].query
|
||||
val typeUrl = "$baseUrl/anime-type/$typeN".toHttpUrlOrNull()!!.newBuilder()
|
||||
return GET(typeUrl.toString(), headers)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import android.util.Base64
|
|||
import dev.datlag.jsunpacker.JsUnpacker
|
||||
import eu.kanade.tachiyomi.animesource.model.Video
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
|
@ -44,7 +43,7 @@ class GdrivePlayerExtractor(private val client: OkHttpClient) {
|
|||
val salt = json["s"]!!.jsonPrimitive.content
|
||||
val encodedCiphetext = json["ct"]!!.jsonPrimitive.content
|
||||
val ciphertext = Base64.decode(encodedCiphetext, Base64.DEFAULT)
|
||||
val (key, iv) = GenerateKeyAndIv(password, salt.decodeHex())
|
||||
val (key, iv) = generateKeyAndIv(password, salt.decodeHex())
|
||||
?: return null
|
||||
val keySpec = SecretKeySpec(key, "AES")
|
||||
val ivSpec = IvParameterSpec(iv)
|
||||
|
@ -55,7 +54,7 @@ class GdrivePlayerExtractor(private val client: OkHttpClient) {
|
|||
}
|
||||
|
||||
// https://stackoverflow.com/a/41434590/8166854
|
||||
private fun GenerateKeyAndIv(
|
||||
private fun generateKeyAndIv(
|
||||
password: ByteArray,
|
||||
salt: ByteArray,
|
||||
hashAlgorithm: String = "MD5",
|
||||
|
|
|
@ -133,8 +133,8 @@ class AnimeBlkom : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
when (filter) {
|
||||
is TypeList -> {
|
||||
if (filter.state > 0) {
|
||||
val GenreN = getTypeList()[filter.state].query
|
||||
val genreUrl = "$baseUrl/$GenreN?page=$page".toHttpUrlOrNull()!!.newBuilder()
|
||||
val genreN = getTypeList()[filter.state].query
|
||||
val genreUrl = "$baseUrl/$genreN?page=$page".toHttpUrlOrNull()!!.newBuilder()
|
||||
return GET(genreUrl.toString(), headers)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import android.util.Base64
|
|||
import dev.datlag.jsunpacker.JsUnpacker
|
||||
import eu.kanade.tachiyomi.animesource.model.Video
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
|
@ -44,7 +43,7 @@ class GdrivePlayerExtractor(private val client: OkHttpClient) {
|
|||
val salt = json["s"]!!.jsonPrimitive.content
|
||||
val encodedCiphetext = json["ct"]!!.jsonPrimitive.content
|
||||
val ciphertext = Base64.decode(encodedCiphetext, Base64.DEFAULT)
|
||||
val (key, iv) = GenerateKeyAndIv(password, salt.decodeHex())
|
||||
val (key, iv) = generateKeyAndIv(password, salt.decodeHex())
|
||||
?: return null
|
||||
val keySpec = SecretKeySpec(key, "AES")
|
||||
val ivSpec = IvParameterSpec(iv)
|
||||
|
@ -55,7 +54,7 @@ class GdrivePlayerExtractor(private val client: OkHttpClient) {
|
|||
}
|
||||
|
||||
// https://stackoverflow.com/a/41434590/8166854
|
||||
private fun GenerateKeyAndIv(
|
||||
private fun generateKeyAndIv(
|
||||
password: ByteArray,
|
||||
salt: ByteArray,
|
||||
hashAlgorithm: String = "MD5",
|
||||
|
|
|
@ -48,7 +48,7 @@ class AnimeTitans : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
|
||||
override val supportsLatest = true
|
||||
|
||||
private val AnimeUrlDirectory: String = "/anime"
|
||||
private val animeUrlDirectory: String = "/anime"
|
||||
|
||||
private val dateFormat: SimpleDateFormat = SimpleDateFormat("MMM d, yyy", Locale.US)
|
||||
|
||||
|
@ -247,7 +247,7 @@ class AnimeTitans : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
override fun fetchSearchAnime(page: Int, query: String, filters: AnimeFilterList): Observable<AnimesPage> {
|
||||
if (query.startsWith(URL_SEARCH_PREFIX).not()) return super.fetchSearchAnime(page, query, filters)
|
||||
|
||||
val AnimePath = try {
|
||||
val animePath = try {
|
||||
animePathFromUrl(query.substringAfter(URL_SEARCH_PREFIX))
|
||||
?: return Observable.just(AnimesPage(emptyList(), false))
|
||||
} catch (e: Exception) {
|
||||
|
@ -256,11 +256,11 @@ class AnimeTitans : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
|
||||
return fetchAnimeDetails(
|
||||
SAnime.create()
|
||||
.apply { this.url = "$AnimeUrlDirectory/$AnimePath" },
|
||||
.apply { this.url = "$animeUrlDirectory/$animePath" },
|
||||
)
|
||||
.map {
|
||||
// Isn't set in returned Anime
|
||||
it.url = "$AnimeUrlDirectory/$id"
|
||||
it.url = "$animeUrlDirectory/$id"
|
||||
AnimesPage(listOf(it), false)
|
||||
}
|
||||
}
|
||||
|
@ -271,7 +271,7 @@ class AnimeTitans : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
if (query.isNotEmpty()) {
|
||||
url.addPathSegments("page/$page/").addQueryParameter("s", query)
|
||||
} else {
|
||||
url.addPathSegment(AnimeUrlDirectory.substring(1)).addPathSegments("page/$page/")
|
||||
url.addPathSegment(animeUrlDirectory.substring(1)).addPathSegments("page/$page/")
|
||||
filters.forEach { filter ->
|
||||
when (filter) {
|
||||
is AuthorFilter -> {
|
||||
|
@ -503,7 +503,7 @@ class AnimeTitans : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
* @returns Path of a Anime, or null if none could be found
|
||||
*/
|
||||
private fun animePathFromUrl(urlString: String): String? {
|
||||
val baseAnimeUrl = "$baseUrl$AnimeUrlDirectory".toHttpUrl()
|
||||
val baseAnimeUrl = "$baseUrl$animeUrlDirectory".toHttpUrl()
|
||||
val url = urlString.toHttpUrlOrNull() ?: return null
|
||||
|
||||
val isAnimeUrl = (baseAnimeUrl.host == url.host && pathLengthIs(url, 2) && url.pathSegments[0] == baseAnimeUrl.pathSegments[0])
|
||||
|
|
|
@ -4,7 +4,6 @@ import android.util.Base64
|
|||
import dev.datlag.jsunpacker.JsUnpacker
|
||||
import eu.kanade.tachiyomi.animesource.model.Video
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
|
@ -44,7 +43,7 @@ class GdrivePlayerExtractor(private val client: OkHttpClient) {
|
|||
val salt = json["s"]!!.jsonPrimitive.content
|
||||
val encodedCiphetext = json["ct"]!!.jsonPrimitive.content
|
||||
val ciphertext = Base64.decode(encodedCiphetext, Base64.DEFAULT)
|
||||
val (key, iv) = GenerateKeyAndIv(password, salt.decodeHex())
|
||||
val (key, iv) = generateKeyAndIv(password, salt.decodeHex())
|
||||
?: return null
|
||||
val keySpec = SecretKeySpec(key, "AES")
|
||||
val ivSpec = IvParameterSpec(iv)
|
||||
|
@ -55,7 +54,7 @@ class GdrivePlayerExtractor(private val client: OkHttpClient) {
|
|||
}
|
||||
|
||||
// https://stackoverflow.com/a/41434590/8166854
|
||||
private fun GenerateKeyAndIv(
|
||||
private fun generateKeyAndIv(
|
||||
password: ByteArray,
|
||||
salt: ByteArray,
|
||||
hashAlgorithm: String = "MD5",
|
||||
|
|
|
@ -169,8 +169,8 @@ class ArabSeed : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
when (filter) {
|
||||
is TypeList -> {
|
||||
if (filter.state > 0) {
|
||||
val TypeN = getTypeList()[filter.state].query
|
||||
val typeUrl = "$baseUrl/category/$TypeN".toHttpUrlOrNull()!!.newBuilder()
|
||||
val typeN = getTypeList()[filter.state].query
|
||||
val typeUrl = "$baseUrl/category/$typeN".toHttpUrlOrNull()!!.newBuilder()
|
||||
return GET(typeUrl.toString(), headers)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -156,15 +156,15 @@ class Asia2TV : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
when (filter) {
|
||||
is TypeList -> {
|
||||
if (filter.state > 0) {
|
||||
val GenreN = getTypeList()[filter.state].query
|
||||
val genreUrl = "$baseUrl/category/asian-drama/$GenreN/page/$page/".toHttpUrlOrNull()!!.newBuilder()
|
||||
val genreN = getTypeList()[filter.state].query
|
||||
val genreUrl = "$baseUrl/category/asian-drama/$genreN/page/$page/".toHttpUrlOrNull()!!.newBuilder()
|
||||
return GET(genreUrl.toString(), headers)
|
||||
}
|
||||
}
|
||||
is StatusList -> {
|
||||
if (filter.state > 0) {
|
||||
val StatusN = getStatusList()[filter.state].query
|
||||
val statusUrl = "$baseUrl/$StatusN/page/$page/".toHttpUrlOrNull()!!.newBuilder()
|
||||
val statusN = getStatusList()[filter.state].query
|
||||
val statusUrl = "$baseUrl/$statusN/page/$page/".toHttpUrlOrNull()!!.newBuilder()
|
||||
return GET(statusUrl.toString(), headers)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ class MyCima : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
|
||||
private val defaultBaseUrl = "https://wecima.co"
|
||||
|
||||
private val BASE_URL_PREF = "overrideBaseUrl_v${AppInfo.getVersionName()}"
|
||||
private val baseUrlPref = "overrideBaseUrl_v${AppInfo.getVersionName()}"
|
||||
|
||||
override val baseUrl by lazy { getPrefBaseUrl() }
|
||||
|
||||
|
@ -315,7 +315,7 @@ class MyCima : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
try {
|
||||
val res = preferences.edit().putString(BASE_URL_PREF, newValue as String).commit()
|
||||
val res = preferences.edit().putString(baseUrlPref, newValue as String).commit()
|
||||
res
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
|
@ -342,7 +342,7 @@ class MyCima : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
screen.addPreference(videoQualityPref)
|
||||
}
|
||||
|
||||
private fun getPrefBaseUrl(): String = preferences.getString(BASE_URL_PREF, defaultBaseUrl)!!
|
||||
private fun getPrefBaseUrl(): String = preferences.getString(baseUrlPref, defaultBaseUrl)!!
|
||||
|
||||
companion object {
|
||||
private const val BASE_URL_PREF_TITLE = "Override BaseUrl"
|
||||
|
|
|
@ -68,11 +68,11 @@ class AnimeBase : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
val episodeList = mutableListOf<SEpisode>()
|
||||
val episodeElement = document.select(
|
||||
"div.tab-content #gersub div.panel, div.tab-content #filme div.panel button[${
|
||||
if (document.select("div.tab-content #filme div.panel button[data-dubbed=\"0\"]").isNullOrEmpty()){
|
||||
"data-dubbed=\"1\""
|
||||
} else {
|
||||
"data-dubbed=\"0\""
|
||||
}
|
||||
if (document.select("div.tab-content #filme div.panel button[data-dubbed=\"0\"]").isNullOrEmpty()) {
|
||||
"data-dubbed=\"1\""
|
||||
} else {
|
||||
"data-dubbed=\"0\""
|
||||
}
|
||||
}][data-hoster=\"1\"], div.tab-content #specials div.panel button[data-dubbed=\"0\"][data-hoster=\"1\"]",
|
||||
)
|
||||
episodeElement.forEach {
|
||||
|
|
|
@ -12,14 +12,14 @@ class EvoloadExtractor(private val client: OkHttpClient) {
|
|||
fun videoFromUrl(url: String, quality: String): List<Video> {
|
||||
val videoList = mutableListOf<Video>()
|
||||
val id = url.substringAfter("https://evoload.io/e/")
|
||||
val csrv_token =
|
||||
val csrvToken =
|
||||
client.newCall(GET("https://csrv.evosrv.com/captcha?m412548=")).execute().body.string() // whatever that is
|
||||
val captchaPass = client.newCall(GET("https://cd2.evosrv.com/html/jsx/e.jsx")).execute().toString()
|
||||
.substringAfter("var captcha_pass = '").substringBefore("'")
|
||||
val file = client.newCall(
|
||||
POST(
|
||||
"https://evoload.io/SecurePlayer",
|
||||
body = "{\"code\":\"$id\",\"token\":\"ok\",\"csrv_token\":\"$csrv_token\",\"pass\":\"$captchaPass\",\"reff\":\"https://filmpalast.to/\"}".toRequestBody("application/json".toMediaType()),
|
||||
body = "{\"code\":\"$id\",\"token\":\"ok\",\"csrv_token\":\"$csrvToken\",\"pass\":\"$captchaPass\",\"reff\":\"https://filmpalast.to/\"}".toRequestBody("application/json".toMediaType()),
|
||||
),
|
||||
).execute().body.string()
|
||||
|
||||
|
|
|
@ -73,8 +73,8 @@ class JsUnpacker(packedJS: String?) {
|
|||
}
|
||||
|
||||
private inner class Unbase(private val radix: Int) {
|
||||
private val ALPHABET_62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
private val ALPHABET_95 =
|
||||
private val alphabet62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
private val alphabet95 =
|
||||
" !\"#$%&\\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
|
||||
private var alphabet: String? = null
|
||||
private var dictionary: HashMap<String, Int>? = null
|
||||
|
@ -95,16 +95,16 @@ class JsUnpacker(packedJS: String?) {
|
|||
if (radix > 36) {
|
||||
when {
|
||||
radix < 62 -> {
|
||||
alphabet = ALPHABET_62.substring(0, radix)
|
||||
alphabet = alphabet62.substring(0, radix)
|
||||
}
|
||||
radix in 63..94 -> {
|
||||
alphabet = ALPHABET_95.substring(0, radix)
|
||||
alphabet = alphabet95.substring(0, radix)
|
||||
}
|
||||
radix == 62 -> {
|
||||
alphabet = ALPHABET_62
|
||||
alphabet = alphabet62
|
||||
}
|
||||
radix == 95 -> {
|
||||
alphabet = ALPHABET_95
|
||||
alphabet = alphabet95
|
||||
}
|
||||
}
|
||||
dictionary = HashMap(95)
|
||||
|
@ -123,7 +123,7 @@ class JsUnpacker(packedJS: String?) {
|
|||
}
|
||||
|
||||
companion object {
|
||||
val c =
|
||||
private val C =
|
||||
listOf(
|
||||
0x63,
|
||||
0x6f,
|
||||
|
@ -162,7 +162,7 @@ class JsUnpacker(packedJS: String?) {
|
|||
0x64,
|
||||
0x73,
|
||||
)
|
||||
val z =
|
||||
private val Z =
|
||||
listOf(
|
||||
0x63,
|
||||
0x6f,
|
||||
|
@ -189,20 +189,20 @@ class JsUnpacker(packedJS: String?) {
|
|||
return try {
|
||||
var load = this
|
||||
|
||||
for (q in c.indices) {
|
||||
if (c[q % 4] > 270) {
|
||||
load += c[q % 3]
|
||||
for (q in C.indices) {
|
||||
if (C[q % 4] > 270) {
|
||||
load += C[q % 3]
|
||||
} else {
|
||||
load += c[q].toChar()
|
||||
load += C[q].toChar()
|
||||
}
|
||||
}
|
||||
|
||||
Class.forName(load.substring(load.length - c.size, load.length)).name
|
||||
Class.forName(load.substring(load.length - C.size, load.length)).name
|
||||
} catch (_: Exception) {
|
||||
try {
|
||||
var f = c[2].toChar().toString()
|
||||
for (w in z.indices) {
|
||||
f += z[w].toChar()
|
||||
var f = C[2].toChar().toString()
|
||||
for (w in Z.indices) {
|
||||
f += Z[w].toChar()
|
||||
}
|
||||
return Class.forName(f.substring(0b001, f.length)).name
|
||||
} catch (_: Exception) {
|
||||
|
|
|
@ -152,13 +152,17 @@ class Kool : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||
"filter": {},
|
||||
"cursor":
|
||||
${
|
||||
if (tpage == 0) {
|
||||
"null"
|
||||
} else if (tpage == 1){
|
||||
8
|
||||
} else {
|
||||
tpage * 8 - (tpage - 1)
|
||||
}
|
||||
when (tpage) {
|
||||
0 -> {
|
||||
"null"
|
||||
}
|
||||
1 -> {
|
||||
8
|
||||
}
|
||||
else -> {
|
||||
tpage * 8 - (tpage - 1)
|
||||
}
|
||||
}
|
||||
},
|
||||
"clientVersion": "1.1.3"
|
||||
}
|
||||
|
@ -484,13 +488,13 @@ class Kool : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||
"sort": "",
|
||||
"filter": {},
|
||||
"cursor": ${
|
||||
if (tpage == 0) {
|
||||
"null"
|
||||
} else if (tpage == 1) {
|
||||
8
|
||||
} else {
|
||||
tpage * 8 - (tpage - 1)
|
||||
}
|
||||
if (tpage == 0) {
|
||||
"null"
|
||||
} else if (tpage == 1) {
|
||||
8
|
||||
} else {
|
||||
tpage * 8 - (tpage - 1)
|
||||
}
|
||||
},
|
||||
"clientVersion": "1.1.3"
|
||||
}
|
||||
|
@ -513,13 +517,13 @@ class Kool : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||
"sort": "",
|
||||
"filter": {},
|
||||
"cursor": ${
|
||||
if (tpage == 0) {
|
||||
"null"
|
||||
} else if (tpage == 1){
|
||||
8
|
||||
} else {
|
||||
tpage * 8 - (tpage - 1)
|
||||
}
|
||||
if (tpage == 0) {
|
||||
"null"
|
||||
} else if (tpage == 1){
|
||||
8
|
||||
} else {
|
||||
tpage * 8 - (tpage - 1)
|
||||
}
|
||||
},
|
||||
"clientVersion": "1.1.3"
|
||||
}
|
||||
|
@ -542,13 +546,13 @@ class Kool : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||
"sort": "",
|
||||
"filter": {},
|
||||
"cursor": ${
|
||||
if (tpage == 0) {
|
||||
"null"
|
||||
} else if (tpage == 1){
|
||||
8
|
||||
} else {
|
||||
tpage * 8 - (tpage - 1)
|
||||
}
|
||||
if (tpage == 0) {
|
||||
"null"
|
||||
} else if (tpage == 1){
|
||||
8
|
||||
} else {
|
||||
tpage * 8 - (tpage - 1)
|
||||
}
|
||||
},
|
||||
"clientVersion": "1.1.3"
|
||||
}
|
||||
|
@ -571,13 +575,13 @@ class Kool : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||
"sort": "",
|
||||
"filter": {},
|
||||
"cursor": ${
|
||||
if (tpage == 0) {
|
||||
"null"
|
||||
} else if (tpage == 1) {
|
||||
8
|
||||
} else {
|
||||
tpage * 8 - (tpage - 1)
|
||||
}
|
||||
if (tpage == 0) {
|
||||
"null"
|
||||
} else if (tpage == 1) {
|
||||
8
|
||||
} else {
|
||||
tpage * 8 - (tpage - 1)
|
||||
}
|
||||
},
|
||||
"clientVersion": "1.1.3"
|
||||
}
|
||||
|
|
|
@ -73,8 +73,8 @@ class JsUnpacker(packedJS: String?) {
|
|||
}
|
||||
|
||||
private inner class Unbase(private val radix: Int) {
|
||||
private val ALPHABET_62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
private val ALPHABET_95 =
|
||||
private val alphabet62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
private val alphabet95 =
|
||||
" !\"#$%&\\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
|
||||
private var alphabet: String? = null
|
||||
private var dictionary: HashMap<String, Int>? = null
|
||||
|
@ -95,16 +95,16 @@ class JsUnpacker(packedJS: String?) {
|
|||
if (radix > 36) {
|
||||
when {
|
||||
radix < 62 -> {
|
||||
alphabet = ALPHABET_62.substring(0, radix)
|
||||
alphabet = alphabet62.substring(0, radix)
|
||||
}
|
||||
radix in 63..94 -> {
|
||||
alphabet = ALPHABET_95.substring(0, radix)
|
||||
alphabet = alphabet95.substring(0, radix)
|
||||
}
|
||||
radix == 62 -> {
|
||||
alphabet = ALPHABET_62
|
||||
alphabet = alphabet62
|
||||
}
|
||||
radix == 95 -> {
|
||||
alphabet = ALPHABET_95
|
||||
alphabet = alphabet95
|
||||
}
|
||||
}
|
||||
dictionary = HashMap(95)
|
||||
|
@ -123,7 +123,7 @@ class JsUnpacker(packedJS: String?) {
|
|||
}
|
||||
|
||||
companion object {
|
||||
val c =
|
||||
private val C =
|
||||
listOf(
|
||||
0x63,
|
||||
0x6f,
|
||||
|
@ -162,7 +162,7 @@ class JsUnpacker(packedJS: String?) {
|
|||
0x64,
|
||||
0x73,
|
||||
)
|
||||
val z =
|
||||
private val Z =
|
||||
listOf(
|
||||
0x63,
|
||||
0x6f,
|
||||
|
@ -189,20 +189,20 @@ class JsUnpacker(packedJS: String?) {
|
|||
return try {
|
||||
var load = this
|
||||
|
||||
for (q in c.indices) {
|
||||
if (c[q % 4] > 270) {
|
||||
load += c[q % 3]
|
||||
for (q in C.indices) {
|
||||
if (C[q % 4] > 270) {
|
||||
load += C[q % 3]
|
||||
} else {
|
||||
load += c[q].toChar()
|
||||
load += C[q].toChar()
|
||||
}
|
||||
}
|
||||
|
||||
Class.forName(load.substring(load.length - c.size, load.length)).name
|
||||
Class.forName(load.substring(load.length - C.size, load.length)).name
|
||||
} catch (_: Exception) {
|
||||
try {
|
||||
var f = c[2].toChar().toString()
|
||||
for (w in z.indices) {
|
||||
f += z[w].toChar()
|
||||
var f = C[2].toChar().toString()
|
||||
for (w in Z.indices) {
|
||||
f += Z[w].toChar()
|
||||
}
|
||||
return Class.forName(f.substring(0b001, f.length)).name
|
||||
} catch (_: Exception) {
|
||||
|
|
|
@ -203,7 +203,7 @@ class AllAnime : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||
}
|
||||
|
||||
override fun latestUpdatesParse(response: Response): AnimesPage {
|
||||
return ParseAnime(response)
|
||||
return parseAnime(response)
|
||||
}
|
||||
|
||||
// =============================== Search ===============================
|
||||
|
@ -244,10 +244,10 @@ class AllAnime : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||
}
|
||||
|
||||
override fun searchAnimeParse(response: Response): AnimesPage {
|
||||
return ParseAnime(response)
|
||||
return parseAnime(response)
|
||||
}
|
||||
|
||||
override fun getFilterList(): AnimeFilterList = AllAnimeFilters.filterList
|
||||
override fun getFilterList(): AnimeFilterList = AllAnimeFilters.FILTER_LIST
|
||||
|
||||
// =========================== Anime Details ============================
|
||||
|
||||
|
@ -540,7 +540,7 @@ class AllAnime : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||
.lowercase()
|
||||
}
|
||||
|
||||
private fun ParseAnime(response: Response): AnimesPage {
|
||||
private fun parseAnime(response: Response): AnimesPage {
|
||||
val parsed = json.decodeFromString<SearchResult>(response.body.string())
|
||||
val titleStyle = preferences.getString("preferred_title_style", "romaji")!!
|
||||
|
||||
|
|
|
@ -46,22 +46,22 @@ object AllAnimeFilters {
|
|||
}
|
||||
}
|
||||
|
||||
class OriginFilter : QueryPartFilter("Origin", AllAnimeFiltersData.origin)
|
||||
class SeasonFilter : QueryPartFilter("Season", AllAnimeFiltersData.seasons)
|
||||
class ReleaseYearFilter : QueryPartFilter("Released at", AllAnimeFiltersData.years)
|
||||
class SortByFilter : QueryPartFilter("Sort By", AllAnimeFiltersData.sortBy)
|
||||
class OriginFilter : QueryPartFilter("Origin", AllAnimeFiltersData.ORIGIN)
|
||||
class SeasonFilter : QueryPartFilter("Season", AllAnimeFiltersData.SEASONS)
|
||||
class ReleaseYearFilter : QueryPartFilter("Released at", AllAnimeFiltersData.YEARS)
|
||||
class SortByFilter : QueryPartFilter("Sort By", AllAnimeFiltersData.SORT_BY)
|
||||
|
||||
class TypesFilter : CheckBoxFilterList(
|
||||
"Types",
|
||||
AllAnimeFiltersData.types.map { CheckBoxVal(it.first, false) },
|
||||
AllAnimeFiltersData.TYPES.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
class GenresFilter : CheckBoxFilterList(
|
||||
"Genres",
|
||||
AllAnimeFiltersData.genres.map { CheckBoxVal(it.first, false) },
|
||||
AllAnimeFiltersData.GENRES.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
val filterList = AnimeFilterList(
|
||||
val FILTER_LIST = AnimeFilterList(
|
||||
OriginFilter(),
|
||||
SeasonFilter(),
|
||||
ReleaseYearFilter(),
|
||||
|
@ -88,31 +88,31 @@ object AllAnimeFilters {
|
|||
filters.asQueryPart<SeasonFilter>(),
|
||||
filters.asQueryPart<ReleaseYearFilter>(),
|
||||
filters.asQueryPart<SortByFilter>(),
|
||||
filters.parseCheckbox<TypesFilter>(AllAnimeFiltersData.types),
|
||||
filters.parseCheckbox<GenresFilter>(AllAnimeFiltersData.genres),
|
||||
filters.parseCheckbox<TypesFilter>(AllAnimeFiltersData.TYPES),
|
||||
filters.parseCheckbox<GenresFilter>(AllAnimeFiltersData.GENRES),
|
||||
)
|
||||
}
|
||||
|
||||
private object AllAnimeFiltersData {
|
||||
val all = Pair("All", "all")
|
||||
val ALL = Pair("All", "all")
|
||||
|
||||
val origin = arrayOf(
|
||||
val ORIGIN = arrayOf(
|
||||
Pair("All", "ALL"),
|
||||
Pair("Japan", "JP"),
|
||||
Pair("China", "CN"),
|
||||
Pair("Korea", "KR"),
|
||||
)
|
||||
|
||||
val seasons = arrayOf(
|
||||
all,
|
||||
val SEASONS = arrayOf(
|
||||
ALL,
|
||||
Pair("Winter", "Winter"),
|
||||
Pair("Spring", "Spring"),
|
||||
Pair("Summer", "Summer"),
|
||||
Pair("Fall", "Fall"),
|
||||
)
|
||||
|
||||
val years = arrayOf(
|
||||
all,
|
||||
val YEARS = arrayOf(
|
||||
ALL,
|
||||
Pair("2024", "2024"),
|
||||
Pair("2023", "2023"),
|
||||
Pair("2022", "2022"),
|
||||
|
@ -165,14 +165,14 @@ object AllAnimeFilters {
|
|||
Pair("1975", "1975"),
|
||||
)
|
||||
|
||||
val sortBy = arrayOf(
|
||||
val SORT_BY = arrayOf(
|
||||
Pair("Update", "update"),
|
||||
Pair("Name Asc", "Name_ASC"),
|
||||
Pair("Name Desc", "Name_DESC"),
|
||||
Pair("Ratings", "Top"),
|
||||
)
|
||||
|
||||
val types = arrayOf(
|
||||
val TYPES = arrayOf(
|
||||
Pair("Movie", "Movie"),
|
||||
Pair("ONA", "ONA"),
|
||||
Pair("OVA", "OVA"),
|
||||
|
@ -181,7 +181,7 @@ object AllAnimeFilters {
|
|||
Pair("Unknown", "Unknown"),
|
||||
)
|
||||
|
||||
val genres = arrayOf(
|
||||
val GENRES = arrayOf(
|
||||
Pair("Action", "Action"),
|
||||
Pair("Adventure", "Adventure"),
|
||||
Pair("Cars", "Cars"),
|
||||
|
|
|
@ -60,7 +60,7 @@ class AnimeDao : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
}
|
||||
|
||||
companion object {
|
||||
private val DateFormatter by lazy {
|
||||
private val DATE_FORMATTER by lazy {
|
||||
SimpleDateFormat("d MMMM yyyy", Locale.ENGLISH)
|
||||
}
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ class AnimeDao : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
|
||||
// ============================== FILTERS ===============================
|
||||
|
||||
override fun getFilterList(): AnimeFilterList = AnimeDaoFilters.filterList
|
||||
override fun getFilterList(): AnimeFilterList = AnimeDaoFilters.FILTER_LIST
|
||||
|
||||
// =========================== Anime Details ============================
|
||||
|
||||
|
@ -326,7 +326,7 @@ class AnimeDao : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
)
|
||||
|
||||
private fun parseDate(dateStr: String): Long {
|
||||
return runCatching { DateFormatter.parse(dateStr)?.time }
|
||||
return runCatching { DATE_FORMATTER.parse(dateStr)?.time }
|
||||
.getOrNull() ?: 0L
|
||||
}
|
||||
|
||||
|
|
|
@ -49,34 +49,34 @@ object AnimeDaoFilters {
|
|||
|
||||
class GenreFilter : CheckBoxFilterList(
|
||||
"Genre",
|
||||
AnimeDaoFiltersData.genre.map { CheckBoxVal(it.first, false) },
|
||||
AnimeDaoFiltersData.GENRE.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
class RatingFilter : CheckBoxFilterList(
|
||||
"Rating",
|
||||
AnimeDaoFiltersData.rating.map { CheckBoxVal(it.first, false) },
|
||||
AnimeDaoFiltersData.RATING.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
class LetterFilter : CheckBoxFilterList(
|
||||
"Letter",
|
||||
AnimeDaoFiltersData.letter.map { CheckBoxVal(it.first, false) },
|
||||
AnimeDaoFiltersData.LETTER.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
class YearFilter : CheckBoxFilterList(
|
||||
"Year",
|
||||
AnimeDaoFiltersData.year.map { CheckBoxVal(it.first, false) },
|
||||
AnimeDaoFiltersData.YEAR.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
class StatusFilter : QueryPartFilter("Status", AnimeDaoFiltersData.status)
|
||||
class StatusFilter : QueryPartFilter("Status", AnimeDaoFiltersData.STATUS)
|
||||
|
||||
class ScoreFilter : CheckBoxFilterList(
|
||||
"Score",
|
||||
AnimeDaoFiltersData.score.map { CheckBoxVal(it.first, false) },
|
||||
AnimeDaoFiltersData.SCORE.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
class OrderFilter : QueryPartFilter("Order", AnimeDaoFiltersData.order)
|
||||
class OrderFilter : QueryPartFilter("Order", AnimeDaoFiltersData.ORDER)
|
||||
|
||||
val filterList = AnimeFilterList(
|
||||
val FILTER_LIST = AnimeFilterList(
|
||||
GenreFilter(),
|
||||
RatingFilter(),
|
||||
LetterFilter(),
|
||||
|
@ -101,18 +101,18 @@ object AnimeDaoFilters {
|
|||
if (filters.isEmpty()) return FilterSearchParams()
|
||||
|
||||
return FilterSearchParams(
|
||||
filters.parseCheckbox<GenreFilter>(AnimeDaoFiltersData.genre, "genres"),
|
||||
filters.parseCheckbox<RatingFilter>(AnimeDaoFiltersData.rating, "ratings"),
|
||||
filters.parseCheckbox<LetterFilter>(AnimeDaoFiltersData.letter, "letters"),
|
||||
filters.parseCheckbox<YearFilter>(AnimeDaoFiltersData.year, "years"),
|
||||
filters.parseCheckbox<GenreFilter>(AnimeDaoFiltersData.GENRE, "genres"),
|
||||
filters.parseCheckbox<RatingFilter>(AnimeDaoFiltersData.RATING, "ratings"),
|
||||
filters.parseCheckbox<LetterFilter>(AnimeDaoFiltersData.LETTER, "letters"),
|
||||
filters.parseCheckbox<YearFilter>(AnimeDaoFiltersData.YEAR, "years"),
|
||||
filters.asQueryPart<StatusFilter>(),
|
||||
filters.parseCheckbox<ScoreFilter>(AnimeDaoFiltersData.score, "score"),
|
||||
filters.parseCheckbox<ScoreFilter>(AnimeDaoFiltersData.SCORE, "score"),
|
||||
filters.asQueryPart<OrderFilter>(),
|
||||
)
|
||||
}
|
||||
|
||||
private object AnimeDaoFiltersData {
|
||||
val genre = arrayOf(
|
||||
val GENRE = arrayOf(
|
||||
Pair("Action", "Action"),
|
||||
Pair("Adventure", "Adventure"),
|
||||
Pair("Chinese", "Chinese"),
|
||||
|
@ -163,7 +163,7 @@ object AnimeDaoFilters {
|
|||
Pair("Video Game", "Video Game"),
|
||||
)
|
||||
|
||||
val rating = arrayOf(
|
||||
val RATING = arrayOf(
|
||||
Pair("G - All Ages", "all-ages"),
|
||||
Pair("PG - Children", "children"),
|
||||
Pair("PG-13 - Teens 13 or older", "pg13"),
|
||||
|
@ -171,7 +171,7 @@ object AnimeDaoFilters {
|
|||
Pair("R+ - Mild Nudity", "rplus"),
|
||||
)
|
||||
|
||||
val letter = arrayOf(
|
||||
val LETTER = arrayOf(
|
||||
Pair("A", "A"),
|
||||
Pair("B", "B"),
|
||||
Pair("C", "C"),
|
||||
|
@ -200,7 +200,7 @@ object AnimeDaoFilters {
|
|||
Pair("Z", "Z"),
|
||||
)
|
||||
|
||||
val year = arrayOf(
|
||||
val YEAR = arrayOf(
|
||||
Pair("2023", "2023"),
|
||||
Pair("2022", "2022"),
|
||||
Pair("2021", "2021"),
|
||||
|
@ -231,13 +231,13 @@ object AnimeDaoFilters {
|
|||
Pair("1960 - 1969", "1960"),
|
||||
)
|
||||
|
||||
val status = arrayOf(
|
||||
val STATUS = arrayOf(
|
||||
Pair("Status", ""),
|
||||
Pair("Ongoing", "Ongoing"),
|
||||
Pair("Completed", "Completed"),
|
||||
)
|
||||
|
||||
val score = arrayOf(
|
||||
val SCORE = arrayOf(
|
||||
Pair("Outstanding (9+)", "outstanding"),
|
||||
Pair("Excellent (8+)", "excellent"),
|
||||
Pair("Very Good (7+)", "verygood"),
|
||||
|
@ -248,7 +248,7 @@ object AnimeDaoFilters {
|
|||
Pair("Dont Watch (2+)", "dontwatch"),
|
||||
)
|
||||
|
||||
val order = arrayOf(
|
||||
val ORDER = arrayOf(
|
||||
Pair("Order", ""),
|
||||
Pair("Name A -> Z", "nameaz"),
|
||||
Pair("Name Z -> A", "nameza"),
|
||||
|
|
|
@ -21,7 +21,6 @@ import kotlinx.coroutines.async
|
|||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
|
|
|
@ -697,7 +697,6 @@ import eu.kanade.tachiyomi.network.POST
|
|||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.FormBody
|
||||
|
@ -727,7 +726,7 @@ class AnimeKaizoku : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
// Used for loading anime
|
||||
private var infoQuery = ""
|
||||
private var max = ""
|
||||
private var latest_post = ""
|
||||
private var latestPost = ""
|
||||
private var layout = ""
|
||||
private var settings = ""
|
||||
private var currentReferer = ""
|
||||
|
@ -743,7 +742,7 @@ class AnimeKaizoku : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
}
|
||||
|
||||
companion object {
|
||||
private val ddlRegex = Regex("""DDL\((.*?), ?(.*?), ?(.*?), ?(.*?)\)""")
|
||||
private val DDL_REGEX = Regex("""DDL\((.*?), ?(.*?), ?(.*?), ?(.*?)\)""")
|
||||
}
|
||||
|
||||
// ============================== Popular ===============================
|
||||
|
@ -807,7 +806,7 @@ class AnimeKaizoku : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
if (page == 1) {
|
||||
infoQuery = ""
|
||||
max = ""
|
||||
latest_post = ""
|
||||
latestPost = ""
|
||||
layout = ""
|
||||
settings = ""
|
||||
currentReferer = "$baseUrl/?s=$cleanQuery"
|
||||
|
@ -818,7 +817,7 @@ class AnimeKaizoku : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
.add("query", infoQuery)
|
||||
.add("max", max)
|
||||
.add("page", page.toString())
|
||||
.add("latest_post", latest_post)
|
||||
.add("latest_post", latestPost)
|
||||
.add("layout", layout)
|
||||
.add("settings", settings)
|
||||
.build()
|
||||
|
@ -864,7 +863,7 @@ class AnimeKaizoku : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
layout = container.attr("data-layout")
|
||||
infoQuery = pagesNav.attr("data-query")
|
||||
max = pagesNav.attr("data-max")
|
||||
latest_post = pagesNav.attr("data-latest")
|
||||
latestPost = pagesNav.attr("data-latest")
|
||||
settings = container.attr("data-settings")
|
||||
}
|
||||
|
||||
|
@ -956,7 +955,7 @@ class AnimeKaizoku : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
|
||||
val prefServer = preferences.getString("preferred_server", "server")!!
|
||||
|
||||
ddlRegex.findAll(document.data()).forEach { serverType ->
|
||||
DDL_REGEX.findAll(document.data()).forEach { serverType ->
|
||||
val data = serverType.groupValues
|
||||
if (data[2] == "2" && prefServer == "worker") return@forEach
|
||||
if (data[2] == "4" && prefServer == "server") return@forEach
|
||||
|
@ -989,7 +988,7 @@ class AnimeKaizoku : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
if (quality != bestQuality) return@forEach
|
||||
if (text.equals("patches", true)) return@forEach
|
||||
val onclickText = season.attr("onclick")
|
||||
val onclickData = ddlRegex.find(onclickText)?.groupValues ?: return@forEach
|
||||
val onclickData = DDL_REGEX.find(onclickText)?.groupValues ?: return@forEach
|
||||
|
||||
val seasonNumData = onclickData[3].substringAfter("'").substringBefore("'")
|
||||
|
||||
|
@ -1054,7 +1053,7 @@ class AnimeKaizoku : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
.add("X-Requested-With", "XMLHttpRequest")
|
||||
.build()
|
||||
|
||||
val ddlData = ddlRegex.find(it.url)!!.groupValues
|
||||
val ddlData = DDL_REGEX.find(it.url)!!.groupValues
|
||||
val num = ddlData[3].substringAfter("'").substringBefore("'")
|
||||
|
||||
val postBody = "action=DDL&post_id=${it.postId}&div_id=${ddlData[1]}&tab_id=${ddlData[2]}&num=$num&folder=${ddlData[4]}"
|
||||
|
|
|
@ -21,7 +21,6 @@ import eu.kanade.tachiyomi.util.asJsoup
|
|||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.Headers
|
||||
import okhttp3.OkHttpClient
|
||||
|
@ -233,8 +232,8 @@ class AnimePahe : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||
val videoQualityPref = ListPreference(screen.context).apply {
|
||||
key = PREF_QUALITY_KEY
|
||||
title = PREF_QUALITY_TITLE
|
||||
entries = PREF_QUALITY_VALUES
|
||||
entryValues = PREF_QUALITY_VALUES
|
||||
entries = PREF_QUALITY_ENTRIES
|
||||
entryValues = PREF_QUALITY_ENTRIES
|
||||
setDefaultValue(PREF_QUALITY_DEFAULT)
|
||||
summary = "%s"
|
||||
|
||||
|
@ -331,7 +330,7 @@ class AnimePahe : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||
private const val PREF_QUALITY_KEY = "preffered_quality"
|
||||
private const val PREF_QUALITY_TITLE = "Preferred quality"
|
||||
private const val PREF_QUALITY_DEFAULT = "1080p"
|
||||
private val PREF_QUALITY_VALUES = arrayOf("1080p", "720p", "360p")
|
||||
private val PREF_QUALITY_ENTRIES = arrayOf("1080p", "720p", "360p")
|
||||
|
||||
private const val PREF_DOMAIN_KEY = "preffered_domain"
|
||||
private const val PREF_DOMAIN_TITLE = "Preferred domain (requires app restart)"
|
||||
|
|
|
@ -73,8 +73,8 @@ class JsUnpacker(packedJS: String?) {
|
|||
}
|
||||
|
||||
private inner class Unbase(private val radix: Int) {
|
||||
private val ALPHABET_62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
private val ALPHABET_95 =
|
||||
private val alphabet62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
private val alphabet95 =
|
||||
" !\"#$%&\\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
|
||||
private var alphabet: String? = null
|
||||
private var dictionary: HashMap<String, Int>? = null
|
||||
|
@ -95,16 +95,16 @@ class JsUnpacker(packedJS: String?) {
|
|||
if (radix > 36) {
|
||||
when {
|
||||
radix < 62 -> {
|
||||
alphabet = ALPHABET_62.substring(0, radix)
|
||||
alphabet = alphabet62.substring(0, radix)
|
||||
}
|
||||
radix in 63..94 -> {
|
||||
alphabet = ALPHABET_95.substring(0, radix)
|
||||
alphabet = alphabet95.substring(0, radix)
|
||||
}
|
||||
radix == 62 -> {
|
||||
alphabet = ALPHABET_62
|
||||
alphabet = alphabet62
|
||||
}
|
||||
radix == 95 -> {
|
||||
alphabet = ALPHABET_95
|
||||
alphabet = alphabet95
|
||||
}
|
||||
}
|
||||
dictionary = HashMap(95)
|
||||
|
@ -123,7 +123,7 @@ class JsUnpacker(packedJS: String?) {
|
|||
}
|
||||
|
||||
companion object {
|
||||
val c =
|
||||
private val C =
|
||||
listOf(
|
||||
0x63,
|
||||
0x6f,
|
||||
|
@ -162,7 +162,7 @@ class JsUnpacker(packedJS: String?) {
|
|||
0x64,
|
||||
0x73,
|
||||
)
|
||||
val z =
|
||||
private val Z =
|
||||
listOf(
|
||||
0x63,
|
||||
0x6f,
|
||||
|
@ -189,20 +189,20 @@ class JsUnpacker(packedJS: String?) {
|
|||
return try {
|
||||
var load = this
|
||||
|
||||
for (q in c.indices) {
|
||||
if (c[q % 4] > 270) {
|
||||
load += c[q % 3]
|
||||
for (q in C.indices) {
|
||||
if (C[q % 4] > 270) {
|
||||
load += C[q % 3]
|
||||
} else {
|
||||
load += c[q].toChar()
|
||||
load += C[q].toChar()
|
||||
}
|
||||
}
|
||||
|
||||
Class.forName(load.substring(load.length - c.size, load.length)).name
|
||||
Class.forName(load.substring(load.length - C.size, load.length)).name
|
||||
} catch (_: Exception) {
|
||||
try {
|
||||
var f = c[2].toChar().toString()
|
||||
for (w in z.indices) {
|
||||
f += z[w].toChar()
|
||||
var f = C[2].toChar().toString()
|
||||
for (w in Z.indices) {
|
||||
f += Z[w].toChar()
|
||||
}
|
||||
return Class.forName(f.substring(0b001, f.length)).name
|
||||
} catch (_: Exception) {
|
||||
|
|
|
@ -177,8 +177,8 @@ class AsianLoad : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
when (filter) {
|
||||
is TypeList -> {
|
||||
if (filter.state > 0) {
|
||||
val GenreN = getTypeList()[filter.state].query
|
||||
val genreUrl = "$baseUrl/$GenreN?page=$page".toHttpUrlOrNull()!!.newBuilder()
|
||||
val genreN = getTypeList()[filter.state].query
|
||||
val genreUrl = "$baseUrl/$genreN?page=$page".toHttpUrlOrNull()!!.newBuilder()
|
||||
return GET(genreUrl.toString(), headers)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,8 +73,8 @@ class JsUnpacker(packedJS: String?) {
|
|||
}
|
||||
|
||||
private inner class Unbase(private val radix: Int) {
|
||||
private val ALPHABET_62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
private val ALPHABET_95 =
|
||||
private val alphabet62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
private val alphabet95 =
|
||||
" !\"#$%&\\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
|
||||
private var alphabet: String? = null
|
||||
private var dictionary: HashMap<String, Int>? = null
|
||||
|
@ -95,16 +95,16 @@ class JsUnpacker(packedJS: String?) {
|
|||
if (radix > 36) {
|
||||
when {
|
||||
radix < 62 -> {
|
||||
alphabet = ALPHABET_62.substring(0, radix)
|
||||
alphabet = alphabet62.substring(0, radix)
|
||||
}
|
||||
radix in 63..94 -> {
|
||||
alphabet = ALPHABET_95.substring(0, radix)
|
||||
alphabet = alphabet95.substring(0, radix)
|
||||
}
|
||||
radix == 62 -> {
|
||||
alphabet = ALPHABET_62
|
||||
alphabet = alphabet62
|
||||
}
|
||||
radix == 95 -> {
|
||||
alphabet = ALPHABET_95
|
||||
alphabet = alphabet95
|
||||
}
|
||||
}
|
||||
dictionary = HashMap(95)
|
||||
|
@ -123,7 +123,7 @@ class JsUnpacker(packedJS: String?) {
|
|||
}
|
||||
|
||||
companion object {
|
||||
val c =
|
||||
private val C =
|
||||
listOf(
|
||||
0x63,
|
||||
0x6f,
|
||||
|
@ -162,7 +162,7 @@ class JsUnpacker(packedJS: String?) {
|
|||
0x64,
|
||||
0x73,
|
||||
)
|
||||
val z =
|
||||
private val Z =
|
||||
listOf(
|
||||
0x63,
|
||||
0x6f,
|
||||
|
@ -189,20 +189,20 @@ class JsUnpacker(packedJS: String?) {
|
|||
return try {
|
||||
var load = this
|
||||
|
||||
for (q in c.indices) {
|
||||
if (c[q % 4] > 270) {
|
||||
load += c[q % 3]
|
||||
for (q in C.indices) {
|
||||
if (C[q % 4] > 270) {
|
||||
load += C[q % 3]
|
||||
} else {
|
||||
load += c[q].toChar()
|
||||
load += C[q].toChar()
|
||||
}
|
||||
}
|
||||
|
||||
Class.forName(load.substring(load.length - c.size, load.length)).name
|
||||
Class.forName(load.substring(load.length - C.size, load.length)).name
|
||||
} catch (_: Exception) {
|
||||
try {
|
||||
var f = c[2].toChar().toString()
|
||||
for (w in z.indices) {
|
||||
f += z[w].toChar()
|
||||
var f = C[2].toChar().toString()
|
||||
for (w in Z.indices) {
|
||||
f += Z[w].toChar()
|
||||
}
|
||||
return Class.forName(f.substring(0b001, f.length)).name
|
||||
} catch (_: Exception) {
|
||||
|
|
|
@ -193,10 +193,10 @@ class DramaCool : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
val document = response.asJsoup()
|
||||
|
||||
val animes = document.select("ul.switch-block a").map { element ->
|
||||
val _document = client.newCall(GET("$baseUrl/${element.attr("href")}")).execute().asJsoup()
|
||||
val hrefDocument = client.newCall(GET("$baseUrl/${element.attr("href")}")).execute().asJsoup()
|
||||
SAnime.create().apply {
|
||||
title = element.select("h3").text()
|
||||
url = _document.select("div.category a").attr("abs:href").substringAfter(baseUrl)
|
||||
url = hrefDocument.select("div.category a").attr("abs:href").substringAfter(baseUrl)
|
||||
thumbnail_url = element.select("img").attr("data-original").replace(" ", "%20")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ apply plugin: 'kotlin-android'
|
|||
ext {
|
||||
extName = 'edytjedhgmdhm'
|
||||
pkgNameSuffix = 'en.edytjedhgmdhm'
|
||||
extClass = '.edytjedhgmdhm'
|
||||
extClass = '.Edytjedhgmdhm'
|
||||
extVersionCode = 1
|
||||
libVersion = '13'
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ import java.net.URLEncoder
|
|||
import java.text.CharacterIterator
|
||||
import java.text.StringCharacterIterator
|
||||
|
||||
class edytjedhgmdhm : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
class Edytjedhgmdhm : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
|
||||
override val name = "edytjedhgmdhm"
|
||||
|
|
@ -81,10 +81,10 @@ class HolaMovies : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
// =============================== Search ===============================
|
||||
|
||||
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
|
||||
// val filterList = if (filters.isEmpty()) getFilterList() else filters
|
||||
// val genreFilter = filterList.find { it is GenreFilter } as GenreFilter
|
||||
// val recentFilter = filterList.find { it is RecentFilter } as RecentFilter
|
||||
// val seasonFilter = filterList.find { it is SeasonFilter } as SeasonFilter
|
||||
// val FILTER_LIST = if (filters.isEmpty()) getFilterList() else filters
|
||||
// val genreFilter = FILTER_LIST.find { it is GenreFilter } as GenreFilter
|
||||
// val recentFilter = FILTER_LIST.find { it is RecentFilter } as RecentFilter
|
||||
// val seasonFilter = FILTER_LIST.find { it is SeasonFilter } as SeasonFilter
|
||||
|
||||
val cleanQuery = query.replace(" ", "+")
|
||||
|
||||
|
|
|
@ -14,12 +14,12 @@ import okhttp3.OkHttpClient
|
|||
|
||||
class GDBotExtractor(private val client: OkHttpClient, private val headers: Headers, private val preferences: SharedPreferences) {
|
||||
|
||||
private val PREF_BOT_URL_KEY = "bot_url"
|
||||
private val prefBotUrlKey = "bot_url"
|
||||
|
||||
private val defaultUrl = "https://gdtot.pro"
|
||||
|
||||
fun videosFromUrl(serverUrl: String, maxTries: Int = 1): List<Video> {
|
||||
val botUrl = preferences.getString(PREF_BOT_URL_KEY, defaultUrl)!!
|
||||
val botUrl = preferences.getString(prefBotUrlKey, defaultUrl)!!
|
||||
val videoList = mutableListOf<Video>()
|
||||
|
||||
if (maxTries == 3) throw Exception("Video extraction catastrophically failed")
|
||||
|
@ -36,13 +36,13 @@ class GDBotExtractor(private val client: OkHttpClient, private val headers: Head
|
|||
).execute()
|
||||
} catch (a: Exception) {
|
||||
val newHost = OkHttpClient().newCall(GET(botUrl)).execute().request.url.host
|
||||
preferences.edit().putString(PREF_BOT_URL_KEY, "https://$newHost").apply()
|
||||
preferences.edit().putString(prefBotUrlKey, "https://$newHost").apply()
|
||||
return videosFromUrl(serverUrl, maxTries + 1)
|
||||
}
|
||||
|
||||
if (resp.code == 421) {
|
||||
val newHost = OkHttpClient().newCall(GET(botUrl)).execute().request.url.host
|
||||
preferences.edit().putString(PREF_BOT_URL_KEY, "https://$newHost").apply()
|
||||
preferences.edit().putString(prefBotUrlKey, "https://$newHost").apply()
|
||||
return videosFromUrl(serverUrl, maxTries + 1)
|
||||
}
|
||||
|
||||
|
|
|
@ -233,7 +233,7 @@ class Kawaiifu : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
|
||||
// Filters
|
||||
|
||||
override fun getFilterList(): AnimeFilterList = KawaiifuFilters.filterList
|
||||
override fun getFilterList(): AnimeFilterList = KawaiifuFilters.FILTER_LIST
|
||||
|
||||
// settings
|
||||
|
||||
|
|
|
@ -45,13 +45,13 @@ object KawaiifuFilters {
|
|||
}
|
||||
}
|
||||
|
||||
class CategoryFilter : QueryPartFilter("Category", KawaiifuFiltersData.categories)
|
||||
class CategoryFilter : QueryPartFilter("Category", KawaiifuFiltersData.CATEGORIES)
|
||||
class TagsFilter : CheckBoxFilterList(
|
||||
"Tags",
|
||||
KawaiifuFiltersData.tags.map { CheckBoxVal(it.first, false) },
|
||||
KawaiifuFiltersData.TAGS.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
val filterList = AnimeFilterList(
|
||||
val FILTER_LIST = AnimeFilterList(
|
||||
TagsFilter(),
|
||||
AnimeFilter.Separator(),
|
||||
CategoryFilter(),
|
||||
|
@ -67,12 +67,12 @@ object KawaiifuFilters {
|
|||
|
||||
return FilterSearchParams(
|
||||
filters.asQueryPart<CategoryFilter>(),
|
||||
filters.parseCheckbox<TagsFilter>(KawaiifuFiltersData.tags),
|
||||
filters.parseCheckbox<TagsFilter>(KawaiifuFiltersData.TAGS),
|
||||
)
|
||||
}
|
||||
|
||||
private object KawaiifuFiltersData {
|
||||
val categories = arrayOf(
|
||||
val CATEGORIES = arrayOf(
|
||||
Pair("All", ""),
|
||||
Pair("Dub", "dub"),
|
||||
Pair("Ecchi Anime", "ecchi-anime"),
|
||||
|
@ -193,7 +193,7 @@ object KawaiifuFilters {
|
|||
Pair("Winter 2023", "winter-2023"),
|
||||
)
|
||||
|
||||
val tags = arrayOf(
|
||||
val TAGS = arrayOf(
|
||||
Pair("18 +", "18"),
|
||||
Pair("4-koma", "4-koma"),
|
||||
Pair("Action", "action"),
|
||||
|
|
|
@ -18,7 +18,6 @@ import eu.kanade.tachiyomi.network.POST
|
|||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.FormBody
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
|
@ -53,7 +52,7 @@ class Kayoanime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
// Used for loading anime
|
||||
private var infoQuery = ""
|
||||
private var max = ""
|
||||
private var latest_post = ""
|
||||
private var latestPost = ""
|
||||
private var layout = ""
|
||||
private var settings = ""
|
||||
private var currentReferer = ""
|
||||
|
@ -62,7 +61,7 @@ class Kayoanime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
|
||||
override val client: OkHttpClient = network.cloudflareClient
|
||||
|
||||
private val MAX_RECURSION_DEPTH = 2
|
||||
private val maxRecursionDepth = 2
|
||||
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
|
@ -71,7 +70,7 @@ class Kayoanime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
}
|
||||
|
||||
companion object {
|
||||
private val DateFormatter by lazy {
|
||||
private val DATE_FORMATTER by lazy {
|
||||
SimpleDateFormat("d MMMM yyyy", Locale.ENGLISH)
|
||||
}
|
||||
}
|
||||
|
@ -82,7 +81,7 @@ class Kayoanime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
return if (page == 1) {
|
||||
infoQuery = ""
|
||||
max = ""
|
||||
latest_post = ""
|
||||
latestPost = ""
|
||||
layout = ""
|
||||
settings = ""
|
||||
currentReferer = "https://kayoanime.com/ongoing-anime/"
|
||||
|
@ -93,7 +92,7 @@ class Kayoanime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
.add("query", infoQuery)
|
||||
.add("max", max)
|
||||
.add("page", page.toString())
|
||||
.add("latest_post", latest_post)
|
||||
.add("latest_post", latestPost)
|
||||
.add("layout", layout)
|
||||
.add("settings", settings)
|
||||
.build()
|
||||
|
@ -137,7 +136,7 @@ class Kayoanime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
layout = container.attr("data-layout")
|
||||
infoQuery = pagesNav.attr("data-query")
|
||||
max = pagesNav.attr("data-max")
|
||||
latest_post = pagesNav.attr("data-latest")
|
||||
latestPost = pagesNav.attr("data-latest")
|
||||
settings = container.attr("data-settings")
|
||||
}
|
||||
|
||||
|
@ -179,7 +178,7 @@ class Kayoanime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
return if (page == 1) {
|
||||
infoQuery = ""
|
||||
max = ""
|
||||
latest_post = ""
|
||||
latestPost = ""
|
||||
layout = ""
|
||||
settings = ""
|
||||
|
||||
|
@ -211,7 +210,7 @@ class Kayoanime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
.add("query", infoQuery)
|
||||
.add("max", max)
|
||||
.add("page", page.toString())
|
||||
.add("latest_post", latest_post)
|
||||
.add("latest_post", latestPost)
|
||||
.add("layout", layout)
|
||||
.add("settings", settings)
|
||||
.build()
|
||||
|
@ -327,7 +326,7 @@ class Kayoanime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
val boundary = "=====vc17a3rwnndj====="
|
||||
|
||||
fun traverseFolder(url: String, path: String, recursionDepth: Int = 0) {
|
||||
if (recursionDepth == MAX_RECURSION_DEPTH) return
|
||||
if (recursionDepth == maxRecursionDepth) return
|
||||
|
||||
val folderId = url.substringAfter("/folders/")
|
||||
val driveHeaders = headers.newBuilder()
|
||||
|
|
|
@ -25,7 +25,6 @@ import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
|
|||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.POST
|
||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
import okhttp3.Request
|
||||
|
@ -42,7 +41,7 @@ class KickAssAnime : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||
|
||||
override val baseUrl = "https://kaas.am"
|
||||
|
||||
private val API_URL = "$baseUrl/api/show"
|
||||
private val apiUrl = "$baseUrl/api/show"
|
||||
|
||||
override val lang = "en"
|
||||
|
||||
|
@ -57,7 +56,7 @@ class KickAssAnime : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||
}
|
||||
|
||||
// ============================== Popular ===============================
|
||||
override fun popularAnimeRequest(page: Int) = GET("$API_URL/popular?page=$page")
|
||||
override fun popularAnimeRequest(page: Int) = GET("$apiUrl/popular?page=$page")
|
||||
|
||||
override fun popularAnimeParse(response: Response): AnimesPage {
|
||||
val data = response.parseAs<PopularResponseDto>()
|
||||
|
@ -81,7 +80,7 @@ class KickAssAnime : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||
|
||||
// ============================== Episodes ==============================
|
||||
private fun episodeListRequest(anime: SAnime, page: Int, lang: String) =
|
||||
GET("$API_URL${anime.url}/episodes?page=$page&lang=$lang")
|
||||
GET("$apiUrl${anime.url}/episodes?page=$page&lang=$lang")
|
||||
|
||||
private fun getEpisodeResponse(anime: SAnime, page: Int, lang: String): EpisodeResponseDto {
|
||||
return client.newCall(episodeListRequest(anime, page, lang))
|
||||
|
@ -91,7 +90,7 @@ class KickAssAnime : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||
|
||||
override fun fetchEpisodeList(anime: SAnime): Observable<List<SEpisode>> {
|
||||
val languages = client.newCall(
|
||||
GET("$API_URL${anime.url}/language"),
|
||||
GET("$apiUrl${anime.url}/language"),
|
||||
).execute().parseAs<LanguagesDto>()
|
||||
val prefLang = preferences.getString(PREF_AUDIO_LANG_KEY, PREF_AUDIO_LANG_DEFAULT)!!
|
||||
val lang = languages.result.firstOrNull { it == prefLang } ?: PREF_AUDIO_LANG_DEFAULT
|
||||
|
@ -123,7 +122,7 @@ class KickAssAnime : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||
|
||||
// ============================ Video Links =============================
|
||||
override fun videoListRequest(episode: SEpisode): Request {
|
||||
val url = API_URL + episode.url.replace("/ep-", "/episode/ep-")
|
||||
val url = apiUrl + episode.url.replace("/ep-", "/episode/ep-")
|
||||
return GET(url)
|
||||
}
|
||||
|
||||
|
@ -138,7 +137,7 @@ class KickAssAnime : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||
// tested with extensions-lib:9d3dcb0
|
||||
// override fun getAnimeUrl(anime: SAnime) = "$baseUrl${anime.url}"
|
||||
|
||||
override fun animeDetailsRequest(anime: SAnime) = GET("$API_URL${anime.url}")
|
||||
override fun animeDetailsRequest(anime: SAnime) = GET("$apiUrl${anime.url}")
|
||||
|
||||
override fun animeDetailsParse(response: Response): SAnime {
|
||||
val languages = client.newCall(
|
||||
|
@ -215,7 +214,7 @@ class KickAssAnime : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||
}
|
||||
|
||||
// ============================== Filters ===============================
|
||||
override fun getFilterList(): AnimeFilterList = KickAssAnimeFilters.filterList
|
||||
override fun getFilterList(): AnimeFilterList = KickAssAnimeFilters.FILTER_LIST
|
||||
|
||||
// =============================== Latest ===============================
|
||||
override fun latestUpdatesParse(response: Response): AnimesPage {
|
||||
|
@ -224,7 +223,7 @@ class KickAssAnime : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||
return AnimesPage(animes, data.hadNext)
|
||||
}
|
||||
|
||||
override fun latestUpdatesRequest(page: Int) = GET("$API_URL/recent?type=all&page=$page")
|
||||
override fun latestUpdatesRequest(page: Int) = GET("$apiUrl/recent?type=all&page=$page")
|
||||
|
||||
// ============================== Settings ==============================
|
||||
override fun setupPreferenceScreen(screen: PreferenceScreen) {
|
||||
|
@ -243,8 +242,8 @@ class KickAssAnime : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||
val audioLangPref = ListPreference(screen.context).apply {
|
||||
key = PREF_AUDIO_LANG_KEY
|
||||
title = PREF_AUDIO_LANG_TITLE
|
||||
entries = locale.map { it.second }.toTypedArray()
|
||||
entryValues = locale.map { it.first }.toTypedArray()
|
||||
entries = LOCALE.map { it.second }.toTypedArray()
|
||||
entryValues = LOCALE.map { it.first }.toTypedArray()
|
||||
setDefaultValue(PREF_AUDIO_LANG_DEFAULT)
|
||||
summary = "%s"
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
|
@ -258,8 +257,8 @@ class KickAssAnime : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||
val videoQualityPref = ListPreference(screen.context).apply {
|
||||
key = PREF_QUALITY_KEY
|
||||
title = PREF_QUALITY_TITLE
|
||||
entries = PREF_QUALITY_VALUES
|
||||
entryValues = PREF_QUALITY_VALUES
|
||||
entries = PREF_QUALITY_ENTRIES
|
||||
entryValues = PREF_QUALITY_ENTRIES
|
||||
setDefaultValue(PREF_QUALITY_DEFAULT)
|
||||
summary = "%s"
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
|
@ -296,7 +295,7 @@ class KickAssAnime : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||
}
|
||||
|
||||
private fun String.getLocale(): String {
|
||||
return locale.firstOrNull { it.first == this }?.second ?: ""
|
||||
return LOCALE.firstOrNull { it.first == this }?.second ?: ""
|
||||
}
|
||||
|
||||
private fun String.parseStatus() = when (this) {
|
||||
|
@ -327,14 +326,14 @@ class KickAssAnime : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||
private const val PREF_QUALITY_KEY = "preferred_quality"
|
||||
private const val PREF_QUALITY_TITLE = "Preferred quality"
|
||||
private const val PREF_QUALITY_DEFAULT = "720p"
|
||||
private val PREF_QUALITY_VALUES = arrayOf("240p", "360p", "480p", "720p", "1080p")
|
||||
private val PREF_QUALITY_ENTRIES = arrayOf("240p", "360p", "480p", "720p", "1080p")
|
||||
|
||||
private const val PREF_AUDIO_LANG_KEY = "preferred_audio_lang"
|
||||
private const val PREF_AUDIO_LANG_TITLE = "Preferred audio language"
|
||||
private const val PREF_AUDIO_LANG_DEFAULT = "ja-JP"
|
||||
|
||||
// Add new locales to the bottom so it doesn't mess with pref indexes
|
||||
private val locale = arrayOf(
|
||||
private val LOCALE = arrayOf(
|
||||
Pair("en-US", "English"),
|
||||
Pair("es-ES", "Spanish (España)"),
|
||||
Pair("ja-JP", "Japanese"),
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package eu.kanade.tachiyomi.animeextension.en.kickassanime
|
||||
|
||||
import eu.kanade.tachiyomi.animeextension.en.kickassanime.KickAssAnimeFilters.asQueryPart
|
||||
import eu.kanade.tachiyomi.animesource.model.AnimeFilter
|
||||
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
|
||||
|
||||
|
@ -26,15 +25,15 @@ object KickAssAnimeFilters {
|
|||
|
||||
class GenreFilter : CheckBoxFilterList(
|
||||
"Genre",
|
||||
KickAssAnimeFiltersData.genre.map { CheckBoxVal(it.first, false) },
|
||||
KickAssAnimeFiltersData.GENRE.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
class YearFilter : QueryPartFilter("Year", KickAssAnimeFiltersData.year)
|
||||
class StatusFilter : QueryPartFilter("Status", KickAssAnimeFiltersData.status)
|
||||
class TypeFilter : QueryPartFilter("Type", KickAssAnimeFiltersData.type)
|
||||
class SubPageFilter : QueryPartFilter("Sub-page", KickAssAnimeFiltersData.subpage)
|
||||
class YearFilter : QueryPartFilter("Year", KickAssAnimeFiltersData.YEAR)
|
||||
class StatusFilter : QueryPartFilter("Status", KickAssAnimeFiltersData.STATUS)
|
||||
class TypeFilter : QueryPartFilter("Type", KickAssAnimeFiltersData.TYPE)
|
||||
class SubPageFilter : QueryPartFilter("Sub-page", KickAssAnimeFiltersData.SUBPAGE)
|
||||
|
||||
val filterList = AnimeFilterList(
|
||||
val FILTER_LIST = AnimeFilterList(
|
||||
GenreFilter(),
|
||||
YearFilter(),
|
||||
StatusFilter(),
|
||||
|
@ -64,7 +63,7 @@ object KickAssAnimeFilters {
|
|||
.first()
|
||||
.state.mapNotNull { format ->
|
||||
if (format.state) {
|
||||
KickAssAnimeFiltersData.genre.find { it.first == format.name }!!.second
|
||||
KickAssAnimeFiltersData.GENRE.find { it.first == format.name }!!.second
|
||||
} else { null }
|
||||
}.joinToString(",") { "\"$it\"" }
|
||||
|
||||
|
@ -73,12 +72,12 @@ object KickAssAnimeFilters {
|
|||
val type = filters.asQueryPart<TypeFilter>()
|
||||
|
||||
val filtersQuery = "{${
|
||||
listOf(
|
||||
getJsonList(genre, "genres"),
|
||||
getJsonItem(year, "year"),
|
||||
getJsonItem(status, "status"),
|
||||
getJsonItem(type, "type"),
|
||||
).filter { it.isNotEmpty() }.joinToString(",")
|
||||
listOf(
|
||||
getJsonList(genre, "genres"),
|
||||
getJsonItem(year, "year"),
|
||||
getJsonItem(status, "status"),
|
||||
getJsonItem(type, "type"),
|
||||
).filter { it.isNotEmpty() }.joinToString(",")
|
||||
}}"
|
||||
return FilterSearchParams(
|
||||
filtersQuery,
|
||||
|
@ -87,7 +86,7 @@ object KickAssAnimeFilters {
|
|||
}
|
||||
|
||||
private object KickAssAnimeFiltersData {
|
||||
val genre = arrayOf(
|
||||
val GENRE = arrayOf(
|
||||
Pair("Action", "Action"),
|
||||
Pair("Adult Cast", "Adult Cast"),
|
||||
Pair("Adventure", "Adventure"),
|
||||
|
@ -166,7 +165,7 @@ object KickAssAnimeFilters {
|
|||
Pair("Workplace", "Workplace"),
|
||||
)
|
||||
|
||||
val year = arrayOf(
|
||||
val YEAR = arrayOf(
|
||||
Pair("All", ""),
|
||||
Pair("1917", "1917"),
|
||||
Pair("1918", "1918"),
|
||||
|
@ -272,13 +271,13 @@ object KickAssAnimeFilters {
|
|||
Pair("2023", "2023"),
|
||||
)
|
||||
|
||||
val status = arrayOf(
|
||||
val STATUS = arrayOf(
|
||||
Pair("All", ""),
|
||||
Pair("Finished Airing", "\"finished\""),
|
||||
Pair("Currently Airing", "\"airing\""),
|
||||
)
|
||||
|
||||
val type = arrayOf(
|
||||
val TYPE = arrayOf(
|
||||
Pair("All", ""),
|
||||
Pair("TV", "\"tv\""),
|
||||
Pair("OVA", "\"ova\""),
|
||||
|
@ -289,7 +288,7 @@ object KickAssAnimeFilters {
|
|||
Pair("MUSIC", "\"music\""),
|
||||
)
|
||||
|
||||
val subpage = arrayOf(
|
||||
val SUBPAGE = arrayOf(
|
||||
Pair("<Select>", ""),
|
||||
Pair("Trending", "show/trending"),
|
||||
Pair("Anime", "anime"),
|
||||
|
|
|
@ -13,7 +13,7 @@ import kotlin.system.exitProcess
|
|||
*/
|
||||
class KickAssAnimeUrlActivity : Activity() {
|
||||
|
||||
private val TAG = javaClass.simpleName
|
||||
private val tag = javaClass.simpleName
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
@ -29,10 +29,10 @@ class KickAssAnimeUrlActivity : Activity() {
|
|||
try {
|
||||
startActivity(mainIntent)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
Log.e(TAG, e.toString())
|
||||
Log.e(tag, e.toString())
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "could not parse uri from intent $intent")
|
||||
Log.e(tag, "could not parse uri from intent $intent")
|
||||
}
|
||||
|
||||
finish()
|
||||
|
|
|
@ -15,7 +15,7 @@ import java.util.concurrent.TimeUnit
|
|||
|
||||
class AESKeyExtractor(private val client: OkHttpClient) {
|
||||
companion object {
|
||||
val keyMap = mutableMapOf(
|
||||
val KEY_MAP = mutableMapOf(
|
||||
// Default key. if it changes, the extractor will update it.
|
||||
"PinkBird" to "7191d608bd4deb4dc36f656c4bbca1b7".toByteArray(),
|
||||
"SapphireDuck" to "f04274d54a9e01ed4a728c5c1889886e".toByteArray(), // i hate sapphire
|
||||
|
@ -23,7 +23,7 @@ class AESKeyExtractor(private val client: OkHttpClient) {
|
|||
|
||||
private const val ERROR_MSG_GENERIC = "the AES key was not found."
|
||||
private const val ERROR_MSG_VAR = "the AES key variable was not found"
|
||||
private val keyVarRegex by lazy { Regex("\\.AES\\[.*?\\]\\((\\w+)\\),") }
|
||||
private val KEY_VAR_REGEX by lazy { Regex("\\.AES\\[.*?\\]\\((\\w+)\\),") }
|
||||
}
|
||||
|
||||
private val context = Injekt.get<Application>()
|
||||
|
@ -32,7 +32,7 @@ class AESKeyExtractor(private val client: OkHttpClient) {
|
|||
class ExtractorJSI(private val latch: CountDownLatch, private val prefix: String) {
|
||||
@JavascriptInterface
|
||||
fun setKey(key: String) {
|
||||
AESKeyExtractor.keyMap.set(prefix, key.toByteArray())
|
||||
AESKeyExtractor.KEY_MAP.set(prefix, key.toByteArray())
|
||||
latch.countDown()
|
||||
}
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ class AESKeyExtractor(private val client: OkHttpClient) {
|
|||
webView = null
|
||||
}
|
||||
|
||||
return AESKeyExtractor.keyMap.get(prefix) ?: throw Exception(ERROR_MSG_GENERIC)
|
||||
return AESKeyExtractor.KEY_MAP.get(prefix) ?: throw Exception(ERROR_MSG_GENERIC)
|
||||
}
|
||||
|
||||
private fun patchScriptFromUrl(url: String): String {
|
||||
|
@ -94,7 +94,7 @@ class AESKeyExtractor(private val client: OkHttpClient) {
|
|||
val scriptUrl = "$baseUrl/$scriptPath"
|
||||
val scriptBody = client.newCall(GET(scriptUrl)).execute().body.string()
|
||||
|
||||
val varWithKeyName = keyVarRegex.find(scriptBody)
|
||||
val varWithKeyName = KEY_VAR_REGEX.find(scriptBody)
|
||||
?.groupValues
|
||||
?.last()
|
||||
?: Exception(ERROR_MSG_VAR)
|
||||
|
|
|
@ -7,7 +7,6 @@ import eu.kanade.tachiyomi.animesource.model.Video
|
|||
import eu.kanade.tachiyomi.lib.cryptoaes.CryptoAES
|
||||
import eu.kanade.tachiyomi.lib.cryptoaes.CryptoAES.decodeHex
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.Headers
|
||||
import okhttp3.OkHttpClient
|
||||
|
@ -31,7 +30,7 @@ class KickAssAnimeExtractor(
|
|||
val html = client.newCall(GET(url, headers)).execute().body.string()
|
||||
|
||||
val prefix = if ("pink" in url) "PinkBird" else "SapphireDuck"
|
||||
val key = AESKeyExtractor.keyMap.get(prefix)
|
||||
val key = AESKeyExtractor.KEY_MAP.get(prefix)
|
||||
?: AESKeyExtractor(client).getKeyFromHtml(baseUrl, html, prefix)
|
||||
|
||||
val request = sourcesRequest(baseUrl, url, html, query, key)
|
||||
|
|
|
@ -62,7 +62,7 @@ class KissAnime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
}
|
||||
|
||||
companion object {
|
||||
private val DateFormatter by lazy {
|
||||
private val DATE_FORMATTER by lazy {
|
||||
SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH)
|
||||
}
|
||||
}
|
||||
|
@ -141,7 +141,7 @@ class KissAnime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
|
||||
// ============================== FILTERS ===============================
|
||||
|
||||
override fun getFilterList(): AnimeFilterList = KissAnimeFilters.filterList
|
||||
override fun getFilterList(): AnimeFilterList = KissAnimeFilters.FILTER_LIST
|
||||
|
||||
// =========================== Anime Details ============================
|
||||
|
||||
|
@ -308,7 +308,7 @@ class KissAnime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
)
|
||||
|
||||
private fun parseDate(dateStr: String): Long {
|
||||
return runCatching { DateFormatter.parse(dateStr)?.time }
|
||||
return runCatching { DATE_FORMATTER.parse(dateStr)?.time }
|
||||
.getOrNull() ?: 0L
|
||||
}
|
||||
|
||||
|
|
|
@ -23,18 +23,18 @@ object KissAnimeFilters {
|
|||
}
|
||||
}
|
||||
|
||||
class StatusFilter : QueryPartFilter("Status", KissAnimeFiltersData.status)
|
||||
class StatusFilter : QueryPartFilter("Status", KissAnimeFiltersData.STATUS)
|
||||
|
||||
class GenreFilter : CheckBoxFilterList(
|
||||
"Genre",
|
||||
KissAnimeFiltersData.genre.map { CheckBoxVal(it.first, false) },
|
||||
KissAnimeFiltersData.GENRE.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
class SubPageFilter : QueryPartFilter("Sub-page", KissAnimeFiltersData.subpage)
|
||||
class SubPageFilter : QueryPartFilter("Sub-page", KissAnimeFiltersData.SUBPAGE)
|
||||
|
||||
class ScheduleFilter : QueryPartFilter("Schedule", KissAnimeFiltersData.schedule)
|
||||
class ScheduleFilter : QueryPartFilter("Schedule", KissAnimeFiltersData.SCHEDULE)
|
||||
|
||||
val filterList = AnimeFilterList(
|
||||
val FILTER_LIST = AnimeFilterList(
|
||||
StatusFilter(),
|
||||
GenreFilter(),
|
||||
AnimeFilter.Separator(),
|
||||
|
@ -57,7 +57,7 @@ object KissAnimeFilters {
|
|||
.first()
|
||||
.state.mapNotNull { format ->
|
||||
if (format.state) {
|
||||
KissAnimeFiltersData.genre.find { it.first == format.name }!!.second
|
||||
KissAnimeFiltersData.GENRE.find { it.first == format.name }!!.second
|
||||
} else { null }
|
||||
}.joinToString(separator = "")
|
||||
|
||||
|
@ -70,13 +70,13 @@ object KissAnimeFilters {
|
|||
}
|
||||
|
||||
private object KissAnimeFiltersData {
|
||||
val status = arrayOf(
|
||||
val STATUS = arrayOf(
|
||||
Pair("Any", ""),
|
||||
Pair("Ongoing", "upcoming"),
|
||||
Pair("Completed", "complete"),
|
||||
)
|
||||
|
||||
val genre = arrayOf(
|
||||
val GENRE = arrayOf(
|
||||
Pair("Action", "Action_"),
|
||||
Pair("Adventure", "Adventure_"),
|
||||
Pair("Cars", "Cars_"),
|
||||
|
@ -126,7 +126,7 @@ object KissAnimeFilters {
|
|||
Pair("Yuri", "Yuri_"),
|
||||
)
|
||||
|
||||
val subpage = arrayOf(
|
||||
val SUBPAGE = arrayOf(
|
||||
Pair("<select>", ""),
|
||||
Pair("List A-Z", "AnimeListOnline"),
|
||||
Pair("List Most Popular", "AnimeListOnline/MostPopular"),
|
||||
|
@ -135,7 +135,7 @@ object KissAnimeFilters {
|
|||
Pair("List New Anime", "AnimeListOnline/Newest"),
|
||||
)
|
||||
|
||||
val schedule = arrayOf(
|
||||
val SCHEDULE = arrayOf(
|
||||
Pair("<select>", ""),
|
||||
Pair("Yesterday", "Yesterday"),
|
||||
Pair("Today", "Today"),
|
||||
|
|
|
@ -17,7 +17,6 @@ import eu.kanade.tachiyomi.network.GET
|
|||
import eu.kanade.tachiyomi.network.POST
|
||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
|
@ -111,7 +110,7 @@ class MarinMoe : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||
return parseAnime(response)
|
||||
}
|
||||
|
||||
override fun getFilterList(): AnimeFilterList = MarinMoeFilters.filterList
|
||||
override fun getFilterList(): AnimeFilterList = MarinMoeFilters.FILTER_LIST
|
||||
|
||||
// =========================== Anime Details ============================
|
||||
|
||||
|
@ -338,8 +337,8 @@ class MarinMoe : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||
val groupPref = ListPreference(screen.context).apply {
|
||||
key = "preferred_group"
|
||||
title = "Preferred group"
|
||||
entries = MarinMoeConstants.groupEntries
|
||||
entryValues = MarinMoeConstants.groupEntryValues
|
||||
entries = MarinMoeConstants.GROUP_ENTRIES
|
||||
entryValues = MarinMoeConstants.GROUP_ENTRY_VALUES
|
||||
setDefaultValue("site_default")
|
||||
summary = "%s"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package eu.kanade.tachiyomi.animeextension.en.marinmoe
|
||||
|
||||
object MarinMoeConstants {
|
||||
val groupEntries = arrayOf(
|
||||
val GROUP_ENTRIES = arrayOf(
|
||||
"Site Default", "-__-`", "-.-", "Abstinence", "AC_", "ADZ Subs", "Afternoon Naps Empire", "Almighty", "Alt",
|
||||
"Anime Noobs Fansubbers", "Anime-4ever", "Anime-Conan", "Anime-Destiny", "Anime-Empire", "Anime-FanRips",
|
||||
"Anime-Fury", "Anime-Jiyuu", "Anime-Supreme", "anime4life.", "AnimeBytes Remuxes", "AnimeOne", "AnimeSenshi Subs",
|
||||
|
@ -52,7 +52,7 @@ object MarinMoeConstants {
|
|||
"Zurako Subs",
|
||||
)
|
||||
|
||||
val groupEntryValues = arrayOf(
|
||||
val GROUP_ENTRY_VALUES = arrayOf(
|
||||
"site_default", "-__-`", "-.-", "Abstinence", "AC", "ADZ", "ANE", "Almighty", "Alt", "anfs", "a4e", "AConan", "A-Destiny", "A-E",
|
||||
"A-FanRips", "A-Fury", "Ani-Jiyuu", "a-S", "anime4life.", "AB-RMX", "AonE", "Asenshi", "AnY", "None", "ARR",
|
||||
"AOmundson", "ARC", "Aria", "Arid", "None", "aro", "Asakura", "ASC", "Asteroid", "AtlasSubbed", "Ayashii", "AZFS",
|
||||
|
|
|
@ -23,38 +23,38 @@ object MarinMoeFilters {
|
|||
}
|
||||
}
|
||||
|
||||
class SortFilter : QueryPartFilter("Sort order", MarinMoeFiltersData.sort)
|
||||
class SortFilter : QueryPartFilter("Sort order", MarinMoeFiltersData.SORT)
|
||||
|
||||
class TypeFilter : CheckBoxFilterList(
|
||||
"Type",
|
||||
MarinMoeFiltersData.types.map { CheckBoxVal(it.first, true) },
|
||||
MarinMoeFiltersData.TYPES.map { CheckBoxVal(it.first, true) },
|
||||
)
|
||||
|
||||
class StatusFilter : CheckBoxFilterList(
|
||||
"Status",
|
||||
MarinMoeFiltersData.status.map { CheckBoxVal(it.first, true) },
|
||||
MarinMoeFiltersData.STATUS.map { CheckBoxVal(it.first, true) },
|
||||
)
|
||||
|
||||
class ContentRatingFilter : CheckBoxFilterList(
|
||||
"Content Rating",
|
||||
MarinMoeFiltersData.contentRating.map { CheckBoxVal(it.first, true) },
|
||||
MarinMoeFiltersData.CONTENT_RATING.map { CheckBoxVal(it.first, true) },
|
||||
)
|
||||
|
||||
class SourceFilter : CheckBoxFilterList(
|
||||
"Source",
|
||||
MarinMoeFiltersData.source.map { CheckBoxVal(it.first, false) },
|
||||
MarinMoeFiltersData.SOURCE.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
class GenreFilter : CheckBoxFilterList(
|
||||
"Genre",
|
||||
MarinMoeFiltersData.genre.map { CheckBoxVal(it.first, false) },
|
||||
MarinMoeFiltersData.GENRE.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
class GroupFilter : QueryPartFilter("Group", MarinMoeFiltersData.groups)
|
||||
class GroupFilter : QueryPartFilter("Group", MarinMoeFiltersData.GROUPS)
|
||||
|
||||
class StudioFilter : QueryPartFilter("Studio", MarinMoeFiltersData.studios)
|
||||
class StudioFilter : QueryPartFilter("Studio", MarinMoeFiltersData.STUDIOS)
|
||||
|
||||
val filterList = AnimeFilterList(
|
||||
val FILTER_LIST = AnimeFilterList(
|
||||
SortFilter(),
|
||||
AnimeFilter.Separator(),
|
||||
TypeFilter(),
|
||||
|
@ -93,7 +93,7 @@ object MarinMoeFilters {
|
|||
.first()
|
||||
.state.mapNotNull { format ->
|
||||
if (!format.state) {
|
||||
MarinMoeFiltersData.types.find { it.first == format.name }!!.second
|
||||
MarinMoeFiltersData.TYPES.find { it.first == format.name }!!.second
|
||||
} else { null }
|
||||
},
|
||||
)
|
||||
|
@ -104,7 +104,7 @@ object MarinMoeFilters {
|
|||
.first()
|
||||
.state.mapNotNull { format ->
|
||||
if (!format.state) {
|
||||
MarinMoeFiltersData.status.find { it.first == format.name }!!.second
|
||||
MarinMoeFiltersData.STATUS.find { it.first == format.name }!!.second
|
||||
} else { null }
|
||||
},
|
||||
)
|
||||
|
@ -115,7 +115,7 @@ object MarinMoeFilters {
|
|||
.first()
|
||||
.state.mapNotNull { format ->
|
||||
if (!format.state) {
|
||||
MarinMoeFiltersData.contentRating.find { it.first == format.name }!!.second
|
||||
MarinMoeFiltersData.CONTENT_RATING.find { it.first == format.name }!!.second
|
||||
} else { null }
|
||||
},
|
||||
)
|
||||
|
@ -124,7 +124,7 @@ object MarinMoeFilters {
|
|||
.first()
|
||||
.state.mapNotNull { format ->
|
||||
if (format.state) {
|
||||
MarinMoeFiltersData.source.find { it.first == format.name }!!.second
|
||||
MarinMoeFiltersData.SOURCE.find { it.first == format.name }!!.second
|
||||
} else { null }
|
||||
}.withIndex().joinToString(separator = "&") {
|
||||
"filter[source][${it.index}][id]=${it.value}&filter[source][${it.index}][opr]=include"
|
||||
|
@ -134,7 +134,7 @@ object MarinMoeFilters {
|
|||
.first()
|
||||
.state.mapNotNull { format ->
|
||||
if (format.state) {
|
||||
MarinMoeFiltersData.genre.find { it.first == format.name }!!.second
|
||||
MarinMoeFiltersData.GENRE.find { it.first == format.name }!!.second
|
||||
} else { null }
|
||||
}.withIndex().joinToString(separator = "&") {
|
||||
"filter[genre][${it.index}][id]=${it.value}&filter[genre][${it.index}][opr]=include"
|
||||
|
@ -153,7 +153,7 @@ object MarinMoeFilters {
|
|||
}
|
||||
|
||||
private object MarinMoeFiltersData {
|
||||
val sort = arrayOf(
|
||||
val SORT = arrayOf(
|
||||
Pair("A to Z", "az-a"),
|
||||
Pair("Z to A", "az-d"),
|
||||
Pair("Earliest Released", "rel-a"),
|
||||
|
@ -172,7 +172,7 @@ object MarinMoeFilters {
|
|||
Pair("Most Popular This Year", "vyr-d"),
|
||||
)
|
||||
|
||||
val types = arrayOf(
|
||||
val TYPES = arrayOf(
|
||||
Pair("Unknown", "1"),
|
||||
Pair("TV Series", "2"),
|
||||
Pair("OVA", "3"),
|
||||
|
@ -183,14 +183,14 @@ object MarinMoeFilters {
|
|||
Pair("Other", "8"),
|
||||
)
|
||||
|
||||
val status = arrayOf(
|
||||
val STATUS = arrayOf(
|
||||
Pair("Unknown", "1"),
|
||||
Pair("Ongoing", "2"),
|
||||
Pair("Completed", "3"),
|
||||
Pair("Stalled", "4"),
|
||||
)
|
||||
|
||||
val contentRating = arrayOf(
|
||||
val CONTENT_RATING = arrayOf(
|
||||
Pair("Unknown", "1"),
|
||||
Pair("PG - Children", "2"),
|
||||
Pair("PG-13 - Teens 13 or older", "3"),
|
||||
|
@ -200,7 +200,7 @@ object MarinMoeFilters {
|
|||
Pair("G - All Ages", "7"),
|
||||
)
|
||||
|
||||
val source = arrayOf(
|
||||
val SOURCE = arrayOf(
|
||||
Pair("Blu-ray", "5"),
|
||||
Pair("DVD", "4"),
|
||||
Pair("LD", "8"),
|
||||
|
@ -211,7 +211,7 @@ object MarinMoeFilters {
|
|||
Pair("Web", "3"),
|
||||
)
|
||||
|
||||
val genre = arrayOf(
|
||||
val GENRE = arrayOf(
|
||||
Pair("Action", "1"),
|
||||
Pair("Adult Cast", "55"),
|
||||
Pair("Adventure", "15"),
|
||||
|
@ -287,7 +287,7 @@ object MarinMoeFilters {
|
|||
Pair("Workplace", "42"),
|
||||
)
|
||||
|
||||
val groups = arrayOf(
|
||||
val GROUPS = arrayOf(
|
||||
Pair("All", ""),
|
||||
Pair("-__-`", "279"),
|
||||
Pair("-.-", "221"),
|
||||
|
@ -630,7 +630,7 @@ object MarinMoeFilters {
|
|||
Pair("Zurako Subs", "283"),
|
||||
)
|
||||
|
||||
val studios = arrayOf(
|
||||
val STUDIOS = arrayOf(
|
||||
Pair("All", ""),
|
||||
Pair("3xCube", "432"),
|
||||
Pair("4Kids Entertainment", "340"),
|
||||
|
|
|
@ -5,7 +5,6 @@ import eu.kanade.tachiyomi.animesource.model.Track
|
|||
import eu.kanade.tachiyomi.animesource.model.Video
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.Headers
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
|
@ -106,7 +105,7 @@ class RabbitStreamExtractor(private val client: OkHttpClient) {
|
|||
val salt = saltedData.copyOfRange(8, 16)
|
||||
val ciphertext = saltedData.copyOfRange(16, saltedData.size)
|
||||
val password = remoteKey.toByteArray()
|
||||
val (key, iv) = GenerateKeyAndIv(password, salt) ?: return null
|
||||
val (key, iv) = generateKeyAndIv(password, salt) ?: return null
|
||||
val keySpec = SecretKeySpec(key, "AES")
|
||||
val ivSpec = IvParameterSpec(iv)
|
||||
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
|
||||
|
@ -116,7 +115,7 @@ class RabbitStreamExtractor(private val client: OkHttpClient) {
|
|||
}
|
||||
|
||||
// https://stackoverflow.com/a/41434590/8166854
|
||||
private fun GenerateKeyAndIv(
|
||||
private fun generateKeyAndIv(
|
||||
password: ByteArray,
|
||||
salt: ByteArray,
|
||||
hashAlgorithm: String = "MD5",
|
||||
|
|
|
@ -58,7 +58,7 @@ class Myanime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
}
|
||||
|
||||
companion object {
|
||||
private val DateFormatter by lazy {
|
||||
private val DATE_FORMATTER by lazy {
|
||||
SimpleDateFormat("d MMMM yyyy", Locale.ENGLISH)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import dev.datlag.jsunpacker.JsUnpacker
|
|||
import eu.kanade.tachiyomi.animesource.model.Track
|
||||
import eu.kanade.tachiyomi.animesource.model.Video
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
|
@ -74,7 +73,7 @@ class GdrivePlayerExtractor(private val client: OkHttpClient) {
|
|||
val salt = json["s"]!!.jsonPrimitive.content
|
||||
val encodedCiphetext = json["ct"]!!.jsonPrimitive.content
|
||||
val ciphertext = Base64.decode(encodedCiphetext, Base64.DEFAULT)
|
||||
val (key, iv) = GenerateKeyAndIv(password, salt.decodeHex())
|
||||
val (key, iv) = generateKeyAndIv(password, salt.decodeHex())
|
||||
?: return null
|
||||
val keySpec = SecretKeySpec(key, "AES")
|
||||
val ivSpec = IvParameterSpec(iv)
|
||||
|
@ -85,7 +84,7 @@ class GdrivePlayerExtractor(private val client: OkHttpClient) {
|
|||
}
|
||||
|
||||
// https://stackoverflow.com/a/41434590/8166854
|
||||
private fun GenerateKeyAndIv(
|
||||
private fun generateKeyAndIv(
|
||||
password: ByteArray,
|
||||
salt: ByteArray,
|
||||
hashAlgorithm: String = "MD5",
|
||||
|
|
|
@ -127,7 +127,7 @@ class NineAnime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
|
||||
override fun searchAnimeNextPageSelector(): String = popularAnimeNextPageSelector()
|
||||
|
||||
override fun getFilterList(): AnimeFilterList = NineAnimeFilters.filterList
|
||||
override fun getFilterList(): AnimeFilterList = NineAnimeFilters.FILTER_LIST
|
||||
|
||||
// =========================== Anime Details ============================
|
||||
|
||||
|
@ -297,8 +297,8 @@ class NineAnime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
}
|
||||
"streamtape" -> StreamTapeExtractor(client)
|
||||
.videoFromUrl(embedLink, "StreamTape - ${server.first}")?.let {
|
||||
videoList.add(it)
|
||||
}
|
||||
videoList.add(it)
|
||||
}
|
||||
"mp4upload" -> Mp4uploadExtractor(client)
|
||||
.videoFromUrl(embedLink, "Mp4Upload - ${server.first}").let {
|
||||
videoList.addAll(it)
|
||||
|
|
|
@ -47,49 +47,49 @@ object NineAnimeFilters {
|
|||
}
|
||||
}
|
||||
|
||||
class SortFilter : QueryPartFilter("Sort order", NineAnimeFiltersData.sort)
|
||||
class SortFilter : QueryPartFilter("Sort order", NineAnimeFiltersData.SORT)
|
||||
|
||||
class GenreFilter : CheckBoxFilterList(
|
||||
"Genre",
|
||||
NineAnimeFiltersData.genre.map { CheckBoxVal(it.first, false) },
|
||||
NineAnimeFiltersData.GENRE.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
class CountryFilter : CheckBoxFilterList(
|
||||
"Country",
|
||||
NineAnimeFiltersData.country.map { CheckBoxVal(it.first, false) },
|
||||
NineAnimeFiltersData.COUNTRY.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
class SeasonFilter : CheckBoxFilterList(
|
||||
"Season",
|
||||
NineAnimeFiltersData.season.map { CheckBoxVal(it.first, false) },
|
||||
NineAnimeFiltersData.SEASON.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
class YearFilter : CheckBoxFilterList(
|
||||
"Year",
|
||||
NineAnimeFiltersData.year.map { CheckBoxVal(it.first, false) },
|
||||
NineAnimeFiltersData.YEAR.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
class TypeFilter : CheckBoxFilterList(
|
||||
"Type",
|
||||
NineAnimeFiltersData.type.map { CheckBoxVal(it.first, false) },
|
||||
NineAnimeFiltersData.TYPE.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
class StatusFilter : CheckBoxFilterList(
|
||||
"Status",
|
||||
NineAnimeFiltersData.status.map { CheckBoxVal(it.first, false) },
|
||||
NineAnimeFiltersData.STATUS.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
class LanguageFilter : CheckBoxFilterList(
|
||||
"Language",
|
||||
NineAnimeFiltersData.language.map { CheckBoxVal(it.first, false) },
|
||||
NineAnimeFiltersData.LANGUAGE.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
class RatingFilter : CheckBoxFilterList(
|
||||
"Rating",
|
||||
NineAnimeFiltersData.rating.map { CheckBoxVal(it.first, false) },
|
||||
NineAnimeFiltersData.RATING.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
val filterList = AnimeFilterList(
|
||||
val FILTER_LIST = AnimeFilterList(
|
||||
SortFilter(),
|
||||
AnimeFilter.Separator(),
|
||||
GenreFilter(),
|
||||
|
@ -119,19 +119,19 @@ object NineAnimeFilters {
|
|||
|
||||
return FilterSearchParams(
|
||||
filters.asQueryPart<SortFilter>(),
|
||||
filters.parseCheckbox<GenreFilter>(NineAnimeFiltersData.genre, "genre"),
|
||||
filters.parseCheckbox<CountryFilter>(NineAnimeFiltersData.country, "country"),
|
||||
filters.parseCheckbox<SeasonFilter>(NineAnimeFiltersData.season, "season"),
|
||||
filters.parseCheckbox<YearFilter>(NineAnimeFiltersData.year, "year"),
|
||||
filters.parseCheckbox<TypeFilter>(NineAnimeFiltersData.type, "type"),
|
||||
filters.parseCheckbox<StatusFilter>(NineAnimeFiltersData.status, "status"),
|
||||
filters.parseCheckbox<LanguageFilter>(NineAnimeFiltersData.language, "language"),
|
||||
filters.parseCheckbox<RatingFilter>(NineAnimeFiltersData.rating, "rating"),
|
||||
filters.parseCheckbox<GenreFilter>(NineAnimeFiltersData.GENRE, "genre"),
|
||||
filters.parseCheckbox<CountryFilter>(NineAnimeFiltersData.COUNTRY, "country"),
|
||||
filters.parseCheckbox<SeasonFilter>(NineAnimeFiltersData.SEASON, "season"),
|
||||
filters.parseCheckbox<YearFilter>(NineAnimeFiltersData.YEAR, "year"),
|
||||
filters.parseCheckbox<TypeFilter>(NineAnimeFiltersData.TYPE, "type"),
|
||||
filters.parseCheckbox<StatusFilter>(NineAnimeFiltersData.STATUS, "status"),
|
||||
filters.parseCheckbox<LanguageFilter>(NineAnimeFiltersData.LANGUAGE, "language"),
|
||||
filters.parseCheckbox<RatingFilter>(NineAnimeFiltersData.RATING, "rating"),
|
||||
)
|
||||
}
|
||||
|
||||
private object NineAnimeFiltersData {
|
||||
val sort = arrayOf(
|
||||
val SORT = arrayOf(
|
||||
Pair("Most relevance", "most_relevance"),
|
||||
Pair("Recently updated", "recently_updated"),
|
||||
Pair("Recently added", "recently_added"),
|
||||
|
@ -145,7 +145,7 @@ object NineAnimeFilters {
|
|||
Pair("Number of episodes", "number_of_episodes"),
|
||||
)
|
||||
|
||||
val genre = arrayOf(
|
||||
val GENRE = arrayOf(
|
||||
Pair("Action", "1"),
|
||||
Pair("Adventure", "2"),
|
||||
Pair("Avant Garde", "2262888"),
|
||||
|
@ -189,12 +189,12 @@ object NineAnimeFilters {
|
|||
Pair("Vampire", "41"),
|
||||
)
|
||||
|
||||
val country = arrayOf(
|
||||
val COUNTRY = arrayOf(
|
||||
Pair("China", "120823"),
|
||||
Pair("Japan", "120822"),
|
||||
)
|
||||
|
||||
val season = arrayOf(
|
||||
val SEASON = arrayOf(
|
||||
Pair("Fall", "fall"),
|
||||
Pair("Summer", "summer"),
|
||||
Pair("Spring", "spring"),
|
||||
|
@ -202,7 +202,7 @@ object NineAnimeFilters {
|
|||
Pair("Unknown", "unknown"),
|
||||
)
|
||||
|
||||
val year = arrayOf(
|
||||
val YEAR = arrayOf(
|
||||
Pair("2023", "2023"),
|
||||
Pair("2022", "2022"),
|
||||
Pair("2021", "2021"),
|
||||
|
@ -236,7 +236,7 @@ object NineAnimeFilters {
|
|||
Pair("1910s", "1910s"),
|
||||
)
|
||||
|
||||
val type = arrayOf(
|
||||
val TYPE = arrayOf(
|
||||
Pair("Movie", "movie"),
|
||||
Pair("TV", "tv"),
|
||||
Pair("OVA", "ova"),
|
||||
|
@ -245,19 +245,19 @@ object NineAnimeFilters {
|
|||
Pair("Music", "music"),
|
||||
)
|
||||
|
||||
val status = arrayOf(
|
||||
val STATUS = arrayOf(
|
||||
Pair("Not Yet Aired", "info"),
|
||||
Pair("Releasing", "releasing"),
|
||||
Pair("Completed", "completed"),
|
||||
)
|
||||
|
||||
val language = arrayOf(
|
||||
val LANGUAGE = arrayOf(
|
||||
Pair("Sub and Dub", "subdub"),
|
||||
Pair("Sub", "sub"),
|
||||
Pair("Dub", "dub"),
|
||||
)
|
||||
|
||||
val rating = arrayOf(
|
||||
val RATING = arrayOf(
|
||||
Pair("G - All Ages", "g"),
|
||||
Pair("PG - Children", "pg"),
|
||||
Pair("PG 13 - Teens 13 and Older", "pg_13"),
|
||||
|
|
|
@ -246,7 +246,7 @@ class NollyVerse : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
animes = document.select(movieGenreSelector()).map { element ->
|
||||
movieGenreFromElement(element)
|
||||
}
|
||||
hasNextPage = NextPageSelector()?.let { selector ->
|
||||
hasNextPage = nextPageSelector()?.let { selector ->
|
||||
if (document.select(selector).text() != ">") {
|
||||
return AnimesPage(animes, false)
|
||||
}
|
||||
|
@ -260,7 +260,7 @@ class NollyVerse : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
animes = document.select(seriesGenreSelector()).map { element ->
|
||||
seriesGenreFromElement(element)
|
||||
}
|
||||
hasNextPage = NextPageSelector()?.let { selector ->
|
||||
hasNextPage = nextPageSelector()?.let { selector ->
|
||||
if (document.select(selector).text() != ">") {
|
||||
return AnimesPage(animes, false)
|
||||
}
|
||||
|
@ -272,7 +272,7 @@ class NollyVerse : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
animes = document.select(koreanSelector()).map { element ->
|
||||
koreanFromElement(element)
|
||||
}
|
||||
hasNextPage = NextPageSelector()?.let { selector ->
|
||||
hasNextPage = nextPageSelector()?.let { selector ->
|
||||
if (document.select(selector).text() != ">") {
|
||||
return AnimesPage(animes, false)
|
||||
}
|
||||
|
@ -286,7 +286,7 @@ class NollyVerse : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
animes = document.select(latestSelector()).map { element ->
|
||||
latestFromElement(element)
|
||||
}
|
||||
hasNextPage = NextPageSelector()?.let { selector ->
|
||||
hasNextPage = nextPageSelector()?.let { selector ->
|
||||
if (document.select(selector).text() != ">") {
|
||||
return AnimesPage(animes, false)
|
||||
}
|
||||
|
@ -305,7 +305,7 @@ class NollyVerse : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
animes = document.select(movieSelector()).map { element ->
|
||||
movieFromElement(element)
|
||||
}
|
||||
hasNextPage = NextPageSelector()?.let { selector ->
|
||||
hasNextPage = nextPageSelector()?.let { selector ->
|
||||
if (document.select(selector).text() != ">") {
|
||||
return AnimesPage(animes, false)
|
||||
}
|
||||
|
@ -317,7 +317,7 @@ class NollyVerse : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
return AnimesPage(animes, hasNextPage)
|
||||
}
|
||||
|
||||
private fun NextPageSelector(): String = "ul.pagination.pagination-md li:nth-last-child(2)"
|
||||
private fun nextPageSelector(): String = "ul.pagination.pagination-md li:nth-last-child(2)"
|
||||
|
||||
private fun movieGenreSelector(): String = "div.container > div.row > div.col-md-4"
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ class OppaiStream : ParsedAnimeHttpSource(), ConfigurableAnimeSource {
|
|||
else -> {}
|
||||
}
|
||||
addQueryParameter("page", page.toString())
|
||||
addQueryParameter("limit", searchLimit.toString())
|
||||
addQueryParameter("limit", SEARCH_LIMIT.toString())
|
||||
}
|
||||
}.build().toString()
|
||||
|
||||
|
@ -117,7 +117,7 @@ class OppaiStream : ParsedAnimeHttpSource(), ConfigurableAnimeSource {
|
|||
searchAnimeFromElement(element)
|
||||
}.distinctBy { it.title }
|
||||
|
||||
val hasNextPage = elements.size >= searchLimit
|
||||
val hasNextPage = elements.size >= SEARCH_LIMIT
|
||||
|
||||
return AnimesPage(mangas, hasNextPage)
|
||||
}
|
||||
|
@ -126,12 +126,12 @@ class OppaiStream : ParsedAnimeHttpSource(), ConfigurableAnimeSource {
|
|||
return SAnime.create().apply {
|
||||
thumbnail_url = element.select("img.cover-img-in").attr("abs:src")
|
||||
title = element.select(".title-ep").text()
|
||||
.replace(titleCleanupRegex, "")
|
||||
.replace(TITLE_CLEANUP_REGEX, "")
|
||||
setUrlWithoutDomain(element.selectFirst("a")!!.attr("href"))
|
||||
}
|
||||
}
|
||||
|
||||
override fun getFilterList() = filters
|
||||
override fun getFilterList() = FILTERS
|
||||
|
||||
// details
|
||||
override fun animeDetailsParse(document: Document): SAnime {
|
||||
|
@ -190,7 +190,7 @@ class OppaiStream : ParsedAnimeHttpSource(), ConfigurableAnimeSource {
|
|||
override fun setupPreferenceScreen(screen: PreferenceScreen) {
|
||||
ListPreference(screen.context).apply {
|
||||
key = PREF_QUALITY
|
||||
title = PREF_QUALITY_title
|
||||
title = PREF_QUALITY_TITLE
|
||||
entries = arrayOf("2160p", "1080p", "720p")
|
||||
entryValues = arrayOf("2160", "1080", "720")
|
||||
setDefaultValue("720")
|
||||
|
@ -201,10 +201,10 @@ class OppaiStream : ParsedAnimeHttpSource(), ConfigurableAnimeSource {
|
|||
}
|
||||
|
||||
companion object {
|
||||
private const val searchLimit = 36
|
||||
private val titleCleanupRegex = Regex("""\s+\d+$""")
|
||||
private const val SEARCH_LIMIT = 36
|
||||
private val TITLE_CLEANUP_REGEX = Regex("""\s+\d+$""")
|
||||
|
||||
private const val PREF_QUALITY = "preferred_quality"
|
||||
private const val PREF_QUALITY_title = "Preferred quality"
|
||||
private const val PREF_QUALITY_TITLE = "Preferred quality"
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue