* Adium is the legal property of its developers, whose names are listed in the copyright file included * with this source distribution. * 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 2 of the License, * or (at your option) any later version. * This program 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 this program; if not, * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #import "AdiumPreferredAccounts.h" #import <Adium/AIAccountControllerProtocol.h> #import <Adium/AIContactControllerProtocol.h> #import <Adium/AIAccount.h> #import <Adium/AIService.h> #import <Adium/AIContentObject.h> #import <Adium/AIListObject.h> #import <Adium/AIListContact.h> #define PREF_GROUP_PREFERRED_ACCOUNTS @"Preferred Accounts" #define KEY_PREFERRED_SOURCE_ACCOUNT @"Preferred Account" @interface AdiumPreferredAccounts () - (void)didSendContent:(NSNotification *)notification; @implementation AdiumPreferredAccounts if ((self = [super init])) { //Observe content (for accountForSendingContentToContact) [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didSendContent:) name:CONTENT_MESSAGE_SENT [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didSendContent:) name:CONTENT_MESSAGE_SENT_GROUP [[NSNotificationCenter defaultCenter] removeObserver:self]; - (AIAccount *)fallbackAccountForSendingToContact:(AIListContact *)inContact strictChecking:(BOOL)strictChecking //First available account in our list of the correct service type for (AIAccount *account in adium.accountController.accounts ) { if (inContact.service == account.service && (account.online || (account.enabled && !strictChecking))) { //First available account in our list of a compatible service type for (AIAccount *account in adium.accountController.accounts ) { if ([inContact.service.serviceClass isEqualToString:account.service.serviceClass] && (account.online || (account.enabled && !strictChecking))) { - (AIAccount *)preferredAccountForSendingContentType:(NSString *)inType toContact:(AIListContact *)inContact strictChecking:(BOOL)strictChecking NSParameterAssert(inContact != nil); //If we've messaged this object previously, and the account we used to message it is online, return that account NSString *accountID = [inContact preferenceForKey:KEY_PREFERRED_SOURCE_ACCOUNT group:PREF_GROUP_PREFERRED_ACCOUNTS]; //Check the metacontact as well. accountID = [inContact.parentContact preferenceForKey:KEY_PREFERRED_SOURCE_ACCOUNT group:PREF_GROUP_PREFERRED_ACCOUNTS]; if (![accountID isKindOfClass:[NSString class]]) { //Old code stored this as an NSNumber; upgrade. accountID = ([accountID isKindOfClass:[NSNumber class]] ? [NSString stringWithFormat:@"%ld",[(NSNumber *)accountID integerValue]] : [inContact setPreference:accountID forKey:KEY_PREFERRED_SOURCE_ACCOUNT group:PREF_GROUP_PREFERRED_ACCOUNTS]; if ((account = [adium.accountController accountWithInternalObjectID:accountID])) { if ([account.service.serviceClass isEqualToString:inContact.service.serviceClass] && ([account availableForSendingContentType:inType toContact:inContact] || !strictChecking)) { //Check all compatible accounts, looking for one that has the contact on its list for (account in [adium.accountController accountsCompatibleWithService:inContact.service]) { AIListContact *possibleContact = [adium.contactController existingContactWithService:account.service if ((possibleContact && !possibleContact.isStranger) && ([account availableForSendingContentType:inType toContact:possibleContact] || !strictChecking)) { //If a contact with this account already exists and isn't a stranger, we've found a good possible choice. /* Now, just look for any account which could send to this contact. * We no longer care if the contact is not a stranger, as we exchausted all those possibilities. for (account in [adium.accountController accountsCompatibleWithService:inContact.service]) { if ([account availableForSendingContentType:inType toContact:inContact] || !strictChecking) { - (AIAccount *)preferredAccountForSendingContentType:(NSString *)inType toContact:(AIListContact *)inContact account = [self preferredAccountForSendingContentType:inType toContact:inContact strictChecking:YES]; AILogWithSignature(@"Could not find an online choice to talk to %@; will include offline accounts", inContact); account = [self preferredAccountForSendingContentType:inType toContact:inContact strictChecking:NO]; AILogWithSignature(@"Could not find a good choice to talk to %@; will return first available account", inContact); account = [self fallbackAccountForSendingToContact:inContact strictChecking:YES]; account = [self fallbackAccountForSendingToContact:inContact strictChecking:NO]; - (void)didSendContent:(NSNotification *)notification NSDictionary *userInfo = [notification userInfo]; AIChat *chat = [userInfo objectForKey:@"AIChat"]; AIListContact *destObject = chat.listObject; if (chat && destObject) { AIContentObject *contentObject = [userInfo objectForKey:@"AIContentObject"]; AIAccount *sourceAccount = (AIAccount *)[contentObject source]; if (![[destObject preferenceForKey:KEY_PREFERRED_SOURCE_ACCOUNT group:PREF_GROUP_PREFERRED_ACCOUNTS] isEqualToString:sourceAccount.internalObjectID]) { [destObject setPreference:sourceAccount.internalObjectID forKey:KEY_PREFERRED_SOURCE_ACCOUNT group:PREF_GROUP_PREFERRED_ACCOUNTS];