mirror of
https://github.com/KokaKiwi/BarInsta
synced 2026-03-05 12:01:35 +00:00
Merge branch 'master' into dm-notifications-enhancements
This commit is contained in:
commit
d6539bddc5
48 changed files with 1000 additions and 792 deletions
|
|
@ -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,45 +46,50 @@ 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);
|
||||
binding.tvComment.setText(args.getText());
|
||||
binding.tvComment.setVisibility(TextUtils.isEmpty(args.getText()) || args.getText().equals(args.getFullName())
|
||||
? View.GONE : View.VISIBLE);
|
||||
binding.tvSubComment.setText(subtext);
|
||||
binding.tvSubComment.setVisibility(model.getType() == NotificationType.AYML ? View.VISIBLE : View.GONE);
|
||||
} else if (text != -1) {
|
||||
binding.tvComment.setText(text);
|
||||
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.isVerified.setVisibility(args.isVerified() ? View.VISIBLE : View.GONE);
|
||||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -366,7 +366,7 @@ public final class DirectInboxItemViewHolder extends RecyclerView.ViewHolder {
|
|||
}
|
||||
}
|
||||
binding.unread.setVisibility(read ? View.GONE : View.VISIBLE);
|
||||
binding.threadTitle.setTypeface(binding.threadTitle.getTypeface(), read ? Typeface.NORMAL : Typeface.BOLD);
|
||||
binding.subtitle.setTypeface(binding.subtitle.getTypeface(), read ? Typeface.NORMAL : Typeface.BOLD);
|
||||
binding.threadTitle.setTypeface(null, read ? Typeface.NORMAL : Typeface.BOLD);
|
||||
binding.subtitle.setTypeface(null, read ? Typeface.NORMAL : Typeface.BOLD);
|
||||
}
|
||||
}
|
||||
|
|
@ -115,7 +115,8 @@ public final class CommentsFetcher extends AsyncTask<Void, Void, List<CommentMod
|
|||
owner.getString("profile_pic_url"),
|
||||
null,
|
||||
new FriendshipStatus(false, false, false, false, false, false, false, false, false, false),
|
||||
false, false, false, false, false, null, null, 0, 0, 0, 0, null, null, 0, null, null);
|
||||
false, false, false, false, false, null, null, 0, 0, 0, 0, null, null, 0, null, null, null,
|
||||
null, null);
|
||||
final JSONObject likedBy = childComment.optJSONObject("edge_liked_by");
|
||||
commentModels.add(new CommentModel(childComment.getString(Constants.EXTRAS_ID),
|
||||
childComment.getString("text"),
|
||||
|
|
@ -193,7 +194,8 @@ public final class CommentsFetcher extends AsyncTask<Void, Void, List<CommentMod
|
|||
null,
|
||||
new FriendshipStatus(false, false, false, false, false, false, false, false, false, false),
|
||||
owner.optBoolean("is_verified"),
|
||||
false, false, false, false, null, null, 0, 0, 0, 0, null, null, 0, null, null);
|
||||
false, false, false, false, null, null, 0, 0, 0, 0, null, null, 0, null, null, null, null,
|
||||
null);
|
||||
final JSONObject likedBy = comment.optJSONObject("edge_liked_by");
|
||||
final String commentId = comment.getString(Constants.EXTRAS_ID);
|
||||
final CommentModel commentModel = new CommentModel(commentId,
|
||||
|
|
@ -235,7 +237,7 @@ public final class CommentsFetcher extends AsyncTask<Void, Void, List<CommentMod
|
|||
null,
|
||||
new FriendshipStatus(false, false, false, false, false, false, false, false, false, false),
|
||||
tempJsonObject.optBoolean("is_verified"), false, false, false, false, null, null, 0, 0, 0, 0, null, null, 0,
|
||||
null, null);
|
||||
null, null, null, null, null);
|
||||
|
||||
tempJsonObject = childComment.optJSONObject("edge_liked_by");
|
||||
childCommentModels.add(new CommentModel(childComment.getString(Constants.EXTRAS_ID),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,51 +0,0 @@
|
|||
package awais.instagrabber.asyncs;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
import awais.instagrabber.models.StoryModel;
|
||||
import awais.instagrabber.utils.NetworkUtils;
|
||||
|
||||
public class SeenAction extends AsyncTask<Void, Void, Void> {
|
||||
private static final String TAG = "SeenAction";
|
||||
|
||||
private final String cookie;
|
||||
private final StoryModel storyModel;
|
||||
|
||||
public SeenAction(final String cookie, final StoryModel storyModel) {
|
||||
this.cookie = cookie;
|
||||
this.storyModel = storyModel;
|
||||
}
|
||||
|
||||
protected Void doInBackground(Void... voids) {
|
||||
final String url = "https://www.instagram.com/stories/reel/seen";
|
||||
try {
|
||||
final String urlParameters = "reelMediaId=" + storyModel.getStoryMediaId().split("_")[0]
|
||||
+ "&reelMediaOwnerId=" + storyModel.getUserId()
|
||||
+ "&reelId=" + storyModel.getUserId()
|
||||
+ "&reelMediaTakenAt=" + storyModel.getTimestamp()
|
||||
+ "&viewSeenAt=" + storyModel.getTimestamp();
|
||||
final HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection();
|
||||
urlConnection.setRequestMethod("POST");
|
||||
urlConnection.setUseCaches(false);
|
||||
urlConnection.setRequestProperty("x-csrftoken", cookie.split("csrftoken=")[1].split(";")[0]);
|
||||
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
||||
urlConnection.setRequestProperty("Content-Length", Integer.toString(urlParameters.getBytes().length));
|
||||
urlConnection.setDoOutput(true);
|
||||
DataOutputStream wr = new DataOutputStream(urlConnection.getOutputStream());
|
||||
wr.writeBytes(urlParameters);
|
||||
wr.flush();
|
||||
wr.close();
|
||||
urlConnection.connect();
|
||||
Log.d(TAG, urlConnection.getResponseCode() + " " + NetworkUtils.readFromConnection(urlConnection));
|
||||
urlConnection.disconnect();
|
||||
} catch (Throwable ex) {
|
||||
Log.e(TAG, "Error", ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -276,7 +276,7 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||
super.onCreate(savedInstanceState);
|
||||
fragmentActivity = (MainActivity) requireActivity();
|
||||
tagsService = TagsService.getInstance();
|
||||
storiesService = StoriesService.getInstance();
|
||||
storiesService = StoriesService.getInstance(null, 0L, null);
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -270,7 +270,7 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR
|
|||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
fragmentActivity = (MainActivity) requireActivity();
|
||||
storiesService = StoriesService.getInstance();
|
||||
storiesService = StoriesService.getInstance(null, 0L, null);
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@ import android.widget.Toast;
|
|||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
|
@ -33,11 +35,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;
|
||||
|
|
@ -53,16 +57,36 @@ import static awais.instagrabber.utils.Utils.settingsHelper;
|
|||
public final class NotificationsViewerFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
|
||||
private static final String TAG = "NotificationsViewer";
|
||||
|
||||
private AppCompatActivity fragmentActivity;
|
||||
private FragmentNotificationsViewerBinding binding;
|
||||
private SwipeRefreshLayout root;
|
||||
private boolean shouldRefresh = true;
|
||||
private NotificationViewModel notificationViewModel;
|
||||
private FriendshipService friendshipService;
|
||||
private MediaService mediaService;
|
||||
private String csrfToken;
|
||||
private NewsService newsService;
|
||||
private String csrfToken, deviceUuid;
|
||||
private String type;
|
||||
private long targetId;
|
||||
private Context context;
|
||||
|
||||
private final ServiceCallback<List<Notification>> cb = new ServiceCallback<List<Notification>>() {
|
||||
@Override
|
||||
public void onSuccess(final List<Notification> notificationModels) {
|
||||
binding.swipeRefreshLayout.setRefreshing(false);
|
||||
notificationViewModel.getList().postValue(notificationModels);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(final Throwable t) {
|
||||
try {
|
||||
binding.swipeRefreshLayout.setRefreshing(false);
|
||||
Toast.makeText(getContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
catch(Throwable e) {}
|
||||
}
|
||||
};
|
||||
|
||||
private final OnNotificationClickListener clickListener = new OnNotificationClickListener() {
|
||||
@Override
|
||||
public void onProfileClick(final String username) {
|
||||
|
|
@ -70,14 +94,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 +123,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 +139,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 +160,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 +177,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();
|
||||
|
|
@ -174,6 +203,7 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
|
|||
@Override
|
||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
fragmentActivity = (AppCompatActivity) requireActivity();
|
||||
context = getContext();
|
||||
if (context == null) return;
|
||||
NotificationManagerCompat.from(context.getApplicationContext()).cancel(Constants.ACTIVITY_NOTIFICATION_ID);
|
||||
|
|
@ -183,9 +213,10 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
|
|||
}
|
||||
mediaService = MediaService.getInstance(null, null, 0);
|
||||
final long userId = CookieUtils.getUserIdFromCookie(cookie);
|
||||
final String deviceUuid = Utils.settingsHelper.getString(Constants.DEVICE_UUID);
|
||||
deviceUuid = Utils.settingsHelper.getString(Constants.DEVICE_UUID);
|
||||
csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie);
|
||||
friendshipService = FriendshipService.getInstance(deviceUuid, csrfToken, userId);
|
||||
newsService = NewsService.getInstance();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
|
@ -210,6 +241,7 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
|
|||
private void init() {
|
||||
final NotificationsViewerFragmentArgs fragmentArgs = NotificationsViewerFragmentArgs.fromBundle(getArguments());
|
||||
type = fragmentArgs.getType();
|
||||
targetId = fragmentArgs.getTargetId();
|
||||
final Context context = getContext();
|
||||
CookieUtils.setupCookies(settingsHelper.getString(Constants.COOKIE));
|
||||
binding.swipeRefreshLayout.setOnRefreshListener(this);
|
||||
|
|
@ -224,11 +256,13 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
|
|||
@Override
|
||||
public void onRefresh() {
|
||||
binding.swipeRefreshLayout.setRefreshing(true);
|
||||
final ActionBar actionBar = fragmentActivity.getSupportActionBar();
|
||||
switch (type) {
|
||||
case "notif":
|
||||
new NotificationsFetcher(true, new FetchListener<List<NotificationModel>>() {
|
||||
if (actionBar != null) actionBar.setTitle(R.string.action_notif);
|
||||
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);
|
||||
}
|
||||
|
|
@ -244,23 +278,12 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
|
|||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
break;
|
||||
case "ayml":
|
||||
final NewsService newsService = NewsService.getInstance();
|
||||
newsService.fetchSuggestions(csrfToken, new ServiceCallback<List<NotificationModel>>() {
|
||||
@Override
|
||||
public void onSuccess(final List<NotificationModel> notificationModels) {
|
||||
binding.swipeRefreshLayout.setRefreshing(false);
|
||||
notificationViewModel.getList().postValue(notificationModels);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(final Throwable t) {
|
||||
try {
|
||||
binding.swipeRefreshLayout.setRefreshing(false);
|
||||
Toast.makeText(getContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
catch(Throwable e) {}
|
||||
}
|
||||
});
|
||||
if (actionBar != null) actionBar.setTitle(R.string.action_ayml);
|
||||
newsService.fetchSuggestions(csrfToken, deviceUuid, cb);
|
||||
break;
|
||||
case "chaining":
|
||||
if (actionBar != null) actionBar.setTitle(R.string.action_ayml);
|
||||
newsService.fetchChaining(targetId, cb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ public final class StoryListViewerFragment extends Fragment implements SwipeRefr
|
|||
fragmentActivity = (AppCompatActivity) requireActivity();
|
||||
context = getContext();
|
||||
if (context == null) return;
|
||||
storiesService = StoriesService.getInstance();
|
||||
storiesService = StoriesService.getInstance(null, 0L, null);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
|
|
|||
|
|
@ -71,7 +71,6 @@ import awais.instagrabber.R;
|
|||
import awais.instagrabber.adapters.StoriesAdapter;
|
||||
import awais.instagrabber.asyncs.CreateThreadAction;
|
||||
import awais.instagrabber.asyncs.PostFetcher;
|
||||
import awais.instagrabber.asyncs.SeenAction;
|
||||
import awais.instagrabber.customviews.helpers.SwipeGestureListener;
|
||||
import awais.instagrabber.databinding.FragmentStoryViewerBinding;
|
||||
import awais.instagrabber.fragments.main.ProfileFragmentDirections;
|
||||
|
|
@ -151,17 +150,16 @@ public class StoryViewerFragment extends Fragment {
|
|||
private DirectMessagesService directMessagesService;
|
||||
|
||||
private final String cookie = settingsHelper.getString(Constants.COOKIE);
|
||||
private final String csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie);
|
||||
private final long userIdFromCookie = CookieUtils.getUserIdFromCookie(cookie);
|
||||
private final String deviceId = settingsHelper.getString(Constants.DEVICE_UUID);
|
||||
private StoryViewerOptions options;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
final String csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie);
|
||||
final long userIdFromCookie = CookieUtils.getUserIdFromCookie(cookie);
|
||||
final String deviceId = settingsHelper.getString(Constants.DEVICE_UUID);
|
||||
fragmentActivity = (AppCompatActivity) requireActivity();
|
||||
storiesService = StoriesService.getInstance();
|
||||
if (csrfToken == null) return;
|
||||
storiesService = StoriesService.getInstance(csrfToken, userIdFromCookie, deviceId);
|
||||
directMessagesService = DirectMessagesService.getInstance(csrfToken, userIdFromCookie, deviceId);
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
|
@ -478,36 +476,32 @@ public class StoryViewerFragment extends Fragment {
|
|||
poll.getLeftChoice() + " (" + poll.getLeftCount() + ")",
|
||||
poll.getRightChoice() + " (" + poll.getRightCount() + ")"
|
||||
}), (d, w) -> {
|
||||
if (!TextUtils.isEmpty(cookie)) {
|
||||
sticking = true;
|
||||
storiesService.respondToPoll(
|
||||
currentStory.getStoryMediaId().split("_")[0],
|
||||
poll.getId(),
|
||||
w,
|
||||
userIdFromCookie,
|
||||
csrfToken,
|
||||
new ServiceCallback<StoryStickerResponse>() {
|
||||
@Override
|
||||
public void onSuccess(final StoryStickerResponse result) {
|
||||
sticking = false;
|
||||
try {
|
||||
poll.setMyChoice(w);
|
||||
Toast.makeText(context, R.string.votef_story_poll, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
catch (Exception ignored) {}
|
||||
sticking = true;
|
||||
storiesService.respondToPoll(
|
||||
currentStory.getStoryMediaId().split("_")[0],
|
||||
poll.getId(),
|
||||
w,
|
||||
new ServiceCallback<StoryStickerResponse>() {
|
||||
@Override
|
||||
public void onSuccess(final StoryStickerResponse result) {
|
||||
sticking = false;
|
||||
try {
|
||||
poll.setMyChoice(w);
|
||||
Toast.makeText(context, R.string.votef_story_poll, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
catch (Exception ignored) {}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(final Throwable t) {
|
||||
sticking = false;
|
||||
Log.e(TAG, "Error responding", t);
|
||||
try {
|
||||
Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
catch (Exception ignored) {}
|
||||
@Override
|
||||
public void onFailure(final Throwable t) {
|
||||
sticking = false;
|
||||
Log.e(TAG, "Error responding", t);
|
||||
try {
|
||||
Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception ignored) {}
|
||||
}
|
||||
});
|
||||
})
|
||||
.setPositiveButton(R.string.cancel, null)
|
||||
.show();
|
||||
|
|
@ -525,8 +519,6 @@ public class StoryViewerFragment extends Fragment {
|
|||
currentStory.getStoryMediaId().split("_")[0],
|
||||
question.getId(),
|
||||
input.getText().toString(),
|
||||
userIdFromCookie,
|
||||
csrfToken,
|
||||
new ServiceCallback<StoryStickerResponse>() {
|
||||
@Override
|
||||
public void onSuccess(final StoryStickerResponse result) {
|
||||
|
|
@ -565,14 +557,12 @@ public class StoryViewerFragment extends Fragment {
|
|||
new AlertDialog.Builder(context)
|
||||
.setTitle(quiz.getMyChoice() > -1 ? getString(R.string.story_quizzed) : quiz.getQuestion())
|
||||
.setAdapter(new ArrayAdapter<>(context, android.R.layout.simple_list_item_1, choices), (d, w) -> {
|
||||
if (quiz.getMyChoice() == -1 && !TextUtils.isEmpty(cookie)) {
|
||||
if (quiz.getMyChoice() == -1) {
|
||||
sticking = true;
|
||||
storiesService.respondToQuiz(
|
||||
currentStory.getStoryMediaId().split("_")[0],
|
||||
quiz.getId(),
|
||||
w,
|
||||
userIdFromCookie,
|
||||
csrfToken,
|
||||
new ServiceCallback<StoryStickerResponse>() {
|
||||
@Override
|
||||
public void onSuccess(final StoryStickerResponse result) {
|
||||
|
|
@ -643,8 +633,6 @@ public class StoryViewerFragment extends Fragment {
|
|||
currentStory.getStoryMediaId().split("_")[0],
|
||||
slider.getId(),
|
||||
sliderValue,
|
||||
userIdFromCookie,
|
||||
csrfToken,
|
||||
new ServiceCallback<StoryStickerResponse>() {
|
||||
@Override
|
||||
public void onSuccess(final StoryStickerResponse result) {
|
||||
|
|
@ -868,7 +856,7 @@ public class StoryViewerFragment extends Fragment {
|
|||
binding.poll.setTag(poll);
|
||||
|
||||
question = currentStory.getQuestion();
|
||||
binding.answer.setVisibility((question != null && !TextUtils.isEmpty(cookie)) ? View.VISIBLE : View.GONE);
|
||||
binding.answer.setVisibility((question != null) ? View.VISIBLE : View.GONE);
|
||||
binding.answer.setTag(question);
|
||||
|
||||
mentions = currentStory.getMentions();
|
||||
|
|
@ -909,7 +897,11 @@ public class StoryViewerFragment extends Fragment {
|
|||
actionBar.setSubtitle(Utils.datetimeParser.format(new Date(currentStory.getTimestamp() * 1000L)));
|
||||
}
|
||||
|
||||
if (settingsHelper.getBoolean(MARK_AS_SEEN)) new SeenAction(cookie, currentStory).execute();
|
||||
if (settingsHelper.getBoolean(MARK_AS_SEEN))
|
||||
storiesService.seen(currentStory.getStoryMediaId(),
|
||||
currentStory.getTimestamp(),
|
||||
System.currentTimeMillis() / 1000,
|
||||
null);
|
||||
}
|
||||
|
||||
private void downloadStory() {
|
||||
|
|
@ -947,7 +939,7 @@ public class StoryViewerFragment extends Fragment {
|
|||
if (menuDownload != null) {
|
||||
menuDownload.setVisible(true);
|
||||
}
|
||||
if (currentStory.canReply() && menuDm != null && !TextUtils.isEmpty(cookie)) {
|
||||
if (currentStory.canReply() && menuDm != null) {
|
||||
menuDm.setVisible(true);
|
||||
}
|
||||
binding.progressView.setVisibility(View.GONE);
|
||||
|
|
@ -980,7 +972,7 @@ public class StoryViewerFragment extends Fragment {
|
|||
@NonNull final LoadEventInfo loadEventInfo,
|
||||
@NonNull final MediaLoadData mediaLoadData) {
|
||||
if (menuDownload != null) menuDownload.setVisible(true);
|
||||
if (currentStory.canReply() && menuDm != null && !TextUtils.isEmpty(cookie))
|
||||
if (currentStory.canReply() && menuDm != null)
|
||||
menuDm.setVisible(true);
|
||||
binding.progressView.setVisibility(View.GONE);
|
||||
}
|
||||
|
|
@ -991,7 +983,7 @@ public class StoryViewerFragment extends Fragment {
|
|||
@NonNull final LoadEventInfo loadEventInfo,
|
||||
@NonNull final MediaLoadData mediaLoadData) {
|
||||
if (menuDownload != null) menuDownload.setVisible(true);
|
||||
if (currentStory.canReply() && menuDm != null && !TextUtils.isEmpty(cookie))
|
||||
if (currentStory.canReply() && menuDm != null)
|
||||
menuDm.setVisible(true);
|
||||
binding.progressView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -259,7 +259,7 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre
|
|||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
fragmentActivity = (MainActivity) requireActivity();
|
||||
storiesService = StoriesService.getInstance();
|
||||
storiesService = StoriesService.getInstance(null, 0L, null);
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ import awais.instagrabber.repositories.responses.FriendshipRestrictResponse;
|
|||
import awais.instagrabber.repositories.responses.FriendshipStatus;
|
||||
import awais.instagrabber.repositories.responses.Media;
|
||||
import awais.instagrabber.repositories.responses.User;
|
||||
import awais.instagrabber.repositories.responses.UserProfileContextLink;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.CookieUtils;
|
||||
import awais.instagrabber.utils.DownloadUtils;
|
||||
|
|
@ -123,6 +124,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||
private HighlightsViewModel highlightsViewModel;
|
||||
private MenuItem blockMenuItem;
|
||||
private MenuItem restrictMenuItem;
|
||||
private MenuItem chainingMenuItem;
|
||||
private boolean highlightsFetching;
|
||||
private boolean postsSetupDone = false;
|
||||
private Set<Media> selectedFeedModels;
|
||||
|
|
@ -306,7 +308,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||
final String csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie);
|
||||
fragmentActivity = (MainActivity) requireActivity();
|
||||
friendshipService = isLoggedIn ? FriendshipService.getInstance(deviceUuid, csrfToken, userId) : null;
|
||||
storiesService = isLoggedIn ? StoriesService.getInstance() : null;
|
||||
storiesService = isLoggedIn ? StoriesService.getInstance(null, 0L, null) : null;
|
||||
mediaService = isLoggedIn ? MediaService.getInstance(null, null, 0) : null;
|
||||
accountRepository = AccountRepository.getInstance(AccountDataSource.getInstance(getContext()));
|
||||
favoriteRepository = FavoriteRepository.getInstance(FavoriteDataSource.getInstance(getContext()));
|
||||
|
|
@ -362,11 +364,31 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||
inflater.inflate(R.menu.profile_menu, menu);
|
||||
blockMenuItem = menu.findItem(R.id.block);
|
||||
if (blockMenuItem != null) {
|
||||
blockMenuItem.setVisible(false);
|
||||
if (profileModel != null) {
|
||||
blockMenuItem.setVisible(!Objects.equals(profileModel.getPk(), CookieUtils.getUserIdFromCookie(cookie)));
|
||||
blockMenuItem.setTitle(profileModel.getFriendshipStatus().isBlocking() ? R.string.unblock : R.string.block);
|
||||
} else {
|
||||
blockMenuItem.setVisible(false);
|
||||
}
|
||||
}
|
||||
restrictMenuItem = menu.findItem(R.id.restrict);
|
||||
if (restrictMenuItem != null) {
|
||||
restrictMenuItem.setVisible(false);
|
||||
if (profileModel != null) {
|
||||
restrictMenuItem.setVisible(!Objects.equals(profileModel.getPk(), CookieUtils.getUserIdFromCookie(cookie)));
|
||||
restrictMenuItem.setTitle(profileModel.getFriendshipStatus().isRestricted() ? R.string.unrestrict : R.string.restrict);
|
||||
}
|
||||
else {
|
||||
restrictMenuItem.setVisible(false);
|
||||
}
|
||||
}
|
||||
chainingMenuItem = menu.findItem(R.id.chaining);
|
||||
if (chainingMenuItem != null) {
|
||||
if (profileModel != null) {
|
||||
chainingMenuItem.setVisible(!Objects.equals(profileModel.getPk(), CookieUtils.getUserIdFromCookie(cookie)));
|
||||
}
|
||||
else {
|
||||
chainingMenuItem.setVisible(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -431,11 +453,18 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||
});
|
||||
return true;
|
||||
}
|
||||
if (item.getItemId() == R.id.chaining) {
|
||||
if (!isLoggedIn) return false;
|
||||
final NavDirections navDirections = ProfileFragmentDirections.actionGlobalNotificationsViewerFragment("chaining", profileModel.getPk());
|
||||
NavHostFragment.findNavController(this).navigate(navDirections);
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
profileDetailsBinding.countsBarrier.setVisibility(View.GONE);
|
||||
profileDetailsBinding.mainProfileImage.setVisibility(View.INVISIBLE);
|
||||
fetchProfileDetails();
|
||||
}
|
||||
|
|
@ -653,6 +682,8 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||
profileDetailsBinding.mainProfileImage.setImageURI(profileModel.getProfilePicUrl());
|
||||
profileDetailsBinding.mainProfileImage.setVisibility(View.VISIBLE);
|
||||
|
||||
profileDetailsBinding.countsBarrier.setVisibility(View.VISIBLE);
|
||||
|
||||
final long followersCount = profileModel.getFollowerCount();
|
||||
final long followingCount = profileModel.getFollowingCount();
|
||||
|
||||
|
|
@ -691,7 +722,11 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||
: profileModel.getFullName());
|
||||
|
||||
final String biography = profileModel.getBiography();
|
||||
if (!TextUtils.isEmpty(biography)) {
|
||||
if (TextUtils.isEmpty(biography)) {
|
||||
profileDetailsBinding.mainBiography.setVisibility(View.GONE);
|
||||
}
|
||||
else {
|
||||
profileDetailsBinding.mainBiography.setVisibility(View.VISIBLE);
|
||||
profileDetailsBinding.mainBiography.setText(biography);
|
||||
profileDetailsBinding.mainBiography.addOnHashtagListener(autoLinkItem -> {
|
||||
final NavController navController = NavHostFragment.findNavController(this);
|
||||
|
|
@ -756,6 +791,27 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
String profileContext = profileModel.getProfileContext();
|
||||
if (TextUtils.isEmpty(profileContext)) {
|
||||
profileDetailsBinding.profileContext.setVisibility(View.GONE);
|
||||
}
|
||||
else {
|
||||
profileDetailsBinding.profileContext.setVisibility(View.VISIBLE);
|
||||
final List<UserProfileContextLink> userProfileContextLinks = profileModel.getProfileContextLinks();
|
||||
for (int i = 0; i < userProfileContextLinks.size(); i++) {
|
||||
final UserProfileContextLink link = userProfileContextLinks.get(i);
|
||||
if (link.getUsername() != null)
|
||||
profileContext = profileContext.substring(0, link.getStart() + i)
|
||||
+ "@" + profileContext.substring(link.getStart() + i);
|
||||
}
|
||||
profileDetailsBinding.profileContext.setText(profileContext);
|
||||
profileDetailsBinding.profileContext.addOnMentionClickListener(autoLinkItem -> {
|
||||
final String originalText = autoLinkItem.getOriginalText().trim();
|
||||
navigateToProfile(originalText);
|
||||
});
|
||||
}
|
||||
|
||||
final String url = profileModel.getExternalUrl();
|
||||
if (TextUtils.isEmpty(url)) {
|
||||
profileDetailsBinding.mainUrl.setVisibility(View.GONE);
|
||||
|
|
@ -830,13 +886,13 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||
}
|
||||
if (profileModel.getFriendshipStatus().isFollowing()) {
|
||||
profileDetailsBinding.btnFollow.setText(R.string.unfollow);
|
||||
profileDetailsBinding.btnFollow.setIconResource(R.drawable.ic_outline_person_add_disabled_24);
|
||||
profileDetailsBinding.btnFollow.setChipIconResource(R.drawable.ic_outline_person_add_disabled_24);
|
||||
} else if (profileModel.getFriendshipStatus().isOutgoingRequest()) {
|
||||
profileDetailsBinding.btnFollow.setText(R.string.cancel);
|
||||
profileDetailsBinding.btnFollow.setIconResource(R.drawable.ic_outline_person_add_disabled_24);
|
||||
profileDetailsBinding.btnFollow.setChipIconResource(R.drawable.ic_outline_person_add_disabled_24);
|
||||
} else {
|
||||
profileDetailsBinding.btnFollow.setText(R.string.follow);
|
||||
profileDetailsBinding.btnFollow.setIconResource(R.drawable.ic_outline_person_add_24);
|
||||
profileDetailsBinding.btnFollow.setChipIconResource(R.drawable.ic_outline_person_add_24);
|
||||
}
|
||||
if (restrictMenuItem != null) {
|
||||
restrictMenuItem.setVisible(true);
|
||||
|
|
@ -854,15 +910,10 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||
blockMenuItem.setTitle(R.string.block);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!isReallyPrivate() && restrictMenuItem != null) {
|
||||
restrictMenuItem.setVisible(true);
|
||||
if (profileModel.getFriendshipStatus().isRestricted()) {
|
||||
restrictMenuItem.setTitle(R.string.unrestrict);
|
||||
} else {
|
||||
restrictMenuItem.setTitle(R.string.restrict);
|
||||
if (chainingMenuItem != null && !Objects.equals(profileId, myId)) {
|
||||
chainingMenuItem.setVisible(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -134,12 +134,12 @@ public class MorePreferencesFragment extends BasePreferencesFragment {
|
|||
screen.addPreference(getDivider(context));
|
||||
if (isLoggedIn) {
|
||||
screen.addPreference(getPreference(R.string.action_notif, R.drawable.ic_not_liked, preference -> {
|
||||
final NavDirections navDirections = MorePreferencesFragmentDirections.actionGlobalNotificationsViewerFragment("notif");
|
||||
final NavDirections navDirections = MorePreferencesFragmentDirections.actionGlobalNotificationsViewerFragment("notif", 0l);
|
||||
NavHostFragment.findNavController(this).navigate(navDirections);
|
||||
return true;
|
||||
}));
|
||||
screen.addPreference(getPreference(R.string.action_ayml, R.drawable.ic_suggested_users, preference -> {
|
||||
final NavDirections navDirections = MorePreferencesFragmentDirections.actionGlobalNotificationsViewerFragment("ayml");
|
||||
final NavDirections navDirections = MorePreferencesFragmentDirections.actionGlobalNotificationsViewerFragment("ayml", 0l);
|
||||
NavHostFragment.findNavController(this).navigate(navDirections);
|
||||
return true;
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -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,9 @@ package awais.instagrabber.repositories;
|
|||
|
||||
import java.util.Map;
|
||||
|
||||
import awais.instagrabber.repositories.responses.AymlResponse;
|
||||
import awais.instagrabber.repositories.responses.NewsInboxResponse;
|
||||
import awais.instagrabber.repositories.responses.UserSearchResponse;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.http.FieldMap;
|
||||
import retrofit2.http.FormUrlEncoded;
|
||||
|
|
@ -16,9 +19,12 @@ 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);
|
||||
|
||||
@GET("/api/v1/discover/chaining/")
|
||||
Call<UserSearchResponse> getChaining(@Header("User-Agent") String userAgent, @Query(value = "target_id") long targetId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,4 +36,8 @@ public interface StoriesRepository {
|
|||
@Path("action") String action,
|
||||
// story_poll_vote, story_question_response, story_slider_vote, story_quiz_answer
|
||||
@FieldMap Map<String, String> form);
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("/api/v2/media/seen/")
|
||||
Call<String> seen(@QueryMap Map<String, String> queryParams, @FieldMap 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,93 @@
|
|||
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
|
||||
private final boolean isVerified; // mostly for AYML, not sure about notif
|
||||
|
||||
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,
|
||||
final boolean isVerified) {
|
||||
this.text = text;
|
||||
this.richText = richText;
|
||||
this.profileId = profileId;
|
||||
this.profileImage = profileImage;
|
||||
this.media = media;
|
||||
this.timestamp = timestamp;
|
||||
this.profileName = profileName;
|
||||
this.fullName = fullName;
|
||||
this.isVerified = isVerified;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public boolean isVerified() {
|
||||
return isVerified;
|
||||
}
|
||||
|
||||
@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,6 +1,7 @@
|
|||
package awais.instagrabber.repositories.responses;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class User implements Serializable {
|
||||
|
|
@ -27,7 +28,9 @@ public class User implements Serializable {
|
|||
private final long usertagsCount;
|
||||
private final String publicEmail;
|
||||
private final HdProfilePicUrlInfo hdProfilePicUrlInfo;
|
||||
|
||||
private final String profileContext;
|
||||
private final List<UserProfileContextLink> profileContextLinksWithUserIds;
|
||||
private final String socialContext;
|
||||
|
||||
public User(final long pk,
|
||||
final String username,
|
||||
|
|
@ -51,7 +54,10 @@ public class User implements Serializable {
|
|||
final String externalUrl,
|
||||
final long usertagsCount,
|
||||
final String publicEmail,
|
||||
final HdProfilePicUrlInfo hdProfilePicUrlInfo) {
|
||||
final HdProfilePicUrlInfo hdProfilePicUrlInfo,
|
||||
final String profileContext,
|
||||
final List<UserProfileContextLink> profileContextLinksWithUserIds,
|
||||
final String socialContext) {
|
||||
this.pk = pk;
|
||||
this.username = username;
|
||||
this.fullName = fullName;
|
||||
|
|
@ -75,6 +81,9 @@ public class User implements Serializable {
|
|||
this.usertagsCount = usertagsCount;
|
||||
this.publicEmail = publicEmail;
|
||||
this.hdProfilePicUrlInfo = hdProfilePicUrlInfo;
|
||||
this.profileContext = profileContext;
|
||||
this.profileContextLinksWithUserIds = profileContextLinksWithUserIds;
|
||||
this.socialContext = socialContext;
|
||||
}
|
||||
|
||||
public long getPk() {
|
||||
|
|
@ -173,46 +182,17 @@ public class User implements Serializable {
|
|||
return publicEmail;
|
||||
}
|
||||
|
||||
// public boolean isReallyPrivate() {
|
||||
// final FriendshipStatus friendshipStatus = getFriendshipStatus();
|
||||
// !user.optBoolean("followed_by_viewer") && (id != uid && isPrivate)
|
||||
// }
|
||||
public String getProfileContext() {
|
||||
return profileContext;
|
||||
}
|
||||
|
||||
// public static User fromProfileModel(final ProfileModel profileModel) {
|
||||
// return new User(
|
||||
// Long.parseLong(profileModel.getId()),
|
||||
// profileModel.getUsername(),
|
||||
// profileModel.getName(),
|
||||
// profileModel.isPrivate(),
|
||||
// profileModel.getSdProfilePic(),
|
||||
// null,
|
||||
// new FriendshipStatus(
|
||||
// profileModel.isFollowing(),
|
||||
// false,
|
||||
// profileModel.isBlocked(),
|
||||
// false,
|
||||
// profileModel.isPrivate(),
|
||||
// false,
|
||||
// profileModel.isRequested(),
|
||||
// false,
|
||||
// profileModel.isRestricted(),
|
||||
// false),
|
||||
// profileModel.isVerified(),
|
||||
// false,
|
||||
// false,
|
||||
// false,
|
||||
// false,
|
||||
// null,
|
||||
// null,
|
||||
// profileModel.getPostCount(),
|
||||
// profileModel.getFollowersCount(),
|
||||
// profileModel.getFollowingCount(),
|
||||
// 0,
|
||||
// profileModel.getBiography(),
|
||||
// profileModel.getUrl(),
|
||||
// 0,
|
||||
// null);
|
||||
// }
|
||||
public String getSocialContext() {
|
||||
return socialContext;
|
||||
}
|
||||
|
||||
public List<UserProfileContextLink> getProfileContextLinks() {
|
||||
return profileContextLinksWithUserIds;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -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 + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package awais.instagrabber.repositories.responses;
|
||||
|
||||
public class UserProfileContextLink {
|
||||
private final String username;
|
||||
private final int start;
|
||||
private final int end;
|
||||
|
||||
public UserProfileContextLink(final String username, final int start, final int end) {
|
||||
this.username = username;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public int getStart() {
|
||||
return start;
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -781,7 +781,8 @@ public final class ResponseBodyUtils {
|
|||
null,
|
||||
friendshipStatus,
|
||||
owner.optBoolean("is_verified"),
|
||||
false, false, false, false, null, null, 0, 0, 0, 0, null, null, 0, null, null);
|
||||
false, false, false, false, null, null, 0, 0, 0, 0, null, null, 0, null, null,
|
||||
null, null, null);
|
||||
}
|
||||
final String id = feedItem.getString(Constants.EXTRAS_ID);
|
||||
final ImageVersions2 imageVersions2 = new ImageVersions2(
|
||||
|
|
|
|||
|
|
@ -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<>();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -243,6 +243,9 @@ public class GraphQLService extends BaseService {
|
|||
null,
|
||||
0,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
));
|
||||
// userModels.add(new ProfileModel(userObject.optBoolean("is_private"),
|
||||
|
|
@ -334,6 +337,9 @@ public class GraphQLService extends BaseService {
|
|||
url,
|
||||
0,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null));
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "onResponse", e);
|
||||
|
|
|
|||
|
|
@ -9,17 +9,24 @@ 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.UserSearchResponse;
|
||||
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 +59,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 +94,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 +114,25 @@ 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,
|
||||
false
|
||||
),
|
||||
type,
|
||||
data.getString(Constants.EXTRAS_ID)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -144,15 +143,21 @@ 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"),
|
||||
data.optBoolean("is_verified")
|
||||
),
|
||||
"REQUEST",
|
||||
data.getString(Constants.EXTRAS_ID)
|
||||
));
|
||||
}
|
||||
}
|
||||
callback.onSuccess(result);
|
||||
|
|
@ -169,40 +174,9 @@ 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 String deviceUuid,
|
||||
final ServiceCallback<List<Notification>> callback) {
|
||||
final Map<String, String> form = new HashMap<>();
|
||||
form.put("_uuid", UUID.randomUUID().toString());
|
||||
form.put("_csrftoken", csrfToken);
|
||||
|
|
@ -210,57 +184,88 @@ 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(),
|
||||
u.isVerified()
|
||||
),
|
||||
"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);
|
||||
public void fetchChaining(final long targetId, final ServiceCallback<List<Notification>> callback) {
|
||||
final Call<UserSearchResponse> request = repository.getChaining(appUa, targetId);
|
||||
request.enqueue(new Callback<UserSearchResponse>() {
|
||||
@Override
|
||||
public void onResponse(@NonNull final Call<UserSearchResponse> call, @NonNull final Response<UserSearchResponse> response) {
|
||||
final UserSearchResponse body = response.body();
|
||||
if (body == null) {
|
||||
callback.onSuccess(null);
|
||||
return;
|
||||
}
|
||||
|
||||
final List<Notification> newsItems = body.getUsers().stream()
|
||||
.map(u -> {
|
||||
return new Notification(
|
||||
new NotificationArgs(
|
||||
u.getSocialContext(),
|
||||
null,
|
||||
u.getPk(),
|
||||
u.getProfilePicUrl(),
|
||||
null,
|
||||
0L,
|
||||
u.getUsername(),
|
||||
u.getFullName(),
|
||||
u.isVerified()
|
||||
),
|
||||
"AYML",
|
||||
u.getProfilePicId() // placeholder
|
||||
);
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
callback.onSuccess(newsItems);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull final Call<UserSearchResponse> call, @NonNull final Throwable t) {
|
||||
callback.onFailure(t);
|
||||
// Log.e(TAG, "onFailure: ", t);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import java.util.Collections;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
import awais.instagrabber.models.FeedStoryModel;
|
||||
|
|
@ -36,20 +37,45 @@ import retrofit2.Retrofit;
|
|||
public class StoriesService extends BaseService {
|
||||
private static final String TAG = "StoriesService";
|
||||
|
||||
private final StoriesRepository repository;
|
||||
|
||||
private static StoriesService instance;
|
||||
|
||||
private StoriesService() {
|
||||
private final StoriesRepository repository;
|
||||
private final String csrfToken;
|
||||
private final long userId;
|
||||
private final String deviceUuid;
|
||||
|
||||
private StoriesService(@NonNull final String csrfToken,
|
||||
final long userId,
|
||||
@NonNull final String deviceUuid) {
|
||||
this.csrfToken = csrfToken;
|
||||
this.userId = userId;
|
||||
this.deviceUuid = deviceUuid;
|
||||
final Retrofit retrofit = getRetrofitBuilder()
|
||||
.baseUrl("https://i.instagram.com")
|
||||
.build();
|
||||
repository = retrofit.create(StoriesRepository.class);
|
||||
}
|
||||
|
||||
public static StoriesService getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new StoriesService();
|
||||
public String getCsrfToken() {
|
||||
return csrfToken;
|
||||
}
|
||||
|
||||
public long getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public String getDeviceUuid() {
|
||||
return deviceUuid;
|
||||
}
|
||||
|
||||
public static StoriesService getInstance(final String csrfToken,
|
||||
final long userId,
|
||||
final String deviceUuid) {
|
||||
if (instance == null
|
||||
|| !Objects.equals(instance.getCsrfToken(), csrfToken)
|
||||
|| !Objects.equals(instance.getUserId(), userId)
|
||||
|| !Objects.equals(instance.getDeviceUuid(), deviceUuid)) {
|
||||
instance = new StoriesService(csrfToken, userId, deviceUuid);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
|
@ -146,6 +172,9 @@ public class StoriesService extends BaseService {
|
|||
null,
|
||||
0,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
final String id = node.getString("id");
|
||||
|
|
@ -205,6 +234,9 @@ public class StoriesService extends BaseService {
|
|||
null,
|
||||
0,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
final String id = node.getString("id");
|
||||
|
|
@ -390,13 +422,11 @@ public class StoriesService extends BaseService {
|
|||
final String action,
|
||||
final String arg1,
|
||||
final String arg2,
|
||||
final long userId,
|
||||
final String csrfToken,
|
||||
final ServiceCallback<StoryStickerResponse> callback) {
|
||||
final Map<String, Object> form = new HashMap<>();
|
||||
form.put("_csrftoken", csrfToken);
|
||||
form.put("_uid", userId);
|
||||
form.put("_uuid", UUID.randomUUID().toString());
|
||||
form.put("_uuid", deviceUuid);
|
||||
form.put("mutation_token", UUID.randomUUID().toString());
|
||||
form.put("client_context", UUID.randomUUID().toString());
|
||||
form.put("radio_type", "wifi-none");
|
||||
|
|
@ -427,39 +457,67 @@ public class StoriesService extends BaseService {
|
|||
public void respondToQuestion(final String storyId,
|
||||
final String stickerId,
|
||||
final String answer,
|
||||
final long userId,
|
||||
final String csrfToken,
|
||||
final ServiceCallback<StoryStickerResponse> callback) {
|
||||
respondToSticker(storyId, stickerId, "story_question_response", "response", answer, userId, csrfToken, callback);
|
||||
respondToSticker(storyId, stickerId, "story_question_response", "response", answer, callback);
|
||||
}
|
||||
|
||||
// QuizAction.java
|
||||
public void respondToQuiz(final String storyId,
|
||||
final String stickerId,
|
||||
final int answer,
|
||||
final long userId,
|
||||
final String csrfToken,
|
||||
final ServiceCallback<StoryStickerResponse> callback) {
|
||||
respondToSticker(storyId, stickerId, "story_quiz_answer", "answer", String.valueOf(answer), userId, csrfToken, callback);
|
||||
respondToSticker(storyId, stickerId, "story_quiz_answer", "answer", String.valueOf(answer), callback);
|
||||
}
|
||||
|
||||
// VoteAction.java
|
||||
public void respondToPoll(final String storyId,
|
||||
final String stickerId,
|
||||
final int answer,
|
||||
final long userId,
|
||||
final String csrfToken,
|
||||
final ServiceCallback<StoryStickerResponse> callback) {
|
||||
respondToSticker(storyId, stickerId, "story_poll_vote", "vote", String.valueOf(answer), userId, csrfToken, callback);
|
||||
respondToSticker(storyId, stickerId, "story_poll_vote", "vote", String.valueOf(answer), callback);
|
||||
}
|
||||
|
||||
public void respondToSlider(final String storyId,
|
||||
final String stickerId,
|
||||
final double answer,
|
||||
final long userId,
|
||||
final String csrfToken,
|
||||
final ServiceCallback<StoryStickerResponse> callback) {
|
||||
respondToSticker(storyId, stickerId, "story_slider_vote", "vote", String.valueOf(answer), userId, csrfToken, callback);
|
||||
respondToSticker(storyId, stickerId, "story_slider_vote", "vote", String.valueOf(answer), callback);
|
||||
}
|
||||
|
||||
public void seen(final String storyMediaId,
|
||||
final long takenAt,
|
||||
final long seenAt,
|
||||
final ServiceCallback<String> callback) {
|
||||
final Map<String, Object> form = new HashMap<>();
|
||||
form.put("_csrftoken", csrfToken);
|
||||
form.put("_uid", userId);
|
||||
form.put("_uuid", deviceUuid);
|
||||
form.put("container_module", "feed_timeline");
|
||||
final Map<String, Object> reelsForm = new HashMap<>();
|
||||
reelsForm.put(storyMediaId, Collections.singletonList(takenAt + "_" + seenAt));
|
||||
form.put("reels", reelsForm);
|
||||
final Map<String, String> signedForm = Utils.sign(form);
|
||||
final Map<String, String> queryMap = new HashMap<>();
|
||||
queryMap.put("reel", "1");
|
||||
queryMap.put("live_vod", "0");
|
||||
final Call<String> request = repository.seen(queryMap, signedForm);
|
||||
request.enqueue(new Callback<String>() {
|
||||
@Override
|
||||
public void onResponse(@NonNull final Call<String> call,
|
||||
@NonNull final Response<String> response) {
|
||||
if (callback != null) {
|
||||
callback.onSuccess(response.body());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull final Call<String> call,
|
||||
@NonNull final Throwable t) {
|
||||
if (callback != null) {
|
||||
callback.onFailure(t);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue