/
TNStropheMUCRoster.j
182 lines (147 loc) · 6.12 KB
/
TNStropheMUCRoster.j
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/*
* TNStropheMUCRoster.j
*
* Copyright (C) 2010 Ben Langfeld <ben@langfeld.me>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/Foundation.j>
@import "../TNStropheRosterBase.j"
/*! @ingroup strophecappuccino
this is an implementation of a basic XMPP Multi-User Chat Roster
*/
@implementation TNStropheMUCRoster : TNStropheRosterBase
{
TNStropheGroup _admins @accessors(getter=admins);
TNStropheGroup _moderators @accessors(getter=moderators);
TNStropheGroup _owners @accessors(getter=owners);
TNStropheGroup _participants @accessors(getter=participants);
TNStropheGroup _visitors @accessors(getter=visitors);
TNStropheMUCRoom _room @accessors(getter=room);
}
#pragma mark -
#pragma mark Class methods
+ (TNStropheMUCRoster)rosterWithConnection:(TNStropheConnection)aConnection forRoom:(TNStropheMUCRoom)aRoom
{
return [[TNStropheMUCRoster alloc] initWithConnection:aConnection forRoom:aRoom];
}
#pragma mark -
#pragma mark Initialization
/*! initialize a roster with a valid TNStropheConnection
@return initialized instance of TNStropheMUCRoster
*/
- (id)initWithConnection:(TNStropheConnection)aConnection forRoom:(TNStropheMUCRoom)aRoom
{
if (self = [super initWithConnection:aConnection])
{
_room = aRoom;
_visitors = [TNStropheGroup stropheGroupWithName:@"Visitors"];
_participants = [TNStropheGroup stropheGroupWithName:@"Participants"];
_moderators = [TNStropheGroup stropheGroupWithName:@"Moderators"];
_admins = [TNStropheGroup stropheGroupWithName:@"Admins"];
_owners = [TNStropheGroup stropheGroupWithName:@"Owners"];
var params = [CPDictionary dictionaryWithObjectsAndKeys:@"presence", @"name",
[[_room roomJID] bare], @"from",
{matchBare: true}, @"options"];
[_connection registerSelector:@selector(_didReceivePresence:) ofObject:self withDict:params];
}
return self;
}
#pragma mark -
#pragma mark Presence
/*! this called when the roster is recieved. Will post TNStropheMUCPresenceRetrievedNotification
@return YES to keep the selector registered with TNStropheConnection
*/
- (BOOL)_didReceivePresence:(id)aStanza
{
var contact = [self contactWithJID:[aStanza from]],
data = [aStanza firstChildWithName:@"x"],
group;
if (data && [data namespace] == @"http://jabber.org/protocol/muc#user")
{
switch ([[data firstChildWithName:@"item"] valueForAttribute:@"role"])
{
case @"visitor":
group = _visitors;
break;
case @"participant":
group = _participants;
break;
case @"moderator":
group = _moderators;
break;
}
}
if (contact)
[contact _didReceivePresence:aStanza];
else
contact = [self addContact:[aStanza from] withName:[aStanza from].split("/")[1] inGroup:group];
if ([aStanza type] === @"unavailable")
{
var statusCode;
if ([data containsChildrenWithName:@"status"])
statusCode = [[data firstChildWithName:@"status"] valueForAttribute:@"code"];
[self removeContact:contact withStatusCode:statusCode];
}
return YES;
}
#pragma mark -
#pragma mark Contacts
/*! add a new contact to the roster with given information
@param aJID the JID of the new contact
@param aName the nickname of the new contact. If nil, it will be the resource of the JID
@param aGroup the group of the new contact. if nil, it will be _visitors
@return the new TNStropheContact
*/
- (TNStropheContact)addContact:(TNStropheJID)aJID withName:(CPString)aName inGroup:(TNStropheGroup)aGroup
{
if ([self containsJID:aJID] == YES)
return;
if (!aGroup)
aGroup = _visitors;
var contact = [TNStropheContact contactWithConnection:_connection JID:aJID groupName:[aGroup name]];
[contact setNickname:aName];
[aGroup addContact:contact];
[_contacts addObject:contact];
var userInfo = [CPDictionary dictionaryWithObject:contact forKey:@"contact"];
[[CPNotificationCenter defaultCenter] postNotificationName:TNStropheMUCContactJoinedNotification object:self userInfo:userInfo];
return contact;
}
/*! remove a TNStropheContact from the roster
@param aJID the JID of the contact to remove
*/
- (void)removeContact:(TNStropheContact)aContact withStatusCode:(CPString)aStatusCode
{
[super removeContact:aContact];
var userInfo = [CPDictionary dictionaryWithObjectsAndKeys:aStatusCode, @"statusCode",
aContact, @"contact"];
[[CPNotificationCenter defaultCenter] postNotificationName:TNStropheMUCContactLeftNotification object:self userInfo:userInfo];
}
/*! return the group of given contact
@param aContact the contact
@return TNStropheGroup of the the contact
*/
- (TNStropheGroup)groupOfContact:(TNStropheContact)aContact
{
var groups = [CPArray arrayWithObjects:_visitors, _participants, _moderators, _admins, _owners];
for (var i = 0; i < [groups count]; i++)
{
var group = [groups objectAtIndex:i];
if ([[group contacts] containsObject:aContact])
return group;
}
return nil;
}
@end