src/ar+de+es dead sources (#814)

* src/es pelisflix/seriesflix

* src/de streamcloud

* src/de movie2k

* src/de cineclix

* src/ar xsanime/xsmovie

* src/ar tuktuk

* src/ar akwam

---------

Co-authored-by: Your Name <you@example.com>
This commit is contained in:
krysanify 2025-03-25 02:30:35 +08:00 committed by GitHub
parent 0fb8c32aa6
commit 3a58bf47ff
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
61 changed files with 0 additions and 2551 deletions

View file

@ -1,7 +0,0 @@
ext {
extName = 'Akwam'
extClass = '.Akwam'
extVersionCode = 9
}
apply from: "$rootDir/common.gradle"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View file

@ -1,355 +0,0 @@
package eu.kanade.tachiyomi.animeextension.ar.akwam
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.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.util.asJsoup
import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
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 Akwam : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override val name = "أكوام"
override val baseUrl = "https://akw-cdn1.link"
override val lang = "ar"
override val supportsLatest = false
private val preferences: SharedPreferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}
// Popular
override fun popularAnimeSelector(): String = "div.entry-box-1 div.entry-image a.box"
override fun popularAnimeRequest(page: Int): Request = GET("$baseUrl/movies?page=$page")
override fun popularAnimeFromElement(element: Element): SAnime {
val anime = SAnime.create()
anime.thumbnail_url = element.select("picture img").attr("data-src")
anime.setUrlWithoutDomain(element.attr("href"))
anime.title = element.select("picture img").attr("alt")
return anime
}
override fun popularAnimeNextPageSelector(): String = "ul.pagination li.page-item a[rel=next]"
// episodes
override fun episodeListSelector() = "div.bg-primary2 h2 a"
override fun episodeListParse(response: Response): List<SEpisode> {
val episodes = mutableListOf<SEpisode>()
fun addEpisodes(document: Document) {
if (document.select(episodeListSelector()).isNullOrEmpty()) {
// add movie
document.select("input#reportInputUrl").map { episodes.add(episodeFromElement(it)) }
} else {
document.select(episodeListSelector()).map { episodes.add(episodesFromElement(it)) }
}
}
addEpisodes(response.asJsoup())
return episodes
}
override fun episodeFromElement(element: Element): SEpisode {
val episode = SEpisode.create()
episode.setUrlWithoutDomain(element.attr("value"))
episode.name = "مشاهدة"
return episode
}
private fun episodesFromElement(element: Element): SEpisode {
val episode = SEpisode.create()
val epNum = getNumberFromEpsString(element.text())
episode.setUrlWithoutDomain(element.attr("href"))
episode.name = element.text()
episode.episode_number = when {
epNum.isNotEmpty() -> epNum.toFloatOrNull() ?: 1F
else -> 1F
}
return episode
}
private fun getNumberFromEpsString(epsStr: String): String {
return epsStr.filter { it.isDigit() }
}
// Video links
override fun videoListParse(response: Response): List<Video> {
val document = response.asJsoup()
val iframe = "https://akw-cdn1.link/watch" + document.select("a.link-show").attr("href").substringAfter("watch") + "/" + document.ownerDocument()!!.select("input#page_id").attr("value")
val referer = response.request.url.toString()
val refererHeaders = Headers.headersOf("referer", referer)
val iframeResponse = client.newCall(GET(iframe, refererHeaders))
.execute().asJsoup()
return iframeResponse.select(videoListSelector()).map { videoFromElement(it) }
}
override fun videoListSelector() = "source"
override fun videoFromElement(element: Element): Video {
return Video(element.attr("src").replace("https", "http"), element.attr("size") + "p", element.attr("src").replace("https", "http"))
}
override fun List<Video>.sort(): List<Video> {
val quality = preferences.getString("preferred_quality", null)
if (quality != null) {
val newList = mutableListOf<Video>()
var preferred = 0
for (video in this) {
if (video.quality.contains(quality)) {
newList.add(preferred, video)
preferred++
} else {
newList.add(video)
}
}
return newList
}
return this
}
override fun videoUrlParse(document: Document) = throw UnsupportedOperationException()
// Search
override fun searchAnimeFromElement(element: Element): SAnime {
val anime = SAnime.create()
anime.thumbnail_url = element.select("picture img").attr("data-src")
anime.setUrlWithoutDomain(element.attr("href"))
anime.title = element.select("picture img").attr("alt")
return anime
}
override fun searchAnimeNextPageSelector(): String = "ul.pagination li.page-item a[rel=next]"
override fun searchAnimeSelector(): String = "div.widget div.widget-body div.col-lg-auto div.entry-box div.entry-image a.box"
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
val url = if (query.isNotBlank()) {
val url = "$baseUrl/search?q=$query&page=$page".toHttpUrlOrNull()!!.newBuilder()
filters.forEach { filter ->
when (filter) {
is SectionFilter -> url.addQueryParameter("section", filter.toUriPart())
is RatingFilter -> url.addQueryParameter("rating", filter.toUriPart())
is FormatFilter -> url.addQueryParameter("formats", filter.toUriPart())
is QualityFilter -> url.addQueryParameter("quality", filter.toUriPart())
else -> {}
}
}
url.toString()
} else {
val url = "$baseUrl/search?page=$page".toHttpUrlOrNull()!!.newBuilder()
var type = "movies"
filters.forEach { filter ->
when (filter) {
is TypeFilter -> type = filter.toUriPart().toString()
is SectionSFilter -> url.addQueryParameter("section", filter.toUriPart())
is CategorySFilter -> url.addQueryParameter("category", filter.toUriPart())
is RatingSFilter -> url.addQueryParameter("rating", filter.toUriPart())
// is LanguageSFilter -> url.addQueryParameter("quality", filter.toUriPart())
else -> {}
}
}
url.toString().replace("search", type)
}
return GET(url, headers)
}
// Anime Details
override fun animeDetailsParse(document: Document): SAnime {
val anime = SAnime.create()
// anime.thumbnail_url = document.select("div.container div div a picture > img.img-fluid").attr("data-src")
anime.title = document.select("picture > img.img-fluid").attr("alt")
anime.genre = document.select("div.font-size-16.d-flex.align-items-center.mt-3 a.badge, span.badge-info, span:contains(جودة الفيلم), span:contains(انتاج)").joinToString(", ") { it.text().replace("جودة الفيلم : ", "") }
anime.author = document.select("span:contains(انتاج)").text().replace("انتاج : ", "")
anime.description = document.select("div.widget:contains(قصة )").text()
anime.status = SAnime.COMPLETED
return anime
}
// Latest
override fun latestUpdatesNextPageSelector(): String = throw UnsupportedOperationException()
override fun latestUpdatesFromElement(element: Element): SAnime = throw UnsupportedOperationException()
override fun latestUpdatesRequest(page: Int): Request = throw UnsupportedOperationException()
override fun latestUpdatesSelector(): String = throw UnsupportedOperationException()
// Filters
override fun getFilterList() = AnimeFilterList(
AnimeFilter.Header("فلترات البحث"),
AnimeFilter.Separator(),
SectionFilter(getSectionFilter()),
RatingFilter(getRatingFilter()),
FormatFilter(getFormatFilter()),
QualityFilter(getQualityFilter()),
AnimeFilter.Header("تصفح الموقع (تعمل فقط لو كان البحث فارغ)"),
AnimeFilter.Separator(),
TypeFilter(getTypeFilter()),
SectionSFilter(getSectionSFilter()),
CategorySFilter(getCategorySFilter()),
RatingSFilter(getRatingSFilter()),
)
private class SectionFilter(vals: Array<Pair<String?, String>>) : UriPartFilter("الأقسام", vals)
private class RatingFilter(vals: Array<Pair<String?, String>>) : UriPartFilter("التقيم", vals)
private class FormatFilter(vals: Array<Pair<String?, String>>) : UriPartFilter("الجودة", vals)
private class QualityFilter(vals: Array<Pair<String?, String>>) : UriPartFilter("الدقة", vals)
private class TypeFilter(vals: Array<Pair<String?, String>>) : UriPartFilter("النوع", vals)
private class SectionSFilter(vals: Array<Pair<String?, String>>) : UriPartFilter("القسم", vals)
private class CategorySFilter(vals: Array<Pair<String?, String>>) : UriPartFilter("التصنيف", vals)
private class RatingSFilter(vals: Array<Pair<String?, String>>) : UriPartFilter("التقييم", vals)
private fun getTypeFilter(): Array<Pair<String?, String>> = arrayOf(
Pair("movies", "افلام"),
Pair("series", "مسلسلات"),
)
private fun getSectionFilter(): Array<Pair<String?, String>> = arrayOf(
Pair("0", "الكل"),
Pair("movie", "افلام"),
Pair("series", "مسلسلات"),
Pair("show", "تلفزيون"),
)
private fun getRatingFilter(): Array<Pair<String?, String>> = arrayOf(
Pair("0", "التقييم"),
Pair("1", "1+"),
Pair("2", "2+"),
Pair("3", "3+"),
Pair("4", "4+"),
Pair("5", "5+"),
Pair("6", "6+"),
Pair("7", "7+"),
Pair("8", "8+"),
Pair("9", "9+"),
)
private fun getFormatFilter(): Array<Pair<String?, String>> = arrayOf(
Pair("0", "الكل"),
Pair("BluRay", "BluRay"),
Pair("WebRip", "WebRip"),
Pair("BRRIP", "BRRIP"),
Pair("DVDrip", "DVDrip"),
Pair("DVDSCR", "DVDSCR"),
Pair("HD", "HD"),
Pair("HDTS", "HDTS"),
Pair("HDTV", "HDTV"),
Pair("CAM", "CAM"),
Pair("WEB-DL", "WEB-DL"),
Pair("HDTC", "HDTC"),
Pair("BDRIP", "BDRIP"),
Pair("HDRIP", "HDRIP"),
Pair("HC+HDRIP", "HC HDRIP"),
)
private fun getQualityFilter(): Array<Pair<String?, String>> = arrayOf(
Pair("0", "الدقة"),
Pair("240p", "240p"),
Pair("360p", "360p"),
Pair("480p", "480p"),
Pair("720p", "720p"),
Pair("1080p", "1080p"),
Pair("3D", "3D"),
Pair("4K", "4K"),
)
private fun getSectionSFilter(): Array<Pair<String?, String>> = arrayOf(
Pair("0", "القسم"),
Pair("29", "عربي"),
Pair("30", "اجنبي"),
Pair("31", "هندي"),
Pair("32", "تركي"),
Pair("33", "اسيوي"),
)
private fun getCategorySFilter(): Array<Pair<String?, String>> = arrayOf(
Pair("0", "التصنيف"),
Pair("87", "رمضان"),
Pair("30", "انمي"),
Pair("18", "اكشن"),
Pair("71", "مدبلج"),
Pair("72", "NETFLIX"),
Pair("20", "كوميدي"),
Pair("35", "اثارة"),
Pair("34", "غموض"),
Pair("33", "عائلي"),
Pair("88", "اطفال"),
Pair("25", "حربي"),
Pair("32", "رياضي"),
Pair("89", "قصير"),
Pair("43", "فانتازيا"),
Pair("24", "خيال علمي"),
Pair("31", "موسيقى"),
Pair("29", "سيرة ذاتية"),
Pair("28", "وثائقي"),
Pair("27", "رومانسي"),
Pair("26", "تاريخي"),
Pair("23", "دراما"),
Pair("22", "رعب"),
Pair("21", "جريمة"),
Pair("19", "مغامرة"),
Pair("91", "غربي"),
)
private fun getRatingSFilter(): Array<Pair<String?, String>> = arrayOf(
Pair("0", "التقييم"),
Pair("1", "1+"),
Pair("2", "2+"),
Pair("3", "3+"),
Pair("4", "4+"),
Pair("5", "5+"),
Pair("6", "6+"),
Pair("7", "7+"),
Pair("8", "8+"),
Pair("9", "9+"),
)
open class UriPartFilter(displayName: String, private val vals: Array<Pair<String?, String>>) :
AnimeFilter.Select<String>(displayName, vals.map { it.second }.toTypedArray()) {
fun toUriPart() = vals[state].first
}
// preferred quality settings
override fun setupPreferenceScreen(screen: PreferenceScreen) {
val videoQualityPref = ListPreference(screen.context).apply {
key = "preferred_quality"
title = "Preferred quality"
entries = arrayOf("1080p", "720p", "480p", "360p", "240p")
entryValues = arrayOf("1080", "720", "480", "360", "240")
setDefaultValue("1080")
summary = "%s"
setOnPreferenceChangeListener { _, newValue ->
val selected = newValue as String
val index = findIndexOfValue(selected)
val entry = entryValues[index] as String
preferences.edit().putString(key, entry).commit()
}
}
screen.addPreference(videoQualityPref)
}
}

View file

@ -1,17 +0,0 @@
ext {
extName = 'Tuktuk Cinema'
extClass = '.Tuktukcinema'
extVersionCode = 24
}
apply from: "$rootDir/common.gradle"
dependencies {
implementation(project(':lib:uqload-extractor'))
implementation(project(':lib:okru-extractor'))
implementation(project(':lib:dood-extractor'))
implementation(project(':lib:streamtape-extractor'))
implementation(project(':lib:vidbom-extractor'))
implementation(project(':lib:playlist-utils'))
implementation(libs.jsunpacker)
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View file

@ -1,309 +0,0 @@
package eu.kanade.tachiyomi.animeextension.ar.tuktukcinema
import android.app.Application
import android.content.SharedPreferences
import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen
import dev.datlag.jsunpacker.JsUnpacker
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.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.doodextractor.DoodExtractor
import eu.kanade.tachiyomi.lib.okruextractor.OkruExtractor
import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils
import eu.kanade.tachiyomi.lib.streamtapeextractor.StreamTapeExtractor
import eu.kanade.tachiyomi.lib.uqloadextractor.UqloadExtractor
import eu.kanade.tachiyomi.lib.vidbomextractor.VidBomExtractor
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
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 Tuktukcinema : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override val name = "توك توك سينما"
// TODO: Check frequency of url changes to potentially
// add back overridable baseurl preference
override val baseUrl = "https://w.tuktokcinema.com"
override val lang = "ar"
override val supportsLatest = true
private val preferences: SharedPreferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}
// ============================ popular ===============================
override fun popularAnimeSelector(): String = "div.Block--Item, div.Small--Box"
override fun popularAnimeRequest(page: Int): Request = GET(baseUrl)
override fun popularAnimeFromElement(element: Element): SAnime {
val anime = SAnime.create()
anime.title = titleEdit(element.select("a").attr("title"), true).trim()
anime.thumbnail_url = element.select("img").attr("data-src")
anime.setUrlWithoutDomain(element.select("a").attr("href") + "watch/")
return anime
}
private fun titleEdit(title: String, details: Boolean = false): String {
return if (Regex("(?:فيلم|عرض)\\s(.*\\s[0-9]+)\\s(.+?)\\s").containsMatchIn(title)) {
val titleGroup = Regex("(?:فيلم|عرض)\\s(.*\\s[0-9]+)\\s(.+?)\\s").find(title)
val movieName = titleGroup!!.groupValues[1]
val type = titleGroup.groupValues[2]
movieName + if (details) " ($type)" else ""
} else if (Regex("(?:مسلسل|برنامج|انمي)\\s(.+)\\sالحلقة\\s(\\d+)").containsMatchIn(title)) {
val titleGroup = Regex("(?:مسلسل|برنامج|انمي)\\s(.+)\\sالحلقة\\s(\\d+)").find(title)
val seriesName = titleGroup!!.groupValues[1]
val epNum = titleGroup.groupValues[2]
if (details) {
"$seriesName (ep:$epNum)"
} else if (seriesName.contains("الموسم")) {
seriesName.split("الموسم")[0].trim()
} else {
seriesName
}
} else {
title
}
}
override fun popularAnimeNextPageSelector(): String = "div.pagination ul.page-numbers li a.next"
// ============================ episodes ===============================
private fun seasonsNextPageSelector() = "section.allseasonss div.Block--Item"
override fun episodeListParse(response: Response): List<SEpisode> {
val episodes = mutableListOf<SEpisode>()
fun addEpisodeNew(url: String, title: String) {
val episode = SEpisode.create()
episode.setUrlWithoutDomain(url)
episode.name = title
episodes.add(episode)
}
fun addEpisodes(response: Response) {
val document = response.asJsoup()
val url = response.request.url.toString()
if (document.select(seasonsNextPageSelector()).isNullOrEmpty()) {
addEpisodeNew("$url/watch/", "مشاهدة")
} else {
document.select(seasonsNextPageSelector()).reversed().forEach { season ->
val seasonNum = season.select("h3").text()
(
if (seasonNum == document.selectFirst("div#mpbreadcrumbs a span:contains(الموسم)")!!.text()) {
document
} else {
client.newCall(GET(season.selectFirst("a")!!.attr("href"))).execute().asJsoup()
}
)
.select("section.allepcont a").forEach { episode ->
addEpisodeNew(
episode.attr("href") + "watch/",
seasonNum + " : الحلقة " + episode.select("div.epnum").text().filter { it.isDigit() },
)
}
}
}
}
addEpisodes(response)
return episodes
}
override fun episodeListSelector() = "link[rel=canonical]"
override fun episodeFromElement(element: Element): SEpisode = throw UnsupportedOperationException()
// ============================ video links ============================
override fun videoListRequest(episode: SEpisode): Request {
val refererHeaders = headers.newBuilder().apply {
add("Referer", "$baseUrl/")
}.build()
return GET("$baseUrl/${episode.url}", headers = refererHeaders)
}
override fun videoListSelector() = "div.watch--servers--list ul li.server--item"
override fun videoListParse(response: Response): List<Video> {
val document = response.asJsoup()
return document.select(videoListSelector())
.parallelCatchingFlatMapBlocking(::extractVideos)
}
private fun extractVideos(element: Element): List<Video> {
val url = element.attr("data-link")
val txt = element.text()
return when {
"Main" in txt -> {
videosFromMain(url)
}
url.contains("ok") -> {
OkruExtractor(client).videosFromUrl(url)
}
"Vidbom" in txt || "Vidshare" in txt || "Govid" in txt -> {
VidBomExtractor(client).videosFromUrl(url)
}
"Doodstream" in txt -> {
DoodExtractor(client).videoFromUrl(url, "Dood mirror")?.let(::listOf)
}
url.contains("uqload") -> {
UqloadExtractor(client).videosFromUrl(url, "mirror")
}
url.contains("tape") -> {
StreamTapeExtractor(client).videoFromUrl(url)?.let(::listOf)
}
"Upstream" in txt || "Streamruby" in txt || "Streamwish" in txt -> {
videosFromOthers(url, txt)
}
else -> null
} ?: emptyList()
}
override fun List<Video>.sort(): List<Video> {
val quality = preferences.getString("preferred_quality", null)!!
return sortedWith(
compareBy { it.quality.contains(quality) },
).reversed()
}
override fun videoUrlParse(document: Document) = throw UnsupportedOperationException()
override fun videoFromElement(element: Element) = throw UnsupportedOperationException()
private fun videosFromMain(url: String): List<Video> {
val jsE = client.newCall(GET(url)).execute().asJsoup().selectFirst("script:containsData(player)")!!.data()
val fileLinks = JsUnpacker.unpackAndCombine(jsE)!!.substringAfter("file").substringBefore("\",")
return Regex("\\[(.*?)\\](.*?mp4)").findAll(fileLinks).map {
Video(it.groupValues[2], "Main: " + it.groupValues[1], it.groupValues[2])
}.toList()
}
private fun videosFromOthers(url: String, prefix: String): List<Video> {
val jsE = client.newCall(GET(url)).execute().asJsoup().selectFirst("script:containsData(source)")!!.data()
val masterUrl = JsUnpacker.unpackAndCombine(jsE)!!.substringAfter("file").substringAfter("\"").substringBefore("\"")
return PlaylistUtils(client).extractFromHls(masterUrl, url, videoNameGen = { "$prefix - $it" })
}
// ============================ search ============================
override fun searchAnimeSelector(): String = "div.Block--Item"
override fun searchAnimeNextPageSelector(): String = "div.pagination ul.page-numbers li a.next"
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
val url = if (query.isNotBlank()) {
"$baseUrl/?s=$query&page=$page"
} else {
val url = baseUrl
(if (filters.isEmpty()) getFilterList() else filters).forEach { filter ->
when (filter) {
is CategoryList -> {
if (filter.state > 0) {
val catQ = getCategoryList()[filter.state].query
val catUrl = "$baseUrl/$catQ/?page=$page/"
return GET(catUrl, headers)
}
}
else -> {}
}
}
return GET(url, headers)
}
return GET(url, headers)
}
override fun searchAnimeFromElement(element: Element): SAnime {
val anime = SAnime.create()
anime.title = titleEdit(element.select("h3").text(), true).trim()
anime.thumbnail_url = element.select("img").attr(if (element.ownerDocument()!!.location().contains("?s="))"src" else "data-src")
anime.setUrlWithoutDomain(element.select("a").attr("href") + "watch/")
return anime
}
// ============================ details ============================
override fun animeDetailsParse(document: Document): SAnime {
val anime = SAnime.create()
anime.genre = document.select("div.catssection li a").joinToString(", ") { it.text() }
anime.title = titleEdit(document.select("h1.post-title").text()).trim()
anime.author = document.select("ul.RightTaxContent li:contains(دولة) a").text()
anime.description = document.select("div.story").text().trim()
anime.status = SAnime.COMPLETED
anime.thumbnail_url = document.select("div.left div.image img").attr("src")
return anime
}
// ============================ latest ============================
override fun latestUpdatesSelector(): String = "div.Block--Item"
override fun latestUpdatesNextPageSelector(): String = "div.pagination ul.page-numbers li a.next"
override fun latestUpdatesRequest(page: Int): Request = GET("$baseUrl/recent/page/$page/")
override fun latestUpdatesFromElement(element: Element): SAnime {
val anime = SAnime.create()
anime.title = titleEdit(element.select("a").attr("title"), true).trim()
anime.thumbnail_url = element.select("img").attr("data-src")
anime.setUrlWithoutDomain(element.select("a").attr("href") + "watch/")
return anime
}
// ============================ filters ============================
override fun getFilterList() = AnimeFilterList(
CategoryList(categoriesName),
)
private class CategoryList(categories: Array<String>) : AnimeFilter.Select<String>("الأقسام", categories)
private data class CatUnit(val name: String, val query: String)
private val categoriesName = getCategoryList().map {
it.name
}.toTypedArray()
private fun getCategoryList() = listOf(
CatUnit("اختر", ""),
CatUnit("كل الافلام", "category/movies-33/"),
CatUnit("افلام اجنبى", "category/movies-33/افلام-اجنبي/"),
CatUnit("افلام انمى", "category/anime-6/افلام-انمي/"),
CatUnit("افلام تركيه", "category/movies-33/افلام-تركي/"),
CatUnit("افلام اسيويه", "category/movies-33/افلام-اسيوي/"),
CatUnit("افلام هنديه", "category/movies-33/افلام-هندى/"),
CatUnit("كل المسسلسلات", "category/series-9/"),
CatUnit("مسلسلات اجنبى", "category/series-9/مسلسلات-اجنبي/"),
CatUnit("مسلسلات انمى", "category/anime-6/انمي-مترجم/"),
CatUnit("مسلسلات تركى", "category/series-9/مسلسلات-تركي/"),
CatUnit("مسلسلات اسيوى", "category/series-9/مسلسلات-أسيوي/"),
CatUnit("مسلسلات هندى", "category/series-9/مسلسلات-هندي/"),
)
override fun setupPreferenceScreen(screen: PreferenceScreen) {
val videoQualityPref = ListPreference(screen.context).apply {
key = "preferred_quality"
title = "Preferred quality"
entries = arrayOf("720p", "480p", "Low", "Normal", "HD", "UHD", "DoodStream", "Uqload")
entryValues = arrayOf("720", "480", "Low", "Normal", "HD", "UHD", "Dood", "Uqload")
setDefaultValue("1080")
summary = "%s"
setOnPreferenceChangeListener { _, newValue ->
val selected = newValue as String
val index = findIndexOfValue(selected)
val entry = entryValues[index] as String
preferences.edit().putString(key, entry).commit()
}
}
screen.addPreference(videoQualityPref)
}
}

View file

@ -1,7 +0,0 @@
ext {
extName = 'XS Anime'
extClass = '.XsAnime'
extVersionCode = 10
}
apply from: "$rootDir/common.gradle"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View file

@ -1,225 +0,0 @@
package eu.kanade.tachiyomi.animeextension.ar.xsanime
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.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.util.asJsoup
import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
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 XsAnime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override val name = "XS Anime"
override val baseUrl = "https://ww.xsanime.com"
override val lang = "ar"
override val supportsLatest = false
private val preferences: SharedPreferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}
// Popular Anime
override fun popularAnimeSelector(): String = "ul.boxes--holder div.itemtype_anime a"
override fun popularAnimeRequest(page: Int): Request = GET("$baseUrl/anime_list/page/$page")
override fun popularAnimeFromElement(element: Element): SAnime {
val anime = SAnime.create()
anime.setUrlWithoutDomain(element.attr("href"))
anime.title = element.attr("title")
anime.thumbnail_url = element.selectFirst("div.itemtype_anime_poster img")!!.attr("data-src")
return anime
}
override fun popularAnimeNextPageSelector(): String = "ul.page-numbers li a.next"
// Episodes
override fun episodeListSelector() = "div.EpisodesList > a"
override fun episodeFromElement(element: Element): SEpisode {
val episode = SEpisode.create()
val epNum = getNumberFromEpsString(element.select("a > em").text())
episode.setUrlWithoutDomain(element.attr("abs:href"))
episode.name = element.select("a > em").text()
episode.episode_number = when {
epNum.isNotEmpty() -> epNum.toFloatOrNull() ?: 1F
else -> 1F
}
return episode
}
private fun getNumberFromEpsString(epsStr: String): String {
return epsStr.filter { it.isDigit() }
}
// Video Links
override fun videoListParse(response: Response): List<Video> {
val document = response.asJsoup()
val srcVid = preferences.getString("preferred_quality", "الجودة العالية")!!
val iframe = document.select("div.downloads ul div.listServ:contains($srcVid) div.serL a[href~=4shared]").attr("href").substringBeforeLast("/").replace("video", "web/embed/file")
val referer = response.request.url.toString()
val refererHeaders = Headers.headersOf("referer", referer)
val iframeResponse = client.newCall(GET(iframe, refererHeaders))
.execute().asJsoup()
return iframeResponse.select(videoListSelector()).map { videoFromElement(it) }
}
override fun videoListSelector() = "source"
override fun videoFromElement(element: Element): Video {
element.attr("src")
return Video(element.attr("src"), "Default: If you want to change the quality go to extension settings", element.attr("src"))
}
override fun videoUrlParse(document: Document) = throw UnsupportedOperationException()
// Search
override fun searchAnimeFromElement(element: Element): SAnime {
val anime = SAnime.create()
anime.setUrlWithoutDomain(element.attr("href"))
anime.title = element.attr("title")
anime.thumbnail_url = element.selectFirst("div.itemtype_anime_poster img")!!.attr("data-src")
return anime
}
override fun searchAnimeNextPageSelector(): String = "ul.page-numbers li a.next"
override fun searchAnimeSelector(): String = "ul.boxes--holder div.itemtype_anime a"
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
return if (query.isNotBlank()) {
GET("$baseUrl/?s=$query&type=anime&page=$page", headers)
} else {
val url = "$baseUrl/anime_list/page/$page/?".toHttpUrlOrNull()!!.newBuilder()
filters.forEach { filter ->
when (filter) {
// is SeasonFilter -> url.addQueryParameter("season", filter.toUriPart())
is GenreFilter -> url.addQueryParameter("genre", filter.toUriPart())
is StatusFilter -> url.addQueryParameter("status", filter.toUriPart())
// is LetterFilter -> url.addQueryParameter("letter", filter.toUriPart())
else -> {}
}
}
GET(url.build().toString(), headers)
}
}
// Anime Details
override fun animeDetailsParse(document: Document): SAnime {
val anime = SAnime.create()
anime.thumbnail_url = document.selectFirst("div.inner--image img")!!.attr("src")
anime.title = document.select("h1.post--inner-title").text()
anime.genre = document.select("ul.terms--and--metas > li:contains(تصنيفات الأنمي) > a").joinToString(", ") { it.text() }
anime.description = document.select("div.post--content--inner").text()
document.select("ul.terms--and--metas li:contains(عدد الحلقات) a").text()?.also { statusText ->
when {
statusText.contains("غير معروف", true) -> anime.status = SAnime.ONGOING
else -> anime.status = SAnime.COMPLETED
}
}
return anime
}
// Filters
override fun getFilterList() = AnimeFilterList(
AnimeFilter.Header("NOTE: Ignored if using text search!"),
AnimeFilter.Separator(),
GenreFilter(getGenreFilters()),
StatusFilter(getStatusFilters()),
// SeasonFilter(getStatusFilters()),
// LetterFilter(getLetterFilter()),
)
private class StatusFilter(vals: Array<Pair<String?, String>>) : UriPartFilter("حالة الأنمي", vals)
private class GenreFilter(vals: Array<Pair<String?, String>>) : UriPartFilter("تصنيفات الانمى", vals)
// private class SeasonFilter(vals: Array<Pair<String?, String>>) : UriPartFilter("موسم الانمى", vals)
// private class LetterFilter(vals: Array<Pair<String?, String>>) : UriPartFilter("الحرف", vals)
private fun getStatusFilters(): Array<Pair<String?, String>> = arrayOf(
Pair("", "<اختر>"),
Pair("مستمر", "مستمر"),
Pair("منتهي", "منتهي"),
)
private fun getGenreFilters(): Array<Pair<String?, String>> = arrayOf(
Pair("", "<اختر>"),
Pair("أكشن", "أكشن"),
Pair("تاريخي", "تاريخي"),
Pair("حريم", "حريم"),
Pair("خارق للطبيعة", "خارق للطبيعة"),
Pair("خيال", "خيال"),
Pair("دراما", "دراما"),
Pair("رومانسي", "رومانسي"),
Pair("رياضي", "رياضي"),
Pair("سينين", "سينين"),
Pair("شونين", "شونين"),
Pair("شياطين", "شياطين"),
Pair("غموض", "غموض"),
Pair("قوى خارقة", "قوى خارقة"),
Pair("كوميدي", "كوميدي"),
Pair("لعبة", "لعبة"),
Pair("مدرسي", "مدرسي"),
Pair("مغامرات", "مغامرات"),
Pair("موسيقي", "موسيقي"),
Pair("نفسي", "نفسي"),
)
open class UriPartFilter(displayName: String, private val vals: Array<Pair<String?, String>>) :
AnimeFilter.Select<String>(displayName, vals.map { it.second }.toTypedArray()) {
fun toUriPart() = vals[state].first
}
// Latest
override fun latestUpdatesNextPageSelector(): String? = throw UnsupportedOperationException()
override fun latestUpdatesFromElement(element: Element): SAnime = throw UnsupportedOperationException()
override fun latestUpdatesRequest(page: Int): Request = throw UnsupportedOperationException()
override fun latestUpdatesSelector(): String = throw UnsupportedOperationException()
// Preferences
override fun setupPreferenceScreen(screen: PreferenceScreen) {
val qualityPref = ListPreference(screen.context).apply {
key = "preferred_quality"
title = "Preferred Quality"
entries = arrayOf("الجودة العالية", "الجودة الخارقة", "الجودة المتوسطة")
entryValues = arrayOf("الجودة العالية", "الجودة الخارقة", "الجودة المتوسطة")
setDefaultValue("الجودة العالية")
summary = "%s"
setOnPreferenceChangeListener { _, newValue ->
val selected = newValue as String
val index = findIndexOfValue(selected)
val entry = entryValues[index] as String
preferences.edit().putString(key, entry).commit()
}
}
screen.addPreference(qualityPref)
}
}

View file

@ -1,7 +0,0 @@
ext {
extName = 'XS Movie'
extClass = '.XsMovie'
extVersionCode = 5
}
apply from: "$rootDir/common.gradle"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View file

@ -1,149 +0,0 @@
package eu.kanade.tachiyomi.animeextension.ar.xsmovie
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.AnimeFilterList
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.util.asJsoup
import okhttp3.Headers
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 XsMovie : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override val name = "XS Movie"
override val baseUrl = "https://ww.xsanime.com"
override val lang = "ar"
override val supportsLatest = false
private val preferences: SharedPreferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}
// Popular Anime
override fun popularAnimeSelector(): String = "ul.boxes--holder div.itemtype_anime a"
override fun popularAnimeRequest(page: Int): Request = GET("$baseUrl/movies_list/page/$page")
override fun popularAnimeFromElement(element: Element): SAnime {
val anime = SAnime.create()
anime.setUrlWithoutDomain(element.attr("href"))
anime.title = element.attr("title")
anime.thumbnail_url = element.selectFirst("div.itemtype_anime_poster img")!!.attr("data-src")
return anime
}
override fun popularAnimeNextPageSelector(): String = "ul.page-numbers li a.next"
// Episodes
override fun episodeListSelector() = "h1.post--inner-title > a"
override fun episodeFromElement(element: Element): SEpisode {
val episode = SEpisode.create()
episode.setUrlWithoutDomain(element.attr("href"))
episode.name = element.text().replace("فيلم ", "").replace("مترجم ", "").replace("اون لاين ", "").replace("بلوراي", "") // "movie"
return episode
}
// Video Links
override fun videoListParse(response: Response): List<Video> {
val document = response.asJsoup()
val srcVid = preferences.getString("preferred_quality", "الجودة العالية")!!
val iframe = document.select("div.downloads ul div.listServ:contains($srcVid) div.serL a[href~=4shared]").attr("href").substringBeforeLast("/").replace("video", "web/embed/file")
val referer = response.request.url.toString()
val refererHeaders = Headers.headersOf("referer", referer)
val iframeResponse = client.newCall(GET(iframe, refererHeaders))
.execute().asJsoup()
return iframeResponse.select(videoListSelector()).map { videoFromElement(it) }
}
override fun videoListSelector() = "source"
override fun videoFromElement(element: Element): Video {
return Video(element.attr("src"), "Default: If you want to change the quality go to extension settings", element.attr("src"))
}
override fun videoUrlParse(document: Document) = throw UnsupportedOperationException()
// Search
override fun searchAnimeFromElement(element: Element): SAnime {
val anime = SAnime.create()
anime.setUrlWithoutDomain(element.attr("href"))
anime.title = element.attr("title")
anime.thumbnail_url = element.selectFirst("div.itemtype_anime_poster img")!!.attr("data-src")
return anime
}
override fun searchAnimeNextPageSelector(): String = "ul.page-numbers li a.next"
override fun searchAnimeSelector(): String = "ul.boxes--holder div.itemtype_anime a"
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
return GET("$baseUrl/?s=$query&type=movie&page=$page", headers)
}
// Anime Details
override fun animeDetailsParse(document: Document): SAnime {
val anime = SAnime.create()
anime.thumbnail_url = document.selectFirst("div.inner--image img")!!.attr("src")
anime.title = document.select("h1.post--inner-title").text()
anime.genre = document.select("ul.terms--and--metas > li:contains(تصنيفات الأنمي) > a").joinToString(", ") { it.text() }
anime.description = document.select("div.post--content--inner").text()
document.select("ul.terms--and--metas li:contains(عدد الحلقات) a").text()?.also { statusText ->
when {
statusText.contains("غير معروف", true) -> anime.status = SAnime.ONGOING
else -> anime.status = SAnime.COMPLETED
}
}
return anime
}
// Latest
override fun latestUpdatesNextPageSelector(): String? = throw UnsupportedOperationException()
override fun latestUpdatesFromElement(element: Element): SAnime = throw UnsupportedOperationException()
override fun latestUpdatesRequest(page: Int): Request = throw UnsupportedOperationException()
override fun latestUpdatesSelector(): String = throw UnsupportedOperationException()
// Preferences
override fun setupPreferenceScreen(screen: PreferenceScreen) {
val qualityPref = ListPreference(screen.context).apply {
key = "preferred_quality"
title = "Preferred Quality"
entries = arrayOf("الجودة العالية", "الجودة الخارقة", "الجودة المتوسطة")
entryValues = arrayOf("الجودة العالية", "الجودة الخارقة", "الجودة المتوسطة")
setDefaultValue("الجودة العالية")
summary = "%s"
setOnPreferenceChangeListener { _, newValue ->
val selected = newValue as String
val index = findIndexOfValue(selected)
val entry = entryValues[index] as String
preferences.edit().putString(key, entry).commit()
}
}
screen.addPreference(qualityPref)
}
}