| 62 | | |
|---|
| 63 | | //XXX - Why is code calling these with a nil contact? |
|---|
| 64 | | //XXX - This method is being misused all over the place as a means to pick the inner contact of a meta? |
|---|
| 65 | | //XXX - Who wants an offline account for sending content, do we absolutely need to do that in the core? |
|---|
| 66 | | //XXX - Why is the method for determining which account to use so complicated? |
|---|
| 67 | | - (AIAccount *)preferredAccountForSendingContentType:(NSString *)inType toContact:(AIListContact *)inContact |
|---|
| 68 | | { |
|---|
| 69 | | return ([self preferredAccountForSendingContentType:inType toContact:inContact includeOffline:NO]); |
|---|
| 70 | | } |
|---|
| 71 | | |
|---|
| 72 | | - (AIAccount *)preferredAccountForSendingContentType:(NSString *)inType toContact:(AIListContact *)inContact includeOffline:(BOOL)includeOffline |
|---|
| | 62 | - (AIAccount *)fallbackAccountForSendingToContact:(AIListContact *)inContact strictChecking:(BOOL)strictChecking |
|---|
| 75 | | |
|---|
| 76 | | //If passed a contact, we have a few better ways to determine the account than just using the first |
|---|
| 77 | | if (inContact) { |
|---|
| 78 | | //If we've messaged this object previously, and the account we used to message it is online, return that account |
|---|
| 79 | | NSString *accountID = [inContact preferenceForKey:KEY_PREFERRED_SOURCE_ACCOUNT |
|---|
| 80 | | group:PREF_GROUP_PREFERRED_ACCOUNTS]; |
|---|
| 81 | | if (accountID) { |
|---|
| 82 | | if (![accountID isKindOfClass:[NSString class]]) { |
|---|
| 83 | | //Old code stored this as an NSNumber; upgrade. |
|---|
| 84 | | accountID = ([accountID isKindOfClass:[NSNumber class]] ? |
|---|
| 85 | | [NSString stringWithFormat:@"%i",[(NSNumber *)accountID intValue]] : |
|---|
| 86 | | nil); |
|---|
| 87 | | |
|---|
| 88 | | [inContact setPreference:accountID |
|---|
| 89 | | forKey:KEY_PREFERRED_SOURCE_ACCOUNT |
|---|
| 90 | | group:PREF_GROUP_PREFERRED_ACCOUNTS]; |
|---|
| 91 | | } |
|---|
| 92 | | |
|---|
| | 65 | NSEnumerator *enumerator; |
|---|
| | 66 | |
|---|
| | 67 | //First available account in our list of the correct service type |
|---|
| | 68 | enumerator = [[[adium accountController] accounts] objectEnumerator]; |
|---|
| | 69 | while ((account = [enumerator nextObject])) { |
|---|
| | 70 | if ([inContact service] == [account service] && |
|---|
| | 71 | ([account online] || ([account enabled] && !strictChecking))) { |
|---|
| | 72 | return account; |
|---|
| | 73 | } |
|---|
| | 74 | } |
|---|
| | 75 | |
|---|
| | 76 | //First available account in our list of a compatible service type |
|---|
| | 77 | enumerator = [[[adium accountController] accounts] objectEnumerator]; |
|---|
| | 78 | while ((account = [enumerator nextObject])) { |
|---|
| | 79 | if ([[inContact serviceClass] isEqualToString:[account serviceClass]] && |
|---|
| | 80 | ([account online] || ([account enabled] && !strictChecking))) { |
|---|
| | 81 | return account; |
|---|
| | 82 | } |
|---|
| | 83 | } |
|---|
| | 84 | |
|---|
| | 85 | //Can't find anything |
|---|
| | 86 | return nil; |
|---|
| | 87 | } |
|---|
| | 88 | |
|---|
| | 89 | - (AIAccount *)preferredAccountForSendingContentType:(NSString *)inType toContact:(AIListContact *)inContact strictChecking:(BOOL)strictChecking |
|---|
| | 90 | { |
|---|
| | 91 | AIAccount *account; |
|---|
| | 92 | |
|---|
| | 93 | NSParameterAssert(inContact != nil); |
|---|
| | 94 | |
|---|
| | 95 | //If we've messaged this object previously, and the account we used to message it is online, return that account |
|---|
| | 96 | NSString *accountID = [inContact preferenceForKey:KEY_PREFERRED_SOURCE_ACCOUNT |
|---|
| | 97 | group:PREF_GROUP_PREFERRED_ACCOUNTS]; |
|---|
| | 98 | if (accountID) { |
|---|
| | 99 | if (![accountID isKindOfClass:[NSString class]]) { |
|---|
| | 100 | //Old code stored this as an NSNumber; upgrade. |
|---|
| | 101 | accountID = ([accountID isKindOfClass:[NSNumber class]] ? |
|---|
| | 102 | [NSString stringWithFormat:@"%i",[(NSNumber *)accountID intValue]] : |
|---|
| | 103 | nil); |
|---|
| 101 | | /* We don't have a known previously used account for this contact. */ |
|---|
| 102 | | |
|---|
| 103 | | //Get the last account used to message someone on this service, and check if the contact is on that account |
|---|
| 104 | | NSString *lastAccountID = [lastAccountIDToSendContent objectForKey:[[inContact service] serviceID]]; |
|---|
| 105 | | AIAccount *lastUsedAccount = (lastAccountID ? [[adium accountController] accountWithInternalObjectID:lastAccountID] : nil); |
|---|
| 106 | | AIListContact *possibleContact = [[adium contactController] existingContactWithService:[lastUsedAccount service] |
|---|
| 107 | | account:lastUsedAccount |
|---|
| 108 | | UID:[inContact UID]]; |
|---|
| 109 | | if (possibleContact && ![possibleContact isStranger] && |
|---|
| 110 | | ([lastUsedAccount availableForSendingContentType:inType toContact:inContact] || includeOffline)) { |
|---|
| 111 | | return lastUsedAccount; |
|---|
| 112 | | } |
|---|
| 113 | | |
|---|
| 114 | | //Use the current account if and only if the contact is not a stranger on that account. |
|---|
| 115 | | if ((account = [inContact account]) && |
|---|
| 116 | | ![inContact isStranger] && |
|---|
| 117 | | ([account availableForSendingContentType:inType toContact:inContact] || includeOffline)) { |
|---|
| 118 | | return account; |
|---|
| 119 | | } |
|---|
| 121 | | //Now check compatible accounts, looking for one that knows about the contact |
|---|
| 122 | | NSEnumerator *enumerator = [[[adium accountController] accountsCompatibleWithService:[inContact service]] objectEnumerator]; |
|---|
| 123 | | while ((account = [enumerator nextObject])) { |
|---|
| 124 | | AIListContact *possibleContact = [[adium contactController] existingContactWithService:[account service] |
|---|
| 125 | | account:account |
|---|
| 126 | | UID:[inContact UID]]; |
|---|
| 127 | | if ((possibleContact && ![possibleContact isStranger]) && |
|---|
| 128 | | ([account availableForSendingContentType:inType toContact:inContact] || includeOffline)) { |
|---|
| 129 | | //If a contact with this account already exists and isn't a stranger, we've found a good possible choice. |
|---|
| | 111 | if ((account = [[adium accountController] accountWithInternalObjectID:accountID])) { |
|---|
| | 112 | if ([account availableForSendingContentType:inType toContact:inContact] || !strictChecking) { |
|---|
| 133 | | |
|---|
| 134 | | /* Now, just look for any account which could send to this contact. |
|---|
| 135 | | * We no longer care if the contact is not a stranger, as we exchausted all those possibilities. |
|---|
| 136 | | * |
|---|
| 137 | | * First, check to see if the last account used on this service will work. |
|---|
| 138 | | */ |
|---|
| 139 | | if ([lastUsedAccount availableForSendingContentType:inType toContact:inContact] || includeOffline) { |
|---|
| 140 | | return lastUsedAccount; |
|---|
| 141 | | } |
|---|
| 142 | | |
|---|
| 143 | | //If inObject is an AIListContact return the account the object is on even if the account is offline |
|---|
| 144 | | if (includeOffline && (account = [inContact account])) { |
|---|
| | 116 | } |
|---|
| | 117 | |
|---|
| | 118 | /* We don't have a known previously used account for this contact. */ |
|---|
| | 119 | |
|---|
| | 120 | //Get the last account used to message someone on this service, and check if the contact is on that account |
|---|
| | 121 | NSString *lastAccountID = [lastAccountIDToSendContent objectForKey:[[inContact service] serviceID]]; |
|---|
| | 122 | AIAccount *lastUsedAccount = (lastAccountID ? [[adium accountController] accountWithInternalObjectID:lastAccountID] : nil); |
|---|
| | 123 | AIListContact *possibleContact = [[adium contactController] existingContactWithService:[lastUsedAccount service] |
|---|
| | 124 | account:lastUsedAccount |
|---|
| | 125 | UID:[inContact UID]]; |
|---|
| | 126 | if (possibleContact && ![possibleContact isStranger] && |
|---|
| | 127 | ([lastUsedAccount availableForSendingContentType:inType toContact:inContact] || !strictChecking)) { |
|---|
| | 128 | return lastUsedAccount; |
|---|
| | 129 | } |
|---|
| | 130 | |
|---|
| | 131 | //Use the current account if and only if the contact is not a stranger on that account. |
|---|
| | 132 | if ((account = [inContact account]) && |
|---|
| | 133 | ![inContact isStranger] && |
|---|
| | 134 | ([account availableForSendingContentType:inType toContact:inContact] || !strictChecking)) { |
|---|
| | 135 | return account; |
|---|
| | 136 | } |
|---|
| | 137 | |
|---|
| | 138 | //Now check compatible accounts, looking for one that knows about the contact |
|---|
| | 139 | NSEnumerator *enumerator = [[[adium accountController] accountsCompatibleWithService:[inContact service]] objectEnumerator]; |
|---|
| | 140 | while ((account = [enumerator nextObject])) { |
|---|
| | 141 | AIListContact *possibleContact = [[adium contactController] existingContactWithService:[account service] |
|---|
| | 142 | account:account |
|---|
| | 143 | UID:[inContact UID]]; |
|---|
| | 144 | if ((possibleContact && ![possibleContact isStranger]) && |
|---|
| | 145 | ([account availableForSendingContentType:inType toContact:inContact] || !strictChecking)) { |
|---|
| | 146 | //If a contact with this account already exists and isn't a stranger, we've found a good possible choice. |
|---|
| 148 | | |
|---|
| 149 | | AILogWithSignature(@"Could not find a good choice to talk to %@; will return first available account", inContact); |
|---|
| 150 | | |
|---|
| 151 | | //If the previous attempts failed, or we weren't passed a contact, use the first appropriate account |
|---|
| 152 | | return [self firstAccountAvailableForSendingContentType:inType |
|---|
| 153 | | toContact:inContact |
|---|
| 154 | | includeOffline:includeOffline]; |
|---|
| 155 | | } |
|---|
| 156 | | |
|---|
| 157 | | //XXX - This seems awfully complex for code that is only run the first time we talk to a contact |
|---|
| 158 | | //XXX - Why isn't this private? |
|---|
| 159 | | - (AIAccount *)firstAccountAvailableForSendingContentType:(NSString *)inType toContact:(AIListContact *)inContact includeOffline:(BOOL)includeOffline |
|---|
| 160 | | { |
|---|
| 161 | | AIAccount *account; |
|---|
| 162 | | NSEnumerator *enumerator; |
|---|
| 163 | | |
|---|
| 164 | | if (inContact) { |
|---|
| 165 | | //First available account in our list of the correct service type |
|---|
| 166 | | enumerator = [[[adium accountController] accounts] objectEnumerator]; |
|---|
| 167 | | while ((account = [enumerator nextObject])) { |
|---|
| 168 | | if ([inContact service] == [account service] && |
|---|
| 169 | | ([account availableForSendingContentType:inType toContact:inContact] || includeOffline)) { |
|---|
| 170 | | return account; |
|---|
| | 150 | |
|---|
| | 151 | /* Now, just look for any account which could send to this contact. |
|---|
| | 152 | * We no longer care if the contact is not a stranger, as we exchausted all those possibilities. |
|---|
| | 153 | * |
|---|
| | 154 | * First, check to see if the last account used on this service will work. |
|---|
| | 155 | */ |
|---|
| | 156 | if ([lastUsedAccount availableForSendingContentType:inType toContact:inContact] || !strictChecking) { |
|---|
| | 157 | return lastUsedAccount; |
|---|
| | 158 | } |
|---|
| | 159 | |
|---|
| | 160 | //If inObject is an AIListContact return the account the object is on even if the account is offline |
|---|
| | 161 | if (!strictChecking && (account = [inContact account])) { |
|---|
| | 162 | return account; |
|---|
| | 163 | } |
|---|
| | 164 | |
|---|
| | 165 | return nil; |
|---|
| | 166 | } |
|---|
| | 167 | |
|---|
| | 168 | - (AIAccount *)preferredAccountForSendingContentType:(NSString *)inType toContact:(AIListContact *)inContact |
|---|
| | 169 | { |
|---|
| | 170 | AIAccount *account; |
|---|
| | 171 | |
|---|
| | 172 | account = [self preferredAccountForSendingContentType:inType toContact:inContact strictChecking:YES]; |
|---|
| | 173 | if (!account) { |
|---|
| | 174 | AILogWithSignature(@"Could not find an online choice to talk to %@; will include offline accounts", inContact); |
|---|
| | 175 | account = [self preferredAccountForSendingContentType:inType toContact:inContact strictChecking:NO]; |
|---|
| | 176 | |
|---|
| | 177 | if (!account) { |
|---|
| | 178 | AILogWithSignature(@"Could not find a good choice to talk to %@; will return first available account", inContact); |
|---|
| | 179 | account = [self fallbackAccountForSendingToContact:inContact strictChecking:YES]; |
|---|
| | 180 | |
|---|
| | 181 | if (!account) { |
|---|
| | 182 | account = [self fallbackAccountForSendingToContact:inContact strictChecking:NO]; |
|---|
| 173 | | |
|---|
| 174 | | //First available account in our list of a compatible service type |
|---|
| 175 | | enumerator = [[[adium accountController] accounts] objectEnumerator]; |
|---|
| 176 | | while ((account = [enumerator nextObject])) { |
|---|
| 177 | | if ([[inContact serviceClass] isEqualToString:[account serviceClass]] && |
|---|
| 178 | | ([account availableForSendingContentType:inType toContact:inContact] || includeOffline)) { |
|---|
| 179 | | return account; |
|---|
| 180 | | } |
|---|
| 181 | | } |
|---|
| 182 | | } else { |
|---|
| 183 | | //First available account in our list |
|---|
| 184 | | enumerator = [[[adium accountController] accounts] objectEnumerator]; |
|---|
| 185 | | while ((account = [enumerator nextObject])) { |
|---|
| 186 | | if ([account enabled] && |
|---|
| 187 | | ([account availableForSendingContentType:inType toContact:inContact] || includeOffline)) { |
|---|
| 188 | | return account; |
|---|
| 189 | | } |
|---|
| 190 | | } |
|---|
| 191 | | } |
|---|
| 192 | | |
|---|
| 193 | | |
|---|
| 194 | | //Can't find anything |
|---|
| 195 | | return nil; |
|---|
| | 185 | } |
|---|
| | 186 | |
|---|
| | 187 | return account; |
|---|