mirror of
https://github.com/KokaKiwi/BarInsta
synced 2024-12-23 05:16:58 +00:00
parent
e39c129b61
commit
c24fd016b1
@ -1,89 +0,0 @@
|
||||
package awais.instagrabber.asyncs;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.UUID;
|
||||
|
||||
import awais.instagrabber.models.StoryModel;
|
||||
import awais.instagrabber.models.stickers.QuizModel;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.CookieUtils;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
|
||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||
|
||||
public class QuizAction extends AsyncTask<Integer, Void, Integer> {
|
||||
private static final String TAG = "QuizAction";
|
||||
|
||||
private final StoryModel storyModel;
|
||||
private final QuizModel quizModel;
|
||||
private final String cookie;
|
||||
private final OnTaskCompleteListener onTaskCompleteListener;
|
||||
|
||||
public QuizAction(final StoryModel storyModel,
|
||||
final QuizModel quizModel,
|
||||
final String cookie,
|
||||
final OnTaskCompleteListener onTaskCompleteListener) {
|
||||
this.storyModel = storyModel;
|
||||
this.quizModel = quizModel;
|
||||
this.cookie = cookie;
|
||||
this.onTaskCompleteListener = onTaskCompleteListener;
|
||||
}
|
||||
|
||||
protected Integer doInBackground(Integer... rawChoice) {
|
||||
int choice = rawChoice[0];
|
||||
final String url = "https://i.instagram.com/api/v1/media/" + storyModel.getStoryMediaId().split("_")[0] + "/" + quizModel.getId() + "/story_quiz_answer/";
|
||||
HttpURLConnection urlConnection = null;
|
||||
try {
|
||||
JSONObject ogBody = new JSONObject("{\"client_context\":\"" + UUID.randomUUID().toString()
|
||||
+ "\",\"mutation_token\":\"" + UUID.randomUUID().toString()
|
||||
+ "\",\"_csrftoken\":\"" + cookie.split("csrftoken=")[1].split(";")[0]
|
||||
+ "\",\"_uid\":\"" + CookieUtils.getUserIdFromCookie(cookie)
|
||||
+ "\",\"__uuid\":\"" + settingsHelper.getString(Constants.DEVICE_UUID)
|
||||
+ "\"}");
|
||||
ogBody.put("answer", String.valueOf(choice));
|
||||
String urlParameters = Utils.sign(ogBody.toString());
|
||||
urlConnection = (HttpURLConnection) new URL(url).openConnection();
|
||||
urlConnection.setRequestMethod("POST");
|
||||
urlConnection.setUseCaches(false);
|
||||
urlConnection.setRequestProperty("User-Agent", Constants.I_USER_AGENT);
|
||||
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
||||
if (urlParameters != null) {
|
||||
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();
|
||||
Log.d(TAG, "quiz: " + url + " " + cookie + " " + urlParameters);
|
||||
urlConnection.connect();
|
||||
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||
return choice;
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
Log.e(TAG, "quiz: " + ex);
|
||||
} finally {
|
||||
if (urlConnection != null) {
|
||||
urlConnection.disconnect();
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final Integer choice) {
|
||||
if (onTaskCompleteListener == null || choice == null) return;
|
||||
onTaskCompleteListener.onTaskComplete(choice);
|
||||
}
|
||||
|
||||
public interface OnTaskCompleteListener {
|
||||
void onTaskComplete(final int choice);
|
||||
}
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
package awais.instagrabber.asyncs;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.UUID;
|
||||
|
||||
import awais.instagrabber.models.StoryModel;
|
||||
import awais.instagrabber.models.stickers.QuestionModel;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.CookieUtils;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
|
||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||
|
||||
public class RespondAction extends AsyncTask<String, Void, Boolean> {
|
||||
|
||||
private final StoryModel storyModel;
|
||||
private final QuestionModel questionModel;
|
||||
private final String cookie;
|
||||
private final OnTaskCompleteListener onTaskCompleteListener;
|
||||
|
||||
public RespondAction(final StoryModel storyModel,
|
||||
final QuestionModel questionModel,
|
||||
final String cookie,
|
||||
final OnTaskCompleteListener onTaskCompleteListener) {
|
||||
this.storyModel = storyModel;
|
||||
this.questionModel = questionModel;
|
||||
this.cookie = cookie;
|
||||
this.onTaskCompleteListener = onTaskCompleteListener;
|
||||
}
|
||||
|
||||
protected Boolean doInBackground(String... rawChoice) {
|
||||
final String url = "https://i.instagram.com/api/v1/media/"
|
||||
+ storyModel.getStoryMediaId().split("_")[0] + "/" + questionModel.getId() + "/story_question_response/";
|
||||
HttpURLConnection urlConnection = null;
|
||||
try {
|
||||
final JSONObject ogbody = new JSONObject("{\"client_context\":\"" + UUID.randomUUID().toString()
|
||||
+ "\",\"mutation_token\":\"" + UUID.randomUUID().toString()
|
||||
+ "\",\"_csrftoken\":\"" + cookie.split("csrftoken=")[1].split(";")[0]
|
||||
+ "\",\"_uid\":\"" + CookieUtils.getUserIdFromCookie(cookie)
|
||||
+ "\",\"__uuid\":\"" + settingsHelper.getString(Constants.DEVICE_UUID)
|
||||
+ "\"}");
|
||||
String choice = rawChoice[0].replaceAll("\"", ("\\\""));
|
||||
ogbody.put("response", choice);
|
||||
String urlParameters = Utils.sign(ogbody.toString());
|
||||
urlConnection = (HttpURLConnection) new URL(url).openConnection();
|
||||
urlConnection.setRequestMethod("POST");
|
||||
urlConnection.setUseCaches(false);
|
||||
urlConnection.setRequestProperty("User-Agent", Constants.I_USER_AGENT);
|
||||
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();
|
||||
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||
return true;
|
||||
}
|
||||
|
||||
} catch (Throwable ex) {
|
||||
Log.e("austin_debug", "respond: " + ex);
|
||||
} finally {
|
||||
if (urlConnection != null) {
|
||||
urlConnection.disconnect();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final Boolean ok) {
|
||||
if (onTaskCompleteListener == null) return;
|
||||
onTaskCompleteListener.onTaskComplete(ok);
|
||||
|
||||
}
|
||||
|
||||
public interface OnTaskCompleteListener {
|
||||
void onTaskComplete(final boolean result);
|
||||
}
|
||||
}
|
@ -1,69 +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.models.stickers.PollModel;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
|
||||
public class VoteAction extends AsyncTask<Integer, Void, Integer> {
|
||||
|
||||
private static final String TAG = "VoteAction";
|
||||
|
||||
private final StoryModel storyModel;
|
||||
private final PollModel pollModel;
|
||||
private final String cookie;
|
||||
private final OnTaskCompleteListener onTaskCompleteListener;
|
||||
|
||||
public VoteAction(final StoryModel storyModel,
|
||||
final PollModel pollModel,
|
||||
final String cookie,
|
||||
final OnTaskCompleteListener onTaskCompleteListener) {
|
||||
this.storyModel = storyModel;
|
||||
this.pollModel = pollModel;
|
||||
this.cookie = cookie;
|
||||
this.onTaskCompleteListener = onTaskCompleteListener;
|
||||
}
|
||||
|
||||
protected Integer doInBackground(Integer... rawChoice) {
|
||||
int choice = rawChoice[0];
|
||||
final String url = "https://www.instagram.com/media/" + storyModel.getStoryMediaId().split("_")[0] + "/" + pollModel.getId() + "/story_poll_vote/";
|
||||
try {
|
||||
final HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection();
|
||||
urlConnection.setRequestMethod("POST");
|
||||
urlConnection.setUseCaches(false);
|
||||
urlConnection.setRequestProperty("User-Agent", Constants.USER_AGENT);
|
||||
urlConnection.setRequestProperty("x-csrftoken", cookie.split("csrftoken=")[1].split(";")[0]);
|
||||
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
||||
urlConnection.setRequestProperty("Content-Length", "6");
|
||||
urlConnection.setDoOutput(true);
|
||||
DataOutputStream wr = new DataOutputStream(urlConnection.getOutputStream());
|
||||
wr.writeBytes("vote=" + choice);
|
||||
wr.flush();
|
||||
wr.close();
|
||||
urlConnection.connect();
|
||||
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||
return choice;
|
||||
}
|
||||
urlConnection.disconnect();
|
||||
} catch (Exception ex) {
|
||||
Log.e(TAG, "Error", ex);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final Integer result) {
|
||||
if (result == null || onTaskCompleteListener == null) return;
|
||||
onTaskCompleteListener.onTaskComplete(result);
|
||||
}
|
||||
|
||||
public interface OnTaskCompleteListener {
|
||||
void onTaskComplete(final int choice);
|
||||
}
|
||||
}
|
@ -11,6 +11,7 @@ import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
@ -20,6 +21,9 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@ -55,6 +59,7 @@ import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
@ -63,10 +68,7 @@ import awais.instagrabber.BuildConfig;
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.adapters.StoriesAdapter;
|
||||
import awais.instagrabber.asyncs.PostFetcher;
|
||||
import awais.instagrabber.asyncs.QuizAction;
|
||||
import awais.instagrabber.asyncs.RespondAction;
|
||||
import awais.instagrabber.asyncs.SeenAction;
|
||||
import awais.instagrabber.asyncs.VoteAction;
|
||||
import awais.instagrabber.asyncs.direct_messages.CreateThreadAction;
|
||||
import awais.instagrabber.asyncs.direct_messages.DirectThreadBroadcaster;
|
||||
import awais.instagrabber.customviews.helpers.SwipeGestureListener;
|
||||
@ -80,7 +82,10 @@ import awais.instagrabber.models.enums.MediaItemType;
|
||||
import awais.instagrabber.models.stickers.PollModel;
|
||||
import awais.instagrabber.models.stickers.QuestionModel;
|
||||
import awais.instagrabber.models.stickers.QuizModel;
|
||||
import awais.instagrabber.models.stickers.SliderModel;
|
||||
import awais.instagrabber.repositories.responses.StoryStickerResponse;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.CookieUtils;
|
||||
import awais.instagrabber.utils.DownloadUtils;
|
||||
import awais.instagrabber.utils.TextUtils;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
@ -117,13 +122,15 @@ public class StoryViewerFragment extends Fragment {
|
||||
private QuestionModel question;
|
||||
private String[] mentions;
|
||||
private QuizModel quiz;
|
||||
private SliderModel slider;
|
||||
private MenuItem menuDownload;
|
||||
private MenuItem menuDm;
|
||||
private SimpleExoPlayer player;
|
||||
private boolean isHashtag, isLoc;
|
||||
private String highlight;
|
||||
private boolean fetching = false;
|
||||
private boolean fetching = false, sticking = false;
|
||||
private int currentFeedStoryIndex;
|
||||
private double sliderValue;
|
||||
private StoriesViewModel storiesViewModel;
|
||||
private boolean shouldRefresh = true;
|
||||
private StoryViewerFragmentArgs fragmentArgs;
|
||||
@ -190,7 +197,7 @@ public class StoryViewerFragment extends Fragment {
|
||||
new AlertDialog.Builder(context)
|
||||
.setTitle(R.string.reply_story)
|
||||
.setView(input)
|
||||
.setPositiveButton(R.string.ok, (d, w) -> new CreateThreadAction(cookie, currentStory.getUserId(), threadId -> {
|
||||
.setPositiveButton(R.string.confirm, (d, w) -> new CreateThreadAction(cookie, currentStory.getUserId(), threadId -> {
|
||||
try {
|
||||
final DirectThreadBroadcaster.StoryReplyBroadcastOptions options = new DirectThreadBroadcaster.StoryReplyBroadcastOptions(
|
||||
input.getText().toString(),
|
||||
@ -273,6 +280,7 @@ public class StoryViewerFragment extends Fragment {
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
private void setupListeners() {
|
||||
final String userIdFromCookie = CookieUtils.getUserIdFromCookie(cookie);
|
||||
final boolean hasFeedStories;
|
||||
List<?> models = null;
|
||||
if (currentFeedStoryIndex >= 0) {
|
||||
@ -297,6 +305,10 @@ public class StoryViewerFragment extends Fragment {
|
||||
swipeEvent = isRightSwipe -> {
|
||||
final List<StoryModel> storyModels = storiesViewModel.getList().getValue();
|
||||
final int storiesLen = storyModels == null ? 0 : storyModels.size();
|
||||
if (sticking) {
|
||||
Toast.makeText(context, R.string.follower_wait_to_load, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
if (storiesLen <= 0) return;
|
||||
final boolean isLeftSwipe = !isRightSwipe;
|
||||
final boolean endOfCurrentStories = slidePos + 1 >= storiesLen;
|
||||
@ -407,15 +419,30 @@ public class StoryViewerFragment extends Fragment {
|
||||
poll.getLeftChoice() + " (" + poll.getLeftCount() + ")",
|
||||
poll.getRightChoice() + " (" + poll.getRightCount() + ")"
|
||||
}), (d, w) -> {
|
||||
if (!TextUtils.isEmpty(cookie))
|
||||
new VoteAction(currentStory, poll, cookie, choice -> {
|
||||
if (choice > -1) {
|
||||
poll.setMyChoice(choice);
|
||||
Toast.makeText(context, R.string.votef_story_poll, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
}).execute(w);
|
||||
if (!TextUtils.isEmpty(cookie)) {
|
||||
sticking = true;
|
||||
storiesService.respondToPoll(
|
||||
currentStory.getStoryMediaId().split("_")[0],
|
||||
poll.getId(),
|
||||
w,
|
||||
userIdFromCookie,
|
||||
CookieUtils.getCsrfTokenFromCookie(cookie),
|
||||
new ServiceCallback<StoryStickerResponse>() {
|
||||
@Override
|
||||
public void onSuccess(final StoryStickerResponse result) {
|
||||
sticking = false;
|
||||
poll.setMyChoice(w);
|
||||
Toast.makeText(context, R.string.votef_story_poll, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(final Throwable t) {
|
||||
sticking = false;
|
||||
Log.e(TAG, "Error responding", t);
|
||||
Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
.setPositiveButton(R.string.cancel, null)
|
||||
.show();
|
||||
@ -427,12 +454,29 @@ public class StoryViewerFragment extends Fragment {
|
||||
new AlertDialog.Builder(context)
|
||||
.setTitle(question.getQuestion())
|
||||
.setView(input)
|
||||
.setPositiveButton(R.string.ok, (d, w) -> new RespondAction(currentStory, question, cookie, result -> {
|
||||
if (result) {
|
||||
Toast.makeText(context, R.string.answered_story, Toast.LENGTH_SHORT).show();
|
||||
} else
|
||||
Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
}).execute(input.getText().toString()))
|
||||
.setPositiveButton(R.string.confirm, (d, w) -> {
|
||||
sticking = true;
|
||||
storiesService.respondToQuestion(
|
||||
currentStory.getStoryMediaId().split("_")[0],
|
||||
question.getId(),
|
||||
input.getText().toString(),
|
||||
userIdFromCookie,
|
||||
CookieUtils.getCsrfTokenFromCookie(cookie),
|
||||
new ServiceCallback<StoryStickerResponse>() {
|
||||
@Override
|
||||
public void onSuccess(final StoryStickerResponse result) {
|
||||
sticking = false;
|
||||
Toast.makeText(context, R.string.answered_story, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(final Throwable t) {
|
||||
sticking = false;
|
||||
Log.e(TAG, "Error responding", t);
|
||||
Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show();
|
||||
} else if (tag instanceof String[]) {
|
||||
@ -452,24 +496,119 @@ 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))
|
||||
new QuizAction(currentStory, quiz, cookie, choice -> {
|
||||
if (choice > -1) {
|
||||
quiz.setMyChoice(choice);
|
||||
Toast.makeText(context, R.string.answered_story, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
}).execute(w);
|
||||
if (quiz.getMyChoice() == -1 && !TextUtils.isEmpty(cookie)) {
|
||||
sticking = true;
|
||||
storiesService.respondToQuiz(
|
||||
currentStory.getStoryMediaId().split("_")[0],
|
||||
quiz.getId(),
|
||||
w,
|
||||
userIdFromCookie,
|
||||
CookieUtils.getCsrfTokenFromCookie(cookie),
|
||||
new ServiceCallback<StoryStickerResponse>() {
|
||||
@Override
|
||||
public void onSuccess(final StoryStickerResponse result) {
|
||||
sticking = false;
|
||||
quiz.setMyChoice(w);
|
||||
Toast.makeText(context, R.string.answered_story, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(final Throwable t) {
|
||||
sticking = false;
|
||||
Log.e(TAG, "Error responding", t);
|
||||
Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
.setPositiveButton(R.string.cancel, null)
|
||||
.show();
|
||||
} else if (tag instanceof SliderModel) {
|
||||
slider = (SliderModel) tag;
|
||||
NumberFormat percentage = NumberFormat.getPercentInstance();
|
||||
percentage.setMaximumFractionDigits(2);
|
||||
LinearLayout sliderView = new LinearLayout(context);
|
||||
sliderView.setLayoutParams(new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT));
|
||||
sliderView.setOrientation(LinearLayout.VERTICAL);
|
||||
TextView tv = new TextView(context);
|
||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||
final SeekBar input = new SeekBar(context);
|
||||
Double avg = slider.getAverage() * 100;
|
||||
input.setProgress(avg.intValue());
|
||||
sliderView.addView(input);
|
||||
sliderView.addView(tv);
|
||||
if (slider.getMyChoice().isNaN() && slider.canVote()) {
|
||||
input.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
sliderValue = progress / 100.0;
|
||||
tv.setText(percentage.format(sliderValue));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
}
|
||||
});
|
||||
new AlertDialog.Builder(context)
|
||||
.setTitle(TextUtils.isEmpty(slider.getQuestion()) ? slider.getEmoji() : slider.getQuestion())
|
||||
.setMessage(getResources().getQuantityString(R.plurals.slider_info,
|
||||
slider.getVoteCount(),
|
||||
slider.getVoteCount(),
|
||||
percentage.format(slider.getAverage())))
|
||||
.setView(sliderView)
|
||||
.setPositiveButton(R.string.confirm, (d, w) -> {
|
||||
sticking = true;
|
||||
storiesService.respondToSlider(
|
||||
currentStory.getStoryMediaId().split("_")[0],
|
||||
slider.getId(),
|
||||
sliderValue,
|
||||
userIdFromCookie,
|
||||
CookieUtils.getCsrfTokenFromCookie(cookie),
|
||||
new ServiceCallback<StoryStickerResponse>() {
|
||||
@Override
|
||||
public void onSuccess(final StoryStickerResponse result) {
|
||||
sticking = false;
|
||||
slider.setMyChoice(sliderValue);
|
||||
Toast.makeText(context, R.string.answered_story, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(final Throwable t) {
|
||||
sticking = false;
|
||||
Log.e(TAG, "Error responding", t);
|
||||
Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
else {
|
||||
input.setEnabled(false);
|
||||
tv.setText(getString(R.string.slider_answer, percentage.format(slider.getMyChoice())));
|
||||
new AlertDialog.Builder(context)
|
||||
.setTitle(TextUtils.isEmpty(slider.getQuestion()) ? slider.getEmoji() : slider.getQuestion())
|
||||
.setMessage(getResources().getQuantityString(R.plurals.slider_info,
|
||||
slider.getVoteCount(),
|
||||
slider.getVoteCount(),
|
||||
percentage.format(slider.getAverage())))
|
||||
.setView(sliderView)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
};
|
||||
binding.poll.setOnClickListener(storyActionListener);
|
||||
binding.answer.setOnClickListener(storyActionListener);
|
||||
binding.mention.setOnClickListener(storyActionListener);
|
||||
binding.quiz.setOnClickListener(storyActionListener);
|
||||
binding.slider.setOnClickListener(storyActionListener);
|
||||
}
|
||||
|
||||
private void resetView() {
|
||||
@ -588,6 +727,10 @@ public class StoryViewerFragment extends Fragment {
|
||||
binding.quiz.setVisibility(quiz != null ? View.VISIBLE : View.GONE);
|
||||
binding.quiz.setTag(quiz);
|
||||
|
||||
slider = currentStory.getSlider();
|
||||
binding.slider.setVisibility(slider != null ? View.VISIBLE : View.GONE);
|
||||
binding.slider.setTag(slider);
|
||||
|
||||
releasePlayer();
|
||||
if (isHashtag || isLoc) {
|
||||
final ActionBar actionBar = fragmentActivity.getSupportActionBar();
|
||||
|
@ -47,6 +47,7 @@ import awais.instagrabber.models.FeedModel;
|
||||
import awais.instagrabber.models.FeedStoryModel;
|
||||
import awais.instagrabber.models.PostsLayoutPreferences;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.CookieUtils;
|
||||
import awais.instagrabber.utils.DownloadUtils;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
import awais.instagrabber.viewmodels.FeedStoriesViewModel;
|
||||
@ -55,6 +56,7 @@ import awais.instagrabber.webservices.StoriesService;
|
||||
|
||||
import static androidx.core.content.PermissionChecker.checkSelfPermission;
|
||||
import static awais.instagrabber.utils.DownloadUtils.WRITE_PERMISSION;
|
||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||
|
||||
public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
|
||||
private static final String TAG = "FeedFragment";
|
||||
@ -367,9 +369,10 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre
|
||||
}
|
||||
|
||||
private void fetchStories() {
|
||||
final String cookie = settingsHelper.getString(Constants.COOKIE);
|
||||
storiesFetching = true;
|
||||
updateSwipeRefreshState();
|
||||
storiesService.getFeedStories(new ServiceCallback<List<FeedStoryModel>>() {
|
||||
storiesService.getFeedStories(CookieUtils.getCsrfTokenFromCookie(cookie), new ServiceCallback<List<FeedStoryModel>>() {
|
||||
@Override
|
||||
public void onSuccess(final List<FeedStoryModel> result) {
|
||||
feedStoriesViewModel.getList().postValue(result);
|
||||
|
@ -6,6 +6,7 @@ import awais.instagrabber.models.enums.MediaItemType;
|
||||
import awais.instagrabber.models.stickers.PollModel;
|
||||
import awais.instagrabber.models.stickers.QuestionModel;
|
||||
import awais.instagrabber.models.stickers.QuizModel;
|
||||
import awais.instagrabber.models.stickers.SliderModel;
|
||||
import awais.instagrabber.models.stickers.SwipeUpModel;
|
||||
|
||||
public final class StoryModel implements Serializable {
|
||||
@ -21,6 +22,7 @@ public final class StoryModel implements Serializable {
|
||||
private String spotify;
|
||||
private PollModel poll;
|
||||
private QuestionModel question;
|
||||
private SliderModel slider;
|
||||
private QuizModel quiz;
|
||||
private SwipeUpModel swipeUp;
|
||||
private String[] mentions;
|
||||
@ -71,6 +73,10 @@ public final class StoryModel implements Serializable {
|
||||
return question;
|
||||
}
|
||||
|
||||
public SliderModel getSlider() {
|
||||
return slider;
|
||||
}
|
||||
|
||||
public QuizModel getQuiz() {
|
||||
return quiz;
|
||||
}
|
||||
@ -109,6 +115,10 @@ public final class StoryModel implements Serializable {
|
||||
this.question = question;
|
||||
}
|
||||
|
||||
public void setSlider(final SliderModel slider) {
|
||||
this.slider = slider;
|
||||
}
|
||||
|
||||
public void setQuiz(final QuizModel quiz) {
|
||||
this.quiz = quiz;
|
||||
}
|
||||
|
53
app/src/main/java/awais/instagrabber/models/stickers/SliderModel.java
Executable file
53
app/src/main/java/awais/instagrabber/models/stickers/SliderModel.java
Executable file
@ -0,0 +1,53 @@
|
||||
package awais.instagrabber.models.stickers;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public final class SliderModel implements Serializable {
|
||||
private final int voteCount;
|
||||
private final Double average;
|
||||
private Double myChoice;
|
||||
private final boolean canVote;
|
||||
private final String id, question, emoji;
|
||||
|
||||
public SliderModel(final String id, final String question, final String emoji, final boolean canVote,
|
||||
final Double average, final int voteCount, final Double myChoice) {
|
||||
this.id = id;
|
||||
this.question = question;
|
||||
this.emoji = emoji;
|
||||
this.canVote = canVote;
|
||||
this.average = average;
|
||||
this.voteCount = voteCount;
|
||||
this.myChoice = myChoice;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getQuestion() {
|
||||
return question;
|
||||
}
|
||||
|
||||
public String getEmoji() {
|
||||
return emoji;
|
||||
}
|
||||
|
||||
public boolean canVote() {
|
||||
return canVote;
|
||||
}
|
||||
|
||||
public int getVoteCount() {
|
||||
return voteCount;
|
||||
}
|
||||
|
||||
public Double getAverage() {
|
||||
return average;
|
||||
}
|
||||
|
||||
public Double getMyChoice() { return myChoice; }
|
||||
|
||||
public Double setMyChoice(final Double choice) {
|
||||
this.myChoice = choice;
|
||||
return choice;
|
||||
}
|
||||
}
|
@ -2,17 +2,33 @@ package awais.instagrabber.repositories;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import awais.instagrabber.repositories.responses.StoryStickerResponse;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.http.FieldMap;
|
||||
import retrofit2.http.FormUrlEncoded;
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.Header;
|
||||
import retrofit2.http.Path;
|
||||
import retrofit2.http.POST;
|
||||
import retrofit2.http.QueryMap;
|
||||
import retrofit2.http.Url;
|
||||
|
||||
public interface StoriesRepository {
|
||||
|
||||
@GET("graphql/query/")
|
||||
Call<String> getStories(@QueryMap(encoded = true) Map<String, String> variables);
|
||||
@FormUrlEncoded
|
||||
@POST("/api/v1/feed/reels_tray/")
|
||||
Call<String> getStories(@Header("User-Agent") String userAgent,
|
||||
@FieldMap Map<String, String> form);
|
||||
|
||||
@GET
|
||||
Call<String> getUserStory(@Header("User-Agent") String userAgent, @Url String url);
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("/api/v1/media/{storyId}/{stickerId}/{action}/")
|
||||
Call<StoryStickerResponse> respondToSticker(@Header("User-Agent") String userAgent,
|
||||
@Path("storyId") String storyId,
|
||||
@Path("stickerId") String stickerId,
|
||||
@Path("action") String action,
|
||||
// story_poll_vote, story_question_response, story_slider_vote, story_quiz_answer
|
||||
@FieldMap Map<String, String> form);
|
||||
}
|
||||
|
@ -0,0 +1,20 @@
|
||||
package awais.instagrabber.repositories.responses;
|
||||
|
||||
public class StoryStickerResponse {
|
||||
private final String status;
|
||||
|
||||
public StoryStickerResponse(final String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "StoryStickerResponse{" +
|
||||
"status='" + status + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -18,6 +18,7 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import awais.instagrabber.models.FeedStoryModel;
|
||||
import awais.instagrabber.models.ProfileModel;
|
||||
@ -26,9 +27,13 @@ import awais.instagrabber.models.enums.MediaItemType;
|
||||
import awais.instagrabber.models.stickers.PollModel;
|
||||
import awais.instagrabber.models.stickers.QuestionModel;
|
||||
import awais.instagrabber.models.stickers.QuizModel;
|
||||
import awais.instagrabber.models.stickers.SliderModel;
|
||||
import awais.instagrabber.models.stickers.SwipeUpModel;
|
||||
import awais.instagrabber.repositories.StoriesRepository;
|
||||
import awais.instagrabber.repositories.responses.StoryStickerResponse;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.ResponseBodyUtils;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
@ -44,7 +49,7 @@ public class StoriesService extends BaseService {
|
||||
|
||||
private StoriesService() {
|
||||
final Retrofit retrofit = getRetrofitBuilder()
|
||||
.baseUrl("https://www.instagram.com")
|
||||
.baseUrl("https://i.instagram.com")
|
||||
.build();
|
||||
repository = retrofit.create(StoriesRepository.class);
|
||||
}
|
||||
@ -56,7 +61,7 @@ public class StoriesService extends BaseService {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void getFeedStories(final ServiceCallback<List<FeedStoryModel>> callback) {
|
||||
public void getFeedStories(final String csrfToken, final ServiceCallback<List<FeedStoryModel>> callback) {
|
||||
if (loadFromMock) {
|
||||
final Handler handler = new Handler();
|
||||
handler.postDelayed(() -> {
|
||||
@ -81,10 +86,13 @@ public class StoriesService extends BaseService {
|
||||
}, 1000);
|
||||
return;
|
||||
}
|
||||
final Map<String, String> queryMap = new HashMap<>();
|
||||
queryMap.put("query_hash", "b7b84d884400bc5aa7cfe12ae843a091");
|
||||
queryMap.put("variables", "{\"only_stories\":true,\"stories_prefetch\":false,\"stories_video_dash_manifest\":false}");
|
||||
final Call<String> response = repository.getStories(queryMap);
|
||||
final Map<String, Object> form = new HashMap<>(4);
|
||||
form.put("reason", "cold_start");
|
||||
form.put("_csrftoken", csrfToken);
|
||||
form.put("_uuid", UUID.randomUUID().toString());
|
||||
form.put("supported_capabilities_new", Constants.SUPPORTED_CAPABILITIES);
|
||||
final Map<String, String> signedForm = Utils.sign(form);
|
||||
final Call<String> response = repository.getStories(Constants.I_USER_AGENT, signedForm);
|
||||
response.enqueue(new Callback<String>() {
|
||||
@Override
|
||||
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) {
|
||||
@ -106,17 +114,12 @@ public class StoriesService extends BaseService {
|
||||
private void parseStoriesBody(final String body, final ServiceCallback<List<FeedStoryModel>> callback) {
|
||||
try {
|
||||
final List<FeedStoryModel> feedStoryModels = new ArrayList<>();
|
||||
final JSONArray feedStoriesReel = new JSONObject(body)
|
||||
.getJSONObject("data")
|
||||
.getJSONObject(Constants.EXTRAS_USER)
|
||||
.getJSONObject("feed_reels_tray")
|
||||
.getJSONObject("edge_reels_tray_to_reel")
|
||||
.getJSONArray("edges");
|
||||
final JSONArray feedStoriesReel = new JSONObject(body).getJSONArray("tray");
|
||||
for (int i = 0; i < feedStoriesReel.length(); ++i) {
|
||||
final JSONObject node = feedStoriesReel.getJSONObject(i).getJSONObject("node");
|
||||
final JSONObject node = feedStoriesReel.getJSONObject(i);
|
||||
final JSONObject user = node.getJSONObject(node.has("user") ? "user" : "owner");
|
||||
final ProfileModel profileModel = new ProfileModel(false, false, false,
|
||||
user.getString("id"),
|
||||
user.getString("pk"),
|
||||
user.getString("username"),
|
||||
null, null, null,
|
||||
user.getString("profile_pic_url"),
|
||||
@ -240,6 +243,27 @@ public class StoriesService extends BaseService {
|
||||
));
|
||||
}
|
||||
}
|
||||
if (data.has("story_cta") && data.has("link_text")) {
|
||||
JSONObject tappableObject = data.getJSONArray("story_cta").getJSONObject(0).getJSONArray("links").getJSONObject(0);
|
||||
String swipeUpUrl = tappableObject.getString("webUri");
|
||||
if (swipeUpUrl.startsWith("http")) {
|
||||
model.setSwipeUp(new SwipeUpModel(swipeUpUrl, data.getString("link_text")));
|
||||
}
|
||||
}
|
||||
if (data.has("story_sliders")) {
|
||||
final JSONObject tappableObject = data.getJSONArray("story_sliders").getJSONObject(0)
|
||||
.optJSONObject("slider_sticker");
|
||||
if (tappableObject != null)
|
||||
model.setSlider(new SliderModel(
|
||||
String.valueOf(tappableObject.getLong("slider_id")),
|
||||
tappableObject.getString("question"),
|
||||
tappableObject.getString("emoji"),
|
||||
tappableObject.getBoolean("viewer_can_vote"),
|
||||
tappableObject.getDouble("slider_vote_average"),
|
||||
tappableObject.getInt("slider_vote_count"),
|
||||
tappableObject.optDouble("viewer_vote")
|
||||
));
|
||||
}
|
||||
JSONArray hashtags = data.optJSONArray("story_hashtags");
|
||||
JSONArray locations = data.optJSONArray("story_locations");
|
||||
JSONArray atmarks = data.optJSONArray("reel_mentions");
|
||||
@ -283,6 +307,83 @@ public class StoriesService extends BaseService {
|
||||
});
|
||||
}
|
||||
|
||||
private void respondToSticker(final String storyId,
|
||||
final String stickerId,
|
||||
final String action,
|
||||
final String arg1,
|
||||
final String arg2,
|
||||
final String 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("mutation_token", UUID.randomUUID().toString());
|
||||
form.put("client_context", UUID.randomUUID().toString());
|
||||
form.put("radio_type", "wifi-none");
|
||||
form.put(arg1, arg2);
|
||||
final Map<String, String> signedForm = Utils.sign(form);
|
||||
final Call<StoryStickerResponse> request =
|
||||
repository.respondToSticker(Constants.I_USER_AGENT, storyId, stickerId, action, signedForm);
|
||||
request.enqueue(new Callback<StoryStickerResponse>() {
|
||||
@Override
|
||||
public void onResponse(@NonNull final Call<StoryStickerResponse> call,
|
||||
@NonNull final Response<StoryStickerResponse> response) {
|
||||
if (callback != null) {
|
||||
callback.onSuccess(response.body());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull final Call<StoryStickerResponse> call,
|
||||
@NonNull final Throwable t) {
|
||||
if (callback != null) {
|
||||
callback.onFailure(t);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// RespondAction.java
|
||||
public void respondToQuestion(final String storyId,
|
||||
final String stickerId,
|
||||
final String answer,
|
||||
final String userId,
|
||||
final String csrfToken,
|
||||
final ServiceCallback<StoryStickerResponse> callback) {
|
||||
respondToSticker(storyId, stickerId, "story_question_response", "response", answer, userId, csrfToken, callback);
|
||||
}
|
||||
|
||||
// QuizAction.java
|
||||
public void respondToQuiz(final String storyId,
|
||||
final String stickerId,
|
||||
final int answer,
|
||||
final String userId,
|
||||
final String csrfToken,
|
||||
final ServiceCallback<StoryStickerResponse> callback) {
|
||||
respondToSticker(storyId, stickerId, "story_quiz_answer", "answer", String.valueOf(answer), userId, csrfToken, callback);
|
||||
}
|
||||
|
||||
// VoteAction.java
|
||||
public void respondToPoll(final String storyId,
|
||||
final String stickerId,
|
||||
final int answer,
|
||||
final String userId,
|
||||
final String csrfToken,
|
||||
final ServiceCallback<StoryStickerResponse> callback) {
|
||||
respondToSticker(storyId, stickerId, "story_poll_vote", "vote", String.valueOf(answer), userId, csrfToken, callback);
|
||||
}
|
||||
|
||||
public void respondToSlider(final String storyId,
|
||||
final String stickerId,
|
||||
final double answer,
|
||||
final String userId,
|
||||
final String csrfToken,
|
||||
final ServiceCallback<StoryStickerResponse> callback) {
|
||||
respondToSticker(storyId, stickerId, "story_slider_vote", "vote", String.valueOf(answer), userId, csrfToken, callback);
|
||||
}
|
||||
|
||||
private String buildUrl(final String id, final boolean isLoc, final boolean isHashtag, final boolean highlight) {
|
||||
final String userId = id.replace(":", "%3A");
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
|
@ -85,6 +85,16 @@
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_blue_background" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/slider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/story_slider"
|
||||
android:textColor="@color/btn_blue_text_color"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_blue_background" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/swipeUp"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -66,9 +66,15 @@
|
||||
<string name="respond_story">Respond</string>
|
||||
<string name="answer_hint">Answer…</string>
|
||||
<string name="answered_story">Answer successful!</string>
|
||||
<plurals name="slider_info" comment="For slider stickers in stories, eg. 3 responses averaging 17.38%">
|
||||
<item quantity="one">%d response averaging %s</item>
|
||||
<item quantity="other">%d responses averaging %s</item>
|
||||
</plurals>
|
||||
<string name="slider_answer">Your answer: %s</string>
|
||||
<string name="reply_story">Reply to story</string>
|
||||
<string name="reply_hint">Reply…</string>
|
||||
<string name="story_quiz">Quiz</string>
|
||||
<string name="story_slider">Slider</string>
|
||||
<string name="story_quizzed">You have already answered!</string>
|
||||
<string name="story_mentions">Mentions</string>
|
||||
<string name="priv_acc">This Account is Private</string>
|
||||
|
Loading…
Reference in New Issue
Block a user