/** * Copyright (c) 2005-2017, KoLmafia development team * http://kolmafia.sourceforge.net/ * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * [1] Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * [2] Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * [3] Neither the name "KoLmafia" nor the names of its contributors may * be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ package net.sourceforge.kolmafia.session; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import net.java.dev.spellcast.utilities.LockableListModel; import net.java.dev.spellcast.utilities.SortedListModel; import net.sourceforge.kolmafia.RequestThread; import net.sourceforge.kolmafia.chat.ChatManager; import net.sourceforge.kolmafia.chat.ChatSender; import net.sourceforge.kolmafia.preferences.Preferences; import net.sourceforge.kolmafia.request.CharPaneRequest; import net.sourceforge.kolmafia.request.ContactListRequest; import net.sourceforge.kolmafia.request.FightRequest; import net.sourceforge.kolmafia.swingui.ContactListFrame; import net.sourceforge.kolmafia.utilities.HTMLListEntry; public class ContactManager { private static final HashMap seenPlayerIds = new HashMap(); private static final HashMap seenPlayerNames = new HashMap(); private static final SortedListModel<String> mailContacts = new SortedListModel<String>(); private static final SortedListModel chatContacts = new SortedListModel(); private static ContactListFrame contactsFrame = null; public static final void updateMailContacts() { if ( ContactManager.mailContacts.isEmpty() && !CharPaneRequest.inValhalla() && !FightRequest.initializingAfterFight() && !ChoiceManager.initializingAfterChoice() ) { RequestThread.postRequest( new ContactListRequest() ); } } public static final boolean isMailContact( final String playerName ) { return ContactManager.mailContacts.contains( playerName ); } public static final LockableListModel<String> getMailContacts() { return ContactManager.mailContacts; } public static final void clearMailContacts() { ContactManager.mailContacts.clear(); } /** * Replaces the current contact list with the given contact list. This is used after every call to /friends or /who. */ public static final void updateContactList( final String title, final Map contacts ) { if ( !ChatManager.isRunning() ) { return; } ContactManager.chatContacts.clear(); Iterator entryIterator = contacts.entrySet().iterator(); while ( entryIterator.hasNext() ) { Entry entry = (Entry) entryIterator.next(); String playerName = ( (String) entry.getKey() ).toLowerCase(); String color = entry.getValue() == Boolean.TRUE ? "black" : "gray"; ContactManager.chatContacts.add( new HTMLListEntry( playerName, color ) ); } if ( Preferences.getBoolean( "useContactsFrame" ) ) { if ( ContactManager.contactsFrame == null ) { ContactManager.contactsFrame = new ContactListFrame( ContactManager.chatContacts ); } ContactManager.contactsFrame.setTitle( title ); ContactManager.contactsFrame.setVisible( true ); } } public static final void addMailContact( String playerName, final String playerId ) { ContactManager.registerPlayerId( playerName, playerId ); playerName = playerName.toLowerCase().replaceAll( "[^0-9A-Za-z_ ]", "" ); if ( !ContactManager.mailContacts.contains( playerName ) ) { ContactManager.mailContacts.add( playerName.toLowerCase() ); } } /** * Registers the given player name and player Id with KoLmafia's player name tracker. * * @param playerName The name of the player * @param playerId The player Id associated with this player */ public static final void registerPlayerId( String playerName, final String playerId ) { if ( playerId.startsWith( "-" ) ) { return; } String lowercase = playerName.toLowerCase().trim(); if ( ContactManager.seenPlayerIds.containsKey( lowercase ) ) { return; } ContactManager.seenPlayerIds.put( lowercase, playerId ); ContactManager.seenPlayerNames.put( playerId, playerName ); } /** * Returns the string form of the player Id associated with the given player name. * * @param playerName The name of the player * @return The player's Id if the player has been seen, or the player's name with spaces replaced with underscores * and other elements encoded if the player's Id has not been seen. */ public static final String getPlayerId( final String playerName ) { return ContactManager.getPlayerId( playerName, false ); } public static final String getPlayerId( final String playerName, boolean retrieveId ) { if ( playerName == null ) { return null; } String playerId = (String) ContactManager.seenPlayerIds.get( playerName.toLowerCase() ); if ( playerId != null ) { return playerId; } if ( !retrieveId ) { return playerName; } ChatSender.executeMacro( "/whois " + playerName ); return ContactManager.getPlayerId( playerName, false ); } /** * Returns the string form of the player Id associated with the given player name. * * @param playerId The Id of the player * @return The player's name if it has been seen, or null if it has not yet appeared in the chat (not likely, but * possible). */ public static final String getPlayerName( final String playerId ) { return ContactManager.getPlayerName( playerId, false ); } public static final String getPlayerName( final String playerId, boolean retrieveName ) { if ( playerId == null ) { return null; } String playerName = (String) ContactManager.seenPlayerNames.get( playerId ); if ( playerName != null ) { return playerName; } if ( !retrieveName ) { return playerId; } ChatSender.executeMacro( "/whois " + playerId ); return ContactManager.getPlayerName( playerId, false ); } public static final String[] extractTargets( final String targetList ) { // If there are no targets in the list, then // return absolutely nothing. if ( targetList == null || targetList.trim().length() == 0 ) { return new String[ 0 ]; } // Otherwise, split the list of targets, and // determine who all the unique targets are. String[] targets = targetList.trim().split( "\\s*,\\s*" ); for ( int i = 0; i < targets.length; ++i ) { targets[ i ] = getPlayerId( targets[ i ] ) == null ? targets[ i ] : getPlayerId( targets[ i ] ); } // Sort the list in order to increase the // speed of duplicate detection. Arrays.sort( targets ); // Determine who all the duplicates are. int uniqueListSize = targets.length; for ( int i = 1; i < targets.length; ++i ) { if ( targets[ i ].equals( targets[ i - 1 ] ) ) { targets[ i - 1 ] = null; --uniqueListSize; } } // Now, create the list of unique targets; // if the list has the same size as the original, // you can skip this step. if ( uniqueListSize != targets.length ) { int addedCount = 0; String[] uniqueList = new String[ uniqueListSize ]; for ( int i = 0; i < targets.length; ++i ) { if ( targets[ i ] != null ) { uniqueList[ addedCount++ ] = targets[ i ]; } } targets = uniqueList; } // Convert all the user Ids back to the // original player names so that the results // are easy to understand for the user. for ( int i = 0; i < targets.length; ++i ) { targets[ i ] = getPlayerName( targets[ i ] ) == null ? targets[ i ] : getPlayerName( targets[ i ] ); } // Sort the list one more time, this time // by player name. Arrays.sort( targets ); // Parsing complete. Return the list of // unique targets. return targets; } }