mirror of
				https://github.com/KokaKiwi/BarInsta
				synced 2025-10-31 03:25:34 +00:00 
			
		
		
		
	Convert GraphQLRepository and GraphQLService to kotlin
This commit is contained in:
		
							parent
							
								
									dd3562116b
								
							
						
					
					
						commit
						143a0ce259
					
				| @ -49,7 +49,6 @@ import awais.instagrabber.models.IntentModel | |||||||
| import awais.instagrabber.models.Resource | import awais.instagrabber.models.Resource | ||||||
| import awais.instagrabber.models.Tab | import awais.instagrabber.models.Tab | ||||||
| import awais.instagrabber.models.enums.IntentModelType | import awais.instagrabber.models.enums.IntentModelType | ||||||
| import awais.instagrabber.repositories.responses.Media |  | ||||||
| import awais.instagrabber.services.ActivityCheckerService | import awais.instagrabber.services.ActivityCheckerService | ||||||
| import awais.instagrabber.services.DMSyncAlarmReceiver | import awais.instagrabber.services.DMSyncAlarmReceiver | ||||||
| import awais.instagrabber.utils.* | import awais.instagrabber.utils.* | ||||||
| @ -61,7 +60,6 @@ import awais.instagrabber.viewmodels.AppStateViewModel | |||||||
| import awais.instagrabber.viewmodels.DirectInboxViewModel | import awais.instagrabber.viewmodels.DirectInboxViewModel | ||||||
| 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 com.google.android.material.appbar.AppBarLayout | import com.google.android.material.appbar.AppBarLayout | ||||||
| import com.google.android.material.appbar.AppBarLayout.ScrollingViewBehavior | import com.google.android.material.appbar.AppBarLayout.ScrollingViewBehavior | ||||||
| import com.google.android.material.appbar.CollapsingToolbarLayout | import com.google.android.material.appbar.CollapsingToolbarLayout | ||||||
| @ -71,6 +69,7 @@ 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.Dispatchers | ||||||
| import kotlinx.coroutines.launch | import kotlinx.coroutines.launch | ||||||
|  | import kotlinx.coroutines.withContext | ||||||
| import java.util.* | import java.util.* | ||||||
| import java.util.stream.Collectors | import java.util.stream.Collectors | ||||||
| 
 | 
 | ||||||
| @ -92,7 +91,6 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL | |||||||
|     var currentTabs: List<Tab> = emptyList() |     var currentTabs: List<Tab> = emptyList() | ||||||
|         private set |         private set | ||||||
|     private var showBottomViewDestinations: List<Int> = emptyList() |     private var showBottomViewDestinations: List<Int> = emptyList() | ||||||
|     private var graphQLService: GraphQLService? = null |  | ||||||
| 
 | 
 | ||||||
|     private val serviceConnection: ServiceConnection = object : ServiceConnection { |     private val serviceConnection: ServiceConnection = object : ServiceConnection { | ||||||
|         override fun onServiceConnected(name: ComponentName, service: IBinder) { |         override fun onServiceConnected(name: ComponentName, service: IBinder) { | ||||||
| @ -633,39 +631,32 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL | |||||||
|             .setCancelable(false) |             .setCancelable(false) | ||||||
|             .setView(R.layout.dialog_opening_post) |             .setView(R.layout.dialog_opening_post) | ||||||
|             .create() |             .create() | ||||||
|         if (graphQLService == null) graphQLService = GraphQLService.getInstance() |         alertDialog.show() | ||||||
|         val postCb: ServiceCallback<Media> = object : ServiceCallback<Media> { |         lifecycleScope.launch(Dispatchers.IO) { | ||||||
|             override fun onSuccess(feedModel: Media?) { |             try { | ||||||
|                 if (feedModel != null) { |                 val media = if (isLoggedIn) MediaService.fetch(shortcodeToId(shortCode)) else GraphQLService.fetchPost(shortCode) | ||||||
|                     val currentNavControllerLiveData = currentNavControllerLiveData ?: return |                 withContext(Dispatchers.Main) { | ||||||
|  |                     if (media == null) { | ||||||
|  |                         Toast.makeText(applicationContext, R.string.post_not_found, Toast.LENGTH_SHORT).show() | ||||||
|  |                         return@withContext | ||||||
|  |                     } | ||||||
|  |                     val currentNavControllerLiveData = currentNavControllerLiveData ?: return@withContext | ||||||
|                     val navController = currentNavControllerLiveData.value |                     val navController = currentNavControllerLiveData.value | ||||||
|                     val bundle = Bundle() |                     val bundle = Bundle() | ||||||
|                     bundle.putSerializable(PostViewV2Fragment.ARG_MEDIA, feedModel) |                     bundle.putSerializable(PostViewV2Fragment.ARG_MEDIA, media) | ||||||
|                     try { |                     try { | ||||||
|                         navController?.navigate(R.id.action_global_post_view, bundle) |                         navController?.navigate(R.id.action_global_post_view, bundle) | ||||||
|                     } catch (e: Exception) { |                     } catch (e: Exception) { | ||||||
|                         Log.e(TAG, "showPostView: ", e) |                         Log.e(TAG, "showPostView: ", e) | ||||||
|                     } |                     } | ||||||
|                 } else Toast.makeText(applicationContext, R.string.post_not_found, Toast.LENGTH_SHORT).show() |                 } | ||||||
|                 alertDialog.dismiss() |             } catch (e: Exception) { | ||||||
|             } |                 Log.e(TAG, "showPostView: ", e) | ||||||
| 
 |             } finally { | ||||||
|             override fun onFailure(t: Throwable) { |                 withContext(Dispatchers.Main) { | ||||||
|                 alertDialog.dismiss() |                     alertDialog.dismiss() | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         alertDialog.show() |  | ||||||
|         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) |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -7,9 +7,11 @@ import awais.instagrabber.interfaces.FetchListener; | |||||||
| import awais.instagrabber.repositories.responses.Hashtag; | import awais.instagrabber.repositories.responses.Hashtag; | ||||||
| import awais.instagrabber.repositories.responses.Media; | import awais.instagrabber.repositories.responses.Media; | ||||||
| import awais.instagrabber.repositories.responses.PostsFetchResponse; | import awais.instagrabber.repositories.responses.PostsFetchResponse; | ||||||
|  | import awais.instagrabber.utils.CoroutineUtilsKt; | ||||||
| import awais.instagrabber.webservices.GraphQLService; | import awais.instagrabber.webservices.GraphQLService; | ||||||
| import awais.instagrabber.webservices.ServiceCallback; | import awais.instagrabber.webservices.ServiceCallback; | ||||||
| import awais.instagrabber.webservices.TagsService; | import awais.instagrabber.webservices.TagsService; | ||||||
|  | import kotlinx.coroutines.Dispatchers; | ||||||
| 
 | 
 | ||||||
| public class HashtagPostFetchService implements PostFetcher.PostFetchService { | public class HashtagPostFetchService implements PostFetcher.PostFetchService { | ||||||
|     private final TagsService tagsService; |     private final TagsService tagsService; | ||||||
| @ -23,7 +25,7 @@ public class HashtagPostFetchService implements PostFetcher.PostFetchService { | |||||||
|         this.hashtagModel = hashtagModel; |         this.hashtagModel = hashtagModel; | ||||||
|         this.isLoggedIn = isLoggedIn; |         this.isLoggedIn = isLoggedIn; | ||||||
|         tagsService = isLoggedIn ? TagsService.getInstance() : null; |         tagsService = isLoggedIn ? TagsService.getInstance() : null; | ||||||
|         graphQLService = isLoggedIn ? null : GraphQLService.getInstance(); |         graphQLService = isLoggedIn ? null : GraphQLService.INSTANCE; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
| @ -48,7 +50,17 @@ public class HashtagPostFetchService implements PostFetcher.PostFetchService { | |||||||
|             } |             } | ||||||
|         }; |         }; | ||||||
|         if (isLoggedIn) tagsService.fetchPosts(hashtagModel.getName().toLowerCase(), nextMaxId, cb); |         if (isLoggedIn) tagsService.fetchPosts(hashtagModel.getName().toLowerCase(), nextMaxId, cb); | ||||||
|         else graphQLService.fetchHashtagPosts(hashtagModel.getName().toLowerCase(), nextMaxId, cb); |         else graphQLService.fetchHashtagPosts( | ||||||
|  |                 hashtagModel.getName().toLowerCase(), | ||||||
|  |                 nextMaxId, | ||||||
|  |                 CoroutineUtilsKt.getContinuation((postsFetchResponse, throwable) -> { | ||||||
|  |                     if (throwable != null) { | ||||||
|  |                         cb.onFailure(throwable); | ||||||
|  |                         return; | ||||||
|  |                     } | ||||||
|  |                     cb.onSuccess(postsFetchResponse); | ||||||
|  |                 }, Dispatchers.getIO()) | ||||||
|  |         ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|  | |||||||
| @ -7,9 +7,11 @@ import awais.instagrabber.interfaces.FetchListener; | |||||||
| import awais.instagrabber.repositories.responses.Location; | import awais.instagrabber.repositories.responses.Location; | ||||||
| import awais.instagrabber.repositories.responses.Media; | import awais.instagrabber.repositories.responses.Media; | ||||||
| import awais.instagrabber.repositories.responses.PostsFetchResponse; | import awais.instagrabber.repositories.responses.PostsFetchResponse; | ||||||
|  | import awais.instagrabber.utils.CoroutineUtilsKt; | ||||||
| import awais.instagrabber.webservices.GraphQLService; | import awais.instagrabber.webservices.GraphQLService; | ||||||
| import awais.instagrabber.webservices.LocationService; | import awais.instagrabber.webservices.LocationService; | ||||||
| import awais.instagrabber.webservices.ServiceCallback; | import awais.instagrabber.webservices.ServiceCallback; | ||||||
|  | import kotlinx.coroutines.Dispatchers; | ||||||
| 
 | 
 | ||||||
| public class LocationPostFetchService implements PostFetcher.PostFetchService { | public class LocationPostFetchService implements PostFetcher.PostFetchService { | ||||||
|     private final LocationService locationService; |     private final LocationService locationService; | ||||||
| @ -23,7 +25,7 @@ public class LocationPostFetchService implements PostFetcher.PostFetchService { | |||||||
|         this.locationModel = locationModel; |         this.locationModel = locationModel; | ||||||
|         this.isLoggedIn = isLoggedIn; |         this.isLoggedIn = isLoggedIn; | ||||||
|         locationService = isLoggedIn ? LocationService.getInstance() : null; |         locationService = isLoggedIn ? LocationService.getInstance() : null; | ||||||
|         graphQLService = isLoggedIn ? null : GraphQLService.getInstance(); |         graphQLService = isLoggedIn ? null : GraphQLService.INSTANCE; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
| @ -48,7 +50,17 @@ public class LocationPostFetchService implements PostFetcher.PostFetchService { | |||||||
|             } |             } | ||||||
|         }; |         }; | ||||||
|         if (isLoggedIn) locationService.fetchPosts(locationModel.getPk(), nextMaxId, cb); |         if (isLoggedIn) locationService.fetchPosts(locationModel.getPk(), nextMaxId, cb); | ||||||
|         else graphQLService.fetchLocationPosts(locationModel.getPk(), nextMaxId, cb); |         else graphQLService.fetchLocationPosts( | ||||||
|  |                 locationModel.getPk(), | ||||||
|  |                 nextMaxId, | ||||||
|  |                 CoroutineUtilsKt.getContinuation((postsFetchResponse, throwable) -> { | ||||||
|  |                     if (throwable != null) { | ||||||
|  |                         cb.onFailure(throwable); | ||||||
|  |                         return; | ||||||
|  |                     } | ||||||
|  |                     cb.onSuccess(postsFetchResponse); | ||||||
|  |                 }, Dispatchers.getIO()) | ||||||
|  |         ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|  | |||||||
| @ -7,9 +7,11 @@ import awais.instagrabber.interfaces.FetchListener; | |||||||
| import awais.instagrabber.repositories.responses.Media; | import awais.instagrabber.repositories.responses.Media; | ||||||
| import awais.instagrabber.repositories.responses.PostsFetchResponse; | import awais.instagrabber.repositories.responses.PostsFetchResponse; | ||||||
| import awais.instagrabber.repositories.responses.User; | import awais.instagrabber.repositories.responses.User; | ||||||
|  | import awais.instagrabber.utils.CoroutineUtilsKt; | ||||||
| import awais.instagrabber.webservices.GraphQLService; | import awais.instagrabber.webservices.GraphQLService; | ||||||
| import awais.instagrabber.webservices.ProfileService; | import awais.instagrabber.webservices.ProfileService; | ||||||
| import awais.instagrabber.webservices.ServiceCallback; | import awais.instagrabber.webservices.ServiceCallback; | ||||||
|  | import kotlinx.coroutines.Dispatchers; | ||||||
| 
 | 
 | ||||||
| public class ProfilePostFetchService implements PostFetcher.PostFetchService { | public class ProfilePostFetchService implements PostFetcher.PostFetchService { | ||||||
|     private static final String TAG = "ProfilePostFetchService"; |     private static final String TAG = "ProfilePostFetchService"; | ||||||
| @ -23,7 +25,7 @@ public class ProfilePostFetchService implements PostFetcher.PostFetchService { | |||||||
|     public ProfilePostFetchService(final User profileModel, final boolean isLoggedIn) { |     public ProfilePostFetchService(final User profileModel, final boolean isLoggedIn) { | ||||||
|         this.profileModel = profileModel; |         this.profileModel = profileModel; | ||||||
|         this.isLoggedIn = isLoggedIn; |         this.isLoggedIn = isLoggedIn; | ||||||
|         graphQLService = isLoggedIn ? null : GraphQLService.getInstance(); |         graphQLService = isLoggedIn ? null : GraphQLService.INSTANCE; | ||||||
|         profileService = isLoggedIn ? ProfileService.getInstance() : null; |         profileService = isLoggedIn ? ProfileService.getInstance() : null; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -49,7 +51,19 @@ public class ProfilePostFetchService implements PostFetcher.PostFetchService { | |||||||
|             } |             } | ||||||
|         }; |         }; | ||||||
|         if (isLoggedIn) profileService.fetchPosts(profileModel.getPk(), nextMaxId, cb); |         if (isLoggedIn) profileService.fetchPosts(profileModel.getPk(), nextMaxId, cb); | ||||||
|         else graphQLService.fetchProfilePosts(profileModel.getPk(), 30, nextMaxId, profileModel, cb); |         else graphQLService.fetchProfilePosts( | ||||||
|  |                 profileModel.getPk(), | ||||||
|  |                 30, | ||||||
|  |                 nextMaxId, | ||||||
|  |                 profileModel, | ||||||
|  |                 CoroutineUtilsKt.getContinuation((postsFetchResponse, throwable) -> { | ||||||
|  |                     if (throwable != null) { | ||||||
|  |                         cb.onFailure(throwable); | ||||||
|  |                         return; | ||||||
|  |                     } | ||||||
|  |                     cb.onSuccess(postsFetchResponse); | ||||||
|  |                 }, Dispatchers.getIO()) | ||||||
|  |         ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|  | |||||||
| @ -7,9 +7,11 @@ import awais.instagrabber.interfaces.FetchListener; | |||||||
| import awais.instagrabber.models.enums.PostItemType; | import awais.instagrabber.models.enums.PostItemType; | ||||||
| import awais.instagrabber.repositories.responses.Media; | import awais.instagrabber.repositories.responses.Media; | ||||||
| import awais.instagrabber.repositories.responses.PostsFetchResponse; | import awais.instagrabber.repositories.responses.PostsFetchResponse; | ||||||
|  | import awais.instagrabber.utils.CoroutineUtilsKt; | ||||||
| import awais.instagrabber.webservices.GraphQLService; | import awais.instagrabber.webservices.GraphQLService; | ||||||
| import awais.instagrabber.webservices.ProfileService; | import awais.instagrabber.webservices.ProfileService; | ||||||
| import awais.instagrabber.webservices.ServiceCallback; | import awais.instagrabber.webservices.ServiceCallback; | ||||||
|  | import kotlinx.coroutines.Dispatchers; | ||||||
| 
 | 
 | ||||||
| public class SavedPostFetchService implements PostFetcher.PostFetchService { | public class SavedPostFetchService implements PostFetcher.PostFetchService { | ||||||
|     private final ProfileService profileService; |     private final ProfileService profileService; | ||||||
| @ -27,7 +29,7 @@ public class SavedPostFetchService implements PostFetcher.PostFetchService { | |||||||
|         this.type = type; |         this.type = type; | ||||||
|         this.isLoggedIn = isLoggedIn; |         this.isLoggedIn = isLoggedIn; | ||||||
|         this.collectionId = collectionId; |         this.collectionId = collectionId; | ||||||
|         graphQLService = isLoggedIn ? null : GraphQLService.getInstance(); |         graphQLService = isLoggedIn ? null : GraphQLService.INSTANCE; | ||||||
|         profileService = isLoggedIn ? ProfileService.getInstance() : null; |         profileService = isLoggedIn ? ProfileService.getInstance() : null; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -58,7 +60,18 @@ public class SavedPostFetchService implements PostFetcher.PostFetchService { | |||||||
|                 break; |                 break; | ||||||
|             case TAGGED: |             case TAGGED: | ||||||
|                 if (isLoggedIn) profileService.fetchTagged(profileId, nextMaxId, callback); |                 if (isLoggedIn) profileService.fetchTagged(profileId, nextMaxId, callback); | ||||||
|                 else graphQLService.fetchTaggedPosts(profileId, 30, nextMaxId, callback); |                 else graphQLService.fetchTaggedPosts( | ||||||
|  |                         profileId, | ||||||
|  |                         30, | ||||||
|  |                         nextMaxId, | ||||||
|  |                         CoroutineUtilsKt.getContinuation((postsFetchResponse, throwable) -> { | ||||||
|  |                             if (throwable != null) { | ||||||
|  |                                 callback.onFailure(throwable); | ||||||
|  |                                 return; | ||||||
|  |                             } | ||||||
|  |                             callback.onSuccess(postsFetchResponse); | ||||||
|  |                         }, Dispatchers.getIO()) | ||||||
|  |                 ); | ||||||
|                 break; |                 break; | ||||||
|             case COLLECTION: |             case COLLECTION: | ||||||
|             case SAVED: |             case SAVED: | ||||||
|  | |||||||
| @ -63,8 +63,10 @@ import awais.instagrabber.repositories.responses.Hashtag; | |||||||
| import awais.instagrabber.repositories.responses.Location; | import awais.instagrabber.repositories.responses.Location; | ||||||
| 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.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.DownloadUtils; | import awais.instagrabber.utils.DownloadUtils; | ||||||
| import awais.instagrabber.utils.TextUtils; | import awais.instagrabber.utils.TextUtils; | ||||||
| import awais.instagrabber.utils.Utils; | import awais.instagrabber.utils.Utils; | ||||||
| @ -72,6 +74,7 @@ import awais.instagrabber.webservices.GraphQLService; | |||||||
| import awais.instagrabber.webservices.ServiceCallback; | import awais.instagrabber.webservices.ServiceCallback; | ||||||
| import awais.instagrabber.webservices.StoriesService; | import awais.instagrabber.webservices.StoriesService; | ||||||
| import awais.instagrabber.webservices.TagsService; | import awais.instagrabber.webservices.TagsService; | ||||||
|  | import kotlinx.coroutines.Dispatchers; | ||||||
| 
 | 
 | ||||||
| import static androidx.core.content.PermissionChecker.checkSelfPermission; | import static androidx.core.content.PermissionChecker.checkSelfPermission; | ||||||
| import static awais.instagrabber.utils.DownloadUtils.WRITE_PERMISSION; | import static awais.instagrabber.utils.DownloadUtils.WRITE_PERMISSION; | ||||||
| @ -218,20 +221,15 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe | |||||||
|             if (TextUtils.isEmpty(user.getUsername())) { |             if (TextUtils.isEmpty(user.getUsername())) { | ||||||
|                 // this only happens for anons |                 // this only happens for anons | ||||||
|                 opening = true; |                 opening = true; | ||||||
|                 graphQLService.fetchPost(feedModel.getCode(), new ServiceCallback<Media>() { |                 graphQLService.fetchPost(feedModel.getCode(), CoroutineUtilsKt.getContinuation((media, throwable) -> { | ||||||
|                     @Override |                     opening = false; | ||||||
|                     public void onSuccess(final Media newFeedModel) { |                     if (throwable != null) { | ||||||
|                         opening = false; |                         Log.e(TAG, "Error", throwable); | ||||||
|                         if (newFeedModel == null) return; |                         return; | ||||||
|                         openPostDialog(newFeedModel, profilePicView, mainPostImage, position); |  | ||||||
|                     } |                     } | ||||||
| 
 |                     if (media == null) return; | ||||||
|                     @Override |                     AppExecutors.INSTANCE.getMainThread().execute(() -> openPostDialog(media, profilePicView, mainPostImage, position)); | ||||||
|                     public void onFailure(final Throwable t) { |                 }, Dispatchers.getIO())); | ||||||
|                         opening = false; |  | ||||||
|                         Log.e(TAG, "Error", t); |  | ||||||
|                     } |  | ||||||
|                 }); |  | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|             opening = true; |             opening = true; | ||||||
| @ -304,7 +302,7 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe | |||||||
|         isLoggedIn = !TextUtils.isEmpty(cookie) && CookieUtils.getUserIdFromCookie(cookie) > 0; |         isLoggedIn = !TextUtils.isEmpty(cookie) && CookieUtils.getUserIdFromCookie(cookie) > 0; | ||||||
|         tagsService = isLoggedIn ? TagsService.getInstance() : null; |         tagsService = isLoggedIn ? TagsService.getInstance() : null; | ||||||
|         storiesService = isLoggedIn ? StoriesService.getInstance(null, 0L, null) : null; |         storiesService = isLoggedIn ? StoriesService.getInstance(null, 0L, null) : null; | ||||||
|         graphQLService = isLoggedIn ? null : GraphQLService.getInstance(); |         graphQLService = isLoggedIn ? null : GraphQLService.INSTANCE; | ||||||
|         setHasOptionsMenu(true); |         setHasOptionsMenu(true); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -385,7 +383,13 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe | |||||||
|     private void fetchHashtagModel() { |     private void fetchHashtagModel() { | ||||||
|         binding.swipeRefreshLayout.setRefreshing(true); |         binding.swipeRefreshLayout.setRefreshing(true); | ||||||
|         if (isLoggedIn) tagsService.fetch(hashtag, cb); |         if (isLoggedIn) tagsService.fetch(hashtag, cb); | ||||||
|         else graphQLService.fetchTag(hashtag, cb); |         else graphQLService.fetchTag(hashtag, CoroutineUtilsKt.getContinuation((hashtag1, throwable) -> { | ||||||
|  |             if (throwable != null) { | ||||||
|  |                 cb.onFailure(throwable); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             AppExecutors.INSTANCE.getMainThread().execute(() -> cb.onSuccess(hashtag1)); | ||||||
|  |         }, Dispatchers.getIO())); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void setupPosts() { |     private void setupPosts() { | ||||||
|  | |||||||
| @ -113,7 +113,7 @@ public final class LikesViewerFragment extends BottomSheetDialogFragment impleme | |||||||
|         final String csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie); |         final String csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie); | ||||||
|         if (csrfToken == null) return; |         if (csrfToken == null) return; | ||||||
|         mediaService = isLoggedIn ? MediaService.INSTANCE : null; |         mediaService = isLoggedIn ? MediaService.INSTANCE : null; | ||||||
|         graphQLService = isLoggedIn ? null : GraphQLService.getInstance(); |         graphQLService = isLoggedIn ? null : GraphQLService.INSTANCE; | ||||||
|         // setHasOptionsMenu(true); |         // setHasOptionsMenu(true); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -135,7 +135,17 @@ public final class LikesViewerFragment extends BottomSheetDialogFragment impleme | |||||||
|     public void onRefresh() { |     public void onRefresh() { | ||||||
|         if (isComment && !isLoggedIn) { |         if (isComment && !isLoggedIn) { | ||||||
|             lazyLoader.resetState(); |             lazyLoader.resetState(); | ||||||
|             graphQLService.fetchCommentLikers(postId, null, anonCb); |             graphQLService.fetchCommentLikers( | ||||||
|  |                     postId, | ||||||
|  |                     null, | ||||||
|  |                     CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> { | ||||||
|  |                         if (throwable != null) { | ||||||
|  |                             anonCb.onFailure(throwable); | ||||||
|  |                             return; | ||||||
|  |                         } | ||||||
|  |                         anonCb.onSuccess(response); | ||||||
|  |                     }), Dispatchers.getIO()) | ||||||
|  |             ); | ||||||
|         } else { |         } else { | ||||||
|             mediaService.fetchLikes( |             mediaService.fetchLikes( | ||||||
|                     postId, |                     postId, | ||||||
| @ -164,8 +174,19 @@ public final class LikesViewerFragment extends BottomSheetDialogFragment impleme | |||||||
|             binding.rvLikes.setLayoutManager(layoutManager); |             binding.rvLikes.setLayoutManager(layoutManager); | ||||||
|             binding.rvLikes.addItemDecoration(new DividerItemDecoration(getContext(), DividerItemDecoration.HORIZONTAL)); |             binding.rvLikes.addItemDecoration(new DividerItemDecoration(getContext(), DividerItemDecoration.HORIZONTAL)); | ||||||
|             lazyLoader = new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> { |             lazyLoader = new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> { | ||||||
|                 if (!TextUtils.isEmpty(endCursor)) |                 if (!TextUtils.isEmpty(endCursor)) { | ||||||
|                     graphQLService.fetchCommentLikers(postId, endCursor, anonCb); |                     graphQLService.fetchCommentLikers( | ||||||
|  |                             postId, | ||||||
|  |                             endCursor, | ||||||
|  |                             CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> { | ||||||
|  |                                 if (throwable != null) { | ||||||
|  |                                     anonCb.onFailure(throwable); | ||||||
|  |                                     return; | ||||||
|  |                                 } | ||||||
|  |                                 anonCb.onSuccess(response); | ||||||
|  |                             }), Dispatchers.getIO()) | ||||||
|  |                     ); | ||||||
|  |                 } | ||||||
|                 endCursor = null; |                 endCursor = null; | ||||||
|             }); |             }); | ||||||
|             binding.rvLikes.addOnScrollListener(lazyLoader); |             binding.rvLikes.addOnScrollListener(lazyLoader); | ||||||
|  | |||||||
| @ -59,8 +59,10 @@ import awais.instagrabber.repositories.requests.StoryViewerOptions; | |||||||
| import awais.instagrabber.repositories.responses.Location; | import awais.instagrabber.repositories.responses.Location; | ||||||
| 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.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.DownloadUtils; | import awais.instagrabber.utils.DownloadUtils; | ||||||
| import awais.instagrabber.utils.TextUtils; | import awais.instagrabber.utils.TextUtils; | ||||||
| import awais.instagrabber.utils.Utils; | import awais.instagrabber.utils.Utils; | ||||||
| @ -208,20 +210,18 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR | |||||||
|             if (user == null) return; |             if (user == null) return; | ||||||
|             if (TextUtils.isEmpty(user.getUsername())) { |             if (TextUtils.isEmpty(user.getUsername())) { | ||||||
|                 opening = true; |                 opening = true; | ||||||
|                 graphQLService.fetchPost(feedModel.getCode(), new ServiceCallback<Media>() { |                 graphQLService.fetchPost( | ||||||
|                     @Override |                         feedModel.getCode(), | ||||||
|                     public void onSuccess(final Media newFeedModel) { |                         CoroutineUtilsKt.getContinuation((media, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> { | ||||||
|                         opening = false; |                             opening = false; | ||||||
|                         if (newFeedModel == null) return; |                             if (throwable != null) { | ||||||
|                         openPostDialog(newFeedModel, profilePicView, mainPostImage, position); |                                 Log.e(TAG, "Error", throwable); | ||||||
|                     } |                                 return; | ||||||
| 
 |                             } | ||||||
|                     @Override |                             if (media == null) return; | ||||||
|                     public void onFailure(final Throwable t) { |                             openPostDialog(media, profilePicView, mainPostImage, position); | ||||||
|                         opening = false; |                         })) | ||||||
|                         Log.e(TAG, "Error", t); |                 ); | ||||||
|                     } |  | ||||||
|                 }); |  | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|             opening = true; |             opening = true; | ||||||
| @ -294,7 +294,7 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR | |||||||
|         isLoggedIn = !TextUtils.isEmpty(cookie) && CookieUtils.getUserIdFromCookie(cookie) > 0; |         isLoggedIn = !TextUtils.isEmpty(cookie) && CookieUtils.getUserIdFromCookie(cookie) > 0; | ||||||
|         locationService = isLoggedIn ? LocationService.getInstance() : null; |         locationService = isLoggedIn ? LocationService.getInstance() : null; | ||||||
|         storiesService = StoriesService.getInstance(null, 0L, null); |         storiesService = StoriesService.getInstance(null, 0L, null); | ||||||
|         graphQLService = isLoggedIn ? null : GraphQLService.getInstance(); |         graphQLService = isLoggedIn ? null : GraphQLService.INSTANCE; | ||||||
|         setHasOptionsMenu(true); |         setHasOptionsMenu(true); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -402,7 +402,16 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR | |||||||
|     private void fetchLocationModel() { |     private void fetchLocationModel() { | ||||||
|         binding.swipeRefreshLayout.setRefreshing(true); |         binding.swipeRefreshLayout.setRefreshing(true); | ||||||
|         if (isLoggedIn) locationService.fetch(locationId, cb); |         if (isLoggedIn) locationService.fetch(locationId, cb); | ||||||
|         else graphQLService.fetchLocation(locationId, cb); |         else graphQLService.fetchLocation( | ||||||
|  |                 locationId, | ||||||
|  |                 CoroutineUtilsKt.getContinuation((location, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> { | ||||||
|  |                     if (throwable != null) { | ||||||
|  |                         cb.onFailure(throwable); | ||||||
|  |                         return; | ||||||
|  |                     } | ||||||
|  |                     cb.onSuccess(location); | ||||||
|  |                 })) | ||||||
|  |         ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void setupLocationDetails() { |     private void setupLocationDetails() { | ||||||
|  | |||||||
| @ -339,7 +339,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe | |||||||
|         storiesService = isLoggedIn ? StoriesService.getInstance(null, 0L, null) : null; |         storiesService = isLoggedIn ? StoriesService.getInstance(null, 0L, null) : null; | ||||||
|         mediaService = isLoggedIn ? MediaService.INSTANCE : null; |         mediaService = isLoggedIn ? MediaService.INSTANCE : null; | ||||||
|         userService = isLoggedIn ? UserService.INSTANCE : null; |         userService = isLoggedIn ? UserService.INSTANCE : null; | ||||||
|         graphQLService = isLoggedIn ? null : GraphQLService.getInstance(); |         graphQLService = isLoggedIn ? null : GraphQLService.INSTANCE; | ||||||
|         final Context context = getContext(); |         final Context context = getContext(); | ||||||
|         if (context == null) return; |         if (context == null) return; | ||||||
|         accountRepository = AccountRepository.getInstance(AccountDataSource.getInstance(context)); |         accountRepository = AccountRepository.getInstance(AccountDataSource.getInstance(context)); | ||||||
| @ -618,25 +618,19 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe | |||||||
|             ); |             ); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         graphQLService.fetchUser(usernameTemp, new ServiceCallback<User>() { |         graphQLService.fetchUser( | ||||||
|             @Override |                 usernameTemp, | ||||||
|             public void onSuccess(final User user) { |                 CoroutineUtilsKt.getContinuation((user, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> { | ||||||
|                 profileModel = user; |                     if (throwable != null) { | ||||||
|                 setProfileDetails(); |                         Log.e(TAG, "Error fetching profile", throwable); | ||||||
|             } |                         final Context context = getContext(); | ||||||
| 
 |                         if (context == null) return; | ||||||
|             @Override |                         Toast.makeText(context, throwable.getMessage(), Toast.LENGTH_SHORT).show(); | ||||||
|             public void onFailure(final Throwable t) { |                     } | ||||||
|                 Log.e(TAG, "Error fetching profile", t); |                     profileModel = user; | ||||||
|                 final Context context = getContext(); |                     setProfileDetails(); | ||||||
|                 try { |                 })) | ||||||
|                     if (t == null) |         ); | ||||||
|                         Toast.makeText(context, R.string.error_loading_profile, Toast.LENGTH_LONG).show(); |  | ||||||
|                     else Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show(); |  | ||||||
|                 } catch (final Throwable ignored) { |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void setProfileDetails() { |     private void setProfileDetails() { | ||||||
|  | |||||||
| @ -1,25 +1,22 @@ | |||||||
| package awais.instagrabber.repositories; | package awais.instagrabber.repositories | ||||||
| 
 | 
 | ||||||
| import java.util.Map; | import retrofit2.http.GET | ||||||
|  | import retrofit2.http.Path | ||||||
|  | import retrofit2.http.QueryMap | ||||||
| 
 | 
 | ||||||
| import retrofit2.Call; | interface GraphQLRepository { | ||||||
| import retrofit2.http.GET; |  | ||||||
| import retrofit2.http.Path; |  | ||||||
| import retrofit2.http.QueryMap; |  | ||||||
| 
 |  | ||||||
| public interface GraphQLRepository { |  | ||||||
|     @GET("/graphql/query/") |     @GET("/graphql/query/") | ||||||
|     Call<String> fetch(@QueryMap(encoded = true) Map<String, String> queryParams); |     suspend fun fetch(@QueryMap(encoded = true) queryParams: Map<String, String>): String | ||||||
| 
 | 
 | ||||||
|     @GET("/{username}/?__a=1") |     @GET("/{username}/?__a=1") | ||||||
|     Call<String> getUser(@Path("username") String username); |     suspend fun getUser(@Path("username") username: String): String | ||||||
| 
 | 
 | ||||||
|     @GET("/p/{shortcode}/?__a=1") |     @GET("/p/{shortcode}/?__a=1") | ||||||
|     Call<String> getPost(@Path("shortcode") String shortcode); |     suspend fun getPost(@Path("shortcode") shortcode: String): String | ||||||
| 
 | 
 | ||||||
|     @GET("/explore/tags/{tag}/?__a=1") |     @GET("/explore/tags/{tag}/?__a=1") | ||||||
|     Call<String> getTag(@Path("tag") String tag); |     suspend fun getTag(@Path("tag") tag: String): String | ||||||
| 
 | 
 | ||||||
|     @GET("/explore/locations/{locationId}/?__a=1") |     @GET("/explore/locations/{locationId}/?__a=1") | ||||||
|     Call<String> getLocation(@Path("locationId") long locationId); |     suspend fun getLocation(@Path("locationId") locationId: Long): String | ||||||
| } | } | ||||||
| @ -30,13 +30,13 @@ import awais.instagrabber.repositories.responses.CommentsFetchResponse; | |||||||
| import awais.instagrabber.repositories.responses.User; | import awais.instagrabber.repositories.responses.User; | ||||||
| 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.Utils; | import awais.instagrabber.utils.Utils; | ||||||
| import awais.instagrabber.webservices.CommentService; | import awais.instagrabber.webservices.CommentService; | ||||||
| import awais.instagrabber.webservices.GraphQLService; | import awais.instagrabber.webservices.GraphQLService; | ||||||
| import awais.instagrabber.webservices.ServiceCallback; | import awais.instagrabber.webservices.ServiceCallback; | ||||||
| import retrofit2.Call; | import kotlin.coroutines.Continuation; | ||||||
| import retrofit2.Callback; | import kotlinx.coroutines.Dispatchers; | ||||||
| import retrofit2.Response; |  | ||||||
| 
 | 
 | ||||||
| import static awais.instagrabber.utils.Utils.settingsHelper; | import static awais.instagrabber.utils.Utils.settingsHelper; | ||||||
| 
 | 
 | ||||||
| @ -113,7 +113,7 @@ public class CommentsViewerViewModel extends ViewModel { | |||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     public CommentsViewerViewModel() { |     public CommentsViewerViewModel() { | ||||||
|         graphQLService = GraphQLService.getInstance(); |         graphQLService = GraphQLService.INSTANCE; | ||||||
|         final String cookie = settingsHelper.getString(Constants.COOKIE); |         final String cookie = settingsHelper.getString(Constants.COOKIE); | ||||||
|         final String deviceUuid = Utils.settingsHelper.getString(Constants.DEVICE_UUID); |         final String deviceUuid = Utils.settingsHelper.getString(Constants.DEVICE_UUID); | ||||||
|         final String csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie); |         final String csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie); | ||||||
| @ -165,8 +165,12 @@ public class CommentsViewerViewModel extends ViewModel { | |||||||
|             commentService.fetchComments(postId, rootCursor, ccb); |             commentService.fetchComments(postId, rootCursor, ccb); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         final Call<String> request = graphQLService.fetchComments(shortCode, true, rootCursor); |         graphQLService.fetchComments( | ||||||
|         enqueueRequest(request, true, shortCode, ccb); |                 shortCode, | ||||||
|  |                 true, | ||||||
|  |                 rootCursor, | ||||||
|  |                 enqueueRequest(true, shortCode, ccb) | ||||||
|  |         ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public void fetchReplies() { |     public void fetchReplies() { | ||||||
| @ -190,54 +194,49 @@ public class CommentsViewerViewModel extends ViewModel { | |||||||
|             commentService.fetchChildComments(postId, commentId, repliesCursor, rcb); |             commentService.fetchChildComments(postId, commentId, repliesCursor, rcb); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         final Call<String> request = graphQLService.fetchComments(commentId, false, repliesCursor); |         graphQLService.fetchComments(commentId, false, repliesCursor, enqueueRequest(false, commentId, rcb)); | ||||||
|         enqueueRequest(request, false, commentId, rcb); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void enqueueRequest(@NonNull final Call<String> request, |     private Continuation<String> enqueueRequest(final boolean root, | ||||||
|                                 final boolean root, |                                                 final String shortCodeOrCommentId, | ||||||
|                                 final String shortCodeOrCommentId, |                                                 @SuppressWarnings("rawtypes") final ServiceCallback callback) { | ||||||
|                                 final ServiceCallback callback) { |         return CoroutineUtilsKt.getContinuation((response, throwable) -> { | ||||||
|         request.enqueue(new Callback<String>() { |             if (throwable != null) { | ||||||
|             @Override |                 callback.onFailure(throwable); | ||||||
|             public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { |                 return; | ||||||
|                 final String rawBody = response.body(); |  | ||||||
|                 if (rawBody == null) { |  | ||||||
|                     Log.e(TAG, "Error occurred while fetching gql comments of " + shortCodeOrCommentId); |  | ||||||
|                     callback.onSuccess(null); |  | ||||||
|                     return; |  | ||||||
|                 } |  | ||||||
|                 try { |  | ||||||
|                     final JSONObject body = root ? new JSONObject(rawBody).getJSONObject("data") |  | ||||||
|                                                                           .getJSONObject("shortcode_media") |  | ||||||
|                                                                           .getJSONObject("edge_media_to_parent_comment") |  | ||||||
|                                                  : new JSONObject(rawBody).getJSONObject("data") |  | ||||||
|                                                                           .getJSONObject("comment") |  | ||||||
|                                                                           .getJSONObject("edge_threaded_comments"); |  | ||||||
|                     final int count = body.optInt("count"); |  | ||||||
|                     final JSONObject pageInfo = body.getJSONObject("page_info"); |  | ||||||
|                     final boolean hasNextPage = pageInfo.getBoolean("has_next_page"); |  | ||||||
|                     final String endCursor = pageInfo.isNull("end_cursor") || !hasNextPage ? null : pageInfo.optString("end_cursor"); |  | ||||||
|                     final JSONArray commentsJsonArray = body.getJSONArray("edges"); |  | ||||||
|                     final ImmutableList.Builder<Comment> builder = ImmutableList.builder(); |  | ||||||
|                     for (int i = 0; i < commentsJsonArray.length(); i++) { |  | ||||||
|                         final Comment commentModel = getComment(commentsJsonArray.getJSONObject(i).getJSONObject("node"), root); |  | ||||||
|                         builder.add(commentModel); |  | ||||||
|                     } |  | ||||||
|                     callback.onSuccess(root ? |  | ||||||
|                                        new CommentsFetchResponse(count, endCursor, builder.build()) : |  | ||||||
|                                        new ChildCommentsFetchResponse(count, endCursor, builder.build())); |  | ||||||
|                 } catch (Exception e) { |  | ||||||
|                     Log.e(TAG, "onResponse", e); |  | ||||||
|                     callback.onFailure(e); |  | ||||||
|                 } |  | ||||||
|             } |             } | ||||||
| 
 |             if (response == null) { | ||||||
|             @Override |                 Log.e(TAG, "Error occurred while fetching gql comments of " + shortCodeOrCommentId); | ||||||
|             public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) { |                 //noinspection unchecked | ||||||
|                 callback.onFailure(t); |                 callback.onSuccess(null); | ||||||
|  |                 return; | ||||||
|             } |             } | ||||||
|         }); |             try { | ||||||
|  |                 final JSONObject body = root ? new JSONObject(response).getJSONObject("data") | ||||||
|  |                                                                        .getJSONObject("shortcode_media") | ||||||
|  |                                                                        .getJSONObject("edge_media_to_parent_comment") | ||||||
|  |                                              : new JSONObject(response).getJSONObject("data") | ||||||
|  |                                                                        .getJSONObject("comment") | ||||||
|  |                                                                        .getJSONObject("edge_threaded_comments"); | ||||||
|  |                 final int count = body.optInt("count"); | ||||||
|  |                 final JSONObject pageInfo = body.getJSONObject("page_info"); | ||||||
|  |                 final boolean hasNextPage = pageInfo.getBoolean("has_next_page"); | ||||||
|  |                 final String endCursor = pageInfo.isNull("end_cursor") || !hasNextPage ? null : pageInfo.optString("end_cursor"); | ||||||
|  |                 final JSONArray commentsJsonArray = body.getJSONArray("edges"); | ||||||
|  |                 final ImmutableList.Builder<Comment> builder = ImmutableList.builder(); | ||||||
|  |                 for (int i = 0; i < commentsJsonArray.length(); i++) { | ||||||
|  |                     final Comment commentModel = getComment(commentsJsonArray.getJSONObject(i).getJSONObject("node"), root); | ||||||
|  |                     builder.add(commentModel); | ||||||
|  |                 } | ||||||
|  |                 final Object result = root ? new CommentsFetchResponse(count, endCursor, builder.build()) | ||||||
|  |                                            : new ChildCommentsFetchResponse(count, endCursor, builder.build()); | ||||||
|  |                 //noinspection unchecked | ||||||
|  |                 callback.onSuccess(result); | ||||||
|  |             } catch (Exception e) { | ||||||
|  |                 Log.e(TAG, "onResponse", e); | ||||||
|  |                 callback.onFailure(e); | ||||||
|  |             } | ||||||
|  |         }, Dispatchers.getIO()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NonNull | ||||||
|  | |||||||
| @ -1,483 +1,266 @@ | |||||||
| package awais.instagrabber.webservices; | package awais.instagrabber.webservices | ||||||
| 
 | 
 | ||||||
| import android.util.Log; | import android.util.Log | ||||||
|  | import awais.instagrabber.models.enums.FollowingType | ||||||
|  | import awais.instagrabber.repositories.GraphQLRepository | ||||||
|  | import awais.instagrabber.repositories.responses.* | ||||||
|  | import awais.instagrabber.utils.Constants | ||||||
|  | import awais.instagrabber.utils.ResponseBodyUtils | ||||||
|  | import awais.instagrabber.utils.extensions.TAG | ||||||
|  | import awais.instagrabber.webservices.RetrofitFactory.retrofitWeb | ||||||
|  | import org.json.JSONException | ||||||
|  | import org.json.JSONObject | ||||||
|  | import java.util.* | ||||||
| 
 | 
 | ||||||
| import androidx.annotation.NonNull; | object GraphQLService : BaseService() { | ||||||
| 
 |     private val repository: GraphQLRepository = retrofitWeb.create(GraphQLRepository::class.java) | ||||||
| import com.google.common.collect.ImmutableMap; |  | ||||||
| 
 |  | ||||||
| import org.json.JSONArray; |  | ||||||
| import org.json.JSONException; |  | ||||||
| import org.json.JSONObject; |  | ||||||
| 
 |  | ||||||
| import java.util.ArrayList; |  | ||||||
| import java.util.Collections; |  | ||||||
| import java.util.HashMap; |  | ||||||
| import java.util.List; |  | ||||||
| import java.util.Map; |  | ||||||
| 
 |  | ||||||
| import awais.instagrabber.models.enums.FollowingType; |  | ||||||
| import awais.instagrabber.repositories.GraphQLRepository; |  | ||||||
| import awais.instagrabber.repositories.responses.FriendshipStatus; |  | ||||||
| import awais.instagrabber.repositories.responses.GraphQLUserListFetchResponse; |  | ||||||
| import awais.instagrabber.repositories.responses.Hashtag; |  | ||||||
| import awais.instagrabber.repositories.responses.Location; |  | ||||||
| import awais.instagrabber.repositories.responses.Media; |  | ||||||
| import awais.instagrabber.repositories.responses.PostsFetchResponse; |  | ||||||
| import awais.instagrabber.repositories.responses.User; |  | ||||||
| import awais.instagrabber.utils.Constants; |  | ||||||
| import awais.instagrabber.utils.ResponseBodyUtils; |  | ||||||
| import awais.instagrabber.utils.TextUtils; |  | ||||||
| import retrofit2.Call; |  | ||||||
| import retrofit2.Callback; |  | ||||||
| import retrofit2.Response; |  | ||||||
| 
 |  | ||||||
| public class GraphQLService extends BaseService { |  | ||||||
|     private static final String TAG = "GraphQLService"; |  | ||||||
| 
 |  | ||||||
|     private final GraphQLRepository repository; |  | ||||||
| 
 |  | ||||||
|     private static GraphQLService instance; |  | ||||||
| 
 |  | ||||||
|     private GraphQLService() { |  | ||||||
|         repository = RetrofitFactory.INSTANCE |  | ||||||
|                 .getRetrofitWeb() |  | ||||||
|                 .create(GraphQLRepository.class); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public static GraphQLService getInstance() { |  | ||||||
|         if (instance == null) { |  | ||||||
|             instance = new GraphQLService(); |  | ||||||
|         } |  | ||||||
|         return instance; |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     // TODO convert string response to a response class |     // TODO convert string response to a response class | ||||||
|     private void fetch(final String queryHash, |     private suspend fun fetch( | ||||||
|                        final String variables, |         queryHash: String, | ||||||
|                        final String arg1, |         variables: String, | ||||||
|                        final String arg2, |         arg1: String, | ||||||
|                        final User backup, |         arg2: String, | ||||||
|                        final ServiceCallback<PostsFetchResponse> callback) { |         backup: User?, | ||||||
|         final Map<String, String> queryMap = new HashMap<>(); |     ): PostsFetchResponse { | ||||||
|         queryMap.put("query_hash", queryHash); |         val queryMap = mapOf( | ||||||
|         queryMap.put("variables", variables); |             "query_hash" to queryHash, | ||||||
|         final Call<String> request = repository.fetch(queryMap); |             "variables" to variables, | ||||||
|         request.enqueue(new Callback<String>() { |         ) | ||||||
|             @Override |         val response = repository.fetch(queryMap) | ||||||
|             public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { |         return parsePostResponse(response, arg1, arg2, backup) | ||||||
|                 try { |  | ||||||
|                     // Log.d(TAG, "onResponse: body: " + response.body()); |  | ||||||
|                     final PostsFetchResponse postsFetchResponse = parsePostResponse(response, arg1, arg2, backup); |  | ||||||
|                     if (callback != null) { |  | ||||||
|                         callback.onSuccess(postsFetchResponse); |  | ||||||
|                     } |  | ||||||
|                 } catch (JSONException e) { |  | ||||||
|                     Log.e(TAG, "onResponse", e); |  | ||||||
|                     if (callback != null) { |  | ||||||
|                         callback.onFailure(e); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             @Override |  | ||||||
|             public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) { |  | ||||||
|                 if (callback != null) { |  | ||||||
|                     callback.onFailure(t); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public void fetchLocationPosts(final long locationId, |     suspend fun fetchLocationPosts( | ||||||
|                                    final String maxId, |         locationId: Long, | ||||||
|                                    final ServiceCallback<PostsFetchResponse> callback) { |         maxId: String?, | ||||||
|         fetch("36bd0f2bf5911908de389b8ceaa3be6d", |     ): PostsFetchResponse = fetch( | ||||||
|               "{\"id\":\"" + locationId + "\"," + |         "36bd0f2bf5911908de389b8ceaa3be6d", | ||||||
|                       "\"first\":25," + |         "{\"id\":\"" + locationId + "\"," + "\"first\":25," + "\"after\":\"" + (maxId ?: "") + "\"}", | ||||||
|                       "\"after\":\"" + (maxId == null ? "" : maxId) + "\"}", |         Constants.EXTRAS_LOCATION, | ||||||
|               Constants.EXTRAS_LOCATION, |         "edge_location_to_media", | ||||||
|               "edge_location_to_media", |         null | ||||||
|               null, |     ) | ||||||
|               callback); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     public void fetchHashtagPosts(@NonNull final String tag, |     suspend fun fetchHashtagPosts( | ||||||
|                                   final String maxId, |         tag: String, | ||||||
|                                   final ServiceCallback<PostsFetchResponse> callback) { |         maxId: String?, | ||||||
|         fetch("9b498c08113f1e09617a1703c22b2f32", |     ): PostsFetchResponse = fetch( | ||||||
|               "{\"tag_name\":\"" + tag + "\"," + |         "9b498c08113f1e09617a1703c22b2f32", | ||||||
|                       "\"first\":25," + |         "{\"tag_name\":\"" + tag + "\"," + "\"first\":25," + "\"after\":\"" + (maxId ?: "") + "\"}", | ||||||
|                       "\"after\":\"" + (maxId == null ? "" : maxId) + "\"}", |         Constants.EXTRAS_HASHTAG, | ||||||
|               Constants.EXTRAS_HASHTAG, |         "edge_hashtag_to_media", | ||||||
|               "edge_hashtag_to_media", |         null, | ||||||
|               null, |     ) | ||||||
|               callback); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     public void fetchProfilePosts(final long profileId, |     suspend fun fetchProfilePosts( | ||||||
|                                   final int postsPerPage, |         profileId: Long, | ||||||
|                                   final String maxId, |         postsPerPage: Int, | ||||||
|                                   final User backup, |         maxId: String?, | ||||||
|                                   final ServiceCallback<PostsFetchResponse> callback) { |         backup: User?, | ||||||
|         fetch("02e14f6a7812a876f7d133c9555b1151", |     ): PostsFetchResponse = fetch( | ||||||
|               "{\"id\":\"" + profileId + "\"," + |         "02e14f6a7812a876f7d133c9555b1151", | ||||||
|                       "\"first\":" + postsPerPage + "," + |         "{\"id\":\"" + profileId + "\"," + "\"first\":" + postsPerPage + "," + "\"after\":\"" + (maxId ?: "") + "\"}", | ||||||
|                       "\"after\":\"" + (maxId == null ? "" : maxId) + "\"}", |         Constants.EXTRAS_USER, | ||||||
|               Constants.EXTRAS_USER, |         "edge_owner_to_timeline_media", | ||||||
|               "edge_owner_to_timeline_media", |         backup, | ||||||
|               backup, |     ) | ||||||
|               callback); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     public void fetchTaggedPosts(final long profileId, |     suspend fun fetchTaggedPosts( | ||||||
|                                  final int postsPerPage, |         profileId: Long, | ||||||
|                                  final String maxId, |         postsPerPage: Int, | ||||||
|                                  final ServiceCallback<PostsFetchResponse> callback) { |         maxId: String?, | ||||||
|         fetch("31fe64d9463cbbe58319dced405c6206", |     ): PostsFetchResponse = fetch( | ||||||
|               "{\"id\":\"" + profileId + "\"," + |         "31fe64d9463cbbe58319dced405c6206", | ||||||
|                       "\"first\":" + postsPerPage + "," + |         "{\"id\":\"" + profileId + "\"," + "\"first\":" + postsPerPage + "," + "\"after\":\"" + (maxId ?: "") + "\"}", | ||||||
|                       "\"after\":\"" + (maxId == null ? "" : maxId) + "\"}", |         Constants.EXTRAS_USER, | ||||||
|               Constants.EXTRAS_USER, |         "edge_user_to_photos_of_you", | ||||||
|               "edge_user_to_photos_of_you", |         null, | ||||||
|               null, |     ) | ||||||
|               callback); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @Throws(JSONException::class) | ||||||
|     private PostsFetchResponse parsePostResponse(@NonNull final Response<String> response, |     private fun parsePostResponse( | ||||||
|                                                  @NonNull final String arg1, |         response: String, | ||||||
|                                                  @NonNull final String arg2, |         arg1: String, | ||||||
|                                                  final User backup) |         arg2: String, | ||||||
|             throws JSONException { |         backup: User?, | ||||||
|         if (TextUtils.isEmpty(response.body())) { |     ): PostsFetchResponse { | ||||||
|             Log.e(TAG, "parseResponse: feed response body is empty with status code: " + response.code()); |         if (response.isBlank()) { | ||||||
|             return new PostsFetchResponse(Collections.emptyList(), false, null); |             Log.e(TAG, "parseResponse: feed response body is empty") | ||||||
|  |             return PostsFetchResponse(emptyList(), false, null) | ||||||
|         } |         } | ||||||
|         return parseResponseBody(response.body(), arg1, arg2, backup); |         return parseResponseBody(response, arg1, arg2, backup) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @Throws(JSONException::class) | ||||||
|     private PostsFetchResponse parseResponseBody(@NonNull final String body, |     private fun parseResponseBody( | ||||||
|                                                  @NonNull final String arg1, |         body: String, | ||||||
|                                                  @NonNull final String arg2, |         arg1: String, | ||||||
|                                                  final User backup) |         arg2: String, | ||||||
|             throws JSONException { |         backup: User?, | ||||||
|         final List<Media> items = new ArrayList<>(); |     ): PostsFetchResponse { | ||||||
|         final JSONObject timelineFeed = new JSONObject(body) |         val items: MutableList<Media> = ArrayList() | ||||||
|                 .getJSONObject("data") |         val timelineFeed = JSONObject(body) | ||||||
|                 .getJSONObject(arg1) |             .getJSONObject("data") | ||||||
|                 .getJSONObject(arg2); |             .getJSONObject(arg1) | ||||||
|         final String endCursor; |             .getJSONObject(arg2) | ||||||
|         final boolean hasNextPage; |         val endCursor: String? | ||||||
| 
 |         val hasNextPage: Boolean | ||||||
|         final JSONObject pageInfo = timelineFeed.getJSONObject("page_info"); |         val pageInfo = timelineFeed.getJSONObject("page_info") | ||||||
|         if (pageInfo.has("has_next_page")) { |         if (pageInfo.has("has_next_page")) { | ||||||
|             hasNextPage = pageInfo.getBoolean("has_next_page"); |             hasNextPage = pageInfo.getBoolean("has_next_page") | ||||||
|             endCursor = hasNextPage ? pageInfo.getString("end_cursor") : null; |             endCursor = if (hasNextPage) pageInfo.getString("end_cursor") else null | ||||||
|         } else { |         } else { | ||||||
|             hasNextPage = false; |             hasNextPage = false | ||||||
|             endCursor = null; |             endCursor = null | ||||||
|         } |         } | ||||||
| 
 |         val feedItems = timelineFeed.getJSONArray("edges") | ||||||
|         final JSONArray feedItems = timelineFeed.getJSONArray("edges"); |         for (i in 0 until feedItems.length()) { | ||||||
| 
 |             val itemJson = feedItems.optJSONObject(i) ?: continue | ||||||
|         for (int i = 0; i < feedItems.length(); ++i) { |             val media = ResponseBodyUtils.parseGraphQLItem(itemJson, backup) | ||||||
|             final JSONObject itemJson = feedItems.optJSONObject(i); |  | ||||||
|             if (itemJson == null) { |  | ||||||
|                 continue; |  | ||||||
|             } |  | ||||||
|             final Media media = ResponseBodyUtils.parseGraphQLItem(itemJson, backup); |  | ||||||
|             if (media != null) { |             if (media != null) { | ||||||
|                 items.add(media); |                 items.add(media) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         return new PostsFetchResponse(items, hasNextPage, endCursor); |         return PostsFetchResponse(items, hasNextPage, endCursor) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // TODO convert string response to a response class |     // TODO convert string response to a response class | ||||||
|     public void fetchCommentLikers(final String commentId, |     suspend fun fetchCommentLikers( | ||||||
|                                    final String endCursor, |         commentId: String, | ||||||
|                                    final ServiceCallback<GraphQLUserListFetchResponse> callback) { |         endCursor: String?, | ||||||
|         final Map<String, String> queryMap = new HashMap<>(); |     ): GraphQLUserListFetchResponse { | ||||||
|         queryMap.put("query_hash", "5f0b1f6281e72053cbc07909c8d154ae"); |         val queryMap = mapOf( | ||||||
|         queryMap.put("variables", "{\"comment_id\":\"" + commentId + "\"," + |             "query_hash" to "5f0b1f6281e72053cbc07909c8d154ae", | ||||||
|                 "\"first\":30," + |             "variables" to "{\"comment_id\":\"" + commentId + "\"," + "\"first\":30," + "\"after\":\"" + (endCursor ?: "") + "\"}" | ||||||
|                 "\"after\":\"" + (endCursor == null ? "" : endCursor) + "\"}"); |         ) | ||||||
|         final Call<String> request = repository.fetch(queryMap); |         val response = repository.fetch(queryMap) | ||||||
|         request.enqueue(new Callback<String>() { |         val body = JSONObject(response) | ||||||
|             @Override |         val status = body.getString("status") | ||||||
|             public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { |         val data = body.getJSONObject("data").getJSONObject("comment").getJSONObject("edge_liked_by") | ||||||
|                 final String rawBody = response.body(); |         val pageInfo = data.getJSONObject("page_info") | ||||||
|                 if (rawBody == null) { |         val newEndCursor = if (pageInfo.getBoolean("has_next_page")) pageInfo.getString("end_cursor") else null | ||||||
|                     Log.e(TAG, "Error occurred while fetching gql comment likes of " + commentId); |         val users = data.getJSONArray("edges") | ||||||
|                     callback.onSuccess(null); |         val usersLen = users.length() | ||||||
|                     return; |         val userModels: MutableList<User> = ArrayList() | ||||||
|                 } |         for (j in 0 until usersLen) { | ||||||
|                 try { |             val userObject = users.getJSONObject(j).getJSONObject("node") | ||||||
|                     final JSONObject body = new JSONObject(rawBody); |             userModels.add(User( | ||||||
|                     final String status = body.getString("status"); |                 userObject.getLong("id"), | ||||||
|                     final JSONObject data = body.getJSONObject("data").getJSONObject("comment").getJSONObject("edge_liked_by"); |                 userObject.getString("username"), | ||||||
|                     final JSONObject pageInfo = data.getJSONObject("page_info"); |                 userObject.optString("full_name"), | ||||||
|                     final String endCursor = pageInfo.getBoolean("has_next_page") ? pageInfo.getString("end_cursor") : null; |                 userObject.optBoolean("is_private"), | ||||||
|                     final JSONArray users = data.getJSONArray("edges"); |                 userObject.getString("profile_pic_url"), | ||||||
|                     final int usersLen = users.length(); |                 userObject.optBoolean("is_verified") | ||||||
|                     final List<User> userModels = new ArrayList<>(); |             )) | ||||||
|                     for (int j = 0; j < usersLen; ++j) { |         } | ||||||
|                         final JSONObject userObject = users.getJSONObject(j).getJSONObject("node"); |         return GraphQLUserListFetchResponse(newEndCursor, status, userModels) | ||||||
|                         userModels.add(new User( |  | ||||||
|                                 userObject.getLong("id"), |  | ||||||
|                                 userObject.getString("username"), |  | ||||||
|                                 userObject.optString("full_name"), |  | ||||||
|                                 userObject.optBoolean("is_private"), |  | ||||||
|                                 userObject.getString("profile_pic_url"), |  | ||||||
|                                 userObject.optBoolean("is_verified") |  | ||||||
|                         )); |  | ||||||
|                         // userModels.add(new ProfileModel(userObject.optBoolean("is_private"), |  | ||||||
|                         //                                 false, |  | ||||||
|                         //                                 userObject.optBoolean("is_verified"), |  | ||||||
|                         //                                 userObject.getString("id"), |  | ||||||
|                         //                                 userObject.getString("username"), |  | ||||||
|                         //                                 userObject.optString("full_name"), |  | ||||||
|                         //                                 null, null, |  | ||||||
|                         //                                 userObject.getString("profile_pic_url"), |  | ||||||
|                         //                                 null, 0, 0, 0, false, false, false, false, false)); |  | ||||||
|                     } |  | ||||||
|                     callback.onSuccess(new GraphQLUserListFetchResponse(endCursor, status, userModels)); |  | ||||||
|                 } catch (JSONException e) { |  | ||||||
|                     Log.e(TAG, "onResponse", e); |  | ||||||
|                     if (callback != null) { |  | ||||||
|                         callback.onFailure(e); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             @Override |  | ||||||
|             public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) { |  | ||||||
|                 if (callback != null) { |  | ||||||
|                     callback.onFailure(t); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public Call<String> fetchComments(final String shortCodeOrCommentId, |     suspend fun fetchComments( | ||||||
|                                       final boolean root, |         shortCodeOrCommentId: String?, | ||||||
|                                       final String cursor) { |         root: Boolean, | ||||||
|         final Map<String, String> queryMap = new HashMap<>(); |         cursor: String?, | ||||||
|         queryMap.put("query_hash", root ? "bc3296d1ce80a24b1b6e40b1e72903f5" : "51fdd02b67508306ad4484ff574a0b62"); |     ): String { | ||||||
|         final Map<String, Object> variables = ImmutableMap.of( |         val variables = mapOf( | ||||||
|                 root ? "shortcode" : "comment_id", shortCodeOrCommentId, |             (if (root) "shortcode" else "comment_id") to shortCodeOrCommentId, | ||||||
|                 "first", 50, |             "first" to 50, | ||||||
|                 "after", cursor == null ? "" : cursor |             "after" to (cursor ?: "") | ||||||
|         ); |         ) | ||||||
|         queryMap.put("variables", new JSONObject(variables).toString()); |         val queryMap = mapOf( | ||||||
|         return repository.fetch(queryMap); |             "query_hash" to if (root) "bc3296d1ce80a24b1b6e40b1e72903f5" else "51fdd02b67508306ad4484ff574a0b62", | ||||||
|  |             "variables" to JSONObject(variables).toString() | ||||||
|  |         ) | ||||||
|  |         return repository.fetch(queryMap) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // TODO convert string response to a response class |     // TODO convert string response to a response class | ||||||
|     public void fetchUser(final String username, |     suspend fun fetchUser( | ||||||
|                           final ServiceCallback<User> callback) { |         username: String, | ||||||
|         final Call<String> request = repository.getUser(username); |     ): User { | ||||||
|         request.enqueue(new Callback<String>() { |         val response = repository.getUser(username) | ||||||
|             @Override |         val body = JSONObject(response) | ||||||
|             public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { |         val userJson = body.getJSONObject("graphql").getJSONObject(Constants.EXTRAS_USER) | ||||||
|                 final String rawBody = response.body(); |         val isPrivate = userJson.getBoolean("is_private") | ||||||
|                 if (rawBody == null) { |         val id = userJson.optLong(Constants.EXTRAS_ID, 0) | ||||||
|                     Log.e(TAG, "Error occurred while fetching gql user of " + username); |         val timelineMedia = userJson.getJSONObject("edge_owner_to_timeline_media") | ||||||
|                     callback.onSuccess(null); |         // if (timelineMedia.has("edges")) { | ||||||
|                     return; |         //     final JSONArray edges = timelineMedia.getJSONArray("edges"); | ||||||
|                 } |         // } | ||||||
|                 try { |         var url: String? = userJson.optString("external_url") | ||||||
|                     final JSONObject body = new JSONObject(rawBody); |         if (url.isNullOrBlank()) url = null | ||||||
|                     final JSONObject userJson = body.getJSONObject("graphql") |         return User( | ||||||
|                                                     .getJSONObject(Constants.EXTRAS_USER); |             id, | ||||||
| 
 |             username, | ||||||
|                     boolean isPrivate = userJson.getBoolean("is_private"); |             userJson.getString("full_name"), | ||||||
|                     final long id = userJson.optLong(Constants.EXTRAS_ID, 0); |             isPrivate, | ||||||
|                     final JSONObject timelineMedia = userJson.getJSONObject("edge_owner_to_timeline_media"); |             userJson.getString("profile_pic_url_hd"), | ||||||
|                     // if (timelineMedia.has("edges")) { |             userJson.getBoolean("is_verified"), | ||||||
|                     //     final JSONArray edges = timelineMedia.getJSONArray("edges"); |             friendshipStatus = FriendshipStatus( | ||||||
|                     // } |                 userJson.optBoolean("followed_by_viewer"), | ||||||
| 
 |                 userJson.optBoolean("follows_viewer"), | ||||||
|                     String url = userJson.optString("external_url"); |                 userJson.optBoolean("blocked_by_viewer"), | ||||||
|                     if (TextUtils.isEmpty(url)) url = null; |                 false, | ||||||
| 
 |                 isPrivate, | ||||||
|                     callback.onSuccess(new User( |                 userJson.optBoolean("has_requested_viewer"), | ||||||
|                             id, |                 userJson.optBoolean("requested_by_viewer"), | ||||||
|                             username, |                 false, | ||||||
|                             userJson.getString("full_name"), |                 userJson.optBoolean("restricted_by_viewer"), | ||||||
|                             isPrivate, |                 false | ||||||
|                             userJson.getString("profile_pic_url_hd"), |             ), | ||||||
|                             userJson.getBoolean("is_verified"), |             mediaCount = timelineMedia.getLong("count"), | ||||||
|                             null, |             followerCount = userJson.getJSONObject("edge_followed_by").getLong("count"), | ||||||
|                             new FriendshipStatus( |             followingCount = userJson.getJSONObject("edge_follow").getLong("count"), | ||||||
|                                     userJson.optBoolean("followed_by_viewer"), |             biography = userJson.getString("biography"), | ||||||
|                                     userJson.optBoolean("follows_viewer"), |             externalUrl = url, | ||||||
|                                     userJson.optBoolean("blocked_by_viewer"), |         ) | ||||||
|                                     false, |  | ||||||
|                                     isPrivate, |  | ||||||
|                                     userJson.optBoolean("has_requested_viewer"), |  | ||||||
|                                     userJson.optBoolean("requested_by_viewer"), |  | ||||||
|                                     false, |  | ||||||
|                                     userJson.optBoolean("restricted_by_viewer"), |  | ||||||
|                                     false |  | ||||||
|                             ), |  | ||||||
|                             false, |  | ||||||
|                             false, |  | ||||||
|                             false, |  | ||||||
|                             false, |  | ||||||
|                             false, |  | ||||||
|                             null, |  | ||||||
|                             null, |  | ||||||
|                             timelineMedia.getLong("count"), |  | ||||||
|                             userJson.getJSONObject("edge_followed_by").getLong("count"), |  | ||||||
|                             userJson.getJSONObject("edge_follow").getLong("count"), |  | ||||||
|                             0, |  | ||||||
|                             userJson.getString("biography"), |  | ||||||
|                             url, |  | ||||||
|                             0, |  | ||||||
|                             null, |  | ||||||
|                             null, |  | ||||||
|                             null, |  | ||||||
|                             null, |  | ||||||
|                             null, |  | ||||||
|                             null)); |  | ||||||
|                 } catch (JSONException e) { |  | ||||||
|                     Log.e(TAG, "onResponse", e); |  | ||||||
|                     if (callback != null) { |  | ||||||
|                         callback.onFailure(e); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             @Override |  | ||||||
|             public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) { |  | ||||||
|                 if (callback != null) { |  | ||||||
|                     callback.onFailure(t); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // TODO convert string response to a response class |     // TODO convert string response to a response class | ||||||
|     public void fetchPost(final String shortcode, |     suspend fun fetchPost( | ||||||
|                           final ServiceCallback<Media> callback) { |         shortcode: String, | ||||||
|         final Call<String> request = repository.getPost(shortcode); |     ): Media { | ||||||
|         request.enqueue(new Callback<String>() { |         val response = repository.getPost(shortcode) | ||||||
|             @Override |         val body = JSONObject(response) | ||||||
|             public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { |         val media = body.getJSONObject("graphql").getJSONObject("shortcode_media") | ||||||
|                 final String rawBody = response.body(); |         return ResponseBodyUtils.parseGraphQLItem(media, null) | ||||||
|                 if (rawBody == null) { |  | ||||||
|                     Log.e(TAG, "Error occurred while fetching gql post of " + shortcode); |  | ||||||
|                     callback.onSuccess(null); |  | ||||||
|                     return; |  | ||||||
|                 } |  | ||||||
|                 try { |  | ||||||
|                     final JSONObject body = new JSONObject(rawBody); |  | ||||||
|                     final JSONObject media = body.getJSONObject("graphql") |  | ||||||
|                                                  .getJSONObject("shortcode_media"); |  | ||||||
|                     callback.onSuccess(ResponseBodyUtils.parseGraphQLItem(media, null)); |  | ||||||
|                 } catch (JSONException e) { |  | ||||||
|                     Log.e(TAG, "onResponse", e); |  | ||||||
|                     if (callback != null) { |  | ||||||
|                         callback.onFailure(e); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             @Override |  | ||||||
|             public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) { |  | ||||||
|                 if (callback != null) { |  | ||||||
|                     callback.onFailure(t); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // TODO convert string response to a response class |     // TODO convert string response to a response class | ||||||
|     public void fetchTag(final String tag, |     suspend fun fetchTag( | ||||||
|                          final ServiceCallback<Hashtag> callback) { |         tag: String, | ||||||
|         final Call<String> request = repository.getTag(tag); |     ): Hashtag { | ||||||
|         request.enqueue(new Callback<String>() { |         val response = repository.getTag(tag) | ||||||
|             @Override |         val body = JSONObject(response) | ||||||
|             public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { |             .getJSONObject("graphql") | ||||||
|                 final String rawBody = response.body(); |             .getJSONObject(Constants.EXTRAS_HASHTAG) | ||||||
|                 if (rawBody == null) { |         val timelineMedia = body.getJSONObject("edge_hashtag_to_media") | ||||||
|                     Log.e(TAG, "Error occurred while fetching gql tag of " + tag); |         return Hashtag( | ||||||
|                     callback.onSuccess(null); |             body.getString(Constants.EXTRAS_ID), | ||||||
|                     return; |             body.getString("name"), | ||||||
|                 } |             timelineMedia.getLong("count"), | ||||||
|                 try { |             if (body.optBoolean("is_following")) FollowingType.FOLLOWING else FollowingType.NOT_FOLLOWING, | ||||||
|                     final JSONObject body = new JSONObject(rawBody) |             null) | ||||||
|                             .getJSONObject("graphql") |  | ||||||
|                             .getJSONObject(Constants.EXTRAS_HASHTAG); |  | ||||||
|                     final JSONObject timelineMedia = body.getJSONObject("edge_hashtag_to_media"); |  | ||||||
|                     callback.onSuccess(new Hashtag( |  | ||||||
|                             body.getString(Constants.EXTRAS_ID), |  | ||||||
|                             body.getString("name"), |  | ||||||
|                             timelineMedia.getLong("count"), |  | ||||||
|                             body.optBoolean("is_following") ? FollowingType.FOLLOWING : FollowingType.NOT_FOLLOWING, |  | ||||||
|                             null)); |  | ||||||
|                 } catch (JSONException e) { |  | ||||||
|                     Log.e(TAG, "onResponse", e); |  | ||||||
|                     if (callback != null) { |  | ||||||
|                         callback.onFailure(e); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             @Override |  | ||||||
|             public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) { |  | ||||||
|                 if (callback != null) { |  | ||||||
|                     callback.onFailure(t); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // TODO convert string response to a response class |     // TODO convert string response to a response class | ||||||
|     public void fetchLocation(final long locationId, |     suspend fun fetchLocation( | ||||||
|                               final ServiceCallback<Location> callback) { |         locationId: Long, | ||||||
|         final Call<String> request = repository.getLocation(locationId); |     ): Location { | ||||||
|         request.enqueue(new Callback<String>() { |         val response = repository.getLocation(locationId) | ||||||
|             @Override |         val body = JSONObject(response) | ||||||
|             public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { |             .getJSONObject("graphql") | ||||||
|                 final String rawBody = response.body(); |             .getJSONObject(Constants.EXTRAS_LOCATION) | ||||||
|                 if (rawBody == null) { |         // val timelineMedia = body.getJSONObject("edge_location_to_media") | ||||||
|                     Log.e(TAG, "Error occurred while fetching gql location of " + locationId); |         val address = JSONObject(body.getString("address_json")) | ||||||
|                     callback.onSuccess(null); |         return Location( | ||||||
|                     return; |             body.getLong(Constants.EXTRAS_ID), | ||||||
|                 } |             body.getString("slug"), | ||||||
|                 try { |             body.getString("name"), | ||||||
|                     final JSONObject body = new JSONObject(rawBody) |             address.optString("street_address"), | ||||||
|                             .getJSONObject("graphql") |             address.optString("city_name"), | ||||||
|                             .getJSONObject(Constants.EXTRAS_LOCATION); |             body.optDouble("lng", 0.0), | ||||||
|                     final JSONObject timelineMedia = body.getJSONObject("edge_location_to_media"); |             body.optDouble("lat", 0.0) | ||||||
|                     final JSONObject address = new JSONObject(body.getString("address_json")); |         ) | ||||||
|                     callback.onSuccess(new Location( |  | ||||||
|                             body.getLong(Constants.EXTRAS_ID), |  | ||||||
|                             body.getString("slug"), |  | ||||||
|                             body.getString("name"), |  | ||||||
|                             address.optString("street_address"), |  | ||||||
|                             address.optString("city_name"), |  | ||||||
|                             body.optDouble("lng", 0d), |  | ||||||
|                             body.optDouble("lat", 0d) |  | ||||||
|                     )); |  | ||||||
|                 } catch (JSONException e) { |  | ||||||
|                     Log.e(TAG, "onResponse", e); |  | ||||||
|                     if (callback != null) { |  | ||||||
|                         callback.onFailure(e); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             @Override |  | ||||||
|             public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) { |  | ||||||
|                 if (callback != null) { |  | ||||||
|                     callback.onFailure(t); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user