I FUCKING HATE EXOPLAYER SUBTITLES

This commit is contained in:
rebelonion 2024-01-19 01:49:24 -06:00
parent ea96291bfc
commit 87a9df4c12
9 changed files with 257 additions and 50 deletions

View file

@ -71,7 +71,17 @@ class DownloadsManager(private val context: Context) {
Toast.makeText(context, "Directory does not exist", Toast.LENGTH_SHORT).show() Toast.makeText(context, "Directory does not exist", Toast.LENGTH_SHORT).show()
cleanDownloads() cleanDownloads()
} }
downloadsList.removeAll { it.title == title } when (type) {
DownloadedType.Type.MANGA -> {
downloadsList.removeAll { it.title == title && it.type == DownloadedType.Type.MANGA }
}
DownloadedType.Type.ANIME -> {
downloadsList.removeAll { it.title == title && it.type == DownloadedType.Type.ANIME }
}
DownloadedType.Type.NOVEL -> {
downloadsList.removeAll { it.title == title && it.type == DownloadedType.Type.NOVEL }
}
}
saveDownloads() saveDownloads()
} }
@ -126,7 +136,7 @@ class DownloadsManager(private val context: Context) {
{ {
val jsonString = gson.toJson(downloadsList) val jsonString = gson.toJson(downloadsList)
val file = File( val file = File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
"Dantotsu/downloads.json" "Dantotsu/downloads.json"
) )
if (file.parentFile?.exists() == false) { if (file.parentFile?.exists() == false) {
@ -199,7 +209,7 @@ class DownloadsManager(private val context: Context) {
) )
} }
val destination = File( val destination = File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
"Dantotsu/${downloadedType.title}/${downloadedType.chapter}" "Dantotsu/${downloadedType.title}/${downloadedType.chapter}"
) )
if (directory.exists()) { if (directory.exists()) {
@ -241,6 +251,46 @@ class DownloadsManager(private val context: Context) {
const val novelLocation = "Dantotsu/Novel" const val novelLocation = "Dantotsu/Novel"
const val mangaLocation = "Dantotsu/Manga" const val mangaLocation = "Dantotsu/Manga"
const val animeLocation = "Dantotsu/Anime" const val animeLocation = "Dantotsu/Anime"
fun getDirectory(context: Context, type: DownloadedType.Type, title: String, chapter: String? = null): File {
return if (type == DownloadedType.Type.MANGA) {
if (chapter != null) {
File(
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
"$mangaLocation/$title/$chapter"
)
} else {
File(
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
"$mangaLocation/$title"
)
}
} else if (type == DownloadedType.Type.ANIME) {
if (chapter != null) {
File(
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
"$animeLocation/$title/$chapter"
)
} else {
File(
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
"$animeLocation/$title"
)
}
} else {
if (chapter != null) {
File(
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
"$novelLocation/$title/$chapter"
)
} else {
File(
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
"$novelLocation/$title"
)
}
}
}
} }
} }

View file

@ -28,6 +28,7 @@ import ani.dantotsu.download.video.ExoplayerDownloadService
import ani.dantotsu.download.video.Helper import ani.dantotsu.download.video.Helper
import ani.dantotsu.logger import ani.dantotsu.logger
import ani.dantotsu.media.Media import ani.dantotsu.media.Media
import ani.dantotsu.media.SubtitleDownloader
import ani.dantotsu.media.anime.AnimeWatchFragment import ani.dantotsu.media.anime.AnimeWatchFragment
import ani.dantotsu.parsers.Subtitle import ani.dantotsu.parsers.Subtitle
import ani.dantotsu.parsers.Video import ani.dantotsu.parsers.Video
@ -228,6 +229,17 @@ class AnimeDownloaderService : Service() {
} }
saveMediaInfo(task) saveMediaInfo(task)
task.subtitle?.let {
SubtitleDownloader.downloadSubtitle(
this@AnimeDownloaderService,
it.file.url,
DownloadedType(
task.title,
task.episode,
DownloadedType.Type.ANIME,
)
)
}
val downloadStarted = val downloadStarted =
hasDownloadStarted(downloadManager, task, 30000) // 30 seconds timeout hasDownloadStarted(downloadManager, task, 30000) // 30 seconds timeout
@ -313,6 +325,7 @@ class AnimeDownloaderService : Service() {
} catch (e: Exception) { } catch (e: Exception) {
logger("Exception while downloading file: ${e.message}") logger("Exception while downloading file: ${e.message}")
snackString("Exception while downloading file: ${e.message}") snackString("Exception while downloading file: ${e.message}")
e.printStackTrace()
FirebaseCrashlytics.getInstance().recordException(e) FirebaseCrashlytics.getInstance().recordException(e)
broadcastDownloadFailed(task.episode) broadcastDownloadFailed(task.episode)
} }

View file

@ -17,6 +17,7 @@ import androidx.core.content.ContextCompat.getString
import androidx.media3.common.C import androidx.media3.common.C
import androidx.media3.common.MediaItem import androidx.media3.common.MediaItem
import androidx.media3.common.MimeTypes import androidx.media3.common.MimeTypes
import androidx.media3.common.TrackSelectionParameters
import androidx.media3.common.util.UnstableApi import androidx.media3.common.util.UnstableApi
import androidx.media3.database.StandaloneDatabaseProvider import androidx.media3.database.StandaloneDatabaseProvider
import androidx.media3.datasource.DataSource import androidx.media3.datasource.DataSource
@ -30,6 +31,7 @@ import androidx.media3.exoplayer.offline.DownloadHelper
import androidx.media3.exoplayer.offline.DownloadManager import androidx.media3.exoplayer.offline.DownloadManager
import androidx.media3.exoplayer.offline.DownloadService import androidx.media3.exoplayer.offline.DownloadService
import androidx.media3.exoplayer.scheduler.Requirements import androidx.media3.exoplayer.scheduler.Requirements
import androidx.media3.ui.TrackSelectionDialogBuilder
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.defaultHeaders import ani.dantotsu.defaultHeaders
import ani.dantotsu.download.DownloadedType import ani.dantotsu.download.DownloadedType
@ -99,28 +101,6 @@ object Helper {
) )
downloadHelper.prepare(object : DownloadHelper.Callback { downloadHelper.prepare(object : DownloadHelper.Callback {
override fun onPrepared(helper: DownloadHelper) { override fun onPrepared(helper: DownloadHelper) {
/*TrackSelectionDialogBuilder( TODO: use this for subtitles
context, "Select Source", helper.getTracks(0).groups
) { _, overrides ->
val params = TrackSelectionParameters.Builder(context)
overrides.forEach {
params.addOverride(it.value)
}
helper.addTrackSelection(0, params.build())
ExoplayerDownloadService
DownloadService.sendAddDownload(
context,
ExoplayerDownloadService::class.java,
helper.getDownloadRequest(null),
false
)
}.apply {
setTheme(R.style.DialogTheme)
setTrackNameProvider {
if (it.frameRate > 0f) it.height.toString() + "p" else it.height.toString() + "p (fps : N/A)"
}
build().show()
}*/
helper.getDownloadRequest(null).let { helper.getDownloadRequest(null).let {
DownloadService.sendAddDownload( DownloadService.sendAddDownload(
context, context,

View file

@ -1,19 +1,23 @@
package ani.dantotsu.media package ani.dantotsu.media
import android.content.Context import android.content.Context
import ani.dantotsu.download.DownloadedType
import ani.dantotsu.download.DownloadsManager
import ani.dantotsu.parsers.SubtitleType import ani.dantotsu.parsers.SubtitleType
import ani.dantotsu.snackString
import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.network.NetworkHelper
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import okhttp3.Request import okhttp3.Request
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.io.File
class SubtitleDownloader { class SubtitleDownloader {
companion object { companion object {
//doesn't really download the subtitles -\_(o_o)_/- //doesn't really download the subtitles -\_(o_o)_/-
suspend fun downloadSubtitles(context: Context, url: String): SubtitleType = suspend fun loadSubtitleType(context: Context, url: String): SubtitleType =
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
// Initialize the NetworkHelper instance. Replace this line based on how you usually initialize it // Initialize the NetworkHelper instance. Replace this line based on how you usually initialize it
val networkHelper = Injekt.get<NetworkHelper>() val networkHelper = Injekt.get<NetworkHelper>()
@ -29,8 +33,8 @@ class SubtitleDownloader {
val subtitleType = when { val subtitleType = when {
responseBody.contains("[Script Info]") == true -> SubtitleType.ASS responseBody.contains("[Script Info]") -> SubtitleType.ASS
responseBody.contains("WEBVTT") == true -> SubtitleType.VTT responseBody.contains("WEBVTT") -> SubtitleType.VTT
else -> SubtitleType.SRT else -> SubtitleType.SRT
} }
@ -39,5 +43,41 @@ class SubtitleDownloader {
return@withContext SubtitleType.UNKNOWN return@withContext SubtitleType.UNKNOWN
} }
} }
//actually downloads lol
suspend fun downloadSubtitle(context: Context, url: String, downloadedType: DownloadedType) {
try {
val directory = DownloadsManager.getDirectory(context, downloadedType.type, downloadedType.title, downloadedType.chapter)
if (!directory.exists()) { //just in case
directory.mkdirs()
}
val type = loadSubtitleType(context, url)
val subtiteFile = File(directory, "subtitle.${type}")
if (subtiteFile.exists()) {
subtiteFile.delete()
}
subtiteFile.createNewFile()
val client = Injekt.get<NetworkHelper>().client
val request = Request.Builder().url(url).build()
val reponse = client.newCall(request).execute()
if (!reponse.isSuccessful) {
snackString("Failed to download subtitle")
return
}
reponse.body.byteStream().use { input ->
subtiteFile.outputStream().use { output ->
input.copyTo(output)
}
}
} catch (e: Exception) {
snackString("Failed to download subtitle")
e.printStackTrace()
return
}
}
} }
} }

View file

@ -48,7 +48,9 @@ import androidx.media3.common.*
import androidx.media3.common.C.AUDIO_CONTENT_TYPE_MOVIE import androidx.media3.common.C.AUDIO_CONTENT_TYPE_MOVIE
import androidx.media3.common.C.TRACK_TYPE_VIDEO import androidx.media3.common.C.TRACK_TYPE_VIDEO
import androidx.media3.common.util.UnstableApi import androidx.media3.common.util.UnstableApi
import androidx.media3.common.util.Util
import androidx.media3.datasource.DataSource import androidx.media3.datasource.DataSource
import androidx.media3.datasource.DefaultDataSourceFactory
import androidx.media3.datasource.HttpDataSource import androidx.media3.datasource.HttpDataSource
import androidx.media3.datasource.cache.CacheDataSource import androidx.media3.datasource.cache.CacheDataSource
import androidx.media3.datasource.okhttp.OkHttpDataSource import androidx.media3.datasource.okhttp.OkHttpDataSource
@ -1284,7 +1286,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
if (subtitle?.type == SubtitleType.UNKNOWN) { if (subtitle?.type == SubtitleType.UNKNOWN) {
val context = this val context = this
runBlocking { runBlocking {
val type = SubtitleDownloader.downloadSubtitles(context, subtitle!!.file.url) val type = SubtitleDownloader.loadSubtitleType(context, subtitle!!.file.url)
val fileUri = Uri.parse(subtitle!!.file.url) val fileUri = Uri.parse(subtitle!!.file.url)
sub = MediaItem.SubtitleConfiguration sub = MediaItem.SubtitleConfiguration
.Builder(fileUri) .Builder(fileUri)
@ -1302,8 +1304,9 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
} }
println("sub: $sub") println("sub: $sub")
} else { } else {
val subUri = Uri.parse((subtitle!!.file.url))
sub = MediaItem.SubtitleConfiguration sub = MediaItem.SubtitleConfiguration
.Builder(Uri.parse(subtitle!!.file.url)) .Builder(subUri)
.setSelectionFlags(C.SELECTION_FLAG_FORCED) .setSelectionFlags(C.SELECTION_FLAG_FORCED)
.setMimeType( .setMimeType(
when (subtitle?.type) { when (subtitle?.type) {
@ -1338,9 +1341,14 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
} }
dataSource dataSource
} }
val dafuckDataSourceFactory = DefaultDataSourceFactory(this, Util.getUserAgent(this, R.string.app_name.toString()))
cacheFactory = CacheDataSource.Factory().apply { cacheFactory = CacheDataSource.Factory().apply {
setCache(Helper.getSimpleCache(this@ExoplayerView)) setCache(Helper.getSimpleCache(this@ExoplayerView))
setUpstreamDataSourceFactory(dataSourceFactory) if (ext.server.offline) {
setUpstreamDataSourceFactory(dafuckDataSourceFactory)
} else {
setUpstreamDataSourceFactory(dataSourceFactory)
}
setCacheWriteDataSinkFactory(null) setCacheWriteDataSinkFactory(null)
} }
@ -1374,7 +1382,14 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
} }
builder.build() builder.build()
} else { } else {
downloadedMediaItem val addedSubsDownloadedMediaItem = downloadedMediaItem.buildUpon()
if (sub != null) {
val listofnotnullsubs = immutableListOf(sub).filterNotNull()
val addLanguage = listofnotnullsubs[0].buildUpon().setLanguage("en").build()
addedSubsDownloadedMediaItem.setSubtitleConfigurations(immutableListOf(addLanguage))
episode.selectedSubtitle = 0
}
addedSubsDownloadedMediaItem.build()
} }
@ -1635,7 +1650,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
if (isInitialized) { if (isInitialized) {
if (exoPlayer.currentPosition.toFloat() / exoPlayer.duration > settings.watchPercentage) { if (exoPlayer.currentPosition.toFloat() / exoPlayer.duration > settings.watchPercentage) {
preloading = true preloading = true
nextEpisode(false) { i -> //TODO: make sure this works for offline episodes nextEpisode(false) { i ->
val ep = episodes[episodeArr[currentEpisodeIndex + i]] ?: return@nextEpisode val ep = episodes[episodeArr[currentEpisodeIndex + i]] ?: return@nextEpisode
val selected = media.selected ?: return@nextEpisode val selected = media.selected ?: return@nextEpisode
lifecycleScope.launch(Dispatchers.IO) { lifecycleScope.launch(Dispatchers.IO) {
@ -1806,7 +1821,6 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
} }
super.onDestroy() super.onDestroy()
Glide.with(this).clear(exoPlay)
finishAndRemoveTask() finishAndRemoveTask()
} }

View file

@ -1,6 +1,7 @@
package ani.dantotsu.media.anime package ani.dantotsu.media.anime
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.AlertDialog
import android.content.DialogInterface import android.content.DialogInterface
import android.content.Intent import android.content.Intent
import android.graphics.Color import android.graphics.Color
@ -24,6 +25,7 @@ import ani.dantotsu.download.video.Helper
import ani.dantotsu.media.Media import ani.dantotsu.media.Media
import ani.dantotsu.media.MediaDetailsViewModel import ani.dantotsu.media.MediaDetailsViewModel
import ani.dantotsu.others.Download.download import ani.dantotsu.others.Download.download
import ani.dantotsu.parsers.Subtitle
import ani.dantotsu.parsers.VideoExtractor import ani.dantotsu.parsers.VideoExtractor
import ani.dantotsu.parsers.VideoType import ani.dantotsu.parsers.VideoType
import com.google.firebase.crashlytics.FirebaseCrashlytics import com.google.firebase.crashlytics.FirebaseCrashlytics
@ -302,18 +304,68 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
val episode = media!!.anime!!.episodes!![media!!.anime!!.selectedEpisode!!]!! val episode = media!!.anime!!.episodes!![media!!.anime!!.selectedEpisode!!]!!
val selectedVideo = val selectedVideo =
if (extractor.videos.size > episode.selectedVideo) extractor.videos[episode.selectedVideo] else null if (extractor.videos.size > episode.selectedVideo) extractor.videos[episode.selectedVideo] else null
if (selectedVideo != null) {
Helper.startAnimeDownloadService( val subtitles = extractor.subtitles
requireActivity(), val subtitleNames = subtitles.map { it.language }
media!!.mainName(), var subtitleToDownload: Subtitle? = null
episode.number, if (subtitles.isNotEmpty()) {
selectedVideo, AlertDialog.Builder(context, R.style.MyPopup)
null, .setTitle("Download Subtitle")
media, .setSingleChoiceItems(
episode.thumb?.url ?: media!!.banner ?: media!!.cover subtitleNames.toTypedArray(),
) -1
) { dialog, which ->
subtitleToDownload = subtitles[which]
}
.setPositiveButton("Download") { _, _ ->
dialog?.dismiss()
if (selectedVideo != null) {
Helper.startAnimeDownloadService(
currActivity()!!,
media!!.mainName(),
episode.number,
selectedVideo,
subtitleToDownload,
media,
episode.thumb?.url ?: media!!.banner ?: media!!.cover
)
} else {
snackString("No Video Selected")
}
}
.setNegativeButton("Cancel") { dialog, _ ->
subtitleToDownload = null
dialog.dismiss()
if (selectedVideo != null) {
Helper.startAnimeDownloadService(
currActivity()!!,
media!!.mainName(),
episode.number,
selectedVideo,
subtitleToDownload,
media,
episode.thumb?.url ?: media!!.banner ?: media!!.cover
)
} else {
snackString("No Video Selected")
}
}
.show()
} else { } else {
snackString("No Video Selected") if (selectedVideo != null) {
Helper.startAnimeDownloadService(
requireActivity(),
media!!.mainName(),
episode.number,
selectedVideo,
subtitleToDownload,
media,
episode.thumb?.url ?: media!!.banner ?: media!!.cover
)
} else {
snackString("No Video Selected")
}
} }
dismiss() dismiss()
} }

View file

@ -6,7 +6,9 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.annotation.OptIn
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.media3.common.util.UnstableApi
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.BottomSheetDialogFragment import ani.dantotsu.BottomSheetDialogFragment
@ -60,6 +62,7 @@ class SubtitleDialogFragment : BottomSheetDialogFragment() {
) )
) )
@OptIn(UnstableApi::class)
override fun onBindViewHolder(holder: StreamViewHolder, position: Int) { override fun onBindViewHolder(holder: StreamViewHolder, position: Int) {
val binding = holder.binding val binding = holder.binding
if (position == 0) { if (position == 0) {

View file

@ -1,9 +1,11 @@
package ani.dantotsu.parsers package ani.dantotsu.parsers
import android.net.Uri
import android.os.Environment import android.os.Environment
import ani.dantotsu.currContext import ani.dantotsu.currContext
import ani.dantotsu.download.DownloadsManager import ani.dantotsu.download.DownloadsManager
import ani.dantotsu.media.anime.AnimeNameAdapter import ani.dantotsu.media.anime.AnimeNameAdapter
import ani.dantotsu.tryWithSuspend
import eu.kanade.tachiyomi.animesource.model.SAnime import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.model.SEpisode import eu.kanade.tachiyomi.animesource.model.SEpisode
import eu.kanade.tachiyomi.animesource.model.SEpisodeImpl import eu.kanade.tachiyomi.animesource.model.SEpisodeImpl
@ -11,6 +13,7 @@ import me.xdrop.fuzzywuzzy.FuzzySearch
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.io.File import java.io.File
import java.util.Locale
class OfflineAnimeParser : AnimeParser() { class OfflineAnimeParser : AnimeParser() {
private val downloadManager = Injekt.get<DownloadsManager>() private val downloadManager = Injekt.get<DownloadsManager>()
@ -34,6 +37,10 @@ class OfflineAnimeParser : AnimeParser() {
val episodes = mutableListOf<Episode>() val episodes = mutableListOf<Episode>()
if (directory.exists()) { if (directory.exists()) {
directory.listFiles()?.forEach { 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) { if (it.isDirectory) {
val episode = Episode( val episode = Episode(
it.name, it.name,
@ -41,6 +48,7 @@ class OfflineAnimeParser : AnimeParser() {
it.name, it.name,
null, null,
null, null,
extra = extraData,
sEpisode = SEpisodeImpl() sEpisode = SEpisodeImpl()
) )
episodes.add(episode) episodes.add(episode)
@ -60,7 +68,8 @@ class OfflineAnimeParser : AnimeParser() {
return listOf( return listOf(
VideoServer( VideoServer(
episodeLink, episodeLink,
offline = true offline = true,
extraData = extra
) )
) )
} }
@ -81,6 +90,21 @@ class OfflineAnimeParser : AnimeParser() {
return returnList 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 { override suspend fun getVideoExtractor(server: VideoServer): VideoExtractor {
return OfflineVideoExtractor(server) return OfflineVideoExtractor(server)
} }
@ -92,7 +116,10 @@ class OfflineVideoExtractor(val videoServer: VideoServer) : VideoExtractor() {
get() = videoServer get() = videoServer
override suspend fun extract(): VideoContainer { override suspend fun extract(): VideoContainer {
val sublist = emptyList<Subtitle>() 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 //we need to return a "fake" video so that the app doesn't crash
val video = Video( val video = Video(
null, null,
@ -102,4 +129,33 @@ class OfflineVideoExtractor(val videoServer: VideoServer) : VideoExtractor() {
return VideoContainer(listOf(video), sublist) 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
}
}
} }

View file

@ -62,9 +62,8 @@ data class VideoServer(
) : Serializable { ) : Serializable {
constructor(name: String, embedUrl: String, extraData: Map<String, String>? = null) constructor(name: String, embedUrl: String, extraData: Map<String, String>? = null)
: this(name, FileUrl(embedUrl), extraData) : this(name, FileUrl(embedUrl), extraData)
constructor(name: String, offline: Boolean, extraData: Map<String, String>?)
constructor(name: String, offline: Boolean) : this(name, FileUrl(""), extraData, null, offline)
: this(name, FileUrl(""), null, null, offline)
constructor( constructor(
name: String, name: String,