diff --git a/app/src/main/java/com/github/libretube/obj/NewPipeSubscription.kt b/app/src/main/java/com/github/libretube/obj/NewPipeSubscription.kt new file mode 100644 index 000000000..986592238 --- /dev/null +++ b/app/src/main/java/com/github/libretube/obj/NewPipeSubscription.kt @@ -0,0 +1,7 @@ +package com.github.libretube.obj + +data class NewPipeSubscription( + val name: String, + val service_id: Int, + val url: String +) diff --git a/app/src/main/java/com/github/libretube/obj/NewPipeSubscriptions.kt b/app/src/main/java/com/github/libretube/obj/NewPipeSubscriptions.kt new file mode 100644 index 000000000..9c19551d2 --- /dev/null +++ b/app/src/main/java/com/github/libretube/obj/NewPipeSubscriptions.kt @@ -0,0 +1,7 @@ +package com.github.libretube.obj + +data class NewPipeSubscriptions( + val app_version: String = "", + val app_version_int: Int = 0, + val subscriptions: List? = null +) diff --git a/app/src/main/java/com/github/libretube/preferences/InstanceSettings.kt b/app/src/main/java/com/github/libretube/preferences/InstanceSettings.kt index d2d82c013..90040fdf8 100644 --- a/app/src/main/java/com/github/libretube/preferences/InstanceSettings.kt +++ b/app/src/main/java/com/github/libretube/preferences/InstanceSettings.kt @@ -21,6 +21,7 @@ import com.github.libretube.dialogs.CustomInstanceDialog import com.github.libretube.dialogs.DeleteAccountDialog import com.github.libretube.dialogs.LoginDialog import com.github.libretube.dialogs.LogoutDialog +import com.github.libretube.util.ImportHelper import com.github.libretube.util.PermissionHelper import com.github.libretube.util.RetrofitInstance import org.json.JSONObject @@ -34,80 +35,6 @@ import java.util.zip.ZipInputStream class InstanceSettings : PreferenceFragmentCompat() { val TAG = "InstanceSettings" - companion object { - lateinit var getContent: ActivityResultLauncher - } - - override fun onCreate(savedInstanceState: Bundle?) { - getContent = - registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? -> - if (uri != null) { - try { - // Open a specific media item using ParcelFileDescriptor. - val resolver: ContentResolver = - requireActivity() - .contentResolver - - // "rw" for read-and-write; - // "rwt" for truncating or overwriting existing file contents. - // val readOnlyMode = "r" - // uri - I have got from onActivityResult - val type = resolver.getType(uri) - - var inputStream: InputStream? = resolver.openInputStream(uri) - val channels = ArrayList() - if (type == "application/json") { - val json = inputStream?.bufferedReader()?.readLines()?.get(0) - val jsonObject = JSONTokener(json).nextValue() as JSONObject - Log.e(TAG, jsonObject.getJSONArray("subscriptions").toString()) - for ( - i in 0 until jsonObject.getJSONArray("subscriptions") - .length() - ) { - var url = - jsonObject.getJSONArray("subscriptions").getJSONObject(i) - .getString("url") - url = url.replace("https://www.youtube.com/channel/", "") - Log.e(TAG, url) - channels.add(url) - } - } else { - if (type == "application/zip") { - val zis = ZipInputStream(inputStream) - var entry: ZipEntry? = zis.nextEntry - while (entry != null) { - if (entry.name.endsWith(".csv")) { - inputStream = zis - break - } - entry = zis.nextEntry - } - } - - inputStream?.bufferedReader()?.readLines()?.forEach { - if (it.isNotBlank()) { - val channelId = it.substringBefore(",") - if (channelId.length == 24) { - channels.add(channelId) - } - } - } - } - inputStream?.close() - - subscribe(channels) - } catch (e: Exception) { - Log.e(TAG, e.toString()) - Toast.makeText( - context, - R.string.error, - Toast.LENGTH_SHORT - ).show() - } - } - } - super.onCreate(savedInstanceState) - } override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.instance_settings, rootKey) @@ -210,8 +137,8 @@ class InstanceSettings : PreferenceFragmentCompat() { lifecycleScope.launchWhenCreated { val customInstances = PreferenceHelper.getCustomInstances() - var instanceNames = arrayListOf() - var instanceValues = arrayListOf() + val instanceNames = arrayListOf() + val instanceValues = arrayListOf() // fetch official public instances @@ -263,39 +190,10 @@ class InstanceSettings : PreferenceFragmentCompat() { // check StorageAccess val accessGranted = PermissionHelper.isStoragePermissionGranted(activity as AppCompatActivity) - if (accessGranted) getContent.launch("*/*") + if (accessGranted) ImportHelper(requireActivity() as AppCompatActivity).importSubscriptions() else PermissionHelper.requestReadWrite(activity as AppCompatActivity) } else { Toast.makeText(context, R.string.login_first, Toast.LENGTH_SHORT).show() } } - - private fun subscribe(channels: List) { - fun run() { - lifecycleScope.launchWhenCreated { - val response = try { - val token = PreferenceHelper.getToken() - RetrofitInstance.authApi.importSubscriptions( - false, - token, - channels - ) - } catch (e: IOException) { - Log.e(TAG, "IOException, you might not have internet connection") - return@launchWhenCreated - } catch (e: HttpException) { - Log.e(TAG, "HttpException, unexpected response$e") - return@launchWhenCreated - } - if (response.message == "ok") { - Toast.makeText( - context, - R.string.importsuccess, - Toast.LENGTH_SHORT - ).show() - } - } - } - run() - } } diff --git a/app/src/main/java/com/github/libretube/util/ImportHelper.kt b/app/src/main/java/com/github/libretube/util/ImportHelper.kt new file mode 100644 index 000000000..74fc85688 --- /dev/null +++ b/app/src/main/java/com/github/libretube/util/ImportHelper.kt @@ -0,0 +1,93 @@ +package com.github.libretube.util + +import android.net.Uri +import android.util.Log +import android.widget.Toast +import androidx.activity.result.contract.ActivityResultContracts +import androidx.appcompat.app.AppCompatActivity +import com.fasterxml.jackson.databind.ObjectMapper +import com.github.libretube.R +import com.github.libretube.obj.NewPipeSubscriptions +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import java.io.BufferedReader +import java.io.InputStream +import java.io.InputStreamReader +import java.util.zip.ZipEntry +import java.util.zip.ZipInputStream + +class ImportHelper( + private val activity: AppCompatActivity +) { + private val TAG = "ImportHelper" + + fun importSubscriptions() { + getContent.launch("*/*") + } + + val getContent = + activity.registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? -> + if (uri != null) { + try { + val type = activity.contentResolver.getType(uri) + + var inputStream: InputStream? = activity.contentResolver.openInputStream(uri) + var channels = ArrayList() + if (type == "application/json") { + val mapper = ObjectMapper() + val json = readTextFromUri(uri) + val subscriptions = mapper.readValue(json, NewPipeSubscriptions::class.java) + channels = subscriptions.subscriptions?.map { + it.url.replace("https://www.youtube.com/channel/", "") + } as ArrayList + } else if (type == "application/zip") { + val zis = ZipInputStream(inputStream) + var entry: ZipEntry? = zis.nextEntry + while (entry != null) { + if (entry.name.endsWith(".csv")) { + inputStream = zis + break + } + entry = zis.nextEntry + } + } + + inputStream?.bufferedReader()?.readLines()?.forEach { + if (it.isNotBlank()) { + val channelId = it.substringBefore(",") + if (channelId.length == 24) { + channels.add(channelId) + } + } + } + inputStream?.close() + + CoroutineScope(Dispatchers.IO).launch { + SubscriptionHelper.importSubscriptions(channels) + } + } catch (e: Exception) { + Log.e(TAG, e.toString()) + Toast.makeText( + activity, + R.string.error, + Toast.LENGTH_SHORT + ).show() + } + } + } + + private fun readTextFromUri(uri: Uri): String { + val stringBuilder = StringBuilder() + activity.contentResolver.openInputStream(uri)?.use { inputStream -> + BufferedReader(InputStreamReader(inputStream)).use { reader -> + var line: String? = reader.readLine() + while (line != null) { + stringBuilder.append(line) + line = reader.readLine() + } + } + } + return stringBuilder.toString() + } +} diff --git a/app/src/main/java/com/github/libretube/util/SubscriptionHelper.kt b/app/src/main/java/com/github/libretube/util/SubscriptionHelper.kt index 19511413f..fe64e8157 100644 --- a/app/src/main/java/com/github/libretube/util/SubscriptionHelper.kt +++ b/app/src/main/java/com/github/libretube/util/SubscriptionHelper.kt @@ -65,6 +65,24 @@ object SubscriptionHelper { } } + suspend fun importSubscriptions(channels: List) { + if (PreferenceHelper.getToken() != "") { + val response = try { + val token = PreferenceHelper.getToken() + RetrofitInstance.authApi.importSubscriptions( + false, + token, + channels + ) + } catch (e: Exception) { + e.printStackTrace() + } + } else { + val newChannels = PreferenceHelper.getLocalSubscriptions().toMutableList() + channels + PreferenceHelper.setLocalSubscriptions(newChannels) + } + } + fun getFormattedLocalSubscriptions(): String { return PreferenceHelper.getLocalSubscriptions().joinToString(",") }