134 lines
5.7 KiB
Kotlin
134 lines
5.7 KiB
Kotlin
/* Copyright 2022 Tusky contributors
|
|
*
|
|
* This file is a part of Tusky.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
|
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
|
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
* Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
|
* see <http://www.gnu.org/licenses>. */
|
|
|
|
package com.keylesspalace.tusky.components.instanceinfo
|
|
|
|
import android.util.Log
|
|
import at.connyduck.calladapter.networkresult.fold
|
|
import at.connyduck.calladapter.networkresult.getOrElse
|
|
import at.connyduck.calladapter.networkresult.onSuccess
|
|
import com.keylesspalace.tusky.db.AccountManager
|
|
import com.keylesspalace.tusky.db.AppDatabase
|
|
import com.keylesspalace.tusky.db.EmojisEntity
|
|
import com.keylesspalace.tusky.db.InstanceInfoEntity
|
|
import com.keylesspalace.tusky.entity.Emoji
|
|
import com.keylesspalace.tusky.network.MastodonApi
|
|
import kotlinx.coroutines.Dispatchers
|
|
import kotlinx.coroutines.withContext
|
|
import javax.inject.Inject
|
|
|
|
class InstanceInfoRepository @Inject constructor(
|
|
private val api: MastodonApi,
|
|
db: AppDatabase,
|
|
accountManager: AccountManager
|
|
) {
|
|
|
|
private val dao = db.instanceDao()
|
|
private val instanceName = accountManager.activeAccount!!.domain
|
|
|
|
/**
|
|
* Returns the custom emojis of the instance.
|
|
* Will always try to fetch them from the api, falls back to cached Emojis in case it is not available.
|
|
* Never throws, returns empty list in case of error.
|
|
*/
|
|
suspend fun getEmojis(): List<Emoji> = withContext(Dispatchers.IO) {
|
|
api.getCustomEmojis()
|
|
.onSuccess { emojiList -> dao.insertOrReplace(EmojisEntity(instanceName, emojiList)) }
|
|
.getOrElse { throwable ->
|
|
Log.w(TAG, "failed to load custom emojis, falling back to cache", throwable)
|
|
getCachedEmojis()
|
|
}
|
|
}
|
|
|
|
suspend fun getCachedEmojis(): List<Emoji> =
|
|
dao.getEmojiInfo(instanceName)?.emojiList.orEmpty()
|
|
|
|
/**
|
|
* Returns information about the instance.
|
|
* Will always try to fetch the most up-to-date data from the api, falls back to cache in case it is not available.
|
|
* Never throws, returns defaults of vanilla Mastodon in case of error.
|
|
*/
|
|
suspend fun getInstanceInfo(): InstanceInfo = withContext(Dispatchers.IO) {
|
|
api.getInstance()
|
|
.fold(
|
|
{ instance ->
|
|
val instanceEntity = InstanceInfoEntity(
|
|
instance = instanceName,
|
|
maximumTootCharacters = instance.configuration?.statuses?.maxCharacters ?: instance.maxTootChars,
|
|
maxPollOptions = instance.configuration?.polls?.maxOptions ?: instance.pollConfiguration?.maxOptions,
|
|
maxPollOptionLength = instance.configuration?.polls?.maxCharactersPerOption ?: instance.pollConfiguration?.maxOptionChars,
|
|
minPollDuration = instance.configuration?.polls?.minExpiration ?: instance.pollConfiguration?.minExpiration,
|
|
maxPollDuration = instance.configuration?.polls?.maxExpiration ?: instance.pollConfiguration?.maxExpiration,
|
|
charactersReservedPerUrl = instance.configuration?.statuses?.charactersReservedPerUrl,
|
|
version = instance.version
|
|
)
|
|
dao.insertOrReplace(instanceEntity)
|
|
instanceEntity
|
|
},
|
|
{ throwable ->
|
|
Log.w(TAG, "failed to instance, falling back to cache and default values", throwable)
|
|
getCachedInstanceInfoEntity()
|
|
}
|
|
).toInstanceInfo()
|
|
}
|
|
|
|
private suspend fun getCachedInstanceInfoEntity(): InstanceInfoEntity? =
|
|
dao.getInstanceInfo(instanceName)
|
|
|
|
suspend fun getCachedInstanceInfo(): InstanceInfo =
|
|
getCachedInstanceInfoEntity().toInstanceInfo()
|
|
|
|
companion object {
|
|
private const val TAG = "InstanceInfoRepo"
|
|
|
|
const val DEFAULT_CHARACTER_LIMIT = 500
|
|
private const val DEFAULT_MAX_OPTION_COUNT = 4
|
|
private const val DEFAULT_MAX_OPTION_LENGTH = 50
|
|
private const val DEFAULT_MIN_POLL_DURATION = 300
|
|
private const val DEFAULT_MAX_POLL_DURATION = 604800
|
|
|
|
@JvmField
|
|
val CAN_USE_QUOTE_ID = arrayOf(
|
|
"odakyu.app",
|
|
"itabashi.0j0.jp",
|
|
"biwakodon.com",
|
|
"dtp-mstdn.jp",
|
|
"nitiasa.com",
|
|
"comm.cx",
|
|
"fedibird.com",
|
|
"qoto.org",
|
|
"kurage.cc",
|
|
"m.eula.dev",
|
|
"otogamer.me",
|
|
"sgp.hostdon.ne.jp",
|
|
"pomdon.work",
|
|
"obapom.work",
|
|
)
|
|
|
|
// Mastodon only counts URLs as this long in terms of status character limits
|
|
const val DEFAULT_CHARACTERS_RESERVED_PER_URL = 23
|
|
|
|
fun InstanceInfoEntity?.toInstanceInfo(): InstanceInfo =
|
|
InstanceInfo(
|
|
maxChars = this?.maximumTootCharacters ?: DEFAULT_CHARACTER_LIMIT,
|
|
pollMaxOptions = this?.maxPollOptions ?: DEFAULT_MAX_OPTION_COUNT,
|
|
pollMaxLength = this?.maxPollOptionLength ?: DEFAULT_MAX_OPTION_LENGTH,
|
|
pollMinDuration = this?.minPollDuration ?: DEFAULT_MIN_POLL_DURATION,
|
|
pollMaxDuration = this?.maxPollDuration ?: DEFAULT_MAX_POLL_DURATION,
|
|
charactersReservedPerUrl = this?.charactersReservedPerUrl ?: DEFAULT_CHARACTERS_RESERVED_PER_URL
|
|
)
|
|
}
|
|
}
|