Initial commit
This commit is contained in:
commit
98ed7e8839
2263 changed files with 108711 additions and 0 deletions
17
src/es/legionanime/build.gradle
Normal file
17
src/es/legionanime/build.gradle
Normal file
|
@ -0,0 +1,17 @@
|
|||
ext {
|
||||
extName = 'LegionAnime'
|
||||
extClass = '.LegionAnime'
|
||||
extVersionCode = 31
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
|
||||
dependencies {
|
||||
implementation(project(':lib:uqload-extractor'))
|
||||
implementation(project(':lib:mp4upload-extractor'))
|
||||
implementation(project(':lib:yourupload-extractor'))
|
||||
implementation(project(':lib:streamtape-extractor'))
|
||||
implementation(project(':lib:okru-extractor'))
|
||||
implementation(project(':lib:dood-extractor'))
|
||||
implementation(project(':lib:streamwish-extractor'))
|
||||
}
|
BIN
src/es/legionanime/res/mipmap-hdpi/ic_launcher.png
Normal file
BIN
src/es/legionanime/res/mipmap-hdpi/ic_launcher.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.6 KiB |
BIN
src/es/legionanime/res/mipmap-mdpi/ic_launcher.png
Normal file
BIN
src/es/legionanime/res/mipmap-mdpi/ic_launcher.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.5 KiB |
BIN
src/es/legionanime/res/mipmap-xhdpi/ic_launcher.png
Normal file
BIN
src/es/legionanime/res/mipmap-xhdpi/ic_launcher.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
BIN
src/es/legionanime/res/mipmap-xxhdpi/ic_launcher.png
Normal file
BIN
src/es/legionanime/res/mipmap-xxhdpi/ic_launcher.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
BIN
src/es/legionanime/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
BIN
src/es/legionanime/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 34 KiB |
|
@ -0,0 +1,479 @@
|
|||
package eu.kanade.tachiyomi.animeextension.es.legionanime
|
||||
|
||||
import android.app.Application
|
||||
import android.content.SharedPreferences
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.PreferenceScreen
|
||||
import eu.kanade.tachiyomi.animeextension.es.legionanime.extractors.JkanimeExtractor
|
||||
import eu.kanade.tachiyomi.animeextension.es.legionanime.extractors.MediaFireExtractor
|
||||
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
|
||||
import eu.kanade.tachiyomi.animesource.model.AnimeFilter
|
||||
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
|
||||
import eu.kanade.tachiyomi.animesource.model.AnimesPage
|
||||
import eu.kanade.tachiyomi.animesource.model.SAnime
|
||||
import eu.kanade.tachiyomi.animesource.model.SEpisode
|
||||
import eu.kanade.tachiyomi.animesource.model.Video
|
||||
import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
|
||||
import eu.kanade.tachiyomi.lib.doodextractor.DoodExtractor
|
||||
import eu.kanade.tachiyomi.lib.mp4uploadextractor.Mp4uploadExtractor
|
||||
import eu.kanade.tachiyomi.lib.okruextractor.OkruExtractor
|
||||
import eu.kanade.tachiyomi.lib.streamtapeextractor.StreamTapeExtractor
|
||||
import eu.kanade.tachiyomi.lib.streamwishextractor.StreamWishExtractor
|
||||
import eu.kanade.tachiyomi.lib.uqloadextractor.UqloadExtractor
|
||||
import eu.kanade.tachiyomi.lib.youruploadextractor.YourUploadExtractor
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.POST
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.jsonArray
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import okhttp3.FormBody
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class LegionAnime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
|
||||
override val name = "LegionAnime"
|
||||
|
||||
override val baseUrl = "https://legionanime.club/api"
|
||||
|
||||
override val lang = "es"
|
||||
|
||||
override val supportsLatest = true
|
||||
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
private val preferences: SharedPreferences by lazy {
|
||||
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
|
||||
}
|
||||
|
||||
private val headers1 = headersBuilder().add("json", JSON_STRING).add("User-Agent", "android l3gi0n4N1mE %E6%9C%AC%E7%89%A9").build()
|
||||
|
||||
override fun animeDetailsRequest(anime: SAnime): Request = episodeListRequest(anime)
|
||||
|
||||
override fun animeDetailsParse(document: Document): SAnime {
|
||||
val jsonResponse = json.decodeFromString<JsonObject>(document.body().text())["response"]!!.jsonObject
|
||||
val anime = jsonResponse["anime"]!!.jsonObject
|
||||
val studioId = anime["studios"]!!.jsonPrimitive.content.split(",")
|
||||
val studio = try { studioId.map { id -> STUDIOS_MAP.filter { it.value == id.toInt() }.keys.first() } } catch (e: Exception) { emptyList() }
|
||||
val malid = anime["mal_id"]!!.jsonPrimitive.content
|
||||
var thumb: String? = null
|
||||
|
||||
try {
|
||||
val jikanResponse = client.newCall(GET("https://api.jikan.moe/v4/anime/$malid")).execute().asJsoup().body().text()
|
||||
val jikanJson = json.decodeFromString<JsonObject>(jikanResponse)
|
||||
val pictures = jikanJson["data"]!!.jsonObject["images"]!!.jsonObject["jpg"]!!.jsonObject
|
||||
thumb = pictures["large_image_url"]!!.jsonPrimitive.content
|
||||
} catch (_: Exception) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
return SAnime.create().apply {
|
||||
title = anime["name"]!!.jsonPrimitive.content
|
||||
if (thumb != null) {
|
||||
thumbnail_url = thumb
|
||||
}
|
||||
description = anime["synopsis"]!!.jsonPrimitive.content
|
||||
genre = anime["genres"]!!.jsonPrimitive.content
|
||||
author = studio.joinToString { it.toString() }
|
||||
status = when (anime["status"]!!.jsonPrimitive.content) {
|
||||
"En emisión" -> SAnime.ONGOING
|
||||
"Finalizado" -> SAnime.COMPLETED
|
||||
else -> SAnime.UNKNOWN
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun episodeListRequest(anime: SAnime): Request = GET(anime.url, headers1)
|
||||
override fun episodeListParse(response: Response): List<SEpisode> {
|
||||
val jsonResponse = json.decodeFromString<JsonObject>(response.asJsoup().body().text())
|
||||
val episodes = jsonResponse["response"]!!.jsonObject["episodes"]!!.jsonArray
|
||||
|
||||
return episodes.map {
|
||||
SEpisode.create().apply {
|
||||
name = "Episodio " + it.jsonObject["name"]!!.jsonPrimitive.content
|
||||
url = "$baseUrl/v2/episode_links/${it.jsonObject["id"]!!.jsonPrimitive.content}"
|
||||
date_upload = parseDate(it.jsonObject["release_date"]!!.jsonPrimitive.content)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun latestUpdatesRequest(page: Int): Request {
|
||||
val body = FormBody.Builder().add("apyki", API_KEY).build()
|
||||
return POST(
|
||||
"$baseUrl/v2/directories?studio=0¬_genre=&year=&orderBy=2&language=&type=&duration=&search=&letter=0&limit=24&genre=&season=&page=${(page - 1) * 24}&status=",
|
||||
headers = headers1,
|
||||
body = body,
|
||||
)
|
||||
}
|
||||
|
||||
override fun latestUpdatesParse(response: Response): AnimesPage = popularAnimeParse(response)
|
||||
|
||||
override fun popularAnimeRequest(page: Int): Request {
|
||||
val body = FormBody.Builder().add("apyki", API_KEY).build()
|
||||
return POST(
|
||||
"$baseUrl/v2/directories?studio=0¬_genre=&year=&orderBy=4&language=&type=&duration=&search=&letter=0&limit=24&genre=&season=&page=${(page - 1) * 24}&status=",
|
||||
headers = headers1,
|
||||
body = body,
|
||||
)
|
||||
}
|
||||
|
||||
override fun popularAnimeParse(response: Response): AnimesPage {
|
||||
val responseJson = json.decodeFromString<JsonObject>(response.asJsoup().body().text())
|
||||
try {
|
||||
val animeArray = responseJson["response"]!!.jsonArray
|
||||
return AnimesPage(
|
||||
animeArray.map {
|
||||
val animeDetail = it.jsonObject
|
||||
val animeId = animeDetail["id"]!!.jsonPrimitive.content
|
||||
SAnime.create().apply {
|
||||
title = animeDetail["nombre"]!!.jsonPrimitive.content
|
||||
url = "$baseUrl/v1/episodes/$animeId"
|
||||
thumbnail_url = AIP.random() + animeDetail["img_url"]!!.jsonPrimitive.content
|
||||
}
|
||||
},
|
||||
true,
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
return AnimesPage(emptyList(), false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
|
||||
val requestBody = FormBody.Builder().add("apyki", API_KEY).build()
|
||||
|
||||
val genreFilter = filters.getTagFilter()?.state ?: emptyList()
|
||||
val excludeGenreFilter = filters.getExcludeTagFilter()?.state ?: emptyList()
|
||||
val studioFilter = filters.getStudioFilter()?.state ?: emptyList()
|
||||
val stateFilter = filters.getStateFilter() ?: StateFilter()
|
||||
val orderByFilter = filters.getOrderByFilter() ?: OrderByFilter()
|
||||
|
||||
val genre = genreFilter.filter { it.state }
|
||||
.map { GENRES[it.name] }
|
||||
.joinToString("%2C") { it.toString() }
|
||||
.takeIf { it.isNotEmpty() } ?: ""
|
||||
|
||||
val excludeGenre = excludeGenreFilter.filter { it.state }
|
||||
.map { GENRES[it.name] }
|
||||
.joinToString("%2C") { it.toString() }
|
||||
.takeIf { it.isNotEmpty() } ?: ""
|
||||
|
||||
val studio = studioFilter.filter { it.state }
|
||||
.map { STUDIOS_MAP[it.name] }
|
||||
.joinToString("%2C") { it.toString() }
|
||||
.takeIf { it.isNotEmpty() } ?: "0"
|
||||
|
||||
val status = stateFilter.toUriPart()
|
||||
val orderBy = orderByFilter.toUriPart()
|
||||
|
||||
val url = buildAnimeSearchUrl(query, page, genre, orderBy, excludeGenre, studio, status)
|
||||
|
||||
return POST(
|
||||
url,
|
||||
headers = headers1,
|
||||
body = requestBody,
|
||||
)
|
||||
}
|
||||
|
||||
private fun AnimeFilterList.getTagFilter() = find { it is TagFilter } as? TagFilter
|
||||
private fun AnimeFilterList.getExcludeTagFilter() = find { it is ExcludeTagFilter } as? ExcludeTagFilter
|
||||
private fun AnimeFilterList.getStudioFilter() = find { it is StudioFilter } as? StudioFilter
|
||||
private fun AnimeFilterList.getStateFilter() = find { it is StateFilter } as? StateFilter
|
||||
private fun AnimeFilterList.getOrderByFilter() = find { it is OrderByFilter } as? OrderByFilter
|
||||
|
||||
private fun buildAnimeSearchUrl(
|
||||
query: String,
|
||||
page: Int,
|
||||
genre: String?,
|
||||
orderBy: String?,
|
||||
excludeGenre: String?,
|
||||
studio: String,
|
||||
status: String?,
|
||||
): String {
|
||||
val itemsPerPage = 24
|
||||
return "$baseUrl/v2/directories?" +
|
||||
"studio=$studio&" +
|
||||
"not_genre=$excludeGenre&" +
|
||||
"year=&" +
|
||||
"orderBy=$orderBy&" +
|
||||
"language=&" +
|
||||
"type=&" +
|
||||
"duration=&" +
|
||||
"search=$query&" +
|
||||
"letter=0&" +
|
||||
"limit=$itemsPerPage&" +
|
||||
"genre=$genre&" +
|
||||
"season=&" +
|
||||
"page=${(page - 1) * itemsPerPage}&" +
|
||||
"status=$status"
|
||||
}
|
||||
|
||||
override fun searchAnimeParse(response: Response): AnimesPage {
|
||||
val responseJson = json.decodeFromString<JsonObject>(response.asJsoup().body().text())
|
||||
try {
|
||||
val animeArray = responseJson["response"]!!.jsonArray
|
||||
return AnimesPage(
|
||||
animeArray.map {
|
||||
val animeDetail = it.jsonObject
|
||||
val animeId = animeDetail["id"]!!.jsonPrimitive.content
|
||||
SAnime.create().apply {
|
||||
title = animeDetail["nombre"]!!.jsonPrimitive.content
|
||||
url = "$baseUrl/v1/episodes/$animeId"
|
||||
thumbnail_url = AIP.random() + animeDetail["img_url"]!!.jsonPrimitive.content
|
||||
}
|
||||
},
|
||||
false,
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
return AnimesPage(emptyList(), false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun videoListRequest(episode: SEpisode): Request {
|
||||
val body = FormBody.Builder().add("apyki", API_KEY).build()
|
||||
return POST(
|
||||
episode.url,
|
||||
headers1,
|
||||
body,
|
||||
)
|
||||
}
|
||||
|
||||
override fun videoListParse(response: Response): List<Video> {
|
||||
val jsonResponse = json.decodeFromString<JsonObject>(response.asJsoup().body().text())
|
||||
val responseArray = jsonResponse["response"]!!.jsonObject
|
||||
val players = responseArray["players"]!!.jsonArray
|
||||
val videoList = mutableListOf<Video>()
|
||||
players.forEach {
|
||||
val server = it.jsonObject["option"]!!.jsonPrimitive.content
|
||||
val preUrl = it.jsonObject["name"]!!.jsonPrimitive.content
|
||||
|
||||
val url = if (preUrl.startsWith("F-")) {
|
||||
preUrl.substringAfter("-")
|
||||
} else {
|
||||
preUrl.substringAfter("-").reversed()
|
||||
}
|
||||
videoList.addAll(parseExtractors(url, server))
|
||||
}
|
||||
|
||||
return videoList.filter { it.url.contains("http") }
|
||||
}
|
||||
|
||||
private fun parseExtractors(url: String, server: String): List<Video> {
|
||||
return when {
|
||||
url.contains("streamwish") -> StreamWishExtractor(client, headers).videosFromUrl(url, prefix = "StreamWish")
|
||||
url.contains("mediafire") -> {
|
||||
val video = MediaFireExtractor(client).getVideoFromUrl(url, server)
|
||||
if (video != null) {
|
||||
listOf(video)
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
url.contains("streamtape") -> {
|
||||
val video = StreamTapeExtractor(client).videoFromUrl(url, server)
|
||||
if (video != null) {
|
||||
listOf(video)
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
url.contains("jkanime") -> {
|
||||
val video = JkanimeExtractor(client).getDesuFromUrl(url)
|
||||
if (video != null) {
|
||||
listOf(video)
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
url.contains("/stream/amz.php?") -> {
|
||||
try {
|
||||
val video = JkanimeExtractor(client).amazonExtractor(url)
|
||||
if (video.isNotBlank()) {
|
||||
listOf(Video(video, server, video))
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
} catch (_: Exception) {
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
url.contains("yourupload") -> {
|
||||
YourUploadExtractor(client).videoFromUrl(url, headers)
|
||||
}
|
||||
url.contains("mp4upload") -> {
|
||||
Mp4uploadExtractor(client).videosFromUrl(url, headers)
|
||||
}
|
||||
url.contains("dood") -> {
|
||||
try {
|
||||
val video = DoodExtractor(client).videoFromUrl(url)
|
||||
if (video != null) {
|
||||
listOf(video)
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
} catch (_: Exception) {
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
url.contains("ok.ru") -> {
|
||||
OkruExtractor(client).videosFromUrl(url)
|
||||
}
|
||||
url.contains("flvvideo") && (url.endsWith(".m3u8") || url.endsWith(".mp4")) -> {
|
||||
if (url.contains("http")) {
|
||||
listOf(Video(url, "VideoFLV", url))
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
url.contains("cdnlat4animecen") && (url.endsWith(".class") || url.endsWith(".m3u8") || url.endsWith(".mp4")) -> {
|
||||
if (url.contains("http")) {
|
||||
listOf(Video(url, "AnimeCen", url))
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
url.contains("uqload") -> {
|
||||
UqloadExtractor(client).videosFromUrl(url)
|
||||
}
|
||||
else -> emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
/* --FilterStuff-- */
|
||||
|
||||
override fun getFilterList(): AnimeFilterList = AnimeFilterList(
|
||||
TagFilter("Generos", checkboxesFrom(GENRES)),
|
||||
OrderByFilter(),
|
||||
StateFilter(),
|
||||
StudioFilter("Estudio", checkboxesFrom(STUDIOS_MAP)),
|
||||
ExcludeTagFilter("Excluir Genero", checkboxesFrom(GENRES)),
|
||||
)
|
||||
|
||||
private class StateFilter : UriPartFilter(
|
||||
"Estado",
|
||||
arrayOf(
|
||||
Pair("<Seleccionar>", ""),
|
||||
Pair("Emision", "1"),
|
||||
Pair("Finalizado", "2"),
|
||||
Pair("Proximamente", "3"),
|
||||
),
|
||||
)
|
||||
|
||||
private class OrderByFilter : UriPartFilter(
|
||||
"Ordenar Por",
|
||||
arrayOf(
|
||||
Pair("<Seleccionar>", ""),
|
||||
Pair("Fecha (Menor a Mayor)", "0"),
|
||||
Pair("Recientemente vistos por otros", "1"),
|
||||
Pair("Fecha (Mayor a Menor)", "2"),
|
||||
Pair("A-Z", "3"),
|
||||
Pair("Más Visitado", "4"),
|
||||
Pair("Z-A", "5"),
|
||||
Pair("Mejor Calificación", "6"),
|
||||
Pair("Peor Calificación", "7"),
|
||||
Pair("Últimos Agregados en app", "8"),
|
||||
Pair("Primeros Agregados en app", "9"),
|
||||
),
|
||||
)
|
||||
|
||||
class TagCheckBox(tag: String) : AnimeFilter.CheckBox(tag, false)
|
||||
private fun checkboxesFrom(tagArray: Map<String, Int>): List<TagCheckBox> = tagArray.map { TagCheckBox(it.key) }
|
||||
class TagFilter(name: String, checkBoxes: List<TagCheckBox>) : AnimeFilter.Group<TagCheckBox>(name, checkBoxes)
|
||||
class StudioFilter(name: String, checkBoxes: List<TagCheckBox>) : AnimeFilter.Group<TagCheckBox>(name, checkBoxes)
|
||||
class ExcludeTagFilter(name: String, checkBoxes: List<TagCheckBox>) : AnimeFilter.Group<TagCheckBox>(name, checkBoxes)
|
||||
|
||||
private open class UriPartFilter(displayName: String, val vals: Array<Pair<String, String>>) :
|
||||
AnimeFilter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) {
|
||||
fun toUriPart() = vals[state].second
|
||||
}
|
||||
|
||||
override fun setupPreferenceScreen(screen: PreferenceScreen) {
|
||||
val qualities = arrayOf(
|
||||
"Okru:1080p", "Okru:720p", "Okru:480p", "Okru:360p", "Okru:240p", // Okru
|
||||
"Xtreme S", "Nozomi", "Desu", "F1S-TAPE", "F1NIX", // video servers without resolution
|
||||
)
|
||||
val videoQualityPref = ListPreference(screen.context).apply {
|
||||
key = "preferred_quality"
|
||||
title = "Preferred quality"
|
||||
entries = qualities
|
||||
entryValues = qualities
|
||||
setDefaultValue("Desu")
|
||||
summary = "%s"
|
||||
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
val selected = newValue as String
|
||||
val index = findIndexOfValue(selected)
|
||||
val entry = entryValues[index] as String
|
||||
preferences.edit().putString(key, entry).commit()
|
||||
}
|
||||
}
|
||||
|
||||
screen.addPreference(videoQualityPref)
|
||||
}
|
||||
|
||||
private fun List<Video>.sortIfContains(item: String): List<Video> {
|
||||
val newList = mutableListOf<Video>()
|
||||
for (video in this) {
|
||||
if (item in video.quality) {
|
||||
newList.add(0, video)
|
||||
} else {
|
||||
newList.add(video)
|
||||
}
|
||||
}
|
||||
return newList
|
||||
}
|
||||
|
||||
override fun List<Video>.sort(): List<Video> {
|
||||
val quality = preferences.getString("preferred_quality", "desu")!!
|
||||
return sortIfContains(quality)
|
||||
}
|
||||
|
||||
private fun parseDate(dateStr: String): Long {
|
||||
return runCatching { DATE_FORMATTER.parse(dateStr)?.time }
|
||||
.getOrNull() ?: 0L
|
||||
}
|
||||
companion object {
|
||||
private val DATE_FORMATTER by lazy {
|
||||
SimpleDateFormat("dd-MM-yyyy", Locale.ENGLISH)
|
||||
}
|
||||
}
|
||||
|
||||
/* --Unused stuff-- */
|
||||
|
||||
override fun popularAnimeSelector(): String = throw UnsupportedOperationException()
|
||||
|
||||
override fun popularAnimeFromElement(element: Element): SAnime = throw UnsupportedOperationException()
|
||||
|
||||
override fun popularAnimeNextPageSelector(): String = throw UnsupportedOperationException()
|
||||
|
||||
override fun videoFromElement(element: Element): Video = throw UnsupportedOperationException()
|
||||
|
||||
override fun videoListSelector(): String = throw UnsupportedOperationException()
|
||||
|
||||
override fun videoUrlParse(document: Document): String = throw UnsupportedOperationException()
|
||||
|
||||
override fun searchAnimeSelector(): String = throw UnsupportedOperationException()
|
||||
|
||||
override fun searchAnimeFromElement(element: Element): SAnime = throw UnsupportedOperationException()
|
||||
|
||||
override fun searchAnimeNextPageSelector(): String = throw UnsupportedOperationException()
|
||||
|
||||
override fun episodeFromElement(element: Element): SEpisode = throw UnsupportedOperationException()
|
||||
|
||||
override fun episodeListSelector(): String = throw UnsupportedOperationException()
|
||||
|
||||
override fun latestUpdatesFromElement(element: Element): SAnime = throw UnsupportedOperationException()
|
||||
|
||||
override fun latestUpdatesNextPageSelector(): String = throw UnsupportedOperationException()
|
||||
|
||||
override fun latestUpdatesSelector(): String = throw UnsupportedOperationException()
|
||||
}
|
|
@ -0,0 +1,465 @@
|
|||
package eu.kanade.tachiyomi.animeextension.es.legionanime
|
||||
|
||||
val STUDIOS_MAP = mapOf(
|
||||
"TMS Entertainment" to 4,
|
||||
"TNK" to 39,
|
||||
"Toei Animation" to 1,
|
||||
"Toho Interactive Animation" to 261,
|
||||
"Tokyo Kids" to 96,
|
||||
"Tokyo Movie Shinsha" to 3,
|
||||
"Tomason" to 329,
|
||||
"Tomovies" to 164,
|
||||
"Topcraft" to 293,
|
||||
"Trans Arts" to 105,
|
||||
"Tri-Slash" to 270,
|
||||
"Triangle Staff" to 219,
|
||||
"TriF Studio" to 239,
|
||||
"Trigger" to 87,
|
||||
"Trinet Entertainment" to 283,
|
||||
"TROYCA" to 120,
|
||||
"Tsuchida Productions" to 192,
|
||||
"TV Tokyo" to 19,
|
||||
"Twilight Studio" to 183,
|
||||
"TYO Animations" to 166,
|
||||
"Typhoon Graphics" to 232,
|
||||
"ufotable" to 47,
|
||||
"Urban Product" to 186,
|
||||
"UWAN Pictures" to 187,
|
||||
"Vega Entertainment" to 274,
|
||||
"View Works" to 248,
|
||||
"Visual Flight" to 339,
|
||||
"Viz Media" to 8,
|
||||
"W-Toon Studio" to 37,
|
||||
"WAO World" to 176,
|
||||
"Wawayu Animation" to 389,
|
||||
"Welz Animation Studios" to 273,
|
||||
"White Fox" to 107,
|
||||
"Wit Studio" to 23,
|
||||
"Wolfsbane" to 136,
|
||||
"Xebec" to 25,
|
||||
"XFLAG" to 313,
|
||||
"Yamato Works" to 299,
|
||||
"Yaoyorozu" to 256,
|
||||
"Yokohama Animation Lab" to 84,
|
||||
"Yostar Pictures" to 343,
|
||||
"Yumeta Company" to 173,
|
||||
"Zero-G" to 132,
|
||||
"Zero-G Room" to 325,
|
||||
"Zexcs" to 83,
|
||||
"Lay-duce" to 56,
|
||||
"Lerche" to 40,
|
||||
"Lesprit" to 158,
|
||||
"LEVELS" to 337,
|
||||
"LICO" to 378,
|
||||
"Lide" to 212,
|
||||
"LIDENFILMS" to 43,
|
||||
"LIDENFILMS Kyoto Studio" to 361,
|
||||
"Life Work" to 322,
|
||||
"Lilix" to 225,
|
||||
"LMD" to 336,
|
||||
"M.S.C" to 72,
|
||||
"Madhouse" to 13,
|
||||
"Magia Doraglier" to 99,
|
||||
"Magic Bus" to 14,
|
||||
"Maho Film" to 182,
|
||||
"Manglobe" to 85,
|
||||
"MAPPA" to 67,
|
||||
"Marine Entertainment" to 236,
|
||||
"Marvy Jack" to 237,
|
||||
"Marza Animation Planet" to 80,
|
||||
"MASTER LIGHTS" to 216,
|
||||
"Millepensee" to 150,
|
||||
"Minami Machi Bugyousho" to 318,
|
||||
"monofilmo" to 54,
|
||||
"MooGoo" to 234,
|
||||
"Mushi Production" to 26,
|
||||
"Nakamura Production" to 311,
|
||||
"Namu Animation" to 199,
|
||||
"NAZ" to 82,
|
||||
"Next Media Animation" to 326,
|
||||
"Nexus" to 127,
|
||||
"NHK" to 334,
|
||||
"Nickelodeon Animation Studio" to 62,
|
||||
"Nihon Ad Systems" to 207,
|
||||
"Nippon Animation" to 36,
|
||||
"Nomad" to 155,
|
||||
"Nut" to 108,
|
||||
"Office DCI" to 317,
|
||||
"Office Nobu" to 324,
|
||||
"Oh! Production" to 310,
|
||||
"Okuruto Noboru" to 221,
|
||||
"OLM" to 65,
|
||||
"OLM Team Yoshioka" to 368,
|
||||
"Orange" to 59,
|
||||
"Ordet" to 250,
|
||||
"OZ" to 367,
|
||||
"P.A. Works" to 6,
|
||||
"P.I.C.S." to 230,
|
||||
"Palm Studio" to 290,
|
||||
"Passione" to 113,
|
||||
"Pastel" to 215,
|
||||
"Picture Magic" to 279,
|
||||
"Pie in the sky" to 321,
|
||||
"Pierrot" to 393,
|
||||
"Pierrot Plus" to 79,
|
||||
"Pine Jam" to 81,
|
||||
"Planet" to 386,
|
||||
"Planet Cartoon" to 394,
|
||||
"Platinum Vision" to 91,
|
||||
"Plum" to 259,
|
||||
"Polygon Pictures" to 88,
|
||||
"PRA" to 181,
|
||||
"Primastea" to 245,
|
||||
"Production +h." to 373,
|
||||
"production doA" to 188,
|
||||
"Production GoodBook" to 227,
|
||||
"Production I.G" to 64,
|
||||
"Production IMS" to 116,
|
||||
"Production Reed" to 18,
|
||||
"Project No.9" to 30,
|
||||
"Purple Cow Studio Japan" to 135,
|
||||
"Quad" to 364,
|
||||
"Qualia Animation" to 217,
|
||||
"Qubic Pictures" to 347,
|
||||
"Quebico" to 350,
|
||||
"Radix" to 235,
|
||||
"Red Dog Culture House" to 379,
|
||||
"Remic" to 304,
|
||||
"Revoroot" to 209,
|
||||
"Rising Force" to 291,
|
||||
"Robot Communications" to 277,
|
||||
"Saetta" to 205,
|
||||
"Sanrio" to 333,
|
||||
"SANZIGEN" to 122,
|
||||
"Satelight" to 51,
|
||||
"Science SARU" to 157,
|
||||
"Scooter Films" to 381,
|
||||
"Seven" to 133,
|
||||
"Seven Arcs" to 115,
|
||||
"Seven Arcs Pictures" to 102,
|
||||
"Seven Stone Entertainment" to 359,
|
||||
"Shaft" to 15,
|
||||
"Shanghai Foch Film and TV Culture Investment" to 352,
|
||||
"Shanghai Foch Film Culture Investment" to 332,
|
||||
"Shenying Animation" to 358,
|
||||
"Shin-Ei Animation" to 57,
|
||||
"Shinkuukan" to 316,
|
||||
"Shirogumi" to 92,
|
||||
"Shogakukan Music & Digital Entertainment" to 231,
|
||||
"Shuka" to 167,
|
||||
"Signal.MD" to 61,
|
||||
"Silver" to 124,
|
||||
"Silver Link." to 31,
|
||||
"Sola Digital Arts" to 148,
|
||||
"Space Neko Company" to 342,
|
||||
"Sparkly Key Animation Studio" to 123,
|
||||
"Sparky Animation" to 320,
|
||||
"Staple Entertainment" to 388,
|
||||
"Stingray" to 268,
|
||||
"Studio 3Hz" to 137,
|
||||
"Studio 4°C" to 241,
|
||||
"Studio A-CAT" to 146,
|
||||
"Studio Animal" to 276,
|
||||
"Studio Bind" to 338,
|
||||
"Studio Blanc" to 109,
|
||||
"Studio Chizu" to 251,
|
||||
"Studio Colorido" to 119,
|
||||
"Studio Comet" to 144,
|
||||
"Studio Crocodile" to 68,
|
||||
"Studio Daisy" to 346,
|
||||
"Studio Deen" to 93,
|
||||
"Studio elle" to 142,
|
||||
"Studio Fantasia" to 233,
|
||||
"Studio Flad" to 77,
|
||||
"Studio Flag" to 278,
|
||||
"Studio Ghibli" to 44,
|
||||
"Studio Gokumi" to 111,
|
||||
"Studio Hibari" to 49,
|
||||
"Studio Junio" to 218,
|
||||
"Studio Kafka" to 353,
|
||||
"Studio Kai" to 260,
|
||||
"Studio Kelmadick" to 309,
|
||||
"Studio Kyuuma" to 284,
|
||||
"Studio LAN" to 243,
|
||||
"Studio Lings" to 197,
|
||||
"Studio Live" to 178,
|
||||
"Studio M2" to 327,
|
||||
"Studio Matrix" to 152,
|
||||
"Studio Moriken" to 35,
|
||||
"studio MOTHER" to 369,
|
||||
"Studio Palette" to 356,
|
||||
"Studio Pierrot" to 11,
|
||||
"Studio Ponoc" to 264,
|
||||
"Studio PuYUKAI" to 117,
|
||||
"Studio Rikka" to 134,
|
||||
"Studio Signpost" to 238,
|
||||
"Studio VOLN" to 94,
|
||||
"Studio W.Baba" to 229,
|
||||
"Studio! Cucuri" to 288,
|
||||
"Sublimation" to 253,
|
||||
"Sunrise" to 45,
|
||||
"Sunrise Beyond" to 46,
|
||||
"Super Normal Studio" to 267,
|
||||
"Synergy Japan" to 28,
|
||||
"SynergySP" to 7,
|
||||
"Tatsunoko Production" to 17,
|
||||
"Team TillDawn" to 269,
|
||||
"Team YokkyuFuman" to 240,
|
||||
"teamKG" to 101,
|
||||
"Tear Studio" to 118,
|
||||
"Telecom Animation Film" to 194,
|
||||
"Tengu Kobo" to 319,
|
||||
"Tezuka Productions" to 110,
|
||||
"The Answer Studio" to 331,
|
||||
"Think Corporation" to 297,
|
||||
"Thundray" to 154,
|
||||
"Todos" to 0,
|
||||
"3xCube" to 41,
|
||||
"8bit" to 90,
|
||||
"A-1 Pictures" to 9,
|
||||
"A-Real" to 201,
|
||||
"A.C.G.T." to 55,
|
||||
"Acca effe" to 210,
|
||||
"Actas" to 163,
|
||||
"Agent 21" to 383,
|
||||
"AIC" to 24,
|
||||
"AIC A.S.T.A." to 97,
|
||||
"AIC Build" to 121,
|
||||
"AIC Classic" to 159,
|
||||
"AIC Frontier" to 305,
|
||||
"AIC Plus+" to 98,
|
||||
"AIC Spirits" to 200,
|
||||
"Ajia-Do" to 76,
|
||||
"Akatsuki" to 372,
|
||||
"Albacrow" to 147,
|
||||
"Amuse" to 315,
|
||||
"Anima" to 306,
|
||||
"Anima&Co." to 203,
|
||||
"Animaruya" to 314,
|
||||
"Animation Do" to 73,
|
||||
"Annapuru" to 298,
|
||||
"Anpro" to 294,
|
||||
"APPP" to 50,
|
||||
"AQUA ARIS" to 189,
|
||||
"ARECT" to 360,
|
||||
"Arms" to 33,
|
||||
"Artland" to 12,
|
||||
"Artmic" to 285,
|
||||
"Arvo Animation" to 125,
|
||||
"Asahi Production" to 202,
|
||||
"Ascension" to 289,
|
||||
"ASK Animation Studio" to 385,
|
||||
"asread." to 86,
|
||||
"AtelierPontdarc" to 357,
|
||||
"AXsiZ" to 131,
|
||||
"B.CMAY PICTURES" to 184,
|
||||
"B&T" to 275,
|
||||
"Bakken Record" to 161,
|
||||
"Bandai Namco Pictures" to 126,
|
||||
"Barnum Studio" to 172,
|
||||
"Bee Media" to 295,
|
||||
"Bee Train" to 162,
|
||||
"Beijing Rocen Digital" to 246,
|
||||
"BeSTACK" to 106,
|
||||
"Bibury Animation CG" to 374,
|
||||
"Bibury Animation Studios" to 196,
|
||||
"BigFireBird Animation" to 104,
|
||||
"Blade" to 153,
|
||||
"Bones" to 22,
|
||||
"Bouncy" to 249,
|
||||
"Brain's Base" to 53,
|
||||
"Bridge" to 29,
|
||||
"Brio Animation" to 280,
|
||||
"Buemon" to 226,
|
||||
"C-Station" to 156,
|
||||
"C2C" to 145,
|
||||
"CANDY BOX" to 344,
|
||||
"CGCG Studio" to 348,
|
||||
"Chaos Project" to 100,
|
||||
"Charaction" to 296,
|
||||
"Children's Playground Entertainment" to 78,
|
||||
"CLAP" to 371,
|
||||
"CloverWorks" to 52,
|
||||
"Colored Pencil Animation" to 351,
|
||||
"CoMix Wave Films" to 69,
|
||||
"Connect" to 32,
|
||||
"Craftar Studios" to 223,
|
||||
"Creators in Pack" to 138,
|
||||
"CyberConnect2" to 312,
|
||||
"Cyclone Graphics" to 391,
|
||||
"CygamesPictures" to 149,
|
||||
"DandeLion Animation Studio" to 220,
|
||||
"Daume" to 143,
|
||||
"David Production" to 2,
|
||||
"Dentsu" to 20,
|
||||
"Digital Frontier" to 160,
|
||||
"Digital Network Animation" to 363,
|
||||
"Diomedea" to 10,
|
||||
"DLE" to 140,
|
||||
"DMM pictures" to 262,
|
||||
"DMM.futureworks" to 38,
|
||||
"Doga Kobo" to 58,
|
||||
"domerica" to 345,
|
||||
"Dongwoo A&E" to 206,
|
||||
"DR Movie" to 376,
|
||||
"DRAWIZ" to 349,
|
||||
"Drive" to 66,
|
||||
"drop" to 307,
|
||||
"Dwango" to 252,
|
||||
"dwarf" to 272,
|
||||
"Dynamo Pictures" to 247,
|
||||
"E&G Films" to 254,
|
||||
"Egg Firm" to 128,
|
||||
"EKACHI EPILKA" to 169,
|
||||
"Emon" to 175,
|
||||
"EMT Squared" to 95,
|
||||
"Encourage Films" to 168,
|
||||
"ENGI" to 129,
|
||||
"Ezόla" to 130,
|
||||
"Fanworks" to 71,
|
||||
"feel." to 21,
|
||||
"Felix Film" to 174,
|
||||
"Fever Creations" to 395,
|
||||
"Fifth Avenue" to 265,
|
||||
"Flat Studio" to 382,
|
||||
"Front Line" to 301,
|
||||
"Fuji TV" to 287,
|
||||
"G-angle" to 228,
|
||||
"G&G Entertainment" to 286,
|
||||
"Gaina" to 112,
|
||||
"Gainax" to 16,
|
||||
"Gainax Kyoto" to 224,
|
||||
"Gallop" to 60,
|
||||
"Gambit" to 354,
|
||||
"Gathering" to 213,
|
||||
"GEEK TOYS" to 366,
|
||||
"GEEKTOYS" to 114,
|
||||
"GEMBA" to 151,
|
||||
"Genco" to 308,
|
||||
"Geno Studio" to 171,
|
||||
"GIFTanimation" to 355,
|
||||
"Giga Production" to 211,
|
||||
"Ginga Ya" to 282,
|
||||
"GoHands" to 89,
|
||||
"Gonzo" to 34,
|
||||
"Gosay Studio" to 244,
|
||||
"Graphinica" to 165,
|
||||
"GRIZZLY" to 384,
|
||||
"Group TAC" to 185,
|
||||
"Grouper Productions" to 302,
|
||||
"Hal Film Maker" to 195,
|
||||
"Haoliners Animation League" to 139,
|
||||
"Hayabusa Film" to 377,
|
||||
"Hoods Drifters Studio" to 190,
|
||||
"Hoods Entertainment" to 63,
|
||||
"HORNETS" to 375,
|
||||
"Hotline" to 328,
|
||||
"HOTZIPANG" to 70,
|
||||
"HS Pictures Studio" to 281,
|
||||
"Husio Studio" to 242,
|
||||
"I.Gzwei" to 300,
|
||||
"iDRAGONS Creative Studio" to 208,
|
||||
"ILCA" to 27,
|
||||
"Imagica Lab." to 204,
|
||||
"Imagin" to 177,
|
||||
"Imagineer" to 191,
|
||||
"Indivision" to 362,
|
||||
"Ishimori Entertainment" to 263,
|
||||
"Issen" to 222,
|
||||
"ixtl" to 42,
|
||||
"Iyasakadou Film" to 330,
|
||||
"J.C.Staff" to 5,
|
||||
"Japan Vistec" to 303,
|
||||
"Jinnan Studio" to 370,
|
||||
"Jinnis Animation Studios" to 271,
|
||||
"Jumondo" to 380,
|
||||
"Jumonji" to 257,
|
||||
"Kachidoki Studio" to 335,
|
||||
"Kamikaze Douga" to 170,
|
||||
"Karaku" to 258,
|
||||
"Kazami Gakuen Koushiki Douga-bu" to 266,
|
||||
"Kenji Studio" to 390,
|
||||
"Khara" to 179,
|
||||
"Kigumi" to 365,
|
||||
"Kinema Citrus" to 103,
|
||||
"Kitty Films" to 214,
|
||||
"KJJ Animation" to 392,
|
||||
"Kung Fu Frog Animation" to 387,
|
||||
"Kyoto Animation" to 48,
|
||||
"Kyotoma" to 323,
|
||||
"l-a-unch・BOX" to 141,
|
||||
"L²Studio" to 180,
|
||||
"LandQ studios" to 193,
|
||||
"Lapin Track" to 198,
|
||||
"Larx Entertainment" to 74,
|
||||
)
|
||||
|
||||
val GENRES = mapOf(
|
||||
"Buscar exactamente con géneros seleccionados" to 100,
|
||||
"Acción" to 1,
|
||||
"Artes Marciales" to 11,
|
||||
"Aventuras" to 21,
|
||||
"Carreras" to 31,
|
||||
"Ciencia Ficción" to 2,
|
||||
"Comedia" to 12,
|
||||
"Demencia" to 22,
|
||||
"Demonios" to 32,
|
||||
"Deportes" to 3,
|
||||
"Donghua" to 45,
|
||||
"Drama" to 13,
|
||||
"Ecchi" to 23,
|
||||
"Escolares" to 33,
|
||||
"Espacial" to 4,
|
||||
"Fantasía" to 14,
|
||||
"Harem" to 24,
|
||||
"Historico" to 34,
|
||||
"Infantil" to 5,
|
||||
"Isekai" to 43,
|
||||
"Josei" to 15,
|
||||
"Juegos" to 25,
|
||||
"Latino y Castellano" to 41,
|
||||
"Magia" to 35,
|
||||
"Mecha" to 6,
|
||||
"Militar" to 16,
|
||||
"Misterio" to 26,
|
||||
"Música" to 36,
|
||||
"Parodia" to 7,
|
||||
"Policía" to 17,
|
||||
"Psicológico" to 27,
|
||||
"Recuentos de la vida" to 37,
|
||||
"Romance" to 8,
|
||||
"Samurai" to 18,
|
||||
"Seinen" to 28,
|
||||
"Shoujo" to 38,
|
||||
"Shounen" to 9,
|
||||
"Sobrenatural" to 19,
|
||||
"Superpoderes" to 29,
|
||||
"Suspenso" to 39,
|
||||
"Terror / Gore" to 10,
|
||||
"Vampiros" to 20,
|
||||
"Yaoi" to 30,
|
||||
"Yuri" to 40,
|
||||
)
|
||||
|
||||
val ORDER_BY = arrayOf(
|
||||
Pair("Fecha (Menor a Mayor)", "0"),
|
||||
Pair("Recientemente vistos por otros", "1"),
|
||||
Pair("Fecha (Mayor a Menor)", "2"),
|
||||
Pair("A-Z", "3"),
|
||||
Pair("Más Visitado", "4"),
|
||||
Pair("Z-A", "5"),
|
||||
Pair("Mejor Calificación", "6"),
|
||||
Pair("Peor Calificación", "7"),
|
||||
Pair("Últimos Agregados en app", "8"),
|
||||
Pair("Primeros Agregados en app", "9"),
|
||||
)
|
||||
|
||||
// this is supposed to be information about the device, it is needed to make any api calls, this could probably be randomized
|
||||
// Apparently there is a section called "package_version" that needs to be updated periodically bruh.
|
||||
val JSON_STRING = "{\"mob3\":\"wj2fea7esGZ44ef\",\"mob\":\"ca-app-pub-8704883736496335~2640452466\",\"mob2\":\"ca-app-pub-8704883736496335/7509635763\",\"laltx\":\"ca-app-pub-7457591504273346/96408526573970637unleinunleba\",\"language\":\"es\",\"isDeb\":false,\"mobx\":\"ca-app-pub-7457591504273346~4714978974\",\"loadLvl\":1,\"code_name\":\"emu64xa\",\"vcode\":\"2.0.2.6\",\"platform\":\"13\",\"lalt\":\"ca-app-pub-8704883736496335/71217888083970637unleinunleba\",\"kind_device\":\"0\",\"manufacturer\":\"Google\",\"som\":\"android\",\"device_name\":\"Sdk_gphone64_x86_64\",\"player_id\":\"50dfea02-9f24-4116-902b-a726146da421\",\"mobf\":\"ca-app-pub-8704883736496335/2195575817\",\"ipv6\":\"FE80::6898:34FF:FE32:E13E\",\"root\":\"0\",\"eth\":\"02:00:00:00:00:00\",\"tel\":\"XXX-XXX-XXX\",\"UUID\":\"00000000-0001-a657-0001-aad30001b11d\",\"yek\":\"bqUgI4l339bqQbnz\",\"moned\":false,\"lvl_sign\":1,\"mobfx\":\"ca-app-pub-7457591504273346/1377852271\",\"device_id\":\"\",\"orp\":false,\"modelo\":\"sdk_gphone64_x86_64\",\"market_name\":\"Sdk_gphone64_x86_64\",\"token\":\"es\",\"isSign\":true,\"malt\":\"ca-app-pub-8704883736496335/7121788808\",\"maltx\":\"ca-app-pub-7457591504273346/9640852657\",\"api_lvl\":\"33\",\"package_version\":\"50\",\"kind_release\":0,\"ipLocal\":\"10.0.2.15\",\"mob2x\":\"ca-app-pub-7457591504273346/9640852657\",\"wlan\":\"02:00:00:00:00:00\",\"inmo\":\"a3c41c881e7f4bc982db32a889eb9e57\",\"inst\":\"\",\"package_name\":\"aplicaciones.paleta.legionanimefull\",\"androidID\":\"b70a95e4fda18f3c\"}"
|
||||
|
||||
// this is supposed to be the api key but apparently it is not necessary, anyway I add it to avoid any errors
|
||||
val API_KEY = "pM7VYr2bBG2plWQp"
|
||||
|
||||
// these are the urls used for the thumbnails, apparently it doesn't matter which one to use but it would be good to check the status of the request before assigning it to the anime
|
||||
val AIP = arrayOf("https://la-space-4.sfo2.digitaloceanspaces.com/", "https://la-space-5.sfo2.digitaloceanspaces.com/", "https://la-space-4.sfo2.digitaloceanspaces.com/", "https://la-space-5.sfo2.digitaloceanspaces.com/", "https://la-space-4.sfo2.cdn.digitaloceanspaces.com/")
|
|
@ -0,0 +1,57 @@
|
|||
package eu.kanade.tachiyomi.animeextension.es.legionanime.extractors
|
||||
|
||||
import eu.kanade.tachiyomi.animesource.model.Video
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.POST
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import okhttp3.Headers
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import org.json.JSONObject
|
||||
|
||||
class JkanimeExtractor(
|
||||
private val client: OkHttpClient,
|
||||
) {
|
||||
|
||||
fun getNozomiFromUrl(url: String, prefix: String = ""): Video? {
|
||||
val dataKeyHeaders = Headers.Builder().add("Referer", url).build()
|
||||
val doc = client.newCall(GET(url, dataKeyHeaders)).execute().asJsoup()
|
||||
val dataKey = doc.select("form input[value]").attr("value")
|
||||
|
||||
val gsplayBody = "data=$dataKey".toRequestBody("application/x-www-form-urlencoded".toMediaTypeOrNull())
|
||||
|
||||
val location = client.newCall(POST("https://jkanime.net/gsplay/redirect_post.php", dataKeyHeaders, gsplayBody)).execute().request.url.toString()
|
||||
val postKey = location.substringAfter("player.html#")
|
||||
|
||||
val nozomiBody = "v=$postKey".toRequestBody("application/x-www-form-urlencoded".toMediaTypeOrNull())
|
||||
val nozomiResponse = client.newCall(POST("https://jkanime.net/gsplay/api.php", body = nozomiBody)).execute()
|
||||
val nozomiUrl = JSONObject(nozomiResponse.body.string()).getString("file")
|
||||
if (nozomiResponse.isSuccessful && nozomiUrl.isNotBlank()) {
|
||||
return Video(nozomiUrl, "${prefix}Nozomi", nozomiUrl)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun getDesuFromUrl(url: String, prefix: String = ""): Video? {
|
||||
val document = client.newCall(GET(url)).execute()
|
||||
val script = document.asJsoup().selectFirst("script:containsData(var parts = {)")!!.data()
|
||||
val streamUrl = script.substringAfter("url: '").substringBefore("'")
|
||||
if (document.isSuccessful && streamUrl.isNotBlank()) {
|
||||
return Video(streamUrl, "${prefix}Desu", streamUrl)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun amazonExtractor(url: String): String {
|
||||
val document = client.newCall(GET(url.replace(".com", ".tv"))).execute().asJsoup()
|
||||
val videoURl = document.selectFirst("script:containsData(sources: [)")!!.data()
|
||||
.substringAfter("[{\"file\":\"")
|
||||
.substringBefore("\",").replace("\\", "")
|
||||
return try {
|
||||
if (client.newCall(GET(videoURl)).execute().code == 200) videoURl else ""
|
||||
} catch (_: Exception) {
|
||||
""
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package eu.kanade.tachiyomi.animeextension.es.legionanime.extractors
|
||||
|
||||
import eu.kanade.tachiyomi.animesource.model.Video
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import okhttp3.OkHttpClient
|
||||
|
||||
class MediaFireExtractor(
|
||||
private val client: OkHttpClient,
|
||||
) {
|
||||
fun getVideoFromUrl(url: String, prefix: String = ""): Video? {
|
||||
val document = client.newCall(GET(url)).execute()
|
||||
val downloadUrl = document.asJsoup().selectFirst("a#downloadButton")?.attr("href")
|
||||
if (!downloadUrl.isNullOrBlank()) {
|
||||
return Video(downloadUrl, "$prefix-MediaFire", downloadUrl)
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue