fix(fr/franime): Fix internal anime list (#2214)
This commit is contained in:
@ -8,7 +8,7 @@ ext {
|
||||
extName = 'FrAnime'
|
||||
pkgNameSuffix = 'fr.franime'
|
||||
extClass = '.FrAnime'
|
||||
extVersionCode = 7
|
||||
extVersionCode = 8
|
||||
libVersion = '13'
|
||||
containsNsfw = true
|
||||
}
|
||||
|
@ -37,48 +37,83 @@ class FrAnime : AnimeHttpSource() {
|
||||
|
||||
override val client: OkHttpClient = network.cloudflareClient
|
||||
|
||||
override fun headersBuilder() = super.headersBuilder().add("Referer", "$baseUrl/")
|
||||
override fun headersBuilder() = super.headersBuilder()
|
||||
.add("Referer", "$baseUrl/")
|
||||
.add("Origin", baseUrl)
|
||||
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
private val database by lazy {
|
||||
client.newCall(GET("$baseApiUrl/animes/")).execute()
|
||||
client.newCall(GET("$baseApiUrl/animes/", headers)).execute()
|
||||
.use { it.body.string() }
|
||||
.let { json.decodeFromString<Array<Anime>>(it) }
|
||||
.let { json.decodeFromString<List<Anime>>(it) }
|
||||
}
|
||||
|
||||
// === Anime Details
|
||||
// ============================== Popular ===============================
|
||||
override fun fetchPopularAnime(page: Int) =
|
||||
pagesToAnimesPage(database.sortedByDescending { it.note }, page)
|
||||
|
||||
override fun popularAnimeParse(response: Response) = throw Exception("not used")
|
||||
|
||||
override fun popularAnimeRequest(page: Int) = throw Exception("not used")
|
||||
|
||||
// =============================== Latest ===============================
|
||||
override fun fetchLatestUpdates(page: Int) = pagesToAnimesPage(database.reversed(), page)
|
||||
|
||||
override fun latestUpdatesParse(response: Response): AnimesPage = throw Exception("not used")
|
||||
|
||||
override fun latestUpdatesRequest(page: Int): Request = throw Exception("not used")
|
||||
|
||||
// =============================== Search ===============================
|
||||
override fun fetchSearchAnime(page: Int, query: String, filters: AnimeFilterList): Observable<AnimesPage> {
|
||||
val pages = database.filter {
|
||||
it.title.contains(query, true) ||
|
||||
it.originalTitle.contains(query, true) ||
|
||||
it.titlesAlt.en?.contains(query, true) == true ||
|
||||
it.titlesAlt.enJp?.contains(query, true) == true ||
|
||||
it.titlesAlt.jaJp?.contains(query, true) == true ||
|
||||
titleToUrl(it.originalTitle).contains(query)
|
||||
}
|
||||
return pagesToAnimesPage(pages, page)
|
||||
}
|
||||
|
||||
override fun searchAnimeParse(response: Response): AnimesPage = throw Exception("not used")
|
||||
|
||||
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request = throw Exception("not used")
|
||||
|
||||
// =========================== Anime Details ============================
|
||||
override fun fetchAnimeDetails(anime: SAnime): Observable<SAnime> = Observable.just(anime)
|
||||
|
||||
override fun animeDetailsParse(response: Response): SAnime = throw Exception("not used")
|
||||
|
||||
// === Episodes
|
||||
|
||||
// ============================== Episodes ==============================
|
||||
override fun fetchEpisodeList(anime: SAnime): Observable<List<SEpisode>> {
|
||||
val url = (baseUrl + anime.url).toHttpUrl()
|
||||
val stem = url.encodedPathSegments.last()
|
||||
val language = url.queryParameter("lang") ?: "vo"
|
||||
val season = url.queryParameter("s")?.toIntOrNull() ?: 1
|
||||
val animeData = database.first { titleToUrl(it.originalTitle) == stem }
|
||||
val episodes = mutableListOf<SEpisode>()
|
||||
animeData.seasons[season - 1].episodes.forEachIndexed { index, episode ->
|
||||
val players = (if (language == "vo") episode.languages.vo else episode.languages.vf).players
|
||||
if (players.isNotEmpty()) {
|
||||
episodes += SEpisode.create().apply {
|
||||
val episodes = animeData.seasons[season - 1].episodes
|
||||
.mapIndexedNotNull { index, episode ->
|
||||
val players = when (language) {
|
||||
"vo" -> episode.languages.vo
|
||||
else -> episode.languages.vf
|
||||
}.players
|
||||
|
||||
if (players.isEmpty()) return@mapIndexedNotNull null
|
||||
|
||||
SEpisode.create().apply {
|
||||
setUrlWithoutDomain(anime.url + "&ep=${index + 1}")
|
||||
name = episode.title
|
||||
episode_number = index.toFloat()
|
||||
episode_number = (index + 1).toFloat()
|
||||
}
|
||||
}
|
||||
}
|
||||
return Observable.just(episodes.sortedByDescending { it.episode_number })
|
||||
}
|
||||
|
||||
override fun episodeListParse(response: Response): List<SEpisode> = throw Exception("not used")
|
||||
|
||||
// === Players
|
||||
|
||||
// ============================ Video Links =============================
|
||||
override fun fetchVideoList(episode: SEpisode): Observable<List<Video>> {
|
||||
val url = (baseUrl + episode.url).toHttpUrl()
|
||||
val seasonNumber = url.queryParameter("s")?.toIntOrNull() ?: 1
|
||||
@ -106,63 +141,23 @@ class FrAnime : AnimeHttpSource() {
|
||||
return Observable.just(videos)
|
||||
}
|
||||
|
||||
// === Latest
|
||||
|
||||
override fun fetchLatestUpdates(page: Int): Observable<AnimesPage> {
|
||||
val pages = database.reversed().toList().chunked(50)
|
||||
val hasNextPage = pages.size > page
|
||||
val entries = pageToSAnimes(pages.getOrNull(page - 1))
|
||||
// ============================= Utilities ==============================
|
||||
private fun pagesToAnimesPage(pages: List<Anime>, page: Int): Observable<AnimesPage> {
|
||||
val chunks = pages.chunked(50)
|
||||
val hasNextPage = chunks.size > page
|
||||
val entries = pageToSAnimes(chunks.getOrNull(page - 1) ?: emptyList())
|
||||
return Observable.just(AnimesPage(entries, hasNextPage))
|
||||
}
|
||||
|
||||
override fun latestUpdatesParse(response: Response): AnimesPage = throw Exception("not used")
|
||||
private val titleRegex by lazy { Regex("[^A-Za-z0-9 ]") }
|
||||
private fun titleToUrl(title: String) = titleRegex.replace(title, "").replace(" ", "-").lowercase()
|
||||
|
||||
override fun latestUpdatesRequest(page: Int): Request = throw Exception("not used")
|
||||
|
||||
// === Popular
|
||||
|
||||
override fun fetchPopularAnime(page: Int): Observable<AnimesPage> {
|
||||
val pages = database.sortedByDescending { it.note }.chunked(50)
|
||||
val hasNextPage = pages.size > page
|
||||
val entries = pageToSAnimes(pages.getOrNull(page - 1))
|
||||
return Observable.just(AnimesPage(entries, hasNextPage))
|
||||
}
|
||||
|
||||
override fun popularAnimeParse(response: Response) = throw Exception("not used")
|
||||
|
||||
override fun popularAnimeRequest(page: Int) = throw Exception("not used")
|
||||
|
||||
// === Search
|
||||
|
||||
override fun fetchSearchAnime(page: Int, query: String, filters: AnimeFilterList): Observable<AnimesPage> {
|
||||
val pages = database.filter {
|
||||
it.title.contains(query, true) ||
|
||||
it.originalTitle.contains(query, true) ||
|
||||
it.titlesAlt.en?.contains(query, true) == true ||
|
||||
it.titlesAlt.enJp?.contains(query, true) == true ||
|
||||
it.titlesAlt.jaJp?.contains(query, true) == true ||
|
||||
titleToUrl(it.originalTitle).contains(query)
|
||||
}.chunked(50)
|
||||
val hasNextPage = pages.size > page
|
||||
val entries = pageToSAnimes(pages.getOrNull(page - 1))
|
||||
return Observable.just(AnimesPage(entries, hasNextPage))
|
||||
}
|
||||
|
||||
override fun searchAnimeParse(response: Response): AnimesPage = throw Exception("not used")
|
||||
|
||||
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request = throw Exception("not used")
|
||||
|
||||
// === Utils
|
||||
|
||||
private fun titleToUrl(title: String): String = Regex("[^A-Za-z0-9 ]").replace(title, "").replace(" ", "-").lowercase()
|
||||
|
||||
private fun pageToSAnimes(page: List<Anime>?): List<SAnime> {
|
||||
val entries = mutableListOf<SAnime>()
|
||||
page?.forEach {
|
||||
for ((index, season) in it.seasons.withIndex()) {
|
||||
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 hasVf = season.episodes.fold(false) { v, e -> v or e.languages.vf.players.isNotEmpty() }
|
||||
private fun pageToSAnimes(page: List<Anime>): List<SAnime> {
|
||||
return page.flatMap { anime ->
|
||||
anime.seasons.flatMapIndexed { index, season ->
|
||||
val seasonTitle = anime.title + if (anime.seasons.size > 1) " S${index + 1}" else ""
|
||||
val hasVostfr = season.episodes.any { ep -> ep.languages.vo.players.isNotEmpty() }
|
||||
val hasVf = season.episodes.any { ep -> ep.languages.vf.players.isNotEmpty() }
|
||||
|
||||
// I want to die for writing this
|
||||
val languages = listOfNotNull(
|
||||
@ -170,20 +165,19 @@ class FrAnime : AnimeHttpSource() {
|
||||
if (hasVf) Triple("VF", "vf", hasVostfr) else null,
|
||||
)
|
||||
|
||||
languages.forEach { lang ->
|
||||
entries += SAnime.create().apply {
|
||||
languages.map { lang ->
|
||||
SAnime.create().apply {
|
||||
title = seasonTitle + if (lang.third) " (${lang.first})" 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=${lang.second}&s=${index + 1}")
|
||||
thumbnail_url = anime.poster
|
||||
genre = anime.genres.joinToString()
|
||||
status = parseStatus(anime.status, anime.seasons.size, index + 1)
|
||||
description = anime.description
|
||||
setUrlWithoutDomain("/anime/${titleToUrl(anime.originalTitle)}?lang=${lang.second}&s=${index + 1}")
|
||||
initialized = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return entries
|
||||
}
|
||||
|
||||
private fun parseStatus(statusString: String?, seasonCount: Int = 1, season: Int = 1): Int {
|
||||
|
Reference in New Issue
Block a user