diff --git a/src/all/netfilm/AndroidManifest.xml b/src/all/netfilm/AndroidManifest.xml deleted file mode 100644 index 568741e54..000000000 --- a/src/all/netfilm/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/src/all/netfilm/build.gradle b/src/all/netfilm/build.gradle deleted file mode 100644 index aeb08c94b..000000000 --- a/src/all/netfilm/build.gradle +++ /dev/null @@ -1,13 +0,0 @@ -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply plugin: 'kotlinx-serialization' - -ext { - extName = 'NetFilm' - pkgNameSuffix = 'all.netfilm' - extClass = '.NetFilm' - extVersionCode = 2 - libVersion = '13' -} - -apply from: "$rootDir/common.gradle" diff --git a/src/all/netfilm/res/mipmap-hdpi/ic_launcher.png b/src/all/netfilm/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a067097ec..000000000 Binary files a/src/all/netfilm/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/src/all/netfilm/res/mipmap-mdpi/ic_launcher.png b/src/all/netfilm/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 4cd35acc3..000000000 Binary files a/src/all/netfilm/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/src/all/netfilm/res/mipmap-xhdpi/ic_launcher.png b/src/all/netfilm/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index d4c3bf663..000000000 Binary files a/src/all/netfilm/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/src/all/netfilm/res/mipmap-xxhdpi/ic_launcher.png b/src/all/netfilm/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index c9475ad6d..000000000 Binary files a/src/all/netfilm/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/src/all/netfilm/res/mipmap-xxxhdpi/ic_launcher.png b/src/all/netfilm/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 95c63c38f..000000000 Binary files a/src/all/netfilm/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/src/all/netfilm/res/web_hi_res_512.png b/src/all/netfilm/res/web_hi_res_512.png deleted file mode 100644 index 436a59fcf..000000000 Binary files a/src/all/netfilm/res/web_hi_res_512.png and /dev/null differ diff --git a/src/all/netfilm/src/eu/kanade/tachiyomi/animeextension/all/netfilm/DataModel.kt b/src/all/netfilm/src/eu/kanade/tachiyomi/animeextension/all/netfilm/DataModel.kt deleted file mode 100644 index 2ddf33ff2..000000000 --- a/src/all/netfilm/src/eu/kanade/tachiyomi/animeextension/all/netfilm/DataModel.kt +++ /dev/null @@ -1,85 +0,0 @@ -package eu.kanade.tachiyomi.animeextension.all.netfilm - -import kotlinx.serialization.Serializable - -@Serializable -data class CategoryResponse( - val data: List, -) { - @Serializable - data class CategoryData( - val coverVerticalUrl: String, - val domainType: Int, - val id: String, - val name: String, - val sort: String, - ) -} - -@Serializable -data class AnimeInfoResponse( - val data: InfoData, -) { - @Serializable - data class InfoData( - val coverVerticalUrl: String, - val episodeVo: List, - val id: String, - val introduction: String, - val name: String, - val category: Int, - val tagList: List, - ) { - @Serializable - data class EpisodeInfo( - val id: Int, - val seriesNo: Float, - ) - - @Serializable - data class IdInfo( - val name: String, - ) - } -} - -@Serializable -data class SearchResponse( - val data: InfoData, -) { - @Serializable - data class InfoData( - val results: List, - ) -} - -@Serializable -data class EpisodeResponse( - val data: EpisodeData, -) { - @Serializable - data class EpisodeData( - val qualities: List, - val subtitles: List, - ) { - @Serializable - data class Quality( - val quality: Int, - val url: String, - ) - - @Serializable - data class Subtitle( - val language: String, - val url: String, - ) - } -} - -@Serializable -data class LinkData( - val category: String, - val id: String, - val url: String, - val episodeId: String? = null, -) diff --git a/src/all/netfilm/src/eu/kanade/tachiyomi/animeextension/all/netfilm/NetFilm.kt b/src/all/netfilm/src/eu/kanade/tachiyomi/animeextension/all/netfilm/NetFilm.kt deleted file mode 100644 index 31d2dd0e9..000000000 --- a/src/all/netfilm/src/eu/kanade/tachiyomi/animeextension/all/netfilm/NetFilm.kt +++ /dev/null @@ -1,279 +0,0 @@ -package eu.kanade.tachiyomi.animeextension.all.netfilm - -import android.app.Application -import android.content.SharedPreferences -import androidx.preference.ListPreference -import androidx.preference.PreferenceScreen -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.Track -import eu.kanade.tachiyomi.animesource.model.Video -import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource -import eu.kanade.tachiyomi.network.GET -import kotlinx.serialization.decodeFromString -import kotlinx.serialization.encodeToString -import kotlinx.serialization.json.Json -import okhttp3.HttpUrl.Companion.toHttpUrl -import okhttp3.OkHttpClient -import okhttp3.Request -import okhttp3.Response -import rx.Observable -import uy.kohesive.injekt.Injekt -import uy.kohesive.injekt.api.get -import uy.kohesive.injekt.injectLazy -import kotlin.math.ceil -import kotlin.math.floor - -class NetFilm : ConfigurableAnimeSource, AnimeHttpSource() { - - override val name = "NetFilm" - - override val baseUrl = "https://net-film.vercel.app/api" - - private val hostName = baseUrl.toHttpUrl().host - - override val lang = "all" - - private var sort = "" - - override val supportsLatest = true - - private val json: Json by injectLazy() - - private val preferences: SharedPreferences by lazy { - Injekt.get().getSharedPreferences("source_$id", 0x0000) - } - - override val client: OkHttpClient = network.cloudflareClient - - private val newHeaders = headers.newBuilder() - .add("Accept", "application/json, text/plain, */*") - .add("appid", "eyJhbGciOiJIUzI1NiJ9") - .add("Host", hostName) - .add("Sec-Fetch-Dest", "empty") - .add("Sec-Fetch-Mode", "cors") - .add("Sec-Fetch-Site", "same-origin") - - // ============================== Popular =============================== - - override fun popularAnimeRequest(page: Int): Request { - if (page == 1) sort = "" - val popHeaders = newHeaders.add("Referer", "https://$hostName/explore").build() - return GET("$baseUrl/category?area=&category=1&order=count¶ms=COMIC&size=30&sort=$sort&subtitles=&year=", headers = popHeaders) - } - - override fun popularAnimeParse(response: Response): AnimesPage { - val parsed = json.decodeFromString(response.body.string()) - if (parsed.data.isEmpty()) { - return AnimesPage(emptyList(), false) - } - - val animeList = parsed.data.map { ani -> - SAnime.create().apply { - title = ani.name - thumbnail_url = ani.coverVerticalUrl - setUrlWithoutDomain( - LinkData( - ani.domainType.toString(), - ani.id, - response.request.url.toString(), - ).toJsonString(), - ) - } - } - - sort = parsed.data.last().sort - - return AnimesPage(animeList, animeList.size == 30) - } - - // =============================== Latest =============================== - - override fun latestUpdatesRequest(page: Int): Request { - if (page == 1) sort = "" - val latestHeaders = newHeaders.add("Referer", "https://$hostName/explore").build() - return GET("$baseUrl/category?area=&category=1&order=up¶ms=COMIC&size=30&sort=$sort&subtitles=&year=", headers = latestHeaders) - } - - override fun latestUpdatesParse(response: Response): AnimesPage = popularAnimeParse(response) - - // =============================== Search =============================== - - override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request { - if (page == 1) sort = "" - return if (query.isNotEmpty()) { - val searchHeaders = newHeaders.add("Referer", "$baseUrl/search?keyword=$query&size=30").build() - GET("$baseUrl/search?keyword=$query&size=30", headers = searchHeaders) - } else { - val pageList = filters.find { it is SubPageFilter } as SubPageFilter - val pageHeaders = newHeaders.add("Referer", "https://$hostName/explore").build() - GET("$baseUrl${pageList.toUriPart()}&sort=$sort&subtitles=&year=", headers = pageHeaders) - } - } - - override fun searchAnimeParse(response: Response): AnimesPage { - val url = response.request.url.encodedPath - return if (url.startsWith("/api/category")) { - popularAnimeParse(response) - } else { - val parsed = json.decodeFromString(response.body.string()) - if (parsed.data.results.isEmpty()) { - return AnimesPage(emptyList(), false) - } - - val animeList = parsed.data.results.map { ani -> - SAnime.create().apply { - title = ani.name - thumbnail_url = ani.coverVerticalUrl - setUrlWithoutDomain( - LinkData( - ani.domainType.toString(), - ani.id, - response.request.url.toString(), - ).toJsonString(), - ) - } - } - - sort = parsed.data.results.last().sort - - AnimesPage(animeList, animeList.size == 30) - } - } - - // ============================== FILTERS =============================== - - override fun getFilterList(): AnimeFilterList = AnimeFilterList( - AnimeFilter.Header("Text search ignores filters"), - SubPageFilter(), - ) - - private class SubPageFilter : UriPartFilter( - "Sub Page", - arrayOf( - Pair("Popular Movie", "/category?area=&category=1&order=count¶ms=MOVIE,TVSPECIAL&size=30"), - Pair("Recent Movie", "/category?area=&category=1&order=up¶ms=MOVIE,TVSPECIAL&size=30"), - Pair("Popular TV Series", "/category?area=&category=1&order=count¶ms=TV,SETI,MINISERIES,VARIETY,TALK,DOCUMENTARY&size=30"), - Pair("Recent TV Series", "/category?area=&category=1&order=up¶ms=TV,SETI,MINISERIES,VARIETY,TALK,DOCUMENTARY&size=30"), - Pair("Popular Anime", "/category?area=&category=1&order=count¶ms=COMIC&size=30"), - Pair("Recent Anime", "/category?area=&category=1&order=up¶ms=COMIC&size=30"), - ), - ) - - private open class UriPartFilter(displayName: String, val vals: Array>) : - AnimeFilter.Select(displayName, vals.map { it.first }.toTypedArray()) { - fun toUriPart() = vals[state].second - } - - // =========================== Anime Details ============================ - - override fun fetchAnimeDetails(anime: SAnime): Observable { - val parsed = json.decodeFromString(anime.url) - val detailsHeader = newHeaders.add("Referer", parsed.url).build() - - val resp = client.newCall( - GET("$baseUrl/detail?category=${parsed.category}&id=${parsed.id}", headers = detailsHeader), - ).execute() - val data = json.decodeFromString(resp.body.string()).data - return Observable.just( - anime.apply { - title = data.name - thumbnail_url = data.coverVerticalUrl - description = data.introduction - genre = data.tagList.joinToString(", ") { it.name } - }, - ) - } - - override fun animeDetailsParse(response: Response): SAnime = throw Exception("Not used") - - // ============================== Episodes ============================== - - override fun fetchEpisodeList(anime: SAnime): Observable> { - val parsed = json.decodeFromString(anime.url) - - val episodeHeader = newHeaders.add("Referer", parsed.url).build() - val resp = client.newCall( - GET("$baseUrl/detail?category=${parsed.category}&id=${parsed.id}", headers = episodeHeader), - ).execute() - val data = json.decodeFromString(resp.body.string()).data - val episodeList = data.episodeVo.map { ep -> - val formattedEpNum = if (floor(ep.seriesNo) == ceil(ep.seriesNo)) { - ep.seriesNo.toInt() - } else { - ep.seriesNo - } - SEpisode.create().apply { - episode_number = ep.seriesNo - setUrlWithoutDomain( - LinkData( - data.category.toString(), - data.id, - "$baseUrl/detail?category=${parsed.category}&id=${parsed.id}", - ep.id.toString(), - ).toJsonString(), - ) - name = "Episode $formattedEpNum" - } - } - return Observable.just(episodeList.reversed()) - } - - override fun episodeListParse(response: Response): List = throw Exception("Not used") - - // ============================ Video Links ============================= - - override fun fetchVideoList(episode: SEpisode): Observable> { - val parsed = json.decodeFromString(episode.url) - val videoHeaders = newHeaders.add("Referer", parsed.url).build() - val resp = client.newCall( - GET("$baseUrl/episode?category=${parsed.category}&id=${parsed.id}&episode=${parsed.episodeId!!}", headers = videoHeaders), - ).execute() - val episodeParsed = json.decodeFromString(resp.body.string()) - val subtitleList = episodeParsed.data.subtitles.map { sub -> - Track(sub.url, sub.language) - } - val videoList = episodeParsed.data.qualities.map { quality -> - Video(quality.url, "${quality.quality}p", quality.url, subtitleTracks = subtitleList) - } - return Observable.just(videoList.sort()) - } - - // ============================= Utilities ============================== - - private fun LinkData.toJsonString(): String { - return json.encodeToString(this) - } - - override fun List