diff --git a/src/en/myasiantv/build.gradle b/src/en/myasiantv/build.gradle new file mode 100644 index 00000000..94e3dd67 --- /dev/null +++ b/src/en/myasiantv/build.gradle @@ -0,0 +1,12 @@ +ext { + extName = 'MyAsianTV' + extClass = '.MyAsianTv' + extVersionCode = 1 +} + +apply from: "$rootDir/common.gradle" + +dependencies { + implementation(project(':lib:vidmoly-extractor')) + implementation(project(':lib:streamwish-extractor')) +} diff --git a/src/en/myasiantv/res/mipmap-hdpi/ic_launcher.png b/src/en/myasiantv/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 00000000..2b58c632 Binary files /dev/null and b/src/en/myasiantv/res/mipmap-hdpi/ic_launcher.png differ diff --git a/src/en/myasiantv/res/mipmap-mdpi/ic_launcher.png b/src/en/myasiantv/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 00000000..b8f37378 Binary files /dev/null and b/src/en/myasiantv/res/mipmap-mdpi/ic_launcher.png differ diff --git a/src/en/myasiantv/res/mipmap-xhdpi/ic_launcher.png b/src/en/myasiantv/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 00000000..b2f0de7c Binary files /dev/null and b/src/en/myasiantv/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/src/en/myasiantv/res/mipmap-xxhdpi/ic_launcher.png b/src/en/myasiantv/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 00000000..e6a1975a Binary files /dev/null and b/src/en/myasiantv/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/src/en/myasiantv/res/mipmap-xxxhdpi/ic_launcher.png b/src/en/myasiantv/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 00000000..a9d674d5 Binary files /dev/null and b/src/en/myasiantv/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/src/en/myasiantv/src/eu/kanade/tachiyomi/animeextension/en/myasiantv/MyAsianTv.kt b/src/en/myasiantv/src/eu/kanade/tachiyomi/animeextension/en/myasiantv/MyAsianTv.kt new file mode 100644 index 00000000..3fbaefb3 --- /dev/null +++ b/src/en/myasiantv/src/eu/kanade/tachiyomi/animeextension/en/myasiantv/MyAsianTv.kt @@ -0,0 +1,228 @@ +package eu.kanade.tachiyomi.animeextension.en.myasiantv + +import android.app.Application +import android.widget.Toast +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.lib.streamwishextractor.StreamWishExtractor +import eu.kanade.tachiyomi.lib.vidmolyextractor.VidMolyExtractor +import eu.kanade.tachiyomi.network.GET +import eu.kanade.tachiyomi.util.asJsoup +import okhttp3.Response +import org.jsoup.nodes.Document +import org.jsoup.nodes.Element +import uy.kohesive.injekt.Injekt +import uy.kohesive.injekt.api.get +import java.text.SimpleDateFormat +import java.util.Locale +import kotlin.time.Duration.Companion.days +import kotlin.time.Duration.Companion.hours +import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.Duration.Companion.minutes +import kotlin.time.Duration.Companion.seconds + +private const val TAG = "MyAsianTv" + +class MyAsianTv : ConfigurableAnimeSource, ParsedAnimeHttpSource() { + private lateinit var prefix: String + + override val lang = "en" + override val supportsLatest = true + override val name = "MyAsianTV" + override val baseUrl by lazy { + val domain = preferences.getString(prefKeyDomain, defaultDomain)!! + // special case for .rest + prefix = if (defaultDomain == domain) "drama-8" else "drama" + "https://$domain" + } + + override fun popularAnimeSelector() = primaryItemSelector + override fun latestUpdatesSelector() = primaryItemSelector + override fun searchAnimeSelector() = primaryItemSelector + + override fun popularAnimeNextPageSelector() = primaryNextSelector + override fun latestUpdatesNextPageSelector() = primaryNextSelector + override fun searchAnimeNextPageSelector() = "ul.pagination li.selected + li a" + + override fun episodeListSelector() = "ul.list-episode li a" + override fun videoListSelector() = "ul.list-server-items li" + + override fun popularAnimeRequest(page: Int) = getDramaList(page, 4) + override fun latestUpdatesRequest(page: Int) = getDramaList(page, 1) + + private fun getDramaList(page: Int, order: Int) = when (page) { + 1 -> GET("$baseUrl/$prefix/?selOrder=$order") + else -> GET("$baseUrl/$prefix/page/$page/?selOrder=$order") + } + + override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList) = + when (page) { + 1 -> GET("$baseUrl/?s=$query") + else -> GET("$baseUrl/search/$query/page/$page") + } + + override fun popularAnimeFromElement(element: Element) = createPrimaryItem(element) + override fun latestUpdatesFromElement(element: Element) = createPrimaryItem(element) + override fun searchAnimeFromElement(element: Element) = createPrimaryItem(element) + + private fun createPrimaryItem(element: Element) = SAnime.create().apply { + setUrlWithoutDomain(element.attr("href")) + title = element.selectFirst("img")?.let { + thumbnail_url = it.attr("src") + it.attr("alt") + } ?: "%08X".format(url.hashCode()) + } + + override fun animeDetailsRequest(anime: SAnime) = GET(baseUrl + anime.url) + + override fun animeDetailsParse(document: Document) = SAnime.create().apply { + document.selectFirst("div.movie img.poster")?.run { + title = attr("alt") + thumbnail_url = absUrl("src") + } + document.selectFirst("div.movie")?.run { + val plot = select("h3:contains(Plot) + div.info p").eachText() + .joinToString("\n").takeUnless(String::isBlank) + val source = plot?.substringAfterLast("(Source:", ")") + ?.substringBefore(")").orEmpty() + description = plot + author = source.substringBeforeLast("||", source.substringBeforeLast(";")) + .substringAfter("=").trim().takeUnless(String::isBlank) + genre = selectFirst("p:contains(Genre) span").textNotBlank() + status = selectFirst("p:contains(Status) span").textToStatus() + } + } + + private val episodeRegex = """\b(Ep|Episode)\b (\d+)(\.\d+)?""".toRegex() + override fun episodeFromElement(element: Element) = SEpisode.create().apply { + setUrlWithoutDomain(element.attr("href")) + val type = element.parent()?.previousElementSibling().textNotBlank() ?: "RAW" + val match = episodeRegex.find(element.attr("title")) + val epNum = when { + null == match -> "0" + match.groupValues[3].isEmpty() -> match.groupValues[2] + else -> "${match.groupValues[2]}${match.groupValues[3]}" + } + name = if ("0" == epNum) "$type Movie" else "$type Episode $epNum" + episode_number = epNum.toFloat() + date_upload = element.parent()?.nextElementSibling().textToDate() + } + + override fun videoListParse(response: Response): List