Dantotsu/app/src/main/java/ani/dantotsu/parsers/OfflineAnimeParser.kt
2024-01-25 12:00:00 +00:00

160 lines
No EOL
5.2 KiB
Kotlin

package ani.dantotsu.parsers
import android.net.Uri
import android.os.Environment
import ani.dantotsu.currContext
import ani.dantotsu.download.DownloadsManager
import ani.dantotsu.media.anime.AnimeNameAdapter
import ani.dantotsu.tryWithSuspend
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.io.File
import java.util.Locale
class OfflineAnimeParser : AnimeParser() {
private val downloadManager = Injekt.get<DownloadsManager>()
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 = File(
currContext()?.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
"${DownloadsManager.animeLocation}/$animeLink"
)
//get all of the folder names and add them to the list
val episodes = mutableListOf<Episode>()
if (directory.exists()) {
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,
"$animeLink - ${it.name}",
it.name,
null,
null,
extra = extraData,
sEpisode = SEpisodeImpl()
)
episodes.add(episode)
}
}
episodes.sortBy { AnimeNameAdapter.findEpisodeNumber(it.number) }
return episodes
}
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.title }.distinct()
val returnTitles: MutableList<String> = mutableListOf()
for (title in titles) {
if (FuzzySearch.ratio(title.lowercase(), query.lowercase()) > 80) {
returnTitles.add(title)
}
}
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(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 {
DownloadsManager.getDirectory(
it,
ani.dantotsu.download.DownloadedType.Type.ANIME,
title,
episode
).listFiles()?.forEach {
if (it.name.contains("subtitle")) {
return listOf(
Subtitle(
"Downloaded Subtitle",
Uri.fromFile(it).toString(),
determineSubtitletype(it.absolutePath)
)
)
}
}
}
return null
}
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
}
}
}