From defe14f3cccfe4c741ddbfd90ba8ca50ef26bf87 Mon Sep 17 00:00:00 2001 From: zaednasr <75589932+zaednasr@users.noreply.github.com> Date: Sun, 1 Sep 2024 23:00:51 +0200 Subject: [PATCH] 1.7.9.1 fr --- .../database/repository/ResultRepository.kt | 119 +++++++++++++----- .../ytdl/ui/adapter/ActiveDownloadAdapter.kt | 2 +- .../adapter/ActiveDownloadMinifiedAdapter.kt | 2 +- .../java/com/deniscerri/ytdl/util/UiUtil.kt | 22 +--- .../ytdl/util/extractors/IYoutubeExtractor.kt | 18 +++ .../ytdl/util/extractors/PipedApiUtil.kt | 25 ++-- .../util/extractors/newpipe/NewPipeUtil.kt | 24 ++-- app/src/main/res/values/arrays.xml | 8 ++ app/src/main/res/values/strings.xml | 1 + app/src/main/res/xml/general_preferences.xml | 9 ++ .../android/en-US/changelogs/10791.txt | 9 +- 11 files changed, 160 insertions(+), 79 deletions(-) create mode 100644 app/src/main/java/com/deniscerri/ytdl/util/extractors/IYoutubeExtractor.kt diff --git a/app/src/main/java/com/deniscerri/ytdl/database/repository/ResultRepository.kt b/app/src/main/java/com/deniscerri/ytdl/database/repository/ResultRepository.kt index 6de60d3b..c091935b 100644 --- a/app/src/main/java/com/deniscerri/ytdl/database/repository/ResultRepository.kt +++ b/app/src/main/java/com/deniscerri/ytdl/database/repository/ResultRepository.kt @@ -16,6 +16,8 @@ import com.deniscerri.ytdl.util.Extensions.isYoutubeChannelURL import com.deniscerri.ytdl.util.Extensions.isYoutubeURL import com.deniscerri.ytdl.util.FileUtil import com.deniscerri.ytdl.util.extractors.GoogleApiUtil +import com.deniscerri.ytdl.util.extractors.IYoutubeExtractor +import com.deniscerri.ytdl.util.extractors.PipedApiUtil import com.deniscerri.ytdl.util.extractors.newpipe.NewPipeUtil import com.deniscerri.ytdl.util.extractors.YTDLPUtil import com.deniscerri.ytdl.util.extractors.YoutubeApiUtil @@ -33,12 +35,20 @@ class ResultRepository(private val resultDao: ResultDao, private val context: Co } private val youtubeApiUtil = YoutubeApiUtil(context) - //private val pipedApiUtil = PipedApiUtil(context) - private val newPipeUtil = NewPipeUtil(context) private val ytdlpUtil = YTDLPUtil(context) - + private var youtubeExtractor: IYoutubeExtractor? = null + private var pipedUtil = PipedApiUtil(context) + private var newPipeUtil = NewPipeUtil(context) private val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) + init { + youtubeExtractor = when(YoutubeExtractors.valueOf(sharedPreferences.getString("data_fetching_extractor_youtube", "PIPED")!!)) { + YoutubeExtractors.PIPED -> PipedApiUtil(context) + YoutubeExtractors.NEWPIPE -> NewPipeUtil(context) + else -> null + } + } + enum class SourceType { YOUTUBE_VIDEO, YOUTUBE_PLAYLIST, @@ -47,6 +57,12 @@ class ResultRepository(private val resultDao: ResultDao, private val context: Co YT_DLP } + enum class YoutubeExtractors { + YT_DLP, + PIPED, + NEWPIPE + } + suspend fun insert(it: ResultItem){ resultDao.insert(it) } @@ -60,7 +76,7 @@ class ResultRepository(private val resultDao: ResultDao, private val context: Co val items = if (sharedPreferences.getString("api_key", "")!!.isNotBlank()) { youtubeApiUtil.getTrending() }else{ - newPipeUtil.getTrending() + youtubeExtractor?.getTrending() ?: listOf() } itemCount.value = items.size @@ -72,27 +88,27 @@ class ResultRepository(private val resultDao: ResultDao, private val context: Co } fun getStreamingUrlAndChapters(url: String) : Pair, List?> { - val newPipeTrial = newPipeUtil.getStreamingUrlAndChapters(url) - if (newPipeTrial.isFailure){ + val extractorsTrial = youtubeExtractor?.getStreamingUrlAndChapters(url) ?: Result.failure(Throwable()) + if (extractorsTrial.isFailure){ val res = ytdlpUtil.getStreamingUrlAndChapters(url) return res.getOrDefault(Pair(listOf(""), null)) } - return newPipeTrial.getOrNull()!! + return extractorsTrial.getOrNull()!! } suspend fun search(inputQuery: String, resetResults: Boolean, addToResults: Boolean) : ArrayList{ if (resetResults) deleteAll() val res = when(sharedPreferences.getString("search_engine", "ytsearch")) { - "ytsearch" -> newPipeUtil.search(inputQuery) - "ytsearchmusic" -> newPipeUtil.searchMusic(inputQuery) + "ytsearch" -> youtubeExtractor?.search(inputQuery) + "ytsearchmusic" -> youtubeExtractor?.searchMusic(inputQuery) else -> Result.failure(Throwable()) } - val items = if (res.isSuccess) { + val items = if (res?.isSuccess == true) { res.getOrNull()!! }else{ - //fallback if newpipe failed + //fallback to yt-dlp ytdlpUtil.getFromYTDL(inputQuery) } @@ -108,10 +124,10 @@ class ResultRepository(private val resultDao: ResultDao, private val context: Co private suspend fun getYoutubeVideo(inputQuery: String, resetResults: Boolean, addToResults: Boolean) : List{ val theURL = inputQuery.replace("\\?list.*".toRegex(), "") - val newPipeRes = newPipeUtil.getVideoData(theURL) + val ytExtractorRes = youtubeExtractor?.getVideoData(theURL) - val res = if (newPipeRes.isSuccess) { - newPipeRes.getOrNull()!! + val res = if (ytExtractorRes?.isSuccess == true) { + ytExtractorRes.getOrNull()!! }else{ ytdlpUtil.getFromYTDL(inputQuery) } @@ -136,7 +152,7 @@ class ResultRepository(private val resultDao: ResultDao, private val context: Co val playlistURL = "https://youtube.com/playlist?list=${id}" if (resetResults) deleteAll() val items = mutableListOf() - val newPipeResult = newPipeUtil.getPlaylistData(playlistURL) { + val ytExtractorResult = youtubeExtractor?.getPlaylistData(playlistURL) { if (addToResults){ runBlocking { val ids = resultDao.insertMultiple(it) @@ -148,8 +164,8 @@ class ResultRepository(private val resultDao: ResultDao, private val context: Co items.addAll(it) } - val response = if (newPipeResult.isSuccess){ - newPipeResult.getOrElse { items } + val response = if (ytExtractorResult?.isSuccess == true){ + ytExtractorResult.getOrElse { items } }else{ val res = ytdlpUtil.getFromYTDL(playlistURL) val ids = resultDao.insertMultiple(res) @@ -166,7 +182,7 @@ class ResultRepository(private val resultDao: ResultDao, private val context: Co private suspend fun getYoutubeChannel(url: String, resetResults: Boolean, addToResults: Boolean) : List{ if (resetResults) deleteAll() val items = mutableListOf() - val newPipeResult = newPipeUtil.getChannelData(url) { + val ytExtractorResult = youtubeExtractor?.getChannelData(url) { if (addToResults){ runBlocking { val ids = resultDao.insertMultiple(it) @@ -178,8 +194,8 @@ class ResultRepository(private val resultDao: ResultDao, private val context: Co items.addAll(it) } - val response = if (newPipeResult.isSuccess){ - newPipeResult.getOrElse { items } + val response = if (ytExtractorResult?.isSuccess == true){ + ytExtractorResult.getOrElse { items } }else{ val res = ytdlpUtil.getFromYTDL(url) val ids = resultDao.insertMultiple(res) @@ -214,12 +230,25 @@ class ResultRepository(private val resultDao: ResultDao, private val context: Co fun getFormats(url: String, source : String? = null) : List { val formatSource = source ?: sharedPreferences.getString("formats_source", "yt-dlp") - val res = if (url.isYoutubeURL() && formatSource == "piped") { - val tmpRes = newPipeUtil.getFormats(url) - if (tmpRes.isFailure && source != null) { - Result.success(listOf()) - }else{ - tmpRes + val res = if (url.isYoutubeURL()) { + when(formatSource) { + "piped" -> { + val tmpRes = pipedUtil.getFormats(url) + if (tmpRes.isFailure && source != null) { + Result.success(listOf()) + }else{ + tmpRes + } + } + "newpipe" -> { + val tmpRes = newPipeUtil.getFormats(url) + if (tmpRes.isFailure && source != null) { + Result.success(listOf()) + }else{ + tmpRes + } + } + else -> Result.failure(Throwable()) } }else{ Result.failure(Throwable()) @@ -235,18 +264,40 @@ class ResultRepository(private val resultDao: ResultDao, private val context: Co suspend fun getFormatsMultiple(urls: List, source: String? = null, progress: (progress: ResultViewModel.MultipleFormatProgress) -> Unit) : MutableList> { val formatSource = source ?: sharedPreferences.getString("formats_source", "yt-dlp") val allYoutubeLinks = urls.all { it.isYoutubeURL() } - if (allYoutubeLinks && formatSource == "piped") { - val res = newPipeUtil.getFormatsForAll(urls) { - progress(it) + + val res = when(formatSource) { + "piped" -> { + if (!allYoutubeLinks) { + Result.failure(Throwable()) + }else{ + val res = pipedUtil.getFormatsForAll(urls) { + progress(it) + } + res + } + } + "newpipe" -> { + val res = newPipeUtil.getFormatsForAll(urls) { + progress(it) + } + res + } + else -> { + Result.failure(Throwable()) + } + } + + if (res.isSuccess) { return res.getOrElse { mutableListOf() } } - else { - val res = ytdlpUtil.getFormatsForAll(urls) { - progress(it) - } - return res.getOrElse { mutableListOf() } + + //last fallback + val ytdlpRes = ytdlpUtil.getFormatsForAll(urls) { + progress(it) } + + return ytdlpRes.getOrElse { mutableListOf() } } suspend fun delete(item: ResultItem){ diff --git a/app/src/main/java/com/deniscerri/ytdl/ui/adapter/ActiveDownloadAdapter.kt b/app/src/main/java/com/deniscerri/ytdl/ui/adapter/ActiveDownloadAdapter.kt index effbbb5e..946ff86f 100644 --- a/app/src/main/java/com/deniscerri/ytdl/ui/adapter/ActiveDownloadAdapter.kt +++ b/app/src/main/java/com/deniscerri/ytdl/ui/adapter/ActiveDownloadAdapter.kt @@ -106,7 +106,7 @@ class ActiveDownloadAdapter(onItemClickListener: OnItemClickListener, activity: sideDetails.add(item.container.uppercase().ifEmpty { item.format.container.uppercase() }) val fileSize = FileUtil.convertFileSize(item.format.filesize) - if (fileSize != "?") sideDetails.add(fileSize) + if (fileSize != "?" && item.downloadSections.isBlank()) sideDetails.add(fileSize) formatDetailsChip.text = sideDetails.filter { it.isNotBlank() }.joinToString(" ยท ") //OUTPUT diff --git a/app/src/main/java/com/deniscerri/ytdl/ui/adapter/ActiveDownloadMinifiedAdapter.kt b/app/src/main/java/com/deniscerri/ytdl/ui/adapter/ActiveDownloadMinifiedAdapter.kt index 1a4ba055..c7421c4b 100644 --- a/app/src/main/java/com/deniscerri/ytdl/ui/adapter/ActiveDownloadMinifiedAdapter.kt +++ b/app/src/main/java/com/deniscerri/ytdl/ui/adapter/ActiveDownloadMinifiedAdapter.kt @@ -125,7 +125,7 @@ class ActiveDownloadMinifiedAdapter(onItemClickListener: OnItemClickListener, ac val fileSize = card.findViewById(R.id.file_size) val fileSizeReadable = FileUtil.convertFileSize(item.format.filesize) - if (fileSizeReadable == "?") fileSize.visibility = View.GONE + if (fileSizeReadable == "?" && item.downloadSections.isNotBlank()) fileSize.visibility = View.GONE else fileSize.text = fileSizeReadable val menu = card.findViewById(R.id.options) diff --git a/app/src/main/java/com/deniscerri/ytdl/util/UiUtil.kt b/app/src/main/java/com/deniscerri/ytdl/util/UiUtil.kt index a9d50b5b..d8025513 100644 --- a/app/src/main/java/com/deniscerri/ytdl/util/UiUtil.kt +++ b/app/src/main/java/com/deniscerri/ytdl/util/UiUtil.kt @@ -1571,12 +1571,10 @@ object UiUtil { fun handleNoResults(context: Activity, message: String, continueAnyway: Boolean = false, continued: () -> Unit, closed: () -> Unit) { - val updateYTDLP = "${context.getString(R.string.update_ytdl)}" - .parseAsHtml(HtmlCompat.FROM_HTML_MODE_COMPACT) val errDialog = MaterialAlertDialogBuilder(context) .setTitle(R.string.no_results) - .setMessage(message + "\n\n" + updateYTDLP) + .setMessage(message) errDialog.setPositiveButton(R.string.copy_log) { d:DialogInterface?, _:Int -> val clipboard: ClipboardManager = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager @@ -1594,23 +1592,7 @@ object UiUtil { closed() } - val dialog = errDialog.show() - dialog.findViewById(android.R.id.message)?.setOnClickListener { - dialog.cancel() - CoroutineScope(Dispatchers.IO).launch { - val res = UpdateUtil(context).updateYoutubeDL() - if (res == YoutubeDL.UpdateStatus.DONE) { - val version = YoutubeDL.getInstance().version(context) - withContext(Dispatchers.Main){ - Toast.makeText(context, context.getString(R.string.ytld_update_success) + " [${version}]", Toast.LENGTH_LONG).show() - } - }else { - withContext(Dispatchers.Main) { - Toast.makeText(context, context.getString(R.string.you_are_in_latest_version), Toast.LENGTH_SHORT).show() - } - } - } - } + errDialog.show() } fun showErrorDialog(context: Context, it: String){ diff --git a/app/src/main/java/com/deniscerri/ytdl/util/extractors/IYoutubeExtractor.kt b/app/src/main/java/com/deniscerri/ytdl/util/extractors/IYoutubeExtractor.kt new file mode 100644 index 00000000..f9a417fb --- /dev/null +++ b/app/src/main/java/com/deniscerri/ytdl/util/extractors/IYoutubeExtractor.kt @@ -0,0 +1,18 @@ +package com.deniscerri.ytdl.util.extractors + +import com.deniscerri.ytdl.database.models.ChapterItem +import com.deniscerri.ytdl.database.models.Format +import com.deniscerri.ytdl.database.models.ResultItem +import com.deniscerri.ytdl.database.viewmodel.ResultViewModel + +interface IYoutubeExtractor { + fun getVideoData(url: String) : Result> + fun getFormats(url: String) : Result> + fun getFormatsForAll(urls: List, progress: (progress: ResultViewModel.MultipleFormatProgress) -> Unit) : Result>> + fun search(query: String) : Result> + fun searchMusic(query: String) : Result> + fun getStreamingUrlAndChapters(url: String) : Result, List?>> + suspend fun getPlaylistData(id: String, progress: (pagedResults: MutableList) -> Unit) : Result> + fun getTrending() : ArrayList + fun getChannelData(url: String, progress: (pagedResults: MutableList) -> Unit) : Result> +} \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdl/util/extractors/PipedApiUtil.kt b/app/src/main/java/com/deniscerri/ytdl/util/extractors/PipedApiUtil.kt index 38086d05..c56d6c71 100644 --- a/app/src/main/java/com/deniscerri/ytdl/util/extractors/PipedApiUtil.kt +++ b/app/src/main/java/com/deniscerri/ytdl/util/extractors/PipedApiUtil.kt @@ -19,7 +19,7 @@ import java.util.ArrayList import java.util.Locale import kotlin.coroutines.cancellation.CancellationException -class PipedApiUtil(private val context: Context) { +class PipedApiUtil(context: Context) : IYoutubeExtractor { private var sharedPreferences: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) private val countryCode = sharedPreferences.getString("locale", "")!!.ifEmpty { "US" } private val defaultPipedURL = "https://pipedapi.kavin.rocks/" @@ -38,7 +38,7 @@ class PipedApiUtil(private val context: Context) { return listOf() } - fun getVideoData(url : String) : Result> { + override fun getVideoData(url : String) : Result> { val id = getIDFromYoutubeURL(url) val res = NetworkUtil.genericRequest("$pipedURL/streams/$id") if (res.length() == 0) { @@ -49,7 +49,7 @@ class PipedApiUtil(private val context: Context) { return Result.success(listOf(vid)) } - fun getFormats(url: String) : Result > { + override fun getFormats(url: String) : Result > { try { val id = getIDFromYoutubeURL(url) val res = NetworkUtil.genericRequest("$pipedURL/streams/$id") @@ -67,7 +67,7 @@ class PipedApiUtil(private val context: Context) { } } - fun getFormatsForAll(urls: List, progress: (progress: ResultViewModel.MultipleFormatProgress) -> Unit) : Result>> { + override fun getFormatsForAll(urls: List, progress: (progress: ResultViewModel.MultipleFormatProgress) -> Unit) : Result>> { return kotlin.runCatching { val formatCollection = mutableListOf>() urls.forEach { url -> @@ -88,7 +88,7 @@ class PipedApiUtil(private val context: Context) { } @Throws(JSONException::class) - fun search(query: String): Result> { + override fun search(query: String): Result> { val items = arrayListOf() val data = NetworkUtil.genericRequest("$pipedURL/search?q=$query&filter=videos®ion=${countryCode}") val dataArray = data.getJSONArray("items") @@ -107,7 +107,7 @@ class PipedApiUtil(private val context: Context) { } @Throws(JSONException::class) - fun searchMusic(query: String): Result> { + override fun searchMusic(query: String): Result> { val items = arrayListOf() val data = NetworkUtil.genericRequest("$pipedURL/search?q=$query=&filter=music_songs®ion=${countryCode}") val dataArray = data.getJSONArray("items") @@ -125,7 +125,7 @@ class PipedApiUtil(private val context: Context) { return Result.success(items) } - fun getStreamingUrlAndChapters(url: String) : Result, List?>> { + override fun getStreamingUrlAndChapters(url: String) : Result, List?>> { val id = getIDFromYoutubeURL(url) val res = NetworkUtil.genericRequest("$pipedURL/streams/$id") if (res.length() == 0) { @@ -140,7 +140,7 @@ class PipedApiUtil(private val context: Context) { } } - suspend fun getPlaylistData(id: String, progress: (pagedResults: MutableList) -> Unit) : Result> { + override suspend fun getPlaylistData(id: String, progress: (pagedResults: MutableList) -> Unit) : Result> { val totalItems = mutableListOf() val nextPageToken = "" var playlistName = "" @@ -194,7 +194,7 @@ class PipedApiUtil(private val context: Context) { } - fun getTrending(): ArrayList { + override fun getTrending(): ArrayList { val items = arrayListOf() val url = "$pipedURL/trending?region=${countryCode}" val res = NetworkUtil.genericArrayRequest(url) @@ -209,6 +209,13 @@ class PipedApiUtil(private val context: Context) { return items } + override fun getChannelData( + url: String, + progress: (pagedResults: MutableList) -> Unit + ): Result> { + return Result.failure(Throwable("Not yet implemented / supported?")) + } + private fun createVideoFromPipedJSON(obj: JSONObject, url: String, ignoreFormatPreference : Boolean = false): ResultItem? { var video: ResultItem? = null try { diff --git a/app/src/main/java/com/deniscerri/ytdl/util/extractors/newpipe/NewPipeUtil.kt b/app/src/main/java/com/deniscerri/ytdl/util/extractors/newpipe/NewPipeUtil.kt index 02c70e71..038abfef 100644 --- a/app/src/main/java/com/deniscerri/ytdl/util/extractors/newpipe/NewPipeUtil.kt +++ b/app/src/main/java/com/deniscerri/ytdl/util/extractors/newpipe/NewPipeUtil.kt @@ -9,6 +9,7 @@ import com.deniscerri.ytdl.database.models.Format import com.deniscerri.ytdl.database.models.ResultItem import com.deniscerri.ytdl.database.viewmodel.ResultViewModel import com.deniscerri.ytdl.util.Extensions.toStringDuration +import com.deniscerri.ytdl.util.extractors.IYoutubeExtractor import com.google.gson.Gson import kotlinx.serialization.Serializer import okhttp3.OkHttpClient @@ -38,7 +39,7 @@ import org.schabi.newpipe.extractor.utils.ExtractorHelper import java.util.Locale import kotlin.coroutines.cancellation.CancellationException -class NewPipeUtil(context: Context) { +class NewPipeUtil(context: Context) : IYoutubeExtractor { private var sharedPreferences: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) private val countryCode = sharedPreferences.getString("locale", "")!!.ifEmpty { "US" } private val language = sharedPreferences.getString("app_language", "")!!.ifEmpty { "en" } @@ -46,7 +47,7 @@ class NewPipeUtil(context: Context) { NewPipe.init(NewPipeDownloaderImpl(OkHttpClient.Builder()), Localization(language, countryCode)) } - fun getVideoData(url : String) : Result> { + override fun getVideoData(url : String) : Result> { try { val streamInfo = StreamInfo.getInfo(NewPipe.getService(ServiceList.YouTube.serviceId), url) val vid = createVideoFromStream(streamInfo, url) ?: return Result.failure(Throwable()) @@ -56,7 +57,7 @@ class NewPipeUtil(context: Context) { } } - fun getFormats(url: String) : Result > { + override fun getFormats(url: String) : Result > { try { val streamInfo = StreamInfo.getInfo(NewPipe.getService(ServiceList.YouTube.serviceId), url) val vid = createVideoFromStream(streamInfo, url) @@ -68,7 +69,7 @@ class NewPipeUtil(context: Context) { } } - fun getFormatsForAll(urls: List, progress: (progress: ResultViewModel.MultipleFormatProgress) -> Unit) : Result>> { + override fun getFormatsForAll(urls: List, progress: (progress: ResultViewModel.MultipleFormatProgress) -> Unit) : Result>> { return kotlin.runCatching { val formatCollection = mutableListOf>() urls.forEach { url -> @@ -85,7 +86,7 @@ class NewPipeUtil(context: Context) { } @Throws(JSONException::class) - fun search(query: String): Result> { + override fun search(query: String): Result> { try { val items = arrayListOf() val res = SearchInfo.getInfo(NewPipe.getService(ServiceList.YouTube.serviceId), @@ -111,7 +112,7 @@ class NewPipeUtil(context: Context) { } @Throws(JSONException::class) - fun searchMusic(query: String): Result> { + override fun searchMusic(query: String): Result> { try { val items = arrayListOf() val res = SearchInfo.getInfo(NewPipe.getService(ServiceList.YouTube.serviceId), @@ -135,7 +136,7 @@ class NewPipeUtil(context: Context) { } } - fun getStreamingUrlAndChapters(url: String) : Result, List?>> { + override fun getStreamingUrlAndChapters(url: String) : Result, List?>> { try { val streamInfo = StreamInfo.getInfo(NewPipe.getService(ServiceList.YouTube.serviceId), url) val item = createVideoFromStream(streamInfo, url) @@ -148,7 +149,7 @@ class NewPipeUtil(context: Context) { } } - fun getChannelData(url: String, progress: (pagedResults: MutableList) -> Unit) : Result> { + override fun getChannelData(url: String, progress: (pagedResults: MutableList) -> Unit) : Result> { try { val req = ChannelInfo.getInfo(ServiceList.YouTube, url) println(Gson().toJson(req)) @@ -214,7 +215,7 @@ class NewPipeUtil(context: Context) { } } - fun getPlaylistData(playlistURL: String, progress: (pagedResults: MutableList) -> Unit) : Result> { + override suspend fun getPlaylistData(playlistURL: String, progress: (pagedResults: MutableList) -> Unit) : Result> { try { val totalItems = mutableListOf() var nextPage : Page? = null @@ -261,7 +262,7 @@ class NewPipeUtil(context: Context) { } - fun getTrending(): ArrayList { + override fun getTrending(): ArrayList { try { val items = arrayListOf() val info = KioskInfo.getInfo(NewPipe.getService(ServiceList.YouTube.serviceId), "https://www.youtube.com/feed/trending") @@ -434,7 +435,4 @@ class NewPipeUtil(context: Context) { query = el[0] return query!! } - - - } \ No newline at end of file diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 8e8108ab..6337c79b 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -235,12 +235,14 @@ + Piped NewPipe yt-dlp piped + newpipe yt-dlp @@ -1494,4 +1496,10 @@ monthly + + YT_DLP + NEWPIPE + PIPED + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 173158cf..39ba741c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -421,4 +421,5 @@ Continue Anyway Use Playlist Name as Album Metadata If Album Metadata is not present, use playlist name instead + Data Fetching Extractor (YouTube) \ No newline at end of file diff --git a/app/src/main/res/xml/general_preferences.xml b/app/src/main/res/xml/general_preferences.xml index e6b418d7..910fca7b 100644 --- a/app/src/main/res/xml/general_preferences.xml +++ b/app/src/main/res/xml/general_preferences.xml @@ -84,6 +84,15 @@ android:summary="@string/api_key_summary" app:title="@string/api_key" /> + +