Merge remote-tracking branch 'origin/master'

This commit is contained in:
Austin Huang 2021-05-25 22:47:42 -04:00
commit 83ac47b04a
No known key found for this signature in database
GPG Key ID: 84C23AA04587A91F
98 changed files with 727 additions and 3210 deletions

View File

@ -182,6 +182,8 @@ dependencies {
def core_version = "1.6.0-beta01" def core_version = "1.6.0-beta01"
implementation "androidx.core:core:$core_version" implementation "androidx.core:core:$core_version"
implementation "androidx.fragment:fragment-ktx:1.3.4"
// Room // Room
def room_version = "2.3.0" def room_version = "2.3.0"
implementation "androidx.room:room-runtime:$room_version" implementation "androidx.room:room-runtime:$room_version"

View File

@ -17,11 +17,9 @@ import java.util.List;
import awais.instagrabber.R; import awais.instagrabber.R;
import awais.instagrabber.adapters.DirectMessageInboxAdapter.OnItemClickListener; import awais.instagrabber.adapters.DirectMessageInboxAdapter.OnItemClickListener;
import awais.instagrabber.databinding.LayoutDmInboxItemBinding; import awais.instagrabber.databinding.LayoutDmInboxItemBinding;
import awais.instagrabber.models.enums.MediaItemType;
import awais.instagrabber.repositories.responses.User; import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.repositories.responses.directmessages.DirectItem; import awais.instagrabber.repositories.responses.directmessages.DirectItem;
import awais.instagrabber.repositories.responses.directmessages.DirectThread; import awais.instagrabber.repositories.responses.directmessages.DirectThread;
import awais.instagrabber.repositories.responses.directmessages.DirectThreadDirectStory;
import awais.instagrabber.utils.DMUtils; import awais.instagrabber.utils.DMUtils;
import awais.instagrabber.utils.TextUtils; import awais.instagrabber.utils.TextUtils;
@ -136,7 +134,7 @@ public final class DirectInboxItemViewHolder extends RecyclerView.ViewHolder {
private void setDateTime(@NonNull final DirectItem item) { private void setDateTime(@NonNull final DirectItem item) {
final long timestamp = item.getTimestamp() / 1000; final long timestamp = item.getTimestamp() / 1000;
final String dateTimeString = TextUtils.getRelativeDateTimeString(itemView.getContext(), timestamp); final String dateTimeString = TextUtils.getRelativeDateTimeString(timestamp);
binding.tvDate.setText(dateTimeString); binding.tvDate.setText(dateTimeString);
} }

View File

@ -22,6 +22,7 @@ import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.repositories.responses.directmessages.DirectItem; import awais.instagrabber.repositories.responses.directmessages.DirectItem;
import awais.instagrabber.repositories.responses.directmessages.DirectItemActionLog; import awais.instagrabber.repositories.responses.directmessages.DirectItemActionLog;
import awais.instagrabber.repositories.responses.directmessages.DirectThread; import awais.instagrabber.repositories.responses.directmessages.DirectThread;
import awais.instagrabber.repositories.responses.directmessages.TextRange;
import awais.instagrabber.utils.TextUtils; import awais.instagrabber.utils.TextUtils;
public class DirectItemActionLogViewHolder extends DirectItemViewHolder { public class DirectItemActionLogViewHolder extends DirectItemViewHolder {
@ -45,16 +46,16 @@ public class DirectItemActionLogViewHolder extends DirectItemViewHolder {
final DirectItemActionLog actionLog = directItemModel.getActionLog(); final DirectItemActionLog actionLog = directItemModel.getActionLog();
final String text = actionLog.getDescription(); final String text = actionLog.getDescription();
final SpannableStringBuilder sb = new SpannableStringBuilder(text); final SpannableStringBuilder sb = new SpannableStringBuilder(text);
final List<DirectItemActionLog.TextRange> bold = actionLog.getBold(); final List<TextRange> bold = actionLog.getBold();
if (bold != null && !bold.isEmpty()) { if (bold != null && !bold.isEmpty()) {
for (final DirectItemActionLog.TextRange textRange : bold) { for (final TextRange textRange : bold) {
final StyleSpan boldStyleSpan = new StyleSpan(Typeface.BOLD); final StyleSpan boldStyleSpan = new StyleSpan(Typeface.BOLD);
sb.setSpan(boldStyleSpan, textRange.getStart(), textRange.getEnd(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); sb.setSpan(boldStyleSpan, textRange.getStart(), textRange.getEnd(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
} }
} }
final List<DirectItemActionLog.TextRange> textAttributes = actionLog.getTextAttributes(); final List<TextRange> textAttributes = actionLog.getTextAttributes();
if (textAttributes != null && !textAttributes.isEmpty()) { if (textAttributes != null && !textAttributes.isEmpty()) {
for (final DirectItemActionLog.TextRange textAttribute : textAttributes) { for (final TextRange textAttribute : textAttributes) {
if (!TextUtils.isEmpty(textAttribute.getColor())) { if (!TextUtils.isEmpty(textAttribute.getColor())) {
final ForegroundColorSpan colorSpan = new ForegroundColorSpan(itemView.getResources().getColor(R.color.deep_orange_400)); final ForegroundColorSpan colorSpan = new ForegroundColorSpan(itemView.getResources().getColor(R.color.deep_orange_400));
sb.setSpan(colorSpan, textAttribute.getStart(), textAttribute.getEnd(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); sb.setSpan(colorSpan, textAttribute.getStart(), textAttribute.getEnd(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);

View File

@ -17,9 +17,9 @@ import awais.instagrabber.databinding.LayoutDmActionLogBinding;
import awais.instagrabber.databinding.LayoutDmBaseBinding; import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.repositories.responses.User; import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.repositories.responses.directmessages.DirectItem; import awais.instagrabber.repositories.responses.directmessages.DirectItem;
import awais.instagrabber.repositories.responses.directmessages.DirectItemActionLog;
import awais.instagrabber.repositories.responses.directmessages.DirectItemVideoCallEvent; import awais.instagrabber.repositories.responses.directmessages.DirectItemVideoCallEvent;
import awais.instagrabber.repositories.responses.directmessages.DirectThread; import awais.instagrabber.repositories.responses.directmessages.DirectThread;
import awais.instagrabber.repositories.responses.directmessages.TextRange;
import awais.instagrabber.utils.TextUtils; import awais.instagrabber.utils.TextUtils;
public class DirectItemVideoCallEventViewHolder extends DirectItemViewHolder { public class DirectItemVideoCallEventViewHolder extends DirectItemViewHolder {
@ -41,9 +41,9 @@ public class DirectItemVideoCallEventViewHolder extends DirectItemViewHolder {
final DirectItemVideoCallEvent videoCallEvent = directItemModel.getVideoCallEvent(); final DirectItemVideoCallEvent videoCallEvent = directItemModel.getVideoCallEvent();
final String text = videoCallEvent.getDescription(); final String text = videoCallEvent.getDescription();
final SpannableStringBuilder sb = new SpannableStringBuilder(text); final SpannableStringBuilder sb = new SpannableStringBuilder(text);
final List<DirectItemActionLog.TextRange> textAttributes = videoCallEvent.getTextAttributes(); final List<TextRange> textAttributes = videoCallEvent.getTextAttributes();
if (textAttributes != null && !textAttributes.isEmpty()) { if (textAttributes != null && !textAttributes.isEmpty()) {
for (final DirectItemActionLog.TextRange textAttribute : textAttributes) { for (final TextRange textAttribute : textAttributes) {
if (!TextUtils.isEmpty(textAttribute.getColor())) { if (!TextUtils.isEmpty(textAttribute.getColor())) {
final ForegroundColorSpan colorSpan = new ForegroundColorSpan(itemView.getResources().getColor(R.color.deep_orange_400)); final ForegroundColorSpan colorSpan = new ForegroundColorSpan(itemView.getResources().getColor(R.color.deep_orange_400));
sb.setSpan(colorSpan, textAttribute.getStart(), textAttribute.getEnd(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); sb.setSpan(colorSpan, textAttribute.getStart(), textAttribute.getEnd(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);

View File

@ -15,6 +15,7 @@ import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.repositories.responses.directmessages.DirectItem; import awais.instagrabber.repositories.responses.directmessages.DirectItem;
import awais.instagrabber.repositories.responses.directmessages.DirectItemXma; import awais.instagrabber.repositories.responses.directmessages.DirectItemXma;
import awais.instagrabber.repositories.responses.directmessages.DirectThread; import awais.instagrabber.repositories.responses.directmessages.DirectThread;
import awais.instagrabber.repositories.responses.directmessages.XmaUrlInfo;
import awais.instagrabber.utils.NullSafePair; import awais.instagrabber.utils.NullSafePair;
import awais.instagrabber.utils.NumberUtils; import awais.instagrabber.utils.NumberUtils;
@ -35,13 +36,13 @@ public class DirectItemXmaViewHolder extends DirectItemViewHolder {
@Override @Override
public void bindItem(final DirectItem item, final MessageDirection messageDirection) { public void bindItem(final DirectItem item, final MessageDirection messageDirection) {
final DirectItemXma xma = item.getXma(); final DirectItemXma xma = item.getXma();
final DirectItemXma.XmaUrlInfo playableUrlInfo = xma.getPlayableUrlInfo(); final XmaUrlInfo playableUrlInfo = xma.getPlayableUrlInfo();
final DirectItemXma.XmaUrlInfo previewUrlInfo = xma.getPreviewUrlInfo(); final XmaUrlInfo previewUrlInfo = xma.getPreviewUrlInfo();
if (playableUrlInfo == null && previewUrlInfo == null) { if (playableUrlInfo == null && previewUrlInfo == null) {
binding.ivAnimatedMessage.setController(null); binding.ivAnimatedMessage.setController(null);
return; return;
} }
final DirectItemXma.XmaUrlInfo urlInfo = playableUrlInfo != null ? playableUrlInfo : previewUrlInfo; final XmaUrlInfo urlInfo = playableUrlInfo != null ? playableUrlInfo : previewUrlInfo;
final String url = urlInfo.getUrl(); final String url = urlInfo.getUrl();
final NullSafePair<Integer, Integer> widthHeight = NumberUtils.calculateWidthHeight( final NullSafePair<Integer, Integer> widthHeight = NumberUtils.calculateWidthHeight(
urlInfo.getHeight(), urlInfo.getHeight(),

View File

@ -6,21 +6,10 @@ import java.time.Instant;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.ZoneId; import java.time.ZoneId;
import java.time.ZoneOffset; import java.time.ZoneOffset;
//import java.util.Date;
import awais.instagrabber.models.enums.FavoriteType; import awais.instagrabber.models.enums.FavoriteType;
public class Converters { public class Converters {
// @TypeConverter
// public static Date fromTimestamp(Long value) {
// return value == null ? null : new Date(value);
// }
//
// @TypeConverter
// public static Long dateToTimestamp(Date date) {
// return date == null ? null : date.getTime();
// }
@TypeConverter @TypeConverter
public static FavoriteType fromFavoriteTypeString(String value) { public static FavoriteType fromFavoriteTypeString(String value) {
try { try {

View File

@ -1,159 +0,0 @@
package awais.instagrabber.fragments;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavController;
import androidx.navigation.fragment.NavHostFragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.util.List;
import awais.instagrabber.R;
import awais.instagrabber.adapters.FavoritesAdapter;
import awais.instagrabber.databinding.FragmentFavoritesBinding;
import awais.instagrabber.db.datasources.FavoriteDataSource;
import awais.instagrabber.db.entities.Favorite;
import awais.instagrabber.db.repositories.FavoriteRepository;
import awais.instagrabber.db.repositories.RepositoryCallback;
import awais.instagrabber.viewmodels.FavoritesViewModel;
public class FavoritesFragment extends Fragment {
private static final String TAG = "FavoritesFragment";
private boolean shouldRefresh = true;
private FragmentFavoritesBinding binding;
private RecyclerView root;
private FavoritesViewModel favoritesViewModel;
private FavoritesAdapter adapter;
private FavoriteRepository favoriteRepository;
@Override
public void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Context context = getContext();
if (context == null) return;
favoriteRepository = FavoriteRepository.getInstance(FavoriteDataSource.getInstance(context));
}
@NonNull
@Override
public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) {
if (root != null) {
shouldRefresh = false;
return root;
}
binding = FragmentFavoritesBinding.inflate(getLayoutInflater());
root = binding.getRoot();
binding.favoriteList.setLayoutManager(new LinearLayoutManager(getContext()));
return root;
}
@Override
public void onViewCreated(@NonNull final View view, @Nullable final Bundle savedInstanceState) {
if (!shouldRefresh) return;
init();
shouldRefresh = false;
}
@Override
public void onResume() {
super.onResume();
if (favoritesViewModel == null || adapter == null) return;
// refresh list every time in onViewStateRestored since it is cheaper than implementing pull down to refresh
favoritesViewModel.getList().observe(getViewLifecycleOwner(), adapter::submitList);
favoriteRepository.getAllFavorites(new RepositoryCallback<List<Favorite>>() {
@Override
public void onSuccess(final List<Favorite> favorites) {
favoritesViewModel.getList().postValue(favorites);
}
@Override
public void onDataNotAvailable() {}
});
}
private void init() {
favoritesViewModel = new ViewModelProvider(this).get(FavoritesViewModel.class);
adapter = new FavoritesAdapter(model -> {
// navigate
switch (model.getType()) {
case USER: {
final String username = model.getQuery();
// Log.d(TAG, "username: " + username);
final NavController navController = NavHostFragment.findNavController(this);
final Bundle bundle = new Bundle();
bundle.putString("username", "@" + username);
navController.navigate(R.id.action_global_profileFragment, bundle);
break;
}
case LOCATION: {
final String locationId = model.getQuery();
// Log.d(TAG, "locationId: " + locationId);
final NavController navController = NavHostFragment.findNavController(this);
final Bundle bundle = new Bundle();
try {
bundle.putLong("locationId", Long.parseLong(locationId));
navController.navigate(R.id.action_global_locationFragment, bundle);
} catch (Exception e) {
Log.e(TAG, "init: ", e);
return;
}
break;
}
case HASHTAG: {
final String hashtag = model.getQuery();
// Log.d(TAG, "hashtag: " + hashtag);
final NavController navController = NavHostFragment.findNavController(this);
final Bundle bundle = new Bundle();
bundle.putString("hashtag", "#" + hashtag);
navController.navigate(R.id.action_global_hashTagFragment, bundle);
break;
}
default:
// do nothing
}
}, model -> {
// delete
final Context context = getContext();
if (context == null) return false;
new MaterialAlertDialogBuilder(context)
.setMessage(getString(R.string.quick_access_confirm_delete, model.getQuery()))
.setPositiveButton(R.string.yes, (d, which) -> favoriteRepository
.deleteFavorite(model.getQuery(), model.getType(), new RepositoryCallback<Void>() {
@Override
public void onSuccess(final Void result) {
d.dismiss();
favoriteRepository.getAllFavorites(new RepositoryCallback<List<Favorite>>() {
@Override
public void onSuccess(final List<Favorite> result) {
favoritesViewModel.getList().postValue(result);
}
@Override
public void onDataNotAvailable() {}
});
}
@Override
public void onDataNotAvailable() {}
}))
.setNegativeButton(R.string.no, null)
.show();
return true;
});
binding.favoriteList.setAdapter(adapter);
}
}

View File

@ -0,0 +1,102 @@
package awais.instagrabber.fragments
import android.content.DialogInterface
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.NavHostFragment
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import awais.instagrabber.R
import awais.instagrabber.adapters.FavoritesAdapter
import awais.instagrabber.databinding.FragmentFavoritesBinding
import awais.instagrabber.db.entities.Favorite
import awais.instagrabber.models.enums.FavoriteType
import awais.instagrabber.utils.extensions.TAG
import awais.instagrabber.viewmodels.FavoritesViewModel
import com.google.android.material.dialog.MaterialAlertDialogBuilder
class FavoritesFragment : Fragment() {
private var shouldRefresh = true
private lateinit var binding: FragmentFavoritesBinding
private lateinit var root: RecyclerView
private lateinit var adapter: FavoritesAdapter
private val favoritesViewModel: FavoritesViewModel by viewModels()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
if (this::root.isInitialized) {
shouldRefresh = false
return root
}
binding = FragmentFavoritesBinding.inflate(layoutInflater)
root = binding.root
binding.favoriteList.layoutManager = LinearLayoutManager(context)
return root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
if (!shouldRefresh) return
init()
shouldRefresh = false
}
override fun onResume() {
super.onResume()
if (!this::adapter.isInitialized) return
// refresh list every time in onViewStateRestored since it is cheaper than implementing pull down to refresh
favoritesViewModel.list.observe(viewLifecycleOwner, { list: List<Favorite?>? -> adapter.submitList(list) })
}
private fun init() {
adapter = FavoritesAdapter({ model: Favorite ->
when (model.type) {
FavoriteType.USER -> {
val username = model.query
// Log.d(TAG, "username: " + username);
val navController = NavHostFragment.findNavController(this)
val bundle = Bundle()
bundle.putString("username", "@$username")
navController.navigate(R.id.action_global_profileFragment, bundle)
}
FavoriteType.LOCATION -> {
val locationId = model.query
// Log.d(TAG, "locationId: " + locationId);
val navController = NavHostFragment.findNavController(this)
val bundle = Bundle()
try {
bundle.putLong("locationId", locationId.toLong())
navController.navigate(R.id.action_global_locationFragment, bundle)
} catch (e: Exception) {
Log.e(TAG, "init: ", e)
}
}
FavoriteType.HASHTAG -> {
val hashtag = model.query
// Log.d(TAG, "hashtag: " + hashtag);
val navController = NavHostFragment.findNavController(this)
val bundle = Bundle()
bundle.putString("hashtag", "#$hashtag")
navController.navigate(R.id.action_global_hashTagFragment, bundle)
}
else -> {
}
}
}, { model: Favorite ->
// delete
val context = context ?: return@FavoritesAdapter false
MaterialAlertDialogBuilder(context)
.setMessage(getString(R.string.quick_access_confirm_delete, model.query))
.setPositiveButton(R.string.yes) { d: DialogInterface, _: Int -> favoritesViewModel.delete(model) { d.dismiss() } }
.setNegativeButton(R.string.no, null)
.show()
true
})
binding.favoriteList.adapter = adapter
}
}

View File

@ -198,7 +198,7 @@ public final class InboxManager {
hasOlder = false; hasOlder = false;
return; return;
} }
if (!response.getStatus().equals("ok")) { if (!Objects.equals(response.getStatus(), "ok")) {
Log.e(TAG, "DM inbox fetch response: status not ok"); Log.e(TAG, "DM inbox fetch response: status not ok");
inbox.postValue(Resource.error(R.string.generic_not_ok_response, getCurrentDirectInbox())); inbox.postValue(Resource.error(R.string.generic_not_ok_response, getCurrentDirectInbox()));
hasOlder = false; hasOlder = false;
@ -209,18 +209,19 @@ public final class InboxManager {
viewer = response.getViewer(); viewer = response.getViewer();
} }
final DirectInbox inbox = response.getInbox(); final DirectInbox inbox = response.getInbox();
if (inbox == null) return;
if (!TextUtils.isEmpty(cursor)) { if (!TextUtils.isEmpty(cursor)) {
final DirectInbox currentDirectInbox = getCurrentDirectInbox(); final DirectInbox currentDirectInbox = getCurrentDirectInbox();
if (currentDirectInbox != null) { if (currentDirectInbox != null) {
List<DirectThread> threads = currentDirectInbox.getThreads(); List<DirectThread> threads = currentDirectInbox.getThreads();
threads = threads == null ? new LinkedList<>() : new LinkedList<>(threads); threads = threads == null ? new LinkedList<>() : new LinkedList<>(threads);
threads.addAll(inbox.getThreads()); threads.addAll(inbox.getThreads() == null ? Collections.emptyList() : inbox.getThreads());
inbox.setThreads(threads); inbox.setThreads(threads);
} }
} }
this.inbox.postValue(Resource.success(inbox)); this.inbox.postValue(Resource.success(inbox));
cursor = inbox.getOldestCursor(); cursor = inbox.getOldestCursor();
hasOlder = inbox.hasOlder(); hasOlder = inbox.getHasOlder();
pendingRequestsTotal.postValue(response.getPendingRequestsTotal()); pendingRequestsTotal.postValue(response.getPendingRequestsTotal());
} }

View File

@ -16,7 +16,6 @@ import com.google.common.collect.Iterables;
import org.json.JSONObject; import org.json.JSONObject;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.util.ArrayList; import java.util.ArrayList;
@ -40,6 +39,7 @@ import awais.instagrabber.models.Resource.Status;
import awais.instagrabber.models.UploadVideoOptions; import awais.instagrabber.models.UploadVideoOptions;
import awais.instagrabber.models.enums.DirectItemType; import awais.instagrabber.models.enums.DirectItemType;
import awais.instagrabber.repositories.requests.UploadFinishOptions; import awais.instagrabber.repositories.requests.UploadFinishOptions;
import awais.instagrabber.repositories.requests.VideoOptions;
import awais.instagrabber.repositories.requests.directmessages.ThreadIdOrUserIds; import awais.instagrabber.repositories.requests.directmessages.ThreadIdOrUserIds;
import awais.instagrabber.repositories.responses.FriendshipChangeResponse; import awais.instagrabber.repositories.responses.FriendshipChangeResponse;
import awais.instagrabber.repositories.responses.FriendshipRestrictResponse; import awais.instagrabber.repositories.responses.FriendshipRestrictResponse;
@ -49,7 +49,7 @@ import awais.instagrabber.repositories.responses.directmessages.DirectItem;
import awais.instagrabber.repositories.responses.directmessages.DirectItemEmojiReaction; import awais.instagrabber.repositories.responses.directmessages.DirectItemEmojiReaction;
import awais.instagrabber.repositories.responses.directmessages.DirectItemReactions; import awais.instagrabber.repositories.responses.directmessages.DirectItemReactions;
import awais.instagrabber.repositories.responses.directmessages.DirectItemSeenResponse; import awais.instagrabber.repositories.responses.directmessages.DirectItemSeenResponse;
import awais.instagrabber.repositories.responses.directmessages.DirectItemSeenResponse.DirectItemSeenResponsePayload; import awais.instagrabber.repositories.responses.directmessages.DirectItemSeenResponsePayload;
import awais.instagrabber.repositories.responses.directmessages.DirectThread; import awais.instagrabber.repositories.responses.directmessages.DirectThread;
import awais.instagrabber.repositories.responses.directmessages.DirectThreadBroadcastResponse; import awais.instagrabber.repositories.responses.directmessages.DirectThreadBroadcastResponse;
import awais.instagrabber.repositories.responses.directmessages.DirectThreadBroadcastResponseMessageMetadata; import awais.instagrabber.repositories.responses.directmessages.DirectThreadBroadcastResponseMessageMetadata;
@ -195,7 +195,7 @@ public final class ThreadManager {
.orElse(null); .orElse(null);
if (thread != null) { if (thread != null) {
cursor = thread.getOldestCursor(); cursor = thread.getOldestCursor();
hasOlder = thread.hasOlder(); hasOlder = thread.getHasOlder();
} }
return thread; return thread;
})); }));
@ -229,7 +229,7 @@ public final class ThreadManager {
})); }));
pending = distinctUntilChanged(map(thread, t -> { pending = distinctUntilChanged(map(thread, t -> {
if (t == null) return true; if (t == null) return true;
return t.isPending(); return t.getPending();
})); }));
adminUserIds = distinctUntilChanged(map(thread, t -> { adminUserIds = distinctUntilChanged(map(thread, t -> {
if (t == null) return Collections.emptyList(); if (t == null) return Collections.emptyList();
@ -249,15 +249,15 @@ public final class ThreadManager {
})); }));
isMuted = distinctUntilChanged(map(thread, t -> { isMuted = distinctUntilChanged(map(thread, t -> {
if (t == null) return false; if (t == null) return false;
return t.isMuted(); return t.getMuted();
})); }));
isApprovalRequiredToJoin = distinctUntilChanged(map(thread, t -> { isApprovalRequiredToJoin = distinctUntilChanged(map(thread, t -> {
if (t == null) return false; if (t == null) return false;
return t.isApprovalRequiredForNewMembers(); return t.getApprovalRequiredForNewMembers();
})); }));
isMentionsMuted = distinctUntilChanged(map(thread, t -> { isMentionsMuted = distinctUntilChanged(map(thread, t -> {
if (t == null) return false; if (t == null) return false;
return t.isMentionsMuted(); return t.getMentionsMuted();
})); }));
pendingRequestsCount = distinctUntilChanged(map(pendingRequests, p -> { pendingRequestsCount = distinctUntilChanged(map(pendingRequests, p -> {
if (p == null) return 0; if (p == null) return 0;
@ -694,9 +694,11 @@ public final class ThreadManager {
public void onUploadComplete(final MediaUploader.MediaUploadResponse response) { public void onUploadComplete(final MediaUploader.MediaUploadResponse response) {
// Log.d(TAG, "onUploadComplete: " + response); // Log.d(TAG, "onUploadComplete: " + response);
if (handleInvalidResponse(data, response)) return; if (handleInvalidResponse(data, response)) return;
final UploadFinishOptions uploadFinishOptions = new UploadFinishOptions() final UploadFinishOptions uploadFinishOptions = new UploadFinishOptions(
.setUploadId(uploadDmVoiceOptions.getUploadId()) uploadDmVoiceOptions.getUploadId(),
.setSourceType("4"); "4",
null
);
final Call<String> uploadFinishRequest = mediaService.uploadFinish(uploadFinishOptions); final Call<String> uploadFinishRequest = mediaService.uploadFinish(uploadFinishOptions);
uploadFinishRequest.enqueue(new Callback<String>() { uploadFinishRequest.enqueue(new Callback<String>() {
@Override @Override
@ -1005,7 +1007,7 @@ public final class ThreadManager {
return; return;
} }
sendPhoto(data, uri, dimensions.first, dimensions.second); sendPhoto(data, uri, dimensions.first, dimensions.second);
} catch (FileNotFoundException e) { } catch (IOException e) {
data.postValue(Resource.error(e.getMessage(), null)); data.postValue(Resource.error(e.getMessage(), null));
Log.e(TAG, "sendPhoto: ", e); Log.e(TAG, "sendPhoto: ", e);
} }
@ -1082,10 +1084,11 @@ public final class ThreadManager {
public void onUploadComplete(final MediaUploader.MediaUploadResponse response) { public void onUploadComplete(final MediaUploader.MediaUploadResponse response) {
// Log.d(TAG, "onUploadComplete: " + response); // Log.d(TAG, "onUploadComplete: " + response);
if (handleInvalidResponse(data, response)) return; if (handleInvalidResponse(data, response)) return;
final UploadFinishOptions uploadFinishOptions = new UploadFinishOptions() final UploadFinishOptions uploadFinishOptions = new UploadFinishOptions(
.setUploadId(uploadDmVideoOptions.getUploadId()) uploadDmVideoOptions.getUploadId(),
.setSourceType("2") "2",
.setVideoOptions(new UploadFinishOptions.VideoOptions().setLength(duration / 1000f)); new VideoOptions(duration / 1000f, Collections.emptyList(), 0, false)
);
final Call<String> uploadFinishRequest = mediaService.uploadFinish(uploadFinishOptions); final Call<String> uploadFinishRequest = mediaService.uploadFinish(uploadFinishOptions);
uploadFinishRequest.enqueue(new Callback<String>() { uploadFinishRequest.enqueue(new Callback<String>() {
@Override @Override

View File

@ -11,7 +11,7 @@ data class UploadVideoOptions(
val height: Int = 0, val height: Int = 0,
val isSideCar: Boolean = false, val isSideCar: Boolean = false,
// Stories // Stories
val isForAlbum: Boolean = false, val forAlbum: Boolean = false,
val isDirect: Boolean = false, val isDirect: Boolean = false,
val isDirectVoice: Boolean = false, val isDirectVoice: Boolean = false,
val isForDirectStory: Boolean = false, val isForDirectStory: Boolean = false,

View File

@ -1,114 +0,0 @@
package awais.instagrabber.repositories.requests;
import com.google.common.collect.ImmutableMap;
import java.util.List;
import java.util.Map;
public class UploadFinishOptions {
private String uploadId;
private String sourceType;
private VideoOptions videoOptions;
public String getUploadId() {
return uploadId;
}
public UploadFinishOptions setUploadId(final String uploadId) {
this.uploadId = uploadId;
return this;
}
public String getSourceType() {
return sourceType;
}
public UploadFinishOptions setSourceType(final String sourceType) {
this.sourceType = sourceType;
return this;
}
public VideoOptions getVideoOptions() {
return videoOptions;
}
public UploadFinishOptions setVideoOptions(final VideoOptions videoOptions) {
this.videoOptions = videoOptions;
return this;
}
public static class VideoOptions {
private float length;
private List<Clip> clips;
private int posterFrameIndex;
private boolean audioMuted;
public float getLength() {
return length;
}
public VideoOptions setLength(final float length) {
this.length = length;
return this;
}
public List<Clip> getClips() {
return clips;
}
public VideoOptions setClips(final List<Clip> clips) {
this.clips = clips;
return this;
}
public int getPosterFrameIndex() {
return posterFrameIndex;
}
public VideoOptions setPosterFrameIndex(final int posterFrameIndex) {
this.posterFrameIndex = posterFrameIndex;
return this;
}
public boolean isAudioMuted() {
return audioMuted;
}
public VideoOptions setAudioMuted(final boolean audioMuted) {
this.audioMuted = audioMuted;
return this;
}
public Map<String, Object> getMap() {
return ImmutableMap.of(
"length", length,
"clips", clips,
"poster_frame_index", posterFrameIndex,
"audio_muted", audioMuted
);
}
}
public static class Clip {
private float length;
private String sourceType;
public float getLength() {
return length;
}
public Clip setLength(final float length) {
this.length = length;
return this;
}
public String getSourceType() {
return sourceType;
}
public Clip setSourceType(final String sourceType) {
this.sourceType = sourceType;
return this;
}
}
}

View File

@ -0,0 +1,27 @@
package awais.instagrabber.repositories.requests
data class UploadFinishOptions(
val uploadId: String,
val sourceType: String,
val videoOptions: VideoOptions? = null
)
data class VideoOptions(
val length: Float = 0f,
var clips: List<Clip> = emptyList(),
val posterFrameIndex: Int = 0,
val isAudioMuted: Boolean = false
) {
val map: Map<String, Any>
get() = mapOf(
"length" to length,
"clips" to clips,
"poster_frame_index" to posterFrameIndex,
"audio_muted" to isAudioMuted
)
}
data class Clip(
val length: Float = 0f,
val sourceType: String
)

View File

@ -2,6 +2,9 @@ package awais.instagrabber.repositories.responses
import java.io.Serializable import java.io.Serializable
data class Caption(val userId: Long, var text: String?) : Serializable { data class Caption(
var pk: Long = 0 val userId: Long = 0,
var text: String? = null,
) : Serializable {
var pk: String? = null
} }

View File

@ -1,31 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
public class DirectBadgeCount {
private final long userId;
private final int badgeCount;
private final long badgeCountAtMs;
private final String status;
public DirectBadgeCount(final long userId, final int badgeCount, final long badgeCountAtMs, final String status) {
this.userId = userId;
this.badgeCount = badgeCount;
this.badgeCountAtMs = badgeCountAtMs;
this.status = status;
}
public long getUserId() {
return userId;
}
public int getBadgeCount() {
return badgeCount;
}
public long getBadgeCountAtMs() {
return badgeCountAtMs;
}
public String getStatus() {
return status;
}
}

View File

@ -0,0 +1,8 @@
package awais.instagrabber.repositories.responses.directmessages
data class DirectBadgeCount(
val userId: Long = 0,
val badgeCount: Int = 0,
val badgeCountAtMs: Long = 0,
val status: String? = null
)

View File

@ -1,62 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
import androidx.annotation.NonNull;
import java.util.List;
public class DirectInbox implements Cloneable {
private List<DirectThread> threads;
private final boolean hasOlder;
private final int unseenCount;
private final String unseenCountTs;
private final String oldestCursor;
private final boolean blendedInboxEnabled;
public DirectInbox(final List<DirectThread> threads,
final boolean hasOlder,
final int unseenCount,
final String unseenCountTs,
final String oldestCursor,
final boolean blendedInboxEnabled) {
this.threads = threads;
this.hasOlder = hasOlder;
this.unseenCount = unseenCount;
this.unseenCountTs = unseenCountTs;
this.oldestCursor = oldestCursor;
this.blendedInboxEnabled = blendedInboxEnabled;
}
public List<DirectThread> getThreads() {
return threads;
}
public void setThreads(final List<DirectThread> threads) {
this.threads = threads;
}
public boolean hasOlder() {
return hasOlder;
}
public int getUnseenCount() {
return unseenCount;
}
public String getUnseenCountTs() {
return unseenCountTs;
}
public String getOldestCursor() {
return oldestCursor;
}
public boolean isBlendedInboxEnabled() {
return blendedInboxEnabled;
}
@NonNull
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}

View File

@ -0,0 +1,15 @@
package awais.instagrabber.repositories.responses.directmessages
data class DirectInbox(
var threads: List<DirectThread>? = emptyList(),
val hasOlder: Boolean = false,
val unseenCount: Int = 0,
val unseenCountTs: String? = null,
val oldestCursor: String? = null,
val blendedInboxEnabled: Boolean
) : Cloneable {
@Throws(CloneNotSupportedException::class)
public override fun clone(): Any {
return super.clone()
}
}

View File

@ -1,64 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
import awais.instagrabber.repositories.responses.User;
public class DirectInboxResponse {
private final User viewer;
private final DirectInbox inbox;
private final long seqId;
private final long snapshotAtMs;
private final int pendingRequestsTotal;
private final boolean hasPendingTopRequests;
private final User mostRecentInviter;
private final String status;
public DirectInboxResponse(final User viewer,
final DirectInbox inbox,
final long seqId,
final long snapshotAtMs,
final int pendingRequestsTotal,
final boolean hasPendingTopRequests,
final User mostRecentInviter,
final String status) {
this.viewer = viewer;
this.inbox = inbox;
this.seqId = seqId;
this.snapshotAtMs = snapshotAtMs;
this.pendingRequestsTotal = pendingRequestsTotal;
this.hasPendingTopRequests = hasPendingTopRequests;
this.mostRecentInviter = mostRecentInviter;
this.status = status;
}
public User getViewer() {
return viewer;
}
public DirectInbox getInbox() {
return inbox;
}
public long getSeqId() {
return seqId;
}
public long getSnapshotAtMs() {
return snapshotAtMs;
}
public int getPendingRequestsTotal() {
return pendingRequestsTotal;
}
public boolean hasPendingTopRequests() {
return hasPendingTopRequests;
}
public User getMostRecentInviter() {
return mostRecentInviter;
}
public String getStatus() {
return status;
}
}

View File

@ -0,0 +1,14 @@
package awais.instagrabber.repositories.responses.directmessages
import awais.instagrabber.repositories.responses.User
data class DirectInboxResponse(
val viewer: User? = null,
val inbox: DirectInbox? = null,
val seqId: Long = 0,
val snapshotAtMs: Long = 0,
val pendingRequestsTotal: Int = 0,
val hasPendingTopRequests: Boolean = false,
val mostRecentInviter: User? = null,
val status: String? = null,
)

View File

@ -1,92 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
import java.io.Serializable;
import java.util.List;
import java.util.Objects;
public class DirectItemActionLog implements Serializable {
private final String description;
private final List<TextRange> bold;
private final List<TextRange> textAttributes;
public DirectItemActionLog(final String description,
final List<TextRange> bold,
final List<TextRange> textAttributes) {
this.description = description;
this.bold = bold;
this.textAttributes = textAttributes;
}
public String getDescription() {
return description;
}
public List<TextRange> getBold() {
return bold;
}
public List<TextRange> getTextAttributes() {
return textAttributes;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final DirectItemActionLog that = (DirectItemActionLog) o;
return Objects.equals(description, that.description) &&
Objects.equals(bold, that.bold) &&
Objects.equals(textAttributes, that.textAttributes);
}
@Override
public int hashCode() {
return Objects.hash(description, bold, textAttributes);
}
public static class TextRange implements Serializable {
private final int start;
private final int end;
private final String color;
private final String intent;
public TextRange(final int start, final int end, final String color, final String intent) {
this.start = start;
this.end = end;
this.color = color;
this.intent = intent;
}
public int getStart() {
return start;
}
public int getEnd() {
return end;
}
public String getColor() {
return color;
}
public String getIntent() {
return intent;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final TextRange textRange = (TextRange) o;
return start == textRange.start &&
end == textRange.end &&
Objects.equals(color, textRange.color) &&
Objects.equals(intent, textRange.intent);
}
@Override
public int hashCode() {
return Objects.hash(start, end, color, intent);
}
}
}

View File

@ -0,0 +1,9 @@
package awais.instagrabber.repositories.responses.directmessages
import java.io.Serializable
data class DirectItemActionLog(
val description: String? = null,
val bold: List<TextRange>? = null,
val textAttributes: List<TextRange>? = null
) : Serializable

View File

@ -1,53 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
import java.io.Serializable;
import java.util.Objects;
import awais.instagrabber.repositories.responses.AnimatedMediaImages;
public final class DirectItemAnimatedMedia implements Serializable {
private final String id;
private final AnimatedMediaImages images;
private final boolean isRandom;
private final boolean isSticker;
public DirectItemAnimatedMedia(final String id, final AnimatedMediaImages images, final boolean isRandom, final boolean isSticker) {
this.id = id;
this.images = images;
this.isRandom = isRandom;
this.isSticker = isSticker;
}
public String getId() {
return id;
}
public AnimatedMediaImages getImages() {
return images;
}
public boolean isRandom() {
return isRandom;
}
public boolean isSticker() {
return isSticker;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final DirectItemAnimatedMedia that = (DirectItemAnimatedMedia) o;
return isRandom == that.isRandom &&
isSticker == that.isSticker &&
Objects.equals(id, that.id) &&
Objects.equals(images, that.images);
}
@Override
public int hashCode() {
return Objects.hash(id, images, isRandom, isSticker);
}
}

View File

@ -0,0 +1,11 @@
package awais.instagrabber.repositories.responses.directmessages
import awais.instagrabber.repositories.responses.AnimatedMediaImages
import java.io.Serializable
data class DirectItemAnimatedMedia(
val id: String? = null,
val images: AnimatedMediaImages? = null,
val isRandom: Boolean = false,
val isSticker: Boolean = false,
) : Serializable

View File

@ -1,31 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
import java.io.Serializable;
import java.util.Objects;
import awais.instagrabber.repositories.responses.Media;
public class DirectItemClip implements Serializable {
private final Media clip;
public DirectItemClip(final Media clip) {
this.clip = clip;
}
public Media getClip() {
return clip;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final DirectItemClip that = (DirectItemClip) o;
return Objects.equals(clip, that.clip);
}
@Override
public int hashCode() {
return Objects.hash(clip);
}
}

View File

@ -0,0 +1,6 @@
package awais.instagrabber.repositories.responses.directmessages
import awais.instagrabber.repositories.responses.Media
import java.io.Serializable
data class DirectItemClip(val clip: Media? = null) : Serializable

View File

@ -1,60 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
import java.io.Serializable;
import java.util.Objects;
public class DirectItemEmojiReaction implements Serializable {
private final long senderId;
private final long timestamp;
private final String emoji;
private final String superReactType;
public DirectItemEmojiReaction(final long senderId, final long timestamp, final String emoji, final String superReactType) {
this.senderId = senderId;
this.timestamp = timestamp;
this.emoji = emoji;
this.superReactType = superReactType;
}
public long getSenderId() {
return senderId;
}
public long getTimestamp() {
return timestamp;
}
public String getEmoji() {
return emoji;
}
public String getSuperReactType() {
return superReactType;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final DirectItemEmojiReaction that = (DirectItemEmojiReaction) o;
return senderId == that.senderId &&
timestamp == that.timestamp &&
Objects.equals(emoji, that.emoji) &&
Objects.equals(superReactType, that.superReactType);
}
@Override
public int hashCode() {
return Objects.hash(senderId, timestamp, emoji, superReactType);
}
@Override
public String toString() {
return "DirectItemEmojiReaction{" +
"senderId=" + senderId +
", timestamp=" + timestamp +
", emoji='" + emoji + '\'' +
", superReactType='" + superReactType + '\'' +
'}';
}
}

View File

@ -0,0 +1,10 @@
package awais.instagrabber.repositories.responses.directmessages
import java.io.Serializable
data class DirectItemEmojiReaction(
val senderId: Long = 0,
val timestamp: Long = 0,
val emoji: String? = null,
val superReactType: String? = null
) : Serializable

View File

@ -1,31 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
import java.io.Serializable;
import java.util.Objects;
import awais.instagrabber.repositories.responses.Media;
public class DirectItemFelixShare implements Serializable {
private final Media video;
public DirectItemFelixShare(final Media video) {
this.video = video;
}
public Media getVideo() {
return video;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final DirectItemFelixShare that = (DirectItemFelixShare) o;
return Objects.equals(video, that.video);
}
@Override
public int hashCode() {
return Objects.hash(video);
}
}

View File

@ -0,0 +1,6 @@
package awais.instagrabber.repositories.responses.directmessages
import awais.instagrabber.repositories.responses.Media
import java.io.Serializable
data class DirectItemFelixShare(val video: Media? = null) : Serializable

View File

@ -1,53 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
import java.io.Serializable;
import java.util.Objects;
public class DirectItemLink implements Serializable {
private final String text;
private final DirectItemLinkContext linkContext;
private final String clientContext;
private final String mutationToken;
public DirectItemLink(final String text,
final DirectItemLinkContext linkContext,
final String clientContext,
final String mutationToken) {
this.text = text;
this.linkContext = linkContext;
this.clientContext = clientContext;
this.mutationToken = mutationToken;
}
public String getText() {
return text;
}
public DirectItemLinkContext getLinkContext() {
return linkContext;
}
public String getClientContext() {
return clientContext;
}
public String getMutationToken() {
return mutationToken;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final DirectItemLink that = (DirectItemLink) o;
return Objects.equals(text, that.text) &&
Objects.equals(linkContext, that.linkContext) &&
Objects.equals(clientContext, that.clientContext) &&
Objects.equals(mutationToken, that.mutationToken);
}
@Override
public int hashCode() {
return Objects.hash(text, linkContext, clientContext, mutationToken);
}
}

View File

@ -0,0 +1,10 @@
package awais.instagrabber.repositories.responses.directmessages
import java.io.Serializable
data class DirectItemLink(
val text: String? = null,
val linkContext: DirectItemLinkContext? = null,
val clientContext: String? = null,
val mutationToken: String? = null,
) : Serializable

View File

@ -1,53 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
import java.io.Serializable;
import java.util.Objects;
public class DirectItemLinkContext implements Serializable {
private final String linkUrl;
private final String linkTitle;
private final String linkSummary;
private final String linkImageUrl;
public DirectItemLinkContext(final String linkUrl,
final String linkTitle,
final String linkSummary,
final String linkImageUrl) {
this.linkUrl = linkUrl;
this.linkTitle = linkTitle;
this.linkSummary = linkSummary;
this.linkImageUrl = linkImageUrl;
}
public String getLinkUrl() {
return linkUrl;
}
public String getLinkTitle() {
return linkTitle;
}
public String getLinkSummary() {
return linkSummary;
}
public String getLinkImageUrl() {
return linkImageUrl;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final DirectItemLinkContext that = (DirectItemLinkContext) o;
return Objects.equals(linkUrl, that.linkUrl) &&
Objects.equals(linkTitle, that.linkTitle) &&
Objects.equals(linkSummary, that.linkSummary) &&
Objects.equals(linkImageUrl, that.linkImageUrl);
}
@Override
public int hashCode() {
return Objects.hash(linkUrl, linkTitle, linkSummary, linkImageUrl);
}
}

View File

@ -0,0 +1,10 @@
package awais.instagrabber.repositories.responses.directmessages
import java.io.Serializable
data class DirectItemLinkContext(
val linkUrl: String? = null,
val linkTitle: String? = null,
val linkSummary: String? = null,
val linkImageUrl: String? = null
) : Serializable

View File

@ -1,45 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
import java.io.Serializable;
import java.util.Objects;
public class DirectItemPlaceholder implements Serializable {
private final boolean isLinked;
private final String title;
private final String message;
public DirectItemPlaceholder(final boolean isLinked,
final String title,
final String message) {
this.isLinked = isLinked;
this.title = title;
this.message = message;
}
public boolean isLinked() {
return isLinked;
}
public String getTitle() {
return title;
}
public String getMessage() {
return message;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final DirectItemPlaceholder that = (DirectItemPlaceholder) o;
return isLinked == that.isLinked &&
Objects.equals(title, that.title) &&
Objects.equals(message, that.message);
}
@Override
public int hashCode() {
return Objects.hash(isLinked, title, message);
}
}

View File

@ -0,0 +1,9 @@
package awais.instagrabber.repositories.responses.directmessages
import java.io.Serializable
data class DirectItemPlaceholder(
val isLinked: Boolean = false,
val title: String? = null,
val message: String? = null,
) : Serializable

View File

@ -1,62 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
import androidx.annotation.NonNull;
import java.io.Serializable;
import java.util.List;
import java.util.Objects;
public class DirectItemReactions implements Cloneable, Serializable {
private List<DirectItemEmojiReaction> emojis;
private List<DirectItemEmojiReaction> likes;
public DirectItemReactions(final List<DirectItemEmojiReaction> emojis,
final List<DirectItemEmojiReaction> likes) {
this.emojis = emojis;
this.likes = likes;
}
public List<DirectItemEmojiReaction> getEmojis() {
return emojis;
}
public List<DirectItemEmojiReaction> getLikes() {
return likes;
}
public void setLikes(final List<DirectItemEmojiReaction> likes) {
this.likes = likes;
}
public void setEmojis(final List<DirectItemEmojiReaction> emojis) {
this.emojis = emojis;
}
@NonNull
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final DirectItemReactions that = (DirectItemReactions) o;
return Objects.equals(emojis, that.emojis) &&
Objects.equals(likes, that.likes);
}
@Override
public int hashCode() {
return Objects.hash(emojis, likes);
}
@Override
public String toString() {
return "DirectItemReactions{" +
"emojis=" + emojis +
", likes=" + likes +
'}';
}
}

View File

@ -0,0 +1,13 @@
package awais.instagrabber.repositories.responses.directmessages
import java.io.Serializable
data class DirectItemReactions(
var emojis: List<DirectItemEmojiReaction>? = null,
var likes: List<DirectItemEmojiReaction>? = null,
) : Cloneable, Serializable {
@Throws(CloneNotSupportedException::class)
public override fun clone(): Any {
return super.clone()
}
}

View File

@ -1,87 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
import java.io.Serializable;
import java.util.Objects;
import awais.instagrabber.repositories.responses.Media;
public class DirectItemReelShare implements Serializable {
private final String text;
private final String type;
private final long reelOwnerId;
private final long mentionedUserId;
private final boolean isReelPersisted;
private final String reelType;
private final Media media;
private final DirectItemReelShareReactionInfo reactionInfo;
public DirectItemReelShare(final String text,
final String type,
final long reelOwnerId,
final long mentionedUserId,
final boolean isReelPersisted,
final String reelType,
final Media media,
final DirectItemReelShareReactionInfo reactionInfo) {
this.text = text;
this.type = type;
this.reelOwnerId = reelOwnerId;
this.mentionedUserId = mentionedUserId;
this.isReelPersisted = isReelPersisted;
this.reelType = reelType;
this.media = media;
this.reactionInfo = reactionInfo;
}
public String getText() {
return text;
}
public String getType() {
return type;
}
public long getReelOwnerId() {
return reelOwnerId;
}
public boolean isReelPersisted() {
return isReelPersisted;
}
public String getReelType() {
return reelType;
}
public Media getMedia() {
return media;
}
public DirectItemReelShareReactionInfo getReactionInfo() {
return reactionInfo;
}
public long getMentionedUserId() {
return mentionedUserId;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final DirectItemReelShare that = (DirectItemReelShare) o;
return reelOwnerId == that.reelOwnerId &&
mentionedUserId == that.mentionedUserId &&
isReelPersisted == that.isReelPersisted &&
Objects.equals(text, that.text) &&
Objects.equals(type, that.type) &&
Objects.equals(reelType, that.reelType) &&
Objects.equals(media, that.media) &&
Objects.equals(reactionInfo, that.reactionInfo);
}
@Override
public int hashCode() {
return Objects.hash(text, type, reelOwnerId, mentionedUserId, isReelPersisted, reelType, media, reactionInfo);
}
}

View File

@ -0,0 +1,15 @@
package awais.instagrabber.repositories.responses.directmessages
import awais.instagrabber.repositories.responses.Media
import java.io.Serializable
data class DirectItemReelShare(
val text: String? = null,
val type: String? = null,
val reelOwnerId: Long = 0,
val mentionedUserId: Long = 0,
val isReelPersisted: Boolean = false,
val reelType: String? = null,
val media: Media? = null,
val reactionInfo: DirectItemReelShareReactionInfo? = null,
) : Serializable

View File

@ -1,36 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
import java.io.Serializable;
import java.util.Objects;
public class DirectItemReelShareReactionInfo implements Serializable {
private final String emoji;
private final String intensity;
public DirectItemReelShareReactionInfo(final String emoji, final String intensity) {
this.emoji = emoji;
this.intensity = intensity;
}
public String getEmoji() {
return emoji;
}
public String getIntensity() {
return intensity;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final DirectItemReelShareReactionInfo that = (DirectItemReelShareReactionInfo) o;
return Objects.equals(emoji, that.emoji) &&
Objects.equals(intensity, that.intensity);
}
@Override
public int hashCode() {
return Objects.hash(emoji, intensity);
}
}

View File

@ -0,0 +1,8 @@
package awais.instagrabber.repositories.responses.directmessages
import java.io.Serializable
data class DirectItemReelShareReactionInfo(
val emoji: String? = null,
val intensity: String? = null,
) : Serializable

View File

@ -1,95 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
import androidx.annotation.NonNull;
import java.util.Objects;
public class DirectItemSeenResponse {
private final String action;
private final DirectItemSeenResponsePayload payload;
private final String status;
public DirectItemSeenResponse(final String action, final DirectItemSeenResponsePayload payload, final String status) {
this.action = action;
this.payload = payload;
this.status = status;
}
public String getAction() {
return action;
}
public DirectItemSeenResponsePayload getPayload() {
return payload;
}
public String getStatus() {
return status;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final DirectItemSeenResponse that = (DirectItemSeenResponse) o;
return Objects.equals(action, that.action) &&
Objects.equals(payload, that.payload) &&
Objects.equals(status, that.status);
}
@Override
public int hashCode() {
return Objects.hash(action, payload, status);
}
@NonNull
@Override
public String toString() {
return "DirectItemSeenResponse{" +
"action='" + action + '\'' +
", payload=" + payload +
", status='" + status + '\'' +
'}';
}
public static class DirectItemSeenResponsePayload {
private final int count;
private final String timestamp;
public DirectItemSeenResponsePayload(final int count, final String timestamp) {
this.count = count;
this.timestamp = timestamp;
}
public int getCount() {
return count;
}
public String getTimestamp() {
return timestamp;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final DirectItemSeenResponsePayload that = (DirectItemSeenResponsePayload) o;
return count == that.count &&
Objects.equals(timestamp, that.timestamp);
}
@Override
public int hashCode() {
return Objects.hash(count, timestamp);
}
@NonNull
@Override
public String toString() {
return "DirectItemSeenResponsePayload{" +
"count=" + count +
", timestamp='" + timestamp + '\'' +
'}';
}
}
}

View File

@ -0,0 +1,7 @@
package awais.instagrabber.repositories.responses.directmessages
data class DirectItemSeenResponse(
val action: String? = null,
val payload: DirectItemSeenResponsePayload? = null,
val status: String? = null,
)

View File

@ -0,0 +1,3 @@
package awais.instagrabber.repositories.responses.directmessages
data class DirectItemSeenResponsePayload(val count: Int = 0, val timestamp: String? = null)

View File

@ -1,79 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
import java.io.Serializable;
import java.util.Objects;
import awais.instagrabber.repositories.responses.Media;
public class DirectItemStoryShare implements Serializable {
private final String reelId;
private final String reelType;
private final String text;
private final boolean isReelPersisted;
private final Media media;
private final String title;
private final String message;
public DirectItemStoryShare(final String reelId,
final String reelType,
final String text,
final boolean isReelPersisted,
final Media media,
final String title,
final String message) {
this.reelId = reelId;
this.reelType = reelType;
this.text = text;
this.isReelPersisted = isReelPersisted;
this.media = media;
this.title = title;
this.message = message;
}
public String getReelId() {
return reelId;
}
public String getReelType() {
return reelType;
}
public String getText() {
return text;
}
public boolean isReelPersisted() {
return isReelPersisted;
}
public Media getMedia() {
return media;
}
public String getTitle() {
return title;
}
public String getMessage() {
return message;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final DirectItemStoryShare that = (DirectItemStoryShare) o;
return isReelPersisted == that.isReelPersisted &&
Objects.equals(reelId, that.reelId) &&
Objects.equals(reelType, that.reelType) &&
Objects.equals(text, that.text) &&
Objects.equals(media, that.media) &&
Objects.equals(title, that.title) &&
Objects.equals(message, that.message);
}
@Override
public int hashCode() {
return Objects.hash(reelId, reelType, text, isReelPersisted, media, title, message);
}
}

View File

@ -0,0 +1,14 @@
package awais.instagrabber.repositories.responses.directmessages
import awais.instagrabber.repositories.responses.Media
import java.io.Serializable
data class DirectItemStoryShare(
val reelId: String? = null,
val reelType: String? = null,
val text: String? = null,
val isReelPersisted: Boolean = false,
val media: Media? = null,
val title: String? = null,
val message: String? = null,
) : Serializable

View File

@ -1,62 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
import java.io.Serializable;
import java.util.List;
import java.util.Objects;
public final class DirectItemVideoCallEvent implements Serializable {
private final String action;
private final String encodedServerDataInfo;
private final String description;
private final boolean threadHasAudioOnlyCall;
private final List<DirectItemActionLog.TextRange> textAttributes;
public DirectItemVideoCallEvent(final String action,
final String encodedServerDataInfo,
final String description,
final boolean threadHasAudioOnlyCall,
final List<DirectItemActionLog.TextRange> textAttributes) {
this.action = action;
this.encodedServerDataInfo = encodedServerDataInfo;
this.description = description;
this.threadHasAudioOnlyCall = threadHasAudioOnlyCall;
this.textAttributes = textAttributes;
}
public String getAction() {
return action;
}
public String getEncodedServerDataInfo() {
return encodedServerDataInfo;
}
public String getDescription() {
return description;
}
public boolean isThreadHasAudioOnlyCall() {
return threadHasAudioOnlyCall;
}
public List<DirectItemActionLog.TextRange> getTextAttributes() {
return textAttributes;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final DirectItemVideoCallEvent that = (DirectItemVideoCallEvent) o;
return threadHasAudioOnlyCall == that.threadHasAudioOnlyCall &&
Objects.equals(action, that.action) &&
Objects.equals(encodedServerDataInfo, that.encodedServerDataInfo) &&
Objects.equals(description, that.description) &&
Objects.equals(textAttributes, that.textAttributes);
}
@Override
public int hashCode() {
return Objects.hash(action, encodedServerDataInfo, description, threadHasAudioOnlyCall, textAttributes);
}
}

View File

@ -0,0 +1,11 @@
package awais.instagrabber.repositories.responses.directmessages
import java.io.Serializable
data class DirectItemVideoCallEvent(
val action: String? = null,
val encodedServerDataInfo: String? = null,
val description: String? = null,
val threadHasAudioOnlyCall: Boolean = false,
val textAttributes: List<TextRange>? = null,
) : Serializable

View File

@ -1,90 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
import java.io.Serializable;
import java.util.List;
import java.util.Objects;
import awais.instagrabber.models.enums.RavenMediaViewMode;
import awais.instagrabber.repositories.responses.Media;
public class DirectItemVisualMedia implements Serializable {
private final long urlExpireAtSecs;
private final int playbackDurationSecs;
private final List<Long> seenUserIds;
private final RavenMediaViewMode viewMode;
private final int seenCount;
private final long replayExpiringAtUs;
private final RavenExpiringMediaActionSummary expiringMediaActionSummary;
private final Media media;
public DirectItemVisualMedia(final long urlExpireAtSecs,
final int playbackDurationSecs,
final List<Long> seenUserIds,
final RavenMediaViewMode viewMode,
final int seenCount,
final long replayExpiringAtUs,
final RavenExpiringMediaActionSummary expiringMediaActionSummary,
final Media media) {
this.urlExpireAtSecs = urlExpireAtSecs;
this.playbackDurationSecs = playbackDurationSecs;
this.seenUserIds = seenUserIds;
this.viewMode = viewMode;
this.seenCount = seenCount;
this.replayExpiringAtUs = replayExpiringAtUs;
this.expiringMediaActionSummary = expiringMediaActionSummary;
this.media = media;
}
public long getUrlExpireAtSecs() {
return urlExpireAtSecs;
}
public int getPlaybackDurationSecs() {
return playbackDurationSecs;
}
public List<Long> getSeenUserIds() {
return seenUserIds;
}
public RavenMediaViewMode getViewMode() {
return viewMode;
}
public int getSeenCount() {
return seenCount;
}
public long getReplayExpiringAtUs() {
return replayExpiringAtUs;
}
public RavenExpiringMediaActionSummary getExpiringMediaActionSummary() {
return expiringMediaActionSummary;
}
public Media getMedia() {
return media;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final DirectItemVisualMedia media1 = (DirectItemVisualMedia) o;
return urlExpireAtSecs == media1.urlExpireAtSecs &&
playbackDurationSecs == media1.playbackDurationSecs &&
seenCount == media1.seenCount &&
replayExpiringAtUs == media1.replayExpiringAtUs &&
Objects.equals(seenUserIds, media1.seenUserIds) &&
viewMode == media1.viewMode &&
Objects.equals(expiringMediaActionSummary, media1.expiringMediaActionSummary) &&
Objects.equals(media, media1.media);
}
@Override
public int hashCode() {
return Objects
.hash(urlExpireAtSecs, playbackDurationSecs, seenUserIds, viewMode, seenCount, replayExpiringAtUs, expiringMediaActionSummary, media);
}
}

View File

@ -0,0 +1,16 @@
package awais.instagrabber.repositories.responses.directmessages
import awais.instagrabber.models.enums.RavenMediaViewMode
import awais.instagrabber.repositories.responses.Media
import java.io.Serializable
data class DirectItemVisualMedia(
val urlExpireAtSecs: Long = 0,
val playbackDurationSecs: Int = 0,
val seenUserIds: List<Long>? = null,
val viewMode: RavenMediaViewMode? = null,
val seenCount: Int = 0,
val replayExpiringAtUs: Long = 0,
val expiringMediaActionSummary: RavenExpiringMediaActionSummary? = null,
val media: Media? = null,
) : Serializable

View File

@ -1,45 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
import java.io.Serializable;
import java.util.Objects;
import awais.instagrabber.repositories.responses.Media;
public class DirectItemVoiceMedia implements Serializable {
private final Media media;
private final int seenCount;
private final String viewMode;
public DirectItemVoiceMedia(final Media media, final int seenCount, final String viewMode) {
this.media = media;
this.seenCount = seenCount;
this.viewMode = viewMode;
}
public Media getMedia() {
return media;
}
public int getSeenCount() {
return seenCount;
}
public String getViewMode() {
return viewMode;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final DirectItemVoiceMedia that = (DirectItemVoiceMedia) o;
return seenCount == that.seenCount &&
Objects.equals(media, that.media) &&
Objects.equals(viewMode, that.viewMode);
}
@Override
public int hashCode() {
return Objects.hash(media, seenCount, viewMode);
}
}

View File

@ -0,0 +1,10 @@
package awais.instagrabber.repositories.responses.directmessages
import awais.instagrabber.repositories.responses.Media
import java.io.Serializable
data class DirectItemVoiceMedia(
val media: Media? = null,
val seenCount: Int = 0,
val viewMode: String? = null,
) : Serializable

View File

@ -1,104 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
import androidx.annotation.NonNull;
import java.io.Serializable;
import java.util.Objects;
public class DirectItemXma {
private final XmaUrlInfo previewUrlInfo;
private final XmaUrlInfo playableUrlInfo;
public DirectItemXma(final XmaUrlInfo previewUrlInfo, final XmaUrlInfo playableUrlInfo) {
this.previewUrlInfo = previewUrlInfo;
this.playableUrlInfo = playableUrlInfo;
}
public XmaUrlInfo getPreviewUrlInfo() {
return previewUrlInfo;
}
public XmaUrlInfo getPlayableUrlInfo() {
return playableUrlInfo;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final DirectItemXma that = (DirectItemXma) o;
return Objects.equals(previewUrlInfo, that.previewUrlInfo) &&
Objects.equals(playableUrlInfo, that.playableUrlInfo);
}
@Override
public int hashCode() {
return Objects.hash(previewUrlInfo, playableUrlInfo);
}
@NonNull
@Override
public String toString() {
return "DirectItemXma{" +
"previewUrlInfo=" + previewUrlInfo +
", playableUrlInfo=" + playableUrlInfo +
'}';
}
public static class XmaUrlInfo implements Serializable {
private final String url;
private final long urlExpirationTimestampUs;
private final int width;
private final int height;
public XmaUrlInfo(final String url, final long urlExpirationTimestampUs, final int width, final int height) {
this.url = url;
this.urlExpirationTimestampUs = urlExpirationTimestampUs;
this.width = width;
this.height = height;
}
public String getUrl() {
return url;
}
public long getUrlExpirationTimestampUs() {
return urlExpirationTimestampUs;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final XmaUrlInfo that = (XmaUrlInfo) o;
return urlExpirationTimestampUs == that.urlExpirationTimestampUs &&
width == that.width &&
height == that.height &&
Objects.equals(url, that.url);
}
@Override
public int hashCode() {
return Objects.hash(url, urlExpirationTimestampUs, width, height);
}
@NonNull
@Override
public String toString() {
return "XmaUrlInfo{" +
"url='" + url + '\'' +
", urlExpirationTimestampUs=" + urlExpirationTimestampUs +
", width=" + width +
", height=" + height +
'}';
}
}
}

View File

@ -0,0 +1,15 @@
package awais.instagrabber.repositories.responses.directmessages
import java.io.Serializable
data class DirectItemXma(
val previewUrlInfo: XmaUrlInfo? = null,
val playableUrlInfo: XmaUrlInfo? = null,
) : Serializable
data class XmaUrlInfo(
val url: String? = null,
val urlExpirationTimestampUs: Long = 0,
val width: Int = 0,
val height: Int = 0,
) : Serializable

View File

@ -1,372 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import awais.instagrabber.repositories.responses.User;
public class DirectThread implements Serializable, Cloneable {
private final String threadId;
private final String threadV2Id;
private List<User> users;
private List<User> leftUsers;
private List<Long> adminUserIds;
private List<DirectItem> items;
private final long lastActivityAt;
private boolean muted;
private final boolean isPin;
private final boolean named;
private final boolean canonical;
private boolean pending;
private final boolean archived;
private final boolean valuedRequest;
private final String threadType;
private final long viewerId;
private final String threadTitle;
private final String pendingScore;
private final long folder;
private final boolean vcMuted;
private final boolean isGroup;
private boolean mentionsMuted;
private final User inviter;
private final boolean hasOlder;
private final boolean hasNewer;
private Map<Long, DirectThreadLastSeenAt> lastSeenAt;
private final String newestCursor;
private final String oldestCursor;
private final boolean isSpam;
private final DirectItem lastPermanentItem;
private final DirectThreadDirectStory directStory;
private boolean approvalRequiredForNewMembers;
private int inputMode;
private final List<ThreadContext> threadContextItems;
private boolean isTemp;
public DirectThread(final String threadId,
final String threadV2Id,
final List<User> users,
final List<User> leftUsers,
final List<Long> adminUserIds,
final List<DirectItem> items,
final long lastActivityAt,
final boolean muted,
final boolean isPin,
final boolean named,
final boolean canonical,
final boolean pending,
final boolean archived,
final boolean valuedRequest,
final String threadType,
final long viewerId,
final String threadTitle,
final String pendingScore,
final long folder,
final boolean vcMuted,
final boolean isGroup,
final boolean mentionsMuted,
final User inviter,
final boolean hasOlder,
final boolean hasNewer,
final Map<Long, DirectThreadLastSeenAt> lastSeenAt,
final String newestCursor,
final String oldestCursor,
final boolean isSpam,
final DirectItem lastPermanentItem,
final DirectThreadDirectStory directStory,
final boolean approvalRequiredForNewMembers,
final int inputMode,
final List<ThreadContext> threadContextItems) {
this.threadId = threadId;
this.threadV2Id = threadV2Id;
this.users = users;
this.leftUsers = leftUsers;
this.adminUserIds = adminUserIds;
this.items = items;
this.lastActivityAt = lastActivityAt;
this.muted = muted;
this.isPin = isPin;
this.named = named;
this.canonical = canonical;
this.pending = pending;
this.archived = archived;
this.valuedRequest = valuedRequest;
this.threadType = threadType;
this.viewerId = viewerId;
this.threadTitle = threadTitle;
this.pendingScore = pendingScore;
this.folder = folder;
this.vcMuted = vcMuted;
this.isGroup = isGroup;
this.mentionsMuted = mentionsMuted;
this.inviter = inviter;
this.hasOlder = hasOlder;
this.hasNewer = hasNewer;
this.lastSeenAt = lastSeenAt;
this.newestCursor = newestCursor;
this.oldestCursor = oldestCursor;
this.isSpam = isSpam;
this.lastPermanentItem = lastPermanentItem;
this.directStory = directStory;
this.approvalRequiredForNewMembers = approvalRequiredForNewMembers;
this.inputMode = inputMode;
this.threadContextItems = threadContextItems;
}
public String getThreadId() {
return threadId;
}
public String getThreadV2Id() {
return threadV2Id;
}
public List<User> getUsers() {
return users;
}
public void setUsers(final List<User> users) {
this.users = users;
}
public List<User> getLeftUsers() {
return leftUsers;
}
public void setLeftUsers(final List<User> leftUsers) {
this.leftUsers = leftUsers;
}
public List<Long> getAdminUserIds() {
return adminUserIds;
}
public void setAdminUserIds(final List<Long> adminUserIds) {
this.adminUserIds = adminUserIds;
}
public List<DirectItem> getItems() {
return items;
}
public void setItems(final List<DirectItem> items) {
this.items = items;
}
public long getLastActivityAt() {
return lastActivityAt;
}
public boolean isMuted() {
return muted;
}
public void setMuted(final boolean muted) {
this.muted = muted;
}
public boolean isPin() {
return isPin;
}
public boolean isNamed() {
return named;
}
public boolean isCanonical() {
return canonical;
}
public boolean isPending() {
return pending;
}
public void setPending(final boolean pending) {
this.pending = pending;
}
public boolean isArchived() {
return archived;
}
public boolean isValuedRequest() {
return valuedRequest;
}
public String getThreadType() {
return threadType;
}
public long getViewerId() {
return viewerId;
}
public String getThreadTitle() {
return threadTitle;
}
public String getPendingScore() {
return pendingScore;
}
public long getFolder() {
return folder;
}
public boolean isVcMuted() {
return vcMuted;
}
public boolean isGroup() {
return isGroup;
}
public boolean isMentionsMuted() {
return mentionsMuted;
}
public void setMentionsMuted(final boolean mentionsMuted) {
this.mentionsMuted = mentionsMuted;
}
public User getInviter() {
return inviter;
}
public boolean hasOlder() {
return hasOlder;
}
public boolean hasNewer() {
return hasNewer;
}
public Map<Long, DirectThreadLastSeenAt> getLastSeenAt() {
return lastSeenAt;
}
public void setLastSeenAt(final Map<Long, DirectThreadLastSeenAt> lastSeenAt) {
this.lastSeenAt = lastSeenAt;
}
public String getNewestCursor() {
return newestCursor;
}
public String getOldestCursor() {
return oldestCursor;
}
public boolean isSpam() {
return isSpam;
}
public DirectItem getLastPermanentItem() {
return lastPermanentItem;
}
public DirectThreadDirectStory getDirectStory() {
return directStory;
}
public boolean isApprovalRequiredForNewMembers() {
return approvalRequiredForNewMembers;
}
public void setApprovalRequiredForNewMembers(final boolean approvalRequiredForNewMembers) {
this.approvalRequiredForNewMembers = approvalRequiredForNewMembers;
}
public int getInputMode() {
return inputMode;
}
public void setInputMode(final int inputMode) {
this.inputMode = inputMode;
}
public List<ThreadContext> getThreadContextItems() {
return threadContextItems;
}
public boolean isTemp() {
return isTemp;
}
public void setTemp(final boolean isTemp) {
this.isTemp = isTemp;
}
@Nullable
public DirectItem getFirstDirectItem() {
DirectItem firstItem = null;
if (!items.isEmpty()) {
int position = 0;
while (firstItem == null && position < items.size()) {
firstItem = items.get(position);
position++;
}
}
return firstItem;
}
@NonNull
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final DirectThread that = (DirectThread) o;
return lastActivityAt == that.lastActivityAt &&
muted == that.muted &&
isPin == that.isPin &&
named == that.named &&
canonical == that.canonical &&
pending == that.pending &&
archived == that.archived &&
valuedRequest == that.valuedRequest &&
viewerId == that.viewerId &&
folder == that.folder &&
vcMuted == that.vcMuted &&
isGroup == that.isGroup &&
mentionsMuted == that.mentionsMuted &&
hasOlder == that.hasOlder &&
hasNewer == that.hasNewer &&
isSpam == that.isSpam &&
approvalRequiredForNewMembers == that.approvalRequiredForNewMembers &&
inputMode == that.inputMode &&
Objects.equals(threadId, that.threadId) &&
Objects.equals(threadV2Id, that.threadV2Id) &&
Objects.equals(users, that.users) &&
Objects.equals(leftUsers, that.leftUsers) &&
Objects.equals(adminUserIds, that.adminUserIds) &&
Objects.equals(items, that.items) &&
Objects.equals(threadType, that.threadType) &&
Objects.equals(threadTitle, that.threadTitle) &&
Objects.equals(pendingScore, that.pendingScore) &&
Objects.equals(inviter, that.inviter) &&
Objects.equals(lastSeenAt, that.lastSeenAt) &&
Objects.equals(newestCursor, that.newestCursor) &&
Objects.equals(oldestCursor, that.oldestCursor) &&
Objects.equals(lastPermanentItem, that.lastPermanentItem) &&
Objects.equals(directStory, that.directStory) &&
Objects.equals(threadContextItems, that.threadContextItems);
}
@Override
public int hashCode() {
return Objects
.hash(threadId, threadV2Id, users, leftUsers, adminUserIds, items, lastActivityAt, muted, isPin, named, canonical, pending, archived,
valuedRequest, threadType, viewerId, threadTitle, pendingScore, folder, vcMuted, isGroup, mentionsMuted, inviter, hasOlder,
hasNewer, lastSeenAt, newestCursor, oldestCursor, isSpam, lastPermanentItem, directStory, approvalRequiredForNewMembers,
inputMode, threadContextItems);
}
}

View File

@ -0,0 +1,49 @@
package awais.instagrabber.repositories.responses.directmessages
import awais.instagrabber.repositories.responses.User
import java.io.Serializable
data class DirectThread(
val threadId: String? = null,
val threadV2Id: String? = null,
var users: List<User>? = null,
var leftUsers: List<User>? = null,
var adminUserIds: List<Long>? = null,
var items: List<DirectItem>? = null,
val lastActivityAt: Long = 0,
var muted: Boolean = false,
val isPin: Boolean = false,
val named: Boolean = false,
val canonical: Boolean = false,
var pending: Boolean = false,
val archived: Boolean = false,
val valuedRequest: Boolean = false,
val threadType: String? = null,
val viewerId: Long = 0,
val threadTitle: String? = null,
val pendingScore: String? = null,
val folder: Long = 0,
val vcMuted: Boolean = false,
val isGroup: Boolean = false,
var mentionsMuted: Boolean = false,
val inviter: User? = null,
val hasOlder: Boolean = false,
val hasNewer: Boolean = false,
var lastSeenAt: Map<Long, DirectThreadLastSeenAt>? = null,
val newestCursor: String? = null,
val oldestCursor: String? = null,
val isSpam: Boolean = false,
val lastPermanentItem: DirectItem? = null,
val directStory: DirectThreadDirectStory? = null,
var approvalRequiredForNewMembers: Boolean = false,
var inputMode: Int = 0,
val threadContextItems: List<ThreadContext>? = null
) : Serializable, Cloneable {
var isTemp = false
val firstDirectItem: DirectItem?
get() = items?.firstNotNullOfOrNull { it }
@Throws(CloneNotSupportedException::class)
public override fun clone(): Any = super.clone()
}

View File

@ -1,57 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
import androidx.annotation.NonNull;
import java.util.List;
public class DirectThreadBroadcastResponse {
private final String action;
private final String statusCode;
private final DirectThreadBroadcastResponsePayload payload;
private final List<DirectThreadBroadcastResponseMessageMetadata> messageMetadata;
private final String status;
public DirectThreadBroadcastResponse(final String action,
final String statusCode,
final DirectThreadBroadcastResponsePayload payload,
final List<DirectThreadBroadcastResponseMessageMetadata> messageMetadata,
final String status) {
this.action = action;
this.statusCode = statusCode;
this.payload = payload;
this.messageMetadata = messageMetadata;
this.status = status;
}
public String getAction() {
return action;
}
public String getStatusCode() {
return statusCode;
}
public DirectThreadBroadcastResponsePayload getPayload() {
return payload;
}
public List<DirectThreadBroadcastResponseMessageMetadata> getMessageMetadata() {
return messageMetadata;
}
public String getStatus() {
return status;
}
@NonNull
@Override
public String toString() {
return "DirectThreadBroadcastResponse{" +
"action='" + action + '\'' +
", statusCode='" + statusCode + '\'' +
", payload=" + payload +
", messageMetadata=" + messageMetadata +
", status='" + status + '\'' +
'}';
}
}

View File

@ -0,0 +1,9 @@
package awais.instagrabber.repositories.responses.directmessages
data class DirectThreadBroadcastResponse(
val action: String? = null,
val statusCode: String? = null,
val payload: DirectThreadBroadcastResponsePayload? = null,
val messageMetadata: List<DirectThreadBroadcastResponseMessageMetadata>? = null,
val status: String? = null
)

View File

@ -1,55 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
import java.util.List;
public class DirectThreadBroadcastResponseMessageMetadata {
private final String clientContext;
private final String itemId;
private final long timestamp;
private final String threadId;
private final List<String> participantIds;
public DirectThreadBroadcastResponseMessageMetadata(final String clientContext,
final String itemId,
final long timestamp,
final String threadId,
final List<String> participantIds) {
this.clientContext = clientContext;
this.itemId = itemId;
this.timestamp = timestamp;
this.threadId = threadId;
this.participantIds = participantIds;
}
public String getClientContext() {
return clientContext;
}
public String getItemId() {
return itemId;
}
public long getTimestamp() {
return timestamp;
}
public String getThreadId() {
return threadId;
}
public List<String> getParticipantIds() {
return participantIds;
}
@Override
public String toString() {
return "DirectThreadBroadcastResponseMessageMetadata{" +
"clientContext='" + clientContext + '\'' +
", itemId='" + itemId + '\'' +
", timestamp=" + timestamp +
", threadId='" + threadId + '\'' +
", participantIds=" + participantIds +
'}';
}
}

View File

@ -0,0 +1,9 @@
package awais.instagrabber.repositories.responses.directmessages
data class DirectThreadBroadcastResponseMessageMetadata(
val clientContext: String? = null,
val itemId: String? = null,
val timestamp: Long = 0,
val threadId: String? = null,
val participantIds: List<String>? = null,
)

View File

@ -1,44 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
public class DirectThreadBroadcastResponsePayload {
private final String clientContext;
private final String itemId;
private final long timestamp;
private final String threadId;
public DirectThreadBroadcastResponsePayload(final String clientContext,
final String itemId,
final long timestamp,
final String threadId) {
this.clientContext = clientContext;
this.itemId = itemId;
this.timestamp = timestamp;
this.threadId = threadId;
}
public String getClientContext() {
return clientContext;
}
public String getItemId() {
return itemId;
}
public long getTimestamp() {
return timestamp;
}
public String getThreadId() {
return threadId;
}
@Override
public String toString() {
return "DirectThreadBroadcastResponsePayload{" +
"clientContext='" + clientContext + '\'' +
", itemId='" + itemId + '\'' +
", timestamp=" + timestamp +
", threadId='" + threadId + '\'' +
'}';
}
}

View File

@ -0,0 +1,8 @@
package awais.instagrabber.repositories.responses.directmessages
data class DirectThreadBroadcastResponsePayload(
val clientContext: String? = null,
val itemId: String? = null,
val timestamp: Long = 0,
val threadId: String? = null,
)

View File

@ -1,19 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
public class DirectThreadDetailsChangeResponse {
private final DirectThread thread;
private final String status;
public DirectThreadDetailsChangeResponse(final DirectThread thread, final String status) {
this.thread = thread;
this.status = status;
}
public DirectThread getThread() {
return thread;
}
public String getStatus() {
return status;
}
}

View File

@ -0,0 +1,6 @@
package awais.instagrabber.repositories.responses.directmessages
data class DirectThreadDetailsChangeResponse(
val thread: DirectThread? = null,
val status: String? = null
)

View File

@ -1,37 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
import java.io.Serializable;
import java.util.List;
import java.util.Objects;
public class DirectThreadDirectStory implements Serializable {
private final List<DirectItem> items;
private final int unseenCount;
public DirectThreadDirectStory(final List<DirectItem> items, final int unseenCount) {
this.items = items;
this.unseenCount = unseenCount;
}
public List<DirectItem> getItems() {
return items;
}
public int getUnseenCount() {
return unseenCount;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final DirectThreadDirectStory that = (DirectThreadDirectStory) o;
return unseenCount == that.unseenCount &&
Objects.equals(items, that.items);
}
@Override
public int hashCode() {
return Objects.hash(items, unseenCount);
}
}

View File

@ -0,0 +1,8 @@
package awais.instagrabber.repositories.responses.directmessages
import java.io.Serializable
data class DirectThreadDirectStory(
val items: List<DirectItem>? = null,
val unseenCount: Int = 0,
) : Serializable

View File

@ -1,19 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
public class DirectThreadFeedResponse {
private final DirectThread thread;
private final String status;
public DirectThreadFeedResponse(final DirectThread thread, final String status) {
this.thread = thread;
this.status = status;
}
public DirectThread getThread() {
return thread;
}
public String getStatus() {
return status;
}
}

View File

@ -0,0 +1,6 @@
package awais.instagrabber.repositories.responses.directmessages
data class DirectThreadFeedResponse(
val thread: DirectThread? = null,
val status: String? = null,
)

View File

@ -1,36 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
import java.io.Serializable;
import java.util.Objects;
public class DirectThreadLastSeenAt implements Serializable {
private final String timestamp;
private final String itemId;
public DirectThreadLastSeenAt(final String timestamp, final String itemId) {
this.timestamp = timestamp;
this.itemId = itemId;
}
public String getTimestamp() {
return timestamp;
}
public String getItemId() {
return itemId;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final DirectThreadLastSeenAt that = (DirectThreadLastSeenAt) o;
return Objects.equals(timestamp, that.timestamp) &&
Objects.equals(itemId, that.itemId);
}
@Override
public int hashCode() {
return Objects.hash(timestamp, itemId);
}
}

View File

@ -0,0 +1,8 @@
package awais.instagrabber.repositories.responses.directmessages
import java.io.Serializable
data class DirectThreadLastSeenAt(
val timestamp: String? = null,
val itemId: String? = null,
) : Serializable

View File

@ -1,70 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
import androidx.annotation.NonNull;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import awais.instagrabber.repositories.responses.User;
public class DirectThreadParticipantRequestsResponse implements Serializable, Cloneable {
private List<User> users;
private final Map<Long, String> requesterUsernames;
private final String cursor;
private final int totalThreadParticipants;
private int totalParticipantRequests;
private final String status;
public DirectThreadParticipantRequestsResponse(final List<User> users,
final Map<Long, String> requesterUsernames,
final String cursor,
final int totalThreadParticipants,
final int totalParticipantRequests,
final String status) {
this.users = users;
this.requesterUsernames = requesterUsernames;
this.cursor = cursor;
this.totalThreadParticipants = totalThreadParticipants;
this.totalParticipantRequests = totalParticipantRequests;
this.status = status;
}
public List<User> getUsers() {
return users;
}
public void setUsers(final List<User> users) {
this.users = users;
}
public Map<Long, String> getRequesterUsernames() {
return requesterUsernames;
}
public String getCursor() {
return cursor;
}
public int getTotalThreadParticipants() {
return totalThreadParticipants;
}
public int getTotalParticipantRequests() {
return totalParticipantRequests;
}
public void setTotalParticipantRequests(final int totalParticipantRequests) {
this.totalParticipantRequests = totalParticipantRequests;
}
public String getStatus() {
return status;
}
@NonNull
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}

View File

@ -0,0 +1,16 @@
package awais.instagrabber.repositories.responses.directmessages
import awais.instagrabber.repositories.responses.User
import java.io.Serializable
data class DirectThreadParticipantRequestsResponse(
var users: List<User>? = null,
val requesterUsernames: Map<Long, String>? = null,
val cursor: String? = null,
val totalThreadParticipants: Int = 0,
var totalParticipantRequests: Int = 0,
val status: String? = null,
) : Serializable, Cloneable {
@Throws(CloneNotSupportedException::class)
public override fun clone(): Any = super.clone()
}

View File

@ -1,46 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
import java.io.Serializable;
import java.util.Objects;
import awais.instagrabber.repositories.responses.User;
public class RankedRecipient implements Serializable {
private final User user;
private final DirectThread thread;
public RankedRecipient(final User user, final DirectThread thread) {
this.user = user;
this.thread = thread;
}
public User getUser() {
return user;
}
public DirectThread getThread() {
return thread;
}
public static RankedRecipient of(final User user) {
return new RankedRecipient(user, null);
}
public static RankedRecipient of(final DirectThread thread) {
return new RankedRecipient(null, thread);
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final RankedRecipient that = (RankedRecipient) o;
return Objects.equals(user, that.user) &&
Objects.equals(thread, that.thread);
}
@Override
public int hashCode() {
return Objects.hash(user, thread);
}
}

View File

@ -0,0 +1,21 @@
package awais.instagrabber.repositories.responses.directmessages
import awais.instagrabber.repositories.responses.User
import java.io.Serializable
data class RankedRecipient(
val user: User? = null,
val thread: DirectThread? = null,
) : Serializable {
companion object {
@JvmStatic
fun of(user: User): RankedRecipient {
return RankedRecipient(user = user)
}
@JvmStatic
fun of(thread: DirectThread): RankedRecipient {
return RankedRecipient(thread = thread)
}
}
}

View File

@ -1,50 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
import java.util.List;
public class RankedRecipientsResponse {
private final List<RankedRecipient> rankedRecipients;
private final long expires;
private final boolean filtered;
private final String requestId;
private final String rankToken;
private final String status;
public RankedRecipientsResponse(final List<RankedRecipient> rankedRecipients,
final long expires,
final boolean filtered,
final String requestId,
final String rankToken,
final String status) {
this.rankedRecipients = rankedRecipients;
this.expires = expires;
this.filtered = filtered;
this.requestId = requestId;
this.rankToken = rankToken;
this.status = status;
}
public List<RankedRecipient> getRankedRecipients() {
return rankedRecipients;
}
public long getExpires() {
return expires;
}
public boolean isFiltered() {
return filtered;
}
public String getRequestId() {
return requestId;
}
public String getRankToken() {
return rankToken;
}
public String getStatus() {
return status;
}
}

View File

@ -0,0 +1,10 @@
package awais.instagrabber.repositories.responses.directmessages
data class RankedRecipientsResponse(
val rankedRecipients: List<RankedRecipient>? = null,
val expires: Long = 0,
val filtered: Boolean = false,
val requestId: String? = null,
val rankToken: String? = null,
val status: String? = null,
)

View File

@ -1,69 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
import com.google.gson.annotations.SerializedName;
import java.io.Serializable;
import java.util.Objects;
public final class RavenExpiringMediaActionSummary implements Serializable {
private final ActionType type;
private final long timestamp;
private final int count;
public RavenExpiringMediaActionSummary(final long timestamp, final int count, final ActionType type) {
this.timestamp = timestamp;
this.count = count;
this.type = type;
}
public long getTimestamp() {
return timestamp;
}
public int getCount() {
return count;
}
public ActionType getType() {
return type;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final RavenExpiringMediaActionSummary that = (RavenExpiringMediaActionSummary) o;
return timestamp == that.timestamp &&
count == that.count &&
type == that.type;
}
@Override
public int hashCode() {
return Objects.hash(type, timestamp, count);
}
// thanks to http://github.com/warifp/InstagramAutoPostImageUrl/blob/master/vendor/mgp25/instagram-php/src/Response/Model/ActionBadge.php
public enum ActionType {
@SerializedName("raven_delivered")
DELIVERED,
@SerializedName("raven_sent")
SENT,
@SerializedName("raven_opened")
OPENED,
@SerializedName("raven_screenshot")
SCREENSHOT,
@SerializedName("raven_replayed")
REPLAYED,
@SerializedName("raven_cannot_deliver")
CANNOT_DELIVER,
@SerializedName("raven_sending")
SENDING,
@SerializedName("raven_blocked")
BLOCKED,
@SerializedName("raven_unknown")
UNKNOWN,
@SerializedName("raven_suggested")
SUGGESTED,
}
}

View File

@ -0,0 +1,43 @@
package awais.instagrabber.repositories.responses.directmessages
import com.google.gson.annotations.SerializedName
import java.io.Serializable
data class RavenExpiringMediaActionSummary(
val timestamp: Long = 0,
val count: Int = 0,
val type: ActionType? = null,
) : Serializable
// thanks to http://github.com/warifp/InstagramAutoPostImageUrl/blob/master/vendor/mgp25/instagram-php/src/Response/Model/ActionBadge.php
enum class ActionType {
@SerializedName("raven_delivered")
DELIVERED,
@SerializedName("raven_sent")
SENT,
@SerializedName("raven_opened")
OPENED,
@SerializedName("raven_screenshot")
SCREENSHOT,
@SerializedName("raven_replayed")
REPLAYED,
@SerializedName("raven_cannot_deliver")
CANNOT_DELIVER,
@SerializedName("raven_sending")
SENDING,
@SerializedName("raven_blocked")
BLOCKED,
@SerializedName("raven_unknown")
UNKNOWN,
@SerializedName("raven_suggested")
SUGGESTED,
}

View File

@ -0,0 +1,10 @@
package awais.instagrabber.repositories.responses.directmessages
import java.io.Serializable
data class TextRange(
val start: Int = 0,
val end: Int = 0,
val color: String? = null,
val intent: String? = null,
) : Serializable

View File

@ -1,36 +0,0 @@
package awais.instagrabber.repositories.responses.directmessages;
import java.io.Serializable;
import java.util.Objects;
public class ThreadContext implements Serializable {
private final int type;
private final String text;
public ThreadContext(final int type, final String text) {
this.type = type;
this.text = text;
}
public int getType() {
return type;
}
public String getText() {
return text;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final ThreadContext that = (ThreadContext) o;
return type == that.type &&
Objects.equals(text, that.text);
}
@Override
public int hashCode() {
return Objects.hash(type, text);
}
}

View File

@ -0,0 +1,8 @@
package awais.instagrabber.repositories.responses.directmessages
import java.io.Serializable
data class ThreadContext(
val type: Int = 0,
val text: String? = null,
) : Serializable

View File

@ -30,7 +30,7 @@ public class CaptionDeserializer implements JsonDeserializer<Caption> {
pkString = pkString.substring(0, pkString.indexOf("_")); pkString = pkString.substring(0, pkString.indexOf("_"));
} }
try { try {
caption.setPk(Long.parseLong(pkString)); caption.setPk(pkString);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
Log.e(TAG, "deserialize: ", e); Log.e(TAG, "deserialize: ", e);
} }

View File

@ -91,7 +91,7 @@ public class DMSyncService extends LifecycleService {
return; return;
} }
for (final DirectThread thread : threads) { for (final DirectThread thread : threads) {
if (thread.isMuted()) continue; if (thread.getMuted()) continue;
final boolean read = DMUtils.isRead(thread); final boolean read = DMUtils.isRead(thread);
if (read) continue; if (read) continue;
final List<DirectItem> unreadMessages = getUnreadMessages(thread); final List<DirectItem> unreadMessages = getUnreadMessages(thread);

View File

@ -17,7 +17,6 @@ import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -243,13 +242,15 @@ public final class BitmapUtils {
* @return dimensions of the image * @return dimensions of the image
*/ */
public static Pair<Integer, Integer> decodeDimensions(@NonNull final ContentResolver contentResolver, public static Pair<Integer, Integer> decodeDimensions(@NonNull final ContentResolver contentResolver,
@NonNull final Uri uri) throws FileNotFoundException { @NonNull final Uri uri) throws IOException {
BitmapFactory.Options options = new BitmapFactory.Options(); BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true; options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(contentResolver.openInputStream(uri), null, options); try (final InputStream stream = contentResolver.openInputStream(uri)) {
return (options.outWidth == -1 || options.outHeight == -1) BitmapFactory.decodeStream(stream, null, options);
? null return (options.outWidth == -1 || options.outHeight == -1)
: new Pair<>(options.outWidth, options.outHeight); ? null
: new Pair<>(options.outWidth, options.outHeight);
}
} }
public static File convertToJpegAndSaveToFile(@NonNull final Bitmap bitmap, @Nullable final File file) throws IOException { public static File convertToJpegAndSaveToFile(@NonNull final Bitmap bitmap, @Nullable final File file) throws IOException {

View File

@ -15,6 +15,7 @@ import awais.instagrabber.models.enums.DirectItemType;
import awais.instagrabber.models.enums.MediaItemType; import awais.instagrabber.models.enums.MediaItemType;
import awais.instagrabber.repositories.responses.Media; import awais.instagrabber.repositories.responses.Media;
import awais.instagrabber.repositories.responses.User; import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.repositories.responses.directmessages.ActionType;
import awais.instagrabber.repositories.responses.directmessages.DirectItem; import awais.instagrabber.repositories.responses.directmessages.DirectItem;
import awais.instagrabber.repositories.responses.directmessages.DirectItemAnimatedMedia; import awais.instagrabber.repositories.responses.directmessages.DirectItemAnimatedMedia;
import awais.instagrabber.repositories.responses.directmessages.DirectItemReelShare; import awais.instagrabber.repositories.responses.directmessages.DirectItemReelShare;
@ -267,7 +268,7 @@ public final class DMUtils {
final DirectItemVisualMedia visualMedia = item.getVisualMedia(); final DirectItemVisualMedia visualMedia = item.getVisualMedia();
final RavenExpiringMediaActionSummary summary = visualMedia.getExpiringMediaActionSummary(); final RavenExpiringMediaActionSummary summary = visualMedia.getExpiringMediaActionSummary();
if (summary != null) { if (summary != null) {
final RavenExpiringMediaActionSummary.ActionType expiringMediaType = summary.getType(); final ActionType expiringMediaType = summary.getType();
int textRes = 0; int textRes = 0;
switch (expiringMediaType) { switch (expiringMediaType) {
case DELIVERED: case DELIVERED:

View File

@ -30,27 +30,24 @@ private fun createPhotoRuploadParams(options: UploadPhotoOptions): Map<String, S
).toMap() ).toMap()
} }
private fun createVideoRuploadParams(options: UploadVideoOptions): Map<String, String> { private fun createVideoRuploadParams(options: UploadVideoOptions): Map<String, String> = listOfNotNull(
val retryContextString = retryContextString "retry_context" to retryContextString,
return listOfNotNull( "media_type" to "2",
"retry_context" to retryContextString, "xsharing_user_ids" to "[]",
"media_type" to "2", "upload_id" to options.uploadId,
"xsharing_user_ids" to "[]", "upload_media_width" to options.width.toString(),
"upload_id" to options.uploadId, "upload_media_height" to options.height.toString(),
"upload_media_width" to options.width.toString(), "upload_media_duration_ms" to options.duration.toString(),
"upload_media_height" to options.height.toString(), if (options.isSideCar) "is_sidecar" to "1" else null,
"upload_media_duration_ms" to options.duration.toString(), if (options.forAlbum) "for_album" to "1" else null,
if (options.isSideCar) "is_sidecar" to "1" else null, if (options.isDirect) "direct_v2" to "1" else null,
if (options.isForAlbum) "for_album" to "1" else null, *(if (options.isForDirectStory) arrayOf(
if (options.isDirect) "direct_v2" to "1" else null, "for_direct_story" to "1",
*(if (options.isForDirectStory) arrayOf( "content_tags" to ""
"for_direct_story" to "1", ) else emptyArray()),
"content_tags" to "" if (options.isIgtvVideo) "is_igtv_video" to "1" else null,
) else emptyArray()), if (options.isDirectVoice) "is_direct_voice" to "1" else null,
if (options.isIgtvVideo) "is_igtv_video" to "1" else null, ).toMap()
if (options.isDirectVoice) "is_direct_voice" to "1" else null,
).toMap()
}
val retryContextString: String val retryContextString: String
get() { get() {
@ -86,7 +83,7 @@ fun createUploadDmVideoOptions(
duration, duration,
width, width,
height, height,
true, isDirect = true,
mediaType = MediaItemType.MEDIA_TYPE_VIDEO, mediaType = MediaItemType.MEDIA_TYPE_VIDEO,
) )
} }

View File

@ -110,6 +110,7 @@ public final class MediaUploader {
@NonNull final OnMediaUploadCompleteListener listener) { @NonNull final OnMediaUploadCompleteListener listener) {
try { try {
final OkHttpClient client = new OkHttpClient.Builder() final OkHttpClient client = new OkHttpClient.Builder()
// .addInterceptor(new LoggingInterceptor())
.addInterceptor(new AddCookiesInterceptor()) .addInterceptor(new AddCookiesInterceptor())
.followRedirects(false) .followRedirects(false)
.followSslRedirects(false) .followSslRedirects(false)

View File

@ -14,7 +14,6 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import awais.instagrabber.BuildConfig;
import awais.instagrabber.models.StoryModel; import awais.instagrabber.models.StoryModel;
import awais.instagrabber.models.enums.MediaItemType; import awais.instagrabber.models.enums.MediaItemType;
import awais.instagrabber.models.stickers.PollModel; import awais.instagrabber.models.stickers.PollModel;
@ -30,7 +29,6 @@ import awais.instagrabber.repositories.responses.Media;
import awais.instagrabber.repositories.responses.MediaCandidate; import awais.instagrabber.repositories.responses.MediaCandidate;
import awais.instagrabber.repositories.responses.User; import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.repositories.responses.VideoVersion; import awais.instagrabber.repositories.responses.VideoVersion;
//import awaisomereport.LogCollector;
public final class ResponseBodyUtils { public final class ResponseBodyUtils {
private static final String TAG = "ResponseBodyUtils"; private static final String TAG = "ResponseBodyUtils";
@ -75,11 +73,7 @@ public final class ResponseBodyUtils {
if (lastIndexMain >= 0) return sources[lastIndexMain]; if (lastIndexMain >= 0) return sources[lastIndexMain];
else if (lastIndexBase >= 0) return sources[lastIndexBase]; else if (lastIndexBase >= 0) return sources[lastIndexBase];
} catch (final Exception e) { } catch (final Exception e) {
// if (Utils.logCollector != null) Log.e(TAG, "", e);
// Utils.logCollector.appendException(e, LogCollector.LogFile.UTILS, "getHighQualityPost",
// new Pair<>("resourcesNull", resources == null),
// new Pair<>("isVideo", isVideo));
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
} }
return null; return null;
} }
@ -93,587 +87,11 @@ public final class ResponseBodyUtils {
src = getHighQualityPost(resources.getJSONObject("image_versions2").getJSONArray("candidates"), false, true, false); src = getHighQualityPost(resources.getJSONObject("image_versions2").getJSONArray("candidates"), false, true, false);
if (src == null) return resources.getString("display_url"); if (src == null) return resources.getString("display_url");
} catch (final Exception e) { } catch (final Exception e) {
// if (Utils.logCollector != null) Log.e(TAG, "", e);
// Utils.logCollector.appendException(e, LogCollector.LogFile.UTILS, "getHighQualityImage",
// new Pair<>("resourcesNull", resources == null));
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
} }
return src; return src;
} }
// public static String getLowQualityImage(final JSONObject resources) {
// String src = null;
// try {
// src = getHighQualityPost(resources.getJSONObject("image_versions2").getJSONArray("candidates"), false, true, true);
// } catch (final Exception e) {
// if (Utils.logCollector != null)
// Utils.logCollector.appendException(e, LogCollector.LogFile.UTILS, "getLowQualityImage",
// new Pair<>("resourcesNull", resources == null));
// if (BuildConfig.DEBUG) Log.e(TAG, "Error in getLowQualityImage", e);
// }
// return src;
// }
// public static ThumbnailDetails getItemThumbnail(@NonNull final JSONArray jsonArray) {
// final ThumbnailDetails thumbnailDetails = new ThumbnailDetails();
// final int imageResLen = jsonArray.length();
// for (int i = 0; i < imageResLen; ++i) {
// final JSONObject imageResource = jsonArray.optJSONObject(i);
// try {
// // final float ratio = (float) height / width;
// // if (ratio >= 0.95f && ratio <= 1.0f) {
// thumbnailDetails.height = imageResource.getInt("height");
// thumbnailDetails.width = imageResource.getInt("width");
// thumbnailDetails.url = imageResource.getString("url");
// break;
// // }
// } catch (final Exception e) {
// if (Utils.logCollector != null)
// Utils.logCollector.appendException(e, LogCollector.LogFile.UTILS, "getItemThumbnail");
// if (BuildConfig.DEBUG) Log.e(TAG, "", e);
// }
// }
// // if (TextUtils.isEmpty(thumbnail)) thumbnail = jsonArray.optJSONObject(0).optString("url");
// return thumbnailDetails;
// }
// public static class ThumbnailDetails {
// int width;
// int height;
// public String url;
// }
// @Nullable
// public static ThumbnailDetails getThumbnailUrl(@NonNull final JSONObject mediaObj, final MediaItemType mediaType) throws Exception {
// ThumbnailDetails thumbnail = null;
// if (mediaType == MediaItemType.MEDIA_TYPE_IMAGE || mediaType == MediaItemType.MEDIA_TYPE_VIDEO) {
// final JSONObject imageVersions = mediaObj.optJSONObject("image_versions2");
// if (imageVersions != null)
// thumbnail = getItemThumbnail(imageVersions.getJSONArray("candidates"));
//
// } else if (mediaType == MediaItemType.MEDIA_TYPE_SLIDER) {
// final JSONArray carouselMedia = mediaObj.optJSONArray("carousel_media");
// if (carouselMedia != null)
// thumbnail = getItemThumbnail(carouselMedia.getJSONObject(0)
// .getJSONObject("image_versions2")
// .getJSONArray("candidates"));
// }
// return thumbnail;
// }
// public static String getVideoUrl(@NonNull final JSONObject mediaObj) {
// String url = null;
// final JSONArray videoVersions = mediaObj.optJSONArray("video_versions");
// if (videoVersions == null) {
// return null;
// }
// int largestWidth = 0;
// for (int i = 0; i < videoVersions.length(); i++) {
// final JSONObject videoVersionJson = videoVersions.optJSONObject(i);
// if (videoVersionJson == null) {
// continue;
// }
// final int width = videoVersionJson.optInt("width");
// if (largestWidth == 0 || width > largestWidth) {
// largestWidth = width;
// url = videoVersionJson.optString("url");
// }
// }
// return url;
// }
// @Nullable
// public static MediaItemType getMediaItemType(final int mediaType) {
// if (mediaType == 1) return MediaItemType.MEDIA_TYPE_IMAGE;
// if (mediaType == 2) return MediaItemType.MEDIA_TYPE_VIDEO;
// if (mediaType == 8) return MediaItemType.MEDIA_TYPE_SLIDER;
// if (mediaType == 11) return MediaItemType.MEDIA_TYPE_VOICE;
// return null;
// }
// public static DirectItemModel.DirectItemMediaModel getDirectMediaModel(final JSONObject mediaObj) throws Exception {
// final DirectItemModel.DirectItemMediaModel mediaModel;
// if (mediaObj == null) mediaModel = null;
// else {
// final JSONObject userObj = mediaObj.optJSONObject("user");
//
// ProfileModel user = null;
// if (userObj != null) {
// user = new ProfileModel(
// userObj.getBoolean("is_private"),
// false,
// userObj.optBoolean("is_verified"),
// String.valueOf(userObj.get("pk")),
// userObj.getString("username"),
// userObj.getString("full_name"),
// null, null,
// userObj.getString("profile_pic_url"),
// null, 0, 0, 0, false, false, false, false, false);
// }
//
// final MediaItemType mediaType = getMediaItemType(mediaObj.optInt("media_type", -1));
//
// String id = mediaObj.optString("id");
// if (TextUtils.isEmpty(id)) id = null;
//
// final ThumbnailDetails thumbnailDetails = getThumbnailUrl(mediaObj, mediaType);
// mediaModel = new DirectItemModel.DirectItemMediaModel(
// mediaType,
// mediaObj.optLong("expiring_at"),
// mediaObj.optLong("pk"),
// id,
// thumbnailDetails != null ? thumbnailDetails.url : null,
// mediaType == MediaItemType.MEDIA_TYPE_VIDEO ? getVideoUrl(mediaObj) : null,
// user,
// mediaObj.optString("code"),
// thumbnailDetails != null ? thumbnailDetails.height : 0,
// thumbnailDetails != null ? thumbnailDetails.width : 0);
// }
// return mediaModel;
// }
//
// private static DirectItemType getDirectItemType(final String itemType) {
// if ("placeholder".equals(itemType)) return DirectItemType.PLACEHOLDER;
// if ("media".equals(itemType)) return DirectItemType.MEDIA;
// if ("link".equals(itemType)) return DirectItemType.LINK;
// if ("like".equals(itemType)) return DirectItemType.LIKE;
// if ("reel_share".equals(itemType)) return DirectItemType.REEL_SHARE;
// if ("media_share".equals(itemType)) return DirectItemType.MEDIA_SHARE;
// if ("action_log".equals(itemType)) return DirectItemType.ACTION_LOG;
// if ("raven_media".equals(itemType)) return DirectItemType.RAVEN_MEDIA;
// if ("profile".equals(itemType)) return DirectItemType.PROFILE;
// if ("video_call_event".equals(itemType)) return DirectItemType.VIDEO_CALL_EVENT;
// if ("animated_media".equals(itemType)) return DirectItemType.ANIMATED_MEDIA;
// if ("voice_media".equals(itemType)) return DirectItemType.VOICE_MEDIA;
// if ("story_share".equals(itemType)) return DirectItemType.STORY_SHARE;
// if ("clip".equals(itemType)) return DirectItemType.CLIP;
// if ("felix_share".equals(itemType)) return DirectItemType.FELIX_SHARE;
// return DirectItemType.TEXT;
// }
//
// @NonNull
// public static InboxThreadModel createInboxThreadModel(@NonNull final JSONObject data, final boolean inThreadView) throws Exception {
// final InboxReadState readState = data.getInt("read_state") == 0 ? InboxReadState.STATE_READ : InboxReadState.STATE_UNREAD;
// final String threadType = data.getString("thread_type"); // they're all "private", group is identified by boolean "is_group"
//
// final String threadId = data.getString("thread_id");
// final String threadV2Id = data.getString("thread_v2_id");
// final String threadTitle = data.getString("thread_title");
//
// final String threadNewestCursor = data.optString("newest_cursor");
// final String threadOldestCursor = data.optString("oldest_cursor");
// final String threadNextCursor = data.has("next_cursor") ? data.getString("next_cursor") : null;
// final String threadPrevCursor = data.has("prev_cursor") ? data.getString("prev_cursor") : null;
//
// final boolean threadHasOlder = data.getBoolean("has_older");
// final long unreadCount = data.optLong("read_state", 0);
//
// final long lastActivityAt = data.optLong("last_activity_at");
// final boolean named = data.optBoolean("named");
// final boolean muted = data.optBoolean("muted");
// final boolean isPin = data.optBoolean("is_pin");
// final boolean isSpam = data.optBoolean("is_spam");
// final boolean isGroup = data.optBoolean("is_group");
// final boolean pending = data.optBoolean("pending");
// final boolean archived = data.optBoolean("archived");
// final boolean canonical = data.optBoolean("canonical");
//
// final JSONArray users = data.getJSONArray("users");
// final int usersLen = users.length();
// final JSONArray leftusers = data.optJSONArray("left_users");
// final int leftusersLen = leftusers == null ? 0 : leftusers.length();
// final JSONArray admins = data.getJSONArray("admin_user_ids");
// final int adminsLen = admins.length();
//
// final ProfileModel[] userModels = new ProfileModel[usersLen];
// for (int j = 0; j < usersLen; ++j) {
// final JSONObject userObject = users.getJSONObject(j);
// userModels[j] = new ProfileModel(userObject.optBoolean("is_private"),
// false,
// userObject.optBoolean("is_verified"),
// String.valueOf(userObject.get("pk")),
// userObject.optString("username"), // optional cuz fb users
// userObject.getString("full_name"),
// null, null,
// userObject.getString("profile_pic_url"),
// null, 0, 0, 0, false, false, false, false, false);
// }
//
// final ProfileModel[] leftuserModels = new ProfileModel[leftusersLen];
// for (int j = 0; j < leftusersLen; ++j) {
// final JSONObject userObject = leftusers.getJSONObject(j);
// leftuserModels[j] = new ProfileModel(userObject.getBoolean("is_private"),
// false,
// userObject.optBoolean("is_verified"),
// String.valueOf(userObject.get("pk")),
// userObject.getString("username"),
// userObject.getString("full_name"),
// null, null,
// userObject.getString("profile_pic_url"),
// null, 0, 0, 0, false, false, false, false, false);
// }
//
// final Long[] adminIDs = new Long[adminsLen];
// for (int j = 0; j < adminsLen; ++j) {
// adminIDs[j] = admins.getLong(j);
// }
//
// final JSONArray items = data.getJSONArray("items");
// final int itemsLen = items.length();
//
// final ArrayList<DirectItemModel> itemModels = new ArrayList<>(itemsLen);
// for (int i = 0; i < itemsLen; ++i) {
// final JSONObject itemObject = items.getJSONObject(i);
//
// CharSequence text = null;
// ProfileModel profileModel = null;
// DirectItemModel.DirectItemLinkModel linkModel = null;
// DirectItemModel.DirectItemMediaModel directMedia = null;
// DirectItemModel.DirectItemReelShareModel reelShareModel = null;
// DirectItemModel.DirectItemActionLogModel actionLogModel = null;
// DirectItemModel.DirectItemAnimatedMediaModel animatedMediaModel = null;
// DirectItemModel.DirectItemVoiceMediaModel voiceMediaModel = null;
// DirectItemModel.DirectItemRavenMediaModel ravenMediaModel = null;
// DirectItemModel.DirectItemVideoCallEventModel videoCallEventModel = null;
//
// final DirectItemType itemType = getDirectItemType(itemObject.getString("item_type"));
// switch (itemType) {
// case ANIMATED_MEDIA: {
// final JSONObject animatedMedia = itemObject.getJSONObject("animated_media");
// final JSONObject stickerImage = animatedMedia.getJSONObject("images").getJSONObject("fixed_height");
//
// animatedMediaModel = new DirectItemModel.DirectItemAnimatedMediaModel(
// animatedMedia.getBoolean("is_random"),
// animatedMedia.getBoolean("is_sticker"),
// animatedMedia.getString("id"),
// stickerImage.getString("url"),
// stickerImage.optString("webp"),
// stickerImage.optString("mp4"),
// stickerImage.getInt("height"),
// stickerImage.getInt("width"));
// }
// break;
//
// case VOICE_MEDIA: {
// final JSONObject voiceMedia = itemObject.getJSONObject("voice_media").getJSONObject("media");
// final JSONObject audio = voiceMedia.getJSONObject("audio");
//
// int[] waveformData = null;
// final JSONArray waveformDataArray = audio.optJSONArray("waveform_data");
// if (waveformDataArray != null) {
// final int waveformDataLen = waveformDataArray.length();
// waveformData = new int[waveformDataLen];
// // 0.011775206
// for (int j = 0; j < waveformDataLen; ++j) {
// waveformData[j] = (int) (waveformDataArray.optDouble(j) * 10);
// }
// }
//
// voiceMediaModel = new DirectItemModel.DirectItemVoiceMediaModel(
// voiceMedia.getString("id"),
// audio.getString("audio_src"),
// audio.getLong("duration"),
// waveformData);
// }
// break;
//
// case LINK: {
// final JSONObject linkObj = itemObject.getJSONObject("link");
//
// DirectItemModel.DirectItemLinkContext itemLinkContext = null;
// final JSONObject linkContext = linkObj.optJSONObject("link_context");
// if (linkContext != null) {
// itemLinkContext = new DirectItemModel.DirectItemLinkContext(
// linkContext.getString("link_url"),
// linkContext.optString("link_title"),
// linkContext.optString("link_summary"),
// linkContext.optString("link_image_url")
// );
// }
//
// linkModel = new DirectItemModel.DirectItemLinkModel(
// linkObj.getString("text"),
// linkObj.getString("client_context"),
// linkObj.optString("mutation_token"),
// itemLinkContext);
// }
// break;
//
// case REEL_SHARE: {
// final JSONObject reelShare = itemObject.getJSONObject("reel_share");
// reelShareModel = new DirectItemModel.DirectItemReelShareModel(
// reelShare.optBoolean("is_reel_persisted"),
// reelShare.getLong("reel_owner_id"),
// reelShare.getJSONObject("media").getJSONObject("user").getString("username"),
// reelShare.getString("text"),
// reelShare.getString("type"),
// reelShare.getString("reel_type"),
// reelShare.optString("reel_name"),
// reelShare.optString("reel_id"),
// getDirectMediaModel(reelShare.optJSONObject("media")));
// }
// break;
//
// case RAVEN_MEDIA: {
// final JSONObject visualMedia = itemObject.getJSONObject("visual_media");
//
// final JSONArray seenUserIdsArray = visualMedia.getJSONArray("seen_user_ids");
// final int seenUsersLen = seenUserIdsArray.length();
// final String[] seenUserIds = new String[seenUsersLen];
// for (int j = 0; j < seenUsersLen; j++)
// seenUserIds[j] = seenUserIdsArray.getString(j);
//
// DirectItemModel.RavenExpiringMediaActionSummaryModel expiringSummaryModel = null;
// final JSONObject actionSummary = visualMedia.optJSONObject("expiring_media_action_summary");
// if (actionSummary != null)
// expiringSummaryModel = new DirectItemModel.RavenExpiringMediaActionSummaryModel(
// actionSummary.getLong("timestamp"), actionSummary.getInt("count"),
// getExpiringMediaType(actionSummary.getString("type")));
//
// final RavenMediaViewType viewType;
// final String viewMode = visualMedia.getString("view_mode");
// switch (viewMode) {
// case "replayable":
// viewType = RavenMediaViewType.REPLAYABLE;
// break;
// case "permanent":
// viewType = RavenMediaViewType.PERMANENT;
// break;
// case "once":
// default:
// viewType = RavenMediaViewType.ONCE;
// }
//
// ravenMediaModel = new DirectItemModel.DirectItemRavenMediaModel(
// visualMedia.optLong(viewType == RavenMediaViewType.PERMANENT ? "url_expire_at_secs" : "replay_expiring_at_us"),
// visualMedia.optInt("playback_duration_secs"),
// visualMedia.getInt("seen_count"),
// seenUserIds,
// viewType,
// getDirectMediaModel(visualMedia.optJSONObject("media")),
// expiringSummaryModel);
//
// }
// break;
//
// case VIDEO_CALL_EVENT: {
// final JSONObject videoCallEvent = itemObject.getJSONObject("video_call_event");
// videoCallEventModel = new DirectItemModel.DirectItemVideoCallEventModel(videoCallEvent.optLong("vc_id"),
// videoCallEvent.optBoolean("thread_has_audio_only_call"),
// videoCallEvent.getString("action"),
// videoCallEvent.getString("description"));
// }
// break;
//
// case PROFILE: {
// final JSONObject profile = itemObject.getJSONObject("profile");
// profileModel = new ProfileModel(profile.getBoolean("is_private"),
// false,
// profile.getBoolean("is_verified"),
// Long.toString(profile.getLong("pk")),
// profile.getString("username"),
// profile.getString("full_name"),
// null, null,
// profile.getString("profile_pic_url"),
// null, 0, 0, 0, false, false, false, false, false);
// }
// break;
//
// case PLACEHOLDER:
// final JSONObject placeholder = itemObject.getJSONObject("placeholder");
// text = placeholder.getString("title") + "<br><small>" + placeholder.getString("message") + "</small>";
// break;
//
// case ACTION_LOG:
// if (inThreadView && itemObject.optInt("hide_in_thread", 0) != 0)
// continue;
// final JSONObject actionLog = itemObject.getJSONObject("action_log");
// String desc = actionLog.getString("description");
// JSONArray bold = actionLog.getJSONArray("bold");
// for (int q = 0; q < bold.length(); ++q) {
// JSONObject boldItem = bold.getJSONObject(q);
// desc = desc.substring(0, boldItem.getInt("start") + q * 7) + "<b>"
// + desc.substring(boldItem.getInt("start") + q * 7, boldItem.getInt("end") + q * 7)
// + "</b>" + desc.substring(boldItem.getInt("end") + q * 7);
// }
// actionLogModel = new DirectItemModel.DirectItemActionLogModel(desc);
// break;
//
// case MEDIA_SHARE:
// directMedia = getDirectMediaModel(itemObject.getJSONObject("media_share"));
// break;
//
// case CLIP:
// directMedia = getDirectMediaModel(itemObject.getJSONObject("clip").getJSONObject("clip"));
// break;
//
// case FELIX_SHARE:
// directMedia = getDirectMediaModel(itemObject.getJSONObject("felix_share").getJSONObject("video"));
// break;
//
// case MEDIA:
// directMedia = getDirectMediaModel(itemObject.optJSONObject("media"));
// break;
//
// case LIKE:
// text = itemObject.getString("like");
// break;
//
// case STORY_SHARE:
// final JSONObject storyShare = itemObject.getJSONObject("story_share");
// if (!storyShare.has("media"))
// text = "<small>" + storyShare.optString("message") + "</small>";
// else {
// reelShareModel = new DirectItemModel.DirectItemReelShareModel(
// storyShare.optBoolean("is_reel_persisted"),
// storyShare.getJSONObject("media").getJSONObject("user").getLong("pk"),
// storyShare.getJSONObject("media").getJSONObject("user").getString("username"),
// storyShare.getString("text"),
// storyShare.getString("story_share_type"),
// storyShare.getString("reel_type"),
// storyShare.optString("reel_name"),
// storyShare.optString("reel_id"),
// getDirectMediaModel(storyShare.optJSONObject("media")));
// }
// break;
//
// case TEXT:
// if (!itemObject.has("text"))
// Log.d("AWAISKING_APP", "itemObject: " + itemObject); // todo
// text = itemObject.optString("text");
// break;
// }
//
// String[] liked = null;
// if (!itemObject.isNull("reactions") && !itemObject.getJSONObject("reactions").isNull("likes")) {
// JSONArray rawLiked = itemObject.getJSONObject("reactions").getJSONArray("likes");
// liked = new String[rawLiked.length()];
// for (int l = 0; l < rawLiked.length(); ++l) {
// liked[l] = String.valueOf(rawLiked.getJSONObject(l).getLong("sender_id"));
// }
// }
//
// itemModels.add(new DirectItemModel(
// itemObject.getLong("user_id"),
// itemObject.getLong("timestamp"),
// itemObject.getString("item_id"),
// liked,
// itemType,
// text,
// linkModel,
// profileModel,
// reelShareModel,
// directMedia,
// actionLogModel,
// voiceMediaModel,
// ravenMediaModel,
// videoCallEventModel,
// animatedMediaModel));
// }
//
// itemModels.trimToSize();
//
// return new InboxThreadModel(readState, threadId, threadV2Id, threadType, threadTitle,
// threadNewestCursor, threadOldestCursor, threadNextCursor, threadPrevCursor,
// null, // todo
// userModels, leftuserModels, adminIDs,
// itemModels.toArray(new DirectItemModel[0]),
// muted, isPin, named, canonical,
// pending, threadHasOlder, unreadCount, isSpam, isGroup, archived, lastActivityAt);
// }
//
// private static RavenExpiringMediaType getExpiringMediaType(final String type) {
// if ("raven_sent".equals(type)) return RavenExpiringMediaType.RAVEN_SENT;
// if ("raven_opened".equals(type)) return RavenExpiringMediaType.RAVEN_OPENED;
// if ("raven_blocked".equals(type)) return RavenExpiringMediaType.RAVEN_BLOCKED;
// if ("raven_sending".equals(type)) return RavenExpiringMediaType.RAVEN_SENDING;
// if ("raven_replayed".equals(type)) return RavenExpiringMediaType.RAVEN_REPLAYED;
// if ("raven_delivered".equals(type)) return RavenExpiringMediaType.RAVEN_DELIVERED;
// if ("raven_suggested".equals(type)) return RavenExpiringMediaType.RAVEN_SUGGESTED;
// if ("raven_screenshot".equals(type)) return RavenExpiringMediaType.RAVEN_SCREENSHOT;
// if ("raven_cannot_deliver".equals(type)) return RavenExpiringMediaType.RAVEN_CANNOT_DELIVER;
// //if ("raven_unknown".equals(type)) [default?]
// return RavenExpiringMediaType.RAVEN_UNKNOWN;
// }
// public static FeedModel parseItem(final JSONObject itemJson) throws JSONException {
// if (itemJson == null) {
// return null;
// }
// ProfileModel profileModel = null;
// if (itemJson.has("user")) {
// final JSONObject user = itemJson.getJSONObject("user");
// final JSONObject friendshipStatus = user.optJSONObject("friendship_status");
// boolean following = false;
// boolean restricted = false;
// boolean requested = false;
// if (friendshipStatus != null) {
// following = friendshipStatus.optBoolean("following");
// requested = friendshipStatus.optBoolean("outgoing_request");
// restricted = friendshipStatus.optBoolean("is_restricted");
// }
// profileModel = new ProfileModel(
// user.optBoolean("is_private"),
// false, // if you can see it then you def follow
// user.optBoolean("is_verified"),
// user.getString("pk"),
// user.getString(Constants.EXTRAS_USERNAME),
// user.optString("full_name"),
// null,
// null,
// user.getString("profile_pic_url"),
// null,
// 0,
// 0,
// 0,
// following,
// false,
// restricted,
// false,
// requested);
// }
// final JSONObject captionJson = itemJson.optJSONObject("caption");
// final JSONObject locationJson = itemJson.optJSONObject("location");
// final MediaItemType mediaType = ResponseBodyUtils.getMediaItemType(itemJson.optInt("media_type"));
// if (mediaType == null) {
// return null;
// }
// final FeedModel.Builder feedModelBuilder = new FeedModel.Builder()
// .setItemType(mediaType)
// .setProfileModel(profileModel)
// .setPostId(itemJson.getString(Constants.EXTRAS_ID))
// .setThumbnailUrl(mediaType != MediaItemType.MEDIA_TYPE_SLIDER ? ResponseBodyUtils.getLowQualityImage(itemJson) : null)
// .setShortCode(itemJson.getString("code"))
// .setPostCaption(captionJson != null ? captionJson.optString("text") : "")
// .setCaptionId(captionJson != null ? captionJson.optString("pk") : null)
// .setCommentsCount(itemJson.optInt("comment_count"))
// .setTimestamp(itemJson.optLong("taken_at", -1))
// .setLiked(itemJson.optBoolean("has_liked"))
// .setBookmarked(itemJson.optBoolean("has_viewer_saved"))
// .setLikesCount(itemJson.optInt("like_count"))
// .setLocationName(locationJson != null ? locationJson.optString("name") : null)
// .setLocationId(locationJson != null ? String.valueOf(locationJson.optLong("pk")) : null)
// .setImageHeight(itemJson.optInt("original_height"))
// .setImageWidth(itemJson.optInt("original_width"));
// switch (mediaType) {
// case MEDIA_TYPE_VIDEO:
// final long videoViews = itemJson.optLong("view_count", 0);
// feedModelBuilder.setViewCount(videoViews)
// .setDisplayUrl(ResponseBodyUtils.getVideoUrl(itemJson));
// break;
// case MEDIA_TYPE_IMAGE:
// feedModelBuilder.setDisplayUrl(ResponseBodyUtils.getHighQualityImage(itemJson));
// break;
// case MEDIA_TYPE_SLIDER:
// final List<PostChild> childPosts = getChildPosts(itemJson);
// feedModelBuilder.setSliderItems(childPosts)
// .setImageHeight(childPosts.get(0).getHeight())
// .setImageWidth(childPosts.get(0).getWidth());
// break;
// }
// return feedModelBuilder.build();
// }
// the "user" argument can be null, it's used because instagram redacts user details from responses // the "user" argument can be null, it's used because instagram redacts user details from responses
public static Media parseGraphQLItem(final JSONObject itemJson, final User backup) throws JSONException { public static Media parseGraphQLItem(final JSONObject itemJson, final User backup) throws JSONException {
if (itemJson == null) { if (itemJson == null) {
@ -859,88 +277,6 @@ public final class ResponseBodyUtils {
); );
} }
// private static List<PostChild> getChildPosts(final JSONObject mediaJson) throws JSONException {
// if (mediaJson == null) {
// return Collections.emptyList();
// }
// final JSONArray carouselMedia = mediaJson.optJSONArray("carousel_media");
// if (carouselMedia == null) {
// return Collections.emptyList();
// }
// final List<PostChild> children = new ArrayList<>();
// for (int i = 0; i < carouselMedia.length(); i++) {
// final JSONObject childJson = carouselMedia.optJSONObject(i);
// final PostChild childPost = getChildPost(childJson);
// if (childPost != null) {
// children.add(childPost);
// }
// }
// return children;
// }
// private static PostChild getChildPost(final JSONObject childJson) throws JSONException {
// if (childJson == null) {
// return null;
// }
// final MediaItemType mediaType = ResponseBodyUtils.getMediaItemType(childJson.optInt("media_type"));
// if (mediaType == null) {
// return null;
// }
// final PostChild.Builder builder = new PostChild.Builder();
// switch (mediaType) {
// case MEDIA_TYPE_VIDEO:
// builder.setDisplayUrl(ResponseBodyUtils.getVideoUrl(childJson));
// break;
// case MEDIA_TYPE_IMAGE:
// builder.setDisplayUrl(ResponseBodyUtils.getHighQualityImage(childJson));
// break;
// }
// return builder.setItemType(mediaType)
// .setPostId(childJson.getString("id"))
// .setThumbnailUrl(ResponseBodyUtils.getLowQualityImage(childJson))
// .setHeight(childJson.optInt("original_height"))
// .setWidth(childJson.optInt("original_width"))
// .build();
// }
// this is for graphql
// @NonNull
// private static List<PostChild> getSliderItems(final JSONArray children) throws JSONException {
// final List<PostChild> sliderItems = new ArrayList<>();
// for (int j = 0; j < children.length(); ++j) {
// final JSONObject childNode = children.optJSONObject(j).getJSONObject("node");
// final boolean isChildVideo = childNode.optBoolean("is_video");
// int height = 0;
// int width = 0;
// final JSONObject dimensions = childNode.optJSONObject("dimensions");
// if (dimensions != null) {
// height = dimensions.optInt("height");
// width = dimensions.optInt("width");
// }
// String thumbnailUrl = null;
// try {
// thumbnailUrl = childNode.getJSONArray("display_resources")
// .getJSONObject(0)
// .getString("src");
// } catch (JSONException ignored) {}
// final PostChild sliderItem = new PostChild.Builder()
// .setItemType(isChildVideo ? MediaItemType.MEDIA_TYPE_VIDEO
// : MediaItemType.MEDIA_TYPE_IMAGE)
// .setPostId(childNode.getString(Constants.EXTRAS_ID))
// .setDisplayUrl(isChildVideo ? childNode.getString("video_url")
// : childNode.getString("display_url"))
// .setThumbnailUrl(thumbnailUrl != null ? thumbnailUrl
// : childNode.getString("display_url"))
// .setVideoViews(childNode.optLong("video_view_count", 0))
// .setHeight(height)
// .setWidth(width)
// .build();
// // Log.d(TAG, "getSliderItems: sliderItem: " + sliderItem);
// sliderItems.add(sliderItem);
// }
// return sliderItems;
// }
public static StoryModel parseStoryItem(final JSONObject data, public static StoryModel parseStoryItem(final JSONObject data,
final boolean isLocOrHashtag, final boolean isLocOrHashtag,
final String username) throws JSONException { final String username) throws JSONException {

View File

@ -1,14 +1,14 @@
package awais.instagrabber.utils package awais.instagrabber.utils
import android.content.Context
import android.text.format.DateFormat
import android.text.format.DateUtils
import android.util.Patterns import android.util.Patterns
import java.time.format.DateTimeFormatter import java.time.Duration
import java.time.Instant import java.time.Instant
import java.time.LocalDateTime import java.time.LocalDateTime
import java.time.ZoneId import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle
import java.util.* import java.util.*
import kotlin.math.absoluteValue
object TextUtils { object TextUtils {
var datetimeParser: DateTimeFormatter = DateTimeFormatter.ofPattern("") var datetimeParser: DateTimeFormatter = DateTimeFormatter.ofPattern("")
@ -40,22 +40,19 @@ object TextUtils {
} else String.format(Locale.ENGLISH, "%02d:%02d", min, sec) } else String.format(Locale.ENGLISH, "%02d:%02d", min, sec)
} }
@JvmStatic private val timeFormatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT)
fun getRelativeDateTimeString(context: Context?, from: Long): String { private val dateFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)
val now = Date()
val then = Date(from)
val days = daysBetween(from, now.time)
return if (days == 0) {
DateFormat.getTimeFormat(context).format(then)
} else DateFormat.getDateFormat(context).format(then)
}
private fun daysBetween(d1: Long, d2: Long): Int { @JvmStatic
return ((d2 - d1) / DateUtils.DAY_IN_MILLIS).toInt() fun getRelativeDateTimeString(from: Long): String {
val now = LocalDateTime.now()
val then = LocalDateTime.ofInstant(Instant.ofEpochMilli(from), ZoneId.systemDefault())
val days = Duration.between(now, then).toDays().absoluteValue
return then.format(if (days == 0L) timeFormatter else dateFormatter)
} }
@JvmStatic @JvmStatic
fun extractUrls(text: String?): List<String> { fun extractUrls(text: String): List<String> {
if (isEmpty(text)) return emptyList() if (isEmpty(text)) return emptyList()
val matcher = Patterns.WEB_URL.matcher(text) val matcher = Patterns.WEB_URL.matcher(text)
val urls: MutableList<String> = ArrayList() val urls: MutableList<String> = ArrayList()
@ -87,8 +84,8 @@ object TextUtils {
@JvmStatic @JvmStatic
fun epochSecondToString(epochSecond: Long): String { fun epochSecondToString(epochSecond: Long): String {
return LocalDateTime.ofInstant( return LocalDateTime.ofInstant(
Instant.ofEpochSecond(epochSecond), Instant.ofEpochSecond(epochSecond),
ZoneId.systemDefault() ZoneId.systemDefault()
).format(datetimeParser) ).format(datetimeParser)
} }

View File

@ -80,7 +80,7 @@ public class DirectSettingsViewModel extends AndroidViewModel {
// final List<Long> adminUserIds = thread.getAdminUserIds(); // final List<Long> adminUserIds = thread.getAdminUserIds();
// this.adminUserIds.postValue(adminUserIds); // this.adminUserIds.postValue(adminUserIds);
// viewerIsAdmin = adminUserIds.contains(viewerId); // viewerIsAdmin = adminUserIds.contains(viewerId);
// muted.postValue(thread.isMuted()); // muted.postValue(thread.getMuted());
// mentionsMuted.postValue(thread.isMentionsMuted()); // mentionsMuted.postValue(thread.isMentionsMuted());
// approvalRequiredToJoin.postValue(thread.isApprovalRequiredForNewMembers()); // approvalRequiredToJoin.postValue(thread.isApprovalRequiredForNewMembers());
// isPending.postValue(thread.isPending()); // isPending.postValue(thread.isPending());

View File

@ -1,19 +0,0 @@
package awais.instagrabber.viewmodels;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import java.util.List;
import awais.instagrabber.db.entities.Favorite;
public class FavoritesViewModel extends ViewModel {
private MutableLiveData<List<Favorite>> list;
public MutableLiveData<List<Favorite>> getList() {
if (list == null) {
list = new MutableLiveData<>();
}
return list;
}
}

View File

@ -0,0 +1,48 @@
package awais.instagrabber.viewmodels
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import awais.instagrabber.db.datasources.FavoriteDataSource
import awais.instagrabber.db.entities.Favorite
import awais.instagrabber.db.repositories.FavoriteRepository
import awais.instagrabber.db.repositories.RepositoryCallback
class FavoritesViewModel(application: Application) : AndroidViewModel(application) {
private val _list = MutableLiveData<List<Favorite>>()
val list: LiveData<List<Favorite>> = _list
private val favoriteRepository: FavoriteRepository = FavoriteRepository.getInstance(FavoriteDataSource.getInstance(application))
init {
fetch()
}
fun fetch() {
favoriteRepository.getAllFavorites(object : RepositoryCallback<List<Favorite>> {
override fun onSuccess(favorites: List<Favorite>?) {
_list.postValue(favorites ?: emptyList())
}
override fun onDataNotAvailable() {}
})
}
fun delete(favorite: Favorite, onSuccess: () -> Unit) {
favoriteRepository.deleteFavorite(favorite.query, favorite.type, object : RepositoryCallback<Void> {
override fun onSuccess(result: Void?) {
onSuccess()
favoriteRepository.getAllFavorites(object : RepositoryCallback<List<Favorite>> {
override fun onSuccess(result: List<Favorite>?) {
_list.postValue(result ?: emptyList())
}
override fun onDataNotAvailable() {}
})
}
override fun onDataNotAvailable() {}
})
}
}

View File

@ -272,7 +272,7 @@ public class PostViewV2ViewModel extends ViewModel {
data.postValue(Resource.loading(null)); data.postValue(Resource.loading(null));
final Caption value = caption.getValue(); final Caption value = caption.getValue();
if (value == null) return data; if (value == null) return data;
mediaService.translate(String.valueOf(value.getPk()), "1", new ServiceCallback<String>() { mediaService.translate(value.getPk(), "1", new ServiceCallback<String>() {
@Override @Override
public void onSuccess(final String result) { public void onSuccess(final String result) {
if (TextUtils.isEmpty(result)) { if (TextUtils.isEmpty(result)) {

View File

@ -107,7 +107,7 @@ public class DiscoverService extends BaseService {
// } // }
// final String type = clusterJson.optString("type"); // final String type = clusterJson.optString("type");
// final boolean canMute = clusterJson.optBoolean("can_mute"); // final boolean canMute = clusterJson.optBoolean("can_mute");
// final boolean isMuted = clusterJson.optBoolean("is_muted"); // final boolean getMuted = clusterJson.optBoolean("is_muted");
// final JSONObject coverMediaJson = clusterJson.optJSONObject("cover_media"); // final JSONObject coverMediaJson = clusterJson.optJSONObject("cover_media");
// final int rankedPosition = clusterJson.optInt("ranked_position"); // final int rankedPosition = clusterJson.optInt("ranked_position");
// final FeedModel feedModel = parseClusterCover(coverMediaJson); // final FeedModel feedModel = parseClusterCover(coverMediaJson);
@ -116,7 +116,7 @@ public class DiscoverService extends BaseService {
// title, // title,
// type, // type,
// canMute, // canMute,
// isMuted, // getMuted,
// rankedPosition, // rankedPosition,
// feedModel // feedModel
// ); // );

View File

@ -52,6 +52,7 @@ public class GraphQLService extends BaseService {
return instance; return instance;
} }
// TODO convert string response to a response class
private void fetch(final String queryHash, private void fetch(final String queryHash,
final String variables, final String variables,
final String arg1, final String arg1,
@ -194,6 +195,7 @@ public class GraphQLService extends BaseService {
return new PostsFetchResponse(items, hasNextPage, endCursor); return new PostsFetchResponse(items, hasNextPage, endCursor);
} }
// TODO convert string response to a response class
public void fetchCommentLikers(final String commentId, public void fetchCommentLikers(final String commentId,
final String endCursor, final String endCursor,
final ServiceCallback<GraphQLUserListFetchResponse> callback) { final ServiceCallback<GraphQLUserListFetchResponse> callback) {
@ -273,6 +275,7 @@ public class GraphQLService extends BaseService {
return repository.fetch(queryMap); return repository.fetch(queryMap);
} }
// TODO convert string response to a response class
public void fetchUser(final String username, public void fetchUser(final String username,
final ServiceCallback<User> callback) { final ServiceCallback<User> callback) {
final Call<String> request = repository.getUser(username); final Call<String> request = repository.getUser(username);
@ -357,6 +360,7 @@ public class GraphQLService extends BaseService {
}); });
} }
// TODO convert string response to a response class
public void fetchPost(final String shortcode, public void fetchPost(final String shortcode,
final ServiceCallback<Media> callback) { final ServiceCallback<Media> callback) {
final Call<String> request = repository.getPost(shortcode); final Call<String> request = repository.getPost(shortcode);
@ -391,6 +395,7 @@ public class GraphQLService extends BaseService {
}); });
} }
// TODO convert string response to a response class
public void fetchTag(final String tag, public void fetchTag(final String tag,
final ServiceCallback<Hashtag> callback) { final ServiceCallback<Hashtag> callback) {
final Call<String> request = repository.getTag(tag); final Call<String> request = repository.getTag(tag);
@ -431,6 +436,7 @@ public class GraphQLService extends BaseService {
}); });
} }
// TODO convert string response to a response class
public void fetchLocation(final long locationId, public void fetchLocation(final long locationId,
final ServiceCallback<Location> callback) { final ServiceCallback<Location> callback) {
final Call<String> request = repository.getLocation(locationId); final Call<String> request = repository.getLocation(locationId);

View File

@ -21,7 +21,9 @@ import java.util.UUID;
import awais.instagrabber.models.Comment; import awais.instagrabber.models.Comment;
import awais.instagrabber.models.enums.MediaItemType; import awais.instagrabber.models.enums.MediaItemType;
import awais.instagrabber.repositories.MediaRepository; import awais.instagrabber.repositories.MediaRepository;
import awais.instagrabber.repositories.requests.Clip;
import awais.instagrabber.repositories.requests.UploadFinishOptions; import awais.instagrabber.repositories.requests.UploadFinishOptions;
import awais.instagrabber.repositories.requests.VideoOptions;
import awais.instagrabber.repositories.responses.LikersResponse; import awais.instagrabber.repositories.responses.LikersResponse;
import awais.instagrabber.repositories.responses.Media; import awais.instagrabber.repositories.responses.Media;
import awais.instagrabber.repositories.responses.MediaInfoResponse; import awais.instagrabber.repositories.responses.MediaInfoResponse;
@ -443,13 +445,9 @@ public class MediaService extends BaseService {
public Call<String> uploadFinish(@NonNull final UploadFinishOptions options) { public Call<String> uploadFinish(@NonNull final UploadFinishOptions options) {
if (options.getVideoOptions() != null) { if (options.getVideoOptions() != null) {
final UploadFinishOptions.VideoOptions videoOptions = options.getVideoOptions(); final VideoOptions videoOptions = options.getVideoOptions();
if (videoOptions.getClips() == null) { if (videoOptions.getClips().isEmpty()) {
videoOptions.setClips(Collections.singletonList( videoOptions.setClips(Collections.singletonList(new Clip(videoOptions.getLength(), options.getSourceType())));
new UploadFinishOptions.Clip()
.setLength(videoOptions.getLength())
.setSourceType(options.getSourceType())
));
} }
} }
final String timezoneOffset = String.valueOf(DateUtils.getTimezoneOffset()); final String timezoneOffset = String.valueOf(DateUtils.getTimezoneOffset());

View File

@ -9,6 +9,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import java.io.IOException; import java.io.IOException;
@ -70,8 +71,18 @@ public class IgErrorsInterceptor implements Interceptor {
try { try {
final String bodyString = body.string(); final String bodyString = body.string();
Log.d(TAG, "checkError: " + bodyString); Log.d(TAG, "checkError: " + bodyString);
final JSONObject jsonObject = new JSONObject(bodyString); JSONObject jsonObject = null;
String message = jsonObject.optString("message"); try {
jsonObject = new JSONObject(bodyString);
} catch (JSONException e) {
Log.e(TAG, "checkError: ", e);
}
String message;
if (jsonObject != null) {
message = jsonObject.optString("message");
} else {
message = bodyString;
}
if (!TextUtils.isEmpty(message)) { if (!TextUtils.isEmpty(message)) {
message = message.toLowerCase(); message = message.toLowerCase();
switch (message) { switch (message) {