Index: src/IRCChannel.h ================================================================== --- src/IRCChannel.h +++ src/IRCChannel.h @@ -19,18 +19,23 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import +#import @class OFString; @interface IRCChannel: OFObject { OFString *name; + OFMutableSet *users; } @property (readonly) OFString *name; +@property (copy) OFSet *users; + channelWithName: (OFString*)name; - initWithName: (OFString*)name; +- (void)IRC_addUser: (OFString*)user; +- (void)IRC_removeUser: (OFString*)user; @end Index: src/IRCChannel.m ================================================================== --- src/IRCChannel.m +++ src/IRCChannel.m @@ -21,11 +21,11 @@ */ #import "IRCChannel.h" @implementation IRCChannel -@synthesize name; +@synthesize name, users; + channelWithName: (OFString*)name { return [[[self alloc] initWithName: name] autorelease]; } @@ -34,10 +34,11 @@ { self = [super init]; @try { name = [name_ copy]; + users = [[OFMutableSet alloc] init]; } @catch (id e) { [self release]; @throw e; } @@ -45,14 +46,25 @@ } - (void)dealloc { [name release]; + [users release]; [super dealloc]; } - (OFString*)description { return name; } + +- (void)IRC_addUser: (OFString*)user +{ + [users addObject: user]; +} + +- (void)IRC_removeUser: (OFString*)user +{ + [users removeObject: user]; +} @end Index: src/IRCConnection.h ================================================================== --- src/IRCConnection.h +++ src/IRCConnection.h @@ -66,10 +66,12 @@ fromUser: (IRCUser*)user; - (void)connection: (IRCConnection*)connection didReceiveNotice: (OFString*)notice fromUser: (IRCUser*)user inChannel: (IRCChannel*)channel; +- (void)connection: (IRCConnection*)connection + didReceiveNamesForChannel: (IRCChannel*)channel; @end @interface IRCConnection: OFObject { OFTCPSocket *sock; Index: src/IRCConnection.m ================================================================== --- src/IRCConnection.m +++ src/IRCConnection.m @@ -224,16 +224,59 @@ [channels setObject: channel forKey: where]; } else channel = [channels objectForKey: where]; + [channel IRC_addUser: user.nickname]; + if ([delegate respondsToSelector: @selector(connection:didSeeUser:joinChannel:)]) [delegate connection: self didSeeUser: user joinChannel: channel]; + [pool release]; + return; + } + + /* NAMES reply */ + if ([action isEqual: @"353"] && split.count >= 6) { + IRCChannel *channel; + OFArray *users; + size_t pos; + + channel = [channels objectForKey: [split objectAtIndex: 4]]; + if (channel == nil) { + /* We did not request that */ + [pool release]; + return; + } + + pos = [[split objectAtIndex: 0] length] + + [[split objectAtIndex: 1] length] + + [[split objectAtIndex: 2] length] + + [[split objectAtIndex: 3] length] + + [[split objectAtIndex: 4] length] + 6; + + users = [[line substringWithRange: + of_range(pos, line.length - pos)] + componentsSeparatedByString: @" "]; + + for (OFString *user in users) { + if ([user hasPrefix: @"@"] || [user hasPrefix: @"+"] || + [user hasPrefix: @"%"] || [user hasPrefix: @"*"]) + user = [user substringWithRange: + of_range(1, user.length - 1)]; + + [channel IRC_addUser: user]; + } + + if ([delegate respondsToSelector: @selector(connection: + didReceiveNamesForChannel:)]) + [delegate connection: self + didReceiveNamesForChannel: channel]; + [pool release]; return; } /* PART */ @@ -251,10 +294,12 @@ channel = [channels objectForKey: where]; if (split.count > 3) reason = [line substringWithRange: of_range(pos + 2, line.length - pos - 2)]; + + [channel IRC_removeUser: user.nickname]; if ([delegate respondsToSelector: @selector(connection:didSeeUser:leaveChannel: withReason:)]) [delegate connection: self @@ -284,10 +329,12 @@ if (split.count > 4) reason = [line substringWithRange: of_range(pos + 2, line.length - pos - 2)]; + [channel IRC_removeUser: user.nickname]; + if ([delegate respondsToSelector: @selector(connection:didSeeUser:kickUser: fromChannel:withReason:)]) [delegate connection: self didSeeUser: user @@ -311,10 +358,13 @@ if (split.count > 2) reason = [line substringWithRange: of_range(pos + 2, line.length - pos - 2)]; + for (IRCChannel *channel in channels) + [channel IRC_removeUser: user.nickname]; + if ([delegate respondsToSelector: @selector(connection:didSeeUserQuit:withReason:)]) [delegate connection: self didSeeUserQuit: user withReason: reason]; @@ -337,10 +387,17 @@ if ([user.nickname isEqual: nickname]) { [nickname release]; nickname = [user.nickname copy]; } + + for (IRCChannel *channel in channels) { + if ([channel.users containsObject: user.nickname]) { + [channel IRC_removeUser: user.nickname]; + [channel IRC_addUser: newNickname]; + } + } if ([delegate respondsToSelector: @selector(connection:didSeeUser:changeNicknameTo:)]) [delegate connection: self didSeeUser: user Index: tests/test.m ================================================================== --- tests/test.m +++ tests/test.m @@ -130,6 +130,12 @@ fromUser: (IRCUser*)user inChannel: (IRCChannel*)channel { of_log(@"NOTICE: [%@] %@: %@", channel, user, notice); } + +- (void)connection: (IRCConnection*)connection + didReceiveNamesForChannel: (IRCChannel*)channel +{ + of_log(@"Users in %@: %@", channel, channel.users); +} @end