Adium plugin to pipe events/messages to an external program
at master 138 lines 3.9 kB view raw
1#import "PipeEventPlugin.h" 2#import "PipeEventDetailPane.h" 3#import <AIUtilities/AIImageAdditions.h> 4#import <Adium/AIContentObject.h> 5#import <Adium/AIListContact.h> 6 7#define PIPE_EVENT_IDENTIFIER @"PipeEvent" 8#define PIPE_EVENT_SHORT @"Pipe event to command" 9#define PIPE_EVENT_LONG @"Pipe event to \"%@\"" 10 11@implementation PipeEventPlugin 12 13- (void)installPlugin 14{ 15 [adium.contactAlertsController registerActionID:PIPE_EVENT_IDENTIFIER withHandler:self]; 16} 17 18/* text for the "Action:" drop down */ 19- (NSString *)shortDescriptionForActionID:(NSString *)actionID 20{ 21 return PIPE_EVENT_SHORT; 22} 23 24/* subtext for the "When you receive any message" line, and the text in the full events list */ 25- (NSString *)longDescriptionForActionID:(NSString *)actionID 26 withDetails:(NSDictionary *)details 27{ 28 NSString *command = [details objectForKey:KEY_COMMAND]; 29 30 if (command && [command length]) 31 return [NSString stringWithFormat:PIPE_EVENT_LONG, [command lastPathComponent]]; 32 else 33 return PIPE_EVENT_SHORT; 34} 35 36- (NSImage *)imageForActionID:(NSString *)actionID 37{ 38 return [NSImage imageNamed:@"TerminalIcon" forClass:[self class]]; 39} 40 41- (AIModularPane *)detailsPaneForActionID:(NSString *)actionID 42{ 43 return [PipeEventDetailPane actionDetailsPane]; 44} 45 46/* the actual event handler */ 47- (BOOL)performActionID:(NSString *)actionID 48 forListObject:(AIListObject *)listObject 49 withDetails:(NSDictionary *)details 50 triggeringEventID:(NSString *)eventID 51 userInfo:(id)userInfo 52{ 53 NSString *command = [details objectForKey:KEY_COMMAND]; 54 NSString *message = [adium.contactAlertsController naturalLanguageDescriptionForEventID:eventID 55 listObject:listObject 56 userInfo:userInfo 57 includeSubject:NO]; 58 NSString *sender; 59 AIChat *chat = nil; 60 61 NSTask *task = [[NSTask alloc] init]; 62 63 [task setLaunchPath:command]; 64 65 // for a message event, listObject should become whoever sent the message 66 if ([adium.contactAlertsController isMessageEvent:eventID] && 67 [userInfo respondsToSelector:@selector(objectForKey:)] && 68 [userInfo objectForKey:@"AIContentObject"]) { 69 AIContentObject *contentObject = [userInfo objectForKey:@"AIContentObject"]; 70 AIListObject *source = [contentObject source]; 71 chat = [userInfo objectForKey:@"AIChat"]; 72 73 if (source) 74 listObject = source; 75 } 76 77 if (listObject) { 78 if ([listObject isKindOfClass:[AIListContact class]]) { 79 // use the parent 80 listObject = [(AIListContact *)listObject parentContact]; 81 sender = [listObject longDisplayName]; 82 } else 83 sender = listObject.displayName; 84 } else if (chat) 85 sender = chat.displayName; 86 87 // pass the sender (or whatever the event sends) as the first arg 88 if (sender) 89 [task setArguments:[NSArray arrayWithObjects:sender, nil]]; 90 91 // stdout and stderr will be closed right away 92 [task setStandardOutput:[NSPipe pipe]]; 93 [task setStandardError:[NSPipe pipe]]; 94 [task setStandardInput:[NSPipe pipe]]; 95 96 // go go gadget nstask 97 [task launch]; 98 99 // close command's stdout and stderr 100 [[[task standardOutput] fileHandleForReading] closeFile]; 101 [[[task standardError] fileHandleForReading] closeFile]; 102 103 // send the message contents (with newline) and then close the filehandle 104 [[[task standardInput] fileHandleForWriting] writeData:[[NSString stringWithFormat:@"%@\n", message] dataUsingEncoding:NSASCIIStringEncoding]]; 105 [[[task standardInput] fileHandleForWriting] closeFile]; 106 107 // uh, i guess magic happens here and everything is cleaned up for us 108 109 return YES; // WE CAN 110} 111 112- (BOOL)allowMultipleActionsWithID:(NSString *)actionID 113{ 114 /* we can be setup with different commands for different things, so, yeah */ 115 return YES; 116} 117 118- (NSString *)pluginAuthor 119{ 120 return @"joshua stein"; 121} 122 123- (NSString *)pluginVersion 124{ 125 return @"1.1"; 126} 127 128- (NSString *)pluginDescription 129{ 130 return @"This plugin pipes events to an external command."; // with gusto! 131} 132 133- (NSString *)pluginURL 134{ 135 return @"http://jcs.org/"; 136} 137 138@end