package app.fedilab.android.mastodon.viewmodel.mastodon; /* Copyright 2021 Thomas Schneider * * This file is a part of Fedilab * * This program is free software; you can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; either version 3 of the * License, or (at your option) any later version. * * Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * You should have received a copy of the GNU General Public License along with Fedilab; if not, * see . */ import static app.fedilab.android.BaseMainActivity.currentAccount; import android.app.Application; import android.net.Uri; import android.os.Handler; import android.os.Looper; import androidx.annotation.NonNull; import androidx.lifecycle.AndroidViewModel; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; import java.net.IDN; import java.util.LinkedHashMap; import java.util.List; import app.fedilab.android.R; import app.fedilab.android.activities.MainActivity; import app.fedilab.android.mastodon.activities.ProfileActivity; import app.fedilab.android.mastodon.client.endpoints.MastodonAccountsService; import app.fedilab.android.mastodon.client.entities.api.Account; import app.fedilab.android.mastodon.client.entities.api.Accounts; import app.fedilab.android.mastodon.client.entities.api.Domains; import app.fedilab.android.mastodon.client.entities.api.FamiliarFollowers; import app.fedilab.android.mastodon.client.entities.api.FeaturedTag; import app.fedilab.android.mastodon.client.entities.api.Field; import app.fedilab.android.mastodon.client.entities.api.Filter; import app.fedilab.android.mastodon.client.entities.api.IdentityProof; import app.fedilab.android.mastodon.client.entities.api.MastodonList; import app.fedilab.android.mastodon.client.entities.api.Pagination; import app.fedilab.android.mastodon.client.entities.api.Preferences; import app.fedilab.android.mastodon.client.entities.api.RelationShip; import app.fedilab.android.mastodon.client.entities.api.Report; import app.fedilab.android.mastodon.client.entities.api.Source; import app.fedilab.android.mastodon.client.entities.api.Status; import app.fedilab.android.mastodon.client.entities.api.Statuses; import app.fedilab.android.mastodon.client.entities.api.Suggestion; import app.fedilab.android.mastodon.client.entities.api.Suggestions; import app.fedilab.android.mastodon.client.entities.api.Tag; import app.fedilab.android.mastodon.client.entities.api.Token; import app.fedilab.android.mastodon.client.entities.app.BaseAccount; import app.fedilab.android.mastodon.client.entities.app.CachedBundle; import app.fedilab.android.mastodon.client.entities.app.MutedAccounts; import app.fedilab.android.mastodon.client.entities.app.StatusCache; import app.fedilab.android.mastodon.exception.DBException; import app.fedilab.android.mastodon.helper.Helper; import app.fedilab.android.mastodon.helper.MastodonHelper; import app.fedilab.android.mastodon.ui.drawer.StatusAdapter; import okhttp3.MultipartBody; import okhttp3.OkHttpClient; import retrofit2.Call; import retrofit2.Response; import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; public class AccountsVM extends AndroidViewModel { final OkHttpClient okHttpClient = Helper.myOkHttpClient(getApplication().getApplicationContext()); private MutableLiveData accountMutableLiveData; private MutableLiveData> accountListMutableLiveData; private MutableLiveData suggestionsMutableLiveData; private MutableLiveData statusesMutableLiveData; private MutableLiveData accountsMutableLiveData; private MutableLiveData> statusListMutableLiveData; private MutableLiveData featuredTagMutableLiveData; private MutableLiveData> featuredTagListMutableLiveData; private MutableLiveData> mastodonListListMutableLiveData; private MutableLiveData> identityProofListMutableLiveData; private MutableLiveData relationShipMutableLiveData; private MutableLiveData> relationShipListMutableLiveData; private MutableLiveData> familiarFollowersListMutableLiveData; private MutableLiveData filterMutableLiveData; private MutableLiveData> filterListMutableLiveData; private MutableLiveData> tagListMutableLiveData; private MutableLiveData preferencesMutableLiveData; private MutableLiveData tokenMutableLiveData; private MutableLiveData domainsMutableLiveData; private MutableLiveData reportMutableLiveData; private MutableLiveData booleanMutableLiveData; public AccountsVM(@NonNull Application application) { super(application); } private MastodonAccountsService init(String instance) { Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://" + (instance != null ? IDN.toASCII(instance, IDN.ALLOW_UNASSIGNED) : null) + "/api/v1/") .addConverterFactory(GsonConverterFactory.create(Helper.getDateBuilder())) .client(okHttpClient) .build(); return retrofit.create(MastodonAccountsService.class); } private MastodonAccountsService initv2(String instance) { Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://" + (instance != null ? IDN.toASCII(instance, IDN.ALLOW_UNASSIGNED) : null) + "/api/v2/") .addConverterFactory(GsonConverterFactory.create(Helper.getDateBuilder())) .client(okHttpClient) .build(); return retrofit.create(MastodonAccountsService.class); } /** * Get connected account * * @return LiveData */ public LiveData getConnectedAccount(@NonNull String instance, String token) { MastodonAccountsService mastodonAccountsService = init(instance); accountMutableLiveData = new MutableLiveData<>(); new Thread(() -> { Account account = null; Call accountCall = mastodonAccountsService.verify_credentials(token); if (accountCall != null) { try { Response accountResponse = accountCall.execute(); if (accountResponse.isSuccessful()) { account = accountResponse.body(); } } catch (Exception e) { e.printStackTrace(); } } Handler mainHandler = new Handler(Looper.getMainLooper()); Account finalAccount = account; Runnable myRunnable = () -> accountMutableLiveData.setValue(finalAccount); mainHandler.post(myRunnable); }).start(); return accountMutableLiveData; } /** * Register an Account * * @param username String * @param email String * @param password String * @param agreement boolean * @param locale boolean * @param reason String * @return Token - {@link Token} */ public LiveData registerAccount(@NonNull String instance, String token, @NonNull String username, @NonNull String email, @NonNull String password, boolean agreement, @NonNull String locale, String reason) { tokenMutableLiveData = new MutableLiveData<>(); new Thread(() -> { MastodonAccountsService mastodonAccountsService = init(instance); Call stringCall = mastodonAccountsService.registerAccount(token, username, email, password, agreement, locale, reason); Token returnedToken = null; String errorMessage = null; if (stringCall != null) { try { Response stringResponse = stringCall.execute(); if (stringResponse.isSuccessful()) { returnedToken = stringResponse.body(); } else { if (stringResponse.errorBody() != null) { errorMessage = stringResponse.errorBody().string(); } } } catch (Exception e) { e.printStackTrace(); errorMessage = e.getMessage() != null ? e.getMessage() : getApplication().getString(R.string.toast_error); } } Handler mainHandler = new Handler(Looper.getMainLooper()); Token finalReturnedToken = returnedToken; String finalErrorMessage = errorMessage; Runnable myRunnable = () -> { if (finalErrorMessage != null) { Helper.sendToastMessage(getApplication(), Helper.RECEIVE_TOAST_TYPE_ERROR, finalErrorMessage); } tokenMutableLiveData.setValue(finalReturnedToken); }; mainHandler.post(myRunnable); }).start(); return tokenMutableLiveData; } /** * Allow to only upload avatar or header when editing profile * * @return {@link LiveData} containing an {@link Account} */ public LiveData updateProfilePicture(@NonNull String instance, String token, Uri uri, UpdateMediaType type) { MastodonAccountsService mastodonAccountsService = init(instance); accountMutableLiveData = new MutableLiveData<>(); new Thread(() -> { Account account = null; MultipartBody.Part avatarMultipartBody = null; MultipartBody.Part headerMultipartBody = null; if (type == UpdateMediaType.AVATAR) { avatarMultipartBody = Helper.getMultipartBody(getApplication(), "avatar", uri); } else if (type == UpdateMediaType.HEADER) { headerMultipartBody = Helper.getMultipartBody(getApplication(), "header", uri); } Call accountCall = mastodonAccountsService.update_media( token, avatarMultipartBody, headerMultipartBody); if (accountCall != null) { try { Response accountResponse = accountCall.execute(); if (accountResponse.isSuccessful()) { account = accountResponse.body(); } } catch (Exception e) { e.printStackTrace(); } } Handler mainHandler = new Handler(Looper.getMainLooper()); Account finalAccount = account; Runnable myRunnable = () -> accountMutableLiveData.setValue(finalAccount); mainHandler.post(myRunnable); }).start(); return accountMutableLiveData; } /** * Update account credentials * * @param discoverable Whether the account should be shown in the profile directory. * @param bot Whether the account has a bot flag. * @param displayName The display name to use for the profile. * @param note The account bio. * @param locked Whether manual approval of follow requests is required. * @param privacy Default post privacy for authored statuses. * @param sensitive Whether to mark authored statuses as sensitive by default. * @param language Default language to use for authored statuses. (ISO 6391) * @param fields Profile metadata name (By default, max 4 fields and 255 characters per property/value) * @return {@link LiveData} containing an {@link Account} */ public LiveData updateCredentials(@NonNull String instance, String token, Boolean discoverable, Boolean bot, String displayName, String note, Boolean locked, String privacy, Boolean sensitive, String language, LinkedHashMap fields ) { MastodonAccountsService mastodonAccountsService = init(instance); accountMutableLiveData = new MutableLiveData<>(); new Thread(() -> { Account account = null; Account.AccountParams accountParams = new Account.AccountParams(); accountParams.bot = bot; accountParams.discoverable = discoverable; accountParams.display_name = displayName; accountParams.note = note; accountParams.locked = locked; accountParams.source = new Source.SourceParams(); accountParams.source.privacy = privacy; accountParams.source.language = language; accountParams.source.sensitive = sensitive; accountParams.fields = fields; Call accountCall = mastodonAccountsService.update_credentials(token, accountParams); // Call accountCall = mastodonAccountsService.update_credentials(token, discoverable, bot, displayName, note, locked, privacy, sensitive, language, fields); if (accountCall != null) { try { Response accountResponse = accountCall.execute(); if (accountResponse.isSuccessful()) { account = accountResponse.body(); } } catch (Exception e) { e.printStackTrace(); } } Handler mainHandler = new Handler(Looper.getMainLooper()); Account finalAccount = account; Runnable myRunnable = () -> accountMutableLiveData.setValue(finalAccount); mainHandler.post(myRunnable); }).start(); return accountMutableLiveData; } /** * @param acct The acct of the account * @return {@link LiveData} containing an {@link Account} */ public LiveData lookUpAccount(@NonNull String instance, @NonNull String acct) { accountMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { Account account = null; Call accountCall = mastodonAccountsService.lookUpAccount(acct); if (accountCall != null) { try { Response accountResponse = accountCall.execute(); if (accountResponse.isSuccessful()) { account = accountResponse.body(); } } catch (Exception e) { e.printStackTrace(); } } Account finalAccount = account; Handler mainHandler = new Handler(Looper.getMainLooper()); Runnable myRunnable = () -> accountMutableLiveData.setValue(finalAccount); mainHandler.post(myRunnable); }).start(); return accountMutableLiveData; } /** * @param id The id of the account * @return {@link LiveData} containing an {@link Account} */ public LiveData getAccount(@NonNull String instance, String token, @NonNull String id) { accountMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { Account account = null; Call accountCall = mastodonAccountsService.getAccount(token, id); if (accountCall != null) { try { Response accountResponse = accountCall.execute(); if (accountResponse.isSuccessful()) { account = accountResponse.body(); new CachedBundle(getApplication().getApplicationContext()).insertAccountBundle(account, currentAccount); } } catch (Exception e) { e.printStackTrace(); } } Account finalAccount = account; Handler mainHandler = new Handler(Looper.getMainLooper()); Runnable myRunnable = () -> accountMutableLiveData.setValue(finalAccount); mainHandler.post(myRunnable); }).start(); return accountMutableLiveData; } /** * Statuses posted to the given account. * * @param id The id of the account * @return {@link LiveData} containing a {@link Statuses}. Note: Not to be confused with {@link Status} */ public LiveData getAccountStatuses(@NonNull String instance, String token, @NonNull String id, String maxId, String sinceId, String minId, Boolean excludeReplies, Boolean excludeReblogs, Boolean only_media, Boolean pinned, int count) { statusesMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { List statusList = null; Pagination pagination = null; Call> accountStatusesCall = mastodonAccountsService.getAccountStatuses( token, id, maxId, sinceId, minId, excludeReplies, excludeReblogs, only_media, pinned, count); if (accountStatusesCall != null) { try { Response> accountStatusesResponse = accountStatusesCall.execute(); if (accountStatusesResponse.isSuccessful()) { statusList = accountStatusesResponse.body(); pagination = MastodonHelper.getPagination(accountStatusesResponse.headers()); } } catch (Exception e) { e.printStackTrace(); } } Statuses statuses = new Statuses(); statuses.statuses = statusList; statuses.pagination = pagination; Handler mainHandler = new Handler(Looper.getMainLooper()); Runnable myRunnable = () -> statusesMutableLiveData.setValue(statuses); mainHandler.post(myRunnable); }).start(); return statusesMutableLiveData; } /** * Accounts which follow the given account, if network is not hidden by the account owner. * * @return {@link LiveData} containing an {@link Accounts}. Note: Not to be confused with {@link Account} */ public LiveData getAccountFollowers(@NonNull String instance, String token, @NonNull String id, String maxId, String sinceId) { accountsMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { List accountList = null; Pagination pagination = null; Call> followersCall = mastodonAccountsService.getAccountFollowers(token, id, maxId, sinceId); if (followersCall != null) { try { Response> followersResponse = followersCall.execute(); if (followersResponse.isSuccessful()) { accountList = followersResponse.body(); pagination = MastodonHelper.getPagination(followersResponse.headers()); } } catch (Exception e) { e.printStackTrace(); } } Accounts accounts = new Accounts(); accounts.accounts = accountList; accounts.pagination = pagination; Handler mainHandler = new Handler(Looper.getMainLooper()); Runnable myRunnable = () -> accountsMutableLiveData.setValue(accounts); mainHandler.post(myRunnable); }).start(); return accountsMutableLiveData; } /** * Accounts which the given account is following, if network is not hidden by the account owner. * * @param id The id of the account * @return {@link LiveData} containing an {@link Accounts}. Note: Not to be confused with {@link Account} */ public LiveData getAccountFollowing(@NonNull String instance, String token, @NonNull String id, String maxId, String sinceId) { accountsMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { List accountList = null; Pagination pagination = null; Call> followingCall = mastodonAccountsService.getAccountFollowing(token, id, maxId, sinceId); if (followingCall != null) { try { Response> followingResponse = followingCall.execute(); if (followingResponse.isSuccessful()) { accountList = followingResponse.body(); pagination = MastodonHelper.getPagination(followingResponse.headers()); } } catch (Exception e) { e.printStackTrace(); } } Accounts accounts = new Accounts(); accounts.accounts = accountList; accounts.pagination = pagination; Handler mainHandler = new Handler(Looper.getMainLooper()); Runnable myRunnable = () -> accountsMutableLiveData.setValue(accounts); mainHandler.post(myRunnable); }).start(); return accountsMutableLiveData; } /** * Tags featured by this account. * * @param id The id of the account * @return {@link LiveData} containing a {@link List} of {@link FeaturedTag}s */ public LiveData> getAccountFeaturedTags(@NonNull String instance, String token, @NonNull String id) { featuredTagListMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { List featuredTagList = null; Call> featuredTagsCall = mastodonAccountsService.getAccountFeaturedTags(token, id); if (featuredTagsCall != null) { try { Response> featuredTagsResponse = featuredTagsCall.execute(); if (featuredTagsResponse.isSuccessful()) { featuredTagList = featuredTagsResponse.body(); } } catch (Exception e) { e.printStackTrace(); } } Handler mainHandler = new Handler(Looper.getMainLooper()); List finalFeaturedTagList = featuredTagList; Runnable myRunnable = () -> featuredTagListMutableLiveData.setValue(finalFeaturedTagList); mainHandler.post(myRunnable); }).start(); return featuredTagListMutableLiveData; } /** * User lists that you have added this account to. * * @param id The id of the account * @return {@link LiveData} containing a {@link List} of {@link MastodonList}s */ public LiveData> getListContainingAccount(@NonNull String instance, String token, @NonNull String id) { mastodonListListMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { List mastodonListList = null; Call> listsCall = mastodonAccountsService.getListContainingAccount(token, id); if (listsCall != null) { try { Response> listsResponse = listsCall.execute(); if (listsResponse.isSuccessful()) { mastodonListList = listsResponse.body(); } } catch (Exception e) { e.printStackTrace(); } } Handler mainHandler = new Handler(Looper.getMainLooper()); List finalMastodonListList = mastodonListList; Runnable myRunnable = () -> mastodonListListMutableLiveData.setValue(finalMastodonListList); mainHandler.post(myRunnable); }).start(); return mastodonListListMutableLiveData; } /** * List of IdentityProofs * * @param id The id of the account * @return {@link LiveData} containing a {@link List} of {@link IdentityProof}s of the given account */ public LiveData> getIdentityProofs(@NonNull String instance, String token, @NonNull String id) { identityProofListMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { List identityProofList = null; Call> identityProofsCall = mastodonAccountsService.getIdentityProofs(token, id); if (identityProofsCall != null) { try { Response> identityProofsResponse = identityProofsCall.execute(); if (identityProofsResponse.isSuccessful()) { identityProofList = identityProofsResponse.body(); } } catch (Exception e) { e.printStackTrace(); } } Handler mainHandler = new Handler(Looper.getMainLooper()); List finalIdentityProofList = identityProofList; Runnable myRunnable = () -> identityProofListMutableLiveData.setValue(finalIdentityProofList); mainHandler.post(myRunnable); }).start(); return identityProofListMutableLiveData; } /** * Update account notes * * @param id The id of the account * @param commment note for the account * @return {@link LiveData} containing the {@link RelationShip} to the given account */ public LiveData updateNote(@NonNull String instance, String token, @NonNull String id, String commment) { relationShipMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { RelationShip relationShip = null; Call noteCall = mastodonAccountsService.note(token, id, commment); if (noteCall != null) { try { Response followResponse = noteCall.execute(); if (followResponse.isSuccessful()) { relationShip = followResponse.body(); } } catch (Exception e) { e.printStackTrace(); } } Handler mainHandler = new Handler(Looper.getMainLooper()); RelationShip finalRelationShip = relationShip; Runnable myRunnable = () -> relationShipMutableLiveData.setValue(finalRelationShip); mainHandler.post(myRunnable); }).start(); return relationShipMutableLiveData; } /** * Follow the given account. Can also be used to update whether to show reblogs or enable notifications. * * @param id The id of the account * @param reblogs Receive this account's reblogs in home timeline? Defaults to true. * @param notify Receive notifications when this account posts a status? Defaults to false. * @param languages Filter received statuses for these languages. * @return {@link LiveData} containing the {@link RelationShip} to the given account */ public LiveData follow(@NonNull String instance, String token, @NonNull String id, boolean reblogs, boolean notify, List languages) { relationShipMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { RelationShip relationShip = null; Call followCall = mastodonAccountsService.follow(token, id, reblogs, notify, languages); if (followCall != null) { try { Response followResponse = followCall.execute(); if (followResponse.isSuccessful()) { relationShip = followResponse.body(); } } catch (Exception e) { e.printStackTrace(); } } Handler mainHandler = new Handler(Looper.getMainLooper()); RelationShip finalRelationShip = relationShip; Runnable myRunnable = () -> relationShipMutableLiveData.setValue(finalRelationShip); mainHandler.post(myRunnable); }).start(); return relationShipMutableLiveData; } /** * Unfollow the given account. * * @param id The id of the account * @return {@link LiveData} containing the {@link RelationShip} to the given account */ public LiveData unfollow(@NonNull String instance, String token, @NonNull String id) { relationShipMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { RelationShip relationShip = null; Call unfollowCall = mastodonAccountsService.unfollow(token, id); if (unfollowCall != null) { try { Response unfollowResponse = unfollowCall.execute(); if (unfollowResponse.isSuccessful()) { relationShip = unfollowResponse.body(); } } catch (Exception e) { e.printStackTrace(); } } Handler mainHandler = new Handler(Looper.getMainLooper()); RelationShip finalRelationShip = relationShip; Runnable myRunnable = () -> relationShipMutableLiveData.setValue(finalRelationShip); mainHandler.post(myRunnable); }).start(); return relationShipMutableLiveData; } /** * Block the given account. Clients should filter statuses from this account if received (e.g. due to a boost in the Home timeline) * * @param id The id of the account * @return {@link LiveData} containing the {@link RelationShip} to the given account */ public LiveData block(@NonNull String instance, String token, @NonNull String id) { relationShipMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { RelationShip relationShip = null; Call blockCall = mastodonAccountsService.block(token, id); if (blockCall != null) { try { Response blockResponse = blockCall.execute(); if (blockResponse.isSuccessful()) { relationShip = blockResponse.body(); StatusAdapter.sendAction(getApplication().getApplicationContext(), Helper.ARG_DELETE_ALL_FOR_ACCOUNT_ID, null, id); new StatusCache(getApplication().getApplicationContext()).deleteStatusForTargetedAccount(MainActivity.currentInstance, MainActivity.currentUserID, id); } } catch (Exception e) { e.printStackTrace(); } Handler mainHandler = new Handler(Looper.getMainLooper()); RelationShip finalRelationShip = relationShip; Runnable myRunnable = () -> relationShipMutableLiveData.setValue(finalRelationShip); mainHandler.post(myRunnable); } }).start(); return relationShipMutableLiveData; } /** * Unblock the given account. * * @param id The id of the account * @return {@link LiveData} containing the {@link RelationShip} to the given account */ public LiveData unblock(@NonNull String instance, String token, @NonNull String id) { relationShipMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { RelationShip relationShip = null; Call unblockCall = mastodonAccountsService.unblock(token, id); if (unblockCall != null) { try { Response unblockResponse = unblockCall.execute(); if (unblockResponse.isSuccessful()) { relationShip = unblockResponse.body(); } } catch (Exception e) { e.printStackTrace(); } Handler mainHandler = new Handler(Looper.getMainLooper()); RelationShip finalRelationShip = relationShip; Runnable myRunnable = () -> relationShipMutableLiveData.setValue(finalRelationShip); mainHandler.post(myRunnable); } }).start(); return relationShipMutableLiveData; } /** * Mute the given account. Clients should filter statuses and notifications from this account, if received (e.g. due to a boost in the Home timeline). * * @param id The id of the account * @param notifications Mute notifications in addition to statuses? Defaults to true. * @param duration How long the mute should last, in seconds. Defaults to 0 (indefinite). * @return {@link LiveData} containing the {@link RelationShip} to the given account */ public LiveData mute(@NonNull String instance, String token, @NonNull String id, Boolean notifications, Integer duration) { relationShipMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { RelationShip relationShip = null; Call muteCall = mastodonAccountsService.mute(token, id, notifications, duration); if (muteCall != null) { try { Response muteResponse = muteCall.execute(); if (muteResponse.isSuccessful()) { relationShip = muteResponse.body(); StatusAdapter.sendAction(getApplication().getApplicationContext(), Helper.ARG_DELETE_ALL_FOR_ACCOUNT_ID, null, id); new StatusCache(getApplication().getApplicationContext()).deleteStatusForTargetedAccount(MainActivity.currentInstance, MainActivity.currentUserID, id); } } catch (Exception e) { e.printStackTrace(); } Handler mainHandler = new Handler(Looper.getMainLooper()); RelationShip finalRelationShip = relationShip; Runnable myRunnable = () -> relationShipMutableLiveData.setValue(finalRelationShip); mainHandler.post(myRunnable); } }).start(); return relationShipMutableLiveData; } /** * Mute the given account in db * * @return {@link LiveData} containing the {@link Account} to the given account */ public LiveData getMutedHome(@NonNull BaseAccount forAccount) { accountsMutableLiveData = new MutableLiveData<>(); new Thread(() -> { Accounts accounts = new Accounts(); MutedAccounts mutedAccount; try { mutedAccount = new MutedAccounts(getApplication().getApplicationContext()).getMutedAccount(forAccount); if (mutedAccount != null) { accounts.accounts = mutedAccount.accounts; } accounts.pagination = new Pagination(); } catch (DBException e) { e.printStackTrace(); } Handler mainHandler = new Handler(Looper.getMainLooper()); Runnable myRunnable = () -> accountsMutableLiveData.setValue(accounts); mainHandler.post(myRunnable); }).start(); return accountsMutableLiveData; } /** * Mute the given account in db * * @return {@link LiveData} containing the {@link Account} to the given account */ public LiveData isMuted(@NonNull BaseAccount forAccount, @NonNull Account target) { booleanMutableLiveData = new MutableLiveData<>(); new Thread(() -> { boolean isMuted = false; try { isMuted = new MutedAccounts(getApplication().getApplicationContext()).isMuted(forAccount, target); } catch (DBException e) { e.printStackTrace(); } Handler mainHandler = new Handler(Looper.getMainLooper()); boolean finalIsMuted = isMuted; Runnable myRunnable = () -> booleanMutableLiveData.setValue(finalIsMuted); mainHandler.post(myRunnable); }).start(); return booleanMutableLiveData; } /** * Mute the given account in db * * @return {@link LiveData} containing the {@link Account} to the given account */ public LiveData muteHome(@NonNull BaseAccount forAccount, @NonNull Account target) { accountMutableLiveData = new MutableLiveData<>(); new Thread(() -> { try { new MutedAccounts(getApplication().getApplicationContext()).muteAccount(forAccount, target); Helper.addMutedAccount(target); } catch (DBException e) { e.printStackTrace(); } Handler mainHandler = new Handler(Looper.getMainLooper()); StatusAdapter.sendAction(getApplication().getApplicationContext(), Helper.ARG_STATUS_ACCOUNT_ID_DELETED, null, target.id); Runnable myRunnable = () -> accountMutableLiveData.setValue(target); mainHandler.post(myRunnable); }).start(); return accountMutableLiveData; } /** * Mute the given account in db * * @return {@link LiveData} containing the {@link Account} to the given account */ public LiveData> muteAccountsHome(@NonNull BaseAccount forAccount, @NonNull List targets) { accountListMutableLiveData = new MutableLiveData<>(); new Thread(() -> { try { for (Account target : targets) { new MutedAccounts(getApplication().getApplicationContext()).muteAccount(forAccount, target); StatusAdapter.sendAction(getApplication().getApplicationContext(), Helper.ARG_STATUS_ACCOUNT_ID_DELETED, null, target.id); Helper.addMutedAccount(target); } } catch (DBException e) { e.printStackTrace(); } Handler mainHandler = new Handler(Looper.getMainLooper()); Runnable myRunnable = () -> accountListMutableLiveData.setValue(targets); mainHandler.post(myRunnable); }).start(); return accountListMutableLiveData; } /** * Unmute the given account in db * * @return {@link LiveData} containing the {@link Account} to the given account */ public LiveData unmuteHome(@NonNull BaseAccount forAccount, @NonNull Account target) { accountMutableLiveData = new MutableLiveData<>(); new Thread(() -> { try { new MutedAccounts(getApplication().getApplicationContext()).unMuteAccount(forAccount, target); Helper.removeMutedAccount(target); } catch (DBException e) { e.printStackTrace(); } Handler mainHandler = new Handler(Looper.getMainLooper()); Runnable myRunnable = () -> accountMutableLiveData.setValue(target); mainHandler.post(myRunnable); }).start(); return accountMutableLiveData; } /** * Unmute the given account. * * @param id The id of the account * @return {@link LiveData} containing the {@link RelationShip} to the given account */ public LiveData unmute(@NonNull String instance, String token, @NonNull String id) { relationShipMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { RelationShip relationShip = null; Call unmuteCall = mastodonAccountsService.unmute(token, id); if (unmuteCall != null) { try { Response unmuteResponse = unmuteCall.execute(); if (unmuteResponse.isSuccessful()) { relationShip = unmuteResponse.body(); } } catch (Exception e) { e.printStackTrace(); } Handler mainHandler = new Handler(Looper.getMainLooper()); RelationShip finalRelationShip = relationShip; Runnable myRunnable = () -> relationShipMutableLiveData.setValue(finalRelationShip); mainHandler.post(myRunnable); } }).start(); return relationShipMutableLiveData; } /** * Add the given account to the user's featured profiles. (Featured profiles are currently shown on the user's own public profile.) * * @param id The id of the account * @return {@link LiveData} containing the {@link RelationShip} to the given account */ public LiveData endorse(@NonNull String instance, String token, @NonNull String id) { relationShipMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { RelationShip relationShip = null; Call endorseCall = mastodonAccountsService.endorse(token, id); if (endorseCall != null) { try { Response endorseResponse = endorseCall.execute(); if (endorseResponse.isSuccessful()) { relationShip = endorseResponse.body(); } } catch (Exception e) { e.printStackTrace(); } Handler mainHandler = new Handler(Looper.getMainLooper()); RelationShip finalRelationShip = relationShip; Runnable myRunnable = () -> relationShipMutableLiveData.setValue(finalRelationShip); mainHandler.post(myRunnable); } }).start(); return relationShipMutableLiveData; } /** * Remove the given account from the user's featured profiles. * * @param id The id of the account * @return {@link LiveData} containing the {@link RelationShip} to the given account */ public LiveData unendorse(@NonNull String instance, String token, @NonNull String id) { relationShipMutableLiveData = new MutableLiveData<>(); new Thread(() -> { RelationShip relationShip = null; MastodonAccountsService mastodonAccountsService = init(instance); Call unendorseCall = mastodonAccountsService.unendorse(token, id); if (unendorseCall != null) { try { Response unendorseResponse = unendorseCall.execute(); if (unendorseResponse.isSuccessful()) { relationShip = unendorseResponse.body(); } } catch (Exception e) { e.printStackTrace(); } Handler mainHandler = new Handler(Looper.getMainLooper()); RelationShip finalRelationShip = relationShip; Runnable myRunnable = () -> relationShipMutableLiveData.setValue(finalRelationShip); mainHandler.post(myRunnable); } }).start(); return relationShipMutableLiveData; } /** * Sets a private note on a user. * * @param id The id of the account * @param comment The comment to be set on that user. Provide an empty string or leave out this parameter to clear the currently set note. * @return {@link LiveData} containing the {@link RelationShip} to the given account */ public LiveData note(@NonNull String instance, String token, @NonNull String id, String comment) { relationShipMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { RelationShip relationShip = null; Call noteCall = mastodonAccountsService.note(token, id, comment); if (noteCall != null) { try { Response noteResponse = noteCall.execute(); if (noteResponse.isSuccessful()) { relationShip = noteResponse.body(); } } catch (Exception e) { e.printStackTrace(); } Handler mainHandler = new Handler(Looper.getMainLooper()); RelationShip finalRelationShip = relationShip; Runnable myRunnable = () -> relationShipMutableLiveData.setValue(finalRelationShip); mainHandler.post(myRunnable); } }).start(); return relationShipMutableLiveData; } /** * Find out whether a given account is followed, blocked, muted, etc. * * @param ids {@link List} of account IDs to check * @return {@link LiveData} containing a {@link List} of {@link RelationShip}s to given account(s) */ public LiveData> getRelationships(@NonNull String instance, String token, @NonNull List ids) { relationShipListMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { List relationShipList = null; Call> relationshipsCall = mastodonAccountsService.getRelationships(token, ids); if (relationshipsCall != null) { try { Response> relationshipsResponse = relationshipsCall.execute(); if (relationshipsResponse.isSuccessful()) { relationShipList = relationshipsResponse.body(); } } catch (Exception e) { e.printStackTrace(); } } Handler mainHandler = new Handler(Looper.getMainLooper()); List finalRelationShipList = relationShipList; Runnable myRunnable = () -> relationShipListMutableLiveData.setValue(finalRelationShipList); mainHandler.post(myRunnable); }).start(); return relationShipListMutableLiveData; } /** * Obtain a list of all accounts that follow a given account, filtered for accounts you follow. * * @param ids {@link List} of account IDs to check * @return {@link LiveData} containing a {@link List} of {@link FamiliarFollowers}s to given account(s) */ public LiveData> getFamiliarFollowers(@NonNull String instance, String token, @NonNull List ids) { familiarFollowersListMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { List familiarFollowers = null; Call> familiarFollowersCall = mastodonAccountsService.getFamiliarFollowers(token, ids); if (familiarFollowersCall != null) { try { Response> familiarFollowersResponse = familiarFollowersCall.execute(); if (familiarFollowersResponse.isSuccessful()) { familiarFollowers = familiarFollowersResponse.body(); } } catch (Exception e) { e.printStackTrace(); } } Handler mainHandler = new Handler(Looper.getMainLooper()); List finalFamiliarFollowers = familiarFollowers; Runnable myRunnable = () -> familiarFollowersListMutableLiveData.setValue(finalFamiliarFollowers); mainHandler.post(myRunnable); }).start(); return familiarFollowersListMutableLiveData; } /** * Search for matching accounts by username or display name. * * @param q What to search for * @param limit Maximum number of results. Defaults to 40. * @param resolve Attempt WebFinger lookup. Defaults to false. Use this when q is an exact address. * @param following Only who the user is following. Defaults to false. * @return {@link LiveData} containing a {@link List} of matching {@link Account}s */ public LiveData> searchAccounts(@NonNull String instance, String token, @NonNull String q, int limit, boolean resolve, boolean following) { accountListMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { List accountList = null; Call> searchCall = mastodonAccountsService.searchAccounts(token, q, limit, resolve, following); if (searchCall != null) { try { Response> searchResponse = searchCall.execute(); if (searchResponse.isSuccessful()) { accountList = searchResponse.body(); if(accountList != null && accountList.size() > 0 ) { new CachedBundle(getApplication().getApplicationContext()).insertAccountBundle(accountList.get(0), currentAccount); } } } catch (Exception e) { e.printStackTrace(); } } List finalAccountList = accountList; Handler mainHandler = new Handler(Looper.getMainLooper()); Runnable myRunnable = () -> accountListMutableLiveData.setValue(finalAccountList); mainHandler.post(myRunnable); }).start(); return accountListMutableLiveData; } /** * Statuses the user has bookmarked. * * @return {@link LiveData} containing a {@link List} of {@link Status}es */ public LiveData getBookmarks(@NonNull String instance, String token, String limit, String maxId, String sinceId, String minId) { statusesMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { List statusList; Statuses statuses = new Statuses(); Call> bookmarksCall = mastodonAccountsService.getBookmarks(token, limit, maxId, sinceId, minId); if (bookmarksCall != null) { try { Response> bookmarksResponse = bookmarksCall.execute(); if (bookmarksResponse.isSuccessful()) { statusList = bookmarksResponse.body(); statuses.statuses = statusList; statuses.pagination = MastodonHelper.getPagination(bookmarksResponse.headers()); } } catch (Exception e) { e.printStackTrace(); } } Handler mainHandler = new Handler(Looper.getMainLooper()); Runnable myRunnable = () -> statusesMutableLiveData.setValue(statuses); mainHandler.post(myRunnable); }).start(); return statusesMutableLiveData; } /** * Statuses the user has favourited. * * @return {@link LiveData} containing a {@link List} of {@link Status}es */ public LiveData getFavourites(@NonNull String instance, String token, String limit, String minId, String maxId) { statusesMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { Statuses statuses = new Statuses(); Call> favouritesCall = mastodonAccountsService.getFavourites(token, limit, minId, maxId); List statusList; if (favouritesCall != null) { try { Response> favouritesResponse = favouritesCall.execute(); if (favouritesResponse.isSuccessful()) { statusList = favouritesResponse.body(); statuses.statuses = statusList; statuses.pagination = MastodonHelper.getPagination(favouritesResponse.headers()); } } catch (Exception e) { e.printStackTrace(); } } Handler mainHandler = new Handler(Looper.getMainLooper()); Runnable myRunnable = () -> statusesMutableLiveData.setValue(statuses); mainHandler.post(myRunnable); }).start(); return statusesMutableLiveData; } /** * Accounts the user has muted. * * @param limit Maximum number of results to return per page. Defaults to 40. * @return {@link LiveData} containing a {@link List} of {@link Account}s */ public LiveData getMutes(@NonNull String instance, String token, String limit, String maxId, String sinceId) { accountsMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { Accounts accounts = new Accounts(); Call> mutesCall = mastodonAccountsService.getMutes(token, limit, maxId, sinceId); List accountList; if (mutesCall != null) { try { Response> mutesResponse = mutesCall.execute(); if (mutesResponse.isSuccessful()) { accountList = mutesResponse.body(); accounts.accounts = accountList; accounts.pagination = MastodonHelper.getPagination(mutesResponse.headers()); } } catch (Exception e) { e.printStackTrace(); } } Handler mainHandler = new Handler(Looper.getMainLooper()); Runnable myRunnable = () -> accountsMutableLiveData.setValue(accounts); mainHandler.post(myRunnable); }).start(); return accountsMutableLiveData; } /** * Accounts the user has blocked. * * @param limit Maximum number of results. Defaults to 40. * @return {@link LiveData} containing a {@link List} of {@link Account}s */ public LiveData getBlocks(@NonNull String instance, String token, String limit, String maxId, String sinceId) { accountsMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { List accountList; Accounts accounts = new Accounts(); Call> blocksCall = mastodonAccountsService.getBlocks(token, limit, maxId, sinceId); if (blocksCall != null) { try { Response> blocksResponse = blocksCall.execute(); if (blocksResponse.isSuccessful()) { accountList = blocksResponse.body(); accounts.accounts = accountList; accounts.pagination = MastodonHelper.getPagination(blocksResponse.headers()); } } catch (Exception e) { e.printStackTrace(); } } Handler mainHandler = new Handler(Looper.getMainLooper()); Runnable myRunnable = () -> accountsMutableLiveData.setValue(accounts); mainHandler.post(myRunnable); }).start(); return accountsMutableLiveData; } /** * View domains the user has blocked. * * @param limit Maximum number of results. Defaults to 40. * @return {@link LiveData} containing {@link Domains} */ public LiveData getDomainBlocks(@NonNull String instance, String token, String limit, String maxId, String sinceId) { domainsMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); Domains domains = new Domains(); new Thread(() -> { List stringList = null; Call> getDomainBlocksCall = mastodonAccountsService.getDomainBlocks(token, limit, maxId, sinceId); if (getDomainBlocksCall != null) { try { Response> getDomainBlocksResponse = getDomainBlocksCall.execute(); if (getDomainBlocksResponse.isSuccessful()) { domains.domains = getDomainBlocksResponse.body(); domains.pagination = MastodonHelper.getPagination(getDomainBlocksResponse.headers()); } } catch (Exception e) { e.printStackTrace(); } } Handler mainHandler = new Handler(Looper.getMainLooper()); Runnable myRunnable = () -> domainsMutableLiveData.setValue(domains); mainHandler.post(myRunnable); }).start(); return domainsMutableLiveData; } /** * block a domain to: * • hide all public posts from it * • hide all notifications from it * • remove all followers from it * • prevent following new users from it (but does not remove existing follows) * * @param domain Domain to block. */ public void addDomainBlocks(@NonNull String instance, String token, String domain) { MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { Call addDomainBlockCall = mastodonAccountsService.addDomainBlock(token, domain); if (addDomainBlockCall != null) { try { addDomainBlockCall.execute(); } catch (Exception e) { e.printStackTrace(); } } }).start(); } /** * Remove a domain block, if it exists in the user's array of blocked domains. * * @param domain Domain to unblock. */ public void removeDomainBlocks(@NonNull String instance, String token, String domain) { MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { Call removeDomainBlockCall = mastodonAccountsService.removeDomainBlocks(token, domain); if (removeDomainBlockCall != null) { try { removeDomainBlockCall.execute(); } catch (Exception e) { e.printStackTrace(); } } }).start(); } /** * File a report * * @param accountId ID of the account to report * @param statusIds {@link List} of IDs of statuses to attach to the report, for context * @param comment Reason for the report (default max 1000 characters) * @param forward If the account is remote, should the report be forwarded to the remote admin? */ public LiveData report(@NonNull String instance, String token, @NonNull String accountId, String category, List statusIds, List ruleIds, String comment, Boolean forward) { reportMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { Report report = null; Report.ReportParams reportParams = new Report.ReportParams(); reportParams.account_id = accountId; reportParams.category = category; reportParams.comment = comment; reportParams.forward = forward; reportParams.rule_ids = ruleIds; reportParams.status_ids = statusIds; Call reportCall = mastodonAccountsService.report(token, reportParams); if (reportCall != null) { try { Response reportRequestsResponse = reportCall.execute(); if (reportRequestsResponse.isSuccessful()) { report = reportRequestsResponse.body(); } } catch (Exception e) { e.printStackTrace(); } } Handler mainHandler = new Handler(Looper.getMainLooper()); Report finalReport = report; Runnable myRunnable = () -> reportMutableLiveData.setValue(finalReport); mainHandler.post(myRunnable); }).start(); return reportMutableLiveData; } /** * View pending follow requests * * @param limit Maximum number of results to return. Defaults to 40. * @return {@link LiveData} containing a {@link List} of {@link Account}s */ public LiveData getFollowRequests(@NonNull String instance, String token, String max_id, int limit) { accountsMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { List accountList = null; Accounts accounts = new Accounts(); Call> followRequestsCall = mastodonAccountsService.getFollowRequests(token, max_id, limit); if (followRequestsCall != null) { try { Response> followRequestsResponse = followRequestsCall.execute(); if (followRequestsResponse.isSuccessful()) { accountList = followRequestsResponse.body(); accounts.accounts = accountList; accounts.pagination = MastodonHelper.getPagination(followRequestsResponse.headers()); } } catch (Exception e) { e.printStackTrace(); } Handler mainHandler = new Handler(Looper.getMainLooper()); Runnable myRunnable = () -> accountsMutableLiveData.setValue(accounts); mainHandler.post(myRunnable); } }).start(); return accountsMutableLiveData; } /** * Accept a pending follow requests * * @param id ID of the account * @return {@link LiveData} containing the {@link RelationShip} to the given account */ public LiveData acceptFollow(@NonNull String instance, String token, String id) { relationShipMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { RelationShip relationShip = null; Call acceptFollowCall = mastodonAccountsService.acceptFollow(token, id); if (acceptFollowCall != null) { try { Response acceptFollowResponse = acceptFollowCall.execute(); if (acceptFollowResponse.isSuccessful()) { relationShip = acceptFollowResponse.body(); } new StatusCache(getApplication().getApplicationContext()).deleteNotifications(MainActivity.currentUserID, instance); } catch (Exception e) { e.printStackTrace(); } } Handler mainHandler = new Handler(Looper.getMainLooper()); RelationShip finalRelationShip = relationShip; Runnable myRunnable = () -> relationShipMutableLiveData.setValue(finalRelationShip); mainHandler.post(myRunnable); }).start(); return relationShipMutableLiveData; } /** * Reject a pending follow requests * * @param id ID of the account * @return {@link LiveData} containing the {@link RelationShip} to the given account */ public LiveData rejectFollow(@NonNull String instance, String token, String id) { relationShipMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { RelationShip relationShip = null; Call rejectFollowCall = mastodonAccountsService.rejectFollow(token, id); if (rejectFollowCall != null) { try { Response rejectFollowResponse = rejectFollowCall.execute(); if (rejectFollowResponse.isSuccessful()) { relationShip = rejectFollowResponse.body(); } new StatusCache(getApplication().getApplicationContext()).deleteNotifications(MainActivity.currentUserID, instance); } catch (Exception e) { e.printStackTrace(); } } Handler mainHandler = new Handler(Looper.getMainLooper()); RelationShip finalRelationShip = relationShip; Runnable myRunnable = () -> relationShipMutableLiveData.setValue(finalRelationShip); mainHandler.post(myRunnable); }).start(); return relationShipMutableLiveData; } /** * View accounts that the user is currently featuring on their profile. * * @param limit Maximum number of results to return. Defaults to 40. * @return {@link LiveData} containing a {@link List} of {@link Account}s */ public LiveData> getEndorsements(@NonNull String instance, String token, String limit, String maxId, String sinceId) { accountListMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { List accountList = null; Call> endorsementsCall = mastodonAccountsService.getEndorsements(token, limit, maxId, sinceId); if (endorsementsCall != null) { try { Response> endorsementsResponse = endorsementsCall.execute(); if (endorsementsResponse.isSuccessful()) { accountList = endorsementsResponse.body(); } } catch (Exception e) { e.printStackTrace(); } } Handler mainHandler = new Handler(Looper.getMainLooper()); List finalAccountList = accountList; Runnable myRunnable = () -> accountListMutableLiveData.setValue(finalAccountList); mainHandler.post(myRunnable); }).start(); return accountListMutableLiveData; } /** * View your featured tags * * @return {@link LiveData} containing a {@link List} of {@link FeaturedTag}s */ public LiveData> getFeaturedTags(@NonNull String instance, String token) { featuredTagListMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { List featuredTagList = null; Call> getFeaturedTagsCall = mastodonAccountsService.getFeaturedTags(token); if (getFeaturedTagsCall != null) { try { Response> getFeaturedTagsResponse = getFeaturedTagsCall.execute(); if (getFeaturedTagsResponse.isSuccessful()) { featuredTagList = getFeaturedTagsResponse.body(); } } catch (Exception e) { e.printStackTrace(); } Handler mainHandler = new Handler(Looper.getMainLooper()); List finalFeaturedTagList = featuredTagList; Runnable myRunnable = () -> featuredTagListMutableLiveData.setValue(finalFeaturedTagList); mainHandler.post(myRunnable); } }).start(); return featuredTagListMutableLiveData; } /** * Feature a tag * * @param name The hashtag to be featured. * @return {@link LiveData} containing a {@link FeaturedTag} */ public LiveData addFeaturedTag(@NonNull String instance, String token, @NonNull String name) { featuredTagMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { FeaturedTag featuredTag = null; Call addFeaturedTagCall = mastodonAccountsService.addFeaturedTag(token, name); if (addFeaturedTagCall != null) { try { Response addFeaturedTagResponse = addFeaturedTagCall.execute(); if (addFeaturedTagResponse.isSuccessful()) { featuredTag = addFeaturedTagResponse.body(); } } catch (Exception e) { e.printStackTrace(); } } Handler mainHandler = new Handler(Looper.getMainLooper()); FeaturedTag finalFeaturedTag = featuredTag; Runnable myRunnable = () -> featuredTagMutableLiveData.setValue(finalFeaturedTag); mainHandler.post(myRunnable); }).start(); return featuredTagMutableLiveData; } /** * Unfeature a tag * * @param id The id of the FeaturedTag to be unfeatured. */ public void removeFeaturedTag(@NonNull String instance, String token, String id) { MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { Call removeFeaturedTagCall = mastodonAccountsService.removeFeaturedTag(token, id); if (removeFeaturedTagCall != null) { try { removeFeaturedTagCall.execute(); } catch (Exception e) { e.printStackTrace(); } } }).start(); } /** * Shows your 10 most-used tags, with usage history for the past week. * * @return {@link LiveData} containing a {@link List} of {@link Tag}s */ public LiveData> getFeaturedTagsSuggestions(@NonNull String instance, String token) { tagListMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { List tagList = null; Call> featuredTagsSuggestionsCall = mastodonAccountsService.getFeaturedTagsSuggestions(token); if (featuredTagsSuggestionsCall != null) { try { Response> featuredTagsSuggestionsResponse = featuredTagsSuggestionsCall.execute(); if (featuredTagsSuggestionsResponse.isSuccessful()) { tagList = featuredTagsSuggestionsResponse.body(); } } catch (Exception e) { e.printStackTrace(); } } Handler mainHandler = new Handler(Looper.getMainLooper()); List finalTagList = tagList; Runnable myRunnable = () -> tagListMutableLiveData.setValue(finalTagList); mainHandler.post(myRunnable); }).start(); return tagListMutableLiveData; } /** * Preferences defined by the user in their account settings. * * @return {@link LiveData} containing {@link Preferences} */ public LiveData getPreferences(@NonNull String instance, String token) { preferencesMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { Preferences preferences = null; Call preferencesCall = mastodonAccountsService.getPreferences(token); if (preferencesCall != null) { try { Response preferencesResponse = preferencesCall.execute(); if (preferencesResponse.isSuccessful()) { preferences = preferencesResponse.body(); } } catch (Exception e) { e.printStackTrace(); } } Handler mainHandler = new Handler(Looper.getMainLooper()); Preferences finalPreferences = preferences; Runnable myRunnable = () -> preferencesMutableLiveData.setValue(finalPreferences); mainHandler.post(myRunnable); }).start(); return preferencesMutableLiveData; } /** * Accounts the user has had past positive interactions with, but is not yet following. * * @param limit Maximum number of results to return. Defaults to 40. * @return {@link LiveData} containing a {@link List} of {@link Suggestion}s */ public LiveData getSuggestions(@NonNull String instance, String token, String limit) { suggestionsMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = initv2(instance); new Thread(() -> { Call> suggestionsCall = mastodonAccountsService.getSuggestions(token, limit); Suggestions suggestions = new Suggestions(); if (suggestionsCall != null) { try { Response> suggestionsResponse = suggestionsCall.execute(); if (suggestionsResponse.isSuccessful()) { suggestions.pagination = MastodonHelper.getOffSetPagination(suggestionsResponse.headers()); suggestions.suggestions = suggestionsResponse.body(); } } catch (Exception e) { e.printStackTrace(); } } Handler mainHandler = new Handler(Looper.getMainLooper()); Runnable myRunnable = () -> suggestionsMutableLiveData.setValue(suggestions); mainHandler.post(myRunnable); }).start(); return suggestionsMutableLiveData; } /** * List accounts visible in the directory. * * @param limit Maximum number of results to return. Defaults to 40. * @return {@link LiveData} containing a {@link List} of {@link Account}s */ public LiveData getDirectory(@NonNull String instance, String token, Integer offset, Integer limit, String order, Boolean local) { accountsMutableLiveData = new MutableLiveData<>(); MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { Call> accountsCall = mastodonAccountsService.getDirectory(token, offset, limit, order, local); Accounts accounts = new Accounts(); if (accountsCall != null) { try { Response> directoryResponse = accountsCall.execute(); if (directoryResponse.isSuccessful()) { accounts.pagination = MastodonHelper.getOffSetPagination(directoryResponse.headers()); accounts.accounts = directoryResponse.body(); } } catch (Exception e) { e.printStackTrace(); } } Handler mainHandler = new Handler(Looper.getMainLooper()); Runnable myRunnable = () -> accountsMutableLiveData.setValue(accounts); mainHandler.post(myRunnable); }).start(); return accountsMutableLiveData; } /** * Remove an account from follow suggestions. * * @param accountId id of the account in the database to be removed from suggestions */ public void removeSuggestion(@NonNull String instance, String token, String accountId) { MastodonAccountsService mastodonAccountsService = init(instance); new Thread(() -> { Call removeSuggestionCall = mastodonAccountsService.removeSuggestion(token, accountId); if (removeSuggestionCall != null) { try { removeSuggestionCall.execute(); } catch (Exception e) { e.printStackTrace(); } } }).start(); } public enum UpdateMediaType { AVATAR, HEADER } }