package com.xabber.android.data.extension.blocking; import android.support.annotation.Nullable; import com.xabber.android.data.Application; import com.xabber.android.data.account.AccountItem; import com.xabber.android.data.account.AccountManager; import com.xabber.android.data.connection.ConnectionItem; import com.xabber.android.data.entity.AccountJid; import com.xabber.android.data.entity.UserJid; import com.xabber.android.data.log.LogManager; import com.xabber.android.data.message.MessageManager; import com.xabber.android.data.notification.NotificationManager; import com.xabber.android.data.roster.OnContactChangedListener; import com.xabber.android.data.roster.RosterContact; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.tcp.XMPPTCPConnection; import org.jivesoftware.smackx.blocking.BlockingCommandManager; import org.jxmpp.jid.Jid; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; public class BlockingManager { static final String LOG_TAG = BlockingManager.class.getSimpleName(); private static BlockingManager instance; @SuppressWarnings("WeakerAccess") Map<AccountJid, Boolean> supportForAccounts; @SuppressWarnings("WeakerAccess") Map<AccountJid, BlockedListener> blockedListeners; @SuppressWarnings("WeakerAccess") Map<AccountJid, UnblockedListener> unblockedListeners; @SuppressWarnings("WeakerAccess") Map<AccountJid, UnblockedAllListener> unblockedAllListeners; public static BlockingManager getInstance() { if (instance == null) { instance = new BlockingManager(); } return instance; } private BlockingManager() { supportForAccounts = new ConcurrentHashMap<>(); blockedListeners = new ConcurrentHashMap<>(); unblockedListeners = new ConcurrentHashMap<>(); unblockedAllListeners = new ConcurrentHashMap<>(); } public void onAuthorized(final ConnectionItem connection) { final AccountJid account = connection.getAccount(); BlockingCommandManager blockingCommandManager = BlockingCommandManager.getInstanceFor(connection.getConnection()); try { boolean supportedByServer = blockingCommandManager.isSupportedByServer(); if (supportedByServer) { // cache block list inside blockingCommandManager.getBlockList(); } addBlockedListener(blockingCommandManager, account); addUnblockedListener(blockingCommandManager, account); addUnblockedAllListener(blockingCommandManager, account); // block list already cached successfully supportForAccounts.put(account, supportedByServer); BlockingManager.notify(account); } catch (SmackException.NotConnectedException | XMPPException.XMPPErrorException | SmackException.NoResponseException | InterruptedException e) { LogManager.exception(this, e); } } @SuppressWarnings("WeakerAccess") void addBlockedListener(BlockingCommandManager blockingCommandManager, AccountJid account) { BlockedListener blockedListener = blockedListeners.remove(account); if (blockedListener != null) { blockingCommandManager.removeJidsBlockedListener(blockedListener); } blockedListener = new BlockedListener(account); blockedListeners.put(account, blockedListener); blockingCommandManager.addJidsBlockedListener(blockedListener); } @SuppressWarnings("WeakerAccess") void addUnblockedListener(BlockingCommandManager blockingCommandManager, AccountJid account) { UnblockedListener unblockedListener = unblockedListeners.remove(account); if (unblockedListener != null) { blockingCommandManager.removeJidsUnblockedListener(unblockedListener); } unblockedListener = new UnblockedListener(account); unblockedListeners.put(account, unblockedListener); blockingCommandManager.addJidsUnblockedListener(unblockedListener); } @SuppressWarnings("WeakerAccess") void addUnblockedAllListener(BlockingCommandManager blockingCommandManager, AccountJid account) { UnblockedAllListener unblockedAllListener = unblockedAllListeners.remove(account); if (unblockedAllListener != null) { blockingCommandManager.removeAllJidsUnblockedListener(unblockedAllListener); } unblockedAllListener = new UnblockedAllListener(account); unblockedAllListeners.put(account, unblockedAllListener); blockingCommandManager.addAllJidsUnblockedListener(unblockedAllListener); } static void notify(final AccountJid account) { Application.getInstance().runOnUiThread(new Runnable() { @Override public void run() { for (OnBlockedListChangedListener onBlockedListChangedListener : Application.getInstance().getUIListeners(OnBlockedListChangedListener.class)) { onBlockedListChangedListener.onBlockedListChanged(account); } for (OnContactChangedListener onContactChangedListener : Application.getInstance().getUIListeners(OnContactChangedListener.class)) { onContactChangedListener.onContactsChanged(new ArrayList<RosterContact>()); } } }); } /** * * @param account * @return true if supported, false if not supported and null if unknown yet */ @Nullable public Boolean isSupported(AccountJid account) { if (getBlockingCommandManager(account) == null) { supportForAccounts.remove(account); return null; } return supportForAccounts.get(account); } public List<UserJid> getBlockedContacts(AccountJid account) { List<UserJid> blockedContacts = new ArrayList<>(); Boolean supported = isSupported(account); BlockingCommandManager blockingCommandManager = getBlockingCommandManager(account); if (blockingCommandManager != null && supported != null && supported) { try { List<Jid> blockedJids = blockingCommandManager.getBlockList(); for (Jid jid : blockedJids) { blockedContacts.add(UserJid.from(jid)); } } catch (SmackException.NoResponseException | XMPPException.XMPPErrorException | InterruptedException | SmackException.NotConnectedException | UserJid.UserJidCreateException e) { LogManager.exception(LOG_TAG, e); } } return blockedContacts; } public interface BlockContactListener { void onSuccess(); void onError(); } public void blockContact(final AccountJid account, final UserJid contactJid, final BlockContactListener listener) { Application.getInstance().runInBackgroundUserRequest(new Runnable() { @Override public void run() { boolean success = false; BlockingCommandManager blockingCommandManager = getBlockingCommandManager(account); if (blockingCommandManager != null) { List<Jid> contactsToBlock = new ArrayList<>(); contactsToBlock.add(contactJid.getJid()); try { blockingCommandManager.blockContacts(contactsToBlock); success = true; } catch (SmackException.NoResponseException | XMPPException.XMPPErrorException | InterruptedException | SmackException.NotConnectedException e) { LogManager.exception(LOG_TAG, e); } } final boolean finalSuccess = success; Application.getInstance().runOnUiThread(new Runnable() { @Override public void run() { if (finalSuccess) { listener.onSuccess(); } else { listener.onError(); } } }); } }); } @SuppressWarnings("WeakerAccess") @Nullable BlockingCommandManager getBlockingCommandManager(AccountJid account) { AccountItem accountItem = AccountManager.getInstance().getAccount(account); if (accountItem == null) { return null; } XMPPTCPConnection connection = accountItem.getConnection(); // "Must have a local (user) JID set. Either you didn't configure one or you where not connected at least once" if (connection.getUser() == null) { return null; } return BlockingCommandManager.getInstanceFor(connection); } static void blockContactLocally(AccountJid account, UserJid contactJid) { MessageManager.getInstance().closeChat(account, contactJid); NotificationManager.getInstance().removeMessageNotification(account, contactJid); } public interface UnblockContactListener { void onSuccess(); void onError(); } public void unblockContacts(final AccountJid account, final List<UserJid> contacts, final UnblockContactListener listener) { Application.getInstance().runInBackgroundUserRequest(new Runnable() { @Override public void run() { boolean success = false; BlockingCommandManager blockingCommandManager = getBlockingCommandManager(account); if (blockingCommandManager != null) { List<Jid> jidsToUnblock = new ArrayList<>(contacts.size()); for (UserJid userJid : contacts) { jidsToUnblock.add(userJid.getBareJid()); } try { blockingCommandManager.unblockContacts(jidsToUnblock); success = true; } catch (SmackException.NoResponseException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | InterruptedException e) { LogManager.exception(LOG_TAG, e); } } final boolean finalSuccess = success; Application.getInstance().runOnUiThread(new Runnable() { @Override public void run() { if (finalSuccess) { listener.onSuccess(); } else { listener.onError(); } } }); } }); } public void unblockAll(final AccountJid account, final UnblockContactListener listener) { Application.getInstance().runInBackgroundUserRequest(new Runnable() { @Override public void run() { boolean success = false; BlockingCommandManager blockingCommandManager = getBlockingCommandManager(account); if (blockingCommandManager != null) { try { blockingCommandManager.unblockAll(); success = true; } catch (SmackException.NoResponseException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | InterruptedException e) { LogManager.exception(LOG_TAG, e); } } final boolean finalSuccess = success; Application.getInstance().runOnUiThread(new Runnable() { @Override public void run() { if (finalSuccess) { listener.onSuccess(); } else { listener.onError(); } } }); } }); } }