root/tags/2C10/JVChatMessage.m

Revision 2013, 7.9 kB (checked in by timothy, 4 years ago)

Allows scripts to do the following during "on process incoming chat message":
set body of theMessage to "New Message."

Line 
1 #import <ChatCore/NSAttributedStringAdditions.h>
2 #import <libxml/xinclude.h>
3 #import <libxml/debugXML.h>
4 #import <libxslt/transform.h>
5 #import <libxslt/xsltutils.h>
6
7 #import "JVChatMessage.h"
8 #import "JVChatTranscript.h"
9 #import "JVChatRoom.h"
10 #import "JVChatRoomMember.h"
11 #import "NSAttributedStringMoreAdditions.h"
12
13 @implementation JVChatMessage
14 + (id) messageWithNode:(/* xmlNode */ void *) node messageIndex:(unsigned long long) messageNumber andTranscript:(JVChatTranscript *) transcript {
15         return [[[self alloc] initWithNode:node messageIndex:messageNumber andTranscript:transcript] autorelease];
16 }
17
18 #pragma mark -
19
20 - (void) load {
21         if( _loaded ) return;
22
23         xmlChar *dateStr = xmlGetProp( _node, "received" );
24         _date = ( dateStr ? [[NSDate dateWithString:[NSString stringWithUTF8String:dateStr]] retain] : nil );
25         xmlFree( dateStr );
26
27         _attributedMessage = [[NSTextStorage attributedStringWithXHTMLTree:_node baseURL:nil defaultFont:nil] retain];
28         _action = ( xmlHasProp( _node, "action" ) ? YES : NO );
29         _highlighted = ( xmlHasProp( _node, "highlight" ) ? YES : NO );
30         _ignoreStatus = ( xmlHasProp( _node, "ignored" ) ? JVMessageIgnored : _ignoreStatus );
31         _ignoreStatus = ( xmlHasProp( ((xmlNode *) _node ) -> parent, "ignored" ) ? JVUserIgnored : _ignoreStatus );
32
33         xmlNode *subNode = ((xmlNode *) _node ) -> parent -> children;
34
35         do {
36                 if( ! strncmp( "sender", subNode -> name, 6 ) ) {
37                         xmlChar *senderStr = xmlGetProp( subNode, "nickname" );
38                         if( ! senderStr ) senderStr = xmlNodeGetContent( subNode );
39                         if( senderStr ) _sender = [NSString stringWithUTF8String:senderStr];
40                         xmlFree( senderStr );
41
42                         if( _sender && [[self transcript] isKindOfClass:[JVChatRoom class]] ) {
43                                 JVChatRoomMember *member = [(JVChatRoom *)[self transcript] chatRoomMemberWithName:_sender];
44                                 if( member ) _sender = member;
45                         }
46
47                         [_sender retain];
48                 }
49         } while( ( subNode = subNode -> next ) );
50
51         _loaded = YES;
52 }
53
54 #pragma mark -
55
56 - (id) init {
57         if( ( self = [super init] ) ) {
58                 _loaded = NO;
59                 _objectSpecifier = nil;
60                 _transcript = nil;
61                 _messageNumber = 0;
62                 _envelopeNumber = 0;
63                 _sender = nil;
64                 _htmlMessage = nil;
65                 _attributedMessage = nil;
66                 _date = nil;
67                 _action = NO;
68                 _highlighted = NO;
69                 _ignoreStatus = JVNotIgnored;
70         }
71
72         return self;
73 }
74
75 - (id) initWithNode:(/* xmlNode */ void *) node messageIndex:(unsigned long long) messageNumber andTranscript:(JVChatTranscript *) transcript {
76         if( ( self = [self init] ) ) {
77                 _node = node;
78                 _transcript = transcript;
79                 _messageNumber = messageNumber;
80
81                 id classDesc = [NSClassDescription classDescriptionForClass:[transcript class]];
82                 [self setObjectSpecifier:[[[NSIndexSpecifier alloc] initWithContainerClassDescription:classDesc containerSpecifier:[transcript objectSpecifier] key:@"messages" index:messageNumber] autorelease]];
83
84                 xmlChar *idStr = xmlGetProp( ((xmlNode *) _node ) -> parent, "id" );
85                 _envelopeNumber = ( idStr ? strtoul( idStr, NULL, 0 ) : 0 );
86                 xmlFree( idStr );
87         }
88
89         return self;
90 }
91
92 - (id) mutableCopyWithZone:(NSZone *) zone {
93         [self load];
94
95         JVMutableChatMessage *ret = [[JVMutableChatMessage allocWithZone:zone] initWithText:_attributedMessage sender:_sender andTranscript:_transcript];
96         [ret setDate:_date];
97         [ret setAction:_action];
98         [ret setHighlighted:_highlighted];
99         [ret setMessageNumber:_messageNumber];
100         [ret setEnvelopeNumber:_envelopeNumber];
101
102         return ret;
103 }
104
105 - (void) dealloc {
106         [_sender release];
107         [_htmlMessage release];
108         [_attributedMessage release];
109         [_date release];
110         [_objectSpecifier release];
111
112         _node = NULL;
113         _transcript = NULL;
114         _sender = nil;
115         _htmlMessage = nil;
116         _attributedMessage = nil;
117         _date = nil;
118         _objectSpecifier = nil;
119
120         [super dealloc];
121 }
122
123 #pragma mark -
124
125 - (void *) node {
126         return _node;
127 }
128
129 #pragma mark -
130
131 - (NSDate *) date {
132         [self load];
133         return _date;
134 }
135
136 - (id) sender {
137         [self load];
138         return _sender;
139 }
140
141 #pragma mark -
142
143 - (NSTextStorage *) body {
144         [self load];
145         return _attributedMessage;
146 }
147
148 - (NSString *) bodyAsPlainText {
149         return [[self body] string];
150 }
151
152 - (NSString *) bodyAsHTML {
153         NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], @"IgnoreFonts", [NSNumber numberWithBool:YES], @"IgnoreFontSizes", nil];
154         return [[self body] HTMLFormatWithOptions:options];
155 }
156
157 #pragma mark -
158
159 - (BOOL) isAction {
160         [self load];
161         return _action;
162 }
163
164 - (BOOL) isHighlighted {
165         [self load];
166         return _highlighted;
167 }
168
169 - (JVIgnoreMatchResult) ignoreStatus {
170         [self load];
171         return _ignoreStatus;
172 }
173
174 #pragma mark -
175
176 - (JVChatTranscript *) transcript {
177         return _transcript;
178 }
179
180 - (unsigned long long) messageNumber {
181         return _messageNumber;
182 }
183
184 - (unsigned long long) envelopeNumber {
185         return _envelopeNumber;
186 }
187
188 #pragma mark -
189
190 - (NSScriptObjectSpecifier *) objectSpecifier {
191         return _objectSpecifier;
192 }
193
194 - (void) setObjectSpecifier:(NSScriptObjectSpecifier *) objectSpecifier {
195         [_objectSpecifier autorelease];
196         _objectSpecifier = [objectSpecifier retain];
197 }
198
199 #pragma mark -
200
201 - (NSString *) description {
202         [self load];
203         return [self bodyAsPlainText];
204 }
205
206 - (NSString *) debugDescription {
207         [self load];
208         return [NSString stringWithFormat:@"<%@ 0x%x: (%@) %@>", NSStringFromClass( [self class] ), (unsigned long) self, [self sender], [self body]];
209 }
210 @end
211
212 #pragma mark -
213
214 @implementation JVMutableChatMessage
215 + (id) messageWithText:(NSTextStorage *) body sender:(NSString *) sender andTranscript:(JVChatTranscript *) transcript {
216         return [[[self alloc] initWithText:body sender:sender andTranscript:transcript] autorelease];
217 }
218
219 - (id) initWithText:(NSTextStorage *) body sender:(NSString *) sender andTranscript:(JVChatTranscript *) transcript {
220         if( ( self = [self init] ) ) {
221                 _loaded = YES;
222                 [self setTranscript:transcript];
223                 [self setDate:[NSDate date]];
224                 [self setBody:body];
225                 [self setSender:sender];
226         }
227
228         return self;
229 }
230
231 #pragma mark -
232
233 - (void) setNode:(/* xmlNode */ void *) node {
234         _node = node;
235 }
236
237 #pragma mark -
238
239 - (void) setDate:(NSDate *) date {
240         [_date autorelease];
241         _date = [date copy];
242 }
243
244 - (void) setSender:(id) sender {
245         if( [sender isKindOfClass:[NSString class]] && [[self transcript] isKindOfClass:[JVChatRoom class]] ) {
246                 JVChatRoomMember *member = [(JVChatRoom *)[self transcript] chatRoomMemberWithName:sender];
247                 if( member ) sender = member;
248         }
249
250         [_sender autorelease];
251         _sender = ( [sender conformsToProtocol:@protocol( NSCopying)] ? [sender copy] : [sender retain] );
252 }
253
254 #pragma mark -
255
256 - (void) setBody:(NSAttributedString *) message {
257         if( ! _attributedMessage ) {
258                 if( [message isKindOfClass:[NSTextStorage class]] ) _attributedMessage = [message retain];
259                 else if( [message isKindOfClass:[NSAttributedString class]] ) _attributedMessage = [[NSTextStorage alloc] initWithAttributedString:message];
260                 else if( [message isKindOfClass:[NSString class]] ) _attributedMessage = [[NSAttributedString alloc] initWithString:(NSString *)message];
261         } else if( _attributedMessage && [message isKindOfClass:[NSAttributedString class]] ) {
262                 [_attributedMessage setAttributedString:message];
263         } else if( _attributedMessage && [message isKindOfClass:[NSString class]] ) {
264                 id string = [[[NSAttributedString alloc] initWithString:(NSString *)message] autorelease];
265                 [_attributedMessage setAttributedString:string];
266         }
267 }
268
269 - (void) setBodyAsPlainText:(NSString *) message {
270         [self setBody:[[[NSAttributedString alloc] initWithString:message] autorelease]];
271 }
272
273 - (void) setBodyAsHTML:(NSString *) message {
274         [self setBody:[NSAttributedString attributedStringWithHTMLFragment:message baseURL:nil]];
275 }
276
277 #pragma mark -
278
279 - (void) setAction:(BOOL) action {
280         _action = action;
281 }
282
283 - (void) setHighlighted:(BOOL) highlighted {
284         _highlighted = highlighted;
285 }
286
287 - (void) setIgnoreStatus:(JVIgnoreMatchResult) ignoreStatus {
288         _ignoreStatus = ignoreStatus;
289 }
290
291 #pragma mark -
292
293 - (void) setTranscript:(JVChatTranscript *) transcript {
294         [_transcript autorelease];
295         _transcript = [transcript retain];
296 }
297
298 - (void) setMessageNumber:(unsigned long long) number {
299         _messageNumber = number;
300 }
301
302 - (void) setEnvelopeNumber:(unsigned long long) number {
303         _envelopeNumber = number;
304 }
305 @end
Note: See TracBrowser for help on using the browser.