Convert FriendshipRepository and FriendshipService to kotlin

This commit is contained in:
Ammar Githam 2021-06-06 14:18:27 +09:00
parent 7769aa220f
commit cf65ed0fc5
6 changed files with 433 additions and 383 deletions

View File

@ -30,9 +30,12 @@ import awais.instagrabber.customviews.helpers.RecyclerLazyLoader;
import awais.instagrabber.databinding.FragmentFollowersViewerBinding;
import awais.instagrabber.models.FollowModel;
import awais.instagrabber.repositories.responses.FriendshipListFetchResponse;
import awais.instagrabber.utils.AppExecutors;
import awais.instagrabber.utils.CoroutineUtilsKt;
import awais.instagrabber.utils.TextUtils;
import awais.instagrabber.webservices.FriendshipService;
import awais.instagrabber.webservices.ServiceCallback;
import kotlinx.coroutines.Dispatchers;
import thoughtbot.expandableadapter.ExpandableGroup;
public final class FollowViewerFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
@ -68,10 +71,32 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh
if (!isFollowersList) followModels.addAll(result.getItems());
if (result.isMoreAvailable()) {
endCursor = result.getNextMaxId();
friendshipService.getList(false, profileId, endCursor, this);
friendshipService.getList(
false,
profileId,
endCursor,
CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
onFailure(throwable);
return;
}
onSuccess(response);
}), Dispatchers.getIO())
);
} else if (followersModels.size() == 0) {
if (!isFollowersList) moreAvailable = false;
friendshipService.getList(true, profileId, null, followingFetchCb);
friendshipService.getList(
true,
profileId,
null,
CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
followingFetchCb.onFailure(throwable);
return;
}
followingFetchCb.onSuccess(response);
}), Dispatchers.getIO())
);
} else {
if (!isFollowersList) moreAvailable = false;
showCompare();
@ -84,8 +109,7 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh
try {
binding.swipeRefreshLayout.setRefreshing(false);
Toast.makeText(getContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
}
catch(Throwable e) {}
} catch (Throwable ignored) {}
Log.e(TAG, "Error fetching list (double, following)", t);
}
};
@ -97,10 +121,32 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh
if (isFollowersList) followModels.addAll(result.getItems());
if (result.isMoreAvailable()) {
endCursor = result.getNextMaxId();
friendshipService.getList(true, profileId, endCursor, this);
friendshipService.getList(
true,
profileId,
endCursor,
CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
onFailure(throwable);
return;
}
onSuccess(response);
}), Dispatchers.getIO())
);
} else if (followingModels.size() == 0) {
if (isFollowersList) moreAvailable = false;
friendshipService.getList(false, profileId, null, followingFetchCb);
friendshipService.getList(
false,
profileId,
null,
CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
followingFetchCb.onFailure(throwable);
return;
}
followingFetchCb.onSuccess(response);
}), Dispatchers.getIO())
);
} else {
if (isFollowersList) moreAvailable = false;
showCompare();
@ -113,8 +159,7 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh
try {
binding.swipeRefreshLayout.setRefreshing(false);
Toast.makeText(getContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
}
catch(Throwable e) {}
} catch (Throwable ignored) {}
Log.e(TAG, "Error fetching list (double, follower)", t);
}
};
@ -122,7 +167,7 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh
@Override
public void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
friendshipService = FriendshipService.getInstance(null, null, 0);
friendshipService = FriendshipService.INSTANCE;
fragmentActivity = (AppCompatActivity) getActivity();
setHasOptionsMenu(true);
}
@ -235,8 +280,7 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh
try {
binding.swipeRefreshLayout.setRefreshing(false);
Toast.makeText(getContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
}
catch(Throwable e) {}
} catch (Throwable ignored) {}
Log.e(TAG, "Error fetching list (single)", t);
}
};
@ -245,7 +289,18 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh
if (!TextUtils.isEmpty(endCursor) && !searching) {
binding.swipeRefreshLayout.setRefreshing(true);
layoutManager.setStackFromEnd(true);
friendshipService.getList(isFollowersList, profileId, endCursor, cb);
friendshipService.getList(
isFollowersList,
profileId,
endCursor,
CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
cb.onFailure(throwable);
return;
}
cb.onSuccess(response);
}), Dispatchers.getIO())
);
endCursor = null;
}
});
@ -253,7 +308,18 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh
binding.rvFollow.setLayoutManager(layoutManager);
if (moreAvailable) {
binding.swipeRefreshLayout.setRefreshing(true);
friendshipService.getList(isFollowersList, profileId, endCursor, cb);
friendshipService.getList(
isFollowersList,
profileId,
endCursor,
CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
cb.onFailure(throwable);
return;
}
cb.onSuccess(response);
}), Dispatchers.getIO())
);
} else {
refreshAdapter(followModels, null, null, null);
layoutManager.scrollToPosition(0);
@ -269,17 +335,34 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh
if (moreAvailable) {
binding.swipeRefreshLayout.setRefreshing(true);
Toast.makeText(getContext(), R.string.follower_start_compare, Toast.LENGTH_LONG).show();
friendshipService.getList(isFollowersList,
profileId,
endCursor,
isFollowersList ? followersFetchCb : followingFetchCb);
friendshipService.getList(
isFollowersList,
profileId,
endCursor,
CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
final ServiceCallback<FriendshipListFetchResponse> callback = isFollowersList ? followersFetchCb : followingFetchCb;
if (throwable != null) {
callback.onFailure(throwable);
return;
}
callback.onSuccess(response);
}), Dispatchers.getIO())
);
} else if (followersModels.size() == 0 || followingModels.size() == 0) {
binding.swipeRefreshLayout.setRefreshing(true);
Toast.makeText(getContext(), R.string.follower_start_compare, Toast.LENGTH_LONG).show();
friendshipService.getList(!isFollowersList,
profileId,
null,
isFollowersList ? followingFetchCb : followersFetchCb);
friendshipService.getList(
!isFollowersList,
profileId,
null,
CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
final ServiceCallback<FriendshipListFetchResponse> callback = isFollowersList ? followingFetchCb : followersFetchCb;
if (throwable != null) {
callback.onFailure(throwable);
return;
}
callback.onSuccess(response);
}), Dispatchers.getIO()));
} else showCompare();
}
@ -337,10 +420,10 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh
final Context context = getContext();
if (loading) Toast.makeText(context, R.string.follower_wait_to_load, Toast.LENGTH_LONG).show();
else if (isCompare) {
isCompare = !isCompare;
isCompare = false;
listFollows();
} else {
isCompare = !isCompare;
isCompare = true;
listCompare();
}
return true;
@ -354,16 +437,15 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh
final ArrayList<ExpandableGroup> groups = new ArrayList<>(1);
if (isCompare && followingModels != null && followersModels != null && allFollowing != null) {
if (followingModels != null && followingModels.size() > 0)
if (followingModels.size() > 0)
groups.add(new ExpandableGroup(resources.getString(R.string.followers_not_following, username), followingModels));
if (followersModels != null && followersModels.size() > 0)
if (followersModels.size() > 0)
groups.add(new ExpandableGroup(resources.getString(R.string.followers_not_follower, namePost), followersModels));
if (allFollowing != null && allFollowing.size() > 0)
if (allFollowing.size() > 0)
groups.add(new ExpandableGroup(resources.getString(R.string.followers_both_following), allFollowing));
} else if (followModels != null) {
groups.add(new ExpandableGroup(type, followModels));
}
else return;
} else return;
adapter = new FollowAdapter(clickListener, groups);
adapter.toggleGroup(0);
binding.rvFollow.setAdapter(adapter);

View File

@ -34,7 +34,6 @@ import awais.instagrabber.adapters.NotificationsAdapter.OnNotificationClickListe
import awais.instagrabber.databinding.FragmentNotificationsViewerBinding;
import awais.instagrabber.models.enums.NotificationType;
import awais.instagrabber.repositories.requests.StoryViewerOptions;
import awais.instagrabber.repositories.responses.FriendshipChangeResponse;
import awais.instagrabber.repositories.responses.notification.Notification;
import awais.instagrabber.repositories.responses.notification.NotificationArgs;
import awais.instagrabber.repositories.responses.notification.NotificationImage;
@ -68,6 +67,7 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
private String type;
private long targetId;
private Context context;
private long userId;
private final ServiceCallback<List<Notification>> cb = new ServiceCallback<List<Notification>>() {
@Override
@ -168,34 +168,40 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
break;
case 1:
if (model.getType() == NotificationType.REQUEST) {
friendshipService.approve(args.getUserId(), new ServiceCallback<FriendshipChangeResponse>() {
@Override
public void onSuccess(final FriendshipChangeResponse result) {
onRefresh();
Log.e(TAG, "approve: status was not ok!");
}
@Override
public void onFailure(final Throwable t) {
Log.e(TAG, "approve: onFailure: ", t);
}
});
friendshipService.approve(
csrfToken,
userId,
deviceUuid,
args.getUserId(),
CoroutineUtilsKt.getContinuation(
(response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
Log.e(TAG, "approve: onFailure: ", throwable);
return;
}
onRefresh();
}),
Dispatchers.getIO()
)
);
return;
}
clickListener.onPreviewClick(model);
break;
case 2:
friendshipService.ignore(args.getUserId(), new ServiceCallback<FriendshipChangeResponse>() {
@Override
public void onSuccess(final FriendshipChangeResponse result) {
onRefresh();
}
@Override
public void onFailure(final Throwable t) {
Log.e(TAG, "ignore: onFailure: ", t);
}
});
friendshipService.ignore(
csrfToken,
userId,
deviceUuid,
args.getUserId(),
CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
Log.e(TAG, "approve: onFailure: ", throwable);
return;
}
onRefresh();
}), Dispatchers.getIO())
);
break;
}
};
@ -219,10 +225,10 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
if (TextUtils.isEmpty(cookie)) {
Toast.makeText(context, R.string.activity_notloggedin, Toast.LENGTH_SHORT).show();
}
final long userId = CookieUtils.getUserIdFromCookie(cookie);
userId = CookieUtils.getUserIdFromCookie(cookie);
deviceUuid = Utils.settingsHelper.getString(Constants.DEVICE_UUID);
csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie);
friendshipService = FriendshipService.getInstance(deviceUuid, csrfToken, userId);
friendshipService = FriendshipService.INSTANCE;
mediaService = MediaService.INSTANCE;
newsService = NewsService.getInstance();
}

View File

@ -79,7 +79,6 @@ import awais.instagrabber.models.enums.FavoriteType;
import awais.instagrabber.models.enums.PostItemType;
import awais.instagrabber.repositories.requests.StoryViewerOptions;
import awais.instagrabber.repositories.responses.FriendshipChangeResponse;
import awais.instagrabber.repositories.responses.FriendshipRestrictResponse;
import awais.instagrabber.repositories.responses.FriendshipStatus;
import awais.instagrabber.repositories.responses.Media;
import awais.instagrabber.repositories.responses.User;
@ -146,6 +145,8 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
private AppStateViewModel appStateViewModel;
private boolean disableDm = false;
private ProfileFragmentViewModel viewModel;
private String csrfToken;
private String deviceUuid;
private final ServiceCallback<FriendshipChangeResponse> changeCb = new ServiceCallback<FriendshipChangeResponse>() {
@Override
@ -331,10 +332,10 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
cookie = Utils.settingsHelper.getString(Constants.COOKIE);
isLoggedIn = !TextUtils.isEmpty(cookie) && CookieUtils.getUserIdFromCookie(cookie) > 0;
myId = CookieUtils.getUserIdFromCookie(cookie);
final String deviceUuid = Utils.settingsHelper.getString(Constants.DEVICE_UUID);
final String csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie);
deviceUuid = Utils.settingsHelper.getString(Constants.DEVICE_UUID);
csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie);
fragmentActivity = (MainActivity) requireActivity();
friendshipService = isLoggedIn ? FriendshipService.getInstance(deviceUuid, csrfToken, myId) : null;
friendshipService = isLoggedIn ? FriendshipService.INSTANCE : null;
directMessagesService = isLoggedIn ? DirectMessagesService.getInstance(csrfToken, myId, deviceUuid) : null;
storiesService = isLoggedIn ? StoriesService.getInstance(null, 0L, null) : null;
mediaService = isLoggedIn ? MediaService.INSTANCE : null;
@ -451,25 +452,38 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
if (!isLoggedIn) return false;
final String action = profileModel.getFriendshipStatus().isRestricted() ? "Unrestrict" : "Restrict";
friendshipService.toggleRestrict(
csrfToken,
deviceUuid,
profileModel.getPk(),
!profileModel.getFriendshipStatus().isRestricted(),
new ServiceCallback<FriendshipRestrictResponse>() {
@Override
public void onSuccess(final FriendshipRestrictResponse result) {
Log.d(TAG, action + " success: " + result);
fetchProfileDetails();
CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
Log.e(TAG, "Error while performing " + action, throwable);
return;
}
@Override
public void onFailure(final Throwable t) {
Log.e(TAG, "Error while performing " + action, t);
}
});
// Log.d(TAG, action + " success: " + response);
fetchProfileDetails();
}), Dispatchers.getIO())
);
return true;
}
if (item.getItemId() == R.id.block) {
if (!isLoggedIn) return false;
friendshipService.changeBlock(profileModel.getFriendshipStatus().getBlocking(), profileModel.getPk(), changeCb);
// changeCb
friendshipService.changeBlock(
csrfToken,
myId,
deviceUuid,
profileModel.getFriendshipStatus().getBlocking(),
profileModel.getPk(),
CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
changeCb.onFailure(throwable);
return;
}
changeCb.onSuccess(response);
}), Dispatchers.getIO())
);
return true;
}
if (item.getItemId() == R.id.chaining) {
@ -484,25 +498,57 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
if (!isLoggedIn) return false;
final String action = profileModel.getFriendshipStatus().isMutingReel() ? "Unmute stories" : "Mute stories";
friendshipService.changeMute(
csrfToken,
myId,
deviceUuid,
profileModel.getFriendshipStatus().isMutingReel(),
profileModel.getPk(),
true,
changeCb);
CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
changeCb.onFailure(throwable);
return;
}
changeCb.onSuccess(response);
}), Dispatchers.getIO())
);
return true;
}
if (item.getItemId() == R.id.mute_posts) {
if (!isLoggedIn) return false;
final String action = profileModel.getFriendshipStatus().getMuting() ? "Unmute stories" : "Mute stories";
friendshipService.changeMute(
csrfToken,
myId,
deviceUuid,
profileModel.getFriendshipStatus().getMuting(),
profileModel.getPk(),
false,
changeCb);
CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
changeCb.onFailure(throwable);
return;
}
changeCb.onSuccess(response);
}), Dispatchers.getIO())
);
return true;
}
if (item.getItemId() == R.id.remove_follower) {
if (!isLoggedIn) return false;
friendshipService.removeFollower(profileModel.getPk(), changeCb);
friendshipService.removeFollower(
csrfToken,
myId,
deviceUuid,
profileModel.getPk(),
CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
changeCb.onFailure(throwable);
return;
}
changeCb.onSuccess(response);
}), Dispatchers.getIO())
);
return true;
}
return super.onOptionsItemSelected(item);
@ -1032,19 +1078,55 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
private void setupCommonListeners() {
final Context context = getContext();
if (context == null) return;
profileDetailsBinding.btnFollow.setOnClickListener(v -> {
if (profileModel.getFriendshipStatus().getFollowing() && profileModel.isPrivate()) {
new AlertDialog.Builder(context)
.setTitle(R.string.priv_acc)
.setMessage(R.string.priv_acc_confirm)
.setPositiveButton(R.string.confirm, (d, w) ->
friendshipService.unfollow(profileModel.getPk(), changeCb))
.setPositiveButton(R.string.confirm, (d, w) -> friendshipService.unfollow(
csrfToken,
myId,
deviceUuid,
profileModel.getPk(),
CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
changeCb.onFailure(throwable);
return;
}
changeCb.onSuccess(response);
}), Dispatchers.getIO())
))
.setNegativeButton(R.string.cancel, null)
.show();
} else if (profileModel.getFriendshipStatus().getFollowing() || profileModel.getFriendshipStatus().getOutgoingRequest()) {
friendshipService.unfollow(profileModel.getPk(), changeCb);
friendshipService.unfollow(
csrfToken,
myId,
deviceUuid,
profileModel.getPk(),
CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
changeCb.onFailure(throwable);
return;
}
changeCb.onSuccess(response);
}), Dispatchers.getIO())
);
} else {
friendshipService.follow(profileModel.getPk(), changeCb);
friendshipService.follow(
csrfToken,
myId,
deviceUuid,
profileModel.getPk(),
CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
changeCb.onFailure(throwable);
return;
}
changeCb.onSuccess(response);
}), Dispatchers.getIO())
);
}
});
profileDetailsBinding.btnSaved.setOnClickListener(v -> {
@ -1109,7 +1191,6 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
}
showProfilePicDialog();
};
if (context == null) return;
new AlertDialog.Builder(context)
.setItems(options, profileDialogListener)
.setNegativeButton(R.string.cancel, null)

View File

@ -19,8 +19,6 @@ 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.Companion.of
import awais.instagrabber.repositories.responses.FriendshipChangeResponse
import awais.instagrabber.repositories.responses.FriendshipRestrictResponse
import awais.instagrabber.repositories.responses.User
import awais.instagrabber.repositories.responses.directmessages.*
import awais.instagrabber.repositories.responses.giphy.GiphyGif
@ -34,7 +32,6 @@ import awais.instagrabber.utils.TextUtils.isEmpty
import awais.instagrabber.webservices.DirectMessagesService
import awais.instagrabber.webservices.FriendshipService
import awais.instagrabber.webservices.MediaService
import awais.instagrabber.webservices.ServiceCallback
import com.google.common.collect.ImmutableList
import com.google.common.collect.Iterables
import kotlinx.coroutines.CoroutineScope
@ -69,7 +66,6 @@ class ThreadManager private constructor(
private val currentUser: User?
private val contentResolver: ContentResolver
private val service: DirectMessagesService
private val friendshipService: FriendshipService
val thread: LiveData<DirectThread?> by lazy {
distinctUntilChanged(map(inboxManager.getInbox()) { inboxResource: Resource<DirectInbox?>? ->
@ -1132,61 +1128,57 @@ class ThreadManager private constructor(
fun blockUser(user: User, scope: CoroutineScope): LiveData<Resource<Any?>> {
val data = MutableLiveData<Resource<Any?>>()
friendshipService.changeBlock(false, user.pk, object : ServiceCallback<FriendshipChangeResponse?> {
override fun onSuccess(result: FriendshipChangeResponse?) {
scope.launch(Dispatchers.IO) {
try {
FriendshipService.changeBlock(csrfToken, viewerId, deviceUuid, false, user.pk)
refreshChats(scope)
} catch (e: Exception) {
Log.e(TAG, "onFailure: ", e)
data.postValue(error(e.message, null))
}
override fun onFailure(t: Throwable) {
Log.e(TAG, "onFailure: ", t)
data.postValue(error(t.message, null))
}
})
}
return data
}
fun unblockUser(user: User, scope: CoroutineScope): LiveData<Resource<Any?>> {
val data = MutableLiveData<Resource<Any?>>()
friendshipService.changeBlock(true, user.pk, object : ServiceCallback<FriendshipChangeResponse?> {
override fun onSuccess(result: FriendshipChangeResponse?) {
scope.launch(Dispatchers.IO) {
try {
FriendshipService.changeBlock(csrfToken, viewerId, deviceUuid, true, user.pk)
refreshChats(scope)
} catch (e: Exception) {
Log.e(TAG, "onFailure: ", e)
data.postValue(error(e.message, null))
}
override fun onFailure(t: Throwable) {
Log.e(TAG, "onFailure: ", t)
data.postValue(error(t.message, null))
}
})
}
return data
}
fun restrictUser(user: User, scope: CoroutineScope): LiveData<Resource<Any?>> {
val data = MutableLiveData<Resource<Any?>>()
friendshipService.toggleRestrict(user.pk, true, object : ServiceCallback<FriendshipRestrictResponse?> {
override fun onSuccess(result: FriendshipRestrictResponse?) {
scope.launch(Dispatchers.IO) {
try {
FriendshipService.toggleRestrict(csrfToken, deviceUuid, user.pk, true)
refreshChats(scope)
} catch (e: Exception) {
Log.e(TAG, "onFailure: ", e)
data.postValue(error(e.message, null))
}
override fun onFailure(t: Throwable) {
Log.e(TAG, "onFailure: ", t)
data.postValue(error(t.message, null))
}
})
}
return data
}
fun unRestrictUser(user: User, scope: CoroutineScope): LiveData<Resource<Any?>> {
val data = MutableLiveData<Resource<Any?>>()
friendshipService.toggleRestrict(user.pk, false, object : ServiceCallback<FriendshipRestrictResponse?> {
override fun onSuccess(result: FriendshipRestrictResponse?) {
scope.launch(Dispatchers.IO) {
try {
FriendshipService.toggleRestrict(csrfToken, deviceUuid, user.pk, false)
refreshChats(scope)
} catch (e: Exception) {
Log.e(TAG, "onFailure: ", e)
data.postValue(error(e.message, null))
}
override fun onFailure(t: Throwable) {
Log.e(TAG, "onFailure: ", t)
data.postValue(error(t.message, null))
}
})
}
return data
}
@ -1415,7 +1407,6 @@ class ThreadManager private constructor(
this.contentResolver = contentResolver
this.viewerId = viewerId
service = DirectMessagesService.getInstance(csrfToken, viewerId, deviceUuid)
friendshipService = FriendshipService.getInstance(deviceUuid, csrfToken, viewerId)
// fetchChats();
}
}

View File

@ -1,37 +1,36 @@
package awais.instagrabber.repositories;
package awais.instagrabber.repositories
import java.util.Map;
import awais.instagrabber.repositories.responses.FriendshipChangeResponse;
import awais.instagrabber.repositories.responses.FriendshipRestrictResponse;
import retrofit2.Call;
import retrofit2.http.FieldMap;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Path;
import retrofit2.http.QueryMap;
public interface FriendshipRepository {
import awais.instagrabber.repositories.responses.FriendshipChangeResponse
import awais.instagrabber.repositories.responses.FriendshipRestrictResponse
import retrofit2.http.*
interface FriendshipRepository {
@FormUrlEncoded
@POST("/api/v1/friendships/{action}/{id}/")
Call<FriendshipChangeResponse> change(@Path("action") String action,
@Path("id") long id,
@FieldMap Map<String, String> form);
suspend fun change(
@Path("action") action: String,
@Path("id") id: Long,
@FieldMap form: Map<String, String>,
): FriendshipChangeResponse
@FormUrlEncoded
@POST("/api/v1/restrict_action/{action}/")
Call<FriendshipRestrictResponse> toggleRestrict(@Path("action") String action,
@FieldMap Map<String, String> form);
suspend fun toggleRestrict(
@Path("action") action: String,
@FieldMap form: Map<String, String>,
): FriendshipRestrictResponse
@GET("/api/v1/friendships/{userId}/{type}/")
Call<String> getList(@Path("userId") long userId,
@Path("type") String type, // following or followers
@QueryMap(encoded = true) Map<String, String> queryParams);
suspend fun getList(
@Path("userId") userId: Long,
@Path("type") type: String, // following or followers
@QueryMap(encoded = true) queryParams: Map<String, String>,
): String
@FormUrlEncoded
@POST("/api/v1/friendships/{action}/")
Call<FriendshipChangeResponse> changeMute(@Path("action") String action,
@FieldMap Map<String, String> form);
}
suspend fun changeMute(
@Path("action") action: String,
@FieldMap form: Map<String, String>,
): FriendshipChangeResponse
}

View File

@ -1,264 +1,155 @@
package awais.instagrabber.webservices;
package awais.instagrabber.webservices
import android.util.Log;
import awais.instagrabber.models.FollowModel
import awais.instagrabber.repositories.FriendshipRepository
import awais.instagrabber.repositories.responses.FriendshipChangeResponse
import awais.instagrabber.repositories.responses.FriendshipListFetchResponse
import awais.instagrabber.repositories.responses.FriendshipRestrictResponse
import awais.instagrabber.utils.Utils
import awais.instagrabber.webservices.RetrofitFactory.retrofit
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
import androidx.annotation.NonNull;
object FriendshipService : BaseService() {
private val repository: FriendshipRepository = retrofit.create(FriendshipRepository::class.java)
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
suspend fun follow(
csrfToken: String,
userId: Long,
deviceUuid: String,
targetUserId: Long,
): FriendshipChangeResponse = change(csrfToken, userId, deviceUuid, "create", targetUserId)
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
suspend fun unfollow(
csrfToken: String,
userId: Long,
deviceUuid: String,
targetUserId: Long,
): FriendshipChangeResponse = change(csrfToken, userId, deviceUuid, "destroy", targetUserId)
import awais.instagrabber.models.FollowModel;
import awais.instagrabber.repositories.FriendshipRepository;
import awais.instagrabber.repositories.responses.FriendshipChangeResponse;
import awais.instagrabber.repositories.responses.FriendshipListFetchResponse;
import awais.instagrabber.repositories.responses.FriendshipRestrictResponse;
import awais.instagrabber.utils.TextUtils;
import awais.instagrabber.utils.Utils;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class FriendshipService extends BaseService {
private static final String TAG = "FriendshipService";
private final FriendshipRepository repository;
private final String deviceUuid, csrfToken;
private final long userId;
private static FriendshipService instance;
private FriendshipService(final String deviceUuid,
final String csrfToken,
final long userId) {
this.deviceUuid = deviceUuid;
this.csrfToken = csrfToken;
this.userId = userId;
repository = RetrofitFactory.INSTANCE
.getRetrofit()
.create(FriendshipRepository.class);
suspend fun changeBlock(
csrfToken: String,
userId: Long,
deviceUuid: String,
unblock: Boolean,
targetUserId: Long,
): FriendshipChangeResponse {
return change(csrfToken, userId, deviceUuid, if (unblock) "unblock" else "block", targetUserId)
}
public String getCsrfToken() {
return csrfToken;
suspend fun toggleRestrict(
csrfToken: String,
deviceUuid: String,
targetUserId: Long,
restrict: Boolean,
): FriendshipRestrictResponse {
val form = mapOf(
"_csrftoken" to csrfToken,
"_uuid" to deviceUuid,
"target_user_id" to targetUserId.toString(),
)
val action = if (restrict) "restrict" else "unrestrict"
return repository.toggleRestrict(action, form)
}
public String getDeviceUuid() {
return deviceUuid;
suspend fun approve(
csrfToken: String,
userId: Long,
deviceUuid: String,
targetUserId: Long,
): FriendshipChangeResponse = change(csrfToken, userId, deviceUuid, "approve", targetUserId)
suspend fun ignore(
csrfToken: String,
userId: Long,
deviceUuid: String,
targetUserId: Long,
): FriendshipChangeResponse = change(csrfToken, userId, deviceUuid, "ignore", targetUserId)
suspend fun removeFollower(
csrfToken: String,
userId: Long,
deviceUuid: String,
targetUserId: Long,
): FriendshipChangeResponse = change(csrfToken, userId, deviceUuid, "remove_follower", targetUserId)
private suspend fun change(
csrfToken: String,
userId: Long,
deviceUuid: String,
action: String,
targetUserId: Long,
): FriendshipChangeResponse {
val form = mapOf(
"_csrftoken" to csrfToken,
"_uid" to userId,
"_uuid" to deviceUuid,
"radio_type" to "wifi-none",
"user_id" to targetUserId,
)
val signedForm = Utils.sign(form)
return repository.change(action, targetUserId, signedForm)
}
public long getUserId() {
return userId;
suspend fun changeMute(
csrfToken: String,
userId: Long,
deviceUuid: String,
unmute: Boolean,
targetUserId: Long,
story: Boolean, // true for story, false for posts
): FriendshipChangeResponse {
val form = mapOf(
"_csrftoken" to csrfToken,
"_uid" to userId.toString(),
"_uuid" to deviceUuid,
(if (story) "target_reel_author_id" else "target_posts_author_id") to targetUserId.toString(),
)
return repository.changeMute(
if (unmute) "unmute_posts_or_story_from_follow" else "mute_posts_or_story_from_follow",
form
)
}
public static FriendshipService getInstance(final String deviceUuid, final String csrfToken, final long userId) {
if (instance == null
|| !Objects.equals(instance.getCsrfToken(), csrfToken)
|| !Objects.equals(instance.getDeviceUuid(), deviceUuid)
|| !Objects.equals(instance.getUserId(), userId)) {
instance = new FriendshipService(deviceUuid, csrfToken, userId);
}
return instance;
suspend fun getList(
follower: Boolean,
targetUserId: Long,
maxId: String?,
): FriendshipListFetchResponse {
val queryMap = if (maxId != null) mapOf("max_id" to maxId) else emptyMap()
val response = repository.getList(targetUserId, if (follower) "followers" else "following", queryMap)
return parseListResponse(response)
}
public void follow(final long targetUserId,
final ServiceCallback<FriendshipChangeResponse> callback) {
change("create", targetUserId, callback);
@Throws(JSONException::class)
private fun parseListResponse(body: String): FriendshipListFetchResponse {
val root = JSONObject(body)
val nextMaxId = root.optString("next_max_id")
val status = root.optString("status")
val itemsJson = root.optJSONArray("users")
val items = parseItems(itemsJson)
return FriendshipListFetchResponse(
nextMaxId,
status,
items
)
}
public void unfollow(final long targetUserId,
final ServiceCallback<FriendshipChangeResponse> callback) {
change("destroy", targetUserId, callback);
}
public void changeBlock(final boolean unblock,
final long targetUserId,
final ServiceCallback<FriendshipChangeResponse> callback) {
change(unblock ? "unblock" : "block", targetUserId, callback);
}
public void toggleRestrict(final long targetUserId,
final boolean restrict,
final ServiceCallback<FriendshipRestrictResponse> callback) {
final Map<String, String> form = new HashMap<>(3);
form.put("_csrftoken", csrfToken);
form.put("_uuid", deviceUuid);
form.put("target_user_id", String.valueOf(targetUserId));
final String action = restrict ? "restrict" : "unrestrict";
final Call<FriendshipRestrictResponse> request = repository.toggleRestrict(action, form);
request.enqueue(new Callback<FriendshipRestrictResponse>() {
@Override
public void onResponse(@NonNull final Call<FriendshipRestrictResponse> call,
@NonNull final Response<FriendshipRestrictResponse> response) {
if (callback != null) {
callback.onSuccess(response.body());
}
}
@Override
public void onFailure(@NonNull final Call<FriendshipRestrictResponse> call,
@NonNull final Throwable t) {
if (callback != null) {
callback.onFailure(t);
}
}
});
}
public void approve(final long targetUserId,
final ServiceCallback<FriendshipChangeResponse> callback) {
change("approve", targetUserId, callback);
}
public void ignore(final long targetUserId,
final ServiceCallback<FriendshipChangeResponse> callback) {
change("ignore", targetUserId, callback);
}
public void removeFollower(final long targetUserId,
final ServiceCallback<FriendshipChangeResponse> callback) {
change("remove_follower", targetUserId, callback);
}
private void change(final String action,
final long targetUserId,
final ServiceCallback<FriendshipChangeResponse> callback) {
final Map<String, Object> form = new HashMap<>(5);
form.put("_csrftoken", csrfToken);
form.put("_uid", userId);
form.put("_uuid", deviceUuid);
form.put("radio_type", "wifi-none");
form.put("user_id", targetUserId);
final Map<String, String> signedForm = Utils.sign(form);
final Call<FriendshipChangeResponse> request = repository.change(action, targetUserId, signedForm);
request.enqueue(new Callback<FriendshipChangeResponse>() {
@Override
public void onResponse(@NonNull final Call<FriendshipChangeResponse> call,
@NonNull final Response<FriendshipChangeResponse> response) {
if (callback != null) {
callback.onSuccess(response.body());
}
}
@Override
public void onFailure(@NonNull final Call<FriendshipChangeResponse> call,
@NonNull final Throwable t) {
if (callback != null) {
callback.onFailure(t);
}
}
});
}
public void changeMute(final boolean unmute,
final long targetUserId,
final boolean story, // true for story, false for posts
final ServiceCallback<FriendshipChangeResponse> callback) {
final Map<String, String> form = new HashMap<>(4);
form.put("_csrftoken", csrfToken);
form.put("_uid", String.valueOf(userId));
form.put("_uuid", deviceUuid);
form.put(story ? "target_reel_author_id" : "target_posts_author_id", String.valueOf(targetUserId));
final Call<FriendshipChangeResponse> request = repository.changeMute(unmute ?
"unmute_posts_or_story_from_follow" :
"mute_posts_or_story_from_follow",
form);
request.enqueue(new Callback<FriendshipChangeResponse>() {
@Override
public void onResponse(@NonNull final Call<FriendshipChangeResponse> call,
@NonNull final Response<FriendshipChangeResponse> response) {
if (callback != null) {
callback.onSuccess(response.body());
}
}
@Override
public void onFailure(@NonNull final Call<FriendshipChangeResponse> call,
@NonNull final Throwable t) {
if (callback != null) {
callback.onFailure(t);
}
}
});
}
public void getList(final boolean follower,
final long targetUserId,
final String maxId,
final ServiceCallback<FriendshipListFetchResponse> callback) {
final Map<String, String> queryMap = new HashMap<>();
if (maxId != null) queryMap.put("max_id", maxId);
final Call<String> request = repository.getList(
targetUserId,
follower ? "followers" : "following",
queryMap);
request.enqueue(new Callback<String>() {
@Override
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) {
try {
if (callback == null) {
return;
}
final String body = response.body();
if (TextUtils.isEmpty(body)) {
callback.onSuccess(null);
return;
}
final FriendshipListFetchResponse friendshipListFetchResponse = parseListResponse(body);
callback.onSuccess(friendshipListFetchResponse);
} catch (JSONException e) {
Log.e(TAG, "onResponse", e);
callback.onFailure(e);
}
}
@Override
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) {
if (callback != null) {
callback.onFailure(t);
}
}
});
}
private FriendshipListFetchResponse parseListResponse(@NonNull final String body) throws JSONException {
final JSONObject root = new JSONObject(body);
final String nextMaxId = root.optString("next_max_id");
final String status = root.optString("status");
final JSONArray itemsJson = root.optJSONArray("users");
final List<FollowModel> items = parseItems(itemsJson);
return new FriendshipListFetchResponse(
nextMaxId,
status,
items
);
}
private List<FollowModel> parseItems(final JSONArray items) throws JSONException {
@Throws(JSONException::class)
private fun parseItems(items: JSONArray?): List<FollowModel> {
if (items == null) {
return Collections.emptyList();
return emptyList()
}
final List<FollowModel> followModels = new ArrayList<>();
for (int i = 0; i < items.length(); i++) {
final JSONObject itemJson = items.optJSONObject(i);
if (itemJson == null) {
continue;
}
final FollowModel followModel = new FollowModel(itemJson.getString("pk"),
itemJson.getString("username"),
itemJson.optString("full_name"),
itemJson.getString("profile_pic_url"));
if (followModel != null) {
followModels.add(followModel);
}
val followModels = mutableListOf<FollowModel>()
for (i in 0 until items.length()) {
val itemJson = items.optJSONObject(i) ?: continue
val followModel = FollowModel(itemJson.getString("pk"),
itemJson.getString("username"),
itemJson.optString("full_name"),
itemJson.getString("profile_pic_url"))
followModels.add(followModel)
}
return followModels;
return followModels
}
}
}