refactor: Move ServerOperation and related types to core.model (#969)

This commit is contained in:
Nik Clayton 2024-10-03 13:41:46 +02:00 committed by GitHub
parent ea53b68b3f
commit fe1c586dae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 294 additions and 228 deletions

View File

@ -74,21 +74,21 @@ import app.pachli.core.common.extensions.show
import app.pachli.core.common.extensions.toggleVisibility
import app.pachli.core.common.extensions.viewBinding
import app.pachli.core.common.extensions.visible
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_BY_DATE
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_FROM
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_AUDIO
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_EMBED
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_IMAGE
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_LINK
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_MEDIA
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_POLL
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_VIDEO
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IN_LIBRARY
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IN_PUBLIC
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IS_REPLY
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IS_SENSITIVE
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_LANGUAGE
import app.pachli.core.network.Server
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_BY_DATE
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_FROM
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_AUDIO
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_EMBED
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_IMAGE
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_LINK
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_MEDIA
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_POLL
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_VIDEO
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IN_LIBRARY
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IN_PUBLIC
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IS_REPLY
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IS_SENSITIVE
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_LANGUAGE
import app.pachli.core.preferences.PrefKeys
import app.pachli.core.ui.extensions.await
import app.pachli.core.ui.extensions.awaitSingleChoiceItem

View File

@ -36,20 +36,20 @@ import app.pachli.components.search.adapter.SearchPagingSourceFactory
import app.pachli.core.accounts.AccountManager
import app.pachli.core.data.repository.ServerRepository
import app.pachli.core.database.model.AccountEntity
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_BY_DATE
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_FROM
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_AUDIO
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_EMBED
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_IMAGE
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_LINK
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_MEDIA
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_POLL
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_VIDEO
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IN_LIBRARY
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IN_PUBLIC
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IS_REPLY
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IS_SENSITIVE
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_LANGUAGE
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_BY_DATE
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_FROM
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_AUDIO
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_EMBED
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_IMAGE
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_LINK
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_MEDIA
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_POLL
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_VIDEO
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IN_LIBRARY
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IN_PUBLIC
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IS_REPLY
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IS_SENSITIVE
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_LANGUAGE
import app.pachli.core.network.model.DeletedStatus
import app.pachli.core.network.model.Poll
import app.pachli.core.network.model.Status

View File

@ -49,13 +49,13 @@ import app.pachli.core.data.repository.ServerRepository
import app.pachli.core.database.model.AccountEntity
import app.pachli.core.database.model.TranslationState
import app.pachli.core.domain.DownloadUrlUseCase
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_STATUSES_TRANSLATE
import app.pachli.core.navigation.AttachmentViewData
import app.pachli.core.navigation.ComposeActivityIntent
import app.pachli.core.navigation.ComposeActivityIntent.ComposeOptions
import app.pachli.core.navigation.ReportActivityIntent
import app.pachli.core.navigation.TimelineActivityIntent
import app.pachli.core.navigation.ViewMediaActivityIntent
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_STATUSES_TRANSLATE
import app.pachli.core.network.model.Attachment
import app.pachli.core.network.model.Status
import app.pachli.core.network.parseAsMastodonHtml

View File

@ -30,9 +30,9 @@ import app.pachli.core.data.repository.ContentFiltersError.GetContentFiltersErro
import app.pachli.core.data.repository.ContentFiltersError.ServerDoesNotFilter
import app.pachli.core.data.repository.ContentFiltersError.ServerRepositoryError
import app.pachli.core.data.repository.ContentFiltersError.UpdateContentFilterError
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_FILTERS_CLIENT
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_FILTERS_SERVER
import app.pachli.core.network.Server
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_FILTERS_CLIENT
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_FILTERS_SERVER
import app.pachli.core.network.model.FilterAction
import app.pachli.core.network.model.FilterContext
import app.pachli.core.network.model.FilterKeyword

View File

@ -29,7 +29,7 @@ import app.pachli.core.data.repository.ServerRepository.Error.GetWellKnownNodeIn
import app.pachli.core.data.repository.ServerRepository.Error.UnsupportedSchema
import app.pachli.core.data.repository.ServerRepository.Error.ValidateNodeInfo
import app.pachli.core.network.Server
import app.pachli.core.network.model.nodeinfo.NodeInfo
import app.pachli.core.network.model.nodeinfo.UnvalidatedNodeInfo
import app.pachli.core.network.retrofit.MastodonApi
import app.pachli.core.network.retrofit.NodeInfoApi
import at.connyduck.calladapter.networkresult.fold
@ -100,7 +100,7 @@ class ServerRepository @Inject constructor(
Timber.d("Loading node info from %s", nodeInfoUrl)
val nodeInfo = nodeInfoApi.nodeInfo(nodeInfoUrl).fold(
{ NodeInfo.from(it).mapError { ValidateNodeInfo(nodeInfoUrl, it) } },
{ it.validate().mapError { ValidateNodeInfo(nodeInfoUrl, it) } },
{ Err(GetNodeInfo(nodeInfoUrl, it)) },
).bind()
@ -136,7 +136,7 @@ class ServerRepository @Inject constructor(
arrayOf(url, throwable.localizedMessage ?: ""),
)
data class ValidateNodeInfo(val url: String, val error: NodeInfo.Error) : Error(
data class ValidateNodeInfo(val url: String, val error: UnvalidatedNodeInfo.Error) : Error(
R.string.server_repository_error_validate_node_info,
arrayOf(url),
cause = error,

View File

@ -23,7 +23,7 @@ import app.pachli.core.accounts.AccountManager
import app.pachli.core.common.di.ApplicationScope
import app.pachli.core.data.model.StatusDisplayOptions
import app.pachli.core.database.model.AccountEntity
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_STATUSES_TRANSLATE
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_STATUSES_TRANSLATE
import app.pachli.core.preferences.CardViewMode
import app.pachli.core.preferences.PrefKeys
import app.pachli.core.preferences.SharedPreferencesRepository

View File

@ -22,9 +22,9 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import app.pachli.core.data.repository.ContentFiltersRepository
import app.pachli.core.data.repository.HiltTestApplication_Application
import app.pachli.core.data.repository.ServerRepository
import app.pachli.core.model.ServerKind
import app.pachli.core.model.ServerOperation
import app.pachli.core.network.Server
import app.pachli.core.network.ServerKind
import app.pachli.core.network.ServerOperation
import app.pachli.core.network.retrofit.MastodonApi
import app.pachli.core.testing.rules.MainCoroutineRule
import com.github.michaelbull.result.Ok

View File

@ -36,4 +36,7 @@ dependencies {
implementation(libs.moshix.sealed.runtime)
ksp(libs.moshix.sealed.codegen)
implementation(libs.semver)
?.because("ServerOperation uses Version")
}

View File

@ -0,0 +1,33 @@
/*
* Copyright 2024 Pachli Association
*
* This file is a part of Pachli.
*
* 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.
*
* Pachli 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 Pachli; if not,
* see <http://www.gnu.org/licenses>.
*/
package app.pachli.core.model
/**
* A validated NodeInfo.
*
* See https://nodeinfo.diaspora.software/protocol.html and
* https://nodeinfo.diaspora.software/schema.html.
*/
data class NodeInfo(val software: Software) {
data class Software(
/** Software name, won't be null, empty, or blank */
val name: String,
/** Software version, won't be null, empty, or blank */
val version: String,
)
}

View File

@ -0,0 +1,64 @@
/*
* Copyright 2024 Pachli Association
*
* This file is a part of Pachli.
*
* 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.
*
* Pachli 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 Pachli; if not,
* see <http://www.gnu.org/licenses>.
*/
package app.pachli.core.model
/**
* Servers that are known to implement the Mastodon client API
*/
enum class ServerKind {
AKKOMA,
FEDIBIRD,
FIREFISH,
FRIENDICA,
GLITCH,
GOTOSOCIAL,
HOMETOWN,
ICESHRIMP,
MASTODON,
PLEROMA,
PIXELFED,
SHARKEY,
/**
* Catch-all for servers we don't recognise but that responded to either
* /api/v1/instance or /api/v2/instance
*/
UNKNOWN,
;
companion object {
fun from(s: NodeInfo.Software) = when (s.name.lowercase()) {
"akkoma" -> AKKOMA
"fedibird" -> FEDIBIRD
"firefish" -> FIREFISH
"friendica" -> FRIENDICA
"gotosocial" -> GOTOSOCIAL
"hometown" -> HOMETOWN
"iceshrimp" -> ICESHRIMP
"mastodon" -> {
// Glitch doesn't report a different software name it stuffs it
// in the version (https://github.com/glitch-soc/mastodon/issues/2582).
if (s.version.contains("+glitch")) GLITCH else MASTODON
}
"pixelfed" -> PIXELFED
"pleroma" -> PLEROMA
"sharkey" -> SHARKEY
else -> UNKNOWN
}
}
}

View File

@ -0,0 +1,80 @@
/*
* Copyright 2024 Pachli Association
*
* This file is a part of Pachli.
*
* 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.
*
* Pachli 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 Pachli; if not,
* see <http://www.gnu.org/licenses>.
*/
package app.pachli.core.model
import io.github.z4kn4fein.semver.Version
/**
* Identifiers for operations that the server may or may not support.
*/
enum class ServerOperation(id: String, versions: List<Version>) {
/** Client-side filters */
ORG_JOINMASTODON_FILTERS_CLIENT(
"org.joinmastodon.filters.client",
listOf(
// Initial introduction in Mastodon 2.4.3
Version(major = 1),
// "account" context available in filter views in Mastodon 3.1.0
Version(major = 1, minor = 1),
),
),
/** Server-side filters */
ORG_JOINMASTODON_FILTERS_SERVER(
"org.joinmastodon.filters.server",
listOf(
// Intitial introduction in Mastodon 4.0.0
Version(major = 1),
),
),
/** Translate a status */
ORG_JOINMASTODON_STATUSES_TRANSLATE(
"org.joinmastodon.statuses.translate",
listOf(
// Initial introduction in Mastodon 4.0.0
Version(major = 1),
// Spoiler warnings, polls, and media descriptions are also translated in Mastodon 4.2.0
Version(major = 1, minor = 1),
),
),
/** Search for posts from a particular account */
ORG_JOINMASTODON_SEARCH_QUERY_FROM(
"org.joinmastodon.search.query:from",
listOf(
// Initial introduction in Mastodon 3.5.0
Version(major = 1),
// Support for `from:me` in Mastodon 4.2.0
Version(major = 1, minor = 1),
),
),
ORG_JOINMASTODON_SEARCH_QUERY_LANGUAGE("org.joinmastodon.search.query:language", listOf(Version(major = 1))),
ORG_JOINMASTODON_SEARCH_QUERY_HAS_MEDIA("org.joinmastodon.search.query:has:media", listOf(Version(major = 1))),
ORG_JOINMASTODON_SEARCH_QUERY_HAS_IMAGE("org.joinmastodon.search.query:has:image", listOf(Version(major = 1))),
ORG_JOINMASTODON_SEARCH_QUERY_HAS_VIDEO("org.joinmastodon.search.query:has:video", listOf(Version(major = 1))),
ORG_JOINMASTODON_SEARCH_QUERY_HAS_AUDIO("org.joinmastodon.search.query:has:audio", listOf(Version(major = 1))),
ORG_JOINMASTODON_SEARCH_QUERY_HAS_POLL("org.joinmastodon.search.query:has:poll", listOf(Version(major = 1))),
ORG_JOINMASTODON_SEARCH_QUERY_HAS_LINK("org.joinmastodon.search.query:has:link", listOf(Version(major = 1))),
ORG_JOINMASTODON_SEARCH_QUERY_HAS_EMBED("org.joinmastodon.search.query:has:embed", listOf(Version(major = 1))),
ORG_JOINMASTODON_SEARCH_QUERY_IS_REPLY("org.joinmastodon.search.query:is:reply", listOf(Version(major = 1))),
ORG_JOINMASTODON_SEARCH_QUERY_IS_SENSITIVE("org.joinmastodon.search.query:is:sensitive", listOf(Version(major = 1))),
ORG_JOINMASTODON_SEARCH_QUERY_IN_LIBRARY("org.joinmastodon.search.query:in:library", listOf(Version(major = 1))),
ORG_JOINMASTODON_SEARCH_QUERY_IN_PUBLIC("org.joinmastodon.search.query:in:public", listOf(Version(major = 1))),
ORG_JOINMASTODON_SEARCH_QUERY_BY_DATE("org.joinmastodon.search.query:in:public", listOf(Version(major = 1))),
}

View File

@ -20,40 +20,42 @@ package app.pachli.core.network
import androidx.annotation.VisibleForTesting
import androidx.annotation.VisibleForTesting.Companion.PRIVATE
import app.pachli.core.common.PachliError
import app.pachli.core.model.NodeInfo
import app.pachli.core.model.ServerKind
import app.pachli.core.model.ServerKind.AKKOMA
import app.pachli.core.model.ServerKind.FEDIBIRD
import app.pachli.core.model.ServerKind.FIREFISH
import app.pachli.core.model.ServerKind.FRIENDICA
import app.pachli.core.model.ServerKind.GLITCH
import app.pachli.core.model.ServerKind.GOTOSOCIAL
import app.pachli.core.model.ServerKind.HOMETOWN
import app.pachli.core.model.ServerKind.ICESHRIMP
import app.pachli.core.model.ServerKind.MASTODON
import app.pachli.core.model.ServerKind.PIXELFED
import app.pachli.core.model.ServerKind.PLEROMA
import app.pachli.core.model.ServerKind.SHARKEY
import app.pachli.core.model.ServerKind.UNKNOWN
import app.pachli.core.model.ServerOperation
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_FILTERS_CLIENT
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_FILTERS_SERVER
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_BY_DATE
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_FROM
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_AUDIO
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_EMBED
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_IMAGE
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_LINK
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_MEDIA
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_POLL
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_VIDEO
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IN_LIBRARY
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IN_PUBLIC
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IS_REPLY
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IS_SENSITIVE
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_LANGUAGE
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_STATUSES_TRANSLATE
import app.pachli.core.network.Server.Error.UnparseableVersion
import app.pachli.core.network.ServerKind.AKKOMA
import app.pachli.core.network.ServerKind.FEDIBIRD
import app.pachli.core.network.ServerKind.FIREFISH
import app.pachli.core.network.ServerKind.FRIENDICA
import app.pachli.core.network.ServerKind.GLITCH
import app.pachli.core.network.ServerKind.GOTOSOCIAL
import app.pachli.core.network.ServerKind.HOMETOWN
import app.pachli.core.network.ServerKind.ICESHRIMP
import app.pachli.core.network.ServerKind.MASTODON
import app.pachli.core.network.ServerKind.PIXELFED
import app.pachli.core.network.ServerKind.PLEROMA
import app.pachli.core.network.ServerKind.SHARKEY
import app.pachli.core.network.ServerKind.UNKNOWN
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_FILTERS_CLIENT
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_FILTERS_SERVER
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_BY_DATE
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_FROM
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_AUDIO
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_EMBED
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_IMAGE
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_LINK
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_MEDIA
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_POLL
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_VIDEO
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IN_LIBRARY
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IN_PUBLIC
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IS_REPLY
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IS_SENSITIVE
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_LANGUAGE
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_STATUSES_TRANSLATE
import app.pachli.core.network.model.InstanceV1
import app.pachli.core.network.model.InstanceV2
import app.pachli.core.network.model.nodeinfo.NodeInfo
import com.github.michaelbull.result.Ok
import com.github.michaelbull.result.Result
import com.github.michaelbull.result.andThen
@ -69,66 +71,6 @@ import io.github.z4kn4fein.semver.toVersion
import java.text.ParseException
import kotlin.collections.set
/**
* Identifiers for operations that the server may or may not support.
*/
enum class ServerOperation(id: String, versions: List<Version>) {
/** Client-side filters */
ORG_JOINMASTODON_FILTERS_CLIENT(
"org.joinmastodon.filters.client",
listOf(
// Initial introduction in Mastodon 2.4.3
Version(major = 1),
// "account" context available in filter views in Mastodon 3.1.0
Version(major = 1, minor = 1),
),
),
/** Server-side filters */
ORG_JOINMASTODON_FILTERS_SERVER(
"org.joinmastodon.filters.server",
listOf(
// Intitial introduction in Mastodon 4.0.0
Version(major = 1),
),
),
/** Translate a status */
ORG_JOINMASTODON_STATUSES_TRANSLATE(
"org.joinmastodon.statuses.translate",
listOf(
// Initial introduction in Mastodon 4.0.0
Version(major = 1),
// Spoiler warnings, polls, and media descriptions are also translated in Mastodon 4.2.0
Version(major = 1, minor = 1),
),
),
/** Search for posts from a particular account */
ORG_JOINMASTODON_SEARCH_QUERY_FROM(
"org.joinmastodon.search.query:from",
listOf(
// Initial introduction in Mastodon 3.5.0
Version(major = 1),
// Support for `from:me` in Mastodon 4.2.0
Version(major = 1, minor = 1),
),
),
ORG_JOINMASTODON_SEARCH_QUERY_LANGUAGE("org.joinmastodon.search.query:language", listOf(Version(major = 1))),
ORG_JOINMASTODON_SEARCH_QUERY_HAS_MEDIA("org.joinmastodon.search.query:has:media", listOf(Version(major = 1))),
ORG_JOINMASTODON_SEARCH_QUERY_HAS_IMAGE("org.joinmastodon.search.query:has:image", listOf(Version(major = 1))),
ORG_JOINMASTODON_SEARCH_QUERY_HAS_VIDEO("org.joinmastodon.search.query:has:video", listOf(Version(major = 1))),
ORG_JOINMASTODON_SEARCH_QUERY_HAS_AUDIO("org.joinmastodon.search.query:has:audio", listOf(Version(major = 1))),
ORG_JOINMASTODON_SEARCH_QUERY_HAS_POLL("org.joinmastodon.search.query:has:poll", listOf(Version(major = 1))),
ORG_JOINMASTODON_SEARCH_QUERY_HAS_LINK("org.joinmastodon.search.query:has:link", listOf(Version(major = 1))),
ORG_JOINMASTODON_SEARCH_QUERY_HAS_EMBED("org.joinmastodon.search.query:has:embed", listOf(Version(major = 1))),
ORG_JOINMASTODON_SEARCH_QUERY_IS_REPLY("org.joinmastodon.search.query:is:reply", listOf(Version(major = 1))),
ORG_JOINMASTODON_SEARCH_QUERY_IS_SENSITIVE("org.joinmastodon.search.query:is:sensitive", listOf(Version(major = 1))),
ORG_JOINMASTODON_SEARCH_QUERY_IN_LIBRARY("org.joinmastodon.search.query:in:library", listOf(Version(major = 1))),
ORG_JOINMASTODON_SEARCH_QUERY_IN_PUBLIC("org.joinmastodon.search.query:in:public", listOf(Version(major = 1))),
ORG_JOINMASTODON_SEARCH_QUERY_BY_DATE("org.joinmastodon.search.query:in:public", listOf(Version(major = 1))),
}
data class Server(
val kind: ServerKind,
val version: Version,
@ -138,8 +80,8 @@ data class Server(
* @return true if the server supports the given operation at the given minimum version
* level, false otherwise.
*/
fun can(operation: ServerOperation, constraint: Constraint) = capabilities[operation]?.let {
version ->
fun can(operation: ServerOperation, constraint: Constraint) =
capabilities[operation]?.let { version ->
version satisfies constraint
} ?: false
@ -401,49 +343,3 @@ data class Server(
}
}
}
/**
* Servers that are known to implement the Mastodon client API
*/
enum class ServerKind {
AKKOMA,
FEDIBIRD,
FIREFISH,
FRIENDICA,
GLITCH,
GOTOSOCIAL,
HOMETOWN,
ICESHRIMP,
MASTODON,
PLEROMA,
PIXELFED,
SHARKEY,
/**
* Catch-all for servers we don't recognise but that responded to either
* /api/v1/instance or /api/v2/instance
*/
UNKNOWN,
;
companion object {
fun from(s: NodeInfo.Software) = when (s.name.lowercase()) {
"akkoma" -> AKKOMA
"fedibird" -> FEDIBIRD
"firefish" -> FIREFISH
"friendica" -> FRIENDICA
"gotosocial" -> GOTOSOCIAL
"hometown" -> HOMETOWN
"iceshrimp" -> ICESHRIMP
"mastodon" -> {
// Glitch doesn't report a different software name it stuffs it
// in the version (https://github.com/glitch-soc/mastodon/issues/2582).
if (s.version.contains("+glitch")) GLITCH else MASTODON
}
"pixelfed" -> PIXELFED
"pleroma" -> PLEROMA
"sharkey" -> SHARKEY
else -> UNKNOWN
}
}
}

View File

@ -19,10 +19,9 @@ package app.pachli.core.network.model.nodeinfo
import androidx.annotation.StringRes
import app.pachli.core.common.PachliError
import app.pachli.core.model.NodeInfo
import app.pachli.core.model.NodeInfo.Software
import app.pachli.core.network.R
import app.pachli.core.network.model.nodeinfo.NodeInfo.Error.NoSoftwareBlock
import app.pachli.core.network.model.nodeinfo.NodeInfo.Error.NoSoftwareName
import app.pachli.core.network.model.nodeinfo.NodeInfo.Error.NoSoftwareVersion
import com.github.michaelbull.result.Err
import com.github.michaelbull.result.Ok
import com.github.michaelbull.result.Result
@ -49,30 +48,20 @@ data class UnvalidatedJrd(val links: List<Link>) {
data class UnvalidatedNodeInfo(val software: Software?) {
@JsonClass(generateAdapter = true)
data class Software(val name: String?, val version: String?)
}
/**
* A validated NodeInfo.
*
* See https://nodeinfo.diaspora.software/protocol.html and
* https://nodeinfo.diaspora.software/schema.html.
*/
data class NodeInfo(val software: Software) {
data class Software(
/** Software name, won't be null, empty, or blank */
val name: String,
/** Software version, won't be null, empty, or blank */
val version: String,
)
companion object {
fun from(nodeInfo: UnvalidatedNodeInfo): Result<NodeInfo, Error> {
fun validate(): Result<NodeInfo, Error> {
return when {
nodeInfo.software == null -> Err(NoSoftwareBlock)
nodeInfo.software.name.isNullOrBlank() -> Err(NoSoftwareName)
nodeInfo.software.version.isNullOrBlank() -> Err(NoSoftwareVersion)
else -> Ok(NodeInfo(Software(nodeInfo.software.name, nodeInfo.software.version)))
}
software == null -> Err(Error.NoSoftwareBlock)
software.name.isNullOrBlank() -> Err(Error.NoSoftwareName)
software.version.isNullOrBlank() -> Err(Error.NoSoftwareVersion)
else -> Ok(
NodeInfo(
NodeInfo.Software(
software.name,
software.version,
),
),
)
}
}

View File

@ -17,29 +17,31 @@
package app.pachli.core.network
import app.pachli.core.network.ServerKind.AKKOMA
import app.pachli.core.network.ServerKind.FIREFISH
import app.pachli.core.network.ServerKind.FRIENDICA
import app.pachli.core.network.ServerKind.GOTOSOCIAL
import app.pachli.core.network.ServerKind.MASTODON
import app.pachli.core.network.ServerKind.PLEROMA
import app.pachli.core.network.ServerKind.UNKNOWN
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_FILTERS_CLIENT
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_FILTERS_SERVER
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_BY_DATE
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_FROM
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_AUDIO
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_EMBED
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_IMAGE
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_LINK
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_MEDIA
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_POLL
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_VIDEO
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IN_LIBRARY
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IS_REPLY
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IS_SENSITIVE
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_LANGUAGE
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_STATUSES_TRANSLATE
import app.pachli.core.model.NodeInfo
import app.pachli.core.model.ServerKind
import app.pachli.core.model.ServerKind.AKKOMA
import app.pachli.core.model.ServerKind.FIREFISH
import app.pachli.core.model.ServerKind.FRIENDICA
import app.pachli.core.model.ServerKind.GOTOSOCIAL
import app.pachli.core.model.ServerKind.MASTODON
import app.pachli.core.model.ServerKind.PLEROMA
import app.pachli.core.model.ServerKind.UNKNOWN
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_FILTERS_CLIENT
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_FILTERS_SERVER
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_BY_DATE
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_FROM
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_AUDIO
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_EMBED
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_IMAGE
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_LINK
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_MEDIA
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_POLL
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_VIDEO
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IN_LIBRARY
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IS_REPLY
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IS_SENSITIVE
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_LANGUAGE
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_STATUSES_TRANSLATE
import app.pachli.core.network.model.Account
import app.pachli.core.network.model.Configuration
import app.pachli.core.network.model.Contact
@ -54,7 +56,6 @@ import app.pachli.core.network.model.Registrations
import app.pachli.core.network.model.Thumbnail
import app.pachli.core.network.model.Usage
import app.pachli.core.network.model.Users
import app.pachli.core.network.model.nodeinfo.NodeInfo
import com.github.michaelbull.result.Ok
import com.github.michaelbull.result.Result
import com.google.common.truth.Truth.assertWithMessage