mirror of
https://github.com/KokaKiwi/BarInsta
synced 2024-11-22 22:57:29 +00:00
Merge branch 'master' into task/separate-dm-type-views
This commit is contained in:
commit
052402a974
@ -10,8 +10,8 @@ android {
|
|||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 29
|
targetSdkVersion 29
|
||||||
|
|
||||||
versionCode 45
|
versionCode 46
|
||||||
versionName '17.9'
|
versionName '18.0'
|
||||||
|
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package awais.instagrabber.activities;
|
package awais.instagrabber.activities;
|
||||||
|
|
||||||
|
import android.app.Notification;
|
||||||
|
import android.app.PendingIntent;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
@ -7,8 +9,10 @@ import android.content.res.Resources;
|
|||||||
import android.database.MatrixCursor;
|
import android.database.MatrixCursor;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
import android.os.PersistableBundle;
|
import android.os.PersistableBundle;
|
||||||
import android.provider.BaseColumns;
|
import android.provider.BaseColumns;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@ -20,10 +24,12 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.appcompat.widget.SearchView;
|
import androidx.appcompat.widget.SearchView;
|
||||||
|
import androidx.core.app.NotificationCompat;
|
||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
import androidx.recyclerview.widget.GridLayoutManager;
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
|
|
||||||
import awais.instagrabber.BuildConfig;
|
import awais.instagrabber.BuildConfig;
|
||||||
@ -31,6 +37,7 @@ import awais.instagrabber.MainHelper;
|
|||||||
import awais.instagrabber.R;
|
import awais.instagrabber.R;
|
||||||
import awais.instagrabber.adapters.HighlightsAdapter;
|
import awais.instagrabber.adapters.HighlightsAdapter;
|
||||||
import awais.instagrabber.adapters.SuggestionsAdapter;
|
import awais.instagrabber.adapters.SuggestionsAdapter;
|
||||||
|
import awais.instagrabber.asyncs.GetActivityAsyncTask;
|
||||||
import awais.instagrabber.asyncs.SuggestionsFetcher;
|
import awais.instagrabber.asyncs.SuggestionsFetcher;
|
||||||
import awais.instagrabber.asyncs.UsernameFetcher;
|
import awais.instagrabber.asyncs.UsernameFetcher;
|
||||||
import awais.instagrabber.asyncs.i.iStoryStatusFetcher;
|
import awais.instagrabber.asyncs.i.iStoryStatusFetcher;
|
||||||
@ -58,6 +65,8 @@ import awais.instagrabber.utils.DataBox;
|
|||||||
import awais.instagrabber.utils.FlavorTown;
|
import awais.instagrabber.utils.FlavorTown;
|
||||||
import awais.instagrabber.utils.Utils;
|
import awais.instagrabber.utils.Utils;
|
||||||
|
|
||||||
|
import static awais.instagrabber.utils.Utils.CHANNEL_ID;
|
||||||
|
import static awais.instagrabber.utils.Utils.notificationManager;
|
||||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||||
|
|
||||||
public final class Main extends BaseLanguageActivity {
|
public final class Main extends BaseLanguageActivity {
|
||||||
@ -97,7 +106,7 @@ public final class Main extends BaseLanguageActivity {
|
|||||||
public SearchView searchView;
|
public SearchView searchView;
|
||||||
public MenuItem downloadAction, settingsAction, dmsAction, notifAction;
|
public MenuItem downloadAction, settingsAction, dmsAction, notifAction;
|
||||||
public StoryModel[] storyModels;
|
public StoryModel[] storyModels;
|
||||||
public String userQuery = null;
|
public String userQuery = null, cookie, uid = null;
|
||||||
public MainHelper mainHelper;
|
public MainHelper mainHelper;
|
||||||
public ProfileModel profileModel;
|
public ProfileModel profileModel;
|
||||||
public HashtagModel hashtagModel;
|
public HashtagModel hashtagModel;
|
||||||
@ -107,6 +116,7 @@ public final class Main extends BaseLanguageActivity {
|
|||||||
private DialogInterface.OnClickListener profileDialogListener;
|
private DialogInterface.OnClickListener profileDialogListener;
|
||||||
private Stack<String> queriesStack;
|
private Stack<String> queriesStack;
|
||||||
private DataBox.CookieModel cookieModel;
|
private DataBox.CookieModel cookieModel;
|
||||||
|
private Runnable runnable;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(@Nullable final Bundle bundle) {
|
protected void onCreate(@Nullable final Bundle bundle) {
|
||||||
@ -117,8 +127,8 @@ public final class Main extends BaseLanguageActivity {
|
|||||||
FlavorTown.updateCheck(this);
|
FlavorTown.updateCheck(this);
|
||||||
FlavorTown.changelogCheck(this);
|
FlavorTown.changelogCheck(this);
|
||||||
|
|
||||||
final String cookie = settingsHelper.getString(Constants.COOKIE);
|
cookie = settingsHelper.getString(Constants.COOKIE);
|
||||||
final String uid = Utils.getUserIdFromCookie(cookie);
|
uid = Utils.getUserIdFromCookie(cookie);
|
||||||
Utils.setupCookies(cookie);
|
Utils.setupCookies(cookie);
|
||||||
|
|
||||||
MainHelper.stopCurrentExecutor();
|
MainHelper.stopCurrentExecutor();
|
||||||
@ -246,6 +256,56 @@ public final class Main extends BaseLanguageActivity {
|
|||||||
mainHelper.onRefresh();
|
mainHelper.onRefresh();
|
||||||
|
|
||||||
mainHelper.onIntent(getIntent());
|
mainHelper.onIntent(getIntent());
|
||||||
|
|
||||||
|
final Handler handler = new Handler();
|
||||||
|
runnable = () -> {
|
||||||
|
final GetActivityAsyncTask activityAsyncTask = new GetActivityAsyncTask(uid, cookie, result -> {
|
||||||
|
if (result == null) {
|
||||||
|
if (!Utils.isEmpty(cookie)) {
|
||||||
|
Toast.makeText(Main.this, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (notificationManager == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final List<String> list = new ArrayList<>();
|
||||||
|
if (result.getRelationshipsCount() != 0) {
|
||||||
|
list.add(getString(R.string.activity_count_relationship, result.getRelationshipsCount()));
|
||||||
|
}
|
||||||
|
if (result.getUserTagsCount() != 0) {
|
||||||
|
list.add(getString(R.string.activity_count_usertags, result.getUserTagsCount()));
|
||||||
|
}
|
||||||
|
if (result.getCommentsCount() != 0) {
|
||||||
|
list.add(getString(R.string.activity_count_comments, result.getCommentsCount()));
|
||||||
|
}
|
||||||
|
if (result.getCommentLikesCount() != 0) {
|
||||||
|
list.add(getString(R.string.activity_count_commentlikes, result.getCommentLikesCount()));
|
||||||
|
}
|
||||||
|
if (result.getLikesCount() != 0) {
|
||||||
|
list.add(getString(R.string.activity_count_likes, result.getLikesCount()));
|
||||||
|
}
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final String join = TextUtils.join(", ", list);
|
||||||
|
final String notificationString = getString(R.string.activity_count_prefix) + " " + join + ".";
|
||||||
|
final Intent intent = new Intent(getApplicationContext(), NotificationsViewer.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
|
final Notification notification = new NotificationCompat.Builder(Main.this, CHANNEL_ID)
|
||||||
|
.setCategory(NotificationCompat.CATEGORY_STATUS)
|
||||||
|
.setSmallIcon(R.drawable.ic_notif)
|
||||||
|
.setAutoCancel(true)
|
||||||
|
.setPriority(NotificationCompat.PRIORITY_MIN)
|
||||||
|
.setContentText(notificationString)
|
||||||
|
.setContentIntent(PendingIntent.getActivity(getApplicationContext(), 1738, intent, PendingIntent.FLAG_UPDATE_CURRENT))
|
||||||
|
.build();
|
||||||
|
notificationManager.cancel(1800000000);
|
||||||
|
notificationManager.notify(1800000000, notification);
|
||||||
|
});
|
||||||
|
activityAsyncTask.execute();
|
||||||
|
handler.postDelayed(runnable, 60000);
|
||||||
|
};
|
||||||
|
handler.postDelayed(runnable, 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void downloadSelectedItems() {
|
private void downloadSelectedItems() {
|
||||||
|
@ -35,8 +35,9 @@ import awais.instagrabber.models.ProfileModel;
|
|||||||
import awais.instagrabber.utils.Constants;
|
import awais.instagrabber.utils.Constants;
|
||||||
import awais.instagrabber.utils.Utils;
|
import awais.instagrabber.utils.Utils;
|
||||||
|
|
||||||
|
import static awais.instagrabber.utils.Utils.notificationManager;
|
||||||
|
|
||||||
public final class NotificationsViewer extends BaseLanguageActivity implements SwipeRefreshLayout.OnRefreshListener {
|
public final class NotificationsViewer extends BaseLanguageActivity implements SwipeRefreshLayout.OnRefreshListener {
|
||||||
private NotificationsAdapter notificationsAdapter;
|
|
||||||
private NotificationModel notificationModel;
|
private NotificationModel notificationModel;
|
||||||
private ActivityNotificationBinding notificationsBinding;
|
private ActivityNotificationBinding notificationsBinding;
|
||||||
private ArrayAdapter<String> commmentDialogAdapter;
|
private ArrayAdapter<String> commmentDialogAdapter;
|
||||||
@ -47,26 +48,18 @@ public final class NotificationsViewer extends BaseLanguageActivity implements S
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(@Nullable final Bundle savedInstanceState) {
|
protected void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||||
|
notificationManager.cancel(1800000000);
|
||||||
|
if (Utils.isEmpty(cookie)) {
|
||||||
|
Toast.makeText(this, R.string.activity_notloggedin, Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
notificationsBinding = ActivityNotificationBinding.inflate(getLayoutInflater());
|
notificationsBinding = ActivityNotificationBinding.inflate(getLayoutInflater());
|
||||||
setContentView(notificationsBinding.getRoot());
|
setContentView(notificationsBinding.getRoot());
|
||||||
notificationsBinding.swipeRefreshLayout.setOnRefreshListener(this);
|
notificationsBinding.swipeRefreshLayout.setOnRefreshListener(this);
|
||||||
|
resources = getResources();
|
||||||
notificationsBinding.swipeRefreshLayout.setRefreshing(true);
|
|
||||||
setSupportActionBar(notificationsBinding.toolbar.toolbar);
|
setSupportActionBar(notificationsBinding.toolbar.toolbar);
|
||||||
notificationsBinding.toolbar.toolbar.setTitle(R.string.action_notif);
|
notificationsBinding.toolbar.toolbar.setTitle(R.string.action_notif);
|
||||||
|
onRefresh();
|
||||||
resources = getResources();
|
|
||||||
|
|
||||||
new NotificationsFetcher(new FetchListener<NotificationModel[]>() {
|
|
||||||
@Override
|
|
||||||
public void onResult(final NotificationModel[] notificationModels) {
|
|
||||||
notificationsAdapter = new NotificationsAdapter(notificationModels, clickListener, mentionClickListener);
|
|
||||||
|
|
||||||
notificationsBinding.rvComments.setAdapter(notificationsAdapter);
|
|
||||||
notificationsBinding.swipeRefreshLayout.setRefreshing(false);
|
|
||||||
}
|
|
||||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -75,11 +68,9 @@ public final class NotificationsViewer extends BaseLanguageActivity implements S
|
|||||||
new NotificationsFetcher(new FetchListener<NotificationModel[]>() {
|
new NotificationsFetcher(new FetchListener<NotificationModel[]>() {
|
||||||
@Override
|
@Override
|
||||||
public void onResult(final NotificationModel[] notificationModels) {
|
public void onResult(final NotificationModel[] notificationModels) {
|
||||||
|
notificationsBinding.rvComments.setAdapter(new NotificationsAdapter(notificationModels, clickListener, mentionClickListener));
|
||||||
notificationsBinding.swipeRefreshLayout.setRefreshing(false);
|
notificationsBinding.swipeRefreshLayout.setRefreshing(false);
|
||||||
|
new SeenAction().execute();
|
||||||
notificationsAdapter = new NotificationsAdapter(notificationModels, clickListener, mentionClickListener);
|
|
||||||
|
|
||||||
notificationsBinding.rvComments.setAdapter(notificationsAdapter);
|
|
||||||
}
|
}
|
||||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
}
|
}
|
||||||
@ -150,7 +141,8 @@ public final class NotificationsViewer extends BaseLanguageActivity implements S
|
|||||||
urlConnection.setUseCaches(false);
|
urlConnection.setUseCaches(false);
|
||||||
urlConnection.setRequestProperty("User-Agent", Constants.USER_AGENT);
|
urlConnection.setRequestProperty("User-Agent", Constants.USER_AGENT);
|
||||||
urlConnection.setRequestProperty("x-csrftoken",
|
urlConnection.setRequestProperty("x-csrftoken",
|
||||||
Utils.settingsHelper.getString(Constants.COOKIE).split("csrftoken=")[1].split(";")[0]);urlConnection.connect();
|
Utils.settingsHelper.getString(Constants.COOKIE).split("csrftoken=")[1].split(";")[0]);
|
||||||
|
urlConnection.connect();
|
||||||
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||||
ok = true;
|
ok = true;
|
||||||
}
|
}
|
||||||
@ -169,4 +161,23 @@ public final class NotificationsViewer extends BaseLanguageActivity implements S
|
|||||||
else Toast.makeText(getApplicationContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
else Toast.makeText(getApplicationContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SeenAction extends AsyncTask<Void, Void, Void> {
|
||||||
|
protected Void doInBackground(Void... lmao) {
|
||||||
|
try {
|
||||||
|
final HttpURLConnection urlConnection =
|
||||||
|
(HttpURLConnection) new URL("https://www.instagram.com/web/activity/mark_checked/").openConnection();
|
||||||
|
urlConnection.setRequestMethod("POST");
|
||||||
|
urlConnection.setUseCaches(false);
|
||||||
|
urlConnection.setRequestProperty("User-Agent", Constants.USER_AGENT);
|
||||||
|
urlConnection.setRequestProperty("x-csrftoken",
|
||||||
|
Utils.settingsHelper.getString(Constants.COOKIE).split("csrftoken=")[1].split(";")[0]);
|
||||||
|
urlConnection.connect();
|
||||||
|
urlConnection.disconnect();
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
Log.e("austin_debug", "seen: " + ex);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -56,6 +56,7 @@ import awais.instagrabber.BuildConfig;
|
|||||||
import awais.instagrabber.R;
|
import awais.instagrabber.R;
|
||||||
import awais.instagrabber.adapters.StoriesAdapter;
|
import awais.instagrabber.adapters.StoriesAdapter;
|
||||||
import awais.instagrabber.asyncs.DownloadAsync;
|
import awais.instagrabber.asyncs.DownloadAsync;
|
||||||
|
import awais.instagrabber.asyncs.direct_messages.DirectThreadBroadcaster;
|
||||||
import awais.instagrabber.asyncs.i.iStoryStatusFetcher;
|
import awais.instagrabber.asyncs.i.iStoryStatusFetcher;
|
||||||
import awais.instagrabber.customviews.helpers.SwipeGestureListener;
|
import awais.instagrabber.customviews.helpers.SwipeGestureListener;
|
||||||
import awais.instagrabber.databinding.ActivityStoryViewerBinding;
|
import awais.instagrabber.databinding.ActivityStoryViewerBinding;
|
||||||
@ -723,8 +724,6 @@ final String url = "https://i.instagram.com/api/v1/media/"+currentStory.getStory
|
|||||||
}
|
}
|
||||||
|
|
||||||
class CommentAction extends AsyncTask<String, Void, Void> {
|
class CommentAction extends AsyncTask<String, Void, Void> {
|
||||||
boolean ok = false;
|
|
||||||
|
|
||||||
protected Void doInBackground(String... rawAction) {
|
protected Void doInBackground(String... rawAction) {
|
||||||
final String action = rawAction[0];
|
final String action = rawAction[0];
|
||||||
final String url = "https://i.instagram.com/api/v1/direct_v2/create_group_thread/";
|
final String url = "https://i.instagram.com/api/v1/direct_v2/create_group_thread/";
|
||||||
@ -747,55 +746,27 @@ final String url = "https://i.instagram.com/api/v1/media/"+currentStory.getStory
|
|||||||
wr.close();
|
wr.close();
|
||||||
urlConnection.connect();
|
urlConnection.connect();
|
||||||
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||||
try {
|
|
||||||
final String threadid = new JSONObject(Utils.readFromConnection(urlConnection)).getString("thread_id");
|
final String threadid = new JSONObject(Utils.readFromConnection(urlConnection)).getString("thread_id");
|
||||||
final String url2 = "https://i.instagram.com/api/v1/direct_v2/threads/broadcast/reel_share/";
|
final DirectThreadBroadcaster.StoryReplyBroadcastOptions options =
|
||||||
final HttpURLConnection urlConnection2 = (HttpURLConnection) new URL(url2).openConnection();
|
new DirectThreadBroadcaster.StoryReplyBroadcastOptions(
|
||||||
urlConnection2.setRequestMethod("POST");
|
action,
|
||||||
urlConnection2.setRequestProperty("User-Agent", Constants.I_USER_AGENT);
|
currentStory.getStoryMediaId(),
|
||||||
urlConnection2.setUseCaches(false);
|
currentStory.getUserId()
|
||||||
final String commentText = URLEncoder.encode(action, "UTF-8")
|
);
|
||||||
.replaceAll("\\+", "%20").replaceAll("\\%21", "!").replaceAll("\\%27", "'")
|
final DirectThreadBroadcaster broadcast = new DirectThreadBroadcaster(threadid);
|
||||||
.replaceAll("\\%28", "(").replaceAll("\\%29", ")").replaceAll("\\%7E", "~");
|
broadcast.setOnTaskCompleteListener(result -> {
|
||||||
final String cc = UUID.randomUUID().toString();
|
Toast.makeText(getApplicationContext(),
|
||||||
final String urlParameters2 = Utils.sign("{\"_csrftoken\":\"" + cookie.split("csrftoken=")[1].split(";")[0]
|
result != null ? R.string.answered_story : R.string.downloader_unknown_error,
|
||||||
+"\",\"_uid\":\"" + Utils.getUserIdFromCookie(cookie)
|
Toast.LENGTH_SHORT).show();
|
||||||
+"\",\"__uuid\":\"" + settingsHelper.getString(Constants.DEVICE_UUID)
|
});
|
||||||
+"\",\"client_context\":\"" + cc
|
broadcast.execute(options);
|
||||||
+"\",\"mutation_token\":\"" + cc
|
|
||||||
+"\",\"text\":\"" + commentText
|
|
||||||
+"\",\"media_id\":\"" + currentStory.getStoryMediaId()
|
|
||||||
+"\",\"reel_id\":\"" + currentStory.getUserId()
|
|
||||||
+"\",\"thread_ids\":\"["+threadid
|
|
||||||
+"]\",\"action\":\"send_item\",\"entry\":\"reel\"}");
|
|
||||||
urlConnection2.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
|
||||||
urlConnection2.setRequestProperty("Content-Length", "" + Integer.toString(urlParameters2.getBytes().length));
|
|
||||||
urlConnection2.setDoOutput(true);
|
|
||||||
DataOutputStream wr2 = new DataOutputStream(urlConnection2.getOutputStream());
|
|
||||||
wr2.writeBytes(urlParameters2);
|
|
||||||
wr2.flush();
|
|
||||||
wr2.close();
|
|
||||||
urlConnection2.connect();
|
|
||||||
if (urlConnection2.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
|
||||||
ok = true;
|
|
||||||
}
|
}
|
||||||
urlConnection2.disconnect();
|
|
||||||
} catch (Throwable ex) {
|
|
||||||
Log.e("austin_debug", "reply (B): " + ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
urlConnection.disconnect();
|
urlConnection.disconnect();
|
||||||
} catch (Throwable ex) {
|
} catch (Throwable ex) {
|
||||||
Log.e("austin_debug", "reply (CT): " + ex);
|
Log.e("austin_debug", "reply (CT): " + ex);
|
||||||
|
Toast.makeText(getApplicationContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(Void result) {
|
|
||||||
Toast.makeText(getApplicationContext(),
|
|
||||||
ok ? R.string.answered_story : R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,113 @@
|
|||||||
|
package awais.instagrabber.asyncs;
|
||||||
|
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import awais.instagrabber.utils.Constants;
|
||||||
|
import awais.instagrabber.utils.Utils;
|
||||||
|
|
||||||
|
public class GetActivityAsyncTask extends AsyncTask<Void, Void, GetActivityAsyncTask.NotificationCounts> {
|
||||||
|
private static final String TAG = "GetActivityAsyncTask";
|
||||||
|
private String uid;
|
||||||
|
private String cookie;
|
||||||
|
private OnTaskCompleteListener onTaskCompleteListener;
|
||||||
|
|
||||||
|
public GetActivityAsyncTask(final String uid, final String cookie, final OnTaskCompleteListener onTaskCompleteListener) {
|
||||||
|
this.uid = uid;
|
||||||
|
this.cookie = cookie;
|
||||||
|
this.onTaskCompleteListener = onTaskCompleteListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected NotificationCounts doInBackground(Void... voids) {
|
||||||
|
if (Utils.isEmpty(cookie)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final String url = "https://www.instagram.com/graphql/query/?query_hash=0f318e8cfff9cc9ef09f88479ff571fb"
|
||||||
|
+ "&variables={\"id\":\"" + uid + "\"}";
|
||||||
|
HttpURLConnection urlConnection = null;
|
||||||
|
try {
|
||||||
|
urlConnection = (HttpURLConnection) new URL(url).openConnection();
|
||||||
|
urlConnection.setUseCaches(false);
|
||||||
|
urlConnection.setRequestProperty("User-Agent", Constants.USER_AGENT);
|
||||||
|
urlConnection.setRequestProperty("x-csrftoken", cookie.split("csrftoken=")[1].split(";")[0]);
|
||||||
|
urlConnection.connect();
|
||||||
|
if (urlConnection.getResponseCode() != HttpURLConnection.HTTP_OK) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final JSONObject data = new JSONObject(Utils.readFromConnection(urlConnection)).getJSONObject("data")
|
||||||
|
.getJSONObject("user").getJSONObject("edge_activity_count").getJSONArray("edges").getJSONObject(0)
|
||||||
|
.getJSONObject("node");
|
||||||
|
return new NotificationCounts(
|
||||||
|
data.getInt("relationships"),
|
||||||
|
data.getInt("usertags"),
|
||||||
|
data.getInt("comments"),
|
||||||
|
data.getInt("comment_likes"),
|
||||||
|
data.getInt("likes")
|
||||||
|
);
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
Log.e(TAG, "Error", ex);
|
||||||
|
} finally {
|
||||||
|
if (urlConnection != null) {
|
||||||
|
urlConnection.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(final NotificationCounts result) {
|
||||||
|
if (onTaskCompleteListener == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
onTaskCompleteListener.onTaskComplete(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class NotificationCounts {
|
||||||
|
private int relationshipsCount;
|
||||||
|
private int userTagsCount;
|
||||||
|
private int commentsCount;
|
||||||
|
private int commentLikesCount;
|
||||||
|
private int likesCount;
|
||||||
|
|
||||||
|
public NotificationCounts(final int relationshipsCount,
|
||||||
|
final int userTagsCount,
|
||||||
|
final int commentsCount,
|
||||||
|
final int commentLikesCount,
|
||||||
|
final int likesCount) {
|
||||||
|
this.relationshipsCount = relationshipsCount;
|
||||||
|
this.userTagsCount = userTagsCount;
|
||||||
|
this.commentsCount = commentsCount;
|
||||||
|
this.commentLikesCount = commentLikesCount;
|
||||||
|
this.likesCount = likesCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRelationshipsCount() {
|
||||||
|
return relationshipsCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUserTagsCount() {
|
||||||
|
return userTagsCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCommentsCount() {
|
||||||
|
return commentsCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCommentLikesCount() {
|
||||||
|
return commentLikesCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLikesCount() {
|
||||||
|
return likesCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface OnTaskCompleteListener {
|
||||||
|
void onTaskComplete(final NotificationCounts result);
|
||||||
|
}
|
||||||
|
}
|
@ -19,6 +19,7 @@ import awais.instagrabber.utils.Utils;
|
|||||||
import awaisomereport.LogCollector;
|
import awaisomereport.LogCollector;
|
||||||
|
|
||||||
import static awais.instagrabber.utils.Utils.logCollector;
|
import static awais.instagrabber.utils.Utils.logCollector;
|
||||||
|
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||||
|
|
||||||
public final class NotificationsFetcher extends AsyncTask<Void, Void, NotificationModel[]> {
|
public final class NotificationsFetcher extends AsyncTask<Void, Void, NotificationModel[]> {
|
||||||
private final FetchListener<NotificationModel[]> fetchListener;
|
private final FetchListener<NotificationModel[]> fetchListener;
|
||||||
@ -31,6 +32,7 @@ public final class NotificationsFetcher extends AsyncTask<Void, Void, Notificati
|
|||||||
protected NotificationModel[] doInBackground(final Void... voids) {
|
protected NotificationModel[] doInBackground(final Void... voids) {
|
||||||
NotificationModel[] result = null;
|
NotificationModel[] result = null;
|
||||||
final String url = "https://www.instagram.com/accounts/activity/?__a=1";
|
final String url = "https://www.instagram.com/accounts/activity/?__a=1";
|
||||||
|
Utils.setupCookies(settingsHelper.getString(Constants.COOKIE));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
|
final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
|
||||||
|
@ -126,6 +126,7 @@ public class DirectThreadBroadcaster extends AsyncTask<DirectThreadBroadcaster.B
|
|||||||
public enum ItemType {
|
public enum ItemType {
|
||||||
TEXT("text"),
|
TEXT("text"),
|
||||||
REACTION("reaction"),
|
REACTION("reaction"),
|
||||||
|
REELSHARE("reel_share"),
|
||||||
IMAGE("configure_photo");
|
IMAGE("configure_photo");
|
||||||
|
|
||||||
private final String value;
|
private final String value;
|
||||||
@ -189,6 +190,29 @@ public class DirectThreadBroadcaster extends AsyncTask<DirectThreadBroadcaster.B
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class StoryReplyBroadcastOptions extends BroadcastOptions {
|
||||||
|
private final String text, mediaId, reelId;
|
||||||
|
|
||||||
|
public StoryReplyBroadcastOptions(String text, String mediaId, String reelId) throws UnsupportedEncodingException {
|
||||||
|
super(ItemType.REELSHARE);
|
||||||
|
this.text = URLEncoder.encode(text, "UTF-8")
|
||||||
|
.replaceAll("\\+", "%20").replaceAll("%21", "!").replaceAll("%27", "'")
|
||||||
|
.replaceAll("%28", "(").replaceAll("%29", ")").replaceAll("%7E", "~");
|
||||||
|
this.mediaId = mediaId;
|
||||||
|
this.reelId = reelId; // or user id, usually same
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Map<String, String> getFormMap() {
|
||||||
|
final Map<String, String> form = new HashMap<>();
|
||||||
|
form.put("text", text);
|
||||||
|
form.put("media_id", mediaId);
|
||||||
|
form.put("reel_id", reelId);
|
||||||
|
form.put("entry", "reel");
|
||||||
|
return form;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class ImageBroadcastOptions extends BroadcastOptions {
|
public static class ImageBroadcastOptions extends BroadcastOptions {
|
||||||
final boolean allowFullAspectRatio;
|
final boolean allowFullAspectRatio;
|
||||||
final String uploadId;
|
final String uploadId;
|
||||||
|
@ -31,15 +31,20 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import awais.instagrabber.R;
|
import awais.instagrabber.R;
|
||||||
import awais.instagrabber.activities.PostViewer;
|
import awais.instagrabber.activities.PostViewer;
|
||||||
@ -78,7 +83,7 @@ public class DirectMessageThreadFragment extends Fragment {
|
|||||||
private DirectItemModelListViewModel listViewModel;
|
private DirectItemModelListViewModel listViewModel;
|
||||||
private DirectItemModel directItemModel;
|
private DirectItemModel directItemModel;
|
||||||
private RecyclerView messageList;
|
private RecyclerView messageList;
|
||||||
private boolean hasSentSomething;
|
private boolean hasSentSomething, hasDeletedSomething;
|
||||||
private boolean hasOlder = true;
|
private boolean hasOlder = true;
|
||||||
|
|
||||||
private final ProfileModel myProfileHolder = ProfileModel.getDefaultProfileModel();
|
private final ProfileModel myProfileHolder = ProfileModel.getDefaultProfileModel();
|
||||||
@ -135,15 +140,16 @@ public class DirectMessageThreadFragment extends Fragment {
|
|||||||
List<DirectItemModel> list = listViewModel.getList().getValue();
|
List<DirectItemModel> list = listViewModel.getList().getValue();
|
||||||
final List<DirectItemModel> newList = Arrays.asList(result.getItems());
|
final List<DirectItemModel> newList = Arrays.asList(result.getItems());
|
||||||
list = list != null ? new LinkedList<>(list) : new LinkedList<>();
|
list = list != null ? new LinkedList<>(list) : new LinkedList<>();
|
||||||
if (hasSentSomething) {
|
if (hasSentSomething || hasDeletedSomething) {
|
||||||
list = newList;
|
list = newList;
|
||||||
hasSentSomething = false;
|
|
||||||
final Handler handler = new Handler();
|
final Handler handler = new Handler();
|
||||||
handler.postDelayed(() -> {
|
if (hasSentSomething) handler.postDelayed(() -> {
|
||||||
if (messageList != null) {
|
if (messageList != null) {
|
||||||
messageList.smoothScrollToPosition(0);
|
messageList.smoothScrollToPosition(0);
|
||||||
}
|
}
|
||||||
}, 200);
|
}, 200);
|
||||||
|
hasSentSomething = false;
|
||||||
|
hasDeletedSomething = false;
|
||||||
} else {
|
} else {
|
||||||
list.addAll(newList);
|
list.addAll(newList);
|
||||||
}
|
}
|
||||||
@ -186,8 +192,7 @@ public class DirectMessageThreadFragment extends Fragment {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
final DialogInterface.OnClickListener onDialogListener = (dialogInterface, which) -> {
|
final DialogInterface.OnClickListener onDialogListener = (dialogInterface, which) -> {
|
||||||
switch (which) {
|
if (which == 0) {
|
||||||
case 0:
|
|
||||||
final DirectItemType itemType = directItemModel.getItemType();
|
final DirectItemType itemType = directItemModel.getItemType();
|
||||||
switch (itemType) {
|
switch (itemType) {
|
||||||
case MEDIA_SHARE:
|
case MEDIA_SHARE:
|
||||||
@ -238,15 +243,13 @@ public class DirectMessageThreadFragment extends Fragment {
|
|||||||
default:
|
default:
|
||||||
Log.d("austin_debug", "unsupported type " + itemType);
|
Log.d("austin_debug", "unsupported type " + itemType);
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case 1:
|
else if (which == 1) {
|
||||||
sendText(null, directItemModel.getItemId(), directItemModel.isLiked());
|
sendText(null, directItemModel.getItemId(), directItemModel.isLiked());
|
||||||
break;
|
}
|
||||||
case 2:
|
else if (which == 2) {
|
||||||
if (String.valueOf(directItemModel.getUserId()).equals(myId)) {
|
if (String.valueOf(directItemModel.getUserId()).equals(myId)) new Unsend().execute();
|
||||||
// unsend: https://www.instagram.com/direct_v2/web/threads/340282366841710300949128288687654467119/items/29473546990090204551245070881259520/delete/
|
else searchUsername(getUser(directItemModel.getUserId()).getUsername());
|
||||||
} else searchUsername(getUser(directItemModel.getUserId()).getUsername());
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
final View.OnClickListener onClickListener = v -> {
|
final View.OnClickListener onClickListener = v -> {
|
||||||
@ -427,4 +430,41 @@ public class DirectMessageThreadFragment extends Fragment {
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Unsend extends AsyncTask<Void, Void, Void> {
|
||||||
|
protected Void doInBackground(Void... lmao) {
|
||||||
|
final String url = "https://i.instagram.com/api/v1/direct_v2/threads/"+threadId+"/items/"+directItemModel.getItemId()+"/delete/";
|
||||||
|
try {
|
||||||
|
String urlParameters = "_csrftoken=" + cookie.split("csrftoken=")[1].split(";")[0]
|
||||||
|
+"&_uuid=" + Utils.settingsHelper.getString(Constants.DEVICE_UUID);
|
||||||
|
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) {
|
||||||
|
hasDeletedSomething = true;
|
||||||
|
}
|
||||||
|
urlConnection.disconnect();
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
Log.e("austin_debug", "unsend: " + ex);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void result) {
|
||||||
|
if (hasDeletedSomething) {
|
||||||
|
directItemModel = null;
|
||||||
|
new DirectMessageInboxThreadFetcher(threadId, UserInboxDirection.OLDER, null, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,9 +33,9 @@ public final class UpdateChecker extends AsyncTask<Void, Void, Boolean> {
|
|||||||
conn.connect();
|
conn.connect();
|
||||||
|
|
||||||
final int responseCode = conn.getResponseCode();
|
final int responseCode = conn.getResponseCode();
|
||||||
if (responseCode == HttpURLConnection.HTTP_MOVED_TEMP) {
|
if (responseCode == HttpURLConnection.HTTP_MOVED_TEMP && !BuildConfig.DEBUG) {
|
||||||
version = conn.getHeaderField("Location").split("/v")[1];
|
version = conn.getHeaderField("Location").split("/v")[1];
|
||||||
return Float.parseFloat(version) > Float.parseFloat(BuildConfig.VERSION_NAME);
|
return version != BuildConfig.VERSION_NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
conn.disconnect();
|
conn.disconnect();
|
||||||
|
@ -175,8 +175,8 @@ public final class Utils {
|
|||||||
clipString = clipString.substring((isHttps ? 22 : 21) + wwwDel);
|
clipString = clipString.substring((isHttps ? 22 : 21) + wwwDel);
|
||||||
|
|
||||||
final char firstChar = clipString.charAt(0);
|
final char firstChar = clipString.charAt(0);
|
||||||
if (clipString.startsWith("p/") || clipString.startsWith("reel/")) {
|
if (clipString.startsWith("p/") || clipString.startsWith("reel/") || clipString.startsWith("tv/")) {
|
||||||
clipString = clipString.substring(clipString.startsWith("p/") ? 2 : 5);
|
clipString = clipString.substring(clipString.startsWith("p/") ? 2 : (clipString.startsWith("tv/") ? 3 : 5));
|
||||||
type = IntentModelType.POST;
|
type = IntentModelType.POST;
|
||||||
} else if (clipString.startsWith("explore/tags/")) {
|
} else if (clipString.startsWith("explore/tags/")) {
|
||||||
clipString = clipString.substring(13);
|
clipString = clipString.substring(13);
|
||||||
|
@ -222,4 +222,11 @@
|
|||||||
<string name="license" translatable="false">InstaGrabber\nCopyright (C) 2019 AWAiS\nCopyright (C) 2020 Austin Huang, Ammar Githam\n\nThis program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. See https://www.gnu.org/licenses/.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR \'\'AS IS\'\' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nSee project page for third-party attributions.</string>
|
<string name="license" translatable="false">InstaGrabber\nCopyright (C) 2019 AWAiS\nCopyright (C) 2020 Austin Huang, Ammar Githam\n\nThis program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. See https://www.gnu.org/licenses/.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR \'\'AS IS\'\' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nSee project page for third-party attributions.</string>
|
||||||
<string name="select_picture">Select Picture</string>
|
<string name="select_picture">Select Picture</string>
|
||||||
<string name="uploading">Uploading...</string>
|
<string name="uploading">Uploading...</string>
|
||||||
|
<string name="activity_count_prefix">You have:</string>
|
||||||
|
<string name="activity_count_relationship">%d follows</string>
|
||||||
|
<string name="activity_count_comments">%d comments</string>
|
||||||
|
<string name="activity_count_commentlikes">%d comment likes</string>
|
||||||
|
<string name="activity_count_usertags">%d usertags</string>
|
||||||
|
<string name="activity_count_likes">%d likes</string>
|
||||||
|
<string name="activity_notloggedin">You logged out before clicking this notification?!</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue
Block a user