cloudstream/app/src/main/java/com/lagradost/cloudstream3/plugins/RepositoryManager.kt

102 lines
3.9 KiB
Kotlin
Raw Normal View History

2022-08-06 18:27:56 +00:00
package com.lagradost.cloudstream3.plugins
import android.content.Context
import com.fasterxml.jackson.annotation.JsonProperty
2022-08-06 23:43:39 +00:00
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey
import com.lagradost.cloudstream3.AcraApplication.Companion.setKey
2022-08-06 18:27:56 +00:00
import com.lagradost.cloudstream3.apmap
import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall
2022-08-06 23:43:39 +00:00
import com.lagradost.cloudstream3.ui.settings.extensions.REPOSITORIES_KEY
import com.lagradost.cloudstream3.ui.settings.extensions.RepositoryData
2022-08-06 18:27:56 +00:00
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
2022-08-06 23:43:39 +00:00
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
2022-08-06 18:27:56 +00:00
import java.io.BufferedInputStream
import java.io.File
import java.io.InputStream
import java.io.OutputStream
data class Repository(
@JsonProperty("name") val name: String,
@JsonProperty("description") val description: String?,
@JsonProperty("manifestVersion") val manifestVersion: Int,
@JsonProperty("pluginLists") val pluginLists: List<String>
)
data class SitePlugin(
@JsonProperty("url") val url: String,
@JsonProperty("tvTypes") val tvTypes: List<String>?,
@JsonProperty("version") val version: Int,
@JsonProperty("apiVersion") val apiVersion: Int,
@JsonProperty("name") val name: String,
@JsonProperty("authors") val authors: List<String>,
@JsonProperty("description") val description: String?,
@JsonProperty("repositoryUrl") val repositoryUrl: String?,
@JsonProperty("language") val language: String?,
@JsonProperty("iconUrl") val iconUrl: String?
)
2022-08-06 23:43:39 +00:00
object RepositoryManager {
const val ONLINE_PLUGINS_FOLDER = "Extensions"
2022-08-06 18:27:56 +00:00
private suspend fun parseRepository(url: String): Repository? {
return suspendSafeApiCall {
// Take manifestVersion and such into account later
app.get(url).parsedSafe()
}
}
private suspend fun parsePlugins(pluginUrls: String): ArrayList<SitePlugin>? {
// Take manifestVersion and such into account later
val response = app.get(pluginUrls)
// Normal parsed function not working?
// return response.parsedSafe()
return tryParseJson<ArrayList<SitePlugin>>(response.text)
}
suspend fun getRepoPlugins(repositoryUrl: String): List<SitePlugin>? {
val repo = parseRepository(repositoryUrl) ?: return null
return repo.pluginLists.apmap {
parsePlugins(it)
}.filterNotNull().flatten()
}
2022-08-06 23:43:39 +00:00
suspend fun downloadPluginToFile(context: Context, pluginUrl: String, name: String): File? {
2022-08-06 18:27:56 +00:00
return suspendSafeApiCall {
2022-08-06 23:43:39 +00:00
val extensionsDir = File(context.filesDir, ONLINE_PLUGINS_FOLDER)
if (!extensionsDir.exists())
extensionsDir.mkdirs()
val newFile = File(extensionsDir, "$name.${pluginUrl.hashCode()}.cs3")
if (newFile.exists()) return@suspendSafeApiCall newFile
newFile.createNewFile()
2022-08-06 18:27:56 +00:00
val body = app.get(pluginUrl).okhttpResponse.body
2022-08-06 23:43:39 +00:00
write(body.byteStream(), newFile.outputStream())
newFile
2022-08-06 18:27:56 +00:00
}
}
2022-08-06 23:43:39 +00:00
// Don't want to read before we write in another thread
private val repoLock = Mutex()
suspend fun addRepository(repository: RepositoryData) {
repoLock.withLock {
val currentRepos = getKey<List<RepositoryData>>(REPOSITORIES_KEY) ?: emptyList()
setKey(REPOSITORIES_KEY, currentRepos + repository)
}
2022-08-06 18:27:56 +00:00
}
private fun write(stream: InputStream, output: OutputStream) {
val input = BufferedInputStream(stream)
val dataBuffer = ByteArray(512)
var readBytes: Int
while (input.read(dataBuffer).also { readBytes = it } != -1) {
output.write(dataBuffer, 0, readBytes)
}
}
}