From 318f4a2c1ba8e4c68a2d4f491cc38ece887086a3 Mon Sep 17 00:00:00 2001 From: Jonathan Schleifer Date: Wed, 5 Oct 2011 19:40:33 +0000 Subject: [PATCH] Keep track of users in a channel. FossilOrigin-Name: 5f51d55981a74610c7d36038d540cc689b15d41194b00b2e8b0c7428bf102341 --- src/IRCChannel.h | 5 ++++ src/IRCChannel.m | 14 ++++++++++- src/IRCConnection.h | 2 ++ src/IRCConnection.m | 57 +++++++++++++++++++++++++++++++++++++++++++++ tests/test.m | 6 +++++ 5 files changed, 83 insertions(+), 1 deletion(-) diff --git a/src/IRCChannel.h b/src/IRCChannel.h index e95c3c0..168c090 100644 --- a/src/IRCChannel.h +++ b/src/IRCChannel.h @@ -21,16 +21,21 @@ */ #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 diff --git a/src/IRCChannel.m b/src/IRCChannel.m index 7238c1d..ab12595 100644 --- a/src/IRCChannel.m +++ b/src/IRCChannel.m @@ -23,7 +23,7 @@ #import "IRCChannel.h" @implementation IRCChannel -@synthesize name; +@synthesize name, users; + channelWithName: (OFString*)name { @@ -36,6 +36,7 @@ @try { name = [name_ copy]; + users = [[OFMutableSet alloc] init]; } @catch (id e) { [self release]; @throw e; @@ -47,6 +48,7 @@ - (void)dealloc { [name release]; + [users release]; [super dealloc]; } @@ -55,4 +57,14 @@ { return name; } + +- (void)IRC_addUser: (OFString*)user +{ + [users addObject: user]; +} + +- (void)IRC_removeUser: (OFString*)user +{ + [users removeObject: user]; +} @end diff --git a/src/IRCConnection.h b/src/IRCConnection.h index 39cd3d3..c6a3209 100644 --- a/src/IRCConnection.h +++ b/src/IRCConnection.h @@ -68,6 +68,8 @@ didReceiveNotice: (OFString*)notice fromUser: (IRCUser*)user inChannel: (IRCChannel*)channel; +- (void)connection: (IRCConnection*)connection + didReceiveNamesForChannel: (IRCChannel*)channel; @end @interface IRCConnection: OFObject diff --git a/src/IRCConnection.m b/src/IRCConnection.m index 62c7944..75baec5 100644 --- a/src/IRCConnection.m +++ b/src/IRCConnection.m @@ -226,6 +226,8 @@ } else channel = [channels objectForKey: where]; + [channel IRC_addUser: user.nickname]; + if ([delegate respondsToSelector: @selector(connection:didSeeUser:joinChannel:)]) [delegate connection: self @@ -236,6 +238,47 @@ 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 */ if ([action isEqual: @"PART"] && split.count >= 3) { OFString *who = [split objectAtIndex: 0]; @@ -254,6 +297,8 @@ reason = [line substringWithRange: of_range(pos + 2, line.length - pos - 2)]; + [channel IRC_removeUser: user.nickname]; + if ([delegate respondsToSelector: @selector(connection:didSeeUser:leaveChannel: withReason:)]) @@ -286,6 +331,8 @@ 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:)]) @@ -313,6 +360,9 @@ 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 @@ -340,6 +390,13 @@ 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 diff --git a/tests/test.m b/tests/test.m index 52aef63..453e7e5 100644 --- a/tests/test.m +++ b/tests/test.m @@ -132,4 +132,10 @@ OF_APPLICATION_DELEGATE(TestApp) { of_log(@"NOTICE: [%@] %@: %@", channel, user, notice); } + +- (void)connection: (IRCConnection*)connection + didReceiveNamesForChannel: (IRCChannel*)channel +{ + of_log(@"Users in %@: %@", channel, channel.users); +} @end