diff --git a/IRCClient/IRCClientChannel.h b/IRCClient/IRCClientChannel.h index 7e55986..b0339aa 100644 --- a/IRCClient/IRCClientChannel.h +++ b/IRCClient/IRCClientChannel.h @@ -27,6 +27,8 @@ * for a given session when the client joins an IRC channel. */ +@class IRCClientSession; + /**********************************************/ #pragma mark IRCClientChannel class declaration /**********************************************/ @@ -40,6 +42,9 @@ /** Delegate to send events to */ @property (assign) id delegate; +/** Associated session */ +@property (readonly) IRCClientSession *session; + /** Name of the channel */ @property (readonly) NSData *name; @@ -50,7 +55,7 @@ * * You can (attempt to) set the topic by using setChannelTopic:, not by * changing this property (which is readonly). If the connected user has the - * privileges to set the channel topic, the channel's delegate will receive a + * privileges to set the channel topic, the channel’s delegate will receive a * topicSet:by: message (and the topic property of the channel object will be * updated automatically). */ @@ -66,18 +71,24 @@ /** Stores arbitrary user info. */ @property (strong) NSDictionary *userInfo; +/********************************************/ +#pragma mark - Initializers & factory methods +/********************************************/ + ++(instancetype) channel; + /**************************/ #pragma mark - IRC commands /**************************/ /** Parts the channel. */ -- (int)part; +-(int) part; /** Invites another IRC client to the channel. * * @param nick the nickname of the client to invite. */ -- (int)invite:(NSData *)nick; +-(int) invite:(NSData *)nick; /** Sets the topic of the channel. * @@ -86,7 +97,7 @@ * * @param aTopic the topic the client wishes to set for the channel. */ -- (void)setChannelTopic:(NSData *)newTopic; +-(int) setChannelTopic:(NSData *)newTopic; /** Sets the mode of the channel. * @@ -95,33 +106,35 @@ * * @param mode the mode to set the channel to */ -- (int)setMode:(NSData *)mode params:(NSData *)params; +-(int) setMode:(NSData *)mode + params:(NSData *)params; /** Sends a public PRIVMSG to the channel. If you try to send more than can fit on an IRC buffer, it will be truncated. @param message the message to send to the channel. */ -- (int)message:(NSData *)message; +-(int) message:(NSData *)message; /** Sends a public CTCP ACTION to the channel. * * @param action action to send to the channel. */ -- (int)action:(NSData *)action; +-(int) action:(NSData *)action; /** Sends a public NOTICE to the channel. * * @param notice message to send to the channel. */ -- (int)notice:(NSData *)notice; +-(int) notice:(NSData *)notice; /** Kicks someone from a channel. * * @param nick the IRC client to kick from the channel. * @param reason the message to give to the channel and the IRC client for the kick. */ -- (int)kick:(NSData *)nick reason:(NSData *)reason; +-(int) kick:(NSData *)nick + reason:(NSData *)reason; /** Sends a CTCP request to the channel. * @@ -130,6 +143,6 @@ * * @param request the string of the request, in CTCP format. */ -- (int)ctcpRequest:(NSData *)request; +-(int) ctcpRequest:(NSData *)request; @end diff --git a/IRCClient/IRCClientChannel.m b/IRCClient/IRCClientChannel.m index 69bb88a..3fba318 100644 --- a/IRCClient/IRCClientChannel.m +++ b/IRCClient/IRCClientChannel.m @@ -25,17 +25,14 @@ #pragma mark IRCClientChannel class extension /********************************************/ -@interface IRCClientChannel() -{ - irc_session_t *_irc_session; +@interface IRCClientChannel() { + irc_session_t *_irc_session; - NSMutableArray *_nicks; + // TODO: actually keep track of nicks! Use RPL_NAMREPLY and so on... + // (see refreshNames...) + NSMutableArray *_nicks; } -@property (readwrite) NSData *topic; -@property (readwrite) NSData *modes; -@property (readwrite) NSMutableArray *nicks; - @end /***************************************************/ @@ -44,37 +41,43 @@ @implementation IRCClientChannel -/******************************/ -#pragma mark - Custom accessors -/******************************/ +/************************/ +#pragma mark - Properties +/************************/ --(NSArray *)nicks -{ - NSArray* nicksCopy = [_nicks copy]; - return nicksCopy; +-(NSArray *) nicks { + return [_nicks copy]; } --(void)setNicks:(NSArray *)nicks -{ - _nicks = [nicks mutableCopy]; +-(IRCClientSession *) session { + return (__bridge IRCClientSession *) irc_get_ctx(_irc_session); +} + +/********************************************/ +#pragma mark - Initializers & factory methods +/********************************************/ + ++(instancetype) channel { + return [self new]; } /**************************/ #pragma mark - Initializers /**************************/ --(instancetype)initWithName:(NSData *)name andIRCSession:(irc_session_t *)irc_session -{ - if ((self = [super init])) - { - _irc_session = irc_session; +-(instancetype) initWithName:(NSData *)name + andIRCSession:(irc_session_t *)irc_session { + self = [super init]; + if (!self) return nil; + + _irc_session = irc_session; + + _name = name; + _encoding = NSUTF8StringEncoding; + _topic = [NSData dataWithBlankCString]; + _modes = [NSData dataWithBlankCString]; + _nicks = [NSMutableArray array]; - _name = name; - _encoding = NSUTF8StringEncoding; - _topic = [NSData dataWithBlankCString]; - _modes = [NSData dataWithBlankCString]; - } - return self; } @@ -82,110 +85,202 @@ #pragma mark - IRC commands /**************************/ -- (int)part -{ - return irc_cmd_part(_irc_session, _name.SA_terminatedCString); +-(int) part { + return irc_send_raw(_irc_session, + "PART %s", + _name.SA_terminatedCString); } -- (int)invite:(NSData *)nick -{ - return irc_cmd_invite(_irc_session, nick.SA_terminatedCString, _name.SA_terminatedCString); +-(int) invite:(NSData *)nick { + if (!nick || nick.length == 0) + return LIBIRC_ERR_STATE; + + return irc_send_raw(_irc_session, + "INVITE %s %s", + nick.SA_terminatedCString, + _name.SA_terminatedCString); } -- (int)refreshNames -{ - return irc_cmd_names(_irc_session, _name.SA_terminatedCString); +-(int) refreshNames { + return irc_send_raw(_irc_session, + "NAMES %s", + _name.SA_terminatedCString); } -- (void)setChannelTopic:(NSData *)newTopic -{ - irc_cmd_topic(_irc_session, _name.SA_terminatedCString, newTopic.SA_terminatedCString); -} - -- (int)setMode:(NSData *)mode params:(NSData *)params -{ - if(params != nil) - { - NSMutableData *fullModeString = (params != nil) ? [NSMutableData dataWithLength:mode.length + 1 + params.length] : [NSMutableData dataWithLength:mode.length]; - sprintf(fullModeString.mutableBytes, "%s %s", mode.bytes, params.bytes); - - return irc_cmd_channel_mode(_irc_session, _name.SA_terminatedCString, fullModeString.SA_terminatedCString); - } +-(int) setChannelTopic:(NSData *)newTopic { + if (newTopic) + return irc_send_raw(_irc_session, + "TOPIC %s :%s", + _name.SA_terminatedCString, + newTopic.SA_terminatedCString); else - { - return irc_cmd_channel_mode(_irc_session, _name.SA_terminatedCString, mode.SA_terminatedCString); + return irc_send_raw(_irc_session, + "TOPIC %s", + _name.SA_terminatedCString); +} + +-(int) setMode:(NSData *)mode + params:(NSData *)params { + if (mode != nil) { + NSMutableData *fullModeString = ((params != nil) ? + [NSMutableData dataWithLength:mode.length + 1 + params.length] : + [NSMutableData dataWithLength:mode.length + 1]); + sprintf(fullModeString.mutableBytes, + "%s %s", + mode.SA_terminatedCString, + params.SA_terminatedCString); + + return irc_send_raw(_irc_session, + "MODE %s %s", + _name.SA_terminatedCString, + fullModeString.SA_terminatedCString); + } else { + return irc_send_raw(_irc_session, + "MODE %s", + _name.SA_terminatedCString); } } -- (int)message:(NSData *)message -{ - return irc_cmd_msg(_irc_session, _name.SA_terminatedCString, message.SA_terminatedCString); +-(int) message:(NSData *)message { + if (!message || message.length == 0) + return LIBIRC_ERR_STATE; + + return irc_send_raw(_irc_session, + "PRIVMSG %s :%s", + _name.SA_terminatedCString, + irc_color_convert_to_mirc(message.SA_terminatedCString)); } -- (int)action:(NSData *)action -{ - return irc_cmd_me(_irc_session, _name.SA_terminatedCString, action.SA_terminatedCString); +-(int) action:(NSData *)action { + if (!action || action.length == 0) + return LIBIRC_ERR_STATE; + + return irc_send_raw(_irc_session, + "PRIVMSG %s :\x01" "ACTION %s\x01", + _name.SA_terminatedCString, + irc_color_convert_to_mirc(action.SA_terminatedCString)); } -- (int)notice:(NSData *)notice -{ - return irc_cmd_notice(_irc_session, _name.SA_terminatedCString, notice.SA_terminatedCString); +-(int) notice:(NSData *)notice { + if (!notice || notice.length == 0) + return LIBIRC_ERR_STATE; + + return irc_send_raw(_irc_session, + "NOTICE %s :%s", + _name.SA_terminatedCString, + notice.SA_terminatedCString); } -- (int)kick:(NSData *)nick reason:(NSData *)reason -{ - return irc_cmd_kick(_irc_session, nick.SA_terminatedCString, _name.SA_terminatedCString, reason.SA_terminatedCString); +-(int) kick:(NSData *)nick + reason:(NSData *)reason { + if (!nick || nick.length == 0) + return LIBIRC_ERR_STATE; + + if (reason) + return irc_send_raw(_irc_session, + "KICK %s %s :%s", + _name.SA_terminatedCString, + nick.SA_terminatedCString, + reason.SA_terminatedCString); + else + return irc_send_raw(_irc_session, + "KICK %s %s", + _name.SA_terminatedCString, + nick.SA_terminatedCString); } -- (int)ctcpRequest:(NSData *)request -{ - return irc_cmd_ctcp_request(_irc_session, _name.SA_terminatedCString, request.SA_terminatedCString); +-(int) ctcpRequest:(NSData *)request { + if (!request || request.length == 0) + return LIBIRC_ERR_STATE; + + return irc_send_raw(_irc_session, + "PRIVMSG %s :\x01%s\x01", + _name.SA_terminatedCString, + request.SA_terminatedCString); } /****************************/ #pragma mark - Event handlers /****************************/ -- (void)userJoined:(NSData *)nick -{ - [_delegate userJoined:nick channel:self]; +-(void) userJoined:(NSData *)nick { + [_nicks addObject:nick]; + + [_delegate userJoined:nick + channel:self]; } -- (void)userParted:(NSData *)nick withReason:(NSData *)reason us:(BOOL)wasItUs -{ - [_delegate userParted:nick channel:self withReason:reason us:wasItUs]; +-(void) userParted:(NSData *)nick + withReason:(NSData *)reason + us:(BOOL)wasItUs { + if (!wasItUs) + [_nicks removeObject:nick]; + // TODO: but what if it was us? the delegate handles it...? or do we do + // something here? + + [_delegate userParted:nick + channel:self + withReason:reason + us:wasItUs]; } -- (void)modeSet:(NSData *)mode withParams:(NSData *)params by:(NSData *)nick -{ - [_delegate modeSet:mode forChannel:self withParams:params by:nick]; +-(void) modeSet:(NSData *)mode + withParams:(NSData *)params + by:(NSData *)nick { + // TODO: actually update the mode based on this event ... figure out what + // mode set event returns? +// _modes = + + [_delegate modeSet:mode + forChannel:self + withParams:params + by:nick]; } -- (void)topicSet:(NSData *)topic by:(NSData *)nick -{ +-(void) topicSet:(NSData *)topic + by:(NSData *)nick { _topic = topic; - [_delegate topicSet:topic forChannel:self by:nick]; + [_delegate topicSet:topic + forChannel:self + by:nick]; } -- (void)userKicked:(NSData *)nick withReason:(NSData *)reason by:(NSData *)byNick us:(BOOL)wasItUs -{ - [_delegate userKicked:nick fromChannel:self withReason:reason by:byNick us:wasItUs]; +-(void) userKicked:(NSData *)nick + withReason:(NSData *)reason + by:(NSData *)byNick + us:(BOOL)wasItUs { + if (!wasItUs) + [_nicks removeObject:nick]; + // TODO: but what if it was us? the delegate handles it...? or do we do + // something here? + + [_delegate userKicked:nick + fromChannel:self + withReason:reason + by:byNick + us:wasItUs]; } -- (void)messageSent:(NSData *)message byUser:(NSData *)nick -{ - [_delegate messageSent:message byUser:nick onChannel:self]; +-(void) messageSent:(NSData *)message + byUser:(NSData *)nick { + [_delegate messageSent:message + byUser:nick + onChannel:self]; } -- (void)noticeSent:(NSData *)notice byUser:(NSData *)nick -{ - [_delegate noticeSent:notice byUser:nick onChannel:self]; +-(void) noticeSent:(NSData *)notice + byUser:(NSData *)nick { + [_delegate noticeSent:notice + byUser:nick + onChannel:self]; } -- (void)actionPerformed:(NSData *)action byUser:(NSData *)nick -{ - [_delegate actionPerformed:action byUser:nick onChannel:self]; +-(void) actionPerformed:(NSData *)action + byUser:(NSData *)nick { + [_delegate actionPerformed:action + byUser:nick + onChannel:self]; } @end diff --git a/IRCClient/IRCClientChannelDelegate.h b/IRCClient/IRCClientChannelDelegate.h index 8d33529..03d699a 100644 --- a/IRCClient/IRCClientChannelDelegate.h +++ b/IRCClient/IRCClientChannelDelegate.h @@ -41,7 +41,8 @@ * * @param nick The nickname of the user that joined the channel. */ -- (void)userJoined:(NSData *)nick channel:(IRCClientChannel *)sender; +-(void) userJoined:(NSData *)nick + channel:(IRCClientChannel *)session; /** When an IRC client parts a channel you are connect to, you will see * an onPart event. You will also see this event when you part a channel. @@ -50,7 +51,10 @@ * @param reason (optional) The reason, if any, that the user gave for leaving. * @param wasItUs (required) Was it us who parted, or another user? */ -- (void)userParted:(NSData *)nick channel:(IRCClientChannel *)sender withReason:(NSData *)reason us:(BOOL)wasItUs; +-(void) userParted:(NSData *)nick + channel:(IRCClientChannel *)session + withReason:(NSData *)reason + us:(BOOL)wasItUs; /** Received when an IRC client changes the channel mode. What modes are available * for a given channel is an implementation detail for each server. @@ -59,14 +63,19 @@ * @param params any parameters with the mode (such as channel key). * @param nick the nickname of the IRC client that changed the mode. */ -- (void)modeSet:(NSData *)mode forChannel:(IRCClientChannel *)sender withParams:(NSData *)params by:(NSData *)nick; +-(void) modeSet:(NSData *)mode + forChannel:(IRCClientChannel *)session + withParams:(NSData *)params + by:(NSData *)nick; /** Received when the topic is changed for the channel. * * @param aTopic The new topic of the channel. * @param nick Nickname of the IRC client that changed the topic. */ -- (void)topicSet:(NSData *)topic forChannel:(IRCClientChannel *)sender by:(NSData *)nick; +-(void) topicSet:(NSData *)topic + forChannel:(IRCClientChannel *)session + by:(NSData *)nick; /** Received when an IRC client is kicked from a channel. * @@ -75,7 +84,11 @@ * @param byNick nickname of the client that performed the kick command * @param wasItUs Was it us who got kicked, or another user? */ -- (void)userKicked:(NSData *)nick fromChannel:(IRCClientChannel *)sender withReason:(NSData *)reason by:(NSData *)byNick us:(BOOL)wasItUs; +-(void) userKicked:(NSData *)nick + fromChannel:(IRCClientChannel *)session + withReason:(NSData *)reason + by:(NSData *)byNick + us:(BOOL)wasItUs; /** Received when an IRC client sends a public PRIVMSG to the channel. Note that the * user may not necessarily be required to be on the channel to send a message @@ -84,7 +97,9 @@ * @param message the message sent to the channel. * @param nick the nickname of the IRC client that sent the message. */ -- (void)messageSent:(NSData *)message byUser:(NSData *)nick onChannel:(IRCClientChannel *)sender; +-(void) messageSent:(NSData *)message + byUser:(NSData *)nick + onChannel:(IRCClientChannel *)session; /** Received when an IRC client sends a public NOTICE to the channel. Note that * the user may not necessarily be required to be on the channel to send a notice to @@ -94,13 +109,17 @@ * @param notice the notice sent to the channel. * @param nick the nickname of the IRC client that sent the notice. */ -- (void)noticeSent:(NSData *)notice byUser:(NSData *)nick onChannel:(IRCClientChannel *)sender; +-(void) noticeSent:(NSData *)notice + byUser:(NSData *)nick + onChannel:(IRCClientChannel *)session; /** Received when an IRC client sends a CTCP ACTION message to the channel. * * @param action the action message sent to the channel. * @param nick the nickname of the IRC client that sent the message. */ -- (void)actionPerformed:(NSData *)action byUser:(NSData *)nick onChannel:(IRCClientChannel *)sender; +-(void) actionPerformed:(NSData *)action + byUser:(NSData *)nick + onChannel:(IRCClientChannel *)session; @end diff --git a/IRCClient/IRCClientChannel_Private.h b/IRCClient/IRCClientChannel_Private.h index ae3e33f..77ace5f 100644 --- a/IRCClient/IRCClientChannel_Private.h +++ b/IRCClient/IRCClientChannel_Private.h @@ -27,37 +27,49 @@ /** initWithName:andIRCSession: * * Returns an initialised IRCClientChannel with a given channel name, associated - * with the given irc_session_t object. You are not expected to initialise your + * with the given irc_session_t object. You are not expected to initialize your * own IRCClientChannel objects; if you wish to join a channel you should send a * [IRCClientSession join:key:] message to your IRCClientSession object. * * @param aName Name of the channel. */ --(instancetype)initWithName:(NSData *)aName andIRCSession:(irc_session_t *)session; +-(instancetype) initWithName:(NSData *)aName + andIRCSession:(irc_session_t *)session; /****************************/ #pragma mark - Event handlers /****************************/ /* NOTE: These methods are not to be called by classes that use IRCClient; - * they are for the framework's internal use only. Do not import this header + * they are for the framework’s internal use only. Do not import this header * in files that make use of the IRCClientChannel class. */ -- (void)userJoined:(NSData *)nick; +-(void) userJoined:(NSData *)nick; -- (void)userParted:(NSData *)nick withReason:(NSData *)reason us:(BOOL)wasItUs; +-(void) userParted:(NSData *)nick + withReason:(NSData *)reason + us:(BOOL)wasItUs; -- (void)modeSet:(NSData *)mode withParams:(NSData *)params by:(NSData *)nick; +-(void) modeSet:(NSData *)mode + withParams:(NSData *)params + by:(NSData *)nick; -- (void)topicSet:(NSData *)newTopic by:(NSData *)nick; +-(void) topicSet:(NSData *)newTopic + by:(NSData *)nick; -- (void)userKicked:(NSData *)nick withReason:(NSData *)reason by:(NSData *)byNick us:(BOOL)wasItUs; +-(void) userKicked:(NSData *)nick + withReason:(NSData *)reason + by:(NSData *)byNick + us:(BOOL)wasItUs; -- (void)messageSent:(NSData *)message byUser:(NSData *)nick; +-(void) messageSent:(NSData *)message + byUser:(NSData *)nick; -- (void)noticeSent:(NSData *)notice byUser:(NSData *)nick; +-(void) noticeSent:(NSData *)notice + byUser:(NSData *)nick; -- (void)actionPerformed:(NSData *)action byUser:(NSData *)nick; +-(void) actionPerformed:(NSData *)action + byUser:(NSData *)nick; @end