From 0b944d108a7c215b9e26138a7cb62f7ba2a5be8a Mon Sep 17 00:00:00 2001 From: deniscerri <64997243+deniscerri@users.noreply.github.com> Date: Wed, 4 Dec 2024 20:48:57 +0100 Subject: [PATCH] Extra Command Bug Fixes --- .github/workflows/android.yml | 67 +++++++++++++++++-- .../ytdl/database/dao/DownloadDao.kt | 3 + .../database/repository/HistoryRepository.kt | 15 +++++ .../database/viewmodel/DownloadViewModel.kt | 4 ++ .../database/viewmodel/HistoryViewModel.kt | 4 ++ .../DownloadMultipleBottomSheetDialog.kt | 5 ++ .../ytdl/ui/downloads/HistoryFragment.kt | 11 ++- .../ui/downloads/SavedDownloadsFragment.kt | 8 +++ .../ytdl/util/extractors/YTDLPUtil.kt | 24 +++---- .../deniscerri/ytdl/work/DownloadWorker.kt | 17 +++-- app/src/main/res/menu/saved_header_menu.xml | 5 ++ 11 files changed, 140 insertions(+), 23 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index b160ebd1..ceb0208f 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -12,9 +12,9 @@ on: jobs: build: - runs-on: ubuntu-latest - + permissions: + contents: write # for deleting/creating a pre-release steps: - uses: actions/checkout@v3 - name: set up JDK 17 @@ -61,6 +61,8 @@ jobs: with: name: YTDLnis APK release generated path: ${{ env.main_project_module }}/build/outputs/apk/release/ + + # Send Message To Telegram - name: send telegram message on push or pull continue-on-error: true uses: appleboy/telegram-action@master @@ -70,7 +72,64 @@ jobs: message: | ${{ github.actor }} created commit: Commit message: ${{ github.event.commits[0].message }} - Repository: ${{ github.repository }} - See changes: https://github.com/${{ github.repository }}/commit/${{github.sha}} + + # Start Creating Pre-Release + - name: Start Pre-Release + uses: actions/checkout@v4 + with: + persist-credentials: false + # returns null if no pre-release exists + - name: Get Commit SHA of Latest Pre-release + run: | + # Install Required Packages + sudo apt-get updated + sudo apt-get install -y curl jq + echo "COMMIT_SHA_TAG=$(jq -r 'map(select(.prerelease)) | first | .tag_name' <<< $(curl -s https://api.github.com/repos/deniscerri/ytdlnis/releases))" >> $GITHUB_ENV + + - run: gh release delete ${{ env.COMMIT_SHA_TAG }} --cleanup-tag + if: (env.COMMIT_SHA_TAG != 'null' && contains("Auto-Release", env.COMMIT_SHA_TAG)) + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # Make sure that an old ci that still runs on main doesn't recreate a prerelease + - name: Check Pullable Commits + id: check_commits + run: | + git fetch + CHANGES=$(git rev-list HEAD..origin/main --count) + echo "CHANGES=$CHANGES" >> $GITHUB_ENV + + - name: Get Release Name + id: get_last_release_tag + run: | + LASTRELEASE=$(curl "https://api.github.com/repos/deniscerri/ytdlnis/releases/latest") + ISPRERELEASE=$(echo $LASTRELEASE | jq -r '.prerelease') + NEWRELEASENAME=$(echo $LASTRELEASE | jq -r '.name') + if ! $ISPRERELEASE; then NEWRELEASENAME=$(echo $NEWRELEASENAME'.1'); else NEWRELEASENAME=$(echo $NEWRELEASENAME | sed -E 's/(.*\.)([0-9]+)$/echo "\1$((\2 + 1))"/e'); fi + echo "NEWRELEASENAME=$NEWRELEASENAME" >> $GITHUB_ENV + + - name: Get last commit SHA + id: last_commit + run: echo "COMMIT_SHA=$(git rev-parse HEAD | cut -c 1-8)" >> $GITHUB_ENV + + - name: Get commmit date + id: commit_date + run: echo "COMMIT_DATE=$(git show -s --date=format:'%Y%m%d' --format=%cd HEAD)" >> $GITHUB_ENV + + + # Create a new pre-release, the other upload_binaries.yml will upload the binaries + # to this pre-release. + - name: Create Prerelease + if: github.ref.name == 'main' && env.CHANGES == '0' + uses: softprops/action-gh-release@4634c16e79c963813287e889244c50009e7f0981 + with: + name: ${{ env.NEWRELEASENAME }} [Auto-Release] [${{ env.COMMIT_DATE }}-${{ env.COMMIT_SHA }}] + tag_name: v${{ env.NEWRELEASENAME }}-beta + body: ${{ github.event.commits[0].message }} + prerelease: true + files: | + ${{ env.main_project_module }}/build/outputs/apk/release/* + ${{ env.main_project_module }}/build/outputs/apk/debug/* + diff --git a/app/src/main/java/com/deniscerri/ytdl/database/dao/DownloadDao.kt b/app/src/main/java/com/deniscerri/ytdl/database/dao/DownloadDao.kt index b98153cd..8c522a42 100644 --- a/app/src/main/java/com/deniscerri/ytdl/database/dao/DownloadDao.kt +++ b/app/src/main/java/com/deniscerri/ytdl/database/dao/DownloadDao.kt @@ -270,6 +270,9 @@ interface DownloadDao { @Query("Select url from downloads where status in (:status)") fun getURLsByStatus(status: List) : List + @Query("Select id from downloads where status in (:status)") + fun getIDsByStatus(status: List) : List + @Query("Select url from downloads where id in (:ids)") fun getURLsByID(ids: List) : List diff --git a/app/src/main/java/com/deniscerri/ytdl/database/repository/HistoryRepository.kt b/app/src/main/java/com/deniscerri/ytdl/database/repository/HistoryRepository.kt index 79c83095..f9c3023a 100644 --- a/app/src/main/java/com/deniscerri/ytdl/database/repository/HistoryRepository.kt +++ b/app/src/main/java/com/deniscerri/ytdl/database/repository/HistoryRepository.kt @@ -1,5 +1,6 @@ package com.deniscerri.ytdl.database.repository +import androidx.compose.runtime.internal.isLiveLiteralsEnabled import androidx.paging.Pager import androidx.paging.PagingConfig import androidx.paging.PagingData @@ -13,6 +14,7 @@ import com.deniscerri.ytdl.util.FileUtil import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.map +import java.io.File class HistoryRepository(private val historyDao: HistoryDao) { val items : Flow> = historyDao.getAllHistory() @@ -113,6 +115,19 @@ class HistoryRepository(private val historyDao: HistoryDao) { historyDao.deleteAllByIDs(ids) } + suspend fun deleteAllWithIDsCheckFiles(ids: List){ + val idsToDelete = mutableListOf() + historyDao.getAllHistoryByIDs(ids).forEach { item -> + val filesNotPresent = item.downloadPath.all { !File(it).exists() && it.isNotBlank()} + if (filesNotPresent) { + idsToDelete.add(item.id) + } + } + if (idsToDelete.isNotEmpty()) { + historyDao.deleteAllByIDs(idsToDelete) + } + } + data class HistoryItemDownloadPaths( val downloadPath: List ) diff --git a/app/src/main/java/com/deniscerri/ytdl/database/viewmodel/DownloadViewModel.kt b/app/src/main/java/com/deniscerri/ytdl/database/viewmodel/DownloadViewModel.kt index 656ea5aa..68956377 100644 --- a/app/src/main/java/com/deniscerri/ytdl/database/viewmodel/DownloadViewModel.kt +++ b/app/src/main/java/com/deniscerri/ytdl/database/viewmodel/DownloadViewModel.kt @@ -1236,6 +1236,10 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel return dao.getURLsByStatus(list.map { it.toString() }) } + fun getIDsByStatus(list: List) : List { + return dao.getIDsByStatus(list.map { it.toString() }) + } + fun getURLsByIds(list: List) : List { return dao.getURLsByID(list) } diff --git a/app/src/main/java/com/deniscerri/ytdl/database/viewmodel/HistoryViewModel.kt b/app/src/main/java/com/deniscerri/ytdl/database/viewmodel/HistoryViewModel.kt index dc6d2bd4..5d271bc3 100644 --- a/app/src/main/java/com/deniscerri/ytdl/database/viewmodel/HistoryViewModel.kt +++ b/app/src/main/java/com/deniscerri/ytdl/database/viewmodel/HistoryViewModel.kt @@ -178,6 +178,10 @@ class HistoryViewModel(application: Application) : AndroidViewModel(application) repository.deleteAllWithIDs(ids, deleteFile) } + fun deleteAllWithIDsCheckFiles(ids: List) = viewModelScope.launch(Dispatchers.IO) { + repository.deleteAllWithIDsCheckFiles(ids) + } + fun getDownloadPathsFromIDs(ids: List) : List> { return repository.getDownloadPathsFromIDs(ids) } diff --git a/app/src/main/java/com/deniscerri/ytdl/ui/downloadcard/DownloadMultipleBottomSheetDialog.kt b/app/src/main/java/com/deniscerri/ytdl/ui/downloadcard/DownloadMultipleBottomSheetDialog.kt index 59dc57b3..33784df2 100644 --- a/app/src/main/java/com/deniscerri/ytdl/ui/downloadcard/DownloadMultipleBottomSheetDialog.kt +++ b/app/src/main/java/com/deniscerri/ytdl/ui/downloadcard/DownloadMultipleBottomSheetDialog.kt @@ -86,6 +86,7 @@ class DownloadMultipleBottomSheetDialog : BottomSheetDialogFragment(), Configure private lateinit var parentActivity: BaseActivity private lateinit var currentDownloadIDs: List + private lateinit var currentHistoryIDs: List private var processingItemsCount : Int = 0 private lateinit var containerBtn : MenuItem @@ -100,6 +101,7 @@ class DownloadMultipleBottomSheetDialog : BottomSheetDialogFragment(), Configure sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext()) currentDownloadIDs = arguments?.getLongArray("currentDownloadIDs")?.toList() ?: listOf() + currentHistoryIDs = arguments?.getLongArray("currentHistoryIDs")?.toList() ?: listOf() processingItemsCount = currentDownloadIDs.size } @@ -225,6 +227,7 @@ class DownloadMultipleBottomSheetDialog : BottomSheetDialogFragment(), Configure lifecycleScope.launch { withContext(Dispatchers.IO){ downloadViewModel.deleteAllWithID(currentDownloadIDs) + historyViewModel.deleteAllWithIDsCheckFiles(currentHistoryIDs) val result = downloadViewModel.updateProcessingDownloadTimeAndQueueScheduled(cal.timeInMillis) if (result.message.isNotBlank()){ lifecycleScope.launch { @@ -248,6 +251,7 @@ class DownloadMultipleBottomSheetDialog : BottomSheetDialogFragment(), Configure lifecycleScope.launch { withContext(Dispatchers.IO){ downloadViewModel.deleteAllWithID(currentDownloadIDs) + historyViewModel.deleteAllWithIDsCheckFiles(currentHistoryIDs) val result = downloadViewModel.queueProcessingDownloads() if (result.message.isNotBlank()){ lifecycleScope.launch { @@ -274,6 +278,7 @@ class DownloadMultipleBottomSheetDialog : BottomSheetDialogFragment(), Configure withContext(Dispatchers.IO){ downloadViewModel.deleteAllWithID(currentDownloadIDs) downloadViewModel.moveProcessingToSavedCategory() + historyViewModel.deleteAllWithIDsCheckFiles(currentHistoryIDs) } downloadViewModel.processingItemsJob?.cancel(CancellationException()) diff --git a/app/src/main/java/com/deniscerri/ytdl/ui/downloads/HistoryFragment.kt b/app/src/main/java/com/deniscerri/ytdl/ui/downloads/HistoryFragment.kt index db5f7151..e1470732 100644 --- a/app/src/main/java/com/deniscerri/ytdl/ui/downloads/HistoryFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdl/ui/downloads/HistoryFragment.kt @@ -500,19 +500,22 @@ class HistoryFragment : Fragment(), HistoryPaginatedAdapter.OnItemClickListener{ } - override fun onCardClick(itemID: Long, isPresent: Boolean) { + override fun onCardClick(itemID: Long, filePresent: Boolean) { lifecycleScope.launch { val item = withContext(Dispatchers.IO){ historyViewModel.getByID(itemID) } - UiUtil.showHistoryItemDetailsCard(item, requireActivity(), isPresent, + UiUtil.showHistoryItemDetailsCard(item, requireActivity(), filePresent, removeItem = { it, deleteFile -> historyViewModel.delete(it, deleteFile) }, redownloadItem = { val downloadItem = downloadViewModel.createDownloadItemFromHistory(it) runBlocking{ + if (!filePresent) { + historyViewModel.delete(it, false) + } downloadViewModel.queueDownloads(listOf(downloadItem)) } historyViewModel.delete(it, false) @@ -651,7 +654,9 @@ class HistoryFragment : Fragment(), HistoryPaginatedAdapter.OnItemClickListener{ downloadViewModel.turnHistoryItemsToProcessingDownloads(selectedObjects, downloadNow = !showDownloadCard) actionMode?.finish() if (showDownloadCard){ - findNavController().navigate(R.id.downloadMultipleBottomSheetDialog2) + val bundle = Bundle() + bundle.putLongArray("currentHistoryIDs", selectedObjects.toLongArray()) + findNavController().navigate(R.id.downloadMultipleBottomSheetDialog2, bundle) } } } diff --git a/app/src/main/java/com/deniscerri/ytdl/ui/downloads/SavedDownloadsFragment.kt b/app/src/main/java/com/deniscerri/ytdl/ui/downloads/SavedDownloadsFragment.kt index 119f11ac..117b4d47 100644 --- a/app/src/main/java/com/deniscerri/ytdl/ui/downloads/SavedDownloadsFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdl/ui/downloads/SavedDownloadsFragment.kt @@ -118,6 +118,14 @@ class SavedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLis popup.menuInflater.inflate(R.menu.saved_header_menu, popup.menu) popup.setOnMenuItemClickListener { m -> when(m.itemId){ + R.id.download_all -> { + lifecycleScope.launch { + val ids = withContext(Dispatchers.IO) { + downloadViewModel.getIDsByStatus(listOf(DownloadRepository.Status.Saved)) + } + downloadViewModel.reQueueDownloadItems(ids) + } + } R.id.delete_all -> { UiUtil.showGenericDeleteAllDialog(requireContext()) { downloadViewModel.deleteSaved() diff --git a/app/src/main/java/com/deniscerri/ytdl/util/extractors/YTDLPUtil.kt b/app/src/main/java/com/deniscerri/ytdl/util/extractors/YTDLPUtil.kt index 47808604..60079410 100644 --- a/app/src/main/java/com/deniscerri/ytdl/util/extractors/YTDLPUtil.kt +++ b/app/src/main/java/com/deniscerri/ytdl/util/extractors/YTDLPUtil.kt @@ -78,8 +78,8 @@ class YTDLPUtil(private val context: Context) { val extraCommands = sharedPreferences.getString("data_fetching_extra_commands", "")!! if (extraCommands.isNotBlank()){ - addCommands(extraCommands.split(" ", "\t", "\n")) - //addConfig(extraCommands) + //addCommands(extraCommands.split(" ", "\t", "\n")) + addConfig(extraCommands) } } @@ -1146,16 +1146,16 @@ class YTDLPUtil(private val context: Context) { } if (downloadItem.extraCommands.isNotBlank() && downloadItem.type != DownloadViewModel.Type.command){ - request.addCommands(downloadItem.extraCommands.split(" ", "\t", "\n")) -// -// val cache = File(FileUtil.getCachePath(context)) -// cache.mkdirs() -// val conf = File(cache.absolutePath + "/${System.currentTimeMillis()}${UUID.randomUUID()}.txt") -// conf.createNewFile() -// conf.writeText(downloadItem.extraCommands) -// val tmp = mutableListOf() -// tmp.addOption("--config-locations", conf.absolutePath) -// request.addCommands(tmp) + //request.addCommands(downloadItem.extraCommands.replace("\"", "").split(" ", "\t", "\n")) + + val cache = File(FileUtil.getCachePath(context)) + cache.mkdirs() + val conf = File(cache.absolutePath + "/${System.currentTimeMillis()}${UUID.randomUUID()}.txt") + conf.createNewFile() + conf.writeText(downloadItem.extraCommands) + val tmp = mutableListOf() + tmp.addOption("--config-locations", conf.absolutePath) + request.addCommands(tmp) } return request diff --git a/app/src/main/java/com/deniscerri/ytdl/work/DownloadWorker.kt b/app/src/main/java/com/deniscerri/ytdl/work/DownloadWorker.kt index 3e3b7310..5aaef912 100644 --- a/app/src/main/java/com/deniscerri/ytdl/work/DownloadWorker.kt +++ b/app/src/main/java/com/deniscerri/ytdl/work/DownloadWorker.kt @@ -44,6 +44,7 @@ import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withContext import org.greenrobot.eventbus.EventBus import java.io.File +import java.security.MessageDigest import java.util.Locale @@ -51,6 +52,7 @@ class DownloadWorker( private val context: Context, workerParams: WorkerParameters ) : CoroutineWorker(context, workerParams) { + @OptIn(ExperimentalStdlibApi::class) @SuppressLint("RestrictedApi") override suspend fun doWork(): Result { if (isStopped) return Result.success() @@ -320,10 +322,12 @@ class DownloadWorker( } } - notificationUtil.cancelDownloadNotification(downloadItem.id.toInt()) - notificationUtil.createDownloadFinished( - downloadItem.id, downloadItem.title, downloadItem.type, if (finalPaths.isEmpty()) null else finalPaths, resources - ) + withContext(Dispatchers.Main) { + notificationUtil.cancelDownloadNotification(downloadItem.id.toInt()) + notificationUtil.createDownloadFinished( + downloadItem.id, downloadItem.title, downloadItem.type, if (finalPaths.isEmpty()) null else finalPaths, resources + ) + } // if (wasQuickDownloaded && createResultItem){ // runCatching { @@ -352,6 +356,11 @@ class DownloadWorker( } if (this@DownloadWorker.isStopped) return@onFailure if (it is YoutubeDL.CanceledException) return@onFailure + if (it.message?.contains("JSONDecodeError") == true) { + val cachePath = "${FileUtil.getCachePath(context)}infojsons" + val infoJsonName = MessageDigest.getInstance("MD5").digest(downloadItem.url.toByteArray()).toHexString() + FileUtil.deleteFile("${cachePath}/${infoJsonName}.info.json") + } if(it.message != null){ if (logDownloads){ diff --git a/app/src/main/res/menu/saved_header_menu.xml b/app/src/main/res/menu/saved_header_menu.xml index 8dfaf6b1..f63073f3 100644 --- a/app/src/main/res/menu/saved_header_menu.xml +++ b/app/src/main/res/menu/saved_header_menu.xml @@ -1,6 +1,11 @@ +