some cleanup and removal of gson dependency

This commit is contained in:
jmir1 2021-12-13 15:10:16 +01:00
parent fffc47b29d
commit bc150ba575
11 changed files with 222 additions and 187 deletions

View File

@ -10,9 +10,8 @@ dependencies {
compileOnly 'com.squareup.okhttp3:okhttp:4.9.1' compileOnly 'com.squareup.okhttp3:okhttp:4.9.1'
compileOnly 'io.reactivex:rxjava:1.3.8' compileOnly 'io.reactivex:rxjava:1.3.8'
compileOnly 'org.jsoup:jsoup:1.13.1' compileOnly 'org.jsoup:jsoup:1.13.1'
compileOnly 'com.google.code.gson:gson:2.8.6' compileOnly 'org.jetbrains.kotlinx:kotlinx-serialization-protobuf:1.2.0'
compileOnly 'com.github.salomonbrys.kotson:kotson:2.5.0' compileOnly 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.0'
compileOnly 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.2'
implementation project(":annotations") implementation project(":annotations")
compileOnly project(':duktape-stub') compileOnly project(':duktape-stub')

View File

@ -5,7 +5,7 @@ ext {
extName = 'AnimePahe' extName = 'AnimePahe'
pkgNameSuffix = 'en.animepahe' pkgNameSuffix = 'en.animepahe'
extClass = '.AnimePahe' extClass = '.AnimePahe'
extVersionCode = 9 extVersionCode = 10
libVersion = '12' libVersion = '12'
} }

View File

@ -5,10 +5,6 @@ import android.content.SharedPreferences
import androidx.preference.ListPreference import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen import androidx.preference.PreferenceScreen
import androidx.preference.SwitchPreferenceCompat import androidx.preference.SwitchPreferenceCompat
import com.google.gson.JsonElement
import com.google.gson.JsonNull
import com.google.gson.JsonObject
import com.google.gson.JsonParser
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
import eu.kanade.tachiyomi.animesource.model.AnimesPage import eu.kanade.tachiyomi.animesource.model.AnimesPage
@ -21,12 +17,21 @@ import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonNull
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.int
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import okhttp3.Headers import okhttp3.Headers
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import java.lang.Exception import java.lang.Exception
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Locale import java.util.Locale
@ -48,6 +53,8 @@ class AnimePahe : ConfigurableAnimeSource, AnimeHttpSource() {
override val supportsLatest = false override val supportsLatest = false
private val json: Json by injectLazy()
override fun headersBuilder(): Headers.Builder { override fun headersBuilder(): Headers.Builder {
try { try {
// Bypass... // Bypass...
@ -111,15 +118,15 @@ class AnimePahe : ConfigurableAnimeSource, AnimeHttpSource() {
} }
private fun parseSearchJson(jsonLine: String?): AnimesPage { private fun parseSearchJson(jsonLine: String?): AnimesPage {
val jElement: JsonElement = JsonParser.parseString(jsonLine) val jsonData = jsonLine ?: return AnimesPage(emptyList(), false)
val jObject: JsonObject = jElement.asJsonObject val jObject = json.decodeFromString<JsonObject>(jsonData)
val data = jObject.get("data") ?: return AnimesPage(emptyList(), false) val data = jObject["data"] ?: return AnimesPage(emptyList(), false)
val array = data.asJsonArray val array = data.jsonArray
val animeList = mutableListOf<SAnime>() val animeList = mutableListOf<SAnime>()
for (item in array) { for (item in array) {
val anime = SAnime.create() val anime = SAnime.create()
anime.title = item.asJsonObject.get("title").asString anime.title = item.jsonObject["title"]!!.jsonPrimitive.content
val animeId = item.asJsonObject.get("id").asInt val animeId = item.jsonObject["id"]!!.jsonPrimitive.int
anime.setUrlWithoutDomain("$baseUrl/anime/?anime_id=$animeId") anime.setUrlWithoutDomain("$baseUrl/anime/?anime_id=$animeId")
animeList.add(anime) animeList.add(anime)
} }
@ -134,19 +141,19 @@ class AnimePahe : ConfigurableAnimeSource, AnimeHttpSource() {
} }
private fun parsePopularAnimeJson(jsonLine: String?): AnimesPage { private fun parsePopularAnimeJson(jsonLine: String?): AnimesPage {
val jElement: JsonElement = JsonParser.parseString(jsonLine) val jsonData = jsonLine ?: return AnimesPage(emptyList(), false)
val jObject: JsonObject = jElement.asJsonObject val jObject = json.decodeFromString<JsonObject>(jsonData)
val lastPage = jObject.get("last_page").asInt val lastPage = jObject["last_page"]!!.jsonPrimitive.int
val page = jObject.get("current_page").asInt val page = jObject["current_page"]!!.jsonPrimitive.int
val hasNextPage = page < lastPage val hasNextPage = page < lastPage
val array = jObject.get("data").asJsonArray val array = jObject["data"]!!.jsonArray
val animeList = mutableListOf<SAnime>() val animeList = mutableListOf<SAnime>()
for (item in array) { for (item in array) {
val anime = SAnime.create() val anime = SAnime.create()
anime.title = item.asJsonObject.get("anime_title").asString anime.title = item.jsonObject["anime_title"]!!.jsonPrimitive.content
val animeId = item.asJsonObject.get("anime_id").asInt val animeId = item.jsonObject["anime_id"]!!.jsonPrimitive.int
anime.setUrlWithoutDomain("$baseUrl/anime/?anime_id=$animeId") anime.setUrlWithoutDomain("$baseUrl/anime/?anime_id=$animeId")
anime.artist = item.asJsonObject.get("fansub").asString anime.artist = item.jsonObject["fansub"]!!.jsonPrimitive.content
animeList.add(anime) animeList.add(anime)
} }
return AnimesPage(animeList, hasNextPage) return AnimesPage(animeList, hasNextPage)
@ -170,19 +177,19 @@ class AnimePahe : ConfigurableAnimeSource, AnimeHttpSource() {
} }
private fun parseEpisodePage(jsonLine: String?): MutableList<SEpisode> { private fun parseEpisodePage(jsonLine: String?): MutableList<SEpisode> {
val jElement: JsonElement = JsonParser.parseString(jsonLine) val jsonData = jsonLine ?: return mutableListOf()
val jObject: JsonObject = jElement.asJsonObject val jObject = json.decodeFromString<JsonObject>(jsonData)
val array = jObject.get("data").asJsonArray val array = jObject["data"]!!.jsonArray
val episodeList = mutableListOf<SEpisode>() val episodeList = mutableListOf<SEpisode>()
for (item in array) { for (item in array) {
val itemO = item.asJsonObject val itemO = item.jsonObject
val episode = SEpisode.create() val episode = SEpisode.create()
episode.date_upload = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US) episode.date_upload = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US)
.parse(itemO.get("created_at").asString)!!.time .parse(itemO["created_at"]!!.jsonPrimitive.content)!!.time
val animeId = itemO.get("anime_id").asInt val animeId = itemO["anime_id"]!!.jsonPrimitive.int
val session = itemO.get("session").asString val session = itemO["session"]!!.jsonPrimitive.content
episode.setUrlWithoutDomain("$baseUrl/api?m=links&id=$animeId&session=$session&p=kwik") episode.setUrlWithoutDomain("$baseUrl/api?m=links&id=$animeId&session=$session&p=kwik")
val epNum = itemO.get("episode").asInt val epNum = itemO["episode"]!!.jsonPrimitive.int
episode.episode_number = epNum.toFloat() episode.episode_number = epNum.toFloat()
episode.name = "Episode $epNum" episode.name = "Episode $epNum"
episodeList.add(episode) episodeList.add(episode)
@ -192,10 +199,9 @@ class AnimePahe : ConfigurableAnimeSource, AnimeHttpSource() {
private fun recursivePages(response: Response): List<SEpisode> { private fun recursivePages(response: Response): List<SEpisode> {
val responseString = response.body!!.string() val responseString = response.body!!.string()
val jElement: JsonElement = JsonParser.parseString(responseString) val jObject = json.decodeFromString<JsonObject>(responseString)
val jObject: JsonObject = jElement.asJsonObject val lastPage = jObject["last_page"]!!.jsonPrimitive.int
val lastPage = jObject.get("last_page").asInt val page = jObject["current_page"]!!.jsonPrimitive.int
val page = jObject.get("current_page").asInt
val hasNextPage = page < lastPage val hasNextPage = page < lastPage
val returnList = parseEpisodePage(responseString) val returnList = parseEpisodePage(responseString)
if (hasNextPage) { if (hasNextPage) {
@ -211,17 +217,15 @@ class AnimePahe : ConfigurableAnimeSource, AnimeHttpSource() {
} }
override fun videoListParse(response: Response): List<Video> { override fun videoListParse(response: Response): List<Video> {
val array = JsonParser.parseString(response.body!!.string()) val array = json.decodeFromString<JsonObject>(response.body!!.string())
.asJsonObject.get("data").asJsonArray .jsonObject["data"]!!.jsonArray
val videos = mutableListOf<Video>() val videos = mutableListOf<Video>()
for (item in array) { for (item in array) {
val quality = item.asJsonObject.keySet().first() val quality = item.jsonObject.keys.first()
val adflyLink = item.asJsonObject.get(quality) val adflyLink = item.jsonObject[quality]!!.jsonObject["kwik_adfly"]!!.jsonPrimitive.content
.asJsonObject.get("kwik_adfly").asString val kwikLink = item.jsonObject[quality]!!.jsonObject["kwik"]!!.jsonPrimitive.content
val kwikLink = item.asJsonObject.get(quality) val audio = item.jsonObject[quality]!!.jsonObject["audio"]!!
.asJsonObject.get("kwik").asString val qualityString = if (audio is JsonNull) "${quality}p" else "${quality}p (" + audio.jsonPrimitive.content + " audio)"
val audio = item.asJsonObject.get(quality).asJsonObject.get("audio")
val qualityString = if (audio is JsonNull) "${quality}p" else "${quality}p (" + audio.asString + " audio)"
videos.add(getVideo(adflyLink, kwikLink, qualityString)) videos.add(getVideo(adflyLink, kwikLink, qualityString))
} }
return videos return videos

View File

@ -5,7 +5,7 @@ ext {
extName = 'hanime.tv' extName = 'hanime.tv'
pkgNameSuffix = 'en.hanime' pkgNameSuffix = 'en.hanime'
extClass = '.Hanime' extClass = '.Hanime'
extVersionCode = 13 extVersionCode = 14
libVersion = '12' libVersion = '12'
containsNsfw = true containsNsfw = true
} }

View File

@ -4,10 +4,6 @@ import android.app.Application
import android.content.SharedPreferences import android.content.SharedPreferences
import androidx.preference.ListPreference import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen import androidx.preference.PreferenceScreen
import com.google.gson.JsonArray
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import com.google.gson.JsonParser
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
import eu.kanade.tachiyomi.animesource.model.AnimeFilter import eu.kanade.tachiyomi.animesource.model.AnimeFilter
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
@ -19,6 +15,15 @@ import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.int
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import kotlinx.serialization.json.long
import okhttp3.Headers import okhttp3.Headers
import okhttp3.MediaType.Companion.toMediaType import okhttp3.MediaType.Companion.toMediaType
import okhttp3.Request import okhttp3.Request
@ -27,6 +32,7 @@ import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response import okhttp3.Response
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import java.util.Locale import java.util.Locale
class Hanime : ConfigurableAnimeSource, AnimeHttpSource() { class Hanime : ConfigurableAnimeSource, AnimeHttpSource() {
@ -39,6 +45,8 @@ class Hanime : ConfigurableAnimeSource, AnimeHttpSource() {
override val supportsLatest = true override val supportsLatest = true
private val json: Json by injectLazy()
private val preferences: SharedPreferences by lazy { private val preferences: SharedPreferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000) Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
} }
@ -69,25 +77,24 @@ class Hanime : ConfigurableAnimeSource, AnimeHttpSource() {
return parseSearchJson(responseString) return parseSearchJson(responseString)
} }
private fun parseSearchJson(jsonLine: String?): AnimesPage { private fun parseSearchJson(jsonLine: String?): AnimesPage {
val jElement: JsonElement = JsonParser.parseString(jsonLine) val jsonData = jsonLine ?: return AnimesPage(emptyList(), false)
val jObject: JsonObject = jElement.asJsonObject val jObject = json.decodeFromString<JsonObject>(jsonData)
val nbPages = jObject.get("nbPages").asInt val nbPages = jObject["nbPages"]!!.jsonPrimitive.int
val page = jObject.get("page").asInt val page = jObject["page"]!!.jsonPrimitive.int
val hasNextPage = page < nbPages - 1 val hasNextPage = page < nbPages - 1
val arrayString = jObject.get("hits").asString val arrayString = jObject["hits"]!!.jsonPrimitive.content
val array = JsonParser.parseString(arrayString) val array = json.decodeFromString<JsonArray>(arrayString)
val jObjectb: JsonArray = array.asJsonArray
val animeList = mutableListOf<SAnime>() val animeList = mutableListOf<SAnime>()
for (item in jObjectb) { for (item in array) {
val anime = SAnime.create() val anime = SAnime.create()
anime.title = item.asJsonObject.get("name").asString anime.title = item.jsonObject["name"]!!.jsonPrimitive.content
anime.thumbnail_url = item.asJsonObject.get("cover_url").asString anime.thumbnail_url = item.jsonObject["cover_url"]!!.jsonPrimitive.content
anime.setUrlWithoutDomain("https://hanime.tv/videos/hentai/" + item.asJsonObject.get("slug").asString) anime.setUrlWithoutDomain("https://hanime.tv/videos/hentai/" + item.jsonObject["slug"]!!.jsonPrimitive.content)
anime.author = item.asJsonObject.get("brand").asString anime.author = item.jsonObject["brand"]!!.jsonPrimitive.content
anime.description = item.asJsonObject.get("description").asString.replace("<p>", "").replace("</p>", "") anime.description = item.jsonObject["description"]!!.jsonPrimitive.content.replace("<p>", "").replace("</p>", "")
anime.status = SAnime.COMPLETED anime.status = SAnime.COMPLETED
val tags = item.asJsonObject.get("tags").asJsonArray val tags = item.jsonObject["tags"]!!.jsonArray
anime.genre = tags.joinToString(", ") { it.asString } anime.genre = tags.joinToString(", ") { it.jsonPrimitive.content }
anime.initialized = true anime.initialized = true
animeList.add(anime) animeList.add(anime)
} }
@ -122,14 +129,21 @@ class Hanime : ConfigurableAnimeSource, AnimeHttpSource() {
override fun videoListParse(response: Response): List<Video> { override fun videoListParse(response: Response): List<Video> {
val responseString = response.body!!.string() val responseString = response.body!!.string()
val jElement: JsonElement = JsonParser.parseString(responseString) val jObject = json.decodeFromString<JsonObject>(responseString)
val jObject: JsonObject = jElement.asJsonObject val server = jObject["videos_manifest"]!!.jsonObject["servers"]!!.jsonArray[0].jsonObject
val server = jObject.get("videos_manifest").asJsonObject.get("servers").asJsonArray[0].asJsonObject val streams = server["streams"]!!.jsonArray
val streams = server.get("streams").asJsonArray
val linkList = mutableListOf<Video>() val linkList = mutableListOf<Video>()
for (stream in streams) { for (stream in streams) {
if (stream.asJsonObject.get("kind").asString != "premium_alert") { val streamObject = stream.jsonObject
linkList.add(Video(stream.asJsonObject.get("url").asString, stream.asJsonObject.get("height").asString + "p", stream.asJsonObject.get("url").asString, null)) if (streamObject["kind"]!!.jsonPrimitive.content != "premium_alert") {
linkList.add(
Video(
url = streamObject["url"]!!.jsonPrimitive.content,
quality = streamObject["height"]!!.jsonPrimitive.content + "p",
videoUrl = streamObject["url"]!!.jsonPrimitive.content,
uri = null
)
)
} }
} }
return linkList return linkList
@ -160,11 +174,10 @@ class Hanime : ConfigurableAnimeSource, AnimeHttpSource() {
override fun episodeListParse(response: Response): List<SEpisode> { override fun episodeListParse(response: Response): List<SEpisode> {
val responseString = response.body!!.string() val responseString = response.body!!.string()
val jElement: JsonElement = JsonParser.parseString(responseString) val jObject = json.decodeFromString<JsonObject>(responseString)
val jObject: JsonObject = jElement.asJsonObject
val episode = SEpisode.create() val episode = SEpisode.create()
episode.date_upload = jObject.asJsonObject.get("hentai_video").asJsonObject.get("released_at_unix").asLong * 1000 episode.date_upload = jObject.jsonObject["hentai_video"]!!.jsonObject["released_at_unix"]!!.jsonPrimitive.long * 1000
episode.name = jObject.asJsonObject.get("hentai_video").asJsonObject.get("name").asString episode.name = jObject.jsonObject["hentai_video"]!!.jsonObject["name"]!!.jsonPrimitive.content
episode.url = response.request.url.toString() episode.url = response.request.url.toString()
episode.episode_number = 1F episode.episode_number = 1F
return listOf(episode) return listOf(episode)

View File

@ -5,7 +5,7 @@ ext {
extName = 'twist.moe' extName = 'twist.moe'
pkgNameSuffix = 'en.twistmoe' pkgNameSuffix = 'en.twistmoe'
extClass = '.TwistMoe' extClass = '.TwistMoe'
extVersionCode = 7 extVersionCode = 8
libVersion = '12' libVersion = '12'
} }

View File

@ -1,10 +1,6 @@
package eu.kanade.tachiyomi.animeextension.en.twistmoe package eu.kanade.tachiyomi.animeextension.en.twistmoe
import android.annotation.SuppressLint import android.annotation.SuppressLint
import com.google.gson.JsonArray
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import com.google.gson.JsonParser
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
import eu.kanade.tachiyomi.animesource.model.AnimesPage import eu.kanade.tachiyomi.animesource.model.AnimesPage
import eu.kanade.tachiyomi.animesource.model.SAnime import eu.kanade.tachiyomi.animesource.model.SAnime
@ -13,11 +9,22 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST import eu.kanade.tachiyomi.network.POST
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.contentOrNull
import kotlinx.serialization.json.float
import kotlinx.serialization.json.int
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import okhttp3.Headers import okhttp3.Headers
import okhttp3.MediaType.Companion.toMediaType import okhttp3.MediaType.Companion.toMediaType
import okhttp3.Request import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response import okhttp3.Response
import uy.kohesive.injekt.injectLazy
import java.lang.Exception import java.lang.Exception
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Locale import java.util.Locale
@ -33,6 +40,8 @@ class TwistMoe : AnimeHttpSource() {
override val supportsLatest = false override val supportsLatest = false
private val json: Json by injectLazy()
override fun headersBuilder() = Headers.Builder().apply { override fun headersBuilder() = Headers.Builder().apply {
add("User-Agent", "Aniyomi") add("User-Agent", "Aniyomi")
add("Referer", "https://twist.moe/") add("Referer", "https://twist.moe/")
@ -46,8 +55,7 @@ class TwistMoe : AnimeHttpSource() {
override fun popularAnimeParse(response: Response): AnimesPage { override fun popularAnimeParse(response: Response): AnimesPage {
val responseString = response.body!!.string() val responseString = response.body!!.string()
val jElement: JsonElement = JsonParser.parseString(responseString) val array = json.decodeFromString<JsonArray>(responseString)
val array: JsonArray = jElement.asJsonArray
val list = mutableListOf<JsonElement>() val list = mutableListOf<JsonElement>()
array.toCollection(list) array.toCollection(list)
val page = response.request.url.fragment!!.toInt() - 1 val page = response.request.url.fragment!!.toInt() - 1
@ -61,9 +69,9 @@ class TwistMoe : AnimeHttpSource() {
val animeList = mutableListOf<SAnime>() val animeList = mutableListOf<SAnime>()
for (item in array) { for (item in array) {
val anime = SAnime.create() val anime = SAnime.create()
anime.title = item.asJsonObject.get("title").asString anime.title = item.jsonObject["title"]!!.jsonPrimitive.content
anime.setUrlWithoutDomain("$baseUrl/a/" + item.asJsonObject.get("slug").asJsonObject.get("slug").asString) anime.setUrlWithoutDomain("$baseUrl/a/" + item.jsonObject["slug"]!!.jsonObject["slug"]!!.jsonPrimitive.content)
anime.status = when (item.asJsonObject.get("ongoing").asInt) { anime.status = when (item.jsonObject["ongoing"]!!.jsonPrimitive.int) {
0 -> SAnime.COMPLETED 0 -> SAnime.COMPLETED
1 -> SAnime.ONGOING 1 -> SAnime.ONGOING
else -> SAnime.UNKNOWN else -> SAnime.UNKNOWN
@ -78,8 +86,7 @@ class TwistMoe : AnimeHttpSource() {
override fun searchAnimeParse(response: Response): AnimesPage { override fun searchAnimeParse(response: Response): AnimesPage {
val responseString = response.body!!.string() val responseString = response.body!!.string()
val jElement: JsonElement = JsonParser.parseString(responseString) val array = json.decodeFromString<JsonArray>(responseString)
val array: JsonArray = jElement.asJsonArray
val list = mutableListOf<JsonElement>() val list = mutableListOf<JsonElement>()
array.toCollection(list) array.toCollection(list)
val query = response.request.url.fragment!! val query = response.request.url.fragment!!
@ -88,9 +95,9 @@ class TwistMoe : AnimeHttpSource() {
.toLowerCase(Locale.ROOT) .toLowerCase(Locale.ROOT)
val toRemove = mutableListOf<JsonElement>() val toRemove = mutableListOf<JsonElement>()
for (entry in list) { for (entry in list) {
val title = entry.asJsonObject.get("title").asString.toLowerCase(Locale.ROOT) val title = entry.jsonObject["title"]!!.jsonPrimitive.content.toLowerCase(Locale.ROOT)
val altTitle = try { val altTitle = try {
entry.asJsonObject.get("alt_title").asString.toLowerCase(Locale.ROOT) entry.jsonObject["alt_title"]!!.jsonPrimitive.content.toLowerCase(Locale.ROOT)
} catch (e: Exception) { "" } } catch (e: Exception) { "" }
if (!(title.contains(query) || altTitle.contains(query))) toRemove.add(entry) if (!(title.contains(query) || altTitle.contains(query))) toRemove.add(entry)
} }
@ -109,13 +116,12 @@ class TwistMoe : AnimeHttpSource() {
override fun animeDetailsParse(response: Response): SAnime { override fun animeDetailsParse(response: Response): SAnime {
val responseString = response.body!!.string() val responseString = response.body!!.string()
val jElement: JsonElement = JsonParser.parseString(responseString) val jObject = json.decodeFromString<JsonObject>(responseString)
val jObject: JsonObject = jElement.asJsonObject
val anime = SAnime.create() val anime = SAnime.create()
anime.title = jObject.get("title").asString anime.title = jObject["title"]!!.jsonPrimitive.content
anime.setUrlWithoutDomain("$baseUrl/a/" + jObject.get("slug").asJsonObject.get("slug").asString) anime.setUrlWithoutDomain("$baseUrl/a/" + jObject["slug"]!!.jsonObject["slug"]!!.jsonPrimitive.content)
anime.description = jObject.get("description").asString anime.description = jObject["description"]!!.jsonPrimitive.content
anime.status = when (jObject.get("ongoing").asInt) { anime.status = when (jObject["ongoing"]!!.jsonPrimitive.int) {
0 -> SAnime.COMPLETED 0 -> SAnime.COMPLETED
1 -> SAnime.ONGOING 1 -> SAnime.ONGOING
else -> SAnime.UNKNOWN else -> SAnime.UNKNOWN
@ -127,11 +133,11 @@ class TwistMoe : AnimeHttpSource() {
private fun getCover(jObject: JsonObject, anime: SAnime) { private fun getCover(jObject: JsonObject, anime: SAnime) {
try { try {
val malID = try { val malID = try {
jObject.get("mal_id").asNumber.toString() jObject["mal_id"]!!.jsonPrimitive.contentOrNull
} catch (e: Exception) { } catch (e: Exception) {
"" ""
} }
if (malID.isNotEmpty()) { if (malID != null) {
val headers = Headers.Builder().apply { val headers = Headers.Builder().apply {
add("Content-Type", "application/json") add("Content-Type", "application/json")
add("Accept", "application/json") add("Accept", "application/json")
@ -139,11 +145,10 @@ class TwistMoe : AnimeHttpSource() {
val bodyString = "{\"query\":\"query(\$id: Int){Media(type:ANIME,idMal:\$id){coverImage{large}}}\",\"variables\":{\"id\":$malID}}" val bodyString = "{\"query\":\"query(\$id: Int){Media(type:ANIME,idMal:\$id){coverImage{large}}}\",\"variables\":{\"id\":$malID}}"
val body = bodyString.toRequestBody("application/json".toMediaType()) val body = bodyString.toRequestBody("application/json".toMediaType())
val coverResponse = client.newCall(POST("https://graphql.anilist.co", headers, body)).execute() val coverResponse = client.newCall(POST("https://graphql.anilist.co", headers, body)).execute()
val imageUrl = JsonParser.parseString(coverResponse.body!!.string()) val imageUrl = json.decodeFromString<JsonObject>(coverResponse.body!!.string())["data"]!!
.asJsonObject.get("data") .jsonObject["Media"]!!
.asJsonObject.get("Media") .jsonObject["coverImage"]!!
.asJsonObject.get("coverImage") .jsonObject["large"]!!.jsonPrimitive.content
.asJsonObject.get("large").asString
if (imageUrl.isNotEmpty()) anime.thumbnail_url = imageUrl if (imageUrl.isNotEmpty()) anime.thumbnail_url = imageUrl
} else { } else {
val query = anime.title val query = anime.title
@ -154,11 +159,10 @@ class TwistMoe : AnimeHttpSource() {
val bodyString = "{\"query\":\"query(\$query: String){Media(type:ANIME,search:\$query){coverImage{large}}}\",\"variables\":{\"query\":\"$query\"}}" val bodyString = "{\"query\":\"query(\$query: String){Media(type:ANIME,search:\$query){coverImage{large}}}\",\"variables\":{\"query\":\"$query\"}}"
val body = bodyString.toRequestBody("application/json".toMediaType()) val body = bodyString.toRequestBody("application/json".toMediaType())
val coverResponse = client.newCall(POST("https://graphql.anilist.co", headers, body)).execute() val coverResponse = client.newCall(POST("https://graphql.anilist.co", headers, body)).execute()
val imageUrl = JsonParser.parseString(coverResponse.body!!.string()) val imageUrl = json.decodeFromString<JsonObject>(coverResponse.body!!.string())["data"]!!
.asJsonObject.get("data") .jsonObject["Media"]!!
.asJsonObject.get("Media") .jsonObject["coverImage"]!!
.asJsonObject.get("coverImage") .jsonObject["large"]!!.jsonPrimitive.content
.asJsonObject.get("large").asString
if (imageUrl.isNotEmpty()) anime.thumbnail_url = imageUrl if (imageUrl.isNotEmpty()) anime.thumbnail_url = imageUrl
} }
} catch (e: Exception) { } catch (e: Exception) {
@ -171,15 +175,15 @@ class TwistMoe : AnimeHttpSource() {
override fun videoListParse(response: Response): List<Video> { override fun videoListParse(response: Response): List<Video> {
val responseString = response.body!!.string() val responseString = response.body!!.string()
val array = JsonParser.parseString(responseString).asJsonArray val array = json.decodeFromString<JsonArray>(responseString)
val list = mutableListOf<JsonElement>() val list = mutableListOf<JsonElement>()
array.toCollection(list) array.toCollection(list)
val episodeNumber = response.request.url.fragment!!.toFloat() val episodeNumber = response.request.url.fragment!!.toFloat()
val videoList = mutableListOf<Video>() val videoList = mutableListOf<Video>()
val aes = AESDecrypt() val aes = AESDecrypt()
for (entry in list) { for (entry in list) {
if (entry.asJsonObject.get("number").asNumber.toFloat() == episodeNumber) { if (entry.jsonObject["number"]!!.jsonPrimitive.float == episodeNumber) {
val source = entry.asJsonObject.get("source").asString val source = entry.jsonObject["source"]!!.jsonPrimitive.content
val ivAndKey = aes.getIvAndKey(source) val ivAndKey = aes.getIvAndKey(source)
val toDecode = aes.getToDecode(source) val toDecode = aes.getToDecode(source)
val url = "https://air-cdn.twist.moe" + val url = "https://air-cdn.twist.moe" +
@ -198,16 +202,16 @@ class TwistMoe : AnimeHttpSource() {
override fun episodeListParse(response: Response): List<SEpisode> { override fun episodeListParse(response: Response): List<SEpisode> {
val responseString = response.body!!.string() val responseString = response.body!!.string()
val array = JsonParser.parseString(responseString).asJsonArray val array = json.decodeFromString<JsonArray>(responseString)
val list = mutableListOf<JsonElement>() val list = mutableListOf<JsonElement>()
array.toCollection(list) array.toCollection(list)
val episodeList = mutableListOf<SEpisode>() val episodeList = mutableListOf<SEpisode>()
for (entry in list) { for (entry in list) {
try { try {
val episode = SEpisode.create() val episode = SEpisode.create()
episode.date_upload = parseDate(entry.asJsonObject.get("updated_at").asString) episode.date_upload = parseDate(entry.jsonObject["updated_at"]!!.jsonPrimitive.content)
episode.name = "Episode " + entry.asJsonObject.get("number").asNumber.toString() episode.name = "Episode " + entry.jsonObject["number"]!!.jsonPrimitive.content
episode.episode_number = entry.asJsonObject.get("number").asNumber.toFloat() episode.episode_number = entry.jsonObject["number"]!!.jsonPrimitive.float
episode.url = response.request.url.toString() + "#${episode.episode_number}" episode.url = response.request.url.toString() + "#${episode.episode_number}"
episodeList.add(episode) episodeList.add(episode)
} catch (e: Exception) { } catch (e: Exception) {

View File

@ -5,7 +5,7 @@ ext {
extName = 'AnimeFLV' extName = 'AnimeFLV'
pkgNameSuffix = 'es.animeflv' pkgNameSuffix = 'es.animeflv'
extClass = '.AnimeFlv' extClass = '.AnimeFlv'
extVersionCode = 4 extVersionCode = 5
libVersion = '12' libVersion = '12'
} }

View File

@ -2,11 +2,10 @@ package eu.kanade.tachiyomi.animeextension.es.animeflv
import android.app.Application import android.app.Application
import android.content.SharedPreferences import android.content.SharedPreferences
import android.util.Log
import androidx.preference.ListPreference import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen import androidx.preference.PreferenceScreen
import com.github.salomonbrys.kotson.get import eu.kanade.tachiyomi.animeextension.es.animeflv.extractors.OkruExtractor
import com.google.gson.JsonParser import eu.kanade.tachiyomi.animeextension.es.animeflv.extractors.StreamTapeExtractor
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
import eu.kanade.tachiyomi.animesource.model.SAnime import eu.kanade.tachiyomi.animesource.model.SAnime
@ -15,6 +14,13 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonNull
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
@ -22,8 +28,8 @@ import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import java.lang.Exception import java.lang.Exception
import java.net.URL
class AnimeFlv : ConfigurableAnimeSource, ParsedAnimeHttpSource() { class AnimeFlv : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
@ -37,6 +43,8 @@ class AnimeFlv : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override val client: OkHttpClient = network.cloudflareClient override val client: OkHttpClient = network.cloudflareClient
private val json: Json by injectLazy()
private val preferences: SharedPreferences by lazy { private val preferences: SharedPreferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000) Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
} }
@ -96,19 +104,23 @@ class AnimeFlv : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
document.select("script").forEach { script -> document.select("script").forEach { script ->
if (script.data().contains("var videos = {")) { if (script.data().contains("var videos = {")) {
val data = script.data().substringAfter("var videos = ").substringBefore(";") val data = script.data().substringAfter("var videos = ").substringBefore(";")
val json = JsonParser.parseString(data).asJsonObject val jsonObject = json.decodeFromString<JsonObject>(data)
val sub = json.get("SUB") val sub = jsonObject["SUB"]!!
if (!sub.isJsonNull) { if (sub !is JsonNull) {
for (server in sub.asJsonArray) { for (server in sub.jsonArray) {
val url = server.asJsonObject.get("code").asString.replace("\\/", "/") val url = server.jsonObject["code"]!!.jsonPrimitive.content.replace("\\/", "/")
val quality = server.asJsonObject.get("title").asString val quality = server.jsonObject["title"]!!.jsonPrimitive.content
if (quality == "Stape") { if (quality == "Stape") {
val videos = getStapeVideos(url) val video = StreamTapeExtractor(client).videoFromUrl(url, quality)
videoList += videos if (video != null) {
videoList.add(video)
}
} }
if (quality == "Okru") { if (quality == "Okru") {
val videos = getOkruVideos(url) val videos = OkruExtractor(client).videosFromUrl(url, quality)
videoList += videos if (videos != null) {
videoList.addAll(videos)
}
} }
} }
} }
@ -123,64 +135,8 @@ class AnimeFlv : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun videoFromElement(element: Element) = throw Exception("not used") override fun videoFromElement(element: Element) = throw Exception("not used")
// this code is trash but work
private fun getStapeVideos(url: String): List<Video> {
val videoList = mutableListOf<Video>()
val url5 = url.replace("https://streamtape.com/e/", "")
val url6 = url5.replace("/", "")
val document = client.newCall(GET("https://api.streamtape.com/file/dlticket?file=$url6&login=ef23317a52e4442dbdd3&key=mydvdBk717tb08Y")).execute().asJsoup()
val test22 = document.body().text()
val test23 = JsonParser.parseString(test22).asJsonObject
val test24 = test23.get("result").get("ticket").toString().replace("\"", "")
val test80 = test24
val url80 = "https://api.streamtape.com/file/dl?file=$url6&ticket=$test24&captcha_response={captcha_response}".replace("={captcha_response}", "={captcha_response}")
Log.i("stapeee", url80)
val document2 = client.newCall(GET(url80)).execute().asJsoup()
//I don't know how to make it wait 5 seconds, but this worked for some reason
val jsjs = URL(url80).readText()
val jsjs1 = URL(url80).readText()
val jsjs2 = URL(url80).readText()
val jsjs3 = URL(url80).readText()
URL(url80).readText()
URL(url80).readText()
URL(url80).readText()
URL(url80).readText()
URL(url80).readText()
URL(url80).readText()
URL(url80).readText()
URL(url80).readText()
URL(url80).readText()
val jsjs4 = URL(url80).readText()
val test29 = document2.body().text()
Log.i("stapeee", jsjs4)
val test30 = JsonParser.parseString(jsjs4).asJsonObject
val test31 = test30.get("result").get("url").toString().replace("\"", "")
Log.i("stapeee", test31)
videoList.add(Video(test31, "Stape", test31, null))
return videoList
}
private fun getOkruVideos(url: String): List<Video> {
val document = client.newCall(GET(url)).execute().asJsoup()
Log.i("bruuh", document.select("div[data-options]").attr("data-options"))
val videoList = mutableListOf<Video>()
val videosString = document.select("div[data-options]").attr("data-options")
.substringAfter("\\\"videos\\\":[{\\\"name\\\":\\\"")
.substringBefore("]")
videosString.split("{\\\"name\\\":\\\"").reversed().forEach {
val videoUrl = it.substringAfter("url\\\":\\\"")
.substringBefore("\\\"")
.replace("\\\\u0026", "&")
val quality = it.substringBefore("\\\"")
if (videoUrl.startsWith("https://")) {
videoList.add(Video(videoUrl, quality, videoUrl, null))
}
}
return videoList
}
override fun List<Video>.sort(): List<Video> { override fun List<Video>.sort(): List<Video> {
val quality = preferences.getString("preferred_quality", "hd") val quality = preferences.getString("preferred_quality", "Stape")
if (quality != null) { if (quality != null) {
val newList = mutableListOf<Video>() val newList = mutableListOf<Video>()
var preferred = 0 var preferred = 0
@ -237,9 +193,9 @@ class AnimeFlv : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
val videoQualityPref = ListPreference(screen.context).apply { val videoQualityPref = ListPreference(screen.context).apply {
key = "preferred_quality" key = "preferred_quality"
title = "Preferred quality" title = "Preferred quality"
entries = arrayOf("hd", "sd", "low", "lowest", "mobile") entries = arrayOf("Stape", "hd", "sd", "low", "lowest", "mobile")
entryValues = arrayOf("hd", "sd", "low", "lowest", "mobile") entryValues = arrayOf("Stape", "hd", "sd", "low", "lowest", "mobile")
setDefaultValue("hd") setDefaultValue("Stape")
summary = "%s" summary = "%s"
setOnPreferenceChangeListener { _, newValue -> setOnPreferenceChangeListener { _, newValue ->

View File

@ -0,0 +1,41 @@
package eu.kanade.tachiyomi.animeextension.es.animeflv.extractors
import android.util.Log
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.Headers
import okhttp3.OkHttpClient
class OkruExtractor(private val client: OkHttpClient) {
fun videosFromUrl(url: String, quality: String): List<Video>? {
val document = client.newCall(GET(url)).execute().asJsoup()
Log.i("bruuh", document.select("div[data-options]").attr("data-options"))
val videoList = mutableListOf<Video>()
val videosString = document.select("div[data-options]").attr("data-options")
.substringAfter("\\\"videos\\\":[{\\\"name\\\":\\\"")
.substringBefore("]")
videosString.split("{\\\"name\\\":\\\"").reversed().forEach {
val videoUrl = it.substringAfter("url\\\":\\\"")
.substringBefore("\\\"")
.replace("\\\\u0026", "&")
val videoQuality = "Okru: " + it.substringBefore("\\\"")
if (videoUrl.startsWith("https://")) {
videoList.add(Video(videoUrl, videoQuality, videoUrl, null))
}
}
return videoList
}
private fun getRandomString(length: Int = 10): String {
val allowedChars = ('A'..'Z') + ('a'..'z') + ('0'..'9')
return (1..length)
.map { allowedChars.random() }
.joinToString("")
}
private fun doodHeaders(tld: String) = Headers.Builder().apply {
add("User-Agent", "Aniyomi")
add("Referer", "https://dood.$tld/")
}.build()
}

View File

@ -0,0 +1,18 @@
package eu.kanade.tachiyomi.animeextension.es.animeflv.extractors
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
class StreamTapeExtractor(private val client: OkHttpClient) {
fun videoFromUrl(url: String, quality: String): Video? {
val document = client.newCall(GET(url)).execute().asJsoup()
val script = document.select("script:containsData(document.getElementById('robotlink'))")
.firstOrNull()?.data()?.substringAfter("document.getElementById('robotlink').innerHTML = '")
?: return null
val videoUrl = "https:" + script.substringBefore("'") +
script.substringAfter("+ ('xcd").substringBefore("'")
return Video(url, quality, videoUrl, null)
}
}