mirror of
				https://github.com/KokaKiwi/BarInsta
				synced 2025-10-31 03:25:34 +00:00 
			
		
		
		
	More suspend funs
This commit is contained in:
		
							parent
							
								
									538a1406a6
								
							
						
					
					
						commit
						741a997424
					
				| @ -88,9 +88,9 @@ import awais.instagrabber.repositories.requests.directmessages.ThreadIdOrUserIds | ||||
| import awais.instagrabber.repositories.responses.Media; | ||||
| import awais.instagrabber.repositories.responses.StoryStickerResponse; | ||||
| import awais.instagrabber.repositories.responses.directmessages.DirectThread; | ||||
| import awais.instagrabber.repositories.responses.directmessages.DirectThreadBroadcastResponse; | ||||
| import awais.instagrabber.utils.Constants; | ||||
| import awais.instagrabber.utils.CookieUtils; | ||||
| import awais.instagrabber.utils.CoroutineUtilsKt; | ||||
| import awais.instagrabber.utils.DownloadUtils; | ||||
| import awais.instagrabber.utils.TextUtils; | ||||
| import awais.instagrabber.utils.Utils; | ||||
| @ -231,32 +231,21 @@ public class StoryViewerFragment extends Fragment { | ||||
|                                     return; | ||||
|                                 } | ||||
|                                 final DirectThread thread = response.body(); | ||||
|                                 final Call<DirectThreadBroadcastResponse> request = directMessagesService.broadcastStoryReply( | ||||
|                                 directMessagesService.broadcastStoryReply( | ||||
|                                         ThreadIdOrUserIds.of(thread.getThreadId()), | ||||
|                                         input.getText().toString(), | ||||
|                                         currentStory.getStoryMediaId(), | ||||
|                                         String.valueOf(currentStory.getUserId()) | ||||
|                                 ); | ||||
|                                 request.enqueue(new Callback<DirectThreadBroadcastResponse>() { | ||||
|                                     @Override | ||||
|                                     public void onResponse(@NonNull final Call<DirectThreadBroadcastResponse> call, | ||||
|                                                            @NonNull final Response<DirectThreadBroadcastResponse> response) { | ||||
|                                         if (!response.isSuccessful()) { | ||||
|                                             Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); | ||||
|                                             return; | ||||
|                                         } | ||||
|                                         Toast.makeText(context, R.string.answered_story, Toast.LENGTH_SHORT).show(); | ||||
|                                     } | ||||
|                                         String.valueOf(currentStory.getUserId()), | ||||
|                                         CoroutineUtilsKt.getContinuation((directThreadBroadcastResponse, throwable) -> { | ||||
|                                             if (throwable != null) { | ||||
|                                                 Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); | ||||
|                                                 Log.e(TAG, "onFailure: ", throwable); | ||||
|                                                 return; | ||||
|                                             } | ||||
|                                             Toast.makeText(context, R.string.answered_story, Toast.LENGTH_SHORT).show(); | ||||
|                                         }) | ||||
| 
 | ||||
|                                     @Override | ||||
|                                     public void onFailure(@NonNull final Call<DirectThreadBroadcastResponse> call, @NonNull final Throwable t) { | ||||
|                                         try { | ||||
|                                             Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); | ||||
|                                             Log.e(TAG, "onFailure: ", t); | ||||
|                                         } catch (Throwable ignored) { | ||||
|                                         } | ||||
|                                     } | ||||
|                                 }); | ||||
|                                 ); | ||||
|                             } | ||||
| 
 | ||||
|                             @Override | ||||
|  | ||||
| @ -12,7 +12,6 @@ import awais.instagrabber.models.Resource.Companion.success | ||||
| import awais.instagrabber.repositories.requests.directmessages.ThreadIdOrUserIds.Companion.of | ||||
| import awais.instagrabber.repositories.responses.User | ||||
| import awais.instagrabber.repositories.responses.directmessages.DirectThread | ||||
| import awais.instagrabber.repositories.responses.directmessages.DirectThreadBroadcastResponse | ||||
| import awais.instagrabber.repositories.responses.directmessages.RankedRecipient | ||||
| import awais.instagrabber.utils.Constants | ||||
| import awais.instagrabber.utils.Utils | ||||
| @ -21,6 +20,8 @@ import awais.instagrabber.utils.getUserIdFromCookie | ||||
| import awais.instagrabber.webservices.DirectMessagesService | ||||
| import awais.instagrabber.webservices.DirectMessagesService.Companion.getInstance | ||||
| import kotlinx.coroutines.CoroutineScope | ||||
| import kotlinx.coroutines.Dispatchers | ||||
| import kotlinx.coroutines.launch | ||||
| import retrofit2.Call | ||||
| import retrofit2.Callback | ||||
| import retrofit2.Response | ||||
| @ -137,7 +138,7 @@ object DirectMessagesManager { | ||||
|             // create thread and forward | ||||
|             createThread(recipient.user.pk) { (threadId) -> | ||||
|                 val threadIdTemp = threadId ?: return@createThread | ||||
|                 sendMedia(threadIdTemp, mediaId) { | ||||
|                 sendMedia(threadIdTemp, mediaId, scope) { | ||||
|                     if (refreshInbox) { | ||||
|                         inboxManager.refresh(scope) | ||||
|                     } | ||||
| @ -149,7 +150,7 @@ object DirectMessagesManager { | ||||
|         // just forward | ||||
|         val thread = recipient.thread | ||||
|         val threadId = thread.threadId ?: return | ||||
|         sendMedia(threadId, mediaId) { | ||||
|         sendMedia(threadId, mediaId, scope) { | ||||
|             if (refreshInbox) { | ||||
|                 inboxManager.refresh(scope) | ||||
|             } | ||||
| @ -160,55 +161,26 @@ object DirectMessagesManager { | ||||
|     private fun sendMedia( | ||||
|         threadId: String, | ||||
|         mediaId: String, | ||||
|         scope: CoroutineScope, | ||||
|         callback: (() -> Unit)?, | ||||
|     ): LiveData<Resource<Any?>> { | ||||
|         val data = MutableLiveData<Resource<Any?>>() | ||||
|         data.postValue(loading(null)) | ||||
|         val request = service.broadcastMediaShare( | ||||
|             UUID.randomUUID().toString(), | ||||
|             of(threadId), | ||||
|             mediaId | ||||
|         ) | ||||
|         request.enqueue(object : Callback<DirectThreadBroadcastResponse?> { | ||||
|             override fun onResponse( | ||||
|                 call: Call<DirectThreadBroadcastResponse?>, | ||||
|                 response: Response<DirectThreadBroadcastResponse?>, | ||||
|             ) { | ||||
|                 if (response.isSuccessful) { | ||||
|                     data.postValue(success(Any())) | ||||
|                     callback?.invoke() | ||||
|                     return | ||||
|                 } | ||||
|                 val errorBody = response.errorBody() | ||||
|                 if (errorBody != null) { | ||||
|                     try { | ||||
|                         val string = errorBody.string() | ||||
|                         val msg = String.format(Locale.US, | ||||
|                             "onResponse: url: %s, responseCode: %d, errorBody: %s", | ||||
|                             call.request().url().toString(), | ||||
|                             response.code(), | ||||
|                             string) | ||||
|                         Log.e(TAG, msg) | ||||
|                         data.postValue(error(msg, null)) | ||||
|                     } catch (e: IOException) { | ||||
|                         Log.e(TAG, "onResponse: ", e) | ||||
|                         data.postValue(error(e.message, null)) | ||||
|                     } | ||||
|                     callback?.invoke() | ||||
|                     return | ||||
|                 } | ||||
|                 val msg = "onResponse: request was not successful and response error body was null" | ||||
|                 Log.e(TAG, msg) | ||||
|                 data.postValue(error(msg, null)) | ||||
|         scope.launch(Dispatchers.IO) { | ||||
|             try { | ||||
|                 service.broadcastMediaShare( | ||||
|                     UUID.randomUUID().toString(), | ||||
|                     of(threadId), | ||||
|                     mediaId | ||||
|                 ) | ||||
|                 data.postValue(success(Any())) | ||||
|                 callback?.invoke() | ||||
|             } catch (e: Exception) { | ||||
|                 Log.e(TAG, "sendMedia: ", e) | ||||
|                 data.postValue(error(e.message, null)) | ||||
|                 callback?.invoke() | ||||
|             } | ||||
| 
 | ||||
|             override fun onFailure(call: Call<DirectThreadBroadcastResponse?>, t: Throwable) { | ||||
|                 Log.e(TAG, "onFailure: ", t) | ||||
|                 data.postValue(error(t.message, null)) | ||||
|                 callback?.invoke() | ||||
|             } | ||||
|         }) | ||||
|         } | ||||
|         return data | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -21,8 +21,6 @@ import kotlinx.coroutines.CoroutineScope | ||||
| import kotlinx.coroutines.Dispatchers | ||||
| import kotlinx.coroutines.launch | ||||
| import retrofit2.Call | ||||
| import retrofit2.Callback | ||||
| import retrofit2.Response | ||||
| import java.util.* | ||||
| import java.util.concurrent.TimeUnit | ||||
| 
 | ||||
| @ -66,49 +64,23 @@ class InboxManager private constructor(private val pending: Boolean) { | ||||
|                 inbox.postValue(error(e.message, currentDirectInbox)) | ||||
|                 hasOlder = false | ||||
|             } | ||||
|             // inboxRequest?.enqueue(object : Callback<DirectInboxResponse?> { | ||||
|             //     override fun onResponse(call: Call<DirectInboxResponse?>, response: Response<DirectInboxResponse?>) { | ||||
|             //         val body = response.body() | ||||
|             //         if (body == null) { | ||||
|             //             Log.e(TAG, "parseInboxResponse: Response is null") | ||||
|             //             inbox.postValue(error(R.string.generic_null_response, currentDirectInbox)) | ||||
|             //             hasOlder = false | ||||
|             //             return | ||||
|             //         } | ||||
|             // | ||||
|             //     } | ||||
|             // | ||||
|             //     override fun onFailure(call: Call<DirectInboxResponse?>, t: Throwable) { | ||||
|             //         Log.e(TAG, "Failed fetching dm inbox", t) | ||||
|             //         inbox.postValue(error(t.message, currentDirectInbox)) | ||||
|             //         hasOlder = false | ||||
|             //     } | ||||
|             // }) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fun fetchUnseenCount() { | ||||
|     fun fetchUnseenCount(scope: CoroutineScope) { | ||||
|         val unseenCountResource = unseenCount.value | ||||
|         if (unseenCountResource != null && unseenCountResource.status === Resource.Status.LOADING) return | ||||
|         stopCurrentUnseenCountRequest() | ||||
|         unseenCount.postValue(loading(currentUnseenCount)) | ||||
|         unseenCountRequest = service.fetchUnseenCount() | ||||
|         unseenCountRequest?.enqueue(object : Callback<DirectBadgeCount?> { | ||||
|             override fun onResponse(call: Call<DirectBadgeCount?>, response: Response<DirectBadgeCount?>) { | ||||
|                 val directBadgeCount = response.body() | ||||
|                 if (directBadgeCount == null) { | ||||
|                     Log.e(TAG, "onResponse: directBadgeCount Response is null") | ||||
|                     unseenCount.postValue(error(R.string.dms_inbox_error_null_count, currentUnseenCount)) | ||||
|                     return | ||||
|                 } | ||||
|         scope.launch(Dispatchers.IO) { | ||||
|             try { | ||||
|                 val directBadgeCount = service.fetchUnseenCount() | ||||
|                 unseenCount.postValue(success(directBadgeCount.badgeCount)) | ||||
|             } catch (e: Exception) { | ||||
|                 Log.e(TAG, "Failed fetching unseen count", e) | ||||
|                 unseenCount.postValue(error(e.message, currentUnseenCount)) | ||||
|             } | ||||
| 
 | ||||
|             override fun onFailure(call: Call<DirectBadgeCount?>, t: Throwable) { | ||||
|                 Log.e(TAG, "Failed fetching unseen count", t) | ||||
|                 unseenCount.postValue(error(t.message, currentUnseenCount)) | ||||
|             } | ||||
|         }) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fun refresh(scope: CoroutineScope) { | ||||
| @ -117,7 +89,7 @@ class InboxManager private constructor(private val pending: Boolean) { | ||||
|         hasOlder = true | ||||
|         fetchInbox(scope) | ||||
|         if (!pending) { | ||||
|             fetchUnseenCount() | ||||
|             fetchUnseenCount(scope) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -350,9 +322,5 @@ class InboxManager private constructor(private val pending: Boolean) { | ||||
|             val threads = inbox?.threads ?: emptyList() | ||||
|             ImmutableList.sortedCopyOf(THREAD_COMPARATOR, threads) | ||||
|         }) | ||||
|         // fetchInbox() | ||||
|         if (!pending) { | ||||
|             fetchUnseenCount() | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -10,11 +10,11 @@ import androidx.lifecycle.Transformations.distinctUntilChanged | ||||
| import androidx.lifecycle.Transformations.map | ||||
| import awais.instagrabber.R | ||||
| import awais.instagrabber.customviews.emoji.Emoji | ||||
| import awais.instagrabber.models.enums.DirectItemType.Companion.getName | ||||
| import awais.instagrabber.models.Resource | ||||
| import awais.instagrabber.models.Resource.Companion.error | ||||
| import awais.instagrabber.models.Resource.Companion.loading | ||||
| import awais.instagrabber.models.Resource.Companion.success | ||||
| import awais.instagrabber.models.enums.DirectItemType | ||||
| import awais.instagrabber.repositories.requests.UploadFinishOptions | ||||
| import awais.instagrabber.repositories.requests.VideoOptions | ||||
| import awais.instagrabber.repositories.requests.directmessages.ThreadIdOrUserIds | ||||
| @ -400,7 +400,7 @@ class ThreadManager private constructor( | ||||
|         return temp | ||||
|     } | ||||
| 
 | ||||
|     fun sendText(text: String): LiveData<Resource<Any?>> { | ||||
|     fun sendText(text: String, scope: CoroutineScope): LiveData<Resource<Any?>> { | ||||
|         val data = MutableLiveData<Resource<Any?>>() | ||||
|         val userId = getCurrentUserId(data) ?: return data | ||||
|         val clientContext = UUID.randomUUID().toString() | ||||
| @ -412,29 +412,36 @@ class ThreadManager private constructor( | ||||
|         data.postValue(loading(directItem)) | ||||
|         val repliedToItemId = replyToItemValue?.itemId | ||||
|         val repliedToClientContext = replyToItemValue?.clientContext | ||||
|         val request = service.broadcastText( | ||||
|             clientContext, | ||||
|             threadIdOrUserIds, | ||||
|             text, | ||||
|             repliedToItemId, | ||||
|             repliedToClientContext | ||||
|         ) | ||||
|         enqueueRequest(request, data, directItem) | ||||
|         scope.launch(Dispatchers.IO) { | ||||
|             try { | ||||
|                 val response = service.broadcastText( | ||||
|                     clientContext, | ||||
|                     threadIdOrUserIds, | ||||
|                     text, | ||||
|                     repliedToItemId, | ||||
|                     repliedToClientContext | ||||
|                 ) | ||||
|                 parseResponse(response, data, directItem) | ||||
|             } catch (e: Exception) { | ||||
|                 data.postValue(error(e.message, directItem)) | ||||
|                 Log.e(TAG, "sendText: ", e) | ||||
|             } | ||||
|         } | ||||
|         return data | ||||
|     } | ||||
| 
 | ||||
|     fun sendUri(entry: MediaController.MediaEntry): LiveData<Resource<Any?>> { | ||||
|     fun sendUri(entry: MediaController.MediaEntry, scope: CoroutineScope): LiveData<Resource<Any?>> { | ||||
|         val data = MutableLiveData<Resource<Any?>>() | ||||
|         val uri = Uri.fromFile(File(entry.path)) | ||||
|         if (!entry.isVideo) { | ||||
|             sendPhoto(data, uri, entry.width, entry.height) | ||||
|             sendPhoto(data, uri, entry.width, entry.height, scope) | ||||
|             return data | ||||
|         } | ||||
|         sendVideo(data, uri, entry.size, entry.duration, entry.width, entry.height) | ||||
|         sendVideo(data, uri, entry.size, entry.duration, entry.width, entry.height, scope) | ||||
|         return data | ||||
|     } | ||||
| 
 | ||||
|     fun sendUri(uri: Uri): LiveData<Resource<Any?>> { | ||||
|     fun sendUri(uri: Uri, scope: CoroutineScope): LiveData<Resource<Any?>> { | ||||
|         val data = MutableLiveData<Resource<Any?>>() | ||||
|         val mimeType = Utils.getMimeType(uri, contentResolver) | ||||
|         if (isEmpty(mimeType)) { | ||||
| @ -443,16 +450,16 @@ class ThreadManager private constructor( | ||||
|         } | ||||
|         val isPhoto = mimeType != null && mimeType.startsWith("image") | ||||
|         if (isPhoto) { | ||||
|             sendPhoto(data, uri) | ||||
|             sendPhoto(data, uri, scope) | ||||
|             return data | ||||
|         } | ||||
|         if (mimeType != null && mimeType.startsWith("video")) { | ||||
|             sendVideo(data, uri) | ||||
|             sendVideo(data, uri, scope) | ||||
|         } | ||||
|         return data | ||||
|     } | ||||
| 
 | ||||
|     fun sendAnimatedMedia(giphyGif: GiphyGif): LiveData<Resource<Any?>> { | ||||
|     fun sendAnimatedMedia(giphyGif: GiphyGif, scope: CoroutineScope): LiveData<Resource<Any?>> { | ||||
|         val data = MutableLiveData<Resource<Any?>>() | ||||
|         val userId = getCurrentUserId(data) ?: return data | ||||
|         val clientContext = UUID.randomUUID().toString() | ||||
| @ -460,12 +467,19 @@ class ThreadManager private constructor( | ||||
|         directItem.isPending = true | ||||
|         addItems(0, listOf(directItem)) | ||||
|         data.postValue(loading(directItem)) | ||||
|         val request = service.broadcastAnimatedMedia( | ||||
|             clientContext, | ||||
|             threadIdOrUserIds, | ||||
|             giphyGif | ||||
|         ) | ||||
|         enqueueRequest(request, data, directItem) | ||||
|         scope.launch(Dispatchers.IO) { | ||||
|             try { | ||||
|                 val request = service.broadcastAnimatedMedia( | ||||
|                     clientContext, | ||||
|                     threadIdOrUserIds, | ||||
|                     giphyGif | ||||
|                 ) | ||||
|                 parseResponse(request, data, directItem) | ||||
|             } catch (e: Exception) { | ||||
|                 data.postValue(error(e.message, directItem)) | ||||
|                 Log.e(TAG, "sendAnimatedMedia: ", e) | ||||
|             } | ||||
|         } | ||||
|         return data | ||||
|     } | ||||
| 
 | ||||
| @ -476,6 +490,7 @@ class ThreadManager private constructor( | ||||
|         samplingFreq: Int, | ||||
|         duration: Long, | ||||
|         byteLength: Long, | ||||
|         scope: CoroutineScope, | ||||
|     ) { | ||||
|         if (duration > 60000) { | ||||
|             // instagram does not allow uploading audio longer than 60 secs for Direct messages | ||||
| @ -502,14 +517,21 @@ class ThreadManager private constructor( | ||||
|                 uploadFinishRequest.enqueue(object : Callback<String?> { | ||||
|                     override fun onResponse(call: Call<String?>, response: Response<String?>) { | ||||
|                         if (response.isSuccessful) { | ||||
|                             val request = service.broadcastVoice( | ||||
|                                 clientContext, | ||||
|                                 threadIdOrUserIds, | ||||
|                                 uploadDmVoiceOptions.uploadId, | ||||
|                                 waveform, | ||||
|                                 samplingFreq | ||||
|                             ) | ||||
|                             enqueueRequest(request, data, directItem) | ||||
|                             scope.launch(Dispatchers.IO) { | ||||
|                                 try { | ||||
|                                     val request = service.broadcastVoice( | ||||
|                                         clientContext, | ||||
|                                         threadIdOrUserIds, | ||||
|                                         uploadDmVoiceOptions.uploadId, | ||||
|                                         waveform, | ||||
|                                         samplingFreq | ||||
|                                     ) | ||||
|                                     parseResponse(request, data, directItem) | ||||
|                                 } catch (e: Exception) { | ||||
|                                     data.postValue(error(e.message, directItem)) | ||||
|                                     Log.e(TAG, "sendVoice: ", e) | ||||
|                                 } | ||||
|                             } | ||||
|                             return | ||||
|                         } | ||||
|                         if (response.errorBody() != null) { | ||||
| @ -537,6 +559,7 @@ class ThreadManager private constructor( | ||||
|     fun sendReaction( | ||||
|         item: DirectItem, | ||||
|         emoji: Emoji, | ||||
|         scope: CoroutineScope, | ||||
|     ): LiveData<Resource<Any?>> { | ||||
|         val data = MutableLiveData<Resource<Any?>>() | ||||
|         val userId = getCurrentUserId(data) | ||||
| @ -557,18 +580,24 @@ class ThreadManager private constructor( | ||||
|             data.postValue(error("itemId is null", null)) | ||||
|             return data | ||||
|         } | ||||
|         val request = service.broadcastReaction( | ||||
|             clientContext, | ||||
|             threadIdOrUserIds, | ||||
|             itemId, | ||||
|             emojiUnicode, | ||||
|             false | ||||
|         ) | ||||
|         handleBroadcastReactionRequest(data, item, request) | ||||
|         scope.launch(Dispatchers.IO) { | ||||
|             try { | ||||
|                 service.broadcastReaction( | ||||
|                     clientContext, | ||||
|                     threadIdOrUserIds, | ||||
|                     itemId, | ||||
|                     emojiUnicode, | ||||
|                     false | ||||
|                 ) | ||||
|             } catch (e: Exception) { | ||||
|                 data.postValue(error(e.message, null)) | ||||
|                 Log.e(TAG, "sendReaction: ", e) | ||||
|             } | ||||
|         } | ||||
|         return data | ||||
|     } | ||||
| 
 | ||||
|     fun sendDeleteReaction(itemId: String): LiveData<Resource<Any?>> { | ||||
|     fun sendDeleteReaction(itemId: String, scope: CoroutineScope): LiveData<Resource<Any?>> { | ||||
|         val data = MutableLiveData<Resource<Any?>>() | ||||
|         val item = getItem(itemId) | ||||
|         if (item == null) { | ||||
| @ -588,8 +617,14 @@ class ThreadManager private constructor( | ||||
|             data.postValue(error("itemId is null", null)) | ||||
|             return data | ||||
|         } | ||||
|         val request = service.broadcastReaction(clientContext, threadIdOrUserIds, itemId1, null, true) | ||||
|         handleBroadcastReactionRequest(data, item, request) | ||||
|         scope.launch(Dispatchers.IO) { | ||||
|             try { | ||||
|                 service.broadcastReaction(clientContext, threadIdOrUserIds, itemId1, null, true) | ||||
|             } catch (e: Exception) { | ||||
|                 data.postValue(error(e.message, null)) | ||||
|                 Log.e(TAG, "sendDeleteReaction: ", e) | ||||
|             } | ||||
|         } | ||||
|         return data | ||||
|     } | ||||
| 
 | ||||
| @ -660,7 +695,7 @@ class ThreadManager private constructor( | ||||
|             data.postValue(error("item type is null", null)) | ||||
|             return data | ||||
|         } | ||||
|         val itemTypeName = getName(itemType) | ||||
|         val itemTypeName = DirectItemType.getName(itemType) | ||||
|         if (itemTypeName == null) { | ||||
|             Log.e(TAG, "forward: itemTypeName was null!") | ||||
|             data.postValue(error("itemTypeName is null", null)) | ||||
| @ -798,6 +833,7 @@ class ThreadManager private constructor( | ||||
|     private fun sendPhoto( | ||||
|         data: MutableLiveData<Resource<Any?>>, | ||||
|         uri: Uri, | ||||
|         scope: CoroutineScope, | ||||
|     ) { | ||||
|         try { | ||||
|             val dimensions = BitmapUtils.decodeDimensions(contentResolver, uri) | ||||
| @ -805,7 +841,7 @@ class ThreadManager private constructor( | ||||
|                 data.postValue(error("Decoding dimensions failed", null)) | ||||
|                 return | ||||
|             } | ||||
|             sendPhoto(data, uri, dimensions.first, dimensions.second) | ||||
|             sendPhoto(data, uri, dimensions.first, dimensions.second, scope) | ||||
|         } catch (e: IOException) { | ||||
|             data.postValue(error(e.message, null)) | ||||
|             Log.e(TAG, "sendPhoto: ", e) | ||||
| @ -817,6 +853,7 @@ class ThreadManager private constructor( | ||||
|         uri: Uri, | ||||
|         width: Int, | ||||
|         height: Int, | ||||
|         scope: CoroutineScope, | ||||
|     ) { | ||||
|         val userId = getCurrentUserId(data) ?: return | ||||
|         val clientContext = UUID.randomUUID().toString() | ||||
| @ -829,8 +866,15 @@ class ThreadManager private constructor( | ||||
|                 if (handleInvalidResponse(data, response)) return | ||||
|                 val response1 = response.response ?: return | ||||
|                 val uploadId = response1.optString("upload_id") | ||||
|                 val request = service.broadcastPhoto(clientContext, threadIdOrUserIds, uploadId) | ||||
|                 enqueueRequest(request, data, directItem) | ||||
|                 scope.launch(Dispatchers.IO) { | ||||
|                     try { | ||||
|                         val response2 = service.broadcastPhoto(clientContext, threadIdOrUserIds, uploadId) | ||||
|                         parseResponse(response2, data, directItem) | ||||
|                     } catch (e: Exception) { | ||||
|                         data.postValue(error(e.message, null)) | ||||
|                         Log.e(TAG, "sendPhoto: ", e) | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             override fun onFailure(t: Throwable) { | ||||
| @ -843,6 +887,7 @@ class ThreadManager private constructor( | ||||
|     private fun sendVideo( | ||||
|         data: MutableLiveData<Resource<Any?>>, | ||||
|         uri: Uri, | ||||
|         scope: CoroutineScope, | ||||
|     ) { | ||||
|         MediaUtils.getVideoInfo(contentResolver, uri, object : OnInfoLoadListener<VideoInfo?> { | ||||
|             override fun onLoad(info: VideoInfo?) { | ||||
| @ -850,7 +895,7 @@ class ThreadManager private constructor( | ||||
|                     data.postValue(error("Could not get the video info", null)) | ||||
|                     return | ||||
|                 } | ||||
|                 sendVideo(data, uri, info.size, info.duration, info.width, info.height) | ||||
|                 sendVideo(data, uri, info.size, info.duration, info.width, info.height, scope) | ||||
|             } | ||||
| 
 | ||||
|             override fun onFailure(t: Throwable) { | ||||
| @ -866,6 +911,7 @@ class ThreadManager private constructor( | ||||
|         duration: Long, | ||||
|         width: Int, | ||||
|         height: Int, | ||||
|         scope: CoroutineScope, | ||||
|     ) { | ||||
|         if (duration > 60000) { | ||||
|             // instagram does not allow uploading videos longer than 60 secs for Direct messages | ||||
| @ -892,14 +938,21 @@ class ThreadManager private constructor( | ||||
|                 uploadFinishRequest.enqueue(object : Callback<String?> { | ||||
|                     override fun onResponse(call: Call<String?>, response: Response<String?>) { | ||||
|                         if (response.isSuccessful) { | ||||
|                             val request = service.broadcastVideo( | ||||
|                                 clientContext, | ||||
|                                 threadIdOrUserIds, | ||||
|                                 uploadDmVideoOptions.uploadId, | ||||
|                                 "", | ||||
|                                 true | ||||
|                             ) | ||||
|                             enqueueRequest(request, data, directItem) | ||||
|                             scope.launch(Dispatchers.IO) { | ||||
|                                 try { | ||||
|                                     val response1 = service.broadcastVideo( | ||||
|                                         clientContext, | ||||
|                                         threadIdOrUserIds, | ||||
|                                         uploadDmVideoOptions.uploadId, | ||||
|                                         "", | ||||
|                                         true | ||||
|                                     ) | ||||
|                                     parseResponse(response1, data, directItem) | ||||
|                                 } catch (e: Exception) { | ||||
|                                     data.postValue(error(e.message, null)) | ||||
|                                     Log.e(TAG, "sendVideo: ", e) | ||||
|                                 } | ||||
|                             } | ||||
|                             return | ||||
|                         } | ||||
|                         if (response.errorBody() != null) { | ||||
| @ -924,64 +977,36 @@ class ThreadManager private constructor( | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     private fun enqueueRequest( | ||||
|         request: Call<DirectThreadBroadcastResponse?>, | ||||
|     private fun parseResponse( | ||||
|         response: DirectThreadBroadcastResponse, | ||||
|         data: MutableLiveData<Resource<Any?>>, | ||||
|         directItem: DirectItem, | ||||
|     ) { | ||||
|         request.enqueue(object : Callback<DirectThreadBroadcastResponse?> { | ||||
|             override fun onResponse( | ||||
|                 call: Call<DirectThreadBroadcastResponse?>, | ||||
|                 response: Response<DirectThreadBroadcastResponse?>, | ||||
|             ) { | ||||
|                 if (response.isSuccessful) { | ||||
|                     val broadcastResponse = response.body() | ||||
|                     if (broadcastResponse == null) { | ||||
|                         data.postValue(error(R.string.generic_null_response, directItem)) | ||||
|                         Log.e(TAG, "enqueueRequest: onResponse: response body is null") | ||||
|                         return | ||||
|                     } | ||||
|                     val payloadClientContext: String? | ||||
|                     val timestamp: Long | ||||
|                     val itemId: String? | ||||
|                     val payload = broadcastResponse.payload | ||||
|                     if (payload == null) { | ||||
|                         val messageMetadata = broadcastResponse.messageMetadata | ||||
|                         if (messageMetadata == null || messageMetadata.isEmpty()) { | ||||
|                             data.postValue(success(directItem)) | ||||
|                             return | ||||
|                         } | ||||
|                         val (clientContext, itemId1, timestamp1) = messageMetadata[0] | ||||
|                         payloadClientContext = clientContext | ||||
|                         itemId = itemId1 | ||||
|                         timestamp = timestamp1 | ||||
|                     } else { | ||||
|                         payloadClientContext = payload.clientContext | ||||
|                         timestamp = payload.timestamp | ||||
|                         itemId = payload.itemId | ||||
|                     } | ||||
|                     if (payloadClientContext == null) { | ||||
|                         data.postValue(error("clientContext in response was null", null)) | ||||
|                         return | ||||
|                     } | ||||
|                     updateItemSent(payloadClientContext, timestamp, itemId) | ||||
|                     data.postValue(success(directItem)) | ||||
|                     return | ||||
|                 } | ||||
|                 if (response.errorBody() != null) { | ||||
|                     handleErrorBody(call, response, data) | ||||
|                 } | ||||
|                 data.postValue(error(R.string.generic_failed_request, directItem)) | ||||
|         val payloadClientContext: String? | ||||
|         val timestamp: Long | ||||
|         val itemId: String? | ||||
|         val payload = response.payload | ||||
|         if (payload == null) { | ||||
|             val messageMetadata = response.messageMetadata | ||||
|             if (messageMetadata == null || messageMetadata.isEmpty()) { | ||||
|                 data.postValue(success(directItem)) | ||||
|                 return | ||||
|             } | ||||
| 
 | ||||
|             override fun onFailure( | ||||
|                 call: Call<DirectThreadBroadcastResponse?>, | ||||
|                 t: Throwable, | ||||
|             ) { | ||||
|                 data.postValue(error(t.message, directItem)) | ||||
|                 Log.e(TAG, "enqueueRequest: onFailure: ", t) | ||||
|             } | ||||
|         }) | ||||
|             val (clientContext, itemId1, timestamp1) = messageMetadata[0] | ||||
|             payloadClientContext = clientContext | ||||
|             itemId = itemId1 | ||||
|             timestamp = timestamp1 | ||||
|         } else { | ||||
|             payloadClientContext = payload.clientContext | ||||
|             timestamp = payload.timestamp | ||||
|             itemId = payload.itemId | ||||
|         } | ||||
|         if (payloadClientContext == null) { | ||||
|             data.postValue(error("clientContext in response was null", null)) | ||||
|             return | ||||
|         } | ||||
|         updateItemSent(payloadClientContext, timestamp, itemId) | ||||
|         data.postValue(success(directItem)) | ||||
|     } | ||||
| 
 | ||||
|     private fun updateItemSent( | ||||
| @ -1054,38 +1079,6 @@ class ThreadManager private constructor( | ||||
|             .firstOrNull() | ||||
|     } | ||||
| 
 | ||||
|     private fun handleBroadcastReactionRequest( | ||||
|         data: MutableLiveData<Resource<Any?>>, | ||||
|         item: DirectItem, | ||||
|         request: Call<DirectThreadBroadcastResponse?>, | ||||
|     ) { | ||||
|         request.enqueue(object : Callback<DirectThreadBroadcastResponse?> { | ||||
|             override fun onResponse( | ||||
|                 call: Call<DirectThreadBroadcastResponse?>, | ||||
|                 response: Response<DirectThreadBroadcastResponse?>, | ||||
|             ) { | ||||
|                 if (!response.isSuccessful) { | ||||
|                     if (response.errorBody() != null) { | ||||
|                         handleErrorBody(call, response, data) | ||||
|                         return | ||||
|                     } | ||||
|                     data.postValue(error(R.string.generic_failed_request, item)) | ||||
|                     return | ||||
|                 } | ||||
|                 val body = response.body() | ||||
|                 if (body == null) { | ||||
|                     data.postValue(error(R.string.generic_null_response, item)) | ||||
|                 } | ||||
|                 // otherwise nothing to do? maybe update the timestamp in the emoji? | ||||
|             } | ||||
| 
 | ||||
|             override fun onFailure(call: Call<DirectThreadBroadcastResponse?>, t: Throwable) { | ||||
|                 data.postValue(error(t.message, item)) | ||||
|                 Log.e(TAG, "enqueueRequest: onFailure: ", t) | ||||
|             } | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     private fun stopCurrentRequest() { | ||||
|         chatsRequest?.let { | ||||
|             if (it.isExecuted || it.isCanceled) return | ||||
| @ -1583,7 +1576,7 @@ class ThreadManager private constructor( | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     fun markAsSeen(directItem: DirectItem): LiveData<Resource<Any?>> { | ||||
|     fun markAsSeen(directItem: DirectItem, scope: CoroutineScope): LiveData<Resource<Any?>> { | ||||
|         val data = MutableLiveData<Resource<Any?>>() | ||||
|         data.postValue(loading(null)) | ||||
|         val request = service.markAsSeen(threadId, directItem) | ||||
| @ -1606,7 +1599,7 @@ class ThreadManager private constructor( | ||||
|                     data.postValue(error(R.string.generic_null_response, null)) | ||||
|                     return | ||||
|                 } | ||||
|                 inboxManager.fetchUnseenCount() | ||||
|                 inboxManager.fetchUnseenCount(scope) | ||||
|                 val payload = seenResponse.payload ?: return | ||||
|                 val timestamp = payload.timestamp | ||||
|                 val thread = thread.value ?: return | ||||
|  | ||||
| @ -1,46 +1,62 @@ | ||||
| package awais.instagrabber.models.enums | ||||
| 
 | ||||
| import com.google.gson.annotations.SerializedName | ||||
| 
 | ||||
| import java.io.Serializable | ||||
| import java.util.* | ||||
| 
 | ||||
| enum class DirectItemType(val id: Int) : Serializable { | ||||
|     UNKNOWN(0), | ||||
| 
 | ||||
|     @SerializedName("text") | ||||
|     TEXT(1), | ||||
| 
 | ||||
|     @SerializedName("like") | ||||
|     LIKE(2), | ||||
| 
 | ||||
|     @SerializedName("link") | ||||
|     LINK(3), | ||||
| 
 | ||||
|     @SerializedName("media") | ||||
|     MEDIA(4), | ||||
| 
 | ||||
|     @SerializedName("raven_media") | ||||
|     RAVEN_MEDIA(5), | ||||
| 
 | ||||
|     @SerializedName("profile") | ||||
|     PROFILE(6), | ||||
| 
 | ||||
|     @SerializedName("video_call_event") | ||||
|     VIDEO_CALL_EVENT(7), | ||||
| 
 | ||||
|     @SerializedName("animated_media") | ||||
|     ANIMATED_MEDIA(8), | ||||
| 
 | ||||
|     @SerializedName("voice_media") | ||||
|     VOICE_MEDIA(9), | ||||
| 
 | ||||
|     @SerializedName("media_share") | ||||
|     MEDIA_SHARE(10), | ||||
| 
 | ||||
|     @SerializedName("reel_share") | ||||
|     REEL_SHARE(11), | ||||
| 
 | ||||
|     @SerializedName("action_log") | ||||
|     ACTION_LOG(12), | ||||
| 
 | ||||
|     @SerializedName("placeholder") | ||||
|     PLACEHOLDER(13), | ||||
| 
 | ||||
|     @SerializedName("story_share") | ||||
|     STORY_SHARE(14), | ||||
| 
 | ||||
|     @SerializedName("clip") | ||||
|     CLIP(15),        // media_share but reel | ||||
| 
 | ||||
|     @SerializedName("felix_share") | ||||
|     FELIX_SHARE(16), // media_share but igtv | ||||
| 
 | ||||
|     @SerializedName("location") | ||||
|     LOCATION(17), | ||||
| 
 | ||||
|     @SerializedName("xma") | ||||
|     XMA(18); // self avatar stickers | ||||
| 
 | ||||
| @ -52,7 +68,6 @@ enum class DirectItemType(val id: Int) : Serializable { | ||||
|             return map[id] | ||||
|         } | ||||
| 
 | ||||
|         @JvmStatic | ||||
|         fun getName(directItemType: DirectItemType): String? { | ||||
|             when (directItemType) { | ||||
|                 TEXT -> return "text" | ||||
| @ -72,12 +87,12 @@ enum class DirectItemType(val id: Int) : Serializable { | ||||
|                 CLIP -> return "clip" | ||||
|                 FELIX_SHARE -> return "felix_share" | ||||
|                 LOCATION -> return "location" | ||||
|                 else -> return null | ||||
|             } | ||||
|             return null | ||||
|         } | ||||
| 
 | ||||
|         init { | ||||
|             for (type in DirectItemType.values()) { | ||||
|             for (type in values()) { | ||||
|                 map[type.id] = type | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @ -18,14 +18,14 @@ interface DirectMessagesRepository { | ||||
|     ): DirectThreadFeedResponse | ||||
| 
 | ||||
|     @GET("/api/v1/direct_v2/get_badge_count/?no_raven=1") | ||||
|     fun fetchUnseenCount(): Call<DirectBadgeCount?> | ||||
|     suspend fun fetchUnseenCount(): DirectBadgeCount | ||||
| 
 | ||||
|     @FormUrlEncoded | ||||
|     @POST("/api/v1/direct_v2/threads/broadcast/{item}/") | ||||
|     fun broadcast( | ||||
|     suspend fun broadcast( | ||||
|         @Path("item") item: String, | ||||
|         @FieldMap signedForm: Map<String, String>, | ||||
|     ): Call<DirectThreadBroadcastResponse?> | ||||
|     ): DirectThreadBroadcastResponse | ||||
| 
 | ||||
|     @FormUrlEncoded | ||||
|     @POST("/api/v1/direct_v2/threads/{threadId}/add_user/") | ||||
|  | ||||
							
								
								
									
										19
									
								
								app/src/main/java/awais/instagrabber/utils/CoroutineUtils.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								app/src/main/java/awais/instagrabber/utils/CoroutineUtils.kt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| package awais.instagrabber.utils | ||||
| 
 | ||||
| import kotlinx.coroutines.CoroutineDispatcher | ||||
| import kotlinx.coroutines.Dispatchers | ||||
| import java.util.function.BiConsumer | ||||
| import kotlin.coroutines.Continuation | ||||
| import kotlin.coroutines.CoroutineContext | ||||
| 
 | ||||
| @JvmOverloads | ||||
| fun <R> getContinuation(onFinished: BiConsumer<R?, Throwable?>, dispatcher: CoroutineDispatcher = Dispatchers.Default): Continuation<R> { | ||||
|     return object : Continuation<R> { | ||||
|         override val context: CoroutineContext | ||||
|             get() = dispatcher | ||||
| 
 | ||||
|         override fun resumeWith(result: Result<R>) { | ||||
|             onFinished.accept(result.getOrNull(), result.exceptionOrNull()) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -32,5 +32,6 @@ class DirectInboxViewModel : ViewModel() { | ||||
| 
 | ||||
|     init { | ||||
|         inboxManager.fetchInbox(viewModelScope) | ||||
|         inboxManager.fetchUnseenCount(viewModelScope) | ||||
|     } | ||||
| } | ||||
| @ -74,15 +74,15 @@ class DirectThreadViewModel( | ||||
|     } | ||||
| 
 | ||||
|     fun sendText(text: String): LiveData<Resource<Any?>> { | ||||
|         return threadManager.sendText(text) | ||||
|         return threadManager.sendText(text, viewModelScope) | ||||
|     } | ||||
| 
 | ||||
|     fun sendUri(entry: MediaController.MediaEntry): LiveData<Resource<Any?>> { | ||||
|         return threadManager.sendUri(entry) | ||||
|         return threadManager.sendUri(entry, viewModelScope) | ||||
|     } | ||||
| 
 | ||||
|     fun sendUri(uri: Uri): LiveData<Resource<Any?>> { | ||||
|         return threadManager.sendUri(uri) | ||||
|         return threadManager.sendUri(uri, viewModelScope) | ||||
|     } | ||||
| 
 | ||||
|     fun startRecording(): LiveData<Resource<Any?>> { | ||||
| @ -106,12 +106,15 @@ class DirectThreadViewModel( | ||||
|                     MediaUtils.getVoiceInfo(contentResolver, uri, object : OnInfoLoadListener<VideoInfo?> { | ||||
|                         override fun onLoad(videoInfo: VideoInfo?) { | ||||
|                             if (videoInfo == null) return | ||||
|                             threadManager.sendVoice(data, | ||||
|                             threadManager.sendVoice( | ||||
|                                 data, | ||||
|                                 uri, | ||||
|                                 result.waveform, | ||||
|                                 result.samplingFreq, | ||||
|                                 videoInfo.duration, | ||||
|                                 videoInfo.size) | ||||
|                                 videoInfo.size, | ||||
|                                 viewModelScope, | ||||
|                             ) | ||||
|                         } | ||||
| 
 | ||||
|                         override fun onFailure(t: Throwable) { | ||||
| @ -133,11 +136,11 @@ class DirectThreadViewModel( | ||||
|     } | ||||
| 
 | ||||
|     fun sendReaction(item: DirectItem, emoji: Emoji): LiveData<Resource<Any?>> { | ||||
|         return threadManager.sendReaction(item, emoji) | ||||
|         return threadManager.sendReaction(item, emoji, viewModelScope) | ||||
|     } | ||||
| 
 | ||||
|     fun sendDeleteReaction(itemId: String): LiveData<Resource<Any?>> { | ||||
|         return threadManager.sendDeleteReaction(itemId) | ||||
|         return threadManager.sendDeleteReaction(itemId, viewModelScope) | ||||
|     } | ||||
| 
 | ||||
|     fun unsend(item: DirectItem): LiveData<Resource<Any?>> { | ||||
| @ -145,7 +148,7 @@ class DirectThreadViewModel( | ||||
|     } | ||||
| 
 | ||||
|     fun sendAnimatedMedia(giphyGif: GiphyGif): LiveData<Resource<Any?>> { | ||||
|         return threadManager.sendAnimatedMedia(giphyGif) | ||||
|         return threadManager.sendAnimatedMedia(giphyGif, viewModelScope) | ||||
|     } | ||||
| 
 | ||||
|     fun getUser(userId: Long): User? { | ||||
| @ -197,7 +200,7 @@ class DirectThreadViewModel( | ||||
|                 return successEventResObjectLiveData | ||||
|             } | ||||
|         } | ||||
|         return threadManager.markAsSeen(directItem) | ||||
|         return threadManager.markAsSeen(directItem, viewModelScope) | ||||
|     } | ||||
| 
 | ||||
|     private val successEventResObjectLiveData: MutableLiveData<Resource<Any?>> | ||||
|  | ||||
| @ -53,17 +53,15 @@ class DirectMessagesService private constructor( | ||||
|         return repository.fetchThread(threadId, queryMap) | ||||
|     } | ||||
| 
 | ||||
|     fun fetchUnseenCount(): Call<DirectBadgeCount?> { | ||||
|         return repository.fetchUnseenCount() | ||||
|     } | ||||
|     suspend fun fetchUnseenCount(): DirectBadgeCount = repository.fetchUnseenCount() | ||||
| 
 | ||||
|     fun broadcastText( | ||||
|     suspend fun broadcastText( | ||||
|         clientContext: String, | ||||
|         threadIdOrUserIds: ThreadIdOrUserIds, | ||||
|         text: String, | ||||
|         repliedToItemId: String?, | ||||
|         repliedToClientContext: String?, | ||||
|     ): Call<DirectThreadBroadcastResponse?> { | ||||
|     ): DirectThreadBroadcastResponse { | ||||
|         val urls = extractUrls(text) | ||||
|         if (urls.isNotEmpty()) { | ||||
|             return broadcastLink(clientContext, threadIdOrUserIds, text, urls, repliedToItemId, repliedToClientContext) | ||||
| @ -76,14 +74,14 @@ class DirectMessagesService private constructor( | ||||
|         return broadcast(broadcastOptions) | ||||
|     } | ||||
| 
 | ||||
|     private fun broadcastLink( | ||||
|     private suspend fun broadcastLink( | ||||
|         clientContext: String, | ||||
|         threadIdOrUserIds: ThreadIdOrUserIds, | ||||
|         linkText: String, | ||||
|         urls: List<String>, | ||||
|         repliedToItemId: String?, | ||||
|         repliedToClientContext: String?, | ||||
|     ): Call<DirectThreadBroadcastResponse?> { | ||||
|     ): DirectThreadBroadcastResponse { | ||||
|         val broadcastOptions = LinkBroadcastOptions(clientContext, threadIdOrUserIds, linkText, urls) | ||||
|         if (!repliedToItemId.isNullOrBlank() && !repliedToClientContext.isNullOrBlank()) { | ||||
|             broadcastOptions.repliedToItemId = repliedToItemId | ||||
| @ -92,70 +90,70 @@ class DirectMessagesService private constructor( | ||||
|         return broadcast(broadcastOptions) | ||||
|     } | ||||
| 
 | ||||
|     fun broadcastPhoto( | ||||
|     suspend fun broadcastPhoto( | ||||
|         clientContext: String, | ||||
|         threadIdOrUserIds: ThreadIdOrUserIds, | ||||
|         uploadId: String, | ||||
|     ): Call<DirectThreadBroadcastResponse?> { | ||||
|     ): DirectThreadBroadcastResponse { | ||||
|         return broadcast(PhotoBroadcastOptions(clientContext, threadIdOrUserIds, true, uploadId)) | ||||
|     } | ||||
| 
 | ||||
|     fun broadcastVideo( | ||||
|     suspend fun broadcastVideo( | ||||
|         clientContext: String, | ||||
|         threadIdOrUserIds: ThreadIdOrUserIds, | ||||
|         uploadId: String, | ||||
|         videoResult: String, | ||||
|         sampled: Boolean, | ||||
|     ): Call<DirectThreadBroadcastResponse?> { | ||||
|     ): DirectThreadBroadcastResponse { | ||||
|         return broadcast(VideoBroadcastOptions(clientContext, threadIdOrUserIds, videoResult, uploadId, sampled)) | ||||
|     } | ||||
| 
 | ||||
|     fun broadcastVoice( | ||||
|     suspend fun broadcastVoice( | ||||
|         clientContext: String, | ||||
|         threadIdOrUserIds: ThreadIdOrUserIds, | ||||
|         uploadId: String, | ||||
|         waveform: List<Float>, | ||||
|         samplingFreq: Int, | ||||
|     ): Call<DirectThreadBroadcastResponse?> { | ||||
|     ): DirectThreadBroadcastResponse { | ||||
|         return broadcast(VoiceBroadcastOptions(clientContext, threadIdOrUserIds, uploadId, waveform, samplingFreq)) | ||||
|     } | ||||
| 
 | ||||
|     fun broadcastStoryReply( | ||||
|     suspend fun broadcastStoryReply( | ||||
|         threadIdOrUserIds: ThreadIdOrUserIds, | ||||
|         text: String, | ||||
|         mediaId: String, | ||||
|         reelId: String, | ||||
|     ): Call<DirectThreadBroadcastResponse?> { | ||||
|     ): DirectThreadBroadcastResponse { | ||||
|         return broadcast(StoryReplyBroadcastOptions(UUID.randomUUID().toString(), threadIdOrUserIds, text, mediaId, reelId)) | ||||
|     } | ||||
| 
 | ||||
|     fun broadcastReaction( | ||||
|     suspend fun broadcastReaction( | ||||
|         clientContext: String, | ||||
|         threadIdOrUserIds: ThreadIdOrUserIds, | ||||
|         itemId: String, | ||||
|         emoji: String?, | ||||
|         delete: Boolean, | ||||
|     ): Call<DirectThreadBroadcastResponse?> { | ||||
|     ): DirectThreadBroadcastResponse { | ||||
|         return broadcast(ReactionBroadcastOptions(clientContext, threadIdOrUserIds, itemId, emoji, delete)) | ||||
|     } | ||||
| 
 | ||||
|     fun broadcastAnimatedMedia( | ||||
|     suspend fun broadcastAnimatedMedia( | ||||
|         clientContext: String, | ||||
|         threadIdOrUserIds: ThreadIdOrUserIds, | ||||
|         giphyGif: GiphyGif, | ||||
|     ): Call<DirectThreadBroadcastResponse?> { | ||||
|     ): DirectThreadBroadcastResponse { | ||||
|         return broadcast(AnimatedMediaBroadcastOptions(clientContext, threadIdOrUserIds, giphyGif)) | ||||
|     } | ||||
| 
 | ||||
|     fun broadcastMediaShare( | ||||
|     suspend fun broadcastMediaShare( | ||||
|         clientContext: String, | ||||
|         threadIdOrUserIds: ThreadIdOrUserIds, | ||||
|         mediaId: String, | ||||
|     ): Call<DirectThreadBroadcastResponse?> { | ||||
|     ): DirectThreadBroadcastResponse { | ||||
|         return broadcast(MediaShareBroadcastOptions(clientContext, threadIdOrUserIds, mediaId)) | ||||
|     } | ||||
| 
 | ||||
|     private fun broadcast(broadcastOptions: BroadcastOptions): Call<DirectThreadBroadcastResponse?> { | ||||
|     private suspend fun broadcast(broadcastOptions: BroadcastOptions): DirectThreadBroadcastResponse { | ||||
|         require(!isEmpty(broadcastOptions.clientContext)) { "Broadcast requires a valid client context value" } | ||||
|         val form = mutableMapOf<String, Any>() | ||||
|         val threadId = broadcastOptions.threadId | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user