feat: support exporting magnets

This commit is contained in:
TwistedUmbrellaX 2024-03-21 18:28:19 -04:00
parent ab7bc15573
commit b3f83816c5
3 changed files with 97 additions and 27 deletions

View file

@ -54,7 +54,6 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.res.ResourcesCompat
import androidx.core.math.MathUtils.clamp
import androidx.core.view.isVisible
import androidx.core.view.WindowCompat
import androidx.core.view.updateLayoutParams
import androidx.lifecycle.lifecycleScope
import androidx.media3.cast.CastPlayer

View file

@ -3,6 +3,8 @@ package ani.dantotsu.media.anime
import android.annotation.SuppressLint
import android.app.Activity
import android.app.AlertDialog
import android.content.ActivityNotFoundException
import android.content.ComponentName
import android.content.DialogInterface
import android.content.Intent
import android.graphics.Color
@ -12,6 +14,8 @@ import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.activity.result.ActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import androidx.fragment.app.activityViewModels
@ -28,10 +32,12 @@ import ani.dantotsu.media.Media
import ani.dantotsu.media.MediaDetailsViewModel
import ani.dantotsu.others.Download.download
import ani.dantotsu.parsers.Subtitle
import ani.dantotsu.parsers.Video
import ani.dantotsu.parsers.VideoExtractor
import ani.dantotsu.parsers.VideoType
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.util.Logger
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@ -212,11 +218,62 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
super.onViewCreated(view, savedInstanceState)
}
private val externalPlayerResult = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()) { result: ActivityResult ->
Logger.log(result.data.toString())
}
private fun exportMagnetIntent(episode: Episode, video: Video) : Intent {
val amnis = "com.amnis"
return Intent(Intent.ACTION_VIEW).apply {
component = ComponentName(amnis, "$amnis.gui.player.PlayerActivity")
data = Uri.parse(video.file.url)
putExtra("title", "${media?.name} - ${episode.title}")
putExtra("position", 0)
putExtra(Intent.EXTRA_RETURN_RESULT, true)
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
putExtra("secure_uri", true)
val headersArray = arrayOf<String>()
video.file.headers.forEach {
headersArray.plus(arrayOf(it.key, it.value))
}
putExtra("headers", headersArray)
}
}
@SuppressLint("UnsafeOptInUsageError")
fun startExoplayer(media: Media) {
prevEpisode = null
dismiss()
episode?.let { ep ->
val video = ep.extractors?.find {
it.server.name == ep.selectedExtractor
}?.videos?.getOrNull(ep.selectedVideo)
video?.file?.url?.let { url ->
if (url.startsWith("magnet:")) {
try {
externalPlayerResult.launch(exportMagnetIntent(ep, video))
} catch (e: ActivityNotFoundException) {
val amnis = "com.amnis"
try {
startActivity(Intent(
Intent.ACTION_VIEW,
Uri.parse("market://details?id=$amnis"))
)
} catch (e: ActivityNotFoundException) {
startActivity(Intent(
Intent.ACTION_VIEW,
Uri.parse("https://play.google.com/store/apps/details?id=$amnis")
))
}
}
return
}
}
}
if (launch!! || model.watchSources!!.isDownloadedSource(media.selected!!.sourceIndex)) {
stopAddingToList()
val intent = Intent(activity, ExoplayerView::class.java)

View file

@ -1,8 +1,11 @@
package ani.dantotsu.parsers
import android.content.ActivityNotFoundException
import android.content.ComponentName
import android.content.ContentResolver
import android.content.ContentValues
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
@ -12,6 +15,7 @@ import android.provider.MediaStore
import ani.dantotsu.FileUrl
import ani.dantotsu.currContext
import ani.dantotsu.media.anime.AnimeNameAdapter
import ani.dantotsu.media.anime.ExoplayerView
import ani.dantotsu.media.manga.ImageData
import ani.dantotsu.media.manga.MangaCache
import ani.dantotsu.snackString
@ -51,6 +55,7 @@ import uy.kohesive.injekt.api.get
import java.io.File
import java.io.FileOutputStream
import java.io.UnsupportedEncodingException
import java.net.MalformedURLException
import java.net.URL
import java.net.URLDecoder
import java.util.regex.Pattern
@ -691,11 +696,14 @@ class VideoServerPassthrough(val videoServer: VideoServer) : VideoExtractor() {
// Check for null video URL
val videoUrl = aniVideo.videoUrl ?: throw Exception("Video URL is null")
var format: VideoType?
try {
val urlObj = URL(videoUrl)
val path = urlObj.path
val query = urlObj.query
var format = getVideoType(path)
format = getVideoType(path)
if (format == null && query != null) {
val queryPairs: List<Pair<String, String>> = query.split("&").map {
@ -721,13 +729,19 @@ class VideoServerPassthrough(val videoServer: VideoServer) : VideoExtractor() {
Logger.log("Unknown video format: $videoUrl")
format = VideoType.CONTAINER
}
} catch (malformed: MalformedURLException) {
if (videoUrl.startsWith("magnet:"))
format = VideoType.CONTAINER
else
throw malformed
}
val headersMap: Map<String, String> =
aniVideo.headers?.toMultimap()?.mapValues { it.value.joinToString() } ?: mapOf()
return Video(
number,
format,
format!!,
FileUrl(videoUrl, headersMap),
if (aniVideo.totalContentLength == 0L) null else aniVideo.bytesDownloaded.toDouble()
)