mirror of
				https://github.com/KokaKiwi/BarInsta
				synced 2025-10-31 03:25:34 +00:00 
			
		
		
		
	notification backend revamp
This commit is contained in:
		
							parent
							
								
									5421bb4592
								
							
						
					
					
						commit
						7acd5faefd
					
				| @ -11,24 +11,25 @@ import androidx.recyclerview.widget.ListAdapter; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
| import java.util.stream.Collectors; | ||||
| 
 | ||||
| import awais.instagrabber.adapters.viewholder.NotificationViewHolder; | ||||
| import awais.instagrabber.databinding.ItemNotificationBinding; | ||||
| import awais.instagrabber.models.NotificationModel; | ||||
| import awais.instagrabber.models.enums.NotificationType; | ||||
| import awais.instagrabber.repositories.responses.Notification; | ||||
| 
 | ||||
| public final class NotificationsAdapter extends ListAdapter<NotificationModel, NotificationViewHolder> { | ||||
| public final class NotificationsAdapter extends ListAdapter<Notification, NotificationViewHolder> { | ||||
|     private final OnNotificationClickListener notificationClickListener; | ||||
| 
 | ||||
|     private static final DiffUtil.ItemCallback<NotificationModel> DIFF_CALLBACK = new DiffUtil.ItemCallback<NotificationModel>() { | ||||
|     private static final DiffUtil.ItemCallback<Notification> DIFF_CALLBACK = new DiffUtil.ItemCallback<Notification>() { | ||||
|         @Override | ||||
|         public boolean areItemsTheSame(@NonNull final NotificationModel oldItem, @NonNull final NotificationModel newItem) { | ||||
|             return oldItem.getId().equals(newItem.getId()); | ||||
|         public boolean areItemsTheSame(@NonNull final Notification oldItem, @NonNull final Notification newItem) { | ||||
|             return oldItem.getPk().equals(newItem.getPk()); | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public boolean areContentsTheSame(@NonNull final NotificationModel oldItem, @NonNull final NotificationModel newItem) { | ||||
|             return oldItem.getId().equals(newItem.getId()); | ||||
|         public boolean areContentsTheSame(@NonNull final Notification oldItem, @NonNull final Notification newItem) { | ||||
|             return oldItem.getPk().equals(newItem.getPk()); | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
| @ -47,12 +48,12 @@ public final class NotificationsAdapter extends ListAdapter<NotificationModel, N | ||||
| 
 | ||||
|     @Override | ||||
|     public void onBindViewHolder(@NonNull final NotificationViewHolder holder, final int position) { | ||||
|         final NotificationModel notificationModel = getItem(position); | ||||
|         holder.bind(notificationModel, notificationClickListener); | ||||
|         final Notification Notification = getItem(position); | ||||
|         holder.bind(Notification, notificationClickListener); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void submitList(@Nullable final List<NotificationModel> list, @Nullable final Runnable commitCallback) { | ||||
|     public void submitList(@Nullable final List<Notification> list, @Nullable final Runnable commitCallback) { | ||||
|         if (list == null) { | ||||
|             super.submitList(null, commitCallback); | ||||
|             return; | ||||
| @ -61,7 +62,7 @@ public final class NotificationsAdapter extends ListAdapter<NotificationModel, N | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void submitList(@Nullable final List<NotificationModel> list) { | ||||
|     public void submitList(@Nullable final List<Notification> list) { | ||||
|         if (list == null) { | ||||
|             super.submitList(null); | ||||
|             return; | ||||
| @ -69,8 +70,10 @@ public final class NotificationsAdapter extends ListAdapter<NotificationModel, N | ||||
|         super.submitList(sort(list)); | ||||
|     } | ||||
| 
 | ||||
|     private List<NotificationModel> sort(final List<NotificationModel> list) { | ||||
|         final List<NotificationModel> listCopy = new ArrayList<>(list); | ||||
|     private List<Notification> sort(final List<Notification> list) { | ||||
|         final List<Notification> listCopy = new ArrayList<>(list).stream() | ||||
|                 .filter(i -> i.getType() != null) | ||||
|                 .collect(Collectors.toList()); | ||||
|         Collections.sort(listCopy, (o1, o2) -> { | ||||
|             // keep requests at top | ||||
|             if (o1.getType() == o2.getType() | ||||
| @ -79,16 +82,16 @@ public final class NotificationsAdapter extends ListAdapter<NotificationModel, N | ||||
|             else if (o1.getType() == NotificationType.REQUEST) return -1; | ||||
|             else if (o2.getType() == NotificationType.REQUEST) return 1; | ||||
|             // timestamp | ||||
|             return Long.compare(o2.getTimestamp(), o1.getTimestamp()); | ||||
|             return Double.compare(o2.getArgs().getTimestamp(), o1.getArgs().getTimestamp()); | ||||
|         }); | ||||
|         return listCopy; | ||||
|     } | ||||
| 
 | ||||
|     public interface OnNotificationClickListener { | ||||
|         void onNotificationClick(final NotificationModel model); | ||||
|         void onNotificationClick(final Notification model); | ||||
| 
 | ||||
|         void onProfileClick(final String username); | ||||
| 
 | ||||
|         void onPreviewClick(final NotificationModel model); | ||||
|         void onPreviewClick(final Notification model); | ||||
|     } | ||||
| } | ||||
| @ -8,8 +8,9 @@ import androidx.recyclerview.widget.RecyclerView; | ||||
| import awais.instagrabber.R; | ||||
| import awais.instagrabber.adapters.NotificationsAdapter.OnNotificationClickListener; | ||||
| import awais.instagrabber.databinding.ItemNotificationBinding; | ||||
| import awais.instagrabber.models.NotificationModel; | ||||
| import awais.instagrabber.models.enums.NotificationType; | ||||
| import awais.instagrabber.repositories.responses.Notification; | ||||
| import awais.instagrabber.repositories.responses.NotificationArgs; | ||||
| 
 | ||||
| public final class NotificationViewHolder extends RecyclerView.ViewHolder { | ||||
|     private final ItemNotificationBinding binding; | ||||
| @ -19,22 +20,23 @@ public final class NotificationViewHolder extends RecyclerView.ViewHolder { | ||||
|         this.binding = binding; | ||||
|     } | ||||
| 
 | ||||
|     public void bind(final NotificationModel model, | ||||
|     public void bind(final Notification model, | ||||
|                      final OnNotificationClickListener notificationClickListener) { | ||||
|         if (model == null) return; | ||||
|         int text = -1; | ||||
|         CharSequence subtext = null; | ||||
|         final NotificationArgs args = model.getArgs(); | ||||
|         switch (model.getType()) { | ||||
|             case LIKE: | ||||
|                 text = R.string.liked_notif; | ||||
|                 break; | ||||
|             case COMMENT: | ||||
|                 text = R.string.comment_notif; | ||||
|                 subtext = model.getText(); | ||||
|                 subtext = args.getText(); | ||||
|                 break; | ||||
|             case COMMENT_MENTION: | ||||
|                 text = R.string.mention_notif; | ||||
|                 subtext = model.getText(); | ||||
|                 subtext = args.getText(); | ||||
|                 break; | ||||
|             case TAGGED: | ||||
|                 text = R.string.tagged_notif; | ||||
| @ -44,18 +46,18 @@ public final class NotificationViewHolder extends RecyclerView.ViewHolder { | ||||
|                 break; | ||||
|             case REQUEST: | ||||
|                 text = R.string.request_notif; | ||||
|                 subtext = model.getText(); | ||||
|                 subtext = args.getText(); | ||||
|                 break; | ||||
|             case COMMENT_LIKE: | ||||
|             case TAGGED_COMMENT: | ||||
|             case RESPONDED_STORY: | ||||
|                 subtext = model.getText(); | ||||
|                 subtext = args.getText(); | ||||
|                 break; | ||||
|             case AYML: | ||||
|                 subtext = model.getPreviewPic(); | ||||
|                 subtext = args.getFullName(); | ||||
|                 break; | ||||
|         } | ||||
|         binding.tvSubComment.setText(model.getType() == NotificationType.AYML ? model.getText() : subtext); | ||||
|         binding.tvSubComment.setText(model.getType() == NotificationType.AYML ? args.getText() : subtext); | ||||
|         if (text == -1 && subtext != null) { | ||||
|             binding.tvComment.setText(subtext); | ||||
|             binding.tvComment.setVisibility(TextUtils.isEmpty(subtext) ? View.GONE : View.VISIBLE); | ||||
| @ -65,24 +67,25 @@ public final class NotificationViewHolder extends RecyclerView.ViewHolder { | ||||
|             binding.tvSubComment.setVisibility(subtext == null ? View.GONE : View.VISIBLE); | ||||
|         } | ||||
| 
 | ||||
|         binding.tvDate.setVisibility(model.getType() == NotificationType.AYML ? View.GONE : View.VISIBLE); | ||||
|         if (model.getType() != NotificationType.REQUEST && model.getType() != NotificationType.AYML) { | ||||
|             binding.tvDate.setText(model.getDateTime()); | ||||
|             binding.tvDate.setText(args.getDateTime()); | ||||
|         } | ||||
| 
 | ||||
|         binding.tvUsername.setText(model.getUsername()); | ||||
|         binding.ivProfilePic.setImageURI(model.getProfilePic()); | ||||
|         binding.tvUsername.setText(args.getUsername()); | ||||
|         binding.ivProfilePic.setImageURI(args.getProfilePic()); | ||||
|         binding.ivProfilePic.setOnClickListener(v -> { | ||||
|             if (notificationClickListener == null) return; | ||||
|             notificationClickListener.onProfileClick(model.getUsername()); | ||||
|             notificationClickListener.onProfileClick(args.getUsername()); | ||||
|         }); | ||||
| 
 | ||||
|         if (model.getType() == NotificationType.AYML) { | ||||
|             binding.ivPreviewPic.setVisibility(View.GONE); | ||||
|         } else if (TextUtils.isEmpty(model.getPreviewPic())) { | ||||
|         } else if (args.getMedia() == null) { | ||||
|             binding.ivPreviewPic.setVisibility(View.INVISIBLE); | ||||
|         } else { | ||||
|             binding.ivPreviewPic.setVisibility(View.VISIBLE); | ||||
|             binding.ivPreviewPic.setImageURI(model.getPreviewPic()); | ||||
|             binding.ivPreviewPic.setImageURI(args.getMedia().get(0).getImage()); | ||||
|             binding.ivPreviewPic.setOnClickListener(v -> { | ||||
|                 if (notificationClickListener == null) return; | ||||
|                 notificationClickListener.onPreviewClick(model); | ||||
|  | ||||
| @ -1,139 +0,0 @@ | ||||
| package awais.instagrabber.asyncs; | ||||
| 
 | ||||
| import android.os.AsyncTask; | ||||
| import android.util.Log; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import org.json.JSONObject; | ||||
| 
 | ||||
| import java.net.HttpURLConnection; | ||||
| import java.net.URL; | ||||
| 
 | ||||
| import awais.instagrabber.utils.Constants; | ||||
| import awais.instagrabber.utils.CookieUtils; | ||||
| import awais.instagrabber.utils.NetworkUtils; | ||||
| import awais.instagrabber.utils.TextUtils; | ||||
| import awais.instagrabber.utils.Utils; | ||||
| 
 | ||||
| public class GetActivityAsyncTask extends AsyncTask<String, Void, GetActivityAsyncTask.NotificationCounts> { | ||||
|     private static final String TAG = "GetActivityAsyncTask"; | ||||
| 
 | ||||
|     private final OnTaskCompleteListener onTaskCompleteListener; | ||||
| 
 | ||||
|     public GetActivityAsyncTask(final OnTaskCompleteListener onTaskCompleteListener) { | ||||
|         this.onTaskCompleteListener = onTaskCompleteListener; | ||||
|     } | ||||
| 
 | ||||
|     /* | ||||
|     This needs to be redone to fetch i inbox instead | ||||
|     Within inbox, data is (body JSON => counts) | ||||
|     Then we have these counts: | ||||
|     new_posts, activity_feed_dot_badge, relationships, campaign_notification | ||||
|     usertags, likes, comment_likes, shopping_notification, comments | ||||
|     photos_of_you (not sure about difference to usertags), requests | ||||
|      */ | ||||
| 
 | ||||
|     protected NotificationCounts doInBackground(final String... cookiesArray) { | ||||
|         if (cookiesArray == null) return null; | ||||
|         final String cookie = cookiesArray[0]; | ||||
|         if (TextUtils.isEmpty(cookie)) return null; | ||||
|         final long uid = CookieUtils.getUserIdFromCookie(cookie); | ||||
|         final String url = "https://www.instagram.com/graphql/query/?query_hash=0f318e8cfff9cc9ef09f88479ff571fb" | ||||
|                 + "&variables={\"id\":\"" + uid + "\"}"; | ||||
|         HttpURLConnection urlConnection = null; | ||||
|         try { | ||||
|             urlConnection = (HttpURLConnection) new URL(url).openConnection(); | ||||
|             urlConnection.setUseCaches(false); | ||||
|             urlConnection.setRequestProperty("User-Agent", Utils.settingsHelper.getString(Constants.BROWSER_UA)); | ||||
|             urlConnection.setRequestProperty("x-csrftoken", cookie.split("csrftoken=")[1].split(";")[0]); | ||||
|             urlConnection.connect(); | ||||
|             if (urlConnection.getResponseCode() != HttpURLConnection.HTTP_OK) { | ||||
|                 return null; | ||||
|             } | ||||
|             final JSONObject data = new JSONObject(NetworkUtils.readFromConnection(urlConnection)) | ||||
|                     .getJSONObject("data") | ||||
|                     .getJSONObject("user") | ||||
|                     .getJSONObject("edge_activity_count") | ||||
|                     .getJSONArray("edges") | ||||
|                     .getJSONObject(0) | ||||
|                     .getJSONObject("node"); | ||||
|             return new NotificationCounts( | ||||
|                     data.getInt("relationships"), | ||||
|                     data.getInt("usertags"), | ||||
|                     data.getInt("comments"), | ||||
|                     data.getInt("comment_likes"), | ||||
|                     data.getInt("likes") | ||||
|             ); | ||||
|         } catch (Throwable ex) { | ||||
|             Log.e(TAG, "Error", ex); | ||||
|         } finally { | ||||
|             if (urlConnection != null) { | ||||
|                 urlConnection.disconnect(); | ||||
|             } | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onPostExecute(final NotificationCounts result) { | ||||
|         if (onTaskCompleteListener == null) return; | ||||
|         onTaskCompleteListener.onTaskComplete(result); | ||||
|     } | ||||
| 
 | ||||
|     public static class NotificationCounts { | ||||
|         private final int relationshipsCount; | ||||
|         private final int userTagsCount; | ||||
|         private final int commentsCount; | ||||
|         private final int commentLikesCount; | ||||
|         private final int likesCount; | ||||
| 
 | ||||
|         public NotificationCounts(final int relationshipsCount, | ||||
|                                   final int userTagsCount, | ||||
|                                   final int commentsCount, | ||||
|                                   final int commentLikesCount, | ||||
|                                   final int likesCount) { | ||||
|             this.relationshipsCount = relationshipsCount; | ||||
|             this.userTagsCount = userTagsCount; | ||||
|             this.commentsCount = commentsCount; | ||||
|             this.commentLikesCount = commentLikesCount; | ||||
|             this.likesCount = likesCount; | ||||
|         } | ||||
| 
 | ||||
|         public int getRelationshipsCount() { | ||||
|             return relationshipsCount; | ||||
|         } | ||||
| 
 | ||||
|         public int getUserTagsCount() { | ||||
|             return userTagsCount; | ||||
|         } | ||||
| 
 | ||||
|         public int getCommentsCount() { | ||||
|             return commentsCount; | ||||
|         } | ||||
| 
 | ||||
|         public int getCommentLikesCount() { | ||||
|             return commentLikesCount; | ||||
|         } | ||||
| 
 | ||||
|         public int getLikesCount() { | ||||
|             return likesCount; | ||||
|         } | ||||
| 
 | ||||
|         @NonNull | ||||
|         @Override | ||||
|         public String toString() { | ||||
|             return "NotificationCounts{" + | ||||
|                     "relationshipsCount=" + relationshipsCount + | ||||
|                     ", userTagsCount=" + userTagsCount + | ||||
|                     ", commentsCount=" + commentsCount + | ||||
|                     ", commentLikesCount=" + commentLikesCount + | ||||
|                     ", likesCount=" + likesCount + | ||||
|                     '}'; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public interface OnTaskCompleteListener { | ||||
|         void onTaskComplete(final NotificationCounts result); | ||||
|     } | ||||
| } | ||||
| @ -8,35 +8,35 @@ import java.util.List; | ||||
| 
 | ||||
| import awais.instagrabber.BuildConfig; | ||||
| import awais.instagrabber.interfaces.FetchListener; | ||||
| import awais.instagrabber.models.NotificationModel; | ||||
| import awais.instagrabber.repositories.responses.Notification; | ||||
| import awais.instagrabber.webservices.NewsService; | ||||
| import awais.instagrabber.webservices.ServiceCallback; | ||||
| import awaisomereport.LogCollector; | ||||
| 
 | ||||
| import static awais.instagrabber.utils.Utils.logCollector; | ||||
| 
 | ||||
| public final class NotificationsFetcher extends AsyncTask<Void, Void, List<NotificationModel>> { | ||||
| public final class NotificationsFetcher extends AsyncTask<Void, Void, List<Notification>> { | ||||
|     private static final String TAG = "NotificationsFetcher"; | ||||
| 
 | ||||
|     private final FetchListener<List<NotificationModel>> fetchListener; | ||||
|     private final FetchListener<List<Notification>> fetchListener; | ||||
|     private final NewsService newsService; | ||||
|     private final boolean markAsSeen; | ||||
|     private boolean fetchedWeb = false; | ||||
| 
 | ||||
|     public NotificationsFetcher(final boolean markAsSeen, | ||||
|                                 final FetchListener<List<NotificationModel>> fetchListener) { | ||||
|                                 final FetchListener<List<Notification>> fetchListener) { | ||||
|         this.markAsSeen = markAsSeen; | ||||
|         this.fetchListener = fetchListener; | ||||
|         newsService = NewsService.getInstance(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected List<NotificationModel> doInBackground(final Void... voids) { | ||||
|         List<NotificationModel> notificationModels = new ArrayList<>(); | ||||
|     protected List<Notification> doInBackground(final Void... voids) { | ||||
|         List<Notification> notificationModels = new ArrayList<>(); | ||||
| 
 | ||||
|         newsService.fetchAppInbox(markAsSeen, new ServiceCallback<List<NotificationModel>>() { | ||||
|         newsService.fetchAppInbox(markAsSeen, new ServiceCallback<List<Notification>>() { | ||||
|             @Override | ||||
|             public void onSuccess(final List<NotificationModel> result) { | ||||
|             public void onSuccess(final List<Notification> result) { | ||||
|                 if (result == null) return; | ||||
|                 notificationModels.addAll(result); | ||||
|                 if (fetchedWeb) { | ||||
| @ -44,7 +44,7 @@ public final class NotificationsFetcher extends AsyncTask<Void, Void, List<Notif | ||||
|                 } | ||||
|                 else { | ||||
|                     fetchedWeb = true; | ||||
|                     newsService.fetchWebInbox(markAsSeen, this); | ||||
|                     newsService.fetchWebInbox(this); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|  | ||||
| @ -33,11 +33,13 @@ import awais.instagrabber.asyncs.NotificationsFetcher; | ||||
| import awais.instagrabber.databinding.FragmentNotificationsViewerBinding; | ||||
| import awais.instagrabber.fragments.settings.MorePreferencesFragmentDirections; | ||||
| import awais.instagrabber.interfaces.FetchListener; | ||||
| import awais.instagrabber.models.NotificationModel; | ||||
| import awais.instagrabber.models.enums.NotificationType; | ||||
| import awais.instagrabber.repositories.requests.StoryViewerOptions; | ||||
| import awais.instagrabber.repositories.responses.FriendshipChangeResponse; | ||||
| import awais.instagrabber.repositories.responses.Media; | ||||
| import awais.instagrabber.repositories.responses.Notification; | ||||
| import awais.instagrabber.repositories.responses.NotificationArgs; | ||||
| import awais.instagrabber.repositories.responses.NotificationImage; | ||||
| import awais.instagrabber.utils.Constants; | ||||
| import awais.instagrabber.utils.CookieUtils; | ||||
| import awais.instagrabber.utils.TextUtils; | ||||
| @ -70,14 +72,18 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public void onPreviewClick(final NotificationModel model) { | ||||
|         public void onPreviewClick(final Notification model) { | ||||
|             final NotificationImage notificationImage = model.getArgs().getMedia().get(0); | ||||
|             final long mediaId = Long.valueOf(notificationImage.getId().split("_")[0]); | ||||
|             if (model.getType() == NotificationType.RESPONDED_STORY) { | ||||
|                 final NavDirections action = NotificationsViewerFragmentDirections | ||||
|                         .actionNotificationsViewerFragmentToStoryViewerFragment(StoryViewerOptions.forStory(model.getPostId(), | ||||
|                                                                                                             model.getUsername())); | ||||
|                         .actionNotificationsViewerFragmentToStoryViewerFragment( | ||||
|                                 StoryViewerOptions.forStory( | ||||
|                                         mediaId, | ||||
|                                         model.getArgs().getUsername())); | ||||
|                 NavHostFragment.findNavController(NotificationsViewerFragment.this).navigate(action); | ||||
|             } else { | ||||
|                 mediaService.fetch(model.getPostId(), new ServiceCallback<Media>() { | ||||
|                 mediaService.fetch(mediaId, new ServiceCallback<Media>() { | ||||
|                     @Override | ||||
|                     public void onSuccess(final Media feedModel) { | ||||
|                         final PostViewV2Fragment fragment = PostViewV2Fragment | ||||
| @ -95,13 +101,14 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public void onNotificationClick(final NotificationModel model) { | ||||
|         public void onNotificationClick(final Notification model) { | ||||
|             if (model == null) return; | ||||
|             final String username = model.getUsername(); | ||||
|             final NotificationArgs args = model.getArgs(); | ||||
|             final String username = args.getUsername(); | ||||
|             if (model.getType() == NotificationType.FOLLOW || model.getType() == NotificationType.AYML) { | ||||
|                 openProfile(username); | ||||
|             } else { | ||||
|                 final SpannableString title = new SpannableString(username + (TextUtils.isEmpty(model.getText()) ? "" : (":\n" + model.getText()))); | ||||
|                 final SpannableString title = new SpannableString(username + (TextUtils.isEmpty(args.getText()) ? "" : (":\n" + args.getText()))); | ||||
|                 title.setSpan(new RelativeSizeSpan(1.23f), 0, username.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); | ||||
| 
 | ||||
|                 String[] commentDialogList; | ||||
| @ -110,7 +117,7 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe | ||||
|                             getString(R.string.open_profile), | ||||
|                             getString(R.string.view_story) | ||||
|                     }; | ||||
|                 } else if (model.getPostId() > 0) { | ||||
|                 } else if (args.getMedia() != null) { | ||||
|                     commentDialogList = new String[]{ | ||||
|                             getString(R.string.open_profile), | ||||
|                             getString(R.string.view_post) | ||||
| @ -131,7 +138,7 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe | ||||
|                             break; | ||||
|                         case 1: | ||||
|                             if (model.getType() == NotificationType.REQUEST) { | ||||
|                                 friendshipService.approve(model.getUserId(), new ServiceCallback<FriendshipChangeResponse>() { | ||||
|                                 friendshipService.approve(args.getUserId(), new ServiceCallback<FriendshipChangeResponse>() { | ||||
|                                     @Override | ||||
|                                     public void onSuccess(final FriendshipChangeResponse result) { | ||||
|                                         onRefresh(); | ||||
| @ -148,7 +155,7 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe | ||||
|                             clickListener.onPreviewClick(model); | ||||
|                             break; | ||||
|                         case 2: | ||||
|                             friendshipService.ignore(model.getUserId(), new ServiceCallback<FriendshipChangeResponse>() { | ||||
|                             friendshipService.ignore(args.getUserId(), new ServiceCallback<FriendshipChangeResponse>() { | ||||
|                                 @Override | ||||
|                                 public void onSuccess(final FriendshipChangeResponse result) { | ||||
|                                     onRefresh(); | ||||
| @ -226,9 +233,9 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe | ||||
|         binding.swipeRefreshLayout.setRefreshing(true); | ||||
|         switch (type) { | ||||
|             case "notif": | ||||
|                 new NotificationsFetcher(true, new FetchListener<List<NotificationModel>>() { | ||||
|                 new NotificationsFetcher(true, new FetchListener<List<Notification>>() { | ||||
|                     @Override | ||||
|                     public void onResult(final List<NotificationModel> notificationModels) { | ||||
|                     public void onResult(final List<Notification> notificationModels) { | ||||
|                         binding.swipeRefreshLayout.setRefreshing(false); | ||||
|                         notificationViewModel.getList().postValue(notificationModels); | ||||
|                     } | ||||
| @ -245,9 +252,9 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe | ||||
|                 break; | ||||
|             case "ayml": | ||||
|                 final NewsService newsService = NewsService.getInstance(); | ||||
|                 newsService.fetchSuggestions(csrfToken, new ServiceCallback<List<NotificationModel>>() { | ||||
|                 newsService.fetchSuggestions(csrfToken, new ServiceCallback<List<Notification>>() { | ||||
|                     @Override | ||||
|                     public void onSuccess(final List<NotificationModel> notificationModels) { | ||||
|                     public void onSuccess(final List<Notification> notificationModels) { | ||||
|                         binding.swipeRefreshLayout.setRefreshing(false); | ||||
|                         notificationViewModel.getList().postValue(notificationModels); | ||||
|                     } | ||||
|  | ||||
| @ -1,79 +0,0 @@ | ||||
| package awais.instagrabber.models; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import java.util.Date; | ||||
| 
 | ||||
| import awais.instagrabber.models.enums.NotificationType; | ||||
| import awais.instagrabber.utils.Utils; | ||||
| 
 | ||||
| public final class NotificationModel { | ||||
|     private final String id; | ||||
|     private final long userId; | ||||
|     private final String username; | ||||
|     private final String profilePicUrl; | ||||
|     private final long postId; | ||||
|     private final String previewUrl; | ||||
|     private final NotificationType type; | ||||
|     private final CharSequence text; | ||||
|     private final long timestamp; | ||||
| 
 | ||||
|     public NotificationModel(final String id, | ||||
|                              final String text, | ||||
|                              final long timestamp, | ||||
|                              final long userId, | ||||
|                              final String username, | ||||
|                              final String profilePicUrl, | ||||
|                              final long postId, | ||||
|                              final String previewUrl, | ||||
|                              final NotificationType type) { | ||||
|         this.id = id; | ||||
|         this.text = text; | ||||
|         this.timestamp = timestamp; | ||||
|         this.userId = userId; | ||||
|         this.username = username; | ||||
|         this.profilePicUrl = profilePicUrl; | ||||
|         this.postId = postId; | ||||
|         this.previewUrl = previewUrl; | ||||
|         this.type = type; | ||||
|     } | ||||
| 
 | ||||
|     public String getId() { | ||||
|         return id; | ||||
|     } | ||||
| 
 | ||||
|     public CharSequence getText() { | ||||
|         return text; | ||||
|     } | ||||
| 
 | ||||
|     public long getTimestamp() { | ||||
|         return timestamp; | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     public String getDateTime() { | ||||
|         return Utils.datetimeParser.format(new Date(timestamp * 1000L)); | ||||
|     } | ||||
| 
 | ||||
|     public long getUserId() { | ||||
|         return userId; | ||||
|     } | ||||
| 
 | ||||
|     public String getUsername() { | ||||
|         return username; | ||||
|     } | ||||
| 
 | ||||
|     public String getProfilePic() { | ||||
|         return profilePicUrl; | ||||
|     } | ||||
| 
 | ||||
|     public long getPostId() { | ||||
|         return postId; | ||||
|     } | ||||
| 
 | ||||
|     public String getPreviewPic() { | ||||
|         return previewUrl; | ||||
|     } | ||||
| 
 | ||||
|     public NotificationType getType() { return type; } | ||||
| } | ||||
| @ -2,6 +2,8 @@ package awais.instagrabber.repositories; | ||||
| 
 | ||||
| import java.util.Map; | ||||
| 
 | ||||
| import awais.instagrabber.repositories.responses.AymlResponse; | ||||
| import awais.instagrabber.repositories.responses.NewsInboxResponse; | ||||
| import retrofit2.Call; | ||||
| import retrofit2.http.FieldMap; | ||||
| import retrofit2.http.FormUrlEncoded; | ||||
| @ -16,9 +18,9 @@ public interface NewsRepository { | ||||
|     Call<String> webInbox(@Header("User-Agent") String userAgent); | ||||
| 
 | ||||
|     @GET("/api/v1/news/inbox/") | ||||
|     Call<String> appInbox(@Header("User-Agent") String userAgent, @Query(value = "mark_as_seen", encoded = true) boolean markAsSeen); | ||||
|     Call<NewsInboxResponse> appInbox(@Header("User-Agent") String userAgent, @Query(value = "mark_as_seen", encoded = true) boolean markAsSeen); | ||||
| 
 | ||||
|     @FormUrlEncoded | ||||
|     @POST("/api/v1/discover/ayml/") | ||||
|     Call<String> getAyml(@Header("User-Agent") String userAgent, @FieldMap final Map<String, String> form); | ||||
|     Call<AymlResponse> getAyml(@Header("User-Agent") String userAgent, @FieldMap final Map<String, String> form); | ||||
| } | ||||
|  | ||||
| @ -0,0 +1,22 @@ | ||||
| package awais.instagrabber.repositories.responses; | ||||
| 
 | ||||
| import java.util.List; | ||||
| 
 | ||||
| public class AymlResponse { | ||||
|     private final AymlUserList newSuggestedUsers; | ||||
|     private final AymlUserList suggestedUsers; | ||||
| 
 | ||||
|     public AymlResponse(final AymlUserList newSuggestedUsers, | ||||
|                         final AymlUserList suggestedUsers) { | ||||
|         this.newSuggestedUsers = newSuggestedUsers; | ||||
|         this.suggestedUsers = suggestedUsers; | ||||
|     } | ||||
| 
 | ||||
|     public AymlUserList getNewSuggestedUsers() { | ||||
|         return newSuggestedUsers; | ||||
|     } | ||||
| 
 | ||||
|     public AymlUserList getSuggestedUsers() { | ||||
|         return suggestedUsers; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,34 @@ | ||||
| package awais.instagrabber.repositories.responses; | ||||
| 
 | ||||
| public class AymlUser { | ||||
|     private final User user; | ||||
|     private final String algorithm; | ||||
|     private final String socialContext; | ||||
|     private final String uuid; | ||||
| 
 | ||||
|     public AymlUser(final User user, | ||||
|                     final String algorithm, | ||||
|                     final String socialContext, | ||||
|                     final String uuid) { | ||||
|         this.user = user; | ||||
|         this.algorithm = algorithm; | ||||
|         this.socialContext = socialContext; | ||||
|         this.uuid = uuid; | ||||
|     } | ||||
| 
 | ||||
|     public User getUser() { | ||||
|         return user; | ||||
|     } | ||||
| 
 | ||||
|     public String getAlgorithm() { | ||||
|         return algorithm; | ||||
|     } | ||||
| 
 | ||||
|     public String getSocialContext() { | ||||
|         return socialContext; | ||||
|     } | ||||
| 
 | ||||
|     public String getUuid() { | ||||
|         return uuid; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,15 @@ | ||||
| package awais.instagrabber.repositories.responses; | ||||
| 
 | ||||
| import java.util.List; | ||||
| 
 | ||||
| public class AymlUserList { | ||||
|     private final List<AymlUser> suggestions; | ||||
| 
 | ||||
|     public AymlUserList(final List<AymlUser> suggestions) { | ||||
|         this.suggestions = suggestions; | ||||
|     } | ||||
| 
 | ||||
|     public List<AymlUser> getSuggestions() { | ||||
|         return suggestions; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,29 @@ | ||||
| package awais.instagrabber.repositories.responses; | ||||
| 
 | ||||
| import java.util.List; | ||||
| 
 | ||||
| public class NewsInboxResponse { | ||||
|     private final NotificationCounts counts; | ||||
|     private final List<Notification> newStories; | ||||
|     private final List<Notification> oldStories; | ||||
| 
 | ||||
|     public NewsInboxResponse(final NotificationCounts counts, | ||||
|                              final List<Notification> newStories, | ||||
|                              final List<Notification> oldStories) { | ||||
|         this.counts = counts; | ||||
|         this.newStories = newStories; | ||||
|         this.oldStories = oldStories; | ||||
|     } | ||||
| 
 | ||||
|     public NotificationCounts getCounts() { | ||||
|         return counts; | ||||
|     } | ||||
| 
 | ||||
|     public List<Notification> getNewStories() { | ||||
|         return newStories; | ||||
|     } | ||||
| 
 | ||||
|     public List<Notification> getOldStories() { | ||||
|         return oldStories; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,29 @@ | ||||
| package awais.instagrabber.repositories.responses; | ||||
| 
 | ||||
| import awais.instagrabber.models.enums.NotificationType; | ||||
| 
 | ||||
| public class Notification { | ||||
|     private final NotificationArgs args; | ||||
|     private final String storyType; | ||||
|     private final String pk; | ||||
| 
 | ||||
|     public Notification(final NotificationArgs args, | ||||
|                         final String storyType, | ||||
|                         final String pk) { | ||||
|         this.args = args; | ||||
|         this.storyType = storyType; | ||||
|         this.pk = pk; | ||||
|     } | ||||
| 
 | ||||
|     public NotificationArgs getArgs() { | ||||
|         return args; | ||||
|     } | ||||
| 
 | ||||
|     public NotificationType getType() { | ||||
|         return NotificationType.valueOfType(storyType); | ||||
|     } | ||||
| 
 | ||||
|     public String getPk() { | ||||
|         return pk; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,86 @@ | ||||
| package awais.instagrabber.repositories.responses; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import java.util.Date; | ||||
| import java.util.List; | ||||
| import java.util.regex.Matcher; | ||||
| import java.util.regex.Pattern; | ||||
| 
 | ||||
| import android.util.Log; | ||||
| 
 | ||||
| import awais.instagrabber.utils.Utils; | ||||
| 
 | ||||
| public class NotificationArgs { | ||||
|     private final String text; | ||||
|     private final String richText; | ||||
|     private final long profileId; | ||||
|     private final String profileImage; | ||||
|     private final List<NotificationImage> media; | ||||
|     private final double timestamp; | ||||
|     private final String profileName; | ||||
|     private final String fullName; // for AYML, not naturally generated | ||||
| 
 | ||||
|     public NotificationArgs(final String text, | ||||
|                             final String richText, // for AYML, this is the algorithm | ||||
|                             final long profileId, | ||||
|                             final String profileImage, | ||||
|                             final List<NotificationImage> media, | ||||
|                             final double timestamp, | ||||
|                             final String profileName, | ||||
|                             final String fullName) { | ||||
|         this.text = text; | ||||
|         this.richText = richText; | ||||
|         this.profileId = profileId; | ||||
|         this.profileImage = profileImage; | ||||
|         this.media = media; | ||||
|         this.timestamp = timestamp; | ||||
|         this.profileName = profileName; | ||||
|         this.fullName = fullName; | ||||
|     } | ||||
| 
 | ||||
|     public String getText() { | ||||
|         return text == null ? cleanRichText(richText) : text; | ||||
|     } | ||||
| 
 | ||||
|     public long getUserId() { | ||||
|         return profileId; | ||||
|     } | ||||
| 
 | ||||
|     public String getProfilePic() { | ||||
|         return profileImage; | ||||
|     } | ||||
| 
 | ||||
|     public String getUsername() { | ||||
|         return profileName; | ||||
|     } | ||||
| 
 | ||||
|     public String getFullName() { | ||||
|         return fullName; | ||||
|     } | ||||
| 
 | ||||
|     public List<NotificationImage> getMedia() { | ||||
|         return media; | ||||
|     } | ||||
| 
 | ||||
|     public double getTimestamp() { | ||||
|         return timestamp; | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     public String getDateTime() { | ||||
|         return Utils.datetimeParser.format(new Date(Math.round(timestamp * 1000))); | ||||
|     } | ||||
| 
 | ||||
|     private String cleanRichText(final String raw) { | ||||
|         if (raw == null) return null; | ||||
|         final Matcher matcher = Pattern.compile("\\{[\\p{L}\\d._]+\\|000000\\|1\\|user\\?id=\\d+\\}").matcher(raw); | ||||
|         String result = raw; | ||||
|         while (matcher.find()) { | ||||
|             final String richObject = raw.substring(matcher.start(), matcher.end()); | ||||
|             final String username = richObject.split("\\|")[0].substring(1); | ||||
|             result = result.replace(richObject, username); | ||||
|         } | ||||
|         return result; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,57 @@ | ||||
| package awais.instagrabber.repositories.responses; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| public class NotificationCounts { | ||||
|     private final int commentLikes; | ||||
|     private final int usertags; | ||||
|     private final int likes; | ||||
|     private final int comments; | ||||
|     private final int relationships; | ||||
|     private final int photosOfYou; | ||||
|     private final int requests; | ||||
| 
 | ||||
|     public NotificationCounts(final int commentLikes, | ||||
|                               final int usertags, | ||||
|                               final int likes, | ||||
|                               final int comments, | ||||
|                               final int relationships, | ||||
|                               final int photosOfYou, | ||||
|                               final int requests) { | ||||
|         this.commentLikes = commentLikes; | ||||
|         this.usertags = usertags; | ||||
|         this.likes = likes; | ||||
|         this.comments = comments; | ||||
|         this.relationships = relationships; | ||||
|         this.photosOfYou = photosOfYou; | ||||
|         this.requests = requests; | ||||
|     } | ||||
| 
 | ||||
|     public int getRelationshipsCount() { | ||||
|         return relationships; | ||||
|     } | ||||
| 
 | ||||
|     public int getUserTagsCount() { | ||||
|         return usertags; | ||||
|     } | ||||
| 
 | ||||
|     public int getCommentsCount() { | ||||
|         return comments; | ||||
|     } | ||||
| 
 | ||||
|     public int getCommentLikesCount() { | ||||
|         return commentLikes; | ||||
|     } | ||||
| 
 | ||||
|     public int getLikesCount() { | ||||
|         return likes; | ||||
|     } | ||||
| 
 | ||||
|     public int getPOYCount() { | ||||
|         return photosOfYou; | ||||
|     } | ||||
| 
 | ||||
|     public int getRequestsCount() { | ||||
|         return requests; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,19 @@ | ||||
| package awais.instagrabber.repositories.responses; | ||||
| 
 | ||||
| public class NotificationImage { | ||||
|     private final String id; | ||||
|     private final String image; | ||||
| 
 | ||||
|     public NotificationImage(final String id, final String image) { | ||||
|         this.id = id; | ||||
|         this.image = image; | ||||
|     } | ||||
| 
 | ||||
|     public String getId() { | ||||
|         return id; | ||||
|     } | ||||
| 
 | ||||
|     public String getImage() { | ||||
|         return image; | ||||
|     } | ||||
| } | ||||
| @ -1,49 +0,0 @@ | ||||
| package awais.instagrabber.repositories.responses; | ||||
| 
 | ||||
| public class UserInfo { | ||||
|     private final long pk; | ||||
|     private final String username, fullName, profilePicUrl, hdProfilePicUrl; | ||||
| 
 | ||||
|     public UserInfo(final long pk, | ||||
|                     final String username, | ||||
|                     final String fullName, | ||||
|                     final String profilePicUrl, | ||||
|                     final String hdProfilePicUrl) { | ||||
|         this.pk = pk; | ||||
|         this.username = username; | ||||
|         this.fullName = fullName; | ||||
|         this.profilePicUrl = profilePicUrl; | ||||
|         this.hdProfilePicUrl = hdProfilePicUrl; | ||||
|     } | ||||
| 
 | ||||
|     public long getPk() { | ||||
|         return pk; | ||||
|     } | ||||
| 
 | ||||
|     public String getUsername() { | ||||
|         return username; | ||||
|     } | ||||
| 
 | ||||
|     public String getFullName() { | ||||
|         return fullName; | ||||
|     } | ||||
| 
 | ||||
|     public String getProfilePicUrl() { | ||||
|         return profilePicUrl; | ||||
|     } | ||||
| 
 | ||||
|     public String getHDProfilePicUrl() { | ||||
|         return hdProfilePicUrl; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         return "UserInfo{" + | ||||
|                 "uid='" + pk + '\'' + | ||||
|                 ", username='" + username + '\'' + | ||||
|                 ", fullName='" + fullName + '\'' + | ||||
|                 ", profilePicUrl='" + profilePicUrl + '\'' + | ||||
|                 ", hdProfilePicUrl='" + hdProfilePicUrl + '\'' + | ||||
|                 '}'; | ||||
|     } | ||||
| } | ||||
| @ -18,8 +18,6 @@ import java.util.List; | ||||
| 
 | ||||
| import awais.instagrabber.R; | ||||
| import awais.instagrabber.activities.MainActivity; | ||||
| import awais.instagrabber.asyncs.GetActivityAsyncTask.NotificationCounts; | ||||
| import awais.instagrabber.asyncs.GetActivityAsyncTask.OnTaskCompleteListener; | ||||
| import awais.instagrabber.utils.Constants; | ||||
| 
 | ||||
| import static awais.instagrabber.utils.Utils.settingsHelper; | ||||
| @ -30,7 +28,7 @@ public class ActivityCheckerService extends Service { | ||||
|     private static final int DELAY_MILLIS = 60000; | ||||
| 
 | ||||
|     private Handler handler; | ||||
|     private OnTaskCompleteListener onTaskCompleteListener; | ||||
|     // private OnTaskCompleteListener onTaskCompleteListener; | ||||
|     private NotificationManagerCompat notificationManager; | ||||
| 
 | ||||
|     private final IBinder binder = new LocalBinder(); | ||||
| @ -50,6 +48,7 @@ public class ActivityCheckerService extends Service { | ||||
|     public void onCreate() { | ||||
|         notificationManager = NotificationManagerCompat.from(getApplicationContext()); | ||||
|         handler = new Handler(); | ||||
|         /* | ||||
|         onTaskCompleteListener = result -> { | ||||
|             // Log.d(TAG, "onTaskCompleteListener: result: " + result); | ||||
|             try { | ||||
| @ -62,20 +61,12 @@ public class ActivityCheckerService extends Service { | ||||
|                 handler.postDelayed(runnable, DELAY_MILLIS); | ||||
|             } | ||||
|         }; | ||||
|          */ | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public IBinder onBind(Intent intent) { | ||||
|         startChecking(); | ||||
|         // Uncomment to test notifications | ||||
|         // final String notificationString = getNotificationString(new NotificationCounts( | ||||
|         //         1, | ||||
|         //         2, | ||||
|         //         3, | ||||
|         //         4, | ||||
|         //         5 | ||||
|         // )); | ||||
|         // showNotification(notificationString); | ||||
|         return binder; | ||||
|     } | ||||
| 
 | ||||
| @ -93,6 +84,7 @@ public class ActivityCheckerService extends Service { | ||||
|         handler.removeCallbacks(runnable); | ||||
|     } | ||||
| 
 | ||||
|     /* | ||||
|     private String getNotificationString(final NotificationCounts result) { | ||||
|         final List<String> list = new ArrayList<>(); | ||||
|         if (result.getRelationshipsCount() != 0) { | ||||
| @ -113,6 +105,7 @@ public class ActivityCheckerService extends Service { | ||||
|         if (list.isEmpty()) return null; | ||||
|         return TextUtils.join(", ", list); | ||||
|     } | ||||
|      */ | ||||
| 
 | ||||
|     private void showNotification(final String notificationString) { | ||||
|         final Notification notification = new NotificationCompat.Builder(this, Constants.ACTIVITY_CHANNEL_ID) | ||||
|  | ||||
| @ -5,12 +5,12 @@ import androidx.lifecycle.ViewModel; | ||||
| 
 | ||||
| import java.util.List; | ||||
| 
 | ||||
| import awais.instagrabber.models.NotificationModel; | ||||
| import awais.instagrabber.repositories.responses.Notification; | ||||
| 
 | ||||
| public class NotificationViewModel extends ViewModel { | ||||
|     private MutableLiveData<List<NotificationModel>> list; | ||||
|     private MutableLiveData<List<Notification>> list; | ||||
| 
 | ||||
|     public MutableLiveData<List<NotificationModel>> getList() { | ||||
|     public MutableLiveData<List<Notification>> getList() { | ||||
|         if (list == null) { | ||||
|             list = new MutableLiveData<>(); | ||||
|         } | ||||
|  | ||||
| @ -9,17 +9,23 @@ 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 java.util.UUID; | ||||
| import java.util.regex.Matcher; | ||||
| import java.util.regex.Pattern; | ||||
| import java.util.stream.Collectors; | ||||
| 
 | ||||
| import awais.instagrabber.BuildConfig; | ||||
| import awais.instagrabber.models.NotificationModel; | ||||
| import awais.instagrabber.models.enums.NotificationType; | ||||
| import awais.instagrabber.repositories.NewsRepository; | ||||
| import awais.instagrabber.repositories.responses.AymlResponse; | ||||
| import awais.instagrabber.repositories.responses.AymlUser; | ||||
| import awais.instagrabber.repositories.responses.NewsInboxResponse; | ||||
| import awais.instagrabber.repositories.responses.Notification; | ||||
| import awais.instagrabber.repositories.responses.NotificationArgs; | ||||
| import awais.instagrabber.repositories.responses.NotificationImage; | ||||
| import awais.instagrabber.repositories.responses.User; | ||||
| import awais.instagrabber.utils.Constants; | ||||
| import awais.instagrabber.utils.Utils; | ||||
| import retrofit2.Call; | ||||
| @ -52,48 +58,31 @@ public class NewsService extends BaseService { | ||||
|     } | ||||
| 
 | ||||
|     public void fetchAppInbox(final boolean markAsSeen, | ||||
|                               final ServiceCallback<List<NotificationModel>> callback) { | ||||
|         final List<NotificationModel> result = new ArrayList<>(); | ||||
|         final Call<String> request = repository.appInbox(appUa, markAsSeen); | ||||
|         request.enqueue(new Callback<String>() { | ||||
|                               final ServiceCallback<List<Notification>> callback) { | ||||
|         final Call<NewsInboxResponse> request = repository.appInbox(appUa, markAsSeen); | ||||
|         request.enqueue(new Callback<NewsInboxResponse>() { | ||||
|             @Override | ||||
|             public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { | ||||
|                 final String body = response.body(); | ||||
|             public void onResponse(@NonNull final Call<NewsInboxResponse> call, @NonNull final Response<NewsInboxResponse> response) { | ||||
|                 final NewsInboxResponse body = response.body(); | ||||
|                 if (body == null) { | ||||
|                     callback.onSuccess(null); | ||||
|                     return; | ||||
|                 } | ||||
|                 try { | ||||
|                     final JSONObject jsonObject = new JSONObject(body); | ||||
|                     final JSONArray oldStories = jsonObject.getJSONArray("old_stories"), | ||||
|                             newStories = jsonObject.getJSONArray("new_stories"); | ||||
| 
 | ||||
|                     for (int j = 0; j < newStories.length(); ++j) { | ||||
|                         final NotificationModel newsItem = parseNewsItem(newStories.getJSONObject(j)); | ||||
|                         if (newsItem != null) result.add(newsItem); | ||||
|                     } | ||||
| 
 | ||||
|                     for (int i = 0; i < oldStories.length(); ++i) { | ||||
|                         final NotificationModel newsItem = parseNewsItem(oldStories.getJSONObject(i)); | ||||
|                         if (newsItem != null) result.add(newsItem); | ||||
|                     } | ||||
| 
 | ||||
|                     callback.onSuccess(result); | ||||
|                 } catch (JSONException e) { | ||||
|                     callback.onFailure(e); | ||||
|                 } | ||||
|                 final List<Notification> result = new ArrayList<>(); | ||||
|                 result.addAll(body.getNewStories()); | ||||
|                 result.addAll(body.getOldStories()); | ||||
|                 callback.onSuccess(result); | ||||
|             } | ||||
| 
 | ||||
|             @Override | ||||
|             public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) { | ||||
|             public void onFailure(@NonNull final Call<NewsInboxResponse> call, @NonNull final Throwable t) { | ||||
|                 callback.onFailure(t); | ||||
|                 // Log.e(TAG, "onFailure: ", t); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     public void fetchWebInbox(final boolean markAsSeen, | ||||
|                               final ServiceCallback<List<NotificationModel>> callback) { | ||||
|     public void fetchWebInbox(final ServiceCallback<List<Notification>> callback) { | ||||
|         final Call<String> request = repository.webInbox(browserUa); | ||||
|         request.enqueue(new Callback<String>() { | ||||
|             @Override | ||||
| @ -104,7 +93,7 @@ public class NewsService extends BaseService { | ||||
|                     return; | ||||
|                 } | ||||
|                 try { | ||||
|                     final List<NotificationModel> result = new ArrayList<>(); | ||||
|                     final List<Notification> result = new ArrayList<>(); | ||||
|                     final JSONObject page = new JSONObject(body) | ||||
|                             .getJSONObject("graphql") | ||||
|                             .getJSONObject("user"); | ||||
| @ -124,16 +113,24 @@ public class NewsService extends BaseService { | ||||
|                             final NotificationType notificationType = NotificationType.valueOfType(type); | ||||
|                             if (notificationType == null) continue; | ||||
|                             final JSONObject user = data.getJSONObject("user"); | ||||
|                             result.add(new NotificationModel( | ||||
|                                     data.getString(Constants.EXTRAS_ID), | ||||
|                                     data.optString("text"), // comments or mentions | ||||
|                                     data.getLong("timestamp"), | ||||
|                                     user.getLong("id"), | ||||
|                                     user.getString("username"), | ||||
|                                     user.getString("profile_pic_url"), | ||||
|                                     !data.isNull("media") ? Long.valueOf(data.getJSONObject("media").getString("id").split("_")[0]) : 0, | ||||
|                                     data.has("media") ? data.getJSONObject("media").getString("thumbnail_src") : null, | ||||
|                                     notificationType)); | ||||
| 
 | ||||
|                             result.add(new Notification( | ||||
|                                     new NotificationArgs( | ||||
|                                             data.optString("text"), | ||||
|                                             null, | ||||
|                                             user.getLong(Constants.EXTRAS_ID), | ||||
|                                             user.getString("profile_pic_url"), | ||||
|                                             data.isNull("media") ? null : Collections.singletonList(new NotificationImage( | ||||
|                                                     data.getJSONObject("media").getString("id"), | ||||
|                                                     data.getJSONObject("media").getString("thumbnail_src") | ||||
|                                             )), | ||||
|                                             data.getLong("timestamp"), | ||||
|                                             user.getString("username"), | ||||
|                                             null | ||||
|                                     ), | ||||
|                                     type, | ||||
|                                     data.getString(Constants.EXTRAS_ID) | ||||
|                             )); | ||||
|                         } | ||||
|                     } | ||||
| 
 | ||||
| @ -144,15 +141,20 @@ public class NewsService extends BaseService { | ||||
|                         for (int i = 0; i < media.length(); ++i) { | ||||
|                             data = media.optJSONObject(i).optJSONObject("node"); | ||||
|                             if (data == null) continue; | ||||
|                             result.add(new NotificationModel( | ||||
|                                     data.getString(Constants.EXTRAS_ID), | ||||
|                                     data.optString("full_name"), | ||||
|                                     0L, | ||||
|                                     data.getLong(Constants.EXTRAS_ID), | ||||
|                                     data.getString("username"), | ||||
|                                     data.getString("profile_pic_url"), | ||||
|                                     0, | ||||
|                                     null, NotificationType.REQUEST)); | ||||
|                             result.add(new Notification( | ||||
|                                     new NotificationArgs( | ||||
|                                             null, | ||||
|                                             null, | ||||
|                                             data.getLong(Constants.EXTRAS_ID), | ||||
|                                             data.getString("profile_pic_url"), | ||||
|                                             null, | ||||
|                                             0L, | ||||
|                                             data.getString("username"), | ||||
|                                             data.optString("full_name") | ||||
|                                     ), | ||||
|                                     "REQUEST", | ||||
|                                     data.getString(Constants.EXTRAS_ID) | ||||
|                             )); | ||||
|                         } | ||||
|                     } | ||||
|                     callback.onSuccess(result); | ||||
| @ -169,40 +171,8 @@ public class NewsService extends BaseService { | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     private NotificationModel parseNewsItem(final JSONObject itemJson) throws JSONException { | ||||
|         if (itemJson == null) return null; | ||||
|         final String type = itemJson.getString("story_type"); | ||||
|         final NotificationType notificationType = NotificationType.valueOfType(type); | ||||
|         if (notificationType == null) { | ||||
|             if (BuildConfig.DEBUG) Log.d("austin_debug", "unhandled news type: " + itemJson); | ||||
|             return null; | ||||
|         } | ||||
|         final JSONObject data = itemJson.getJSONObject("args"); | ||||
|         return new NotificationModel( | ||||
|                 data.getString("tuuid"), | ||||
|                 data.has("text") ? data.getString("text") : cleanRichText(data.optString("rich_text", "")), | ||||
|                 data.getLong("timestamp"), | ||||
|                 data.getLong("profile_id"), | ||||
|                 data.getString("profile_name"), | ||||
|                 data.getString("profile_image"), | ||||
|                 !data.isNull("media") ? Long.valueOf(data.getJSONArray("media").getJSONObject(0).getString("id").split("_")[0]) : 0, | ||||
|                 !data.isNull("media") ? data.getJSONArray("media").getJSONObject(0).getString("image") : null, | ||||
|                 notificationType); | ||||
|     } | ||||
| 
 | ||||
|     private String cleanRichText(final String raw) { | ||||
|         final Matcher matcher = Pattern.compile("\\{[\\p{L}\\d._]+\\|000000\\|1\\|user\\?id=\\d+\\}").matcher(raw); | ||||
|         String result = raw; | ||||
|         while (matcher.find()) { | ||||
|             final String richObject = raw.substring(matcher.start(), matcher.end()); | ||||
|             final String username = richObject.split("\\|")[0].substring(1); | ||||
|             result = result.replace(richObject, username); | ||||
|         } | ||||
|         return result; | ||||
|     } | ||||
| 
 | ||||
|     public void fetchSuggestions(final String csrfToken, | ||||
|                                  final ServiceCallback<List<NotificationModel>> callback) { | ||||
|                                  final ServiceCallback<List<Notification>> callback) { | ||||
|         final Map<String, String> form = new HashMap<>(); | ||||
|         form.put("_uuid", UUID.randomUUID().toString()); | ||||
|         form.put("_csrftoken", csrfToken); | ||||
| @ -210,57 +180,46 @@ public class NewsService extends BaseService { | ||||
|         form.put("device_id", UUID.randomUUID().toString()); | ||||
|         form.put("module", "discover_people"); | ||||
|         form.put("paginate", "false"); | ||||
|         final Call<String> request = repository.getAyml(appUa, form); | ||||
|         request.enqueue(new Callback<String>() { | ||||
|         final Call<AymlResponse> request = repository.getAyml(appUa, form); | ||||
|         request.enqueue(new Callback<AymlResponse>() { | ||||
|             @Override | ||||
|             public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { | ||||
|                 final String body = response.body(); | ||||
|             public void onResponse(@NonNull final Call<AymlResponse> call, @NonNull final Response<AymlResponse> response) { | ||||
|                 final AymlResponse body = response.body(); | ||||
|                 if (body == null) { | ||||
|                     callback.onSuccess(null); | ||||
|                     return; | ||||
|                 } | ||||
|                 try { | ||||
|                     final List<NotificationModel> result = new ArrayList<>(); | ||||
|                     final JSONObject jsonObject = new JSONObject(body); | ||||
|                     final JSONArray oldStories = jsonObject.getJSONObject("suggested_users").getJSONArray("suggestions"), | ||||
|                             newStories = jsonObject.getJSONObject("new_suggested_users").getJSONArray("suggestions"); | ||||
|                 final List<AymlUser> aymlUsers = new ArrayList<>(); | ||||
|                 aymlUsers.addAll(body.getNewSuggestedUsers().getSuggestions()); | ||||
|                 aymlUsers.addAll(body.getSuggestedUsers().getSuggestions()); | ||||
| 
 | ||||
|                     for (int j = 0; j < newStories.length(); ++j) { | ||||
|                         final NotificationModel newsItem = parseAymlItem(newStories.getJSONObject(j)); | ||||
|                         if (newsItem != null) result.add(newsItem); | ||||
|                     } | ||||
| 
 | ||||
|                     for (int i = 0; i < oldStories.length(); ++i) { | ||||
|                         final NotificationModel newsItem = parseAymlItem(oldStories.getJSONObject(i)); | ||||
|                         if (newsItem != null) result.add(newsItem); | ||||
|                     } | ||||
| 
 | ||||
|                     callback.onSuccess(result); | ||||
|                 } catch (JSONException e) { | ||||
|                     callback.onFailure(e); | ||||
|                 } | ||||
|                 final List<Notification> newsItems = aymlUsers.stream() | ||||
|                         .map(i -> { | ||||
|                             final User u = i.getUser(); | ||||
|                             return new Notification( | ||||
|                                     new NotificationArgs( | ||||
|                                             i.getSocialContext(), | ||||
|                                             i.getAlgorithm(), | ||||
|                                             u.getPk(), | ||||
|                                             u.getProfilePicUrl(), | ||||
|                                             null, | ||||
|                                             0L, | ||||
|                                             u.getUsername(), | ||||
|                                             u.getFullName() | ||||
|                                     ), | ||||
|                                     "AYML", | ||||
|                                     i.getUuid() | ||||
|                             ); | ||||
|                         }) | ||||
|                         .collect(Collectors.toList()); | ||||
|                 callback.onSuccess(newsItems); | ||||
|             } | ||||
| 
 | ||||
|             @Override | ||||
|             public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) { | ||||
|             public void onFailure(@NonNull final Call<AymlResponse> call, @NonNull final Throwable t) { | ||||
|                 callback.onFailure(t); | ||||
|                 // Log.e(TAG, "onFailure: ", t); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     private NotificationModel parseAymlItem(final JSONObject itemJson) throws JSONException { | ||||
|         if (itemJson == null) return null; | ||||
|         final JSONObject data = itemJson.getJSONObject("user"); | ||||
|         return new NotificationModel( | ||||
|                 itemJson.getString("uuid"), | ||||
|                 itemJson.getString("social_context"), | ||||
|                 0L, | ||||
|                 data.getLong("pk"), | ||||
|                 data.getString("username"), | ||||
|                 data.getString("profile_pic_url"), | ||||
|                 0, | ||||
|                 data.getString("full_name"), // just borrowing this field | ||||
|                 NotificationType.AYML); | ||||
|     } | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user