Dantotsu/app/src/main/java/ani/dantotsu/parsers/OfflineAnimeParser.kt
2024-04-21 02:58:17 -05:00

171 lines
No EOL
5.9 KiB
Kotlin

package ani.dantotsu.parsers
import android.app.Application
import ani.dantotsu.currContext
import ani.dantotsu.download.DownloadCompat.Companion.loadEpisodesCompat
import ani.dantotsu.download.DownloadCompat.Companion.loadSubtitleCompat
import ani.dantotsu.download.DownloadsManager
import ani.dantotsu.download.DownloadsManager.Companion.getSubDirectory
import ani.dantotsu.download.anime.AnimeDownloaderService.AnimeDownloadTask.Companion.getTaskName
import ani.dantotsu.media.MediaNameAdapter
import ani.dantotsu.media.MediaType
import ani.dantotsu.tryWithSuspend
import ani.dantotsu.util.Logger
import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.model.SEpisode
import eu.kanade.tachiyomi.animesource.model.SEpisodeImpl
import me.xdrop.fuzzywuzzy.FuzzySearch
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.Locale
class OfflineAnimeParser : AnimeParser() {
private val downloadManager = Injekt.get<DownloadsManager>()
private val context = Injekt.get<Application>()
override val name = "Offline"
override val saveName = "Offline"
override val hostUrl = "Offline"
override val isNSFW = false
override suspend fun loadEpisodes(
animeLink: String,
extra: Map<String, String>?,
sAnime: SAnime
): List<Episode> {
val directory = getSubDirectory(context, MediaType.ANIME, false, animeLink)
//get all of the folder names and add them to the list
val episodes = mutableListOf<Episode>()
if (directory?.exists() == true) {
directory.listFiles().forEach {
//put the title and episdode number in the extra data
val extraData = mutableMapOf<String, String>()
extraData["title"] = animeLink
extraData["episode"] = it.name!!
if (it.isDirectory) {
val episode = Episode(
it.name!!,
getTaskName(animeLink, it.name!!),
it.name,
null,
null,
extra = extraData,
sEpisode = SEpisodeImpl()
)
episodes.add(episode)
}
}
return if (episodes.isNotEmpty()) {
episodes.sortBy { MediaNameAdapter.findEpisodeNumber(it.number) }
episodes
} else {
loadEpisodesCompat(animeLink, extra, sAnime)
}
}
return emptyList()
}
override suspend fun loadVideoServers(
episodeLink: String,
extra: Map<String, String>?,
sEpisode: SEpisode
): List<VideoServer> {
return listOf(
VideoServer(
episodeLink,
offline = true,
extraData = extra
)
)
}
override suspend fun search(query: String): List<ShowResponse> {
val titles = downloadManager.animeDownloadedTypes.map { it.titleName }.distinct()
val returnTitlesPair: MutableList<Pair<String, Int>> = mutableListOf()
for (title in titles) {
Logger.log("Comparing $title to $query")
val score = FuzzySearch.ratio(title.lowercase(), query.lowercase())
if (score > 80) {
returnTitlesPair.add(Pair(title, score))
}
}
val returnTitles = returnTitlesPair.sortedByDescending { it.second }.map { it.first }
val returnList: MutableList<ShowResponse> = mutableListOf()
for (title in returnTitles) {
returnList.add(ShowResponse(title, title, title))
}
return returnList
}
override suspend fun loadByVideoServers(
episodeUrl: String,
extra: Map<String, String>?,
sEpisode: SEpisode,
callback: (VideoExtractor) -> Unit
) {
val server = loadVideoServers(episodeUrl, extra, sEpisode).first()
OfflineVideoExtractor(server).apply {
tryWithSuspend {
load()
}
callback.invoke(this)
}
}
override suspend fun getVideoExtractor(server: VideoServer): VideoExtractor {
return OfflineVideoExtractor(server)
}
}
class OfflineVideoExtractor(private val videoServer: VideoServer) : VideoExtractor() {
override val server: VideoServer
get() = videoServer
override suspend fun extract(): VideoContainer {
val sublist = getSubtitle(
videoServer.extraData?.get("title") ?: "",
videoServer.extraData?.get("episode") ?: ""
) ?: emptyList()
//we need to return a "fake" video so that the app doesn't crash
val video = Video(
null,
VideoType.CONTAINER,
"",
)
return VideoContainer(listOf(video), sublist)
}
private fun getSubtitle(title: String, episode: String): List<Subtitle>? {
currContext()?.let {
getSubDirectory(
it,
MediaType.ANIME,
false,
title,
episode
)?.listFiles()?.forEach { file ->
if (file.name?.contains("subtitle") == true) {
return listOf(
Subtitle(
"Downloaded Subtitle",
file.uri.toString(),
determineSubtitleType(file.name ?: "")
)
)
}
}
loadSubtitleCompat(title, episode)?.let { return it }
}
return null
}
private fun determineSubtitleType(url: String): SubtitleType {
return when {
url.lowercase(Locale.ROOT).endsWith("ass") -> SubtitleType.ASS
url.lowercase(Locale.ROOT).endsWith("vtt") -> SubtitleType.VTT
else -> SubtitleType.SRT
}
}
}