Skip to content

Commit

Permalink
feat(en/fmovies): Add status and next episode air date using title (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
Samfun75 authored Jan 29, 2024
1 parent 4470991 commit e54612a
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 9 deletions.
2 changes: 1 addition & 1 deletion src/en/fmovies/build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
ext {
extName = 'FMovies'
extClass = '.FMovies'
extVersionCode = 17
extVersionCode = 18
}

apply from: "$rootDir/common.gradle"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class FMovies : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}

private val utils by lazy { FmoviesUtils() }
private val utils by lazy { FmoviesUtils(client, headers) }

// ============================== Popular ===============================

Expand Down Expand Up @@ -107,15 +107,36 @@ class FMovies : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
val desc = descElement?.selectFirst("div[data-name=full]")?.ownText() ?: descElement?.ownText() ?: ""
val extraInfo = detail?.select("> div")?.joinToString("\n") { it.text() } ?: ""

val mediaTitle = info.selectFirst("h1.name")!!.text()
val mediaDetail = utils.getDetail(mediaTitle)

return SAnime.create().apply {
title = info.selectFirst("h1.name")!!.text()
title = mediaTitle
status = when (mediaDetail?.status) {
"Ended", "Released" -> SAnime.COMPLETED
"In Production" -> SAnime.LICENSED
"Canceled" -> SAnime.CANCELLED
"Returning Series" -> {
mediaDetail.nextEpisode?.let { SAnime.ONGOING } ?: SAnime.ON_HIATUS
}
else -> SAnime.UNKNOWN
}
thumbnail_url = document.selectFirst("section#w-info > div.poster img")!!.attr("src")
description = if (desc.isBlank()) extraInfo else "$desc\n\n$extraInfo"
genre = detail?.let {
it.select("> div:has(> div:contains(Genre:)) span").joinToString(", ") { it.text() }
description = buildString {
appendLine(desc.ifBlank { mediaDetail?.overview })
appendLine()
mediaDetail?.nextEpisode?.let {
appendLine("Next: Ep ${it.epNumber} - ${it.name}")
appendLine("Air Date: ${it.airDate}")
appendLine()
}
appendLine(extraInfo)
}
genre = detail?.let { dtl ->
dtl.select("> div:has(> div:contains(Genre:)) span").joinToString { it.text() }
}
author = detail?.let {
it.select("> div:has(> div:contains(Production:)) span").joinToString(", ") { it.text() }
author = detail?.let { dtl ->
dtl.select("> div:has(> div:contains(Production:)) span").joinToString { it.text() }
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,66 @@
package eu.kanade.tachiyomi.animeextension.en.fmovies

import android.util.Base64
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import eu.kanade.tachiyomi.util.parseAs
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
import java.net.URLDecoder
import javax.crypto.Cipher
import javax.crypto.spec.SecretKeySpec

class FmoviesUtils {
class FmoviesUtils(private val client: OkHttpClient, private val headers: Headers) {

// ===================== Media Detail ================================

private val tmdbURL = "https://api.themoviedb.org/3".toHttpUrl()

private val seez = "https://seez.su"

private val apiKey by lazy {
val jsUrl = client.newCall(GET(seez, headers)).execute().asJsoup()
.select("script[defer][src]")[1].attr("abs:src")

val jsBody = client.newCall(GET(jsUrl, headers)).execute().use { it.body.string() }
Regex("""f="(\w{20,})"""").find(jsBody)!!.groupValues[1]
}

private val apiHeaders = headers.newBuilder().apply {
add("Accept", "application/json, text/javascript, */*; q=0.01")
add("Host", "api.themoviedb.org")
add("Origin", seez)
add("Referer", "$seez/")
}.build()

fun getDetail(mediaTitle: String): TmdbDetailsResponse? =
runCatching {
val searchUrl = tmdbURL.newBuilder().apply {
addPathSegment("search")
addPathSegment("multi")
addQueryParameter("query", mediaTitle)
addQueryParameter("api_key", apiKey)
}.build().toString()
val searchResp = client.newCall(GET(searchUrl, headers = apiHeaders))
.execute()
.parseAs<TmdbResponse>()

val media = searchResp.results.first()

val detailUrl = tmdbURL.newBuilder().apply {
addPathSegment(media.mediaType)
addPathSegment(media.id.toString())
addQueryParameter("api_key", apiKey)
}.build().toString()
client.newCall(GET(detailUrl, headers = apiHeaders))
.execute()
.parseAs<TmdbDetailsResponse>()
}.getOrNull()

// ===================== Encryption ================================
fun vrfEncrypt(input: String): String {
val rc4Key = SecretKeySpec("FWsfu0KQd9vxYGNB".toByteArray(), "RC4")
val cipher = Cipher.getInstance("RC4")
Expand Down Expand Up @@ -53,3 +107,32 @@ class FmoviesUtils {
return vrf
}
}

@Serializable
data class TmdbResponse(
val results: List<TmdbResult>,
) {
@Serializable
data class TmdbResult(
val id: Int,
@SerialName("media_type")
val mediaType: String = "tv",
)
}

@Serializable
data class TmdbDetailsResponse(
val status: String,
val overview: String? = null,
@SerialName("next_episode_to_air")
val nextEpisode: NextEpisode? = null,
) {
@Serializable
data class NextEpisode(
val name: String? = "",
@SerialName("episode_number")
val epNumber: Int,
@SerialName("air_date")
val airDate: String,
)
}

0 comments on commit e54612a

Please sign in to comment.