Yandex штуки
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
package com.github.nullptroma.wallenc.data.network.yandexdisk
|
||||
|
||||
import java.io.IOException
|
||||
|
||||
class YandexDiskAuthException(message: String? = null) : IOException(message)
|
||||
@@ -1,10 +1,13 @@
|
||||
package com.github.nullptroma.wallenc.data.network.yandexdisk.repository
|
||||
|
||||
import android.util.Log
|
||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||
import com.fasterxml.jackson.module.kotlin.readValue
|
||||
import com.github.nullptroma.wallenc.data.network.yandexdisk.YandexDiskApi
|
||||
import com.github.nullptroma.wallenc.data.network.yandexdisk.YandexDiskAuthException
|
||||
import com.github.nullptroma.wallenc.data.network.yandexdisk.dto.CustomPropertiesPatchDto
|
||||
import com.github.nullptroma.wallenc.data.network.yandexdisk.dto.DiskInfoDto
|
||||
import com.github.nullptroma.wallenc.data.network.yandexdisk.dto.EmbeddedResourceListDto
|
||||
import com.github.nullptroma.wallenc.data.network.yandexdisk.dto.LinkDto
|
||||
import com.github.nullptroma.wallenc.data.network.yandexdisk.dto.OperationStatusDto
|
||||
import com.github.nullptroma.wallenc.data.network.yandexdisk.dto.ResourceDto
|
||||
@@ -22,8 +25,6 @@ import retrofit2.Response
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
|
||||
class YandexDiskAuthException(message: String? = null) : IOException(message)
|
||||
|
||||
class YandexDiskRepository(
|
||||
private val api: YandexDiskApi,
|
||||
private val rawHttp: okhttp3.OkHttpClient,
|
||||
@@ -36,7 +37,15 @@ class YandexDiskRepository(
|
||||
|
||||
suspend fun list(path: String, limit: Int, offset: Int, sort: String? = null): ResourceDto =
|
||||
withContext(ioDispatcher) {
|
||||
wrapAuth { api.listResources(path, limit, offset, sort) }
|
||||
try {
|
||||
wrapAuth { api.listResources(path, limit, offset, sort) }
|
||||
} catch (e: HttpException) {
|
||||
if (e.code() == 404) {
|
||||
ResourceDto(embedded = EmbeddedResourceListDto(items = emptyList()))
|
||||
} else {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun get(path: String): ResourceDto = withContext(ioDispatcher) {
|
||||
@@ -47,7 +56,7 @@ class YandexDiskRepository(
|
||||
val resp = wrapAuth { api.createFolder(path) }
|
||||
when (resp.code()) {
|
||||
201 -> Unit
|
||||
409 -> Unit // уже существует
|
||||
409 -> Unit
|
||||
else -> throw failure("createFolder", resp)
|
||||
}
|
||||
}
|
||||
@@ -170,8 +179,17 @@ class YandexDiskRepository(
|
||||
try {
|
||||
return block()
|
||||
} catch (e: HttpException) {
|
||||
if (e.code() == 401) throw YandexDiskAuthException(e.message())
|
||||
throw e
|
||||
when (e.code()) {
|
||||
401 -> {
|
||||
Log.w(TAG, "Disk API 401: ${e.message()}")
|
||||
throw YandexDiskAuthException(e.message())
|
||||
}
|
||||
404 -> throw e
|
||||
else -> {
|
||||
Log.w(TAG, "Disk API HTTP ${e.code()}: ${e.message()}")
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,6 +202,7 @@ class YandexDiskRepository(
|
||||
jackson.readValue(body.string())
|
||||
|
||||
companion object {
|
||||
private const val TAG = "YandexDiskRepo"
|
||||
private val jackson = jacksonObjectMapper().apply { findAndRegisterModules() }
|
||||
private val OCTET_STREAM = "application/octet-stream".toMediaType()
|
||||
private const val OPERATION_POLL_DELAY_MS = 300L
|
||||
|
||||
@@ -86,10 +86,8 @@ abstract class BaseStorage(
|
||||
|
||||
private suspend fun updateMetaInfo(meta: IStorageMetaInfo) = withContext(ioDispatcher) {
|
||||
val writer = accessor.openWriteSystemFile(metaInfoFileName)
|
||||
try {
|
||||
writer.use { writer ->
|
||||
jackson.writeValue(writer, meta)
|
||||
} finally {
|
||||
writer.close()
|
||||
}
|
||||
_metaInfo.value = meta
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.github.nullptroma.wallenc.data.storages.yandex
|
||||
|
||||
import com.github.nullptroma.wallenc.data.network.yandexdisk.repository.YandexDiskAuthException
|
||||
import com.github.nullptroma.wallenc.data.network.yandexdisk.YandexDiskAuthException
|
||||
import com.github.nullptroma.wallenc.data.network.yandexdisk.dto.ResourceDto
|
||||
import com.github.nullptroma.wallenc.data.network.yandexdisk.repository.YandexDiskRepository
|
||||
import com.github.nullptroma.wallenc.data.utils.CloseHandledStreamExtension.Companion.onClosed
|
||||
@@ -23,6 +23,7 @@ import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import android.util.Log
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.ByteArrayOutputStream
|
||||
@@ -72,13 +73,16 @@ class YandexStorageAccessor(
|
||||
try {
|
||||
scanSizeAndNumOfFiles()
|
||||
_storageReady.value = true
|
||||
Log.d(TAG, "init ok storageUuid=$storageUuid")
|
||||
} catch (e: YandexDiskAuthException) {
|
||||
reportAuthFailure()
|
||||
_storageReady.value = false
|
||||
Log.w(TAG, "init auth failed storageUuid=$storageUuid", e)
|
||||
throw e
|
||||
} catch (_: Exception) {
|
||||
} catch (e: Exception) {
|
||||
_storageReady.value = false
|
||||
throw Exception("Yandex storage init failed")
|
||||
Log.w(TAG, "init failed storageUuid=$storageUuid", e)
|
||||
throw Exception("Yandex storage init failed", e)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -432,6 +436,7 @@ class YandexStorageAccessor(
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "YandexStorageAcc"
|
||||
private const val SYSTEM_HIDDEN_DIRNAME = "wallenc-yandex-system"
|
||||
private const val DATA_PAGE_LENGTH = 10
|
||||
private const val API_LIST_LIMIT = 200
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.github.nullptroma.wallenc.data.vaults.yandex
|
||||
|
||||
import com.github.nullptroma.wallenc.data.network.yandexdisk.repository.YandexDiskAuthException
|
||||
import com.github.nullptroma.wallenc.data.network.yandexdisk.YandexDiskAuthException
|
||||
import com.github.nullptroma.wallenc.data.network.yandexdisk.repository.YandexDiskRepository
|
||||
import com.github.nullptroma.wallenc.data.storages.yandex.YandexStorage
|
||||
import com.github.nullptroma.wallenc.domain.datatypes.StorageEncryptionInfo
|
||||
@@ -12,6 +12,7 @@ import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import android.util.Log
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.util.UUID
|
||||
@@ -64,12 +65,15 @@ class YandexVault(
|
||||
_availableSpace.value = (total - used).coerceAtLeast(0L)
|
||||
_vaultReachable.value = true
|
||||
_storages.value = loadStoragesList()
|
||||
} catch (_: YandexDiskAuthException) {
|
||||
Log.d(TAG, "refresh ok uuid=$uuid storages=${_storages.value.size}")
|
||||
} catch (e: YandexDiskAuthException) {
|
||||
_vaultReachable.value = false
|
||||
_storages.value = emptyList()
|
||||
} catch (_: Exception) {
|
||||
Log.w(TAG, "refresh auth failed uuid=$uuid: ${e.message}")
|
||||
} catch (e: Exception) {
|
||||
_vaultReachable.value = false
|
||||
_storages.value = emptyList()
|
||||
Log.w(TAG, "refresh failed uuid=$uuid", e)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,8 +100,8 @@ class YandexVault(
|
||||
try {
|
||||
storage.init()
|
||||
out.add(storage)
|
||||
} catch (_: Exception) {
|
||||
// пропускаем битое/частично созданное хранилище
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, "skip broken storage uuid=$storageUuid: ${e.message}")
|
||||
}
|
||||
}
|
||||
if (items.size < APP_LIST_LIMIT) break
|
||||
@@ -108,6 +112,7 @@ class YandexVault(
|
||||
|
||||
override suspend fun createStorage(): IStorage = withContext(ioDispatcher) {
|
||||
val id = UUID.randomUUID()
|
||||
Log.d(TAG, "createStorage start vault=$uuid storage=$id")
|
||||
repo.createFolder("app:/$id")
|
||||
val storage = YandexStorage(
|
||||
uuid = id,
|
||||
@@ -121,6 +126,7 @@ class YandexVault(
|
||||
)
|
||||
storage.init()
|
||||
_storages.value = _storages.value + storage
|
||||
Log.d(TAG, "createStorage done storage=$id")
|
||||
storage
|
||||
}
|
||||
|
||||
@@ -132,11 +138,13 @@ class YandexVault(
|
||||
|
||||
override suspend fun remove(storage: IStorage) = withContext(ioDispatcher) {
|
||||
if (storage !is YandexStorage) return@withContext
|
||||
Log.d(TAG, "remove storage=${storage.uuid}")
|
||||
repo.delete("app:/${storage.uuid}", permanently = true)
|
||||
_storages.value = _storages.value.filter { it.uuid != storage.uuid }
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private const val TAG = "YandexVault"
|
||||
private const val APP_LIST_LIMIT = 200
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user