mirror of
https://github.com/KokaKiwi/BarInsta
synced 2024-11-21 22:27:29 +00:00
story stickers and various bug fixes
This commit is contained in:
parent
90daf3069c
commit
eac0d9a5f7
@ -12,8 +12,8 @@ android {
|
||||
// REMEMBER TO CHANGE versionCode AS WELL
|
||||
// 16.7 is 32, 16.9 is 35 (34 is public beta)
|
||||
|
||||
versionCode 36
|
||||
versionName '17.0'
|
||||
versionCode 37
|
||||
versionName '17.1'
|
||||
|
||||
multiDexEnabled true
|
||||
|
||||
|
@ -8,6 +8,7 @@ import androidx.multidex.MultiDexApplication;
|
||||
|
||||
import java.net.CookieHandler;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.UUID;
|
||||
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.DataBox;
|
||||
@ -61,6 +62,8 @@ public final class InstaApp extends MultiDexApplication {
|
||||
settingsHelper.getString(Constants.CUSTOM_DATE_TIME_FORMAT) :
|
||||
settingsHelper.getString(Constants.DATE_TIME_FORMAT), LocaleUtils.getCurrentLocale());
|
||||
|
||||
settingsHelper.putString(Constants.DEVICE_UUID, UUID.randomUUID().toString());
|
||||
|
||||
changeTheme();
|
||||
}
|
||||
}
|
@ -60,7 +60,7 @@ import awais.instagrabber.asyncs.HighlightsFetcher;
|
||||
import awais.instagrabber.asyncs.LocationFetcher;
|
||||
import awais.instagrabber.asyncs.PostsFetcher;
|
||||
import awais.instagrabber.asyncs.ProfileFetcher;
|
||||
import awais.instagrabber.asyncs.StoryStatusFetcher;
|
||||
import awais.instagrabber.asyncs.i.iStoryStatusFetcher;
|
||||
import awais.instagrabber.customviews.MouseDrawer;
|
||||
import awais.instagrabber.customviews.RamboTextView;
|
||||
import awais.instagrabber.customviews.helpers.GridAutofitLayoutManager;
|
||||
@ -543,7 +543,7 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
|
||||
else main.startActivity(new Intent(main, PostViewer.class)
|
||||
.putExtra(Constants.EXTRAS_INDEX, itemModel.getPosition())
|
||||
.putExtra(Constants.EXTRAS_TYPE, ItemGetType.DISCOVER_ITEMS)
|
||||
.putExtra(Constants.EXTRAS_POST, new PostModel(itemModel.getShortCode())));
|
||||
.putExtra(Constants.EXTRAS_POST, new PostModel(itemModel.getShortCode(), false)));
|
||||
}
|
||||
}, v -> {
|
||||
final Object tag = v.getTag();
|
||||
@ -599,7 +599,7 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
|
||||
if (modelType == IntentModelType.POST) {
|
||||
main.startActivityForResult(new Intent(main, PostViewer.class)
|
||||
.putExtra(Constants.EXTRAS_USER, main.userQuery)
|
||||
.putExtra(Constants.EXTRAS_POST, new PostModel(modelText)), 9629);
|
||||
.putExtra(Constants.EXTRAS_POST, new PostModel(modelText, false)), 9629);
|
||||
} else {
|
||||
main.addToStack();
|
||||
main.userQuery = modelType == IntentModelType.HASHTAG ? '#' + modelText : ("@"+modelText);
|
||||
@ -700,8 +700,6 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
|
||||
return;
|
||||
}
|
||||
|
||||
final String profileId = hashtagModel.getId();
|
||||
|
||||
final String cookie = Utils.settingsHelper.getString(Constants.COOKIE);
|
||||
final boolean isLoggedIn = !Utils.isEmpty(cookie);
|
||||
|
||||
@ -711,7 +709,7 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
|
||||
main.mainBinding.btnFollowTag.setVisibility(View.VISIBLE);
|
||||
|
||||
if (isLoggedIn) {
|
||||
new StoryStatusFetcher(profileId, hashtagModel.getName(), false, result -> {
|
||||
new iStoryStatusFetcher(hashtagModel.getName(), null, false, true, result -> {
|
||||
main.storyModels = result;
|
||||
if (result != null && result.length > 0) main.mainBinding.mainHashtagImage.setStoriesBorder();
|
||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
@ -774,7 +772,7 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
|
||||
final String cookie = Utils.settingsHelper.getString(Constants.COOKIE);
|
||||
final boolean isLoggedIn = !Utils.isEmpty(cookie);
|
||||
if (isLoggedIn) {
|
||||
new StoryStatusFetcher(profileId, "", false, result -> {
|
||||
new iStoryStatusFetcher(profileId, profileModel.getUsername(), false, false, result -> {
|
||||
main.storyModels = result;
|
||||
if (result != null && result.length > 0) main.mainBinding.mainProfileImage.setStoriesBorder();
|
||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
@ -971,7 +969,7 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
|
||||
main.mainBinding.toolbar.toolbar.setTitle(main.userQuery);
|
||||
main.mainBinding.locInfoContainer.setVisibility(View.VISIBLE);
|
||||
|
||||
currentlyExecuting = new LocationFetcher(main.userQuery, locationModel -> {
|
||||
currentlyExecuting = new LocationFetcher(main.userQuery.split("/")[0], locationModel -> {
|
||||
main.locationModel = locationModel;
|
||||
|
||||
main.mainBinding.toolbar.toolbar.setTitle(locationModel.getName());
|
||||
@ -988,7 +986,7 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
|
||||
final String cookie = Utils.settingsHelper.getString(Constants.COOKIE);
|
||||
final boolean isLoggedIn = !Utils.isEmpty(cookie);
|
||||
if (isLoggedIn) {
|
||||
new StoryStatusFetcher(profileId, "", true, result -> {
|
||||
new iStoryStatusFetcher(profileId.split("/")[0], null, true, false, result -> {
|
||||
main.storyModels = result;
|
||||
if (result != null && result.length > 0) main.mainBinding.mainLocationImage.setStoriesBorder();
|
||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
@ -1199,7 +1197,7 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
|
||||
private final View.OnClickListener profileActionListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
final boolean iamme = isLoggedIn
|
||||
final boolean iamme = (isLoggedIn && main.profileModel != null)
|
||||
? Utils.getUserIdFromCookie(Utils.settingsHelper.getString(Constants.COOKIE)).equals(main.profileModel.getId())
|
||||
: false;
|
||||
if (!isLoggedIn && Utils.dataBox.getFavorite(main.userQuery) != null && v == main.mainBinding.btnFollow) {
|
||||
|
@ -50,6 +50,7 @@ public final class CommentsViewer extends BaseLanguageActivity implements SwipeR
|
||||
private final String cookie = Utils.settingsHelper.getString(Constants.COOKIE);
|
||||
private Resources resources;
|
||||
private InputMethodManager imm;
|
||||
private View focus;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
@ -122,7 +123,8 @@ public final class CommentsViewer extends BaseLanguageActivity implements SwipeR
|
||||
} else if (which == 3) {
|
||||
Utils.copyText(this, commentModel.getText().toString());
|
||||
} else if (which == 4) {
|
||||
commentsBinding.rvComments.findViewWithTag(commentModel).setBackgroundColor(0x80888888);
|
||||
focus = commentsBinding.rvComments.findViewWithTag(commentModel);
|
||||
focus.setBackgroundColor(0x80888888);
|
||||
commentsBinding.commentCancelParent.setVisibility(View.VISIBLE);
|
||||
String mention = "@"+profileModel.getUsername()+" ";
|
||||
commentsBinding.commentText.setText(mention);
|
||||
@ -200,10 +202,11 @@ public final class CommentsViewer extends BaseLanguageActivity implements SwipeR
|
||||
Toast.makeText(getApplicationContext(), R.string.comment_send_empty_comment, Toast.LENGTH_SHORT).show();
|
||||
else if (v == commentsBinding.commentSend) new CommentAction().execute("add");
|
||||
else if (v == commentsBinding.commentCancelParent) {
|
||||
commentsBinding.rvComments.findViewWithTag(commentModel).setBackgroundColor(commentModel.getLiked() ? 0x40FF69B4 : 0x00000000);
|
||||
focus.setBackgroundColor(commentModel.getLiked() ? 0x40FF69B4 : 0x00000000);
|
||||
commentsBinding.commentCancelParent.setVisibility(View.GONE);
|
||||
commentsBinding.commentText.setText("");
|
||||
commentModel = null;
|
||||
focus = null;
|
||||
}
|
||||
};
|
||||
|
||||
@ -287,9 +290,11 @@ public final class CommentsViewer extends BaseLanguageActivity implements SwipeR
|
||||
@Override
|
||||
protected void onPostExecute(Void result) {
|
||||
if (ok == true) {
|
||||
if (commentModel != null) {
|
||||
commentsBinding.rvComments.findViewWithTag(commentModel).setBackgroundColor(commentModel.getLiked() ? 0x40FF69B4 : 0x00000000);
|
||||
if (focus != null) {
|
||||
focus.setBackgroundColor(commentModel.getLiked() ? 0x40FF69B4 : 0x00000000);
|
||||
commentsBinding.commentCancelParent.setVisibility(View.GONE);
|
||||
commentModel = null;
|
||||
focus = null;
|
||||
}
|
||||
|
||||
//imm.hideSoftInputFromWindow(commentsBinding.getView().getRootView().getWindowToken(), 0);
|
||||
|
@ -110,7 +110,7 @@ public final class DirectMessagesUserInbox extends AppCompatActivity {
|
||||
switch (itemType) {
|
||||
case MEDIA_SHARE:
|
||||
startActivity(new Intent(this, PostViewer.class)
|
||||
.putExtra(Constants.EXTRAS_POST, new PostModel(directItemModel.getMediaModel().getCode())));
|
||||
.putExtra(Constants.EXTRAS_POST, new PostModel(directItemModel.getMediaModel().getCode(), false)));
|
||||
break;
|
||||
case LINK:
|
||||
Intent linkIntent = new Intent(Intent.ACTION_VIEW);
|
||||
|
@ -92,7 +92,7 @@ public final class NotificationsViewer extends BaseLanguageActivity implements S
|
||||
searchUsername(notificationModel.getUsername());
|
||||
else if (which == 1)
|
||||
startActivity(new Intent(getApplicationContext(), PostViewer.class)
|
||||
.putExtra(Constants.EXTRAS_POST, new PostModel(notificationModel.getShortcode())));
|
||||
.putExtra(Constants.EXTRAS_POST, new PostModel(notificationModel.getShortcode(), false)));
|
||||
};
|
||||
|
||||
private final View.OnClickListener clickListener = v -> {
|
||||
|
@ -57,9 +57,11 @@ import awais.instagrabber.R;
|
||||
import awais.instagrabber.adapters.PostsMediaAdapter;
|
||||
import awais.instagrabber.asyncs.PostFetcher;
|
||||
import awais.instagrabber.asyncs.ProfileFetcher;
|
||||
import awais.instagrabber.asyncs.i.iPostFetcher;
|
||||
import awais.instagrabber.customviews.CommentMentionClickSpan;
|
||||
import awais.instagrabber.customviews.helpers.SwipeGestureListener;
|
||||
import awais.instagrabber.databinding.ActivityViewerBinding;
|
||||
import awais.instagrabber.interfaces.FetchListener;
|
||||
import awais.instagrabber.interfaces.SwipeEvent;
|
||||
import awais.instagrabber.models.BasePostModel;
|
||||
import awais.instagrabber.models.PostModel;
|
||||
@ -185,6 +187,83 @@ public final class PostViewer extends BaseLanguageActivity {
|
||||
private final PostsMediaAdapter mediaAdapter = new PostsMediaAdapter(null, onClickListener);
|
||||
private RequestManager glideRequestManager;
|
||||
private LinearLayout.LayoutParams containerLayoutParams;
|
||||
private final FetchListener<ViewerPostModel[]> pfl = result -> {
|
||||
if (result == null || result.length < 1) {
|
||||
Toast.makeText(this, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
viewerPostModel = result[0];
|
||||
|
||||
mediaAdapter.setData(result);
|
||||
if (result.length > 1) {
|
||||
viewerBinding.mediaList.setLayoutParams(new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT, 0, 0.55f
|
||||
));
|
||||
containerLayoutParams.weight = 1.35f;
|
||||
containerLayoutParams.weight += (Utils.isEmpty(settingsHelper.getString(Constants.COOKIE))) ? 0.3f : 0;
|
||||
viewerBinding.container.setLayoutParams(containerLayoutParams);
|
||||
viewerBinding.mediaList.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
final View viewStoryPost = findViewById(R.id.viewStoryPost);
|
||||
if (viewStoryPost != null) {
|
||||
viewStoryPost.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
if (profileModel.isPrivate())
|
||||
Toast.makeText(getApplicationContext(), R.string.share_private_post, Toast.LENGTH_LONG).show();
|
||||
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
|
||||
sharingIntent.setType("text/plain");
|
||||
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, "https://instagram.com/p/"+postModel.getShortCode());
|
||||
startActivity(Intent.createChooser(sharingIntent,
|
||||
(profileModel.isPrivate()) ? getString(R.string.share_private_post) : getString(R.string.share_public_post)));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
viewerCaptionParent.setOnTouchListener(gestureTouchListener);
|
||||
viewerBinding.playerView.setOnTouchListener(gestureTouchListener);
|
||||
viewerBinding.imageViewer.setOnSingleFlingListener((e1, e2, velocityX, velocityY) -> {
|
||||
final float diffX = e2.getX() - e1.getX();
|
||||
if (Math.abs(diffX) > Math.abs(e2.getY() - e1.getY()) && Math.abs(diffX) > SwipeGestureListener.SWIPE_THRESHOLD
|
||||
&& Math.abs(velocityX) > SwipeGestureListener.SWIPE_VELOCITY_THRESHOLD) {
|
||||
swipeEvent.onSwipe(diffX > 0);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
final long commentsCount = viewerPostModel.getCommentsCount();
|
||||
viewerBinding.bottomPanel.commentsCount.setText(String.valueOf(commentsCount));
|
||||
viewerBinding.bottomPanel.btnComments.setVisibility(View.VISIBLE);
|
||||
|
||||
viewerBinding.bottomPanel.btnComments.setOnClickListener(v ->
|
||||
startActivityForResult(new Intent(this, CommentsViewer.class)
|
||||
.putExtra(Constants.EXTRAS_SHORTCODE, postShortCode)
|
||||
.putExtra(Constants.EXTRAS_POST, viewerPostModel.getPostId())
|
||||
.putExtra(Constants.EXTRAS_USER, postUserId), 6969));
|
||||
viewerBinding.bottomPanel.btnComments.setClickable(true);
|
||||
viewerBinding.bottomPanel.btnComments.setEnabled(true);
|
||||
|
||||
if (postModel instanceof PostModel) {
|
||||
final PostModel postModel = (PostModel) this.postModel;
|
||||
postModel.setPostId(viewerPostModel.getPostId());
|
||||
postModel.setTimestamp(viewerPostModel.getTimestamp());
|
||||
postModel.setPostCaption(viewerPostModel.getPostCaption());
|
||||
postModel.setLike(viewerPostModel.getLike());
|
||||
postModel.setBookmark(viewerPostModel.getBookmark());
|
||||
}
|
||||
|
||||
setupPostInfoBar("@"+viewerPostModel.getUsername(), viewerPostModel.getItemType(),
|
||||
viewerPostModel.getLocation() == null ? null : viewerPostModel.getLocation());
|
||||
|
||||
postCaption = postModel.getPostCaption();
|
||||
viewerCaptionParent.setVisibility(View.VISIBLE);
|
||||
|
||||
viewerBinding.bottomPanel.btnDownload.setOnClickListener(downloadClickListener);
|
||||
|
||||
refreshPost();
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
@ -341,85 +420,10 @@ public final class PostViewer extends BaseLanguageActivity {
|
||||
viewerBinding.imageViewer.setImageResource(0);
|
||||
viewerBinding.imageViewer.setImageDrawable(null);
|
||||
|
||||
new PostFetcher(postModel.getShortCode(), result -> {
|
||||
if (result == null || result.length < 1) {
|
||||
Toast.makeText(this, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
viewerPostModel = result[0];
|
||||
commentsEndCursor = viewerPostModel.getCommentsEndCursor();
|
||||
|
||||
mediaAdapter.setData(result);
|
||||
if (result.length > 1) {
|
||||
viewerBinding.mediaList.setLayoutParams(new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT, 0, 0.55f
|
||||
));
|
||||
containerLayoutParams.weight = 1.35f;
|
||||
containerLayoutParams.weight += (Utils.isEmpty(settingsHelper.getString(Constants.COOKIE))) ? 0.3f : 0;
|
||||
viewerBinding.container.setLayoutParams(containerLayoutParams);
|
||||
viewerBinding.mediaList.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
final View viewStoryPost = findViewById(R.id.viewStoryPost);
|
||||
if (viewStoryPost != null) {
|
||||
viewStoryPost.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
if (profileModel.isPrivate())
|
||||
Toast.makeText(getApplicationContext(), R.string.share_private_post, Toast.LENGTH_LONG).show();
|
||||
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
|
||||
sharingIntent.setType("text/plain");
|
||||
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, "https://instagram.com/p/"+postModel.getShortCode());
|
||||
startActivity(Intent.createChooser(sharingIntent,
|
||||
(profileModel.isPrivate()) ? getString(R.string.share_private_post) : getString(R.string.share_public_post)));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
viewerCaptionParent.setOnTouchListener(gestureTouchListener);
|
||||
viewerBinding.playerView.setOnTouchListener(gestureTouchListener);
|
||||
viewerBinding.imageViewer.setOnSingleFlingListener((e1, e2, velocityX, velocityY) -> {
|
||||
final float diffX = e2.getX() - e1.getX();
|
||||
if (Math.abs(diffX) > Math.abs(e2.getY() - e1.getY()) && Math.abs(diffX) > SwipeGestureListener.SWIPE_THRESHOLD
|
||||
&& Math.abs(velocityX) > SwipeGestureListener.SWIPE_VELOCITY_THRESHOLD) {
|
||||
swipeEvent.onSwipe(diffX > 0);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
final long commentsCount = viewerPostModel.getCommentsCount();
|
||||
viewerBinding.bottomPanel.commentsCount.setText(String.valueOf(commentsCount));
|
||||
viewerBinding.bottomPanel.btnComments.setVisibility(View.VISIBLE);
|
||||
|
||||
viewerBinding.bottomPanel.btnComments.setOnClickListener(v ->
|
||||
startActivityForResult(new Intent(this, CommentsViewer.class)
|
||||
.putExtra(Constants.EXTRAS_END_CURSOR, commentsEndCursor)
|
||||
.putExtra(Constants.EXTRAS_SHORTCODE, postShortCode)
|
||||
.putExtra(Constants.EXTRAS_POST, viewerPostModel.getPostId())
|
||||
.putExtra(Constants.EXTRAS_USER, postUserId), 6969));
|
||||
viewerBinding.bottomPanel.btnComments.setClickable(true);
|
||||
viewerBinding.bottomPanel.btnComments.setEnabled(true);
|
||||
|
||||
if (postModel instanceof PostModel) {
|
||||
final PostModel postModel = (PostModel) this.postModel;
|
||||
postModel.setPostId(viewerPostModel.getPostId());
|
||||
postModel.setTimestamp(viewerPostModel.getTimestamp());
|
||||
postModel.setPostCaption(viewerPostModel.getPostCaption());
|
||||
postModel.setLike(viewerPostModel.getLike());
|
||||
postModel.setBookmark(viewerPostModel.getBookmark());
|
||||
}
|
||||
|
||||
setupPostInfoBar("@"+viewerPostModel.getUsername(), viewerPostModel.getItemType(),
|
||||
viewerPostModel.getLocation() == null ? null : viewerPostModel.getLocation());
|
||||
|
||||
postCaption = postModel.getPostCaption();
|
||||
viewerCaptionParent.setVisibility(View.VISIBLE);
|
||||
|
||||
viewerBinding.bottomPanel.btnDownload.setOnClickListener(downloadClickListener);
|
||||
|
||||
refreshPost();
|
||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
if (postModel.getShortCode() != null)
|
||||
new PostFetcher(postModel.getShortCode(), pfl).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
else if (postModel.getPostId() != null)
|
||||
new iPostFetcher(postModel.getPostId(), pfl).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
private void searchUsername(final String text) {
|
||||
@ -673,7 +677,7 @@ public final class PostViewer extends BaseLanguageActivity {
|
||||
viewerBinding.topPanel.ivProfilePic.setImageDrawable(null);
|
||||
viewerBinding.topPanel.ivProfilePic.setImageResource(0);
|
||||
|
||||
if (from.charAt(0) == '@')
|
||||
if (!Utils.isEmpty(from) && from.charAt(0) == '@')
|
||||
new ProfileFetcher(from.substring(1), result -> {
|
||||
profileModel = result;
|
||||
|
||||
|
@ -10,12 +10,15 @@ import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.text.InputType;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@ -43,6 +46,10 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import awais.instagrabber.BuildConfig;
|
||||
import awais.instagrabber.R;
|
||||
@ -52,7 +59,8 @@ import awais.instagrabber.customviews.helpers.SwipeGestureListener;
|
||||
import awais.instagrabber.databinding.ActivityStoryViewerBinding;
|
||||
import awais.instagrabber.interfaces.SwipeEvent;
|
||||
import awais.instagrabber.models.FeedStoryModel;
|
||||
import awais.instagrabber.models.PollModel;
|
||||
import awais.instagrabber.models.stickers.PollModel;
|
||||
import awais.instagrabber.models.stickers.QuestionModel;
|
||||
import awais.instagrabber.models.PostModel;
|
||||
import awais.instagrabber.models.StoryModel;
|
||||
import awais.instagrabber.models.enums.MediaItemType;
|
||||
@ -86,6 +94,8 @@ public final class StoryViewer extends BaseLanguageActivity {
|
||||
private SwipeEvent swipeEvent;
|
||||
private MenuItem menuDownload;
|
||||
private PollModel poll;
|
||||
private QuestionModel question;
|
||||
private String[] mentions;
|
||||
private StoryModel currentStory;
|
||||
private String url, username;
|
||||
private int slidePos = 0, lastSlidePos = 0;
|
||||
@ -206,10 +216,10 @@ public final class StoryViewer extends BaseLanguageActivity {
|
||||
storyViewerBinding.viewStoryPost.setOnClickListener(v -> {
|
||||
final Object tag = v.getTag();
|
||||
if (tag instanceof CharSequence) startActivity(new Intent(this, PostViewer.class)
|
||||
.putExtra(Constants.EXTRAS_POST, new PostModel(tag.toString())));
|
||||
.putExtra(Constants.EXTRAS_POST, new PostModel(tag.toString(), tag.toString().matches("^[\\d]+$"))));
|
||||
});
|
||||
|
||||
storyViewerBinding.interactStory.setOnClickListener(v -> {
|
||||
final View.OnClickListener storyActionListener = v -> {
|
||||
final Object tag = v.getTag();
|
||||
if (tag instanceof PollModel) {
|
||||
poll = (PollModel) tag;
|
||||
@ -231,7 +241,32 @@ public final class StoryViewer extends BaseLanguageActivity {
|
||||
.setPositiveButton(R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
});
|
||||
else if (tag instanceof QuestionModel) {
|
||||
question = (QuestionModel) tag;
|
||||
final EditText input = new EditText(this);
|
||||
input.setHint(R.string.answer_hint);
|
||||
new AlertDialog.Builder(this).setTitle(question.getQuestion())
|
||||
.setView(input)
|
||||
.setPositiveButton(R.string.ok, (d,w) -> {
|
||||
new RespondAction().execute(input.getText().toString());
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
else if (tag instanceof String[]) {
|
||||
mentions = (String[]) tag;
|
||||
new AlertDialog.Builder(this).setTitle(R.string.story_mentions)
|
||||
.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, mentions), (d,w) -> {
|
||||
searchUsername(mentions[w]);
|
||||
})
|
||||
.setPositiveButton(R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
};
|
||||
|
||||
storyViewerBinding.poll.setOnClickListener(storyActionListener);
|
||||
storyViewerBinding.answer.setOnClickListener(storyActionListener);
|
||||
storyViewerBinding.mention.setOnClickListener(storyActionListener);
|
||||
|
||||
storiesAdapter.setData(storyModels);
|
||||
if (storyModels.length > 1) storyViewerBinding.storiesList.setVisibility(View.VISIBLE);
|
||||
@ -410,10 +445,17 @@ public final class StoryViewer extends BaseLanguageActivity {
|
||||
storyViewerBinding.spotify.setVisibility(spotify != null ? View.VISIBLE : View.GONE);
|
||||
storyViewerBinding.spotify.setTag(spotify);
|
||||
|
||||
final PollModel poll = currentStory.getPoll();
|
||||
storyViewerBinding.interactStory.setVisibility(poll != null ? View.VISIBLE : View.GONE);
|
||||
storyViewerBinding.interactStory.setText(R.string.vote_story_poll);
|
||||
storyViewerBinding.interactStory.setTag(poll);
|
||||
poll = currentStory.getPoll();
|
||||
storyViewerBinding.poll.setVisibility(poll != null ? View.VISIBLE : View.GONE);
|
||||
storyViewerBinding.poll.setTag(poll);
|
||||
|
||||
question = currentStory.getQuestion();
|
||||
storyViewerBinding.answer.setVisibility(question != null ? View.VISIBLE : View.GONE);
|
||||
storyViewerBinding.answer.setTag(question);
|
||||
|
||||
mentions = currentStory.getMentions();
|
||||
storyViewerBinding.mention.setVisibility((mentions != null && mentions.length > 0) ? View.VISIBLE : View.GONE);
|
||||
storyViewerBinding.mention.setTag(mentions);
|
||||
|
||||
releasePlayer();
|
||||
final Intent intent = getIntent();
|
||||
@ -497,4 +539,53 @@ public final class StoryViewer extends BaseLanguageActivity {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RespondAction extends AsyncTask<String, Void, Void> {
|
||||
boolean ok = false;
|
||||
String action;
|
||||
|
||||
protected Void doInBackground(String... rawchoice) {
|
||||
final String cookie = settingsHelper.getString(Constants.COOKIE);
|
||||
final String url = "https://i.instagram.com/api/v1/media/"
|
||||
+currentStory.getStoryMediaId()+"/"+question.getId()+"/story_question_response/";
|
||||
try {
|
||||
JSONObject ogbody = new JSONObject("{\"client_context\":\"" + UUID.randomUUID().toString()
|
||||
+"\",\"mutation_token\":\"" + UUID.randomUUID().toString()
|
||||
+"\",\"_csrftoken\":\"" + cookie.split("csrftoken=")[1].split(";")[0]
|
||||
+"\",\"_uid\":\"" + Utils.getUserIdFromCookie(cookie)
|
||||
+"\",\"__uuid\":\"" + settingsHelper.getString(Constants.DEVICE_UUID)
|
||||
+"\"}");
|
||||
String choice = rawchoice[0].replaceAll("\"", ("\\\""));
|
||||
ogbody.put("response", choice);
|
||||
String urlParameters = Utils.sign(ogbody.toString());
|
||||
final HttpURLConnection 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) {
|
||||
ok = true;
|
||||
}
|
||||
else Toast.makeText(getApplicationContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
urlConnection.disconnect();
|
||||
} catch (Throwable ex) {
|
||||
Log.e("austin_debug", "vote: " + ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void result) {
|
||||
if (ok) {
|
||||
Toast.makeText(getApplicationContext(), R.string.answered_story, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -93,7 +93,7 @@ public final class FeedAdapter extends RecyclerView.Adapter<FeedItemViewHolder>
|
||||
case R.id.viewStoryPost:
|
||||
activity.startActivity(new Intent(activity, PostViewer.class)
|
||||
.putExtra(Constants.EXTRAS_INDEX, feedModel.getPosition())
|
||||
.putExtra(Constants.EXTRAS_POST, new PostModel(feedModel.getShortCode()))
|
||||
.putExtra(Constants.EXTRAS_POST, new PostModel(feedModel.getShortCode(), false))
|
||||
.putExtra(Constants.EXTRAS_TYPE, ItemGetType.FEED_ITEMS));
|
||||
break;
|
||||
|
||||
@ -210,15 +210,9 @@ public final class FeedAdapter extends RecyclerView.Adapter<FeedItemViewHolder>
|
||||
final long commentsCount = feedModel.getCommentsCount();
|
||||
viewHolder.commentsCount.setText(String.valueOf(commentsCount));
|
||||
|
||||
if (commentsCount <= 0) {
|
||||
viewHolder.btnComments.setTag(null);
|
||||
viewHolder.btnComments.setOnClickListener(null);
|
||||
viewHolder.btnComments.setEnabled(false);
|
||||
} else {
|
||||
viewHolder.btnComments.setTag(feedModel);
|
||||
viewHolder.btnComments.setOnClickListener(clickListener);
|
||||
viewHolder.btnComments.setEnabled(true);
|
||||
}
|
||||
viewHolder.btnComments.setTag(feedModel);
|
||||
viewHolder.btnComments.setOnClickListener(clickListener);
|
||||
viewHolder.btnComments.setEnabled(true);
|
||||
|
||||
final JSONObject location = feedModel.getLocation();
|
||||
|
||||
@ -234,6 +228,12 @@ public final class FeedAdapter extends RecyclerView.Adapter<FeedItemViewHolder>
|
||||
viewHolder.username.setLayoutParams(new RelativeLayout.LayoutParams(
|
||||
RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT
|
||||
));
|
||||
viewHolder.location.setOnClickListener(v ->
|
||||
new AlertDialog.Builder(v.getContext()).setTitle(location.optString("name"))
|
||||
.setMessage(R.string.comment_view_mention_location_search)
|
||||
.setNegativeButton(R.string.cancel, null).setPositiveButton(R.string.ok,
|
||||
(dialog, which) -> mentionClickListener.onClick(null, location.optString("id")+"/"+location.optString("slug"), false)).show()
|
||||
);
|
||||
}
|
||||
|
||||
final String thumbnailUrl = feedModel.getThumbnailUrl();
|
||||
|
@ -68,14 +68,21 @@ public final class FeedStoriesFetcher extends AsyncTask<Void, Void, FeedStoryMod
|
||||
feedStoryModels[i] = new FeedStoryModel(id, profileModel);
|
||||
}
|
||||
|
||||
url = "https://www.instagram.com/graphql/query/?query_hash=0a85e6ea60a4c99edc58ab2f3d17cfdf&variables=" +
|
||||
"{\"reel_ids\":" + Utils.highlightIdsMerger(feedStoryIDs) + ",\"precomposed_overlay\":false}";
|
||||
conn = (HttpURLConnection) new URL(url).openConnection();
|
||||
conn.setInstanceFollowRedirects(false);
|
||||
conn.setUseCaches(false);
|
||||
conn.connect();
|
||||
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||
Utils.putHighlightModels(conn, feedStoryModels);
|
||||
for (int s = 0; s <= Math.ceil(feedStoryIDs.length / 20); ++s) {
|
||||
String[] shard = new String[Math.min(20, (feedStoryIDs.length - s*20))];
|
||||
FeedStoryModel[] feedStoryShard = new FeedStoryModel[Math.min(20, (feedStoryIDs.length - s*20))];
|
||||
System.arraycopy(feedStoryIDs, s*20, shard, 0, shard.length);
|
||||
System.arraycopy(feedStoryModels, s*20, feedStoryShard, 0, shard.length);
|
||||
url = "https://i.instagram.com/api/v1/feed/reels_media/?reel_ids=" + Utils.iHighlightIdsMerger(shard);
|
||||
conn = (HttpURLConnection) new URL(url).openConnection();
|
||||
conn.setRequestProperty("User-Agent", Constants.USER_AGENT);
|
||||
conn.setInstanceFollowRedirects(false);
|
||||
conn.setUseCaches(false);
|
||||
conn.setReadTimeout(2000);
|
||||
conn.connect();
|
||||
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||
Utils.iPutFeedStoryModels(conn, feedStoryShard, shard);
|
||||
}
|
||||
}
|
||||
|
||||
result = feedStoryModels;
|
||||
|
@ -26,7 +26,7 @@ public final class LocationFetcher extends AsyncTask<Void, Void, LocationModel>
|
||||
private final String idSlug;
|
||||
|
||||
public LocationFetcher(String idSlug, FetchListener<LocationModel> fetchListener) {
|
||||
// idSlug = id + "/" + slug
|
||||
// idSlug = id + "/" + slug UPDATE: slug can be ignored tbh
|
||||
this.idSlug = idSlug;
|
||||
this.fetchListener = fetchListener;
|
||||
}
|
||||
|
@ -97,7 +97,6 @@ public final class PostFetcher extends AsyncTask<Void, Void, ViewerPostModel[]>
|
||||
media.optJSONObject("location"));
|
||||
|
||||
postModel.setCommentsCount(commentsCount);
|
||||
postModel.setCommentsEndCursor(endCursor);
|
||||
|
||||
Utils.checkExistence(downloadDir, customDir, false, postModel);
|
||||
|
||||
@ -127,7 +126,6 @@ public final class PostFetcher extends AsyncTask<Void, Void, ViewerPostModel[]>
|
||||
}
|
||||
|
||||
postModels[0].setCommentsCount(commentsCount);
|
||||
postModels[0].setCommentsEndCursor(endCursor);
|
||||
|
||||
result = postModels;
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ public final class ProfileFetcher extends AsyncTask<Void, Void, ProfileModel> {
|
||||
final JSONObject timelineMedia = user.getJSONObject("edge_owner_to_timeline_media");
|
||||
if (timelineMedia.has("edges")) {
|
||||
final JSONArray edges = timelineMedia.getJSONArray("edges");
|
||||
if (edges.length() > 0) reallyPrivate = false;
|
||||
if (edges.length() > 0 || timelineMedia.getLong("count") == 0L) reallyPrivate = false;
|
||||
}
|
||||
|
||||
String url = user.optString("external_url");
|
||||
|
@ -5,6 +5,10 @@ import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.select.Elements;
|
||||
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
@ -33,11 +37,11 @@ public final class ProfilePictureFetcher extends AsyncTask<Void, Void, String> {
|
||||
|
||||
@Override
|
||||
protected String doInBackground(final Void... voids) {
|
||||
String out = picUrl;
|
||||
if (!isHashtag) try {
|
||||
final String url = "https://i.instagram.com/api/v1/users/"+userId+"/info/";
|
||||
|
||||
final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
|
||||
String out = null;
|
||||
if (isHashtag) out = picUrl;
|
||||
else try {
|
||||
final HttpURLConnection conn =
|
||||
(HttpURLConnection) new URL("https://i.instagram.com/api/v1/users/"+userId+"/info/").openConnection();
|
||||
conn.setUseCaches(false);
|
||||
conn.setRequestMethod("GET");
|
||||
conn.setRequestProperty("User-Agent", Constants.USER_AGENT);
|
||||
@ -50,13 +54,45 @@ public final class ProfilePictureFetcher extends AsyncTask<Void, Void, String> {
|
||||
if (data.has("hd_profile_pic_url_info"))
|
||||
out = data.getJSONObject("hd_profile_pic_url_info").optString("url");
|
||||
}
|
||||
|
||||
if (Utils.isEmpty(out)) {
|
||||
final HttpURLConnection backup =
|
||||
(HttpURLConnection) new URL("https://instadp.com/fullsize/" + userName).openConnection();
|
||||
backup.setUseCaches(false);
|
||||
backup.setRequestMethod("GET");
|
||||
|
||||
final String instadp = backup.getResponseCode() == HttpURLConnection.HTTP_OK ? Utils.readFromConnection(backup) : null;
|
||||
backup.disconnect();
|
||||
|
||||
if (!Utils.isEmpty(instadp)) {
|
||||
final Document doc = Jsoup.parse(instadp);
|
||||
boolean fallback = false;
|
||||
|
||||
final int imgIndex = instadp.indexOf("preloadImg('"), lastIndex;
|
||||
|
||||
Element element = doc.selectFirst(".instadp");
|
||||
if (element != null && (element = element.selectFirst(".picture")) != null)
|
||||
out = element.attr("src");
|
||||
else if ((element = doc.selectFirst(".download-btn")) != null)
|
||||
out = element.attr("href");
|
||||
else if (imgIndex != -1 && (lastIndex = instadp.indexOf("')", imgIndex)) != -1)
|
||||
out = instadp.substring(imgIndex + 12, lastIndex);
|
||||
else {
|
||||
final Elements imgs = doc.getElementsByTag("img");
|
||||
for (final Element img : imgs) {
|
||||
final String imgStr = img.toString();
|
||||
if (imgStr.contains("cdninstagram.com")) out = img.attr("src");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (out == null) out = picUrl;
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
if (logCollector != null)
|
||||
logCollector.appendException(e, LogCollector.LogFile.ASYNC_PROFILE_PICTURE_FETCHER, "doInBackground");
|
||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
||||
}
|
||||
|
||||
if (out == null) out = picUrl;
|
||||
return out;
|
||||
}
|
||||
|
||||
|
@ -1,121 +0,0 @@
|
||||
package awais.instagrabber.asyncs;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
import awais.instagrabber.BuildConfig;
|
||||
import awais.instagrabber.interfaces.FetchListener;
|
||||
import awais.instagrabber.models.enums.MediaItemType;
|
||||
import awais.instagrabber.models.PollModel;
|
||||
import awais.instagrabber.models.StoryModel;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
import awaisomereport.LogCollector;
|
||||
|
||||
import static awais.instagrabber.utils.Utils.logCollector;
|
||||
|
||||
public final class StoryStatusFetcher extends AsyncTask<Void, Void, StoryModel[]> {
|
||||
private final String id, hashtag;
|
||||
private final boolean location;
|
||||
private final FetchListener<StoryModel[]> fetchListener;
|
||||
|
||||
public StoryStatusFetcher(final String id, final String hashtag, final boolean location, final FetchListener<StoryModel[]> fetchListener) {
|
||||
this.id = id;
|
||||
this.hashtag = hashtag;
|
||||
this.location = location;
|
||||
this.fetchListener = fetchListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected StoryModel[] doInBackground(final Void... voids) {
|
||||
StoryModel[] result = null;
|
||||
final String url = "https://www.instagram.com/graphql/query/?query_hash=90709b530ea0969f002c86a89b4f2b8d&variables=" +
|
||||
"{\"precomposed_overlay\":false,\"show_story_viewer_list\":false,\"stories_video_dash_manifest\":false,"
|
||||
+(!Utils.isEmpty(hashtag) ? ("\"tag_names\":\""+hashtag+"\"}") : (
|
||||
location ? "\"location_ids\":[\""+id.split("/")[0]+"\"]}" : "\"reel_ids\":[\"" + id + "\"]}"));
|
||||
|
||||
try {
|
||||
final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
|
||||
conn.setInstanceFollowRedirects(false);
|
||||
conn.setUseCaches(false);
|
||||
conn.connect();
|
||||
|
||||
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||
JSONObject data = new JSONObject(Utils.readFromConnection(conn)).getJSONObject("data");
|
||||
|
||||
JSONArray media;
|
||||
if ((media = data.optJSONArray("reels_media")) != null && media.length() > 0 &&
|
||||
(data = media.optJSONObject(0)) != null &&
|
||||
(media = data.optJSONArray("items")) != null) {
|
||||
|
||||
final int mediaLen = media.length();
|
||||
|
||||
final StoryModel[] models = new StoryModel[mediaLen];
|
||||
for (int i = 0; i < mediaLen; ++i) {
|
||||
data = media.getJSONObject(i);
|
||||
final boolean isVideo = data.getBoolean("is_video");
|
||||
|
||||
final JSONArray tappableObjects = data.optJSONArray("tappable_objects");
|
||||
final int tappableLength = tappableObjects != null ? tappableObjects.length() : 0;
|
||||
|
||||
models[i] = new StoryModel(data.getString(Constants.EXTRAS_ID),
|
||||
data.getString("display_url"),
|
||||
isVideo ? MediaItemType.MEDIA_TYPE_VIDEO : MediaItemType.MEDIA_TYPE_IMAGE,
|
||||
data.optLong("taken_at_timestamp", 0),
|
||||
data.getJSONObject("owner").getString("username"));
|
||||
|
||||
final JSONArray videoResources = data.optJSONArray("video_resources");
|
||||
if (isVideo && videoResources != null)
|
||||
models[i].setVideoUrl(Utils.getHighQualityPost(videoResources, true));
|
||||
|
||||
if (!data.isNull("story_app_attribution"))
|
||||
models[i].setSpotify(data.getJSONObject("story_app_attribution").optString("content_url").split("\\?")[0]);
|
||||
|
||||
for (int j = 0; j < tappableLength; ++j) {
|
||||
JSONObject tappableObject = tappableObjects.getJSONObject(j);
|
||||
if (tappableObject.optString("__typename").equals("GraphTappableFeedMedia")) {
|
||||
models[i].setTappableShortCode(tappableObject.getJSONObject("media").getString(Constants.EXTRAS_SHORTCODE));
|
||||
}
|
||||
else if (tappableObject.optString("__typename").equals("GraphTappableStoryPoll")) {
|
||||
models[i].setPoll(new PollModel(
|
||||
tappableObject.getString("id"),
|
||||
tappableObject.getString("question"),
|
||||
tappableObject.getJSONArray("tallies").getJSONObject(0).getString("text"),
|
||||
tappableObject.getJSONArray("tallies").getJSONObject(0).getInt("count"),
|
||||
tappableObject.getJSONArray("tallies").getJSONObject(1).getString("text"),
|
||||
tappableObject.getJSONArray("tallies").getJSONObject(1).getInt("count"),
|
||||
tappableObject.optInt("viewer_vote", -1)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
result = models;
|
||||
}
|
||||
}
|
||||
|
||||
conn.disconnect();
|
||||
} catch (final Exception e) {
|
||||
if (logCollector != null)
|
||||
logCollector.appendException(e, LogCollector.LogFile.ASYNC_STORY_STATUS_FETCHER, "doInBackground");
|
||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
if (fetchListener != null) fetchListener.doBefore();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final StoryModel[] result) {
|
||||
if (fetchListener != null) fetchListener.onResult(result);
|
||||
}
|
||||
}
|
146
app/src/main/java/awais/instagrabber/asyncs/i/iPostFetcher.java
Executable file
146
app/src/main/java/awais/instagrabber/asyncs/i/iPostFetcher.java
Executable file
@ -0,0 +1,146 @@
|
||||
package awais.instagrabber.asyncs.i;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Environment;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
import awais.instagrabber.BuildConfig;
|
||||
import awais.instagrabber.interfaces.FetchListener;
|
||||
import awais.instagrabber.models.ViewerPostModel;
|
||||
import awais.instagrabber.models.enums.MediaItemType;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
import awaisomereport.LogCollector;
|
||||
|
||||
import static awais.instagrabber.utils.Constants.DOWNLOAD_USER_FOLDER;
|
||||
import static awais.instagrabber.utils.Constants.FOLDER_PATH;
|
||||
import static awais.instagrabber.utils.Constants.FOLDER_SAVE_TO;
|
||||
import static awais.instagrabber.utils.Utils.logCollector;
|
||||
|
||||
public final class iPostFetcher extends AsyncTask<Void, Void, ViewerPostModel[]> {
|
||||
private final String id;
|
||||
private final FetchListener<ViewerPostModel[]> fetchListener;
|
||||
|
||||
public iPostFetcher(final String id, final FetchListener<ViewerPostModel[]> fetchListener) {
|
||||
this.id = id;
|
||||
this.fetchListener = fetchListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ViewerPostModel[] doInBackground(final Void... voids) {
|
||||
ViewerPostModel[] result = null;
|
||||
try {
|
||||
final HttpURLConnection conn = (HttpURLConnection) new URL("https://i.instagram.com/api/v1/media/" + id + "/info").openConnection();
|
||||
conn.setUseCaches(false);
|
||||
conn.setRequestProperty("User-Agent", Constants.USER_AGENT);
|
||||
conn.connect();
|
||||
|
||||
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||
|
||||
final JSONObject media = new JSONObject(Utils.readFromConnection(conn)).getJSONArray("items").getJSONObject(0);
|
||||
|
||||
final String username = media.has("user") ? media.getJSONObject("user").getString(Constants.EXTRAS_USERNAME) : null;
|
||||
|
||||
// to check if file exists
|
||||
final File downloadDir = new File(Environment.getExternalStorageDirectory(), "Download" +
|
||||
(Utils.settingsHelper.getBoolean(DOWNLOAD_USER_FOLDER) ? ("/"+username) : ""));
|
||||
File customDir = null;
|
||||
if (Utils.settingsHelper.getBoolean(FOLDER_SAVE_TO)) {
|
||||
final String customPath = Utils.settingsHelper.getString(FOLDER_PATH +
|
||||
(Utils.settingsHelper.getBoolean(DOWNLOAD_USER_FOLDER) ? ("/"+username) : ""));
|
||||
if (!Utils.isEmpty(customPath)) customDir = new File(customPath);
|
||||
}
|
||||
|
||||
final long timestamp = media.getLong("taken_at");
|
||||
|
||||
final boolean isVideo = media.has("has_audio") && media.optBoolean("has_audio");
|
||||
final boolean isSlider = !media.isNull("carousel_media_count");
|
||||
|
||||
final MediaItemType mediaItemType;
|
||||
if (isSlider) mediaItemType = MediaItemType.MEDIA_TYPE_SLIDER;
|
||||
else if (isVideo) mediaItemType = MediaItemType.MEDIA_TYPE_VIDEO;
|
||||
else mediaItemType = MediaItemType.MEDIA_TYPE_IMAGE;
|
||||
|
||||
final String postCaption;
|
||||
final JSONObject mediaToCaption = media.optJSONObject("caption");
|
||||
if (mediaToCaption == null) postCaption = null;
|
||||
else postCaption = mediaToCaption.optString("text");
|
||||
|
||||
final long commentsCount = media.optLong("comment_count");
|
||||
|
||||
if (mediaItemType != MediaItemType.MEDIA_TYPE_SLIDER) {
|
||||
final ViewerPostModel postModel = new ViewerPostModel(mediaItemType,
|
||||
media.getString(Constants.EXTRAS_ID),
|
||||
isVideo
|
||||
? Utils.getHighQualityPost(media.optJSONArray("video_versions"), true, true)
|
||||
: Utils.getHighQualityImage(media),
|
||||
media.getString("code"),
|
||||
Utils.isEmpty(postCaption) ? null : postCaption,
|
||||
username,
|
||||
isVideo && media.has("view_count") ? media.getLong("view_count") : -1,
|
||||
timestamp, media.optBoolean("has_liked"), media.optBoolean("has_viewer_saved"),
|
||||
media.getLong("like_count"),
|
||||
media.optJSONObject("location"));
|
||||
|
||||
postModel.setCommentsCount(commentsCount);
|
||||
|
||||
Utils.checkExistence(downloadDir, customDir, false, postModel);
|
||||
|
||||
result = new ViewerPostModel[]{postModel};
|
||||
|
||||
} else {
|
||||
final JSONArray children = media.getJSONArray("carousel_media");
|
||||
final ViewerPostModel[] postModels = new ViewerPostModel[children.length()];
|
||||
|
||||
for (int i = 0; i < postModels.length; ++i) {
|
||||
final JSONObject node = children.getJSONObject(i);
|
||||
final boolean isChildVideo = node.has("video_duration");
|
||||
|
||||
postModels[i] = new ViewerPostModel(isChildVideo ? MediaItemType.MEDIA_TYPE_VIDEO : MediaItemType.MEDIA_TYPE_IMAGE,
|
||||
media.getString(Constants.EXTRAS_ID),
|
||||
isChildVideo
|
||||
? Utils.getHighQualityPost(node.optJSONArray("video_versions"), true, true)
|
||||
: Utils.getHighQualityImage(node),
|
||||
media.getString("code"),
|
||||
postCaption,
|
||||
username,
|
||||
-1,
|
||||
timestamp, media.optBoolean("has_liked"), media.optBoolean("has_viewer_saved"),
|
||||
media.getLong("like_count"),
|
||||
media.optJSONObject("location"));
|
||||
postModels[i].setSliderDisplayUrl(Utils.getHighQualityImage(node));
|
||||
|
||||
Utils.checkExistence(downloadDir, customDir, true, postModels[i]);
|
||||
}
|
||||
|
||||
postModels[0].setCommentsCount(commentsCount);
|
||||
result = postModels;
|
||||
}
|
||||
}
|
||||
|
||||
conn.disconnect();
|
||||
} catch (Exception e) {
|
||||
if (logCollector != null)
|
||||
logCollector.appendException(e, LogCollector.LogFile.ASYNC_POST_FETCHER, "doInBackground (i)");
|
||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
if (fetchListener != null) fetchListener.doBefore();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final ViewerPostModel[] postModels) {
|
||||
if (fetchListener != null) fetchListener.onResult(postModels);
|
||||
}
|
||||
}
|
152
app/src/main/java/awais/instagrabber/asyncs/i/iStoryStatusFetcher.java
Executable file
152
app/src/main/java/awais/instagrabber/asyncs/i/iStoryStatusFetcher.java
Executable file
@ -0,0 +1,152 @@
|
||||
package awais.instagrabber.asyncs.i;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
import awais.instagrabber.BuildConfig;
|
||||
import awais.instagrabber.interfaces.FetchListener;
|
||||
import awais.instagrabber.models.stickers.PollModel;
|
||||
import awais.instagrabber.models.stickers.QuestionModel;
|
||||
import awais.instagrabber.models.StoryModel;
|
||||
import awais.instagrabber.models.enums.MediaItemType;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
import awaisomereport.LogCollector;
|
||||
|
||||
import static awais.instagrabber.utils.Utils.logCollector;
|
||||
|
||||
public final class iStoryStatusFetcher extends AsyncTask<Void, Void, StoryModel[]> {
|
||||
private final String id, username;
|
||||
private final boolean isLoc, isHashtag;
|
||||
private final FetchListener<StoryModel[]> fetchListener;
|
||||
|
||||
public iStoryStatusFetcher(final String id, final String username, final boolean isLoc,
|
||||
final boolean isHashtag, final FetchListener<StoryModel[]> fetchListener) {
|
||||
this.id = id;
|
||||
this.username = username;
|
||||
this.isLoc = isLoc;
|
||||
this.isHashtag = isHashtag;
|
||||
this.fetchListener = fetchListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected StoryModel[] doInBackground(final Void... voids) {
|
||||
StoryModel[] result = null;
|
||||
final String url = "https://i.instagram.com/api/v1/" + (isLoc ? "locations/" : (isHashtag ? "tags/" : "feed/reels_media/?reel_ids="))
|
||||
+ id + ((isLoc || isHashtag) ? "/story/" : "");
|
||||
|
||||
try {
|
||||
final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
|
||||
conn.setInstanceFollowRedirects(false);
|
||||
conn.setUseCaches(false);
|
||||
conn.setRequestProperty("User-Agent", Constants.USER_AGENT);
|
||||
conn.connect();
|
||||
|
||||
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||
JSONObject data = (isLoc || isHashtag)
|
||||
? new JSONObject(Utils.readFromConnection(conn)).getJSONObject("story")
|
||||
: new JSONObject(Utils.readFromConnection(conn)).getJSONObject("reels").getJSONObject(id);
|
||||
|
||||
JSONArray media;
|
||||
if ((media = data.optJSONArray("items")) != null && media.length() > 0 &&
|
||||
(data = media.optJSONObject(0)) != null) {
|
||||
|
||||
final int mediaLen = media.length();
|
||||
|
||||
final StoryModel[] models = new StoryModel[mediaLen];
|
||||
for (int i = 0; i < mediaLen; ++i) {
|
||||
data = media.getJSONObject(i);
|
||||
final boolean isVideo = data.has("has_audio") && data.optBoolean("has_audio");
|
||||
|
||||
models[i] = new StoryModel(data.getString("pk"),
|
||||
data.getJSONObject("image_versions2").getJSONArray("candidates").getJSONObject(0).getString("url"),
|
||||
isVideo ? MediaItemType.MEDIA_TYPE_VIDEO : MediaItemType.MEDIA_TYPE_IMAGE,
|
||||
data.optLong("taken_at", 0),
|
||||
(isLoc || isHashtag) ? data.getJSONObject("user").getString("username") : username);
|
||||
|
||||
final JSONArray videoResources = data.optJSONArray("video_versions");
|
||||
if (isVideo && videoResources != null)
|
||||
models[i].setVideoUrl(Utils.getHighQualityPost(videoResources, true, true));
|
||||
|
||||
if (data.has("story_feed_media")) {
|
||||
models[i].setTappableShortCode(data.getJSONArray("story_feed_media").getJSONObject(0).optString("media_id"));
|
||||
}
|
||||
|
||||
if (!data.isNull("story_app_attribution"))
|
||||
models[i].setSpotify(data.getJSONObject("story_app_attribution").optString("content_url").split("\\?")[0]);
|
||||
|
||||
if (data.has("story_polls")) {
|
||||
JSONObject tappableObject = data.optJSONArray("story_polls").getJSONObject(0).optJSONObject("poll_sticker");
|
||||
if (tappableObject != null) models[i].setPoll(new PollModel(
|
||||
String.valueOf(tappableObject.getLong("poll_id")),
|
||||
tappableObject.getString("question"),
|
||||
tappableObject.getJSONArray("tallies").getJSONObject(0).getString("text"),
|
||||
tappableObject.getJSONArray("tallies").getJSONObject(0).getInt("count"),
|
||||
tappableObject.getJSONArray("tallies").getJSONObject(1).getString("text"),
|
||||
tappableObject.getJSONArray("tallies").getJSONObject(1).getInt("count"),
|
||||
tappableObject.optInt("viewer_vote", -1)
|
||||
));
|
||||
}
|
||||
if (data.has("story_questions")) {
|
||||
JSONObject tappableObject = data.getJSONArray("story_questions").getJSONObject(0).optJSONObject("question_sticker");
|
||||
if (tappableObject != null) models[i].setQuestion(new QuestionModel(
|
||||
String.valueOf(tappableObject.getLong("question_id")),
|
||||
tappableObject.getString("question")
|
||||
));
|
||||
}
|
||||
JSONArray hashtags = data.optJSONArray("story_hashtags");
|
||||
JSONArray locations = data.optJSONArray("story_locations");
|
||||
JSONArray atmarks = data.optJSONArray("reel_mentions");
|
||||
String[] mentions = new String[(hashtags == null ? 0 : hashtags.length())
|
||||
+ (atmarks == null ? 0 : atmarks.length())
|
||||
+ (locations == null ? 0 : locations.length())];
|
||||
if (hashtags != null) {
|
||||
for (int h = 0; h < hashtags.length(); ++h) {
|
||||
mentions[h] = "#"+hashtags.getJSONObject(h).getJSONObject("hashtag").getString("name");
|
||||
}
|
||||
}
|
||||
if (atmarks != null) {
|
||||
for (int h = 0; h < atmarks.length(); ++h) {
|
||||
mentions[h + (hashtags == null ? 0 : hashtags.length())] =
|
||||
"@"+atmarks.getJSONObject(h).getJSONObject("user").getString("username");
|
||||
}
|
||||
}
|
||||
if (locations != null) {
|
||||
for (int h = 0; h < locations.length(); ++h) {
|
||||
mentions[h + (hashtags == null ? 0 : hashtags.length()) + (atmarks == null ? 0 : atmarks.length())] =
|
||||
String.valueOf(locations.getJSONObject(h).getJSONObject("location").getLong("pk"))
|
||||
+"/ ("+locations.getJSONObject(h).getJSONObject("location").getString("short_name")+")";
|
||||
}
|
||||
}
|
||||
if (mentions.length != 0) models[i].setMentions(mentions);
|
||||
}
|
||||
result = models;
|
||||
}
|
||||
}
|
||||
|
||||
conn.disconnect();
|
||||
} catch (final Exception e) {
|
||||
if (logCollector != null)
|
||||
logCollector.appendException(e, LogCollector.LogFile.ASYNC_STORY_STATUS_FETCHER, "doInBackground (i)");
|
||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
if (fetchListener != null) fetchListener.doBefore();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final StoryModel[] result) {
|
||||
if (fetchListener != null) fetchListener.onResult(result);
|
||||
}
|
||||
}
|
@ -7,8 +7,9 @@ public class PostModel extends BasePostModel {
|
||||
protected String endCursor;
|
||||
protected boolean hasNextPage;
|
||||
|
||||
public PostModel(final String shortCode) {
|
||||
this.shortCode = shortCode;
|
||||
public PostModel(final String shortCode, final boolean isid) {
|
||||
if (!isid) this.shortCode = shortCode;
|
||||
else this.postId = shortCode;
|
||||
this.thumbnailUrl = null;
|
||||
}
|
||||
|
||||
|
@ -3,13 +3,17 @@ package awais.instagrabber.models;
|
||||
import java.io.Serializable;
|
||||
|
||||
import awais.instagrabber.models.enums.MediaItemType;
|
||||
import awais.instagrabber.models.stickers.PollModel;
|
||||
import awais.instagrabber.models.stickers.QuestionModel;
|
||||
|
||||
public final class StoryModel implements Serializable {
|
||||
private final String storyMediaId, storyUrl, username;
|
||||
private final MediaItemType itemType;
|
||||
private final long timestamp;
|
||||
private String videoUrl, tappableShortCode, spotify;
|
||||
private String videoUrl, tappableShortCode, tappableId, spotify;
|
||||
private PollModel poll;
|
||||
private QuestionModel question;
|
||||
private String[] mentions;
|
||||
private int position;
|
||||
private boolean isCurrentSlide = false;
|
||||
|
||||
@ -49,6 +53,14 @@ public final class StoryModel implements Serializable {
|
||||
return poll;
|
||||
}
|
||||
|
||||
public QuestionModel getQuestion() {
|
||||
return question;
|
||||
}
|
||||
|
||||
public String[] getMentions() {
|
||||
return mentions;
|
||||
}
|
||||
|
||||
public int getPosition() {
|
||||
return position;
|
||||
}
|
||||
@ -73,6 +85,14 @@ public final class StoryModel implements Serializable {
|
||||
this.poll = poll;
|
||||
}
|
||||
|
||||
public void setQuestion(final QuestionModel question) {
|
||||
this.question = question;
|
||||
}
|
||||
|
||||
public void setMentions(final String[] mentions) {
|
||||
this.mentions = mentions;
|
||||
}
|
||||
|
||||
public void setPosition(final int position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ public final class ViewerPostModel extends BasePostModel {
|
||||
protected final String username;
|
||||
protected final JSONObject location;
|
||||
protected final long videoViews;
|
||||
protected String sliderDisplayUrl, commentsEndCursor;
|
||||
protected String sliderDisplayUrl;
|
||||
protected long commentsCount, likes;
|
||||
private boolean isCurrentSlide = false;
|
||||
|
||||
@ -44,10 +44,6 @@ public final class ViewerPostModel extends BasePostModel {
|
||||
return location;
|
||||
}
|
||||
|
||||
public String getCommentsEndCursor() {
|
||||
return commentsEndCursor;
|
||||
}
|
||||
|
||||
public final long getVideoViews() {
|
||||
return videoViews;
|
||||
}
|
||||
@ -71,10 +67,6 @@ public final class ViewerPostModel extends BasePostModel {
|
||||
this.commentsCount = commentsCount;
|
||||
}
|
||||
|
||||
public void setCommentsEndCursor(final String commentsEndCursor) {
|
||||
this.commentsEndCursor = commentsEndCursor;
|
||||
}
|
||||
|
||||
public void setCurrentSlide(final boolean currentSlide) {
|
||||
this.isCurrentSlide = currentSlide;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package awais.instagrabber.models;
|
||||
package awais.instagrabber.models.stickers;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
20
app/src/main/java/awais/instagrabber/models/stickers/QuestionModel.java
Executable file
20
app/src/main/java/awais/instagrabber/models/stickers/QuestionModel.java
Executable file
@ -0,0 +1,20 @@
|
||||
package awais.instagrabber.models.stickers;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public final class QuestionModel implements Serializable {
|
||||
private final String id, question;
|
||||
|
||||
public QuestionModel(final String id, final String question) {
|
||||
this.id = id; // only the poll id
|
||||
this.question = question;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getQuestion() {
|
||||
return question;
|
||||
}
|
||||
}
|
@ -22,6 +22,7 @@ public final class Constants {
|
||||
// never Export
|
||||
public static final String COOKIE = "cookie";
|
||||
public static final String SHOW_QUICK_ACCESS_DIALOG = "show_quick_dlg";
|
||||
public static final String DEVICE_UUID = "device_uuid";
|
||||
//////////////////////// EXTRAS ////////////////////////
|
||||
public static final String EXTRAS_USER = "user";
|
||||
public static final String EXTRAS_HASHTAG = "hashtag";
|
||||
@ -45,6 +46,8 @@ public final class Constants {
|
||||
public static final String USER_AGENT = "Mozilla/5.0 (Linux; Android 8.1.0; motorola one Build/OPKS28.63-18-3; wv) " +
|
||||
"AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.80 Mobile Safari/537.36 " +
|
||||
"Instagram 72.0.0.21.98 Android (27/8.1.0; 320dpi; 720x1362; motorola; motorola one; deen_sprout; qcom; pt_BR; 132081645)";
|
||||
public static final String I_USER_AGENT =
|
||||
"Instagram 72.0.0.21.98 Android (27/8.1.0; 320dpi; 720x1362; motorola; motorola one; deen_sprout; qcom; pt_BR; 132081645)";
|
||||
// see https://github.com/dilame/instagram-private-api/blob/master/src/core/constants.ts
|
||||
public static final String SUPPORTED_CAPABILITIES = "[ { \"name\": \"SUPPORTED_SDK_VERSIONS\", \"value\":" +
|
||||
" \"13.0,14.0,15.0,16.0,17.0,18.0,19.0,20.0,21.0,22.0,23.0,24.0,25.0,26.0,27.0,28.0,29.0,30.0,31.0," +
|
||||
|
@ -18,6 +18,7 @@ import static awais.instagrabber.utils.Constants.CUSTOM_DATE_TIME_FORMAT;
|
||||
import static awais.instagrabber.utils.Constants.CUSTOM_DATE_TIME_FORMAT_ENABLED;
|
||||
import static awais.instagrabber.utils.Constants.DATE_TIME_FORMAT;
|
||||
import static awais.instagrabber.utils.Constants.DATE_TIME_SELECTION;
|
||||
import static awais.instagrabber.utils.Constants.DEVICE_UUID;
|
||||
import static awais.instagrabber.utils.Constants.DOWNLOAD_USER_FOLDER;
|
||||
import static awais.instagrabber.utils.Constants.FOLDER_PATH;
|
||||
import static awais.instagrabber.utils.Constants.FOLDER_SAVE_TO;
|
||||
@ -101,7 +102,7 @@ public final class SettingsHelper {
|
||||
if (sharedPreferences != null) sharedPreferences.edit().putBoolean(key, val).apply();
|
||||
}
|
||||
|
||||
@StringDef({COOKIE, FOLDER_PATH, DATE_TIME_FORMAT, DATE_TIME_SELECTION, CUSTOM_DATE_TIME_FORMAT})
|
||||
@StringDef({COOKIE, FOLDER_PATH, DATE_TIME_FORMAT, DATE_TIME_SELECTION, CUSTOM_DATE_TIME_FORMAT, DEVICE_UUID})
|
||||
public @interface StringSettings {}
|
||||
|
||||
@StringDef({DOWNLOAD_USER_FOLDER, BOTTOM_TOOLBAR, FOLDER_SAVE_TO, AUTOPLAY_VIDEOS, SHOW_QUICK_ACCESS_DIALOG, MUTED_VIDEOS,
|
||||
|
@ -53,7 +53,6 @@ import java.net.HttpCookie;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.security.MessageDigest;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -75,7 +74,7 @@ import awais.instagrabber.models.BasePostModel;
|
||||
import awais.instagrabber.models.FeedStoryModel;
|
||||
import awais.instagrabber.models.HighlightModel;
|
||||
import awais.instagrabber.models.IntentModel;
|
||||
import awais.instagrabber.models.PollModel;
|
||||
import awais.instagrabber.models.stickers.PollModel;
|
||||
import awais.instagrabber.models.ProfileModel;
|
||||
import awais.instagrabber.models.StoryModel;
|
||||
import awais.instagrabber.models.direct_messages.DirectItemModel;
|
||||
@ -89,6 +88,7 @@ import awais.instagrabber.models.enums.MediaItemType;
|
||||
import awais.instagrabber.models.enums.NotificationType;
|
||||
import awais.instagrabber.models.enums.RavenExpiringMediaType;
|
||||
import awais.instagrabber.models.enums.RavenMediaViewType;
|
||||
import awais.instagrabber.models.stickers.QuestionModel;
|
||||
import awaisomereport.LogCollector;
|
||||
|
||||
import static awais.instagrabber.models.direct_messages.DirectItemModel.DirectItemActionLogModel;
|
||||
@ -260,8 +260,9 @@ public final class Utils {
|
||||
return stringBuilder;
|
||||
}
|
||||
|
||||
// isI: true if the content was requested from i.instagram.com instead of graphql
|
||||
@Nullable
|
||||
public static String getHighQualityPost(final JSONArray resources, final boolean isVideo) {
|
||||
public static String getHighQualityPost(final JSONArray resources, final boolean isVideo, final boolean isI) {
|
||||
try {
|
||||
final int resourcesLen = resources.length();
|
||||
|
||||
@ -270,18 +271,18 @@ public final class Utils {
|
||||
int lastResBase = 0, lastIndexBase = -1;
|
||||
for (int i = 0; i < resourcesLen; ++i) {
|
||||
final JSONObject item = resources.getJSONObject(i);
|
||||
if (item != null && (!isVideo || item.has(Constants.EXTRAS_PROFILE))) {
|
||||
sources[i] = item.getString("src");
|
||||
final int currRes = item.getInt("config_width") * item.getInt("config_height");
|
||||
if (item != null && (!isVideo || item.has(Constants.EXTRAS_PROFILE) || isI)) {
|
||||
sources[i] = item.getString(isI ? "url" : "src");
|
||||
final int currRes = item.getInt(isI ? "width" : "config_width") * item.getInt(isI ? "height" : "config_height");
|
||||
|
||||
final String profile = isVideo ? item.getString(Constants.EXTRAS_PROFILE) : null;
|
||||
final String profile = isVideo ? item.optString(Constants.EXTRAS_PROFILE) : null;
|
||||
|
||||
if (!isVideo || "MAIN".equals(profile)) {
|
||||
if (currRes > lastResMain) {
|
||||
lastResMain = currRes;
|
||||
lastIndexMain = i;
|
||||
}
|
||||
} else if ("BASELINE".equals(profile)) {
|
||||
} else {
|
||||
if (currRes > lastResBase) {
|
||||
lastResBase = currRes;
|
||||
lastIndexBase = i;
|
||||
@ -305,7 +306,9 @@ public final class Utils {
|
||||
public static String getHighQualityImage(final JSONObject resources) {
|
||||
String src = null;
|
||||
try {
|
||||
if (resources.has("display_resources")) src = getHighQualityPost(resources.getJSONArray("display_resources"), false);
|
||||
if (resources.has("display_resources")) src = getHighQualityPost(resources.getJSONArray("display_resources"), false, false);
|
||||
else if (resources.has("image_versions2"))
|
||||
src = getHighQualityPost(resources.getJSONObject("image_versions2").getJSONArray("candidates"), false, true);
|
||||
if (src == null) return resources.getString("display_url");
|
||||
} catch (final Exception e) {
|
||||
if (logCollector != null)
|
||||
@ -1157,6 +1160,23 @@ public final class Utils {
|
||||
return "[]";
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static String iHighlightIdsMerger(final String... strings) {
|
||||
if (strings != null) {
|
||||
int iMax = strings.length - 1;
|
||||
if (iMax != -1) {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
for (int i = 0; ; i++) {
|
||||
builder.append(strings[i]);
|
||||
if (i == iMax) return builder.toString();
|
||||
builder.append("&reel_ids=");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static void putHighlightModels(final HttpURLConnection conn, final Object[] model) throws Exception {
|
||||
final boolean isHighlightModel = model instanceof HighlightModel[];
|
||||
final boolean isFeedStoryModel = model instanceof FeedStoryModel[];
|
||||
@ -1192,7 +1212,7 @@ public final class Utils {
|
||||
data.getLong("taken_at_timestamp"), data.getJSONObject("owner").getString("username"));
|
||||
|
||||
if (isVideo && data.has("video_resources"))
|
||||
storyModels[j].setVideoUrl(Utils.getHighQualityPost(data.getJSONArray("video_resources"), true));
|
||||
storyModels[j].setVideoUrl(Utils.getHighQualityPost(data.getJSONArray("video_resources"), true, false));
|
||||
|
||||
if (!data.isNull("story_app_attribution"))
|
||||
storyModels[j].setSpotify(data.getJSONObject("story_app_attribution").optString("content_url").split("\\?")[0]);
|
||||
@ -1226,6 +1246,75 @@ public final class Utils {
|
||||
}
|
||||
}
|
||||
|
||||
public static void iPutFeedStoryModels(final HttpURLConnection conn, final FeedStoryModel[] model, final String[] ids) throws Exception {
|
||||
final JSONObject highlightsMediaReel = new JSONObject(Utils.readFromConnection(conn)).getJSONObject("reels");
|
||||
final int mediaLength = highlightsMediaReel.length();
|
||||
|
||||
for (int i = 0; i < mediaLength; ++i) {
|
||||
final JSONArray items = highlightsMediaReel.getJSONObject(ids[i]).getJSONArray("items");
|
||||
final int itemsLen = items.length();
|
||||
|
||||
final StoryModel[] storyModels = new StoryModel[itemsLen];
|
||||
for (int j = 0; j < itemsLen; ++j) {
|
||||
final JSONObject data = items.getJSONObject(j);
|
||||
final boolean isVideo = data.has("has_audio") && data.optBoolean("has_audio");
|
||||
|
||||
storyModels[j] = new StoryModel(data.getString("pk"),
|
||||
data.getJSONObject("image_versions2").getJSONArray("candidates").getJSONObject(0).getString("url"),
|
||||
isVideo ? MediaItemType.MEDIA_TYPE_VIDEO : MediaItemType.MEDIA_TYPE_IMAGE,
|
||||
data.optLong("taken_at", 0),
|
||||
model[i].getProfileModel().getUsername());
|
||||
|
||||
final JSONArray videoResources = data.optJSONArray("video_versions");
|
||||
if (isVideo && videoResources != null)
|
||||
storyModels[j].setVideoUrl(Utils.getHighQualityPost(videoResources, true, true));
|
||||
|
||||
if (data.has("story_feed_media")) {
|
||||
storyModels[j].setTappableShortCode(data.getJSONArray("story_feed_media").getJSONObject(0).optString("media_id"));
|
||||
}
|
||||
|
||||
if (!data.isNull("story_app_attribution"))
|
||||
storyModels[j].setSpotify(data.getJSONObject("story_app_attribution").optString("content_url").split("\\?")[0]);
|
||||
|
||||
if (data.has("story_polls")) {
|
||||
JSONObject tappableObject = data.optJSONArray("story_polls").getJSONObject(0).optJSONObject("poll_sticker");
|
||||
if (tappableObject != null) storyModels[j].setPoll(new PollModel(
|
||||
String.valueOf(tappableObject.getLong("poll_id")),
|
||||
tappableObject.getString("question"),
|
||||
tappableObject.getJSONArray("tallies").getJSONObject(0).getString("text"),
|
||||
tappableObject.getJSONArray("tallies").getJSONObject(0).getInt("count"),
|
||||
tappableObject.getJSONArray("tallies").getJSONObject(1).getString("text"),
|
||||
tappableObject.getJSONArray("tallies").getJSONObject(1).getInt("count"),
|
||||
tappableObject.optInt("viewer_vote", -1)
|
||||
));
|
||||
}
|
||||
if (data.has("story_questions")) {
|
||||
JSONObject tappableObject = data.getJSONArray("story_questions").getJSONObject(0).optJSONObject("question_sticker");
|
||||
if (tappableObject != null) storyModels[j].setQuestion(new QuestionModel(
|
||||
String.valueOf(tappableObject.getLong("question_id")),
|
||||
tappableObject.getString("question")
|
||||
));
|
||||
}
|
||||
JSONArray hashtags = data.optJSONArray("story_hashtags");
|
||||
JSONArray atmarks = data.optJSONArray("reel_mentions");
|
||||
String[] mentions = new String[(hashtags == null ? 0 : hashtags.length()) + (atmarks == null ? 0 : atmarks.length())];
|
||||
if (hashtags != null) {
|
||||
for (int h = 0; h < hashtags.length(); ++h) {
|
||||
mentions[h] = "#"+hashtags.getJSONObject(h).getJSONObject("hashtag").getString("name");
|
||||
}
|
||||
}
|
||||
if (atmarks != null) {
|
||||
for (int h = 0; h < atmarks.length(); ++h) {
|
||||
mentions[h + (hashtags == null ? 0 : hashtags.length())] =
|
||||
"@"+atmarks.getJSONObject(h).getJSONObject("user").getString("username");
|
||||
}
|
||||
}
|
||||
storyModels[j].setMentions(mentions);
|
||||
}
|
||||
model[i].setStoryModels(storyModels);
|
||||
}
|
||||
}
|
||||
|
||||
public static String sign(final String message) {
|
||||
try {
|
||||
Mac hasher = Mac.getInstance("HmacSHA256");
|
||||
@ -1237,8 +1326,7 @@ public final class Utils {
|
||||
if (hex.length() == 1) hexString.append('0');
|
||||
hexString.append(hex);
|
||||
}
|
||||
Log.d("austin_debug", "hash: " + hexString.toString());
|
||||
return hexString.toString() + "." + message;
|
||||
return "ig_sig_key_version="+Constants.SIGNATURE_VERSION+"&signed_body=" + hexString.toString() + "." + message;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
Log.e("austin_debug", "sign: ", e);
|
||||
|
@ -44,7 +44,6 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.3"
|
||||
android:background="#0000"
|
||||
android:weightSum="3"
|
||||
android:layout_gravity="bottom">
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/viewStoryPost"
|
||||
@ -56,14 +55,32 @@
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_green_background" />
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/interactStory"
|
||||
android:id="@+id/poll"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/view_story_post"
|
||||
android:text="@string/vote_story_poll"
|
||||
android:textColor="@color/btn_blue_text_color"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_blue_background" />
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/answer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/answer_story"
|
||||
android:textColor="@color/btn_blue_text_color"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_blue_background" />
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/mention"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/story_mentions"
|
||||
android:textColor="@color/btn_orange_text_color"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_orange_background" />
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/spotify"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -67,6 +67,10 @@
|
||||
<string name="vote_story_poll">Vote</string>
|
||||
<string name="votef_story_poll">Vote successful!</string>
|
||||
<string name="voted_story_poll">You have already voted!</string>
|
||||
<string name="answer_story">Answer</string>
|
||||
<string name="answer_hint">Answer...</string>
|
||||
<string name="answered_story">Answer successful!</string>
|
||||
<string name="story_mentions">Mentions</string>
|
||||
<string name="priv_acc">This Account is Private</string>
|
||||
<string name="no_acc">You can log in via Settings on the bottom-right corner. Or, you can view public accounts without login!</string>
|
||||
<string name="no_acc_logged_in">You can swipe left/right for explore/feed, or search something below!</string>
|
||||
|
5
fastlane/metadata/android/changelogs/37.txt
Normal file
5
fastlane/metadata/android/changelogs/37.txt
Normal file
@ -0,0 +1,5 @@
|
||||
* You can now respond to question boxes in stories
|
||||
* You can now check out story mentions (except non-Spotify music stickers, but you can hear them by playing the story)
|
||||
* Above 2 does not apply to highlights
|
||||
* You can now click on locations from feed
|
||||
* Fixed a bug where you cannot access your own follower/following list when you are private and have no posts
|
Loading…
Reference in New Issue
Block a user