fix story seen

This commit is contained in:
Austin Huang 2021-03-04 12:33:59 -05:00
parent de86668caf
commit 5421bb4592
No known key found for this signature in database
GPG Key ID: 84C23AA04587A91F
9 changed files with 119 additions and 123 deletions

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}

View File

@ -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);
}

View File

@ -307,7 +307,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()));

View File

@ -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);
}

View File

@ -14,7 +14,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import java.util.Objects;
import java.util.UUID;
import awais.instagrabber.models.FeedStoryModel;
@ -37,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;
}
@ -391,13 +416,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");
@ -428,39 +451,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