diff --git a/src/pt/doramogo/AndroidManifest.xml b/src/pt/doramogo/AndroidManifest.xml new file mode 100644 index 000000000..46ad028b5 --- /dev/null +++ b/src/pt/doramogo/AndroidManifest.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + diff --git a/src/pt/doramogo/build.gradle b/src/pt/doramogo/build.gradle new file mode 100644 index 000000000..c38a2e34b --- /dev/null +++ b/src/pt/doramogo/build.gradle @@ -0,0 +1,15 @@ +ext { + extName = 'Doramogo' + extClass = '.Doramogo' + extVersionCode = 1 +} + +apply from: "$rootDir/common.gradle" + +dependencies { + implementation(project(':lib:dailymotion-extractor')) + implementation(project(":lib:googledrive-extractor")) + implementation(project(":lib:okru-extractor")) + implementation(project(":lib:playlist-utils")) + implementation("dev.datlag.jsunpacker:jsunpacker:1.0.1") +} diff --git a/src/pt/doramogo/res/mipmap-hdpi/ic_launcher.png b/src/pt/doramogo/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..b94475662 Binary files /dev/null and b/src/pt/doramogo/res/mipmap-hdpi/ic_launcher.png differ diff --git a/src/pt/doramogo/res/mipmap-mdpi/ic_launcher.png b/src/pt/doramogo/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..a6970e66f Binary files /dev/null and b/src/pt/doramogo/res/mipmap-mdpi/ic_launcher.png differ diff --git a/src/pt/doramogo/res/mipmap-xhdpi/ic_launcher.png b/src/pt/doramogo/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..d38227fae Binary files /dev/null and b/src/pt/doramogo/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/src/pt/doramogo/res/mipmap-xxhdpi/ic_launcher.png b/src/pt/doramogo/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..33eae73c8 Binary files /dev/null and b/src/pt/doramogo/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/src/pt/doramogo/res/mipmap-xxxhdpi/ic_launcher.png b/src/pt/doramogo/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..d63638038 Binary files /dev/null and b/src/pt/doramogo/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/src/pt/doramogo/src/eu/kanade/tachiyomi/animeextension/pt/doramogo/Doramogo.kt b/src/pt/doramogo/src/eu/kanade/tachiyomi/animeextension/pt/doramogo/Doramogo.kt new file mode 100644 index 000000000..dcaa1b0c9 --- /dev/null +++ b/src/pt/doramogo/src/eu/kanade/tachiyomi/animeextension/pt/doramogo/Doramogo.kt @@ -0,0 +1,206 @@ +package eu.kanade.tachiyomi.animeextension.pt.doramogo + +import eu.kanade.tachiyomi.animeextension.pt.doramogo.extractors.DoramogoExtractor +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.dailymotionextractor.DailymotionExtractor +import eu.kanade.tachiyomi.lib.googledriveextractor.GoogleDriveExtractor +import eu.kanade.tachiyomi.lib.okruextractor.OkruExtractor +import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils +import eu.kanade.tachiyomi.network.GET +import eu.kanade.tachiyomi.network.awaitSuccess +import eu.kanade.tachiyomi.util.asJsoup +import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking +import okhttp3.HttpUrl +import okhttp3.HttpUrl.Companion.toHttpUrl +import okhttp3.Request +import okhttp3.Response +import org.jsoup.nodes.Document +import org.jsoup.nodes.Element + +class Doramogo : ParsedAnimeHttpSource() { + + override val name = "Doramogo" + + override val baseUrl = "https://doramogo.com" + + override val lang = "pt-BR" + + override val supportsLatest = true + + override fun headersBuilder() = super.headersBuilder() + .add("Referer", baseUrl) + .add("Origin", baseUrl) + + // ============================== Popular =============================== + override fun popularAnimeRequest(page: Int) = GET("$baseUrl/doramas/?filter_order=popular", headers) + + override fun popularAnimeSelector() = "div.item-drm" + + override fun popularAnimeFromElement(element: Element) = SAnime.create().apply { + setUrlWithoutDomain(element.selectFirst("a")!!.attr("href")) + title = element.selectFirst("div.title h3")!!.text() + thumbnail_url = element.selectFirst("div.cover > img")!!.attr("src") + } + + override fun popularAnimeNextPageSelector() = null + + // =============================== Latest =============================== + override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/doramas/?filter_orderby=date", headers) + + override fun latestUpdatesSelector() = popularAnimeSelector() + + override fun latestUpdatesFromElement(element: Element) = popularAnimeFromElement(element) + + override fun latestUpdatesNextPageSelector() = null + + // =============================== Search =============================== + override suspend fun getSearchAnime(page: Int, query: String, filters: AnimeFilterList): AnimesPage { + return if (query.startsWith(PREFIX_SEARCH)) { // URL intent handler + val id = query.removePrefix(PREFIX_SEARCH) + client.newCall(GET("$baseUrl/dorama/$id")) + .awaitSuccess() + .use(::searchAnimeByIdParse) + } else { + super.getSearchAnime(page, query, filters) + } + } + + private fun searchAnimeByIdParse(response: Response): AnimesPage { + val details = animeDetailsParse(response.asJsoup()) + return AnimesPage(listOf(details), false) + } + + override fun getFilterList() = DoramogoFilters.FILTER_LIST + + override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request { + val params = DoramogoFilters.getSearchParameters(filters) + + val url = "$baseUrl/search".toHttpUrl().newBuilder() + .addPathSegment(query) + .addIfNotBlank("filter_audio", params.audio) + .addIfNotBlank("filter_genre", params.genre) + .build() + + return GET(url, headers = headers) + } + + override fun searchAnimeSelector() = popularAnimeSelector() + + override fun searchAnimeFromElement(element: Element) = popularAnimeFromElement(element) + + override fun searchAnimeNextPageSelector() = null + + // =========================== Anime Details ============================ + override fun animeDetailsParse(document: Document) = SAnime.create().apply { + setUrlWithoutDomain(document.location()) + title = document.selectFirst("div.dados h1")!!.text() + thumbnail_url = document.select("div.image--cover").attr("style") + .substringAfter("background-image: url('").substringBefore("')") + description = document.selectFirst("p.readMor")!!.textNodes().joinToString("") + } + + // ============================== Episodes ============================== + override fun episodeListParse(response: Response): List { + return super.episodeListParse(response).reversed() + } + + override fun episodeListSelector() = "li.episode--content" + + override fun episodeFromElement(element: Element) = SEpisode.create().apply { + setUrlWithoutDomain(element.selectFirst("a")!!.attr("href")) + element.selectFirst("div.title-episode a")!!.textNodes().joinToString("").let { + name = it.substringAfter(". ") + episode_number = it.substringBefore(". ").toFloatOrNull() ?: 1F + } + } + + // ============================ Video Links ============================= + override fun videoListParse(response: Response): List