diff --git a/src/en/nollyverse/build.gradle b/src/en/nollyverse/build.gradle deleted file mode 100644 index 97bdc44d..00000000 --- a/src/en/nollyverse/build.gradle +++ /dev/null @@ -1,7 +0,0 @@ -ext { - extName = 'NollyVerse' - extClass = '.NollyVerse' - extVersionCode = 3 -} - -apply from: "$rootDir/common.gradle" diff --git a/src/en/nollyverse/res/mipmap-hdpi/ic_launcher.png b/src/en/nollyverse/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 01b41f68..00000000 Binary files a/src/en/nollyverse/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/src/en/nollyverse/res/mipmap-mdpi/ic_launcher.png b/src/en/nollyverse/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 50583232..00000000 Binary files a/src/en/nollyverse/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/src/en/nollyverse/res/mipmap-xhdpi/ic_launcher.png b/src/en/nollyverse/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 62f929f7..00000000 Binary files a/src/en/nollyverse/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/src/en/nollyverse/res/mipmap-xxhdpi/ic_launcher.png b/src/en/nollyverse/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index f5e1c241..00000000 Binary files a/src/en/nollyverse/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/src/en/nollyverse/res/mipmap-xxxhdpi/ic_launcher.png b/src/en/nollyverse/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index beeb4e3c..00000000 Binary files a/src/en/nollyverse/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/src/en/nollyverse/src/eu/kanade/tachiyomi/animeextension/en/nollyverse/NollyVerse.kt b/src/en/nollyverse/src/eu/kanade/tachiyomi/animeextension/en/nollyverse/NollyVerse.kt deleted file mode 100644 index 52fae357..00000000 --- a/src/en/nollyverse/src/eu/kanade/tachiyomi/animeextension/en/nollyverse/NollyVerse.kt +++ /dev/null @@ -1,551 +0,0 @@ -package eu.kanade.tachiyomi.animeextension.en.nollyverse - -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.Video -import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource -import eu.kanade.tachiyomi.network.GET -import eu.kanade.tachiyomi.network.POST -import eu.kanade.tachiyomi.util.asJsoup -import okhttp3.FormBody -import okhttp3.HttpUrl.Companion.toHttpUrl -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 NollyVerse : ConfigurableAnimeSource, ParsedAnimeHttpSource() { - - override val name = "NollyVerse" - - override val baseUrl = "https://www.thenollyverse.com" - - override val lang = "en" - - override val supportsLatest = true - - private val preferences: SharedPreferences by lazy { - Injekt.get().getSharedPreferences("source_$id", 0x0000) - } - - // ============================== Popular =============================== - - override fun popularAnimeRequest(page: Int): Request = GET("$baseUrl/category/trending-movies/page/$page/") - - override fun popularAnimeParse(response: Response): AnimesPage { - val document = response.asJsoup() - - val animes = document.select(popularAnimeSelector()).map { element -> - popularAnimeFromElement(element) - } - - val hasNextPage = popularAnimeNextPageSelector()?.let { selector -> - if (document.select(selector).text() != ">") { - return AnimesPage(animes, false) - } - document.select(selector).first() - } != null - - return AnimesPage(animes, hasNextPage) - } - - override fun popularAnimeSelector(): String = "div.col-md-8 div.row div.col-md-6" - - override fun popularAnimeFromElement(element: Element): SAnime = SAnime.create().apply { - title = element.select("div.post-body h3 a").text() - thumbnail_url = element.select("a.post-img img").attr("data-src") - setUrlWithoutDomain(element.select("a.post-img").attr("href")) - } - - override fun popularAnimeNextPageSelector(): String = "div.loadmore ul.pagination.pagination-md li:nth-last-child(2)" - - // =============================== Latest =============================== - - override fun latestUpdatesRequest(page: Int): Request = GET("$baseUrl/category/new-series/page/$page/") - - override fun latestUpdatesParse(response: Response): AnimesPage { - val document = response.asJsoup() - - val animes = document.select(latestUpdatesSelector()).map { element -> - latestUpdatesFromElement(element) - } - - val hasNextPage = latestUpdatesNextPageSelector()?.let { selector -> - if (document.select(selector).text() != ">") { - return AnimesPage(animes, false) - } - document.select(selector).first() - } != null - - return AnimesPage(animes, hasNextPage) - } - - override fun latestUpdatesSelector(): String = "div.section div.container div.row div.post.post-row" - - override fun latestUpdatesFromElement(element: Element): SAnime = SAnime.create().apply { - title = element.select("div.post-body h3 a").text() - thumbnail_url = element.select("a.post-img img").attr("data-src").ifEmpty { - element.select("a.post-img img").attr("src") - } - setUrlWithoutDomain(element.select("a.post-img").attr("href")) - } - - override fun latestUpdatesNextPageSelector(): String = "div.loadmore ul.pagination.pagination-md li:nth-last-child(2)" - - // =============================== Search =============================== - - override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request { - return if (query.isNotBlank()) { - val body = FormBody.Builder() - .add("name", "$query") - .build() - POST("$baseUrl/livesearch.php", body = body) - } else { - var searchPath = "" - filters.filter { it.state != 0 }.forEach { filter -> - when (filter) { - is CategoryFilter -> searchPath = if (filter.toUriPart() == "/series/") filter.toUriPart() else "${filter.toUriPart()}page/$page" - is MovieGenreFilter -> searchPath = "/movies/genre/${filter.toUriPart()}/page/$page" - is SeriesGenreFilter -> searchPath = "/series/genre/${filter.toUriPart()}/page/$page" - else -> "" - } - } - - require(searchPath.isNotEmpty()) { "Search must not be empty" } - - GET(baseUrl + searchPath) - } - } - - override fun searchAnimeParse(response: Response): AnimesPage { - val document = response.asJsoup() - val path = response.request.url.encodedPath - - var hasNextPage: Boolean - var animes: List - - when { - path.startsWith("/livesearch") -> { - hasNextPage = false - animes = document.select(searchAnimeSelector()).map { element -> - searchAnimeFromElement(element) - } - } - - path.startsWith("/movies/genre/") -> { - animes = document.select(movieGenreSelector()).map { element -> - movieGenreFromElement(element) - } - hasNextPage = nextPageSelector()?.let { selector -> - if (document.select(selector).text() != ">") { - return AnimesPage(animes, false) - } - document.select(selector).first() - } != null - } - - path.startsWith("/series/genre/") || - path.startsWith("/category/popular-movies/") || - path.startsWith("/category/trending-movies/") -> { - animes = document.select(seriesGenreSelector()).map { element -> - seriesGenreFromElement(element) - } - hasNextPage = nextPageSelector()?.let { selector -> - if (document.select(selector).text() != ">") { - return AnimesPage(animes, false) - } - document.select(selector).first() - } != null - } - - path.startsWith("/category/korean-movies/") || path.startsWith("/category/korean-series/") -> { - animes = document.select(koreanSelector()).map { element -> - koreanFromElement(element) - } - hasNextPage = nextPageSelector()?.let { selector -> - if (document.select(selector).text() != ">") { - return AnimesPage(animes, false) - } - document.select(selector).first() - } != null - } - - path.startsWith("/category/latest-movies/") || - path.startsWith("/category/new-series/") || - path.startsWith("/category/latest-uploads/") -> { - animes = document.select(latestSelector()).map { element -> - latestFromElement(element) - } - hasNextPage = nextPageSelector()?.let { selector -> - if (document.select(selector).text() != ">") { - return AnimesPage(animes, false) - } - document.select(selector).first() - } != null - } - - path.startsWith("/series/") -> { - animes = document.select(seriesSelector()).map { element -> - seriesFromElement(element) - } - hasNextPage = false - } - - else -> { - animes = document.select(movieSelector()).map { element -> - movieFromElement(element) - } - hasNextPage = nextPageSelector()?.let { selector -> - if (document.select(selector).text() != ">") { - return AnimesPage(animes, false) - } - document.select(selector).first() - } != null - } - } - - return AnimesPage(animes, hasNextPage) - } - - private fun movieGenreSelector(): String = "div.container > div.row > div.col-md-4" - - private fun movieGenreFromElement(element: Element): SAnime = latestUpdatesFromElement(element) - - private fun seriesGenreSelector(): String = "div.row div.col-md-8 div.col-md-6" - - private fun seriesGenreFromElement(element: Element): SAnime = latestUpdatesFromElement(element) - - private fun koreanSelector(): String = "div.col-md-8 div.row div.col-md-6" - - private fun koreanFromElement(element: Element): SAnime = latestUpdatesFromElement(element) - - private fun latestSelector(): String = latestUpdatesSelector() - - private fun latestFromElement(element: Element): SAnime = latestUpdatesFromElement(element) - - private fun seriesSelector(): String = "div.section-row ul.list-style li" - - private fun seriesFromElement(element: Element): SAnime = SAnime.create().apply { - title = element.select("a").text() - thumbnail_url = toImgUrl(element.select("a").attr("href")) - setUrlWithoutDomain(element.select("a").attr("href")) - } - - private fun movieSelector(): String = "div.container div.row div.col-md-12 div.col-md-4" - - private fun movieFromElement(element: Element): SAnime = SAnime.create().apply { - title = element.select("h3 a").text() - thumbnail_url = element.select("a img").attr("src") - setUrlWithoutDomain(element.select("a.post-img").attr("href")) - } - - override fun searchAnimeSelector(): String = "a" - - override fun searchAnimeFromElement(element: Element): SAnime = SAnime.create().apply { - title = element.text() - thumbnail_url = toImgUrl(element.attr("href")) - setUrlWithoutDomain(element.attr("href")) - } - - private fun nextPageSelector(): String = "ul.pagination.pagination-md li:nth-last-child(2)" - - override fun searchAnimeNextPageSelector(): String = throw UnsupportedOperationException() - - // =========================== Anime Details ============================ - - override fun animeDetailsParse(document: Document): SAnime = SAnime.create().apply { - title = document.select("div.page-header div.container div.row div.text-center h1").text() - description = document.select("blockquote.blockquote small").text() - genre = document.select("div.col-md-8 ul.list-style li").firstOrNull { - it.text().startsWith("Genre: ") - }?.text()?.substringAfter("Genre: ")?.replace(",", ", ") - } - - // ============================== Episodes ============================== - - override fun episodeListRequest(anime: SAnime): Request { - return if (anime.url.startsWith("/movie/")) { - GET(baseUrl + anime.url + "/download/", headers) - } else { - GET(baseUrl + anime.url + "/seasons/", headers) - } - } - - override fun episodeListParse(response: Response): List { - val path = response.request.url.encodedPath - - val document = response.asJsoup() - val episodeList = mutableListOf() - - if (path.startsWith("/movie/")) { - episodeList.add( - SEpisode.create().apply { - name = "Movie" - episode_number = 1F - setUrlWithoutDomain(path) - }, - ) - } else { - var counter = 1 - for (season in document.select("table.table.table-striped tbody tr").reversed()) { - val seasonUrl = season.select("td a[href]").attr("href") - val seasonSoup = client.newCall( - GET(seasonUrl, headers), - ).execute().asJsoup() - - val episodeTable = seasonSoup.select("table.table.table-striped") - val seasonNumber = episodeTable.select("thead th").eachText().find { - t -> - """Season (\d+)""".toRegex().matches(t) - }?.split(" ")!![1] - - for (ep in episodeTable.select("tbody tr")) { - episodeList.add( - SEpisode.create().apply { - name = "Episode S${seasonNumber}E${ep.selectFirst("td")!!.text().split(" ")!![1]}" - episode_number = counter.toFloat() - setUrlWithoutDomain(seasonUrl + "#$counter") - }, - ) - counter++ - } - - // Stop abuse - Thread.sleep(500) - } - } - - return episodeList.reversed() - } - - override fun episodeFromElement(element: Element): SEpisode { - val seasonNum = element.ownerDocument()!!.select("div.Title span").text() - - return SEpisode.create().apply { - name = "Season $seasonNum" + "x" + element.select("td span.Num").text() + " : " + element.select("td.MvTbTtl > a").text() - episode_number = element.select("td > span.Num").text().toFloat() - setUrlWithoutDomain(element.select("td.MvTbPly > a.ClA").attr("abs:href")) - } - } - - override fun episodeListSelector() = throw UnsupportedOperationException() - - // ============================ Video Links ============================= - - override fun videoListRequest(episode: SEpisode): Request { - return if (episode.name == "Movie") { - GET(baseUrl + episode.url + "#movie", headers) - } else { - val episodeIndex = """Episode S(\d+)E(?\d+)""".toRegex().matchEntire( - episode.name, - )!!.groups["num"]!!.value - GET(baseUrl + episode.url.replaceAfterLast("#", "") + episodeIndex, headers) - } - } - - override fun videoListParse(response: Response): List