diff --git a/UASerialProvider/build.gradle.kts b/UASerialProvider/build.gradle.kts
new file mode 100644
index 0000000..33eaa5a
--- /dev/null
+++ b/UASerialProvider/build.gradle.kts
@@ -0,0 +1,25 @@
+// use an integer for version numbers
+version = 1
+
+
+cloudstream {
+ language = "uk"
+ // All of these properties are optional, you can safely remove them
+
+ description = "Дивись онлайн серіали тільки найкращих світових студій Netflix, HBO, Disney, Amazon та інших. Серіали із українською озвучкою та онлайн, у HD якості."
+ authors = listOf("CakesTwix")
+
+ /**
+ * Status int as the following:
+ * 0: Down
+ * 1: Ok
+ * 2: Slow
+ * 3: Beta only
+ * */
+ status = 1 // will be 3 if unspecified
+ tvTypes = listOf(
+ "TvSeries",
+ )
+
+ iconUrl = "https://www.google.com/s2/favicons?domain=uaserial.tv&sz=%size%"
+}
\ No newline at end of file
diff --git a/UASerialProvider/src/main/AndroidManifest.xml b/UASerialProvider/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..29aec9d
--- /dev/null
+++ b/UASerialProvider/src/main/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/UASerialProvider/src/main/kotlin/com/lagradost/UASerialProvider.kt b/UASerialProvider/src/main/kotlin/com/lagradost/UASerialProvider.kt
new file mode 100644
index 0000000..56013a6
--- /dev/null
+++ b/UASerialProvider/src/main/kotlin/com/lagradost/UASerialProvider.kt
@@ -0,0 +1,141 @@
+package com.lagradost
+
+import com.lagradost.cloudstream3.*
+import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
+import com.lagradost.cloudstream3.utils.ExtractorLink
+import com.lagradost.cloudstream3.utils.M3u8Helper
+import com.lagradost.models.GeneralInfo
+import org.jsoup.nodes.Element
+
+class UASerialProvider : MainAPI() {
+
+ // Basic Info
+ override var mainUrl = "https://uaserial.tv"
+ override var name = "UASerial"
+ override val hasMainPage = true
+ override var lang = "uk"
+ override val hasDownloadSupport = true
+ override val supportedTypes = setOf(
+ TvType.TvSeries,
+ )
+
+ // Sections
+ override val mainPage = mainPageOf(
+ "$mainUrl/%d?priority=popular" to "⭐ За популярністю",
+ "$mainUrl/%d?priority=views" to "\uD83D\uDC40 За переглядами",
+ "$mainUrl/%d?priority=rating" to "\uD83C\uDFC6 За рейтингом",
+ "$mainUrl/%d?priority=date" to "\uD83D\uDD25 За новизною",
+ )
+
+ override suspend fun getMainPage(
+ page: Int,
+ request: MainPageRequest
+ ): HomePageResponse {
+ var document = app.get(request.data.format(page)).document
+
+ val home = document.select(".row .col").map {
+ it.toSearchResponse()
+ }
+ return newHomePageResponse(request.name, home)
+ }
+
+ private fun Element.toSearchResponse(): SearchResponse {
+ val title = this.selectFirst("div.name")?.text()?.trim().toString()
+ val href = this.selectFirst("a")?.attr("href").toString()
+ val posterUrl = mainUrl + this.selectFirst("img.cover")?.attr("src")
+
+ return newMovieSearchResponse(title, href, TvType.Movie) {
+ this.posterUrl = posterUrl
+ }
+
+ }
+
+ override suspend fun search(query: String): List {
+ val document = app.post(
+ url = "$mainUrl",
+ data = mapOf(
+ "do" to "search",
+ "subaction" to "search",
+ "story" to query.replace(" ", "+")
+ )
+ ).document
+
+ return document.select("article.short").map {
+ it.toSearchResponse()
+ }
+ }
+
+ // Detailed information
+ override suspend fun load(url: String): LoadResponse {
+ val document = app.get(url).document
+ // Log.d("load-debug", document.select("script[type=application/ld+json]").html())
+ val titleJson =
+ tryParseJson(document.select("script[type=application/ld+json]").html())!!
+
+ // Parse info
+ val title = titleJson.partOfTVSeries.name
+ val poster = mainUrl + document.selectFirst("img.cover")?.attr("src")
+ val tags = document.select("div.genre div a").map { it.text() }
+ val year = document.select("div.release div a").text().toIntOrNull()
+
+ val tvType = TvType.TvSeries
+ val description = document.selectFirst(".text")?.text()?.trim()
+ val rating = document.select("div.rating__item--imdb div.number").text().toRatingInt()
+
+ // val actors = full_info[4].select("a").map { it.text() }
+
+ var episodes: List = emptyList()
+ titleJson.partOfTVSeries.containsSeason.map { season ->
+ season.episode.map { episode ->
+ episodes = episodes.plus(
+ Episode(
+ "${season.url}, ${episode.episodeNumber}",
+ episode.name.replaceFirstChar { it.uppercase() },
+ season.seasonNumber,
+ episode.episodeNumber
+ )
+ )
+ }
+ }
+
+ return newTvSeriesLoadResponse(title, url, tvType, episodes) {
+ this.posterUrl = poster
+ this.year = year
+ this.plot = description
+ this.tags = tags
+ this.rating = rating
+ }
+ }
+
+
+ // It works when I click to view the series
+ override suspend fun loadLinks(
+ data: String, // Url with season, episode number
+ isCasting: Boolean,
+ subtitleCallback: (SubtitleFile) -> Unit,
+ callback: (ExtractorLink) -> Unit
+ ): Boolean {
+ val dataList = data.split(", ")
+ val document = app.get(mainUrl + app.get(dataList[0]).document.select("option[data-series-number=${dataList[1]}]").attr("value")).document
+ document.select(".player .voices__wrap").map{ player ->
+ // Log.d("load-debug", player.attr("data-player-id")) // Player name
+ player.select("select.voices__select option").map{ dub ->
+ // Log.d("load-debug", dub.text()) // Name
+ // Log.d("load-debug", dub.attr("value"))// Url
+
+ val m3u8Url = app.get(dub.attr("value")).document.select("script").html()
+ .substringAfterLast("file:\"")
+ .substringBefore("\",")
+
+ M3u8Helper.generateM3u8(
+ source = "${dub.text()} (${player.attr("data-player-id").replaceFirstChar { it.uppercase() }})",
+ streamUrl = m3u8Url,
+ referer = "https://tortuga.wtf/"
+ ).forEach(callback)
+ }
+ }
+ // selecto__dropdown-item
+ return true
+ }
+
+}
\ No newline at end of file
diff --git a/UASerialProvider/src/main/kotlin/com/lagradost/UASerialProviderPlugin.kt b/UASerialProvider/src/main/kotlin/com/lagradost/UASerialProviderPlugin.kt
new file mode 100644
index 0000000..1bfe419
--- /dev/null
+++ b/UASerialProvider/src/main/kotlin/com/lagradost/UASerialProviderPlugin.kt
@@ -0,0 +1,13 @@
+package com.lagradost
+
+import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
+import com.lagradost.cloudstream3.plugins.Plugin
+import android.content.Context
+
+@CloudstreamPlugin
+class UASerialProviderPlugin: Plugin() {
+ override fun load(context: Context) {
+ // All providers should be added in this manner. Please don't edit the providers list directly.
+ registerMainAPI(UASerialProvider())
+ }
+}
\ No newline at end of file
diff --git a/UASerialProvider/src/main/kotlin/com/lagradost/models/GeneralInfo.kt b/UASerialProvider/src/main/kotlin/com/lagradost/models/GeneralInfo.kt
new file mode 100644
index 0000000..bf28e9b
--- /dev/null
+++ b/UASerialProvider/src/main/kotlin/com/lagradost/models/GeneralInfo.kt
@@ -0,0 +1,61 @@
+package com.lagradost.models
+
+data class GeneralInfo (
+
+ // val @context : String,
+ // val @type : String,
+ val datePublished : String,
+ val numberOfEpisodes : Int,
+ val partOfTVSeries : PartOfTVSeries,
+ val aggregateRating : AggregateRating,
+ val url : String,
+ val name : String
+)
+
+data class PartOfTVSeries (
+
+ // val @type : String,
+ val actor : List,
+ val director : List,
+ val name : String,
+ val containsSeason : List
+)
+
+data class AggregateRating (
+
+ // val @type : String,
+ val ratingValue : Double,
+ val ratingCount : Int,
+ val bestRating : Int,
+ val worstRating : Int
+)
+
+data class Actor (
+
+ // val @type : String,
+ val name : String
+)
+
+data class ContainsSeason (
+
+ val url : String,
+ // val @type : String,
+ val seasonNumber : Int,
+ val datePublished : String,
+ val name : String,
+ val episode : List,
+ val numberOfEpisodes : Int
+)
+
+data class Episode (
+
+ // val @type : String,
+ val episodeNumber : Int,
+ val name : String
+)
+
+data class Director (
+
+ // val @type : String,
+ val name : String
+)