diff --git a/src/all/lmanime/AndroidManifest.xml b/src/all/lmanime/AndroidManifest.xml new file mode 100644 index 000000000..3cc5b53de --- /dev/null +++ b/src/all/lmanime/AndroidManifest.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + diff --git a/src/all/lmanime/build.gradle b/src/all/lmanime/build.gradle new file mode 100644 index 000000000..faaa5c33e --- /dev/null +++ b/src/all/lmanime/build.gradle @@ -0,0 +1,19 @@ +plugins { + alias(libs.plugins.android.application) + alias(libs.plugins.kotlin.android) + alias(libs.plugins.kotlin.serialization) +} + +ext { + extName = 'LMAnime' + pkgNameSuffix = 'all.lmanime' + extClass = '.LMAnime' + extVersionCode = 1 +} + +dependencies { + implementation(project(":lib-fembed-extractor")) + implementation(project(":lib-okru-extractor")) +} + +apply from: "$rootDir/common.gradle" diff --git a/src/all/lmanime/res/mipmap-hdpi/ic_launcher.png b/src/all/lmanime/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..436816e4e Binary files /dev/null and b/src/all/lmanime/res/mipmap-hdpi/ic_launcher.png differ diff --git a/src/all/lmanime/res/mipmap-mdpi/ic_launcher.png b/src/all/lmanime/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..33d8ec8af Binary files /dev/null and b/src/all/lmanime/res/mipmap-mdpi/ic_launcher.png differ diff --git a/src/all/lmanime/res/mipmap-xhdpi/ic_launcher.png b/src/all/lmanime/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..983ced376 Binary files /dev/null and b/src/all/lmanime/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/src/all/lmanime/res/mipmap-xxhdpi/ic_launcher.png b/src/all/lmanime/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..ca11fcebb Binary files /dev/null and b/src/all/lmanime/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/src/all/lmanime/res/mipmap-xxxhdpi/ic_launcher.png b/src/all/lmanime/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..ff058cdbd Binary files /dev/null and b/src/all/lmanime/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/src/all/lmanime/src/eu/kanade/tachiyomi/animeextension/all/lmanime/LMAnime.kt b/src/all/lmanime/src/eu/kanade/tachiyomi/animeextension/all/lmanime/LMAnime.kt new file mode 100644 index 000000000..73d0cbb04 --- /dev/null +++ b/src/all/lmanime/src/eu/kanade/tachiyomi/animeextension/all/lmanime/LMAnime.kt @@ -0,0 +1,344 @@ +package eu.kanade.tachiyomi.animeextension.all.lmanime + +import android.app.Application +import android.content.SharedPreferences +import android.util.Base64 +import androidx.preference.ListPreference +import androidx.preference.MultiSelectListPreference +import androidx.preference.PreferenceScreen +import eu.kanade.tachiyomi.animeextension.all.lmanime.extractors.DailymotionExtractor +import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource +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.fembedextractor.FembedExtractor +import eu.kanade.tachiyomi.lib.okruextractor.OkruExtractor +import eu.kanade.tachiyomi.network.GET +import eu.kanade.tachiyomi.network.asObservableSuccess +import eu.kanade.tachiyomi.util.asJsoup +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.runBlocking +import okhttp3.Request +import okhttp3.Response +import org.jsoup.nodes.Document +import org.jsoup.nodes.Element +import rx.Observable +import uy.kohesive.injekt.Injekt +import uy.kohesive.injekt.api.get +import java.text.SimpleDateFormat +import java.util.Locale + +class LMAnime : ConfigurableAnimeSource, ParsedAnimeHttpSource() { + + override val name = "LMAnime" + + override val baseUrl = "https://lmanime.com" + + override val lang = "all" + + override val supportsLatest = true + + private val preferences: SharedPreferences by lazy { + Injekt.get().getSharedPreferences("source_$id", 0x0000) + } + + // ============================== Popular =============================== + override fun popularAnimeFromElement(element: Element): SAnime { + return SAnime.create().apply { + val ahref = element.selectFirst("h4 > a.series")!! + setUrlWithoutDomain(ahref.attr("href")) + title = ahref.text() + thumbnail_url = element.selectFirst("img")!!.attr("src") + } + } + + override fun popularAnimeNextPageSelector() = null + + override fun popularAnimeRequest(page: Int) = GET(baseUrl) + + override fun popularAnimeSelector() = "div.serieslist.wpop-alltime li" + + // ============================== Episodes ============================== + override fun episodeListParse(response: Response): List { + val doc = getRealDoc(response.asJsoup()) + return doc.select(episodeListSelector()).map(::episodeFromElement) + } + + override fun episodeFromElement(element: Element): SEpisode { + return SEpisode.create().apply { + setUrlWithoutDomain(element.attr("href")) + element.selectFirst("div.epl-title")!!.text().let { + name = it + episode_number = it.substringBefore(" (") + .substringAfterLast(" ") + .toFloatOrNull() ?: 0F + } + + date_upload = element.selectFirst("div.epl-date")?.text().toDate() + } + } + + override fun episodeListSelector() = "div.eplister > ul > li > a" + + // =========================== Anime Details ============================ + override fun animeDetailsParse(document: Document): SAnime { + val doc = getRealDoc(document) + return SAnime.create().apply { + setUrlWithoutDomain(doc.location()) + title = doc.selectFirst("h1.entry-title")!!.text() + thumbnail_url = doc.selectFirst("div.thumb > img")!!.attr("src") + + val infos = doc.selectFirst("div.info-content")!! + genre = infos.select("div.genxed > a").eachText().joinToString() + status = parseStatus(infos.getInfo("Status")) + artist = infos.getInfo("Studio") + author = infos.getInfo("Fansub") + + description = buildString { + doc.selectFirst("div.entry-content")?.text()?.let { + append("$it\n\n") + } + + infos.select("div.spe > span").eachText().forEach { + append("$it\n") + } + } + } + } + + // ============================ Video Links ============================= + override fun videoListSelector() = "select.mirror > option[data-index]" + + override fun videoListParse(response: Response): List