123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583 |
- /*
- * Nextcloud Talk - Android Client
- *
- * SPDX-FileCopyrightText: 2021-2022 Marcel Hibbe <dev@mhibbe.de>
- * SPDX-FileCopyrightText: 2021 Tim Krüger <t@timkrueger.me>
- * SPDX-FileCopyrightText: 2017-2018 Mario Danic <mario@lovelyhq.com>
- * SPDX-License-Identifier: GPL-3.0-or-later
- */
- package com.nextcloud.talk.utils
- import android.net.Uri
- import android.text.TextUtils
- import android.util.Log
- import com.nextcloud.talk.BuildConfig
- import com.nextcloud.talk.R
- import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
- import com.nextcloud.talk.data.user.model.User
- import com.nextcloud.talk.models.RetrofitBucket
- import com.nextcloud.talk.models.json.capabilities.SpreedCapability
- import com.nextcloud.talk.utils.CapabilitiesUtil.hasSpreedFeatureCapability
- import okhttp3.Credentials.basic
- import java.nio.charset.StandardCharsets
- @Suppress("TooManyFunctions")
- object ApiUtils {
- private val TAG = ApiUtils::class.java.simpleName
- const val API_V1 = 1
- private const val API_V2 = 2
- const val API_V3 = 3
- const val API_V4 = 4
- private const val AVATAR_SIZE_BIG = 512
- private const val AVATAR_SIZE_SMALL = 64
- private const val OCS_API_VERSION = "/ocs/v2.php"
- private const val SPREED_API_VERSION = "/apps/spreed/api/v1"
- private const val SPREED_API_BASE = "$OCS_API_VERSION/apps/spreed/api/v"
- @JvmStatic
- val userAgent = "Mozilla/5.0 (Android) Nextcloud-Talk v"
- get() = field + BuildConfig.VERSION_NAME
- @Deprecated(
- "This is only supported on API v1-3, in API v4+ please use " +
- "{@link ApiUtils#getUrlForAttendees(int, String, String)} instead."
- )
- fun getUrlForRemovingParticipantFromConversation(baseUrl: String?, roomToken: String?, isGuest: Boolean): String {
- var url = getUrlForParticipants(API_V1, baseUrl, roomToken)
- if (isGuest) {
- url += "/guests"
- }
- return url
- }
- private fun getRetrofitBucketForContactsSearch(baseUrl: String, searchQuery: String?): RetrofitBucket {
- var query = searchQuery
- val retrofitBucket = RetrofitBucket()
- retrofitBucket.url = "$baseUrl$OCS_API_VERSION/apps/files_sharing/api/v1/sharees"
- val queryMap: MutableMap<String, String> = HashMap()
- if (query == null) {
- query = ""
- }
- queryMap["format"] = "json"
- queryMap["search"] = query
- queryMap["itemType"] = "call"
- retrofitBucket.queryMap = queryMap
- return retrofitBucket
- }
- fun getUrlForFilePreviewWithRemotePath(baseUrl: String, remotePath: String?, px: Int): String {
- return (
- baseUrl + "/index.php/core/preview.png?file=" +
- Uri.encode(remotePath, "UTF-8") +
- "&x=" + px + "&y=" + px + "&a=1&mode=cover&forceIcon=1"
- )
- }
- fun getUrlForFilePreviewWithFileId(baseUrl: String, fileId: String, px: Int): String {
- return (
- baseUrl + "/index.php/core/preview?fileId=" +
- fileId + "&x=" + px + "&y=" + px + "&a=1&mode=cover&forceIcon=1"
- )
- }
- fun getSharingUrl(baseUrl: String): String {
- return "$baseUrl$OCS_API_VERSION/apps/files_sharing/api/v1/shares"
- }
- fun getRetrofitBucketForContactsSearchFor14(baseUrl: String, searchQuery: String?): RetrofitBucket {
- val retrofitBucket = getRetrofitBucketForContactsSearch(baseUrl, searchQuery)
- retrofitBucket.url = "$baseUrl$OCS_API_VERSION/core/autocomplete/get"
- retrofitBucket.queryMap?.put("itemId", "new")
- return retrofitBucket
- }
- @JvmStatic
- fun getUrlForCapabilities(baseUrl: String): String {
- return "$baseUrl$OCS_API_VERSION/cloud/capabilities"
- }
- @Throws(NoSupportedApiException::class)
- fun getCallApiVersion(capabilities: User, versions: IntArray): Int {
- return getConversationApiVersion(capabilities, versions)
- }
- @JvmStatic
- @Throws(NoSupportedApiException::class)
- @Suppress("ReturnCount")
- fun getConversationApiVersion(user: User, versions: IntArray): Int {
- var hasApiV4 = false
- for (version in versions) {
- hasApiV4 = hasApiV4 or (version == API_V4)
- }
- if (!hasApiV4) {
- val e = Exception("Api call did not try conversation-v4 api")
- Log.d(TAG, e.message, e)
- }
- for (version in versions) {
- if (user.hasSpreedFeatureCapability("conversation-v$version")) {
- return version
- }
- // Fallback for old API versions
- if (version == API_V1 || version == API_V2) {
- if (user.hasSpreedFeatureCapability("conversation-v2")) {
- return version
- }
- if (version == API_V1 &&
- user.hasSpreedFeatureCapability("mention-flag") &&
- !user.hasSpreedFeatureCapability("conversation-v4")
- ) {
- return version
- }
- }
- }
- throw NoSupportedApiException()
- }
- @JvmStatic
- @Throws(NoSupportedApiException::class)
- @Suppress("ReturnCount")
- fun getSignalingApiVersion(user: User, versions: IntArray): Int {
- val spreedCapabilities = user.capabilities!!.spreedCapability
- for (version in versions) {
- if (spreedCapabilities != null) {
- if (spreedCapabilities.features!!.contains("signaling-v$version")) {
- return version
- }
- if (version == API_V2 &&
- hasSpreedFeatureCapability(spreedCapabilities, SpreedFeatures.SIP_SUPPORT) &&
- !hasSpreedFeatureCapability(spreedCapabilities, SpreedFeatures.SIGNALING_V3)
- ) {
- return version
- }
- if (version == API_V1 &&
- !hasSpreedFeatureCapability(spreedCapabilities, SpreedFeatures.SIGNALING_V3)
- ) {
- // Has no capability, we just assume it is always there when there is no v3 or later
- return version
- }
- }
- }
- throw NoSupportedApiException()
- }
- @JvmStatic
- @Throws(NoSupportedApiException::class)
- fun getChatApiVersion(spreedCapabilities: SpreedCapability, versions: IntArray): Int {
- for (version in versions) {
- if (version == API_V1 && hasSpreedFeatureCapability(spreedCapabilities, SpreedFeatures.CHAT_V2)) {
- // Do not question that chat-v2 capability shows the availability of api/v1/ endpoint *see no evil*
- return version
- }
- }
- throw NoSupportedApiException()
- }
- private fun getUrlForApi(version: Int, baseUrl: String?): String {
- return baseUrl + SPREED_API_BASE + version
- }
- fun getUrlForRooms(version: Int, baseUrl: String?): String {
- return getUrlForApi(version, baseUrl) + "/room"
- }
- @JvmStatic
- fun getUrlForRoom(version: Int, baseUrl: String?, token: String?): String {
- return getUrlForRooms(version, baseUrl) + "/" + token
- }
- fun getUrlForAttendees(version: Int, baseUrl: String?, token: String?): String {
- return getUrlForRoom(version, baseUrl, token) + "/attendees"
- }
- fun getUrlForParticipants(version: Int, baseUrl: String?, token: String?): String {
- if (token.isNullOrEmpty()) {
- Log.e(TAG, "token was null or empty")
- }
- return getUrlForRoom(version, baseUrl, token) + "/participants"
- }
- fun getUrlForParticipantsActive(version: Int, baseUrl: String?, token: String?): String {
- return getUrlForParticipants(version, baseUrl, token) + "/active"
- }
- @JvmStatic
- fun getUrlForParticipantsSelf(version: Int, baseUrl: String?, token: String?): String {
- return getUrlForParticipants(version, baseUrl, token) + "/self"
- }
- fun getUrlForParticipantsResendInvitations(version: Int, baseUrl: String?, token: String?): String {
- return getUrlForParticipants(version, baseUrl, token) + "/resend-invitations"
- }
- fun getUrlForRoomFavorite(version: Int, baseUrl: String?, token: String?): String {
- return getUrlForRoom(version, baseUrl, token) + "/favorite"
- }
- fun getUrlForRoomModerators(version: Int, baseUrl: String?, token: String?): String {
- return getUrlForRoom(version, baseUrl, token) + "/moderators"
- }
- @JvmStatic
- fun getUrlForRoomNotificationLevel(version: Int, baseUrl: String?, token: String?): String {
- return getUrlForRoom(version, baseUrl, token) + "/notify"
- }
- fun getUrlForRoomPublic(version: Int, baseUrl: String?, token: String?): String {
- return getUrlForRoom(version, baseUrl, token) + "/public"
- }
- fun getUrlForRoomPassword(version: Int, baseUrl: String?, token: String?): String {
- return getUrlForRoom(version, baseUrl, token) + "/password"
- }
- fun getUrlForRoomReadOnlyState(version: Int, baseUrl: String?, token: String?): String {
- return getUrlForRoom(version, baseUrl, token) + "/read-only"
- }
- fun getUrlForRoomWebinaryLobby(version: Int, baseUrl: String?, token: String?): String {
- return getUrlForRoom(version, baseUrl, token) + "/webinar/lobby"
- }
- @JvmStatic
- fun getUrlForRoomNotificationCalls(version: Int, baseUrl: String?, token: String?): String {
- return getUrlForRoom(version, baseUrl, token) + "/notify-calls"
- }
- fun getUrlForCall(version: Int, baseUrl: String?, token: String): String {
- return getUrlForApi(version, baseUrl) + "/call/" + token
- }
- fun getUrlForChat(version: Int, baseUrl: String?, token: String): String {
- return getUrlForApi(version, baseUrl) + "/chat/" + token
- }
- @JvmStatic
- fun getUrlForMentionSuggestions(version: Int, baseUrl: String?, token: String): String {
- return getUrlForChat(version, baseUrl, token) + "/mentions"
- }
- fun getUrlForChatMessage(version: Int, baseUrl: String?, token: String, messageId: String): String {
- return getUrlForChat(version, baseUrl, token) + "/" + messageId
- }
- fun getUrlForChatSharedItems(version: Int, baseUrl: String?, token: String): String {
- return getUrlForChat(version, baseUrl, token) + "/share"
- }
- fun getUrlForChatSharedItemsOverview(version: Int, baseUrl: String?, token: String): String {
- return getUrlForChatSharedItems(version, baseUrl, token) + "/overview"
- }
- fun getUrlForSignaling(version: Int, baseUrl: String?): String {
- return getUrlForApi(version, baseUrl) + "/signaling"
- }
- @JvmStatic
- fun getUrlForSignalingBackend(version: Int, baseUrl: String?): String {
- return getUrlForSignaling(version, baseUrl) + "/backend"
- }
- @JvmStatic
- fun getUrlForSignalingSettings(version: Int, baseUrl: String?): String {
- return getUrlForSignaling(version, baseUrl) + "/settings"
- }
- fun getUrlForSignaling(version: Int, baseUrl: String?, token: String): String {
- return getUrlForSignaling(version, baseUrl) + "/" + token
- }
- fun getUrlForOpenConversations(version: Int, baseUrl: String?): String {
- return getUrlForApi(version, baseUrl) + "/listed-room"
- }
- @Suppress("LongParameterList")
- fun getRetrofitBucketForCreateRoom(
- version: Int,
- baseUrl: String?,
- roomType: String,
- source: String?,
- invite: String?,
- conversationName: String?
- ): RetrofitBucket {
- val retrofitBucket = RetrofitBucket()
- retrofitBucket.url = getUrlForRooms(version, baseUrl)
- val queryMap: MutableMap<String, String> = HashMap()
- queryMap["roomType"] = roomType
- if (invite != null) {
- queryMap["invite"] = invite
- }
- if (source != null) {
- queryMap["source"] = source
- }
- if (conversationName != null) {
- queryMap["roomName"] = conversationName
- }
- retrofitBucket.queryMap = queryMap
- return retrofitBucket
- }
- @JvmStatic
- fun getRetrofitBucketForAddParticipant(
- version: Int,
- baseUrl: String?,
- token: String?,
- user: String
- ): RetrofitBucket {
- val retrofitBucket = RetrofitBucket()
- retrofitBucket.url = getUrlForParticipants(version, baseUrl, token)
- val queryMap: MutableMap<String, String> = HashMap()
- queryMap["newParticipant"] = user
- retrofitBucket.queryMap = queryMap
- return retrofitBucket
- }
- @JvmStatic
- fun getRetrofitBucketForAddParticipantWithSource(
- version: Int,
- baseUrl: String?,
- token: String?,
- source: String,
- id: String
- ): RetrofitBucket {
- val retrofitBucket = getRetrofitBucketForAddParticipant(version, baseUrl, token, id)
- retrofitBucket.queryMap?.put("source", source)
- return retrofitBucket
- }
- fun getUrlForUserProfile(baseUrl: String): String {
- return "$baseUrl$OCS_API_VERSION/cloud/user"
- }
- fun getUrlForUserData(baseUrl: String, userId: String): String {
- return "$baseUrl$OCS_API_VERSION/cloud/users/$userId"
- }
- fun getUrlForUserSettings(baseUrl: String): String {
- // FIXME Introduce API version
- return "$baseUrl$OCS_API_VERSION$SPREED_API_VERSION/settings/user"
- }
- fun getUrlPostfixForStatus(): String {
- return "/status.php"
- }
- @JvmStatic
- fun getUrlForAvatar(baseUrl: String?, name: String?, requestBigSize: Boolean): String {
- val avatarSize = if (requestBigSize) AVATAR_SIZE_BIG else AVATAR_SIZE_SMALL
- return baseUrl + "/index.php/avatar/" + Uri.encode(name) + "/" + avatarSize
- }
- @JvmStatic
- fun getUrlForFederatedAvatar(
- baseUrl: String,
- token: String,
- cloudId: String,
- darkTheme: Int,
- requestBigSize: Boolean
- ): String {
- val avatarSize = if (requestBigSize) AVATAR_SIZE_BIG else AVATAR_SIZE_SMALL
- val url = "$baseUrl$OCS_API_VERSION$SPREED_API_VERSION/proxy/$token/user-avatar/$avatarSize"
- return "$url?cloudId=$cloudId&darkTheme=$darkTheme"
- }
- @JvmStatic
- fun getUrlForGuestAvatar(baseUrl: String?, name: String?, requestBigSize: Boolean): String {
- val avatarSize = if (requestBigSize) AVATAR_SIZE_BIG else AVATAR_SIZE_SMALL
- return baseUrl + "/index.php/avatar/guest/" + Uri.encode(name) + "/" + avatarSize
- }
- fun getUrlForConversationAvatar(version: Int, baseUrl: String?, token: String?): String {
- return getUrlForRoom(version, baseUrl, token) + "/avatar"
- }
- fun getUrlForConversationAvatarWithVersion(
- version: Int,
- baseUrl: String?,
- token: String?,
- isDark: Boolean,
- avatarVersion: String?
- ): String {
- var isDarkString = ""
- if (isDark) {
- isDarkString = "/dark"
- }
- var avatarVersionString = ""
- if (avatarVersion != null) {
- avatarVersionString = "?avatarVersion=$avatarVersion"
- }
- return getUrlForRoom(version, baseUrl, token) + "/avatar" + isDarkString + avatarVersionString
- }
- @JvmStatic
- fun getCredentials(username: String?, token: String?): String? {
- return if (TextUtils.isEmpty(username) && TextUtils.isEmpty(token)) {
- null
- } else {
- basic(username!!, token!!, StandardCharsets.UTF_8)
- }
- }
- @JvmStatic
- fun getUrlNextcloudPush(baseUrl: String): String {
- return "$baseUrl$OCS_API_VERSION/apps/notifications/api/v2/push"
- }
- @JvmStatic
- fun getUrlPushProxy(): String {
- return sharedApplication!!.applicationContext.resources.getString(R.string.nc_push_server_url) + "/devices"
- }
- // see https://github.com/nextcloud/notifications/blob/master/docs/ocs-endpoint-v2.md
- fun getUrlForNcNotificationWithId(baseUrl: String, notificationId: String): String {
- return "$baseUrl$OCS_API_VERSION/apps/notifications/api/v2/notifications/$notificationId"
- }
- fun getUrlForSearchByNumber(baseUrl: String): String {
- return "$baseUrl$OCS_API_VERSION/cloud/users/search/by-phone"
- }
- fun getUrlForFileUpload(baseUrl: String, user: String, remotePath: String): String {
- return "$baseUrl/remote.php/dav/files/$user$remotePath"
- }
- fun getUrlForChunkedUpload(baseUrl: String, user: String): String {
- return "$baseUrl/remote.php/dav/uploads/$user"
- }
- fun getUrlForFileDownload(baseUrl: String, user: String, remotePath: String): String {
- return "$baseUrl/remote.php/dav/files/$user/$remotePath"
- }
- fun getUrlForTempAvatar(baseUrl: String): String {
- return "$baseUrl$OCS_API_VERSION/apps/spreed/temp-user-avatar"
- }
- fun getUrlForUserFields(baseUrl: String): String {
- return "$baseUrl$OCS_API_VERSION/cloud/user/fields"
- }
- fun getUrlToSendLocation(version: Int, baseUrl: String?, roomToken: String): String {
- return getUrlForChat(version, baseUrl, roomToken) + "/share"
- }
- fun getUrlForHoverCard(baseUrl: String, userId: String): String {
- return baseUrl + OCS_API_VERSION +
- "/hovercard/v1/" + userId
- }
- fun getUrlForChatReadMarker(version: Int, baseUrl: String?, roomToken: String): String {
- return getUrlForChat(version, baseUrl, roomToken) + "/read"
- }
- /*
- * OCS Status API
- */
- @JvmStatic
- fun getUrlForStatus(baseUrl: String): String {
- return "$baseUrl$OCS_API_VERSION/apps/user_status/api/v1/user_status"
- }
- fun getUrlForSetStatusType(baseUrl: String): String {
- return getUrlForStatus(baseUrl) + "/status"
- }
- fun getUrlForPredefinedStatuses(baseUrl: String): String {
- return "$baseUrl$OCS_API_VERSION/apps/user_status/api/v1/predefined_statuses"
- }
- fun getUrlForStatusMessage(baseUrl: String): String {
- return getUrlForStatus(baseUrl) + "/message"
- }
- fun getUrlForSetCustomStatus(baseUrl: String): String {
- return "$baseUrl$OCS_API_VERSION/apps/user_status/api/v1/user_status/message/custom"
- }
- fun getUrlForSetPredefinedStatus(baseUrl: String): String {
- return "$baseUrl$OCS_API_VERSION/apps/user_status/api/v1/user_status/message/predefined"
- }
- fun getUrlForUserStatuses(baseUrl: String): String {
- return "$baseUrl$OCS_API_VERSION/apps/user_status/api/v1/statuses"
- }
- fun getUrlForMessageReaction(baseUrl: String, roomToken: String, messageId: String): String {
- return "$baseUrl$OCS_API_VERSION$SPREED_API_VERSION/reaction/$roomToken/$messageId"
- }
- fun getUrlForUnifiedSearch(baseUrl: String, providerId: String): String {
- return "$baseUrl$OCS_API_VERSION/search/providers/$providerId/search"
- }
- fun getUrlForPoll(baseUrl: String, roomToken: String, pollId: String): String {
- return getUrlForPoll(baseUrl, roomToken) + "/" + pollId
- }
- fun getUrlForPoll(baseUrl: String, roomToken: String): String {
- return "$baseUrl$OCS_API_VERSION$SPREED_API_VERSION/poll/$roomToken"
- }
- @JvmStatic
- fun getUrlForMessageExpiration(version: Int, baseUrl: String?, token: String?): String {
- return getUrlForRoom(version, baseUrl, token) + "/message-expiration"
- }
- fun getUrlForOpenGraph(baseUrl: String): String {
- return "$baseUrl$OCS_API_VERSION/references/resolve"
- }
- fun getUrlForRecording(version: Int, baseUrl: String?, token: String): String {
- return getUrlForApi(version, baseUrl) + "/recording/" + token
- }
- fun getUrlForRequestAssistance(version: Int, baseUrl: String?, token: String): String {
- return getUrlForApi(version, baseUrl) + "/breakout-rooms/" + token + "/request-assistance"
- }
- fun getUrlForConversationDescription(version: Int, baseUrl: String?, token: String?): String {
- return getUrlForRoom(version, baseUrl, token) + "/description"
- }
- fun getUrlForTranslation(baseUrl: String): String {
- return "$baseUrl$OCS_API_VERSION/translation/translate"
- }
- fun getUrlForLanguages(baseUrl: String): String {
- return "$baseUrl$OCS_API_VERSION/translation/languages"
- }
- fun getUrlForReminder(user: User, roomToken: String, messageId: String, version: Int): String {
- val url = getUrlForChatMessage(version, user.baseUrl!!, roomToken, messageId)
- return "$url/reminder"
- }
- fun getUrlForRecordingConsent(version: Int, baseUrl: String?, token: String?): String {
- return getUrlForRoom(version, baseUrl, token) + "/recording-consent"
- }
- fun getUrlForInvitation(baseUrl: String): String {
- return baseUrl + OCS_API_VERSION + SPREED_API_VERSION + "/federation/invitation"
- }
- fun getUrlForInvitationAccept(baseUrl: String, id: Int): String {
- return getUrlForInvitation(baseUrl) + "/" + id
- }
- fun getUrlForInvitationReject(baseUrl: String, id: Int): String {
- return getUrlForInvitation(baseUrl) + "/" + id
- }
- @JvmStatic
- fun getUrlForRoomCapabilities(version: Int, baseUrl: String?, token: String?): String {
- return getUrlForRooms(version, baseUrl) + "/" + token + "/capabilities"
- }
- fun getUrlForBans(baseUrl: String, token: String): String {
- return "$baseUrl/ocs/v1.php$SPREED_API_VERSION/ban/$token"
- }
- fun getUrlForUnban(baseUrl: String, token: String, banId: Int): String {
- return "${getUrlForBans(baseUrl, token)}/$banId"
- }
- }
|