diff --git a/src/fr/nekosama/build.gradle b/src/fr/nekosama/build.gradle deleted file mode 100644 index 6b230c85..00000000 --- a/src/fr/nekosama/build.gradle +++ /dev/null @@ -1,13 +0,0 @@ -ext { - extName = 'NekoSama' - extClass = '.NekoSama' - extVersionCode = 12 - isNsfw = true -} - -apply from: "$rootDir/common.gradle" - -dependencies { - implementation(project(':lib:streamtape-extractor')) - implementation(project(':lib:fusevideo-extractor')) -} diff --git a/src/fr/nekosama/res/mipmap-hdpi/ic_launcher.png b/src/fr/nekosama/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 236b668e..00000000 Binary files a/src/fr/nekosama/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/src/fr/nekosama/res/mipmap-mdpi/ic_launcher.png b/src/fr/nekosama/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 236b668e..00000000 Binary files a/src/fr/nekosama/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/src/fr/nekosama/res/mipmap-xhdpi/ic_launcher.png b/src/fr/nekosama/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 236b668e..00000000 Binary files a/src/fr/nekosama/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/src/fr/nekosama/res/mipmap-xxhdpi/ic_launcher.png b/src/fr/nekosama/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 236b668e..00000000 Binary files a/src/fr/nekosama/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/src/fr/nekosama/res/mipmap-xxxhdpi/ic_launcher.png b/src/fr/nekosama/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 236b668e..00000000 Binary files a/src/fr/nekosama/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/src/fr/nekosama/src/eu/kanade/tachiyomi/animeextension/fr/nekosama/NekoSama.kt b/src/fr/nekosama/src/eu/kanade/tachiyomi/animeextension/fr/nekosama/NekoSama.kt deleted file mode 100644 index 2bf76ce1..00000000 --- a/src/fr/nekosama/src/eu/kanade/tachiyomi/animeextension/fr/nekosama/NekoSama.kt +++ /dev/null @@ -1,316 +0,0 @@ -package eu.kanade.tachiyomi.animeextension.fr.nekosama - -import android.app.Application -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.Video -import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource -import eu.kanade.tachiyomi.lib.fusevideoextractor.FusevideoExtractor -import eu.kanade.tachiyomi.lib.streamtapeextractor.StreamTapeExtractor -import eu.kanade.tachiyomi.network.GET -import eu.kanade.tachiyomi.util.asJsoup -import eu.kanade.tachiyomi.util.parseAs -import kotlinx.serialization.Serializable -import okhttp3.HttpUrl -import okhttp3.Request -import okhttp3.Response -import org.jsoup.nodes.Document -import org.jsoup.nodes.Element -import uy.kohesive.injekt.Injekt -import uy.kohesive.injekt.api.get - -class NekoSama : ConfigurableAnimeSource, ParsedAnimeHttpSource() { - - override val name = "Neko-Sama" - - override val baseUrl by lazy { - val domain = preferences.getString(PREF_DOMAIN_KEY, PREF_DOMAIN_DEFAULT)!! - HttpUrl.Builder() - .scheme("https") - .host(domain) - .build() - .toString() - } - - override val lang = "fr" - - override val supportsLatest = true - - private val preferences by lazy { - Injekt.get().getSharedPreferences("source_$id", 0x0000) - } - - // ============================== Popular =============================== - override fun popularAnimeSelector() = "div.anime" - - override fun popularAnimeRequest(page: Int): Request { - return if (page > 1) { - GET("$baseUrl/anime/$page") - } else { - GET("$baseUrl/anime/") - } - } - - override fun popularAnimeFromElement(element: Element) = SAnime.create().apply { - with(element.selectFirst("div.info a")!!) { - setUrlWithoutDomain(attr("href")) - title = text() - } - - element.selectFirst("div.cover a div img:not(.placeholder)")?.run { - thumbnail_url = attr("data-src").ifBlank { attr("src") } - } - } - - override fun popularAnimeNextPageSelector() = "div.nekosama.pagination a.active ~ a" - - // =============================== Search =============================== - override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request { - val filterList = if (filters.isEmpty()) getFilterList() else filters - val typeFilter = filterList.find { it is TypeFilter } as TypeFilter - val typeSearch = when (typeFilter.toUriPart()) { - "anime" -> "vostfr" - "anime-vf" -> "vf" - else -> "vostfr" - } - - val url = when { - query.isNotBlank() -> "$baseUrl/animes-search-$typeSearch.json?$query" - typeFilter.state != 0 || query.isNotBlank() -> when (page) { - 1 -> "$baseUrl/${typeFilter.toUriPart()}" - else -> "$baseUrl/${typeFilter.toUriPart()}/page$page" - } - else -> when (page) { - 1 -> "$baseUrl/anime/" - else -> "$baseUrl/anime/page$page" - } - } - - return GET(url) - } - - override fun searchAnimeParse(response: Response): AnimesPage { - val pageUrl = response.request.url.toString() - val query = pageUrl.substringAfter("?").lowercase().replace("%20", " ") - - return when { - pageUrl.contains("animes-search") -> { - val jsonSearch = response.parseAs>() - val animes = jsonSearch - .filter { it.title.orEmpty().lowercase().contains(query) } - .mapNotNull { - val anime = SAnime.create().apply { - url = it.url?.substringAfterLast("/")?.substringBefore("-") ?: return@mapNotNull null - title = it.title ?: return@mapNotNull null - thumbnail_url = it.url_image ?: "$baseUrl/images/default_poster.png" - setUrlWithoutDomain(url) // call setUrlWithoutDomain on the SAnime instance - } - anime - } - AnimesPage(animes, false) - } - else -> { - val page = response.asJsoup() - val animes = page.select(popularAnimeSelector()).map(::popularAnimeFromElement) - AnimesPage(animes, true) - } - } - } - - override fun searchAnimeFromElement(element: Element): SAnime = throw UnsupportedOperationException() - - override fun searchAnimeNextPageSelector(): String = throw UnsupportedOperationException() - - override fun searchAnimeSelector(): String = throw UnsupportedOperationException() - - // =============================== Latest =============================== - override fun latestUpdatesRequest(page: Int) = GET(baseUrl, headers) - - override fun latestUpdatesSelector() = throw UnsupportedOperationException() - - override fun latestUpdatesFromElement(element: Element) = throw UnsupportedOperationException() - - override fun latestUpdatesParse(response: Response): AnimesPage { - val jsonLatest = response.parseAs> { it.substringAfter("var lastEpisodes = ").substringBefore(";\n") } - - val animeList = jsonLatest.mapNotNull { item -> - SAnime.create().apply { - val itemUrl = item.url ?: return@mapNotNull null - title = item.title ?: return@mapNotNull null - val animeId = itemUrl.substringAfterLast("/").substringBefore("-") - val titleSlug = title.replace("[^a-zA-Z0-9 -]".toRegex(), "").replace(" ", "-").lowercase() - url = "anime/info/$animeId-${titleSlug}_vostfr" - thumbnail_url = item.url_image ?: "/images/default_poster.png" - } - } - - return AnimesPage(animeList, false) - } - - override fun latestUpdatesNextPageSelector() = throw UnsupportedOperationException() - - // =========================== Anime Details ============================ - override fun animeDetailsParse(document: Document) = SAnime.create().apply { - title = document.selectFirst("div.row > div.col > h1")!!.ownText() - genre = document.select("div.col > div.list span").joinToString { it.text() } - - with(document.selectFirst("div.row > div#details")!!) { - thumbnail_url = selectFirst("div.cover img")?.absUrl("src") ?: "$baseUrl/images/default_poster.png" - description = buildString { - document.selectFirst("div.synopsis p")?.also { append(it.text(), "\n\n") } - getInfo("Score")?.also { append("Score moyen: *", it, "\n") } - getInfo("Status")?.also { - append("Status: ", it, "\n") - status = parseStatus(it) - } - getInfo("Format")?.also { append("Format: ", it, "\n") } - getInfo("Diffusion")?.also { append("Diffusion: ", it, "\n") } - } - } - } - - private fun Element.getInfo(item: String) = - selectFirst("div#anime-info-list div.item:contains($item)")?.ownText()?.trim() - - private fun parseStatus(statusString: String): Int { - return when (statusString) { - "En cours" -> SAnime.ONGOING - "Terminé" -> SAnime.COMPLETED - else -> SAnime.UNKNOWN - } - } - - // ============================== Episodes ============================== - override fun episodeListSelector() = "div.episodes div > a.button" - - override fun episodeFromElement(element: Element) = SEpisode.create().apply { - setUrlWithoutDomain(element.attr("href")) - val text = element.text() - val episodeNumber = text.substringAfterLast("- ").toFloatOrNull() ?: 0F - name = "Épisode ${episodeNumber.toInt()}" - episode_number = episodeNumber - } - - // ============================ Video Links ============================= - private val fusevideoExtractor by lazy { FusevideoExtractor(client, headers) } - private val streamTapeExtractor by lazy { StreamTapeExtractor(client) } - - override fun videoListParse(response: Response): List