fix(fr/franime): Fix video extraction (#1964)

This commit is contained in:
Claudemirovsky
2023-07-28 12:40:13 +00:00
committed by GitHub
parent 9c9445d8b5
commit db6c9eb905
2 changed files with 32 additions and 35 deletions

View File

@ -1,12 +1,14 @@
apply plugin: 'com.android.application' plugins {
apply plugin: 'kotlin-android' alias(libs.plugins.android.application)
apply plugin: 'kotlinx-serialization' alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.serialization)
}
ext { ext {
extName = 'FrAnime' extName = 'FrAnime'
pkgNameSuffix = 'fr.franime' pkgNameSuffix = 'fr.franime'
extClass = '.FrAnime' extClass = '.FrAnime'
extVersionCode = 3 extVersionCode = 4
libVersion = '13' libVersion = '13'
containsNsfw = true containsNsfw = true
} }

View File

@ -1,6 +1,5 @@
package eu.kanade.tachiyomi.animeextension.fr.franime package eu.kanade.tachiyomi.animeextension.fr.franime
import android.net.UrlQuerySanitizer
import eu.kanade.tachiyomi.animeextension.fr.franime.dto.Anime import eu.kanade.tachiyomi.animeextension.fr.franime.dto.Anime
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
@ -14,15 +13,13 @@ import eu.kanade.tachiyomi.lib.sibnetextractor.SibnetExtractor
import eu.kanade.tachiyomi.lib.streamsbextractor.StreamSBExtractor import eu.kanade.tachiyomi.lib.streamsbextractor.StreamSBExtractor
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import rx.Observable import rx.Observable
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.lang.Exception import java.lang.Exception
import java.net.URI
import kotlin.io.path.Path
import kotlin.io.path.name
class FrAnime : AnimeHttpSource() { class FrAnime : AnimeHttpSource() {
@ -41,6 +38,8 @@ class FrAnime : AnimeHttpSource() {
override val client: OkHttpClient = network.cloudflareClient override val client: OkHttpClient = network.cloudflareClient
override fun headersBuilder() = super.headersBuilder().add("Referer", "$baseUrl/")
private val json: Json by injectLazy() private val json: Json by injectLazy()
private val database by lazy { private val database by lazy {
@ -58,9 +57,10 @@ class FrAnime : AnimeHttpSource() {
// === Episodes // === Episodes
override fun fetchEpisodeList(anime: SAnime): Observable<List<SEpisode>> { override fun fetchEpisodeList(anime: SAnime): Observable<List<SEpisode>> {
val stem = Path(URI(anime.url).path).name // WILL break on API update ! name becomes fileName in new versions ! val url = (baseUrl + anime.url).toHttpUrl()
val language = UrlQuerySanitizer(anime.url).getValue("lang") val stem = url.encodedPathSegments.last()
val season = UrlQuerySanitizer(anime.url).getValue("s").toInt() val language = url.queryParameter("lang") ?: "vo"
val season = url.queryParameter("s")?.toIntOrNull() ?: 1
val animeData = database.first { titleToUrl(it.originalTitle) == stem } val animeData = database.first { titleToUrl(it.originalTitle) == stem }
val episodes = mutableListOf<SEpisode>() val episodes = mutableListOf<SEpisode>()
animeData.seasons[season - 1].episodes.forEachIndexed { index, episode -> animeData.seasons[season - 1].episodes.forEachIndexed { index, episode ->
@ -81,30 +81,30 @@ class FrAnime : AnimeHttpSource() {
// === Players // === Players
override fun fetchVideoList(episode: SEpisode): Observable<List<Video>> { override fun fetchVideoList(episode: SEpisode): Observable<List<Video>> {
val seasonNumber = UrlQuerySanitizer(episode.url).getValue("s").toInt() val url = (baseUrl + episode.url).toHttpUrl()
val episodeNumber = UrlQuerySanitizer(episode.url).getValue("ep").toInt() val seasonNumber = url.queryParameter("s")?.toIntOrNull() ?: 1
val episodeLang = UrlQuerySanitizer(episode.url).getValue("lang") val episodeNumber = url.queryParameter("ep")?.toIntOrNull() ?: 1
val stem = Path(URI(episode.url).path).name val episodeLang = url.queryParameter("lang") ?: "vo"
val stem = url.encodedPathSegments.last()
val animeData = database.first { titleToUrl(it.originalTitle) == stem } val animeData = database.first { titleToUrl(it.originalTitle) == stem }
val episodeData = animeData.seasons[seasonNumber - 1].episodes[episodeNumber - 1] val episodeData = animeData.seasons[seasonNumber - 1].episodes[episodeNumber - 1]
val videoBaseUrl = "$baseApiAnimeUrl/${animeData.id}/${seasonNumber - 1}/${episodeNumber - 1}" val videoBaseUrl = "$baseApiAnimeUrl/${animeData.id}/${seasonNumber - 1}/${episodeNumber - 1}"
val videos = mutableListOf<Video>()
val players = if (episodeLang == "vo") episodeData.languages.vo.players else episodeData.languages.vf.players val players = if (episodeLang == "vo") episodeData.languages.vo.players else episodeData.languages.vf.players
players.forEachIndexed { index, playerName -> val videos = players.flatMapIndexed { index, playerName ->
val apiUrl = "$videoBaseUrl/$episodeLang/$index" val apiUrl = "$videoBaseUrl/$episodeLang/$index"
val playerUrl = client.newCall(GET(apiUrl)).execute().body.string() val playerUrl = client.newCall(GET(apiUrl, headers)).execute().body.string()
val playerVideos = when (playerName) { when (playerName) {
"franime_myvi" -> listOf(Video(playerUrl, "FRAnime", playerUrl)) "franime_myvi" -> listOf(Video(playerUrl, "FRAnime", playerUrl))
"myvi" -> MytvExtractor(client).videosFromUrl(playerUrl) "myvi" -> MytvExtractor(client).videosFromUrl(playerUrl)
"sendvid" -> SendvidExtractor(client, headers).videosFromUrl(playerUrl) "sendvid" -> SendvidExtractor(client, headers).videosFromUrl(playerUrl)
"sibnet" -> SibnetExtractor(client).videosFromUrl(playerUrl) "sibnet" -> SibnetExtractor(client).videosFromUrl(playerUrl)
"sbfull" -> StreamSBExtractor(client).videosFromUrl(playerUrl, headers) "sbfull" -> StreamSBExtractor(client).videosFromUrl(playerUrl, headers)
else -> null else -> emptyList()
} }
if (playerVideos != null) videos.addAll(playerVideos)
} }
return Observable.just(videos) return Observable.just(videos)
} }
@ -165,26 +165,21 @@ class FrAnime : AnimeHttpSource() {
val seasonTitle = it.title + if (it.seasons.size > 1) " S${index + 1}" else "" val seasonTitle = it.title + if (it.seasons.size > 1) " S${index + 1}" else ""
val hasVostfr = season.episodes.fold(false) { v, e -> v or e.languages.vo.players.isNotEmpty() } val hasVostfr = season.episodes.fold(false) { v, e -> v or e.languages.vo.players.isNotEmpty() }
val hasVf = season.episodes.fold(false) { v, e -> v or e.languages.vf.players.isNotEmpty() } val hasVf = season.episodes.fold(false) { v, e -> v or e.languages.vf.players.isNotEmpty() }
// I want to die for writing this // I want to die for writing this
if (hasVostfr) { val languages = listOfNotNull(
if (hasVostfr) Triple("VOSTFR", "vo", hasVf) else null,
if (hasVf) Triple("VF", "vf", hasVostfr) else null,
)
languages.forEach { lang ->
entries += SAnime.create().apply { entries += SAnime.create().apply {
title = seasonTitle + if (hasVf) " (VOSTFR)" else "" title = seasonTitle + if (lang.third) " (${lang.first})" else ""
thumbnail_url = it.poster thumbnail_url = it.poster
genre = it.genres.joinToString() genre = it.genres.joinToString()
status = parseStatus(it.status, it.seasons.size, index + 1) status = parseStatus(it.status, it.seasons.size, index + 1)
description = it.description description = it.description
setUrlWithoutDomain("/anime/${titleToUrl(it.originalTitle)}?lang=vo&s=${index + 1}") setUrlWithoutDomain("/anime/${titleToUrl(it.originalTitle)}?lang=${lang.second}&s=${index + 1}")
initialized = true
}
}
if (hasVf) {
entries += SAnime.create().apply {
title = seasonTitle + if (hasVostfr) " (VF)" else ""
thumbnail_url = it.poster
genre = it.genres.joinToString()
status = parseStatus(it.status, it.seasons.size, index + 1)
description = it.description
setUrlWithoutDomain("/anime/${titleToUrl(it.originalTitle)}?lang=vf&s=${index + 1}")
initialized = true initialized = true
} }
} }