Added `-[NSArray validateAsPropertyList]` and `-[NSDictionary validateAsPropertyList...
[adiumx.git] / Source / AdiumMessageEvents.m
blob5243c33e7db0620a61f1626c8d729062ca68ac77
1 /* 
2  * Adium is the legal property of its developers, whose names are listed in the copyright file included
3  * with this source distribution.
4  * 
5  * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
6  * General Public License as published by the Free Software Foundation; either version 2 of the License,
7  * or (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
10  * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
11  * Public License for more details.
12  * 
13  * You should have received a copy of the GNU General Public License along with this program; if not,
14  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
15  */
17 #import "AdiumMessageEvents.h"
18 #import <Adium/AIContactAlertsControllerProtocol.h>
19 #import <Adium/AIChatControllerProtocol.h>
20 #import <Adium/AIContentControllerProtocol.h>
21 #import <Adium/AIChat.h>
22 #import <Adium/AIListContact.h>
23 #import <AIUtilities/AIAttributedStringAdditions.h>
24 #import <AIUtilities/AIImageAdditions.h>
25 #import <Adium/AIListGroup.h>
27 @implementation AdiumMessageEvents
29 - (id)init
31         if ((self = [super init])) {
32                 //Empty
33         }
34         
35         return self;
38 //Requires contactAlertController loaded
39 - (void)controllerDidLoad
41         //Register the events we generate
42         [[adium contactAlertsController] registerEventID:CONTENT_MESSAGE_SENT withHandler:self inGroup:AIMessageEventHandlerGroup globalOnly:NO];
43         [[adium contactAlertsController] registerEventID:CONTENT_MESSAGE_RECEIVED withHandler:self inGroup:AIMessageEventHandlerGroup globalOnly:NO];
44         [[adium contactAlertsController] registerEventID:CONTENT_MESSAGE_RECEIVED_FIRST withHandler:self inGroup:AIMessageEventHandlerGroup globalOnly:NO];
45         [[adium contactAlertsController] registerEventID:CONTENT_MESSAGE_RECEIVED_BACKGROUND withHandler:self inGroup:AIMessageEventHandlerGroup globalOnly:NO];
46         [[adium contactAlertsController] registerEventID:CONTENT_MESSAGE_RECEIVED_GROUP withHandler:self inGroup:AIMessageEventHandlerGroup globalOnly:NO];
47         [[adium contactAlertsController] registerEventID:CONTENT_MESSAGE_RECEIVED_BACKGROUND_GROUP withHandler:self inGroup:AIMessageEventHandlerGroup globalOnly:NO];
48         
49         //Observe chat changes
50         [[adium chatController] registerChatObserver:self];
53 - (void)dealloc
55         [[adium chatController] unregisterChatObserver:self];
56         
57         [super dealloc];
60 #pragma mark Message event handling
61 - (NSSet *)updateChat:(AIChat *)inChat keys:(NSSet *)inModifiedKeys silent:(BOOL)silent
63         if (inModifiedKeys == nil ||
64                 [inModifiedKeys containsObject:KEY_CHAT_TIMED_OUT] ||
65                 [inModifiedKeys containsObject:KEY_CHAT_CLOSED_WINDOW] ||
66                 [inModifiedKeys containsObject:KEY_CHAT_ERROR]) {
67                 
68                 NSString                *message = nil;
69                 NSString                *type = nil;
70                 AIListContact   *listObject = [inChat listObject];
71                 
72                 if ([inChat statusObjectForKey:KEY_CHAT_ERROR] != nil) {
73                         
74                         AIChatErrorType errorType = [inChat integerStatusObjectForKey:KEY_CHAT_ERROR];
75                         type = @"chat-error";
76                         
77                         switch (errorType) {
78                                 case AIChatUnknownError:
79                                         message = [NSString stringWithFormat:AILocalizedString(@"Unknown conversation error.",nil)];
80                                         break;
81                                         
82                                 case AIChatMessageSendingUserNotAvailable:
83                                         message = [NSString stringWithFormat:AILocalizedString(@"Could not send because %@ is not available.",nil),[listObject formattedUID]];
84                                         break;
85                                         
86                                 case AIChatMessageSendingUserIsBlocked:
87                                         message = [NSString stringWithFormat:AILocalizedString(@"Could not send because %@ is blocked.",nil),[listObject formattedUID]];
88                                         break;
89                                         
90                                 case AIChatMessageSendingTooLarge:
91                                         message = AILocalizedString(@"Could not send the last message because it was too large.",nil);
92                                         break;
93                                         
94                                 case AIChatMessageSendingTimeOutOccurred:
95                                         message = AILocalizedString(@"A message may not have been sent; a timeout occurred.",nil);
96                                         break;
97                                         
98                                 case AIChatMessageSendingMissedRateLimitExceeded:
99                                         message = AILocalizedString(@"Could not send the last message because the rate limit has been exceeded. Please wait a moment and then try again.",nil);
100                                         break;
102                                 case AIChatMessageReceivingMissedTooLarge:
103                                         message = AILocalizedString(@"Could not receive the last message because it was too large.",nil);
104                                         break;
105                                         
106                                 case AIChatMessageReceivingMissedInvalid:
107                                         message = AILocalizedString(@"Could not receive the last message because it was invalid.",nil);
108                                         break;
109                                         
110                                 case AIChatMessageReceivingMissedRateLimitExceeded:
111                                         message = AILocalizedString(@"Could not receive the last message because the rate limit has been exceeded. Please wait a moment and then try again.",nil);
112                                         break;
113                                         
114                                 case AIChatMessageReceivingMissedRemoteIsTooEvil:
115                                         message = [NSString stringWithFormat:AILocalizedString(@"Could not receive; %@ is too evil.",nil),[listObject formattedUID]];
116                                         
117                                         break;
118                                 case AIChatMessageReceivingMissedLocalIsTooEvil:
119                                         message = AILocalizedString(@"Could not receive: you are too evil.",nil);
120                                         break;
121                                         
122                                 case AIChatCommandFailed:
123                                         message = AILocalizedString(@"Command failed.",nil);
124                                         break;
125                                         
126                                 case AIChatInvalidNumberOfArguments:
127                                         message = AILocalizedString(@"Incorrect number of command argments.",nil);
128                                         break;
129                                         
130                                 case AIChatMessageSendingConnectionError:
131                                         message = AILocalizedString(@"Could not send; a connection error occurred.",nil);
132                                         break;
133                                         
134                                 case AIChatMessageSendingNotAllowedWhileInvisible:
135                                         message = AILocalizedString(@"Could not send; not allowed while invisible.",nil);
136                                         break;
137                         }
138                         
139                 } else if ([inChat integerStatusObjectForKey:KEY_CHAT_CLOSED_WINDOW] && listObject) {
140                         message = [NSString stringWithFormat:AILocalizedString(@"%@ closed the conversation window.",nil),[listObject displayName]];
141                         type = @"closed";
142                 } else if ([inChat integerStatusObjectForKey:KEY_CHAT_TIMED_OUT] && listObject) {
143                         message = [NSString stringWithFormat:AILocalizedString(@"The conversation with %@ timed out.",nil),[listObject displayName]];                   
144                         type = @"timed_out";
145                 }
146                 
147                 if (message) {
148                         [[adium contentController] displayEvent:message
149                                                                                          ofType:type
150                                                                                          inChat:inChat];
151                 }
152         }
153         
154         return nil;
157 #pragma mark Event descriptions
158 - (NSString *)shortDescriptionForEventID:(NSString *)eventID
160         NSString        *description;
161         
162         if ([eventID isEqualToString:CONTENT_MESSAGE_SENT]) {
163                 description = AILocalizedString(@"Is sent a message",nil);
164         } else if ([eventID isEqualToString:CONTENT_MESSAGE_RECEIVED]) {
165                 description = AILocalizedString(@"Sends a message",nil);
166         } else if ([eventID isEqualToString:CONTENT_MESSAGE_RECEIVED_FIRST]) {
167                 description = AILocalizedString(@"Sends an initial message",nil);
168         } else if ([eventID isEqualToString:CONTENT_MESSAGE_RECEIVED_BACKGROUND]) {
169                 description = AILocalizedString(@"Sends a message in a background chat",nil);
170         } else if ([eventID isEqualToString:CONTENT_MESSAGE_RECEIVED_GROUP]) {
171                 description = AILocalizedString(@"Sends a message in a group chat",nil);
172         } else if ([eventID isEqualToString:CONTENT_MESSAGE_RECEIVED_BACKGROUND_GROUP]) {
173                 description = AILocalizedString(@"Sends a message in a background group chat",nil);
174         } else {
175                 description = @"";
176         }
177         
178         return description;
181 - (NSString *)globalShortDescriptionForEventID:(NSString *)eventID
183         NSString        *description;
184         
185         if ([eventID isEqualToString:CONTENT_MESSAGE_SENT]) {
186                 description = AILocalizedString(@"Message sent",nil);
187         } else if ([eventID isEqualToString:CONTENT_MESSAGE_RECEIVED]) {
188                 description = AILocalizedString(@"Message received",nil);
189         } else if ([eventID isEqualToString:CONTENT_MESSAGE_RECEIVED_FIRST]) {
190                 description = AILocalizedString(@"Message received (Initial)",nil);
191         } else if ([eventID isEqualToString:CONTENT_MESSAGE_RECEIVED_BACKGROUND]) {
192                 description = AILocalizedString(@"Message received (Background Chat)",nil);
193         } else if ([eventID isEqualToString:CONTENT_MESSAGE_RECEIVED_GROUP]) {
194                 description = AILocalizedString(@"Message received (Group Chat)",nil);
195         } else if ([eventID isEqualToString:CONTENT_MESSAGE_RECEIVED_BACKGROUND_GROUP]) {
196                 description = AILocalizedString(@"Message received (Background Group Chat)",nil);
197         } else {
198                 description = @"";
199         }
200         
201         return description;
204 //Evan: This exists because old X(tras) relied upon matching the description of event IDs, and I don't feel like making
205 //a converter for old packs.  If anyone wants to fix this situation, please feel free :)
206 - (NSString *)englishGlobalShortDescriptionForEventID:(NSString *)eventID
208         NSString        *description;
209         
210         if ([eventID isEqualToString:CONTENT_MESSAGE_SENT]) {
211                 description = @"Message Sent";
212         } else if ([eventID isEqualToString:CONTENT_MESSAGE_RECEIVED]) {
213                 description = @"Message Received";
214         } else if ([eventID isEqualToString:CONTENT_MESSAGE_RECEIVED_FIRST]) {
215                 description = @"Message Received (New)";
216         } else if ([eventID isEqualToString:CONTENT_MESSAGE_RECEIVED_BACKGROUND]) {
217                 description = @"Message Received (Background Chat)";
218         } else if ([eventID isEqualToString:CONTENT_MESSAGE_RECEIVED_GROUP]) {
219                 description = @"Message Received (Group Chat)";
220         } else if ([eventID isEqualToString:CONTENT_MESSAGE_RECEIVED_BACKGROUND_GROUP]) {
221                 description = @"Message Received (Background Group Chat)";
222         } else {
223                 description = @"";
224         }
225         
226         return description;
229 - (NSString *)longDescriptionForEventID:(NSString *)eventID forListObject:(AIListObject *)listObject
231         NSString        *description = nil;
232         
233         if (listObject) {
234                 NSString        *name;
235                 NSString        *format;
236                 
237                 if ([eventID isEqualToString:CONTENT_MESSAGE_SENT]) {
238                         format = AILocalizedString(@"When you send %@ a message",nil);
239                 } else if ([eventID isEqualToString:CONTENT_MESSAGE_RECEIVED]) {
240                         format = AILocalizedString(@"When %@ sends a message to you",nil);
241                 } else if ([eventID isEqualToString:CONTENT_MESSAGE_RECEIVED_FIRST]) {
242                         format = AILocalizedString(@"When %@ sends an initial message to you",nil);
243                 } else if ([eventID isEqualToString:CONTENT_MESSAGE_RECEIVED_BACKGROUND]) {
244                         format = AILocalizedString(@"When %@ sends a message to you in a background chat",nil);
245                 } else if ([eventID isEqualToString:CONTENT_MESSAGE_RECEIVED_GROUP]) {
246                         format = AILocalizedString(@"When %@ sends a message to you in a group chat",nil);
247                 } else if ([eventID isEqualToString:CONTENT_MESSAGE_RECEIVED_BACKGROUND_GROUP]) {
248                         format = AILocalizedString(@"When %@ sends a message to you in a background group chat",nil);
249                 } else {
250                         format = nil;
251                 }
252                 
253                 if (format) {
254                         name = ([listObject isKindOfClass:[AIListGroup class]] ?
255                                         [NSString stringWithFormat:AILocalizedString(@"a member of %@",nil),[listObject displayName]] :
256                                         [listObject displayName]);
257                         
258                         description = [NSString stringWithFormat:format, name];
259                 }
260                 
261         } else {
262                 if ([eventID isEqualToString:CONTENT_MESSAGE_SENT]) {
263                         description = AILocalizedString(@"When you send a message",nil);
264                 } else if ([eventID isEqualToString:CONTENT_MESSAGE_RECEIVED]) {
265                         description = AILocalizedString(@"When you receive any message",nil);
266                 } else if ([eventID isEqualToString:CONTENT_MESSAGE_RECEIVED_FIRST]) {
267                         description = AILocalizedString(@"When you receive an initial message",nil);
268                 } else if ([eventID isEqualToString:CONTENT_MESSAGE_RECEIVED_BACKGROUND]) {
269                         description = AILocalizedString(@"When you receive a message in a background chat",nil);
270                 } else if ([eventID isEqualToString:CONTENT_MESSAGE_RECEIVED_GROUP]) {
271                         description = AILocalizedString(@"When you receive a message in a group chat",nil);
272                 } else if ([eventID isEqualToString:CONTENT_MESSAGE_RECEIVED_BACKGROUND_GROUP]) {
273                         description = AILocalizedString(@"When you receive a message in a background group chat",nil);
274                 } else {
275                         description = @"";
276                 }
277         }
278         
279         return description;
282 - (NSString *)naturalLanguageDescriptionForEventID:(NSString *)eventID
283                                                                                 listObject:(AIListObject *)listObject
284                                                                                   userInfo:(id)userInfo
285                                                                         includeSubject:(BOOL)includeSubject
287         NSString                *description = nil;
288         AIContentObject *contentObject;
289         NSString                *messageText;
290         NSString                *displayName;
291         
292         NSParameterAssert([userInfo isKindOfClass:[NSDictionary class]]);
293         
294         contentObject = [(NSDictionary *)userInfo objectForKey:@"AIContentObject"];
295         messageText = [[[contentObject message] attributedStringByConvertingAttachmentsToStrings] string];
296         
297         if (includeSubject) {
298                 
299                 if ([eventID isEqualToString:CONTENT_MESSAGE_SENT]) {
300                         displayName = (listObject ? [listObject displayName] : [[contentObject chat] name]);
301                 
302                         if (messageText && [messageText length]) {
303                                 description = [NSString stringWithFormat:
304                                         AILocalizedString(@"You said %@ to %@","You said Message to Contact"),
305                                         messageText,
306                                         displayName];
308                         } else {
309                                 description = [NSString stringWithFormat:
310                                         AILocalizedString(@"You sent a message to %@","You sent a message to Contact"),
311                                         displayName];
312                         }
313                         
314                 } else if ([eventID isEqualToString:CONTENT_MESSAGE_RECEIVED] ||
315                                    [eventID isEqualToString:CONTENT_MESSAGE_RECEIVED_FIRST] ||
316                                    [eventID isEqualToString:CONTENT_MESSAGE_RECEIVED_BACKGROUND]) {
317                         displayName = (listObject ? [listObject displayName] : [[contentObject source] displayName]);
318                         
319                         if (messageText && [messageText length]) {
320                                 description = [NSString stringWithFormat:
321                                         AILocalizedString(@"%@ said %@","Contact said Message"),
322                                         displayName,
323                                         messageText];
325                         } else {
326                                 description = [NSString stringWithFormat:
327                                         AILocalizedString(@"%@ sent you a message","Contact sent you a message"),
328                                         displayName];                           
329                         }
330                 }       
331                 
332         } else {
333                 if (messageText && [messageText length]) {
334                         description = messageText;
335                 } else {
336                         if ([eventID isEqualToString:CONTENT_MESSAGE_RECEIVED] ||
337                                 [eventID isEqualToString:CONTENT_MESSAGE_RECEIVED_FIRST] ||
338                                 [eventID isEqualToString:CONTENT_MESSAGE_RECEIVED_BACKGROUND] ||
339                                 [eventID isEqualToString:CONTENT_MESSAGE_RECEIVED_GROUP] ||
340                                 [eventID isEqualToString:CONTENT_MESSAGE_RECEIVED_BACKGROUND_GROUP]) {
341                                 //Use the message received text for all message received events if we don't have a message
342                                 description = [self globalShortDescriptionForEventID:CONTENT_MESSAGE_RECEIVED];
343                         } else {
344                                 description = [self globalShortDescriptionForEventID:eventID];                          
345                         }
346                 }
347         }
348         
349         return description;
352 - (NSImage *)imageForEventID:(NSString *)eventID
354         static NSImage  *eventImage = nil;
355         //Use the message icon from the main bundle
356         if (!eventImage) eventImage = [[NSImage imageNamed:@"message"] retain];
357         return eventImage;
360 @end