mirror of
				https://github.com/KokaKiwi/BarInsta
				synced 2025-10-31 11:35:34 +00:00 
			
		
		
		
	Convert MediaRepository and MediaService to kotlin.
This commit is contained in:
		
							parent
							
								
									708e0fda5b
								
							
						
					
					
						commit
						b997504602
					
				| @ -31,6 +31,7 @@ import androidx.fragment.app.FragmentManager | |||||||
| import androidx.lifecycle.LiveData | import androidx.lifecycle.LiveData | ||||||
| import androidx.lifecycle.Observer | import androidx.lifecycle.Observer | ||||||
| import androidx.lifecycle.ViewModelProvider | import androidx.lifecycle.ViewModelProvider | ||||||
|  | import androidx.lifecycle.lifecycleScope | ||||||
| import androidx.navigation.NavController | import androidx.navigation.NavController | ||||||
| import androidx.navigation.NavController.OnDestinationChangedListener | import androidx.navigation.NavController.OnDestinationChangedListener | ||||||
| import androidx.navigation.NavDestination | import androidx.navigation.NavDestination | ||||||
| @ -68,6 +69,8 @@ import com.google.android.material.bottomnavigation.BottomNavigationView | |||||||
| import com.google.android.material.textfield.TextInputLayout | import com.google.android.material.textfield.TextInputLayout | ||||||
| import com.google.common.collect.ImmutableList | import com.google.common.collect.ImmutableList | ||||||
| import com.google.common.collect.Iterators | import com.google.common.collect.Iterators | ||||||
|  | import kotlinx.coroutines.Dispatchers | ||||||
|  | import kotlinx.coroutines.launch | ||||||
| import java.util.* | import java.util.* | ||||||
| import java.util.stream.Collectors | import java.util.stream.Collectors | ||||||
| 
 | 
 | ||||||
| @ -81,11 +84,14 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL | |||||||
|     private var isActivityCheckerServiceBound = false |     private var isActivityCheckerServiceBound = false | ||||||
|     private var isBackStackEmpty = false |     private var isBackStackEmpty = false | ||||||
|     private var isLoggedIn = false |     private var isLoggedIn = false | ||||||
|  |     private var deviceUuid: String? = null | ||||||
|  |     private var csrfToken: String? = null | ||||||
|  |     private var userId: Long = 0 | ||||||
| 
 | 
 | ||||||
|     // private var behavior: HideBottomViewOnScrollBehavior<BottomNavigationView>? = null |     // private var behavior: HideBottomViewOnScrollBehavior<BottomNavigationView>? = null | ||||||
|     var currentTabs: List<Tab> = emptyList() |     var currentTabs: List<Tab> = emptyList() | ||||||
|         private set |         private set | ||||||
|     private var showBottomViewDestinations: List<Int> = emptyList<Int>() |     private var showBottomViewDestinations: List<Int> = emptyList() | ||||||
|     private var graphQLService: GraphQLService? = null |     private var graphQLService: GraphQLService? = null | ||||||
|     private var mediaService: MediaService? = null |     private var mediaService: MediaService? = null | ||||||
| 
 | 
 | ||||||
| @ -157,17 +163,17 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL | |||||||
| 
 | 
 | ||||||
|     private fun setupCookie() { |     private fun setupCookie() { | ||||||
|         val cookie = Utils.settingsHelper.getString(Constants.COOKIE) |         val cookie = Utils.settingsHelper.getString(Constants.COOKIE) | ||||||
|         var userId: Long = 0 |         userId = 0 | ||||||
|         var csrfToken: String? = null |         csrfToken = null | ||||||
|         if (!isEmpty(cookie)) { |         if (cookie.isNotBlank()) { | ||||||
|             userId = getUserIdFromCookie(cookie) |             userId = getUserIdFromCookie(cookie) | ||||||
|             csrfToken = getCsrfTokenFromCookie(cookie) |             csrfToken = getCsrfTokenFromCookie(cookie) | ||||||
|         } |         } | ||||||
|         if (isEmpty(cookie) || userId == 0L || isEmpty(csrfToken)) { |         if (cookie.isBlank() || userId == 0L || csrfToken.isNullOrBlank()) { | ||||||
|             isLoggedIn = false |             isLoggedIn = false | ||||||
|             return |             return | ||||||
|         } |         } | ||||||
|         val deviceUuid = Utils.settingsHelper.getString(Constants.DEVICE_UUID) |         deviceUuid = Utils.settingsHelper.getString(Constants.DEVICE_UUID) | ||||||
|         if (isEmpty(deviceUuid)) { |         if (isEmpty(deviceUuid)) { | ||||||
|             Utils.settingsHelper.putString(Constants.DEVICE_UUID, UUID.randomUUID().toString()) |             Utils.settingsHelper.putString(Constants.DEVICE_UUID, UUID.randomUUID().toString()) | ||||||
|         } |         } | ||||||
| @ -175,6 +181,7 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL | |||||||
|         isLoggedIn = true |         isLoggedIn = true | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     @Suppress("unused") | ||||||
|     private fun initDmService() { |     private fun initDmService() { | ||||||
|         if (!isLoggedIn) return |         if (!isLoggedIn) return | ||||||
|         val enabled = Utils.settingsHelper.getBoolean(PreferenceKeys.PREF_ENABLE_DM_AUTO_REFRESH) |         val enabled = Utils.settingsHelper.getBoolean(PreferenceKeys.PREF_ENABLE_DM_AUTO_REFRESH) | ||||||
| @ -628,7 +635,9 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL | |||||||
|             .setView(R.layout.dialog_opening_post) |             .setView(R.layout.dialog_opening_post) | ||||||
|             .create() |             .create() | ||||||
|         if (graphQLService == null) graphQLService = GraphQLService.getInstance() |         if (graphQLService == null) graphQLService = GraphQLService.getInstance() | ||||||
|         if (mediaService == null) mediaService = MediaService.getInstance(null, null, 0L) |         if (mediaService == null) { | ||||||
|  |             mediaService = deviceUuid?.let { csrfToken?.let { it1 -> MediaService.getInstance(it, it1, userId) } } | ||||||
|  |         } | ||||||
|         val postCb: ServiceCallback<Media> = object : ServiceCallback<Media> { |         val postCb: ServiceCallback<Media> = object : ServiceCallback<Media> { | ||||||
|             override fun onSuccess(feedModel: Media?) { |             override fun onSuccess(feedModel: Media?) { | ||||||
|                 if (feedModel != null) { |                 if (feedModel != null) { | ||||||
| @ -650,7 +659,18 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         alertDialog.show() |         alertDialog.show() | ||||||
|         if (isLoggedIn) mediaService?.fetch(shortcodeToId(shortCode), postCb) else graphQLService?.fetchPost(shortCode, postCb) |         if (isLoggedIn) { | ||||||
|  |             lifecycleScope.launch(Dispatchers.IO) { | ||||||
|  |                 try { | ||||||
|  |                     val media = mediaService?.fetch(shortcodeToId(shortCode)) | ||||||
|  |                     postCb.onSuccess(media) | ||||||
|  |                 } catch (e: Exception) { | ||||||
|  |                     postCb.onFailure(e) | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             graphQLService?.fetchPost(shortCode, postCb) | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private fun showLocationView(intentModel: IntentModel) { |     private fun showLocationView(intentModel: IntentModel) { | ||||||
|  | |||||||
| @ -25,12 +25,15 @@ import awais.instagrabber.customviews.helpers.RecyclerLazyLoader; | |||||||
| import awais.instagrabber.databinding.FragmentLikesBinding; | import awais.instagrabber.databinding.FragmentLikesBinding; | ||||||
| import awais.instagrabber.repositories.responses.GraphQLUserListFetchResponse; | import awais.instagrabber.repositories.responses.GraphQLUserListFetchResponse; | ||||||
| import awais.instagrabber.repositories.responses.User; | import awais.instagrabber.repositories.responses.User; | ||||||
|  | import awais.instagrabber.utils.AppExecutors; | ||||||
| import awais.instagrabber.utils.Constants; | import awais.instagrabber.utils.Constants; | ||||||
| import awais.instagrabber.utils.CookieUtils; | import awais.instagrabber.utils.CookieUtils; | ||||||
|  | import awais.instagrabber.utils.CoroutineUtilsKt; | ||||||
| import awais.instagrabber.utils.TextUtils; | import awais.instagrabber.utils.TextUtils; | ||||||
| import awais.instagrabber.webservices.GraphQLService; | import awais.instagrabber.webservices.GraphQLService; | ||||||
| import awais.instagrabber.webservices.MediaService; | import awais.instagrabber.webservices.MediaService; | ||||||
| import awais.instagrabber.webservices.ServiceCallback; | import awais.instagrabber.webservices.ServiceCallback; | ||||||
|  | import kotlinx.coroutines.Dispatchers; | ||||||
| 
 | 
 | ||||||
| import static awais.instagrabber.utils.Utils.settingsHelper; | import static awais.instagrabber.utils.Utils.settingsHelper; | ||||||
| 
 | 
 | ||||||
| @ -104,9 +107,12 @@ public final class LikesViewerFragment extends BottomSheetDialogFragment impleme | |||||||
|     public void onCreate(@Nullable final Bundle savedInstanceState) { |     public void onCreate(@Nullable final Bundle savedInstanceState) { | ||||||
|         super.onCreate(savedInstanceState); |         super.onCreate(savedInstanceState); | ||||||
|         final String cookie = settingsHelper.getString(Constants.COOKIE); |         final String cookie = settingsHelper.getString(Constants.COOKIE); | ||||||
|         isLoggedIn = !TextUtils.isEmpty(cookie) && CookieUtils.getUserIdFromCookie(cookie) > 0; |         final long userId = CookieUtils.getUserIdFromCookie(cookie); | ||||||
|         // final AppCompatActivity fragmentActivity = (AppCompatActivity) getActivity(); |         isLoggedIn = !TextUtils.isEmpty(cookie) && userId != 0; | ||||||
|         mediaService = isLoggedIn ? MediaService.getInstance(null, null, 0) : null; |         final String deviceUuid = settingsHelper.getString(Constants.DEVICE_UUID); | ||||||
|  |         final String csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie); | ||||||
|  |         if (csrfToken == null) return; | ||||||
|  |         mediaService = isLoggedIn ? MediaService.getInstance(deviceUuid, csrfToken, userId) : null; | ||||||
|         graphQLService = isLoggedIn ? null : GraphQLService.getInstance(); |         graphQLService = isLoggedIn ? null : GraphQLService.getInstance(); | ||||||
|         // setHasOptionsMenu(true); |         // setHasOptionsMenu(true); | ||||||
|     } |     } | ||||||
| @ -130,7 +136,20 @@ public final class LikesViewerFragment extends BottomSheetDialogFragment impleme | |||||||
|         if (isComment && !isLoggedIn) { |         if (isComment && !isLoggedIn) { | ||||||
|             lazyLoader.resetState(); |             lazyLoader.resetState(); | ||||||
|             graphQLService.fetchCommentLikers(postId, null, anonCb); |             graphQLService.fetchCommentLikers(postId, null, anonCb); | ||||||
|         } else mediaService.fetchLikes(postId, isComment, cb); |         } else { | ||||||
|  |             mediaService.fetchLikes( | ||||||
|  |                     postId, | ||||||
|  |                     isComment, | ||||||
|  |                     CoroutineUtilsKt.getContinuation((users, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> { | ||||||
|  |                         if (throwable != null) { | ||||||
|  |                             cb.onFailure(throwable); | ||||||
|  |                             return; | ||||||
|  |                         } | ||||||
|  |                         //noinspection unchecked | ||||||
|  |                         cb.onSuccess((List<User>) users); | ||||||
|  |                     }), Dispatchers.getIO()) | ||||||
|  |             ); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void init() { |     private void init() { | ||||||
|  | |||||||
| @ -35,12 +35,13 @@ import awais.instagrabber.databinding.FragmentNotificationsViewerBinding; | |||||||
| import awais.instagrabber.models.enums.NotificationType; | import awais.instagrabber.models.enums.NotificationType; | ||||||
| import awais.instagrabber.repositories.requests.StoryViewerOptions; | import awais.instagrabber.repositories.requests.StoryViewerOptions; | ||||||
| import awais.instagrabber.repositories.responses.FriendshipChangeResponse; | import awais.instagrabber.repositories.responses.FriendshipChangeResponse; | ||||||
| import awais.instagrabber.repositories.responses.Media; |  | ||||||
| import awais.instagrabber.repositories.responses.notification.Notification; | import awais.instagrabber.repositories.responses.notification.Notification; | ||||||
| import awais.instagrabber.repositories.responses.notification.NotificationArgs; | import awais.instagrabber.repositories.responses.notification.NotificationArgs; | ||||||
| import awais.instagrabber.repositories.responses.notification.NotificationImage; | import awais.instagrabber.repositories.responses.notification.NotificationImage; | ||||||
|  | import awais.instagrabber.utils.AppExecutors; | ||||||
| import awais.instagrabber.utils.Constants; | import awais.instagrabber.utils.Constants; | ||||||
| import awais.instagrabber.utils.CookieUtils; | import awais.instagrabber.utils.CookieUtils; | ||||||
|  | import awais.instagrabber.utils.CoroutineUtilsKt; | ||||||
| import awais.instagrabber.utils.TextUtils; | import awais.instagrabber.utils.TextUtils; | ||||||
| import awais.instagrabber.utils.Utils; | import awais.instagrabber.utils.Utils; | ||||||
| import awais.instagrabber.viewmodels.NotificationViewModel; | import awais.instagrabber.viewmodels.NotificationViewModel; | ||||||
| @ -48,6 +49,7 @@ import awais.instagrabber.webservices.FriendshipService; | |||||||
| import awais.instagrabber.webservices.MediaService; | import awais.instagrabber.webservices.MediaService; | ||||||
| import awais.instagrabber.webservices.NewsService; | import awais.instagrabber.webservices.NewsService; | ||||||
| import awais.instagrabber.webservices.ServiceCallback; | import awais.instagrabber.webservices.ServiceCallback; | ||||||
|  | import kotlinx.coroutines.Dispatchers; | ||||||
| 
 | 
 | ||||||
| import static awais.instagrabber.utils.Utils.settingsHelper; | import static awais.instagrabber.utils.Utils.settingsHelper; | ||||||
| 
 | 
 | ||||||
| @ -106,26 +108,25 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe | |||||||
|                         .setView(R.layout.dialog_opening_post) |                         .setView(R.layout.dialog_opening_post) | ||||||
|                         .create(); |                         .create(); | ||||||
|                 alertDialog.show(); |                 alertDialog.show(); | ||||||
|                 mediaService.fetch(mediaId, new ServiceCallback<Media>() { |                 mediaService.fetch( | ||||||
|                     @Override |                         mediaId, | ||||||
|                     public void onSuccess(final Media feedModel) { |                         CoroutineUtilsKt.getContinuation((media, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> { | ||||||
|                         final NavController navController = NavHostFragment.findNavController(NotificationsViewerFragment.this); |                             if (throwable != null) { | ||||||
|                         final Bundle bundle = new Bundle(); |                                 alertDialog.dismiss(); | ||||||
|                         bundle.putSerializable(PostViewV2Fragment.ARG_MEDIA, feedModel); |                                 Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); | ||||||
|                         try { |                                 return; | ||||||
|                             navController.navigate(R.id.action_global_post_view, bundle); |                             } | ||||||
|                             alertDialog.dismiss(); |                             final NavController navController = NavHostFragment.findNavController(NotificationsViewerFragment.this); | ||||||
|                         } catch (Exception e) { |                             final Bundle bundle = new Bundle(); | ||||||
|                             Log.e(TAG, "onSuccess: ", e); |                             bundle.putSerializable(PostViewV2Fragment.ARG_MEDIA, media); | ||||||
|                         } |                             try { | ||||||
|                     } |                                 navController.navigate(R.id.action_global_post_view, bundle); | ||||||
| 
 |                                 alertDialog.dismiss(); | ||||||
|                     @Override |                             } catch (Exception e) { | ||||||
|                     public void onFailure(final Throwable t) { |                                 Log.e(TAG, "onSuccess: ", e); | ||||||
|                         alertDialog.dismiss(); |                             } | ||||||
|                         Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); |                         }), Dispatchers.getIO()) | ||||||
|                     } |                 ); | ||||||
|                 }); |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -218,11 +219,11 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe | |||||||
|         if (TextUtils.isEmpty(cookie)) { |         if (TextUtils.isEmpty(cookie)) { | ||||||
|             Toast.makeText(context, R.string.activity_notloggedin, Toast.LENGTH_SHORT).show(); |             Toast.makeText(context, R.string.activity_notloggedin, Toast.LENGTH_SHORT).show(); | ||||||
|         } |         } | ||||||
|         mediaService = MediaService.getInstance(null, null, 0); |  | ||||||
|         final long userId = CookieUtils.getUserIdFromCookie(cookie); |         final long userId = CookieUtils.getUserIdFromCookie(cookie); | ||||||
|         deviceUuid = Utils.settingsHelper.getString(Constants.DEVICE_UUID); |         deviceUuid = Utils.settingsHelper.getString(Constants.DEVICE_UUID); | ||||||
|         csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie); |         csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie); | ||||||
|         friendshipService = FriendshipService.getInstance(deviceUuid, csrfToken, userId); |         friendshipService = FriendshipService.getInstance(deviceUuid, csrfToken, userId); | ||||||
|  |         mediaService = MediaService.getInstance(deviceUuid, csrfToken, userId); | ||||||
|         newsService = NewsService.getInstance(); |         newsService = NewsService.getInstance(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -85,8 +85,8 @@ import awais.instagrabber.models.stickers.SwipeUpModel; | |||||||
| import awais.instagrabber.repositories.requests.StoryViewerOptions; | import awais.instagrabber.repositories.requests.StoryViewerOptions; | ||||||
| import awais.instagrabber.repositories.requests.StoryViewerOptions.Type; | import awais.instagrabber.repositories.requests.StoryViewerOptions.Type; | ||||||
| import awais.instagrabber.repositories.requests.directmessages.ThreadIdOrUserIds; | import awais.instagrabber.repositories.requests.directmessages.ThreadIdOrUserIds; | ||||||
| import awais.instagrabber.repositories.responses.Media; |  | ||||||
| import awais.instagrabber.repositories.responses.StoryStickerResponse; | import awais.instagrabber.repositories.responses.StoryStickerResponse; | ||||||
|  | import awais.instagrabber.utils.AppExecutors; | ||||||
| import awais.instagrabber.utils.Constants; | import awais.instagrabber.utils.Constants; | ||||||
| import awais.instagrabber.utils.CookieUtils; | import awais.instagrabber.utils.CookieUtils; | ||||||
| import awais.instagrabber.utils.CoroutineUtilsKt; | import awais.instagrabber.utils.CoroutineUtilsKt; | ||||||
| @ -159,7 +159,7 @@ public class StoryViewerFragment extends Fragment { | |||||||
|         final String deviceId = settingsHelper.getString(Constants.DEVICE_UUID); |         final String deviceId = settingsHelper.getString(Constants.DEVICE_UUID); | ||||||
|         fragmentActivity = (AppCompatActivity) requireActivity(); |         fragmentActivity = (AppCompatActivity) requireActivity(); | ||||||
|         storiesService = StoriesService.getInstance(csrfToken, userIdFromCookie, deviceId); |         storiesService = StoriesService.getInstance(csrfToken, userIdFromCookie, deviceId); | ||||||
|         mediaService = MediaService.getInstance(null, null, 0); |         mediaService = MediaService.getInstance(deviceId, csrfToken, userIdFromCookie); | ||||||
|         directMessagesService = DirectMessagesService.getInstance(csrfToken, userIdFromCookie, deviceId); |         directMessagesService = DirectMessagesService.getInstance(csrfToken, userIdFromCookie, deviceId); | ||||||
|         setHasOptionsMenu(true); |         setHasOptionsMenu(true); | ||||||
|     } |     } | ||||||
| @ -220,7 +220,7 @@ public class StoryViewerFragment extends Fragment { | |||||||
|                     .setPositiveButton(R.string.confirm, (d, w) -> directMessagesService.createThread( |                     .setPositiveButton(R.string.confirm, (d, w) -> directMessagesService.createThread( | ||||||
|                             Collections.singletonList(currentStory.getUserId()), |                             Collections.singletonList(currentStory.getUserId()), | ||||||
|                             null, |                             null, | ||||||
|                             CoroutineUtilsKt.getContinuation((thread, throwable) -> { |                             CoroutineUtilsKt.getContinuation((thread, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> { | ||||||
|                                 if (throwable != null) { |                                 if (throwable != null) { | ||||||
|                                     Log.e(TAG, "onOptionsItemSelected: ", throwable); |                                     Log.e(TAG, "onOptionsItemSelected: ", throwable); | ||||||
|                                     Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); |                                     Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); | ||||||
| @ -231,17 +231,19 @@ public class StoryViewerFragment extends Fragment { | |||||||
|                                         input.getText().toString(), |                                         input.getText().toString(), | ||||||
|                                         currentStory.getStoryMediaId(), |                                         currentStory.getStoryMediaId(), | ||||||
|                                         String.valueOf(currentStory.getUserId()), |                                         String.valueOf(currentStory.getUserId()), | ||||||
|                                         CoroutineUtilsKt.getContinuation((directThreadBroadcastResponse, throwable1) -> { |                                         CoroutineUtilsKt.getContinuation( | ||||||
|                                             if (throwable1 != null) { |                                                 (directThreadBroadcastResponse, throwable1) -> AppExecutors.INSTANCE.getMainThread().execute(() -> { | ||||||
|                                                 Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); |                                                     if (throwable1 != null) { | ||||||
|                                                 Log.e(TAG, "onFailure: ", throwable1); |                                                         Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); | ||||||
|                                                 return; |                                                         Log.e(TAG, "onFailure: ", throwable1); | ||||||
|                                             } |                                                         return; | ||||||
|                                             Toast.makeText(context, R.string.answered_story, Toast.LENGTH_SHORT).show(); |                                                     } | ||||||
|                                         }, Dispatchers.getIO()) |                                                     Toast.makeText(context, R.string.answered_story, Toast.LENGTH_SHORT).show(); | ||||||
|  |                                                 }), Dispatchers.getIO() | ||||||
|  |                                         ) | ||||||
| 
 | 
 | ||||||
|                                 ); |                                 ); | ||||||
|                             }, Dispatchers.getIO()) |                             }), Dispatchers.getIO()) | ||||||
|                     )) |                     )) | ||||||
|                     .setNegativeButton(R.string.cancel, null) |                     .setNegativeButton(R.string.cancel, null) | ||||||
|                     .show(); |                     .show(); | ||||||
| @ -451,26 +453,25 @@ public class StoryViewerFragment extends Fragment { | |||||||
|                     .setView(R.layout.dialog_opening_post) |                     .setView(R.layout.dialog_opening_post) | ||||||
|                     .create(); |                     .create(); | ||||||
|             alertDialog.show(); |             alertDialog.show(); | ||||||
|             mediaService.fetch(Long.parseLong(mediaId), new ServiceCallback<Media>() { |             mediaService.fetch( | ||||||
|                 @Override |                     Long.parseLong(mediaId), | ||||||
|                 public void onSuccess(final Media feedModel) { |                     CoroutineUtilsKt.getContinuation((media, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> { | ||||||
|                     final NavController navController = NavHostFragment.findNavController(StoryViewerFragment.this); |                         if (throwable != null) { | ||||||
|                     final Bundle bundle = new Bundle(); |                             alertDialog.dismiss(); | ||||||
|                     bundle.putSerializable(PostViewV2Fragment.ARG_MEDIA, feedModel); |                             Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); | ||||||
|                     try { |                             return; | ||||||
|                         navController.navigate(R.id.action_global_post_view, bundle); |                         } | ||||||
|                         alertDialog.dismiss(); |                         final NavController navController = NavHostFragment.findNavController(StoryViewerFragment.this); | ||||||
|                     } catch (Exception e) { |                         final Bundle bundle = new Bundle(); | ||||||
|                         Log.e(TAG, "openPostDialog: ", e); |                         bundle.putSerializable(PostViewV2Fragment.ARG_MEDIA, media); | ||||||
|                     } |                         try { | ||||||
|                 } |                             navController.navigate(R.id.action_global_post_view, bundle); | ||||||
| 
 |                             alertDialog.dismiss(); | ||||||
|                 @Override |                         } catch (Exception e) { | ||||||
|                 public void onFailure(final Throwable t) { |                             Log.e(TAG, "openPostDialog: ", e); | ||||||
|                     alertDialog.dismiss(); |                         } | ||||||
|                     Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); |                     }), Dispatchers.getIO()) | ||||||
|                 } |             ); | ||||||
|             }); |  | ||||||
|         }); |         }); | ||||||
|         final View.OnClickListener storyActionListener = v -> { |         final View.OnClickListener storyActionListener = v -> { | ||||||
|             final Object tag = v.getTag(); |             final Object tag = v.getTag(); | ||||||
|  | |||||||
| @ -55,6 +55,7 @@ import awais.instagrabber.viewmodels.ImageEditViewModel; | |||||||
| import jp.co.cyberagent.android.gpuimage.GPUImage; | import jp.co.cyberagent.android.gpuimage.GPUImage; | ||||||
| import jp.co.cyberagent.android.gpuimage.filter.GPUImageFilter; | import jp.co.cyberagent.android.gpuimage.filter.GPUImageFilter; | ||||||
| import jp.co.cyberagent.android.gpuimage.filter.GPUImageFilterGroup; | import jp.co.cyberagent.android.gpuimage.filter.GPUImageFilterGroup; | ||||||
|  | import kotlinx.coroutines.Dispatchers; | ||||||
| 
 | 
 | ||||||
| public class FiltersFragment extends Fragment { | public class FiltersFragment extends Fragment { | ||||||
|     private static final String TAG = FiltersFragment.class.getSimpleName(); |     private static final String TAG = FiltersFragment.class.getSimpleName(); | ||||||
| @ -461,31 +462,33 @@ public class FiltersFragment extends Fragment { | |||||||
|             filtersAdapter.setSelected(position); |             filtersAdapter.setSelected(position); | ||||||
|             appliedFilter = filter; |             appliedFilter = filter; | ||||||
|         }; |         }; | ||||||
|         BitmapUtils.getThumbnail(context, sourceUri, CoroutineUtilsKt.getContinuation((bitmapResult, throwable) -> { |         BitmapUtils.getThumbnail( | ||||||
|             if (throwable != null) { |                 context, | ||||||
|                 Log.e(TAG, "setupFilters: ", throwable); |                 sourceUri, | ||||||
|                 return; |                 CoroutineUtilsKt.getContinuation((bitmapResult, throwable) -> appExecutors.getMainThread().execute(() -> { | ||||||
|             } |                     if (throwable != null) { | ||||||
|             if (bitmapResult == null || bitmapResult.getBitmap() == null) { |                         Log.e(TAG, "setupFilters: ", throwable); | ||||||
|                 return; |                         return; | ||||||
|             } |                     } | ||||||
|             filtersAdapter = new FiltersAdapter( |                     if (bitmapResult == null || bitmapResult.getBitmap() == null) { | ||||||
|                     tuningFilters.values() |                         return; | ||||||
|                                  .stream() |                     } | ||||||
|                                  .map(Filter::getInstance) |                     filtersAdapter = new FiltersAdapter( | ||||||
|                                  .collect(Collectors.toList()), |                             tuningFilters.values() | ||||||
|                     sourceUri.toString(), |                                          .stream() | ||||||
|                     bitmapResult.getBitmap(), |                                          .map(Filter::getInstance) | ||||||
|                     onFilterClickListener |                                          .collect(Collectors.toList()), | ||||||
|             ); |                             sourceUri.toString(), | ||||||
|             appExecutors.getMainThread().execute(() -> { |                             bitmapResult.getBitmap(), | ||||||
|                 binding.filters.setAdapter(filtersAdapter); |                             onFilterClickListener | ||||||
|                 filtersAdapter.submitList(FiltersHelper.getFilters(), () -> { |                     ); | ||||||
|                     if (appliedFilter == null) return; |                     binding.filters.setAdapter(filtersAdapter); | ||||||
|                     filtersAdapter.setSelectedFilter(appliedFilter.getInstance()); |                     filtersAdapter.submitList(FiltersHelper.getFilters(), () -> { | ||||||
|                 }); |                         if (appliedFilter == null) return; | ||||||
|             }); |                         filtersAdapter.setSelectedFilter(appliedFilter.getInstance()); | ||||||
|         })); |                     }); | ||||||
|  |                 }), Dispatchers.getIO()) | ||||||
|  |         ); | ||||||
|         addInitialFilter(); |         addInitialFilter(); | ||||||
|         binding.preview.setFilter(filterGroup); |         binding.preview.setFilter(filterGroup); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -30,11 +30,16 @@ import awais.instagrabber.fragments.PostViewV2Fragment; | |||||||
| import awais.instagrabber.repositories.responses.Media; | import awais.instagrabber.repositories.responses.Media; | ||||||
| import awais.instagrabber.repositories.responses.discover.TopicCluster; | import awais.instagrabber.repositories.responses.discover.TopicCluster; | ||||||
| import awais.instagrabber.repositories.responses.discover.TopicalExploreFeedResponse; | import awais.instagrabber.repositories.responses.discover.TopicalExploreFeedResponse; | ||||||
|  | import awais.instagrabber.utils.AppExecutors; | ||||||
|  | import awais.instagrabber.utils.Constants; | ||||||
|  | import awais.instagrabber.utils.CookieUtils; | ||||||
|  | import awais.instagrabber.utils.CoroutineUtilsKt; | ||||||
| import awais.instagrabber.utils.Utils; | import awais.instagrabber.utils.Utils; | ||||||
| import awais.instagrabber.viewmodels.TopicClusterViewModel; | import awais.instagrabber.viewmodels.TopicClusterViewModel; | ||||||
| import awais.instagrabber.webservices.DiscoverService; | import awais.instagrabber.webservices.DiscoverService; | ||||||
| import awais.instagrabber.webservices.MediaService; | import awais.instagrabber.webservices.MediaService; | ||||||
| import awais.instagrabber.webservices.ServiceCallback; | import awais.instagrabber.webservices.ServiceCallback; | ||||||
|  | import kotlinx.coroutines.Dispatchers; | ||||||
| 
 | 
 | ||||||
| public class DiscoverFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener { | public class DiscoverFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener { | ||||||
|     private static final String TAG = "DiscoverFragment"; |     private static final String TAG = "DiscoverFragment"; | ||||||
| @ -52,7 +57,11 @@ public class DiscoverFragment extends Fragment implements SwipeRefreshLayout.OnR | |||||||
|         super.onCreate(savedInstanceState); |         super.onCreate(savedInstanceState); | ||||||
|         fragmentActivity = (MainActivity) requireActivity(); |         fragmentActivity = (MainActivity) requireActivity(); | ||||||
|         discoverService = DiscoverService.getInstance(); |         discoverService = DiscoverService.getInstance(); | ||||||
|         mediaService = MediaService.getInstance(null, null, 0); |         final String deviceUuid = Utils.settingsHelper.getString(Constants.DEVICE_UUID); | ||||||
|  |         final String cookie = Utils.settingsHelper.getString(Constants.COOKIE); | ||||||
|  |         final String csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie); | ||||||
|  |         final long userId = CookieUtils.getUserIdFromCookie(cookie); | ||||||
|  |         mediaService = MediaService.getInstance(deviceUuid, csrfToken, userId); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
| @ -104,29 +113,29 @@ public class DiscoverFragment extends Fragment implements SwipeRefreshLayout.OnR | |||||||
|                         .setView(R.layout.dialog_opening_post) |                         .setView(R.layout.dialog_opening_post) | ||||||
|                         .create(); |                         .create(); | ||||||
|                 alertDialog.show(); |                 alertDialog.show(); | ||||||
|                 mediaService.fetch(Long.valueOf(coverMedia.getPk()), new ServiceCallback<Media>() { |                 final String pk = coverMedia.getPk(); | ||||||
|                     @Override |                 if (pk == null) return; | ||||||
|                     public void onSuccess(final Media feedModel) { |                 mediaService.fetch( | ||||||
|                         final NavController navController = NavHostFragment.findNavController(DiscoverFragment.this); |                         Long.parseLong(pk), | ||||||
|                         final Bundle bundle = new Bundle(); |                         CoroutineUtilsKt.getContinuation((media, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> { | ||||||
|                         bundle.putSerializable(PostViewV2Fragment.ARG_MEDIA, feedModel); |                             if (throwable != null) { | ||||||
|                         try { |                                 alertDialog.dismiss(); | ||||||
|                             navController.navigate(R.id.action_global_post_view, bundle); |                                 try { | ||||||
|                             alertDialog.dismiss(); |                                     Toast.makeText(requireContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); | ||||||
|                         } catch (Exception e) { |                                 } catch (Throwable ignored) {} | ||||||
|                             Log.e(TAG, "onSuccess: ", e); |                                 return; | ||||||
|                         } |                             } | ||||||
|                     } |                             final NavController navController = NavHostFragment.findNavController(DiscoverFragment.this); | ||||||
| 
 |                             final Bundle bundle = new Bundle(); | ||||||
|                     @Override |                             bundle.putSerializable(PostViewV2Fragment.ARG_MEDIA, media); | ||||||
|                     public void onFailure(final Throwable t) { |                             try { | ||||||
|                         alertDialog.dismiss(); |                                 navController.navigate(R.id.action_global_post_view, bundle); | ||||||
|                         try { |                                 alertDialog.dismiss(); | ||||||
|                             Toast.makeText(requireContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); |                             } catch (Exception e) { | ||||||
|                         } |                                 Log.e(TAG, "onTopicLongClick: ", e); | ||||||
|                         catch (Throwable e) {} |                             } | ||||||
|                     } |                         }), Dispatchers.getIO()) | ||||||
|                 }); |                 ); | ||||||
|             } |             } | ||||||
|         }; |         }; | ||||||
|         final DiscoverTopicsAdapter adapter = new DiscoverTopicsAdapter(otcl); |         final DiscoverTopicsAdapter adapter = new DiscoverTopicsAdapter(otcl); | ||||||
|  | |||||||
| @ -84,6 +84,7 @@ import awais.instagrabber.repositories.responses.FriendshipStatus; | |||||||
| import awais.instagrabber.repositories.responses.Media; | import awais.instagrabber.repositories.responses.Media; | ||||||
| import awais.instagrabber.repositories.responses.User; | import awais.instagrabber.repositories.responses.User; | ||||||
| import awais.instagrabber.repositories.responses.UserProfileContextLink; | import awais.instagrabber.repositories.responses.UserProfileContextLink; | ||||||
|  | import awais.instagrabber.utils.AppExecutors; | ||||||
| import awais.instagrabber.utils.Constants; | import awais.instagrabber.utils.Constants; | ||||||
| import awais.instagrabber.utils.CookieUtils; | import awais.instagrabber.utils.CookieUtils; | ||||||
| import awais.instagrabber.utils.CoroutineUtilsKt; | import awais.instagrabber.utils.CoroutineUtilsKt; | ||||||
| @ -335,7 +336,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe | |||||||
|         friendshipService = isLoggedIn ? FriendshipService.getInstance(deviceUuid, csrfToken, myId) : null; |         friendshipService = isLoggedIn ? FriendshipService.getInstance(deviceUuid, csrfToken, myId) : null; | ||||||
|         directMessagesService = isLoggedIn ? DirectMessagesService.getInstance(csrfToken, myId, deviceUuid) : null; |         directMessagesService = isLoggedIn ? DirectMessagesService.getInstance(csrfToken, myId, deviceUuid) : null; | ||||||
|         storiesService = isLoggedIn ? StoriesService.getInstance(null, 0L, null) : null; |         storiesService = isLoggedIn ? StoriesService.getInstance(null, 0L, null) : null; | ||||||
|         mediaService = isLoggedIn ? MediaService.getInstance(null, null, 0) : null; |         mediaService = isLoggedIn ? MediaService.getInstance(deviceUuid, csrfToken, myId) : null; | ||||||
|         userService = isLoggedIn ? UserService.getInstance() : null; |         userService = isLoggedIn ? UserService.getInstance() : null; | ||||||
|         graphQLService = isLoggedIn ? null : GraphQLService.getInstance(); |         graphQLService = isLoggedIn ? null : GraphQLService.getInstance(); | ||||||
|         final Context context = getContext(); |         final Context context = getContext(); | ||||||
| @ -821,26 +822,26 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe | |||||||
|                                     Utils.copyText(context, biography); |                                     Utils.copyText(context, biography); | ||||||
|                                     break; |                                     break; | ||||||
|                                 case 1: |                                 case 1: | ||||||
|                                     mediaService.translate(String.valueOf(profileModel.getPk()), "3", new ServiceCallback<String>() { |                                     mediaService.translate(String.valueOf(profileModel.getPk()), "3", CoroutineUtilsKt.getContinuation( | ||||||
|                                         @Override |                                             (result, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> { | ||||||
|                                         public void onSuccess(final String result) { |                                                 if (throwable != null) { | ||||||
|                                             if (TextUtils.isEmpty(result)) { |                                                     Log.e(TAG, "Error translating bio", throwable); | ||||||
|                                                 Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); |                                                     Toast.makeText(context, throwable.getMessage(), Toast.LENGTH_SHORT).show(); | ||||||
|                                                 return; |                                                     return; | ||||||
|                                             } |                                                 } | ||||||
|                                             new AlertDialog.Builder(context) |                                                 if (TextUtils.isEmpty(result)) { | ||||||
|                                                     .setTitle(profileModel.getUsername()) |                                                     Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT) | ||||||
|                                                     .setMessage(result) |                                                          .show(); | ||||||
|                                                     .setPositiveButton(R.string.ok, null) |                                                     return; | ||||||
|                                                     .show(); |                                                 } | ||||||
|                                         } |                                                 new AlertDialog.Builder(context) | ||||||
| 
 |                                                         .setTitle(profileModel.getUsername()) | ||||||
|                                         @Override |                                                         .setMessage(result) | ||||||
|                                         public void onFailure(final Throwable t) { |                                                         .setPositiveButton(R.string.ok, null) | ||||||
|                                             Log.e(TAG, "Error translating bio", t); |                                                         .show(); | ||||||
|                                             Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show(); |                                             }), | ||||||
|                                         } |                                             Dispatchers.getIO() | ||||||
|                                     }); |                                     )); | ||||||
|                                     break; |                                     break; | ||||||
|                             } |                             } | ||||||
|                         }) |                         }) | ||||||
| @ -1079,7 +1080,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe | |||||||
|                 directMessagesService.createThread( |                 directMessagesService.createThread( | ||||||
|                         Collections.singletonList(profileModel.getPk()), |                         Collections.singletonList(profileModel.getPk()), | ||||||
|                         null, |                         null, | ||||||
|                         CoroutineUtilsKt.getContinuation((thread, throwable) -> { |                         CoroutineUtilsKt.getContinuation((thread, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> { | ||||||
|                             if (throwable != null) { |                             if (throwable != null) { | ||||||
|                                 Log.e(TAG, "setupCommonListeners: ", throwable); |                                 Log.e(TAG, "setupCommonListeners: ", throwable); | ||||||
|                                 Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); |                                 Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); | ||||||
| @ -1092,7 +1093,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe | |||||||
|                                 inboxManager.addThread(thread, 0); |                                 inboxManager.addThread(thread, 0); | ||||||
|                             } |                             } | ||||||
|                             fragmentActivity.navigateToThread(thread.getThreadId(), profileModel.getUsername()); |                             fragmentActivity.navigateToThread(thread.getThreadId(), profileModel.getUsername()); | ||||||
|                         }, Dispatchers.getIO()) |                         }), Dispatchers.getIO()) | ||||||
|                 ); |                 ); | ||||||
|             }); |             }); | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -41,8 +41,6 @@ import kotlinx.coroutines.CoroutineScope | |||||||
| import kotlinx.coroutines.Dispatchers | import kotlinx.coroutines.Dispatchers | ||||||
| import kotlinx.coroutines.launch | import kotlinx.coroutines.launch | ||||||
| import retrofit2.Call | import retrofit2.Call | ||||||
| import retrofit2.Callback |  | ||||||
| import retrofit2.Response |  | ||||||
| import java.io.File | import java.io.File | ||||||
| import java.io.IOException | import java.io.IOException | ||||||
| import java.net.HttpURLConnection | import java.net.HttpURLConnection | ||||||
| @ -457,40 +455,15 @@ class ThreadManager private constructor( | |||||||
|                     "4", |                     "4", | ||||||
|                     null |                     null | ||||||
|                 ) |                 ) | ||||||
|                 val uploadFinishRequest = mediaService.uploadFinish(uploadFinishOptions) |                 mediaService.uploadFinish(uploadFinishOptions) | ||||||
|                 uploadFinishRequest.enqueue(object : Callback<String?> { |                 val broadcastResponse = service.broadcastVoice( | ||||||
|                     override fun onResponse(call: Call<String?>, response: Response<String?>) { |                     clientContext, | ||||||
|                         if (response.isSuccessful) { |                     threadIdOrUserIds, | ||||||
|                             scope.launch(Dispatchers.IO) { |                     uploadDmVoiceOptions.uploadId, | ||||||
|                                 try { |                     waveform, | ||||||
|                                     val request = service.broadcastVoice( |                     samplingFreq | ||||||
|                                         clientContext, |                 ) | ||||||
|                                         threadIdOrUserIds, |                 parseResponse(broadcastResponse, data, directItem) | ||||||
|                                         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) { |  | ||||||
|                             handleErrorBody(call, response, data) |  | ||||||
|                             return |  | ||||||
|                         } |  | ||||||
|                         data.postValue(error("uploadFinishRequest was not successful and response error body was null", directItem)) |  | ||||||
|                         Log.e(TAG, "uploadFinishRequest was not successful and response error body was null") |  | ||||||
|                     } |  | ||||||
| 
 |  | ||||||
|                     override fun onFailure(call: Call<String?>, t: Throwable) { |  | ||||||
|                         data.postValue(error(t.message, directItem)) |  | ||||||
|                         Log.e(TAG, "sendVoice: ", t) |  | ||||||
|                     } |  | ||||||
|                 }) |  | ||||||
|             } catch (e: Exception) { |             } catch (e: Exception) { | ||||||
|                 data.postValue(error(e.message, directItem)) |                 data.postValue(error(e.message, directItem)) | ||||||
|                 Log.e(TAG, "sendVoice: ", e) |                 Log.e(TAG, "sendVoice: ", e) | ||||||
| @ -806,39 +779,15 @@ class ThreadManager private constructor( | |||||||
|                     "2", |                     "2", | ||||||
|                     VideoOptions(duration / 1000f, emptyList(), 0, false) |                     VideoOptions(duration / 1000f, emptyList(), 0, false) | ||||||
|                 ) |                 ) | ||||||
|                 val uploadFinishRequest = mediaService.uploadFinish(uploadFinishOptions) |                 mediaService.uploadFinish(uploadFinishOptions) | ||||||
|                 uploadFinishRequest.enqueue(object : Callback<String?> { |                 val broadcastResponse = service.broadcastVideo( | ||||||
|                     override fun onResponse(call: Call<String?>, response: Response<String?>) { |                     clientContext, | ||||||
|                         if (response.isSuccessful) { |                     threadIdOrUserIds, | ||||||
|                             scope.launch(Dispatchers.IO) { |                     uploadDmVideoOptions.uploadId, | ||||||
|                                 try { |                     "", | ||||||
|                                     val response1 = service.broadcastVideo( |                     true | ||||||
|                                         clientContext, |                 ) | ||||||
|                                         threadIdOrUserIds, |                 parseResponse(broadcastResponse, data, directItem) | ||||||
|                                         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) { |  | ||||||
|                             handleErrorBody(call, response, data) |  | ||||||
|                             return |  | ||||||
|                         } |  | ||||||
|                         data.postValue(error("uploadFinishRequest was not successful and response error body was null", directItem)) |  | ||||||
|                         Log.e(TAG, "uploadFinishRequest was not successful and response error body was null") |  | ||||||
|                     } |  | ||||||
|                     override fun onFailure(call: Call<String?>, t: Throwable) { |  | ||||||
|                         data.postValue(error(t.message, directItem)) |  | ||||||
|                         Log.e(TAG, "sendVideo: ", t) |  | ||||||
|                     } |  | ||||||
|                 }) |  | ||||||
|             } catch (e: Exception) { |             } catch (e: Exception) { | ||||||
|                 data.postValue(error(e.message, directItem)) |                 data.postValue(error(e.message, directItem)) | ||||||
|                 Log.e(TAG, "sendVideo: ", e) |                 Log.e(TAG, "sendVideo: ", e) | ||||||
| @ -900,26 +849,6 @@ class ThreadManager private constructor( | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private fun handleErrorBody( |  | ||||||
|         call: Call<*>, |  | ||||||
|         response: Response<*>, |  | ||||||
|         data: MutableLiveData<Resource<Any?>>?, |  | ||||||
|     ) { |  | ||||||
|         try { |  | ||||||
|             val string = response.errorBody()?.string() ?: "" |  | ||||||
|             val msg = String.format(Locale.US, |  | ||||||
|                 "onResponse: url: %s, responseCode: %d, errorBody: %s", |  | ||||||
|                 call.request().url().toString(), |  | ||||||
|                 response.code(), |  | ||||||
|                 string) |  | ||||||
|             data?.postValue(error(msg, null)) |  | ||||||
|             Log.e(TAG, msg) |  | ||||||
|         } catch (e: IOException) { |  | ||||||
|             data?.postValue(error(e.message, null)) |  | ||||||
|             Log.e(TAG, "onResponse: ", e) |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private fun handleInvalidResponse( |     private fun handleInvalidResponse( | ||||||
|         data: MutableLiveData<Resource<Any?>>, |         data: MutableLiveData<Resource<Any?>>, | ||||||
|         response: MediaUploadResponse, |         response: MediaUploadResponse, | ||||||
|  | |||||||
| @ -1,55 +0,0 @@ | |||||||
| package awais.instagrabber.repositories; |  | ||||||
| 
 |  | ||||||
| import java.util.Map; |  | ||||||
| 
 |  | ||||||
| import awais.instagrabber.repositories.responses.LikersResponse; |  | ||||||
| import awais.instagrabber.repositories.responses.MediaInfoResponse; |  | ||||||
| import retrofit2.Call; |  | ||||||
| import retrofit2.http.FieldMap; |  | ||||||
| import retrofit2.http.FormUrlEncoded; |  | ||||||
| import retrofit2.http.GET; |  | ||||||
| import retrofit2.http.Header; |  | ||||||
| import retrofit2.http.POST; |  | ||||||
| import retrofit2.http.Path; |  | ||||||
| import retrofit2.http.Query; |  | ||||||
| import retrofit2.http.QueryMap; |  | ||||||
| 
 |  | ||||||
| public interface MediaRepository { |  | ||||||
|     @GET("/api/v1/media/{mediaId}/info/") |  | ||||||
|     Call<MediaInfoResponse> fetch(@Path("mediaId") final long mediaId); |  | ||||||
| 
 |  | ||||||
|     @GET("/api/v1/media/{mediaId}/{action}/") |  | ||||||
|     Call<LikersResponse> fetchLikes(@Path("mediaId") final String mediaId, |  | ||||||
|                                     @Path("action") final String action); // one of "likers" or "comment_likers" |  | ||||||
| 
 |  | ||||||
|     @FormUrlEncoded |  | ||||||
|     @POST("/api/v1/media/{mediaId}/{action}/") |  | ||||||
|     Call<String> action(@Path("action") final String action, |  | ||||||
|                         @Path("mediaId") final String mediaId, |  | ||||||
|                         @FieldMap final Map<String, String> signedForm); |  | ||||||
| 
 |  | ||||||
|     @FormUrlEncoded |  | ||||||
|     @POST("/api/v1/media/{mediaId}/edit_media/") |  | ||||||
|     Call<String> editCaption(@Path("mediaId") final String mediaId, |  | ||||||
|                              @FieldMap final Map<String, String> signedForm); |  | ||||||
| 
 |  | ||||||
|     @GET("/api/v1/language/translate/") |  | ||||||
|     Call<String> translate(@QueryMap final Map<String, String> form); |  | ||||||
| 
 |  | ||||||
|     @FormUrlEncoded |  | ||||||
|     @POST("/api/v1/media/upload_finish/") |  | ||||||
|     Call<String> uploadFinish(@Header("retry_context") final String retryContext, |  | ||||||
|                               @QueryMap Map<String, String> queryParams, |  | ||||||
|                               @FieldMap final Map<String, String> signedForm); |  | ||||||
| 
 |  | ||||||
|     @FormUrlEncoded |  | ||||||
|     @POST("/api/v1/media/{mediaId}/delete/") |  | ||||||
|     Call<String> delete(@Path("mediaId") final String mediaId, |  | ||||||
|                         @Query("media_type") final String mediaType, |  | ||||||
|                         @FieldMap final Map<String, String> signedForm); |  | ||||||
| 
 |  | ||||||
|     @FormUrlEncoded |  | ||||||
|     @POST("/api/v1/media/{mediaId}/archive/") |  | ||||||
|     Call<String> archive(@Path("mediaId") final String mediaId, |  | ||||||
|                          @FieldMap final Map<String, String> signedForm); |  | ||||||
| } |  | ||||||
| @ -0,0 +1,57 @@ | |||||||
|  | package awais.instagrabber.repositories | ||||||
|  | 
 | ||||||
|  | import awais.instagrabber.repositories.responses.LikersResponse | ||||||
|  | import awais.instagrabber.repositories.responses.MediaInfoResponse | ||||||
|  | import retrofit2.http.* | ||||||
|  | 
 | ||||||
|  | interface MediaRepository { | ||||||
|  |     @GET("/api/v1/media/{mediaId}/info/") | ||||||
|  |     suspend fun fetch(@Path("mediaId") mediaId: Long): MediaInfoResponse | ||||||
|  | 
 | ||||||
|  |     @GET("/api/v1/media/{mediaId}/{action}/") | ||||||
|  |     suspend fun fetchLikes( | ||||||
|  |         @Path("mediaId") mediaId: String, // one of "likers" or "comment_likers" | ||||||
|  |         @Path("action") action: String, | ||||||
|  |     ): LikersResponse | ||||||
|  | 
 | ||||||
|  |     @FormUrlEncoded | ||||||
|  |     @POST("/api/v1/media/{mediaId}/{action}/") | ||||||
|  |     suspend fun action( | ||||||
|  |         @Path("action") action: String, | ||||||
|  |         @Path("mediaId") mediaId: String, | ||||||
|  |         @FieldMap signedForm: Map<String, String>, | ||||||
|  |     ): String | ||||||
|  | 
 | ||||||
|  |     @FormUrlEncoded | ||||||
|  |     @POST("/api/v1/media/{mediaId}/edit_media/") | ||||||
|  |     suspend fun editCaption( | ||||||
|  |         @Path("mediaId") mediaId: String, | ||||||
|  |         @FieldMap signedForm: Map<String, String>, | ||||||
|  |     ): String | ||||||
|  | 
 | ||||||
|  |     @GET("/api/v1/language/translate/") | ||||||
|  |     suspend fun translate(@QueryMap form: Map<String, String>): String | ||||||
|  | 
 | ||||||
|  |     @FormUrlEncoded | ||||||
|  |     @POST("/api/v1/media/upload_finish/") | ||||||
|  |     suspend fun uploadFinish( | ||||||
|  |         @Header("retry_context") retryContext: String, | ||||||
|  |         @QueryMap queryParams: Map<String, String>, | ||||||
|  |         @FieldMap signedForm: Map<String, String>, | ||||||
|  |     ): String | ||||||
|  | 
 | ||||||
|  |     @FormUrlEncoded | ||||||
|  |     @POST("/api/v1/media/{mediaId}/delete/") | ||||||
|  |     suspend fun delete( | ||||||
|  |         @Path("mediaId") mediaId: String, | ||||||
|  |         @Query("media_type") mediaType: String, | ||||||
|  |         @FieldMap signedForm: Map<String, String>, | ||||||
|  |     ): String | ||||||
|  | 
 | ||||||
|  |     @FormUrlEncoded | ||||||
|  |     @POST("/api/v1/media/{mediaId}/archive/") | ||||||
|  |     suspend fun archive( | ||||||
|  |         @Path("mediaId") mediaId: String, | ||||||
|  |         @FieldMap signedForm: Map<String, String>, | ||||||
|  |     ): String | ||||||
|  | } | ||||||
| @ -26,12 +26,10 @@ object MediaUploader { | |||||||
|     suspend fun uploadPhoto( |     suspend fun uploadPhoto( | ||||||
|         uri: Uri, |         uri: Uri, | ||||||
|         contentResolver: ContentResolver, |         contentResolver: ContentResolver, | ||||||
|     ): MediaUploadResponse { |     ): MediaUploadResponse = withContext(Dispatchers.IO) { | ||||||
|         return withContext(Dispatchers.IO) { |         val bitmapResult = BitmapUtils.loadBitmap(contentResolver, uri, 1000f, false) | ||||||
|             val bitmapResult = BitmapUtils.loadBitmap(contentResolver, uri, 1000f, false) |         val bitmap = bitmapResult?.bitmap ?: throw IOException("bitmap is null") | ||||||
|             val bitmap = bitmapResult?.bitmap ?: throw IOException("bitmap is null") |         uploadPhoto(bitmap) | ||||||
|             uploadPhoto(bitmap) |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Suppress("BlockingMethodInNonBlockingContext") |     @Suppress("BlockingMethodInNonBlockingContext") | ||||||
| @ -98,25 +96,23 @@ object MediaUploader { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private fun create(mediaType: MediaType, inputStream: InputStream): RequestBody { |     private fun create(mediaType: MediaType, inputStream: InputStream): RequestBody = object : RequestBody() { | ||||||
|         return object : RequestBody() { |         override fun contentType(): MediaType { | ||||||
|             override fun contentType(): MediaType { |             return mediaType | ||||||
|                 return mediaType |         } | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             override fun contentLength(): Long { |         override fun contentLength(): Long { | ||||||
|                 return try { |             return try { | ||||||
|                     inputStream.available().toLong() |                 inputStream.available().toLong() | ||||||
|                 } catch (e: IOException) { |             } catch (e: IOException) { | ||||||
|                     0 |                 0 | ||||||
|                 } |  | ||||||
|             } |             } | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|             @Throws(IOException::class) |         @Throws(IOException::class) | ||||||
|             @Suppress("DEPRECATION_ERROR") |         @Suppress("DEPRECATION_ERROR") | ||||||
|             override fun writeTo(sink: BufferedSink) { |         override fun writeTo(sink: BufferedSink) { | ||||||
|                 Okio.source(inputStream).use { sink.writeAll(it) } |             Okio.source(inputStream).use { sink.writeAll(it) } | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -23,11 +23,9 @@ import awais.instagrabber.utils.extensions.TAG | |||||||
| import awais.instagrabber.utils.getCsrfTokenFromCookie | import awais.instagrabber.utils.getCsrfTokenFromCookie | ||||||
| import awais.instagrabber.utils.getUserIdFromCookie | import awais.instagrabber.utils.getUserIdFromCookie | ||||||
| import awais.instagrabber.webservices.MediaService | import awais.instagrabber.webservices.MediaService | ||||||
| import awais.instagrabber.webservices.ServiceCallback |  | ||||||
| import com.google.common.collect.ImmutableList | import com.google.common.collect.ImmutableList | ||||||
| import retrofit2.Call | import kotlinx.coroutines.Dispatchers | ||||||
| import retrofit2.Callback | import kotlinx.coroutines.launch | ||||||
| import retrofit2.Response |  | ||||||
| import java.util.* | import java.util.* | ||||||
| 
 | 
 | ||||||
| class PostViewV2ViewModel : ViewModel() { | class PostViewV2ViewModel : ViewModel() { | ||||||
| @ -127,44 +125,51 @@ class PostViewV2ViewModel : ViewModel() { | |||||||
|     fun like(): LiveData<Resource<Any?>> { |     fun like(): LiveData<Resource<Any?>> { | ||||||
|         val data = MutableLiveData<Resource<Any?>>() |         val data = MutableLiveData<Resource<Any?>>() | ||||||
|         data.postValue(loading(null)) |         data.postValue(loading(null)) | ||||||
|         mediaService?.like(media.pk, getLikeUnlikeCallback(data)) |         viewModelScope.launch(Dispatchers.IO) { | ||||||
|  |             try { | ||||||
|  |                 val mediaId = media.pk ?: return@launch | ||||||
|  |                 val liked = mediaService?.like(mediaId) | ||||||
|  |                 updateMediaLikeUnlike(data, liked ?: false) | ||||||
|  |             } catch (e: Exception) { | ||||||
|  |                 data.postValue(error(e.message, null)) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|         return data |         return data | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun unlike(): LiveData<Resource<Any?>> { |     fun unlike(): LiveData<Resource<Any?>> { | ||||||
|         val data = MutableLiveData<Resource<Any?>>() |         val data = MutableLiveData<Resource<Any?>>() | ||||||
|         data.postValue(loading(null)) |         data.postValue(loading(null)) | ||||||
|         mediaService?.unlike(media.pk, getLikeUnlikeCallback(data)) |         viewModelScope.launch(Dispatchers.IO) { | ||||||
|  |             try { | ||||||
|  |                 val mediaId = media.pk ?: return@launch | ||||||
|  |                 val unliked = mediaService?.unlike(mediaId) | ||||||
|  |                 updateMediaLikeUnlike(data, unliked ?: false) | ||||||
|  |             } catch (e: Exception) { | ||||||
|  |                 data.postValue(error(e.message, null)) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|         return data |         return data | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private fun getLikeUnlikeCallback(data: MutableLiveData<Resource<Any?>>): ServiceCallback<Boolean?> { |     private fun updateMediaLikeUnlike(data: MutableLiveData<Resource<Any?>>, result: Boolean) { | ||||||
|         return object : ServiceCallback<Boolean?> { |         if (!result) { | ||||||
|             override fun onSuccess(result: Boolean?) { |             data.postValue(error("", null)) | ||||||
|                 if (result != null && !result) { |             return | ||||||
|                     data.postValue(error("", null)) |  | ||||||
|                     return |  | ||||||
|                 } |  | ||||||
|                 data.postValue(success(true)) |  | ||||||
|                 val currentLikesCount = media.likeCount |  | ||||||
|                 val updatedCount: Long |  | ||||||
|                 if (!media.hasLiked) { |  | ||||||
|                     updatedCount = currentLikesCount + 1 |  | ||||||
|                     media.hasLiked = true |  | ||||||
|                 } else { |  | ||||||
|                     updatedCount = currentLikesCount - 1 |  | ||||||
|                     media.hasLiked = false |  | ||||||
|                 } |  | ||||||
|                 media.likeCount = updatedCount |  | ||||||
|                 likeCount.postValue(updatedCount) |  | ||||||
|                 liked.postValue(media.hasLiked) |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             override fun onFailure(t: Throwable) { |  | ||||||
|                 data.postValue(error(t.message, null)) |  | ||||||
|                 Log.e(TAG, "Error during like/unlike", t) |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|  |         data.postValue(success(true)) | ||||||
|  |         val currentLikesCount = media.likeCount | ||||||
|  |         val updatedCount: Long | ||||||
|  |         if (!media.hasLiked) { | ||||||
|  |             updatedCount = currentLikesCount + 1 | ||||||
|  |             media.hasLiked = true | ||||||
|  |         } else { | ||||||
|  |             updatedCount = currentLikesCount - 1 | ||||||
|  |             media.hasLiked = false | ||||||
|  |         } | ||||||
|  |         media.likeCount = updatedCount | ||||||
|  |         likeCount.postValue(updatedCount) | ||||||
|  |         liked.postValue(media.hasLiked) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun toggleSave(): LiveData<Resource<Any?>> { |     fun toggleSave(): LiveData<Resource<Any?>> { | ||||||
| @ -180,79 +185,87 @@ class PostViewV2ViewModel : ViewModel() { | |||||||
|     fun save(collection: String?, ignoreSaveState: Boolean): LiveData<Resource<Any?>> { |     fun save(collection: String?, ignoreSaveState: Boolean): LiveData<Resource<Any?>> { | ||||||
|         val data = MutableLiveData<Resource<Any?>>() |         val data = MutableLiveData<Resource<Any?>>() | ||||||
|         data.postValue(loading(null)) |         data.postValue(loading(null)) | ||||||
|         mediaService?.save(media.pk, collection, getSaveUnsaveCallback(data, ignoreSaveState)) |         viewModelScope.launch(Dispatchers.IO) { | ||||||
|  |             try { | ||||||
|  |                 val mediaId = media.pk ?: return@launch | ||||||
|  |                 val saved = mediaService?.save(mediaId, collection) | ||||||
|  |                 getSaveUnsaveCallback(data, saved ?: false, ignoreSaveState) | ||||||
|  |             } catch (e: Exception) { | ||||||
|  |                 data.postValue(error(e.message, null)) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|         return data |         return data | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun unsave(): LiveData<Resource<Any?>> { |     fun unsave(): LiveData<Resource<Any?>> { | ||||||
|         val data = MutableLiveData<Resource<Any?>>() |         val data = MutableLiveData<Resource<Any?>>() | ||||||
|         data.postValue(loading(null)) |         data.postValue(loading(null)) | ||||||
|         mediaService?.unsave(media.pk, getSaveUnsaveCallback(data, false)) |         viewModelScope.launch(Dispatchers.IO) { | ||||||
|  |             val mediaId = media.pk ?: return@launch | ||||||
|  |             val unsaved = mediaService?.unsave(mediaId) | ||||||
|  |             getSaveUnsaveCallback(data, unsaved ?: false, false) | ||||||
|  |         } | ||||||
|         return data |         return data | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private fun getSaveUnsaveCallback( |     private fun getSaveUnsaveCallback( | ||||||
|         data: MutableLiveData<Resource<Any?>>, |         data: MutableLiveData<Resource<Any?>>, | ||||||
|  |         result: Boolean, | ||||||
|         ignoreSaveState: Boolean, |         ignoreSaveState: Boolean, | ||||||
|     ): ServiceCallback<Boolean?> { |     ) { | ||||||
|         return object : ServiceCallback<Boolean?> { |         if (!result) { | ||||||
|             override fun onSuccess(result: Boolean?) { |             data.postValue(error("", null)) | ||||||
|                 if (result != null && !result) { |             return | ||||||
|                     data.postValue(error("", null)) |  | ||||||
|                     return |  | ||||||
|                 } |  | ||||||
|                 data.postValue(success(true)) |  | ||||||
|                 if (!ignoreSaveState) media.hasViewerSaved = !media.hasViewerSaved |  | ||||||
|                 saved.postValue(media.hasViewerSaved) |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             override fun onFailure(t: Throwable) { |  | ||||||
|                 data.postValue(error(t.message, null)) |  | ||||||
|                 Log.e(TAG, "Error during save/unsave", t) |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|  |         data.postValue(success(true)) | ||||||
|  |         if (!ignoreSaveState) media.hasViewerSaved = !media.hasViewerSaved | ||||||
|  |         saved.postValue(media.hasViewerSaved) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun updateCaption(caption: String): LiveData<Resource<Any?>> { |     fun updateCaption(caption: String): LiveData<Resource<Any?>> { | ||||||
|         val data = MutableLiveData<Resource<Any?>>() |         val data = MutableLiveData<Resource<Any?>>() | ||||||
|         data.postValue(loading(null)) |         data.postValue(loading(null)) | ||||||
|         mediaService?.editCaption(media.pk, caption, object : ServiceCallback<Boolean?> { |         viewModelScope.launch(Dispatchers.IO) { | ||||||
|             override fun onSuccess(result: Boolean?) { |             try { | ||||||
|  |                 val postId = media.pk ?: return@launch | ||||||
|  |                 val result = mediaService?.editCaption(postId, caption) | ||||||
|                 if (result != null && result) { |                 if (result != null && result) { | ||||||
|                     data.postValue(success("")) |                     data.postValue(success("")) | ||||||
|                     media.setPostCaption(caption) |                     media.setPostCaption(caption) | ||||||
|                     this@PostViewV2ViewModel.caption.postValue(media.caption) |                     this@PostViewV2ViewModel.caption.postValue(media.caption) | ||||||
|                     return |                     return@launch | ||||||
|                 } |                 } | ||||||
|                 data.postValue(error("", null)) |                 data.postValue(error("", null)) | ||||||
|  |             } catch (e: Exception) { | ||||||
|  |                 Log.e(TAG, "Error editing caption", e) | ||||||
|  |                 data.postValue(error(e.message, null)) | ||||||
|             } |             } | ||||||
| 
 |         } | ||||||
|             override fun onFailure(t: Throwable) { |  | ||||||
|                 Log.e(TAG, "Error editing caption", t) |  | ||||||
|                 data.postValue(error(t.message, null)) |  | ||||||
|             } |  | ||||||
|         }) |  | ||||||
|         return data |         return data | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun translateCaption(): LiveData<Resource<String?>> { |     fun translateCaption(): LiveData<Resource<String?>> { | ||||||
|         val data = MutableLiveData<Resource<String?>>() |         val data = MutableLiveData<Resource<String?>>() | ||||||
|         data.postValue(loading(null)) |         data.postValue(loading(null)) | ||||||
|         val value = caption.value ?: return data |         val value = caption.value | ||||||
|         mediaService?.translate(value.pk, "1", object : ServiceCallback<String?> { |         val pk = value?.pk | ||||||
|             override fun onSuccess(result: String?) { |         if (pk == null) { | ||||||
|  |             data.postValue(error("caption is null", null)) | ||||||
|  |             return data | ||||||
|  |         } | ||||||
|  |         viewModelScope.launch(Dispatchers.IO) { | ||||||
|  |             try { | ||||||
|  |                 val result = mediaService?.translate(pk, "1") | ||||||
|                 if (result.isNullOrBlank()) { |                 if (result.isNullOrBlank()) { | ||||||
|                     data.postValue(error("", null)) |                     data.postValue(error("", null)) | ||||||
|                     return |                     return@launch | ||||||
|                 } |                 } | ||||||
|                 data.postValue(success(result)) |                 data.postValue(success(result)) | ||||||
|  |             } catch (e: Exception) { | ||||||
|  |                 Log.e(TAG, "Error translating comment", e) | ||||||
|  |                 data.postValue(error(e.message, null)) | ||||||
|             } |             } | ||||||
| 
 |         } | ||||||
|             override fun onFailure(t: Throwable) { |  | ||||||
|                 Log.e(TAG, "Error translating comment", t) |  | ||||||
|                 data.postValue(error(t.message, null)) |  | ||||||
|             } |  | ||||||
|         }) |  | ||||||
|         return data |         return data | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -273,30 +286,19 @@ class PostViewV2ViewModel : ViewModel() { | |||||||
|             data.postValue(error("media id or type is null", null)) |             data.postValue(error("media id or type is null", null)) | ||||||
|             return data |             return data | ||||||
|         } |         } | ||||||
|         val request = mediaService?.delete(mediaId, mediaType) |         viewModelScope.launch(Dispatchers.IO) { | ||||||
|         if (request == null) { |             try { | ||||||
|             data.postValue(success(Any())) |                 val response = mediaService?.delete(mediaId, mediaType) | ||||||
|             return data |                 if (response == null) { | ||||||
|         } |                     data.postValue(success(Any())) | ||||||
|         request.enqueue(object : Callback<String?> { |                     return@launch | ||||||
|             override fun onResponse(call: Call<String?>, response: Response<String?>) { |  | ||||||
|                 if (!response.isSuccessful) { |  | ||||||
|                     data.postValue(error(R.string.generic_null_response, null)) |  | ||||||
|                     return |  | ||||||
|                 } |  | ||||||
|                 val body = response.body() |  | ||||||
|                 if (body == null) { |  | ||||||
|                     data.postValue(error(R.string.generic_null_response, null)) |  | ||||||
|                     return |  | ||||||
|                 } |                 } | ||||||
|                 data.postValue(success(Any())) |                 data.postValue(success(Any())) | ||||||
|  |             } catch (e: Exception) { | ||||||
|  |                 Log.e(TAG, "delete: ", e) | ||||||
|  |                 data.postValue(error(e.message, null)) | ||||||
|             } |             } | ||||||
| 
 |         } | ||||||
|             override fun onFailure(call: Call<String?>, t: Throwable) { |  | ||||||
|                 Log.e(TAG, "onFailure: ", t) |  | ||||||
|                 data.postValue(error(t.message, null)) |  | ||||||
|             } |  | ||||||
|         }) |  | ||||||
|         return data |         return data | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,317 +0,0 @@ | |||||||
| package awais.instagrabber.webservices; |  | ||||||
| 
 |  | ||||||
| import android.util.Log; |  | ||||||
| 
 |  | ||||||
| import androidx.annotation.NonNull; |  | ||||||
| 
 |  | ||||||
| import com.google.common.collect.ImmutableList; |  | ||||||
| import com.google.common.collect.ImmutableMap; |  | ||||||
| 
 |  | ||||||
| import org.json.JSONException; |  | ||||||
| import org.json.JSONObject; |  | ||||||
| 
 |  | ||||||
| import java.util.Collections; |  | ||||||
| import java.util.HashMap; |  | ||||||
| import java.util.List; |  | ||||||
| import java.util.Map; |  | ||||||
| import java.util.Objects; |  | ||||||
| 
 |  | ||||||
| import awais.instagrabber.models.enums.MediaItemType; |  | ||||||
| import awais.instagrabber.repositories.MediaRepository; |  | ||||||
| import awais.instagrabber.repositories.requests.Clip; |  | ||||||
| import awais.instagrabber.repositories.requests.UploadFinishOptions; |  | ||||||
| import awais.instagrabber.repositories.requests.VideoOptions; |  | ||||||
| import awais.instagrabber.repositories.responses.LikersResponse; |  | ||||||
| import awais.instagrabber.repositories.responses.Media; |  | ||||||
| import awais.instagrabber.repositories.responses.MediaInfoResponse; |  | ||||||
| import awais.instagrabber.repositories.responses.User; |  | ||||||
| import awais.instagrabber.utils.DateUtils; |  | ||||||
| import awais.instagrabber.utils.MediaUploadHelper; |  | ||||||
| import awais.instagrabber.utils.TextUtils; |  | ||||||
| import awais.instagrabber.utils.Utils; |  | ||||||
| import retrofit2.Call; |  | ||||||
| import retrofit2.Callback; |  | ||||||
| import retrofit2.Response; |  | ||||||
| 
 |  | ||||||
| public class MediaService extends BaseService { |  | ||||||
|     private static final String TAG = "MediaService"; |  | ||||||
|     private static final List<MediaItemType> DELETABLE_ITEMS_TYPES = ImmutableList.of(MediaItemType.MEDIA_TYPE_IMAGE, |  | ||||||
|                                                                                       MediaItemType.MEDIA_TYPE_VIDEO, |  | ||||||
|                                                                                       MediaItemType.MEDIA_TYPE_SLIDER); |  | ||||||
| 
 |  | ||||||
|     private final MediaRepository repository; |  | ||||||
|     private final String deviceUuid, csrfToken; |  | ||||||
|     private final long userId; |  | ||||||
| 
 |  | ||||||
|     private static MediaService instance; |  | ||||||
| 
 |  | ||||||
|     private MediaService(final String deviceUuid, |  | ||||||
|                          final String csrfToken, |  | ||||||
|                          final long userId) { |  | ||||||
|         this.deviceUuid = deviceUuid; |  | ||||||
|         this.csrfToken = csrfToken; |  | ||||||
|         this.userId = userId; |  | ||||||
|         repository = RetrofitFactory.INSTANCE |  | ||||||
|                                     .getRetrofit() |  | ||||||
|                                     .create(MediaRepository.class); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public String getCsrfToken() { |  | ||||||
|         return csrfToken; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public String getDeviceUuid() { |  | ||||||
|         return deviceUuid; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public long getUserId() { |  | ||||||
|         return userId; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public static MediaService getInstance(final String deviceUuid, final String csrfToken, final long userId) { |  | ||||||
|         if (instance == null |  | ||||||
|                 || !Objects.equals(instance.getCsrfToken(), csrfToken) |  | ||||||
|                 || !Objects.equals(instance.getDeviceUuid(), deviceUuid) |  | ||||||
|                 || !Objects.equals(instance.getUserId(), userId)) { |  | ||||||
|             instance = new MediaService(deviceUuid, csrfToken, userId); |  | ||||||
|         } |  | ||||||
|         return instance; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public void fetch(final long mediaId, |  | ||||||
|                       final ServiceCallback<Media> callback) { |  | ||||||
|         final Call<MediaInfoResponse> request = repository.fetch(mediaId); |  | ||||||
|         request.enqueue(new Callback<MediaInfoResponse>() { |  | ||||||
|             @Override |  | ||||||
|             public void onResponse(@NonNull final Call<MediaInfoResponse> call, |  | ||||||
|                                    @NonNull final Response<MediaInfoResponse> response) { |  | ||||||
|                 if (callback == null) return; |  | ||||||
|                 final MediaInfoResponse mediaInfoResponse = response.body(); |  | ||||||
|                 if (mediaInfoResponse == null || mediaInfoResponse.getItems() == null || mediaInfoResponse.getItems().isEmpty()) { |  | ||||||
|                     callback.onSuccess(null); |  | ||||||
|                     return; |  | ||||||
|                 } |  | ||||||
|                 callback.onSuccess(mediaInfoResponse.getItems().get(0)); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             @Override |  | ||||||
|             public void onFailure(@NonNull final Call<MediaInfoResponse> call, |  | ||||||
|                                   @NonNull final Throwable t) { |  | ||||||
|                 if (callback != null) { |  | ||||||
|                     callback.onFailure(t); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public void like(final String mediaId, |  | ||||||
|                      final ServiceCallback<Boolean> callback) { |  | ||||||
|         action(mediaId, "like", null, callback); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public void unlike(final String mediaId, |  | ||||||
|                        final ServiceCallback<Boolean> callback) { |  | ||||||
|         action(mediaId, "unlike", null, callback); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public void save(final String mediaId, |  | ||||||
|                      final String collection, |  | ||||||
|                      final ServiceCallback<Boolean> callback) { |  | ||||||
|         action(mediaId, "save", collection, callback); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public void unsave(final String mediaId, |  | ||||||
|                        final ServiceCallback<Boolean> callback) { |  | ||||||
|         action(mediaId, "unsave", null, callback); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private void action(final String mediaId, |  | ||||||
|                         final String action, |  | ||||||
|                         final String collection, |  | ||||||
|                         final ServiceCallback<Boolean> callback) { |  | ||||||
|         final Map<String, Object> form = new HashMap<>(); |  | ||||||
|         form.put("media_id", mediaId); |  | ||||||
|         form.put("_csrftoken", csrfToken); |  | ||||||
|         form.put("_uid", userId); |  | ||||||
|         form.put("_uuid", deviceUuid); |  | ||||||
|         // form.put("radio_type", "wifi-none"); |  | ||||||
|         if (action.equals("save") && !TextUtils.isEmpty(collection)) form.put("added_collection_ids", "[" + collection + "]"); |  | ||||||
|         // there also exists "removed_collection_ids" which can be used with "save" and "unsave" |  | ||||||
|         final Map<String, String> signedForm = Utils.sign(form); |  | ||||||
|         final Call<String> request = repository.action(action, mediaId, signedForm); |  | ||||||
|         request.enqueue(new Callback<String>() { |  | ||||||
|             @Override |  | ||||||
|             public void onResponse(@NonNull final Call<String> call, |  | ||||||
|                                    @NonNull final Response<String> response) { |  | ||||||
|                 if (callback == null) return; |  | ||||||
|                 final String body = response.body(); |  | ||||||
|                 if (body == null) { |  | ||||||
|                     callback.onFailure(new RuntimeException("Returned body is null")); |  | ||||||
|                     return; |  | ||||||
|                 } |  | ||||||
|                 try { |  | ||||||
|                     final JSONObject jsonObject = new JSONObject(body); |  | ||||||
|                     final String status = jsonObject.optString("status"); |  | ||||||
|                     callback.onSuccess(status.equals("ok")); |  | ||||||
|                 } catch (JSONException e) { |  | ||||||
|                     callback.onFailure(e); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             @Override |  | ||||||
|             public void onFailure(@NonNull final Call<String> call, |  | ||||||
|                                   @NonNull final Throwable t) { |  | ||||||
|                 if (callback != null) { |  | ||||||
|                     callback.onFailure(t); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public void editCaption(final String postId, |  | ||||||
|                             final String newCaption, |  | ||||||
|                             @NonNull final ServiceCallback<Boolean> callback) { |  | ||||||
|         final Map<String, Object> form = new HashMap<>(); |  | ||||||
|         form.put("_csrftoken", csrfToken); |  | ||||||
|         form.put("_uid", userId); |  | ||||||
|         form.put("_uuid", deviceUuid); |  | ||||||
|         form.put("igtv_feed_preview", "false"); |  | ||||||
|         form.put("media_id", postId); |  | ||||||
|         form.put("caption_text", newCaption); |  | ||||||
|         final Map<String, String> signedForm = Utils.sign(form); |  | ||||||
|         final Call<String> request = repository.editCaption(postId, signedForm); |  | ||||||
|         request.enqueue(new Callback<String>() { |  | ||||||
|             @Override |  | ||||||
|             public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { |  | ||||||
|                 final String body = response.body(); |  | ||||||
|                 if (body == null) { |  | ||||||
|                     Log.e(TAG, "Error occurred while editing caption"); |  | ||||||
|                     callback.onSuccess(false); |  | ||||||
|                     return; |  | ||||||
|                 } |  | ||||||
|                 try { |  | ||||||
|                     final JSONObject jsonObject = new JSONObject(body); |  | ||||||
|                     final String status = jsonObject.optString("status"); |  | ||||||
|                     callback.onSuccess(status.equals("ok")); |  | ||||||
|                 } catch (JSONException e) { |  | ||||||
|                     // Log.e(TAG, "Error parsing body", e); |  | ||||||
|                     callback.onFailure(e); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             @Override |  | ||||||
|             public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) { |  | ||||||
|                 Log.e(TAG, "Error editing caption", t); |  | ||||||
|                 callback.onFailure(t); |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public void fetchLikes(final String mediaId, |  | ||||||
|                            final boolean isComment, |  | ||||||
|                            @NonNull final ServiceCallback<List<User>> callback) { |  | ||||||
|         final Call<LikersResponse> likesRequest = repository.fetchLikes(mediaId, isComment ? "comment_likers" : "likers"); |  | ||||||
|         likesRequest.enqueue(new Callback<LikersResponse>() { |  | ||||||
|             @Override |  | ||||||
|             public void onResponse(@NonNull final Call<LikersResponse> call, @NonNull final Response<LikersResponse> response) { |  | ||||||
|                 final LikersResponse likersResponse = response.body(); |  | ||||||
|                 if (likersResponse == null) { |  | ||||||
|                     Log.e(TAG, "Error occurred while fetching likes of " + mediaId); |  | ||||||
|                     callback.onSuccess(null); |  | ||||||
|                     return; |  | ||||||
|                 } |  | ||||||
|                 callback.onSuccess(likersResponse.getUsers()); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             @Override |  | ||||||
|             public void onFailure(@NonNull final Call<LikersResponse> call, @NonNull final Throwable t) { |  | ||||||
|                 Log.e(TAG, "Error getting likes", t); |  | ||||||
|                 callback.onFailure(t); |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public void translate(final String id, |  | ||||||
|                           final String type, // 1 caption 2 comment 3 bio |  | ||||||
|                           @NonNull final ServiceCallback<String> callback) { |  | ||||||
|         final Map<String, String> form = new HashMap<>(); |  | ||||||
|         form.put("id", String.valueOf(id)); |  | ||||||
|         form.put("type", type); |  | ||||||
|         final Call<String> request = repository.translate(form); |  | ||||||
|         request.enqueue(new Callback<String>() { |  | ||||||
|             @Override |  | ||||||
|             public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { |  | ||||||
|                 final String body = response.body(); |  | ||||||
|                 if (body == null) { |  | ||||||
|                     Log.e(TAG, "Error occurred while translating"); |  | ||||||
|                     callback.onSuccess(null); |  | ||||||
|                     return; |  | ||||||
|                 } |  | ||||||
|                 try { |  | ||||||
|                     final JSONObject jsonObject = new JSONObject(body); |  | ||||||
|                     final String translation = jsonObject.optString("translation"); |  | ||||||
|                     callback.onSuccess(translation); |  | ||||||
|                 } catch (JSONException e) { |  | ||||||
|                     // Log.e(TAG, "Error parsing body", e); |  | ||||||
|                     callback.onFailure(e); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             @Override |  | ||||||
|             public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) { |  | ||||||
|                 Log.e(TAG, "Error translating", t); |  | ||||||
|                 callback.onFailure(t); |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public Call<String> uploadFinish(@NonNull final UploadFinishOptions options) { |  | ||||||
|         if (options.getVideoOptions() != null) { |  | ||||||
|             final VideoOptions videoOptions = options.getVideoOptions(); |  | ||||||
|             if (videoOptions.getClips().isEmpty()) { |  | ||||||
|                 videoOptions.setClips(Collections.singletonList(new Clip(videoOptions.getLength(), options.getSourceType()))); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         final String timezoneOffset = String.valueOf(DateUtils.getTimezoneOffset()); |  | ||||||
|         final ImmutableMap.Builder<String, Object> formBuilder = ImmutableMap.<String, Object>builder() |  | ||||||
|                 .put("timezone_offset", timezoneOffset) |  | ||||||
|                 .put("_csrftoken", csrfToken) |  | ||||||
|                 .put("source_type", options.getSourceType()) |  | ||||||
|                 .put("_uid", String.valueOf(userId)) |  | ||||||
|                 .put("_uuid", deviceUuid) |  | ||||||
|                 .put("upload_id", options.getUploadId()); |  | ||||||
|         if (options.getVideoOptions() != null) { |  | ||||||
|             formBuilder.putAll(options.getVideoOptions().getMap()); |  | ||||||
|         } |  | ||||||
|         final Map<String, String> queryMap = options.getVideoOptions() != null ? ImmutableMap.of("video", "1") : Collections.emptyMap(); |  | ||||||
|         final Map<String, String> signedForm = Utils.sign(formBuilder.build()); |  | ||||||
|         return repository.uploadFinish(MediaUploadHelper.getRetryContextString(), queryMap, signedForm); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public Call<String> delete(@NonNull final String postId, |  | ||||||
|                                @NonNull final MediaItemType type) { |  | ||||||
|         if (!DELETABLE_ITEMS_TYPES.contains(type)) return null; |  | ||||||
|         final Map<String, Object> form = new HashMap<>(); |  | ||||||
|         form.put("_csrftoken", csrfToken); |  | ||||||
|         form.put("_uid", userId); |  | ||||||
|         form.put("_uuid", deviceUuid); |  | ||||||
|         form.put("igtv_feed_preview", "false"); |  | ||||||
|         form.put("media_id", postId); |  | ||||||
|         final Map<String, String> signedForm = Utils.sign(form); |  | ||||||
|         final String mediaType; |  | ||||||
|         switch (type) { |  | ||||||
|             case MEDIA_TYPE_IMAGE: |  | ||||||
|                 mediaType = "PHOTO"; |  | ||||||
|                 break; |  | ||||||
|             case MEDIA_TYPE_VIDEO: |  | ||||||
|                 mediaType = "VIDEO"; |  | ||||||
|                 break; |  | ||||||
|             case MEDIA_TYPE_SLIDER: |  | ||||||
|                 mediaType = "CAROUSEL"; |  | ||||||
|                 break; |  | ||||||
|             default: |  | ||||||
|                 return null; |  | ||||||
|         } |  | ||||||
|         return repository.delete(postId, mediaType, signedForm); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
							
								
								
									
										169
									
								
								app/src/main/java/awais/instagrabber/webservices/MediaService.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								app/src/main/java/awais/instagrabber/webservices/MediaService.kt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,169 @@ | |||||||
|  | package awais.instagrabber.webservices | ||||||
|  | 
 | ||||||
|  | import awais.instagrabber.models.enums.MediaItemType | ||||||
|  | import awais.instagrabber.repositories.MediaRepository | ||||||
|  | import awais.instagrabber.repositories.requests.Clip | ||||||
|  | import awais.instagrabber.repositories.requests.UploadFinishOptions | ||||||
|  | import awais.instagrabber.repositories.responses.Media | ||||||
|  | import awais.instagrabber.repositories.responses.User | ||||||
|  | import awais.instagrabber.utils.DateUtils | ||||||
|  | import awais.instagrabber.utils.Utils | ||||||
|  | import awais.instagrabber.utils.retryContextString | ||||||
|  | import awais.instagrabber.webservices.RetrofitFactory.retrofit | ||||||
|  | import org.json.JSONObject | ||||||
|  | 
 | ||||||
|  | class MediaService private constructor( | ||||||
|  |     val deviceUuid: String, | ||||||
|  |     val csrfToken: String, | ||||||
|  |     val userId: Long, | ||||||
|  | ) : BaseService() { | ||||||
|  |     private val repository: MediaRepository = retrofit.create(MediaRepository::class.java) | ||||||
|  | 
 | ||||||
|  |     suspend fun fetch( | ||||||
|  |         mediaId: Long, | ||||||
|  |     ): Media? { | ||||||
|  |         val response = repository.fetch(mediaId) | ||||||
|  |         return if (response.items.isNullOrEmpty()) { | ||||||
|  |             null | ||||||
|  |         } else response.items[0] | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     suspend fun like(mediaId: String): Boolean = action(mediaId, "like", null) | ||||||
|  | 
 | ||||||
|  |     suspend fun unlike(mediaId: String): Boolean = action(mediaId, "unlike", null) | ||||||
|  | 
 | ||||||
|  |     suspend fun save(mediaId: String, collection: String?): Boolean = action(mediaId, "save", collection) | ||||||
|  | 
 | ||||||
|  |     suspend fun unsave(mediaId: String): Boolean = action(mediaId, "unsave", null) | ||||||
|  | 
 | ||||||
|  |     private suspend fun action( | ||||||
|  |         mediaId: String, | ||||||
|  |         action: String, | ||||||
|  |         collection: String?, | ||||||
|  |     ): Boolean { | ||||||
|  |         val form: MutableMap<String, Any> = mutableMapOf( | ||||||
|  |             "media_id" to mediaId, | ||||||
|  |             "_csrftoken" to csrfToken, | ||||||
|  |             "_uid" to userId, | ||||||
|  |             "_uuid" to deviceUuid, | ||||||
|  |         ) | ||||||
|  |         // form.put("radio_type", "wifi-none"); | ||||||
|  |         if (action == "save" && !collection.isNullOrBlank()) { | ||||||
|  |             form["added_collection_ids"] = "[$collection]" | ||||||
|  |         } | ||||||
|  |         // there also exists "removed_collection_ids" which can be used with "save" and "unsave" | ||||||
|  |         val signedForm = Utils.sign(form) | ||||||
|  |         val response = repository.action(action, mediaId, signedForm) | ||||||
|  |         val jsonObject = JSONObject(response) | ||||||
|  |         val status = jsonObject.optString("status") | ||||||
|  |         return status == "ok" | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     suspend fun editCaption( | ||||||
|  |         postId: String, | ||||||
|  |         newCaption: String, | ||||||
|  |     ): Boolean { | ||||||
|  |         val form = mapOf( | ||||||
|  |             "_csrftoken" to csrfToken, | ||||||
|  |             "_uid" to userId, | ||||||
|  |             "_uuid" to deviceUuid, | ||||||
|  |             "igtv_feed_preview" to "false", | ||||||
|  |             "media_id" to postId, | ||||||
|  |             "caption_text" to newCaption, | ||||||
|  |         ) | ||||||
|  |         val signedForm = Utils.sign(form) | ||||||
|  |         val response = repository.editCaption(postId, signedForm) | ||||||
|  |         val jsonObject = JSONObject(response) | ||||||
|  |         val status = jsonObject.optString("status") | ||||||
|  |         return status == "ok" | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     suspend fun fetchLikes( | ||||||
|  |         mediaId: String, | ||||||
|  |         isComment: Boolean, | ||||||
|  |     ): List<User> { | ||||||
|  |         val response = repository.fetchLikes(mediaId, if (isComment) "comment_likers" else "likers") | ||||||
|  |         return response.users | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     suspend fun translate( | ||||||
|  |         id: String, | ||||||
|  |         type: String,  // 1 caption 2 comment 3 bio | ||||||
|  |     ): String { | ||||||
|  |         val form = mapOf( | ||||||
|  |             "id" to id, | ||||||
|  |             "type" to type, | ||||||
|  |         ) | ||||||
|  |         val response = repository.translate(form) | ||||||
|  |         val jsonObject = JSONObject(response) | ||||||
|  |         return jsonObject.optString("translation") | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     suspend fun uploadFinish(options: UploadFinishOptions): String { | ||||||
|  |         if (options.videoOptions != null) { | ||||||
|  |             val videoOptions = options.videoOptions | ||||||
|  |             if (videoOptions.clips.isEmpty()) { | ||||||
|  |                 videoOptions.clips = listOf(Clip(videoOptions.length, options.sourceType)) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         val timezoneOffset = DateUtils.getTimezoneOffset().toString() | ||||||
|  |         val form = mutableMapOf<String, Any>( | ||||||
|  |             "timezone_offset" to timezoneOffset, | ||||||
|  |             "_csrftoken" to csrfToken, | ||||||
|  |             "source_type" to options.sourceType, | ||||||
|  |             "_uid" to userId.toString(), | ||||||
|  |             "_uuid" to deviceUuid, | ||||||
|  |             "upload_id" to options.uploadId, | ||||||
|  |         ) | ||||||
|  |         if (options.videoOptions != null) { | ||||||
|  |             form.putAll(options.videoOptions.map) | ||||||
|  |         } | ||||||
|  |         val queryMap = if (options.videoOptions != null) mapOf("video" to "1") else emptyMap() | ||||||
|  |         val signedForm = Utils.sign(form) | ||||||
|  |         return repository.uploadFinish(retryContextString, queryMap, signedForm) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     suspend fun delete( | ||||||
|  |         postId: String, | ||||||
|  |         type: MediaItemType, | ||||||
|  |     ): String? { | ||||||
|  |         if (!DELETABLE_ITEMS_TYPES.contains(type)) return null | ||||||
|  |         val form = mapOf( | ||||||
|  |             "_csrftoken" to csrfToken, | ||||||
|  |             "_uid" to userId, | ||||||
|  |             "_uuid" to deviceUuid, | ||||||
|  |             "igtv_feed_preview" to "false", | ||||||
|  |             "media_id" to postId, | ||||||
|  |         ) | ||||||
|  |         val signedForm = Utils.sign(form) | ||||||
|  |         val mediaType: String = when (type) { | ||||||
|  |             MediaItemType.MEDIA_TYPE_IMAGE -> "PHOTO" | ||||||
|  |             MediaItemType.MEDIA_TYPE_VIDEO -> "VIDEO" | ||||||
|  |             MediaItemType.MEDIA_TYPE_SLIDER -> "CAROUSEL" | ||||||
|  |             else -> return null | ||||||
|  |         } | ||||||
|  |         return repository.delete(postId, mediaType, signedForm) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     companion object { | ||||||
|  |         private val DELETABLE_ITEMS_TYPES = listOf( | ||||||
|  |             MediaItemType.MEDIA_TYPE_IMAGE, | ||||||
|  |             MediaItemType.MEDIA_TYPE_VIDEO, | ||||||
|  |             MediaItemType.MEDIA_TYPE_SLIDER | ||||||
|  |         ) | ||||||
|  |         private lateinit var instance: MediaService | ||||||
|  | 
 | ||||||
|  |         @JvmStatic | ||||||
|  |         fun getInstance(deviceUuid: String, csrfToken: String, userId: Long): MediaService { | ||||||
|  |             if (!this::instance.isInitialized | ||||||
|  |                 || instance.csrfToken != csrfToken | ||||||
|  |                 || instance.deviceUuid != deviceUuid | ||||||
|  |                 || instance.userId != userId | ||||||
|  |             ) { | ||||||
|  |                 instance = MediaService(deviceUuid, csrfToken, userId) | ||||||
|  |             } | ||||||
|  |             return instance | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user