3 # Copyright (c) Twisted Matrix Laboratories.
4 # See LICENSE for details.
6 from zope.interface import implements
8 from twisted.cred import portal, checkers
9 from twisted.spread import pb
10 from twisted.internet import reactor
14 self.groups = {} # indexed by name
16 def joinGroup(self, groupname, user, allowMattress):
17 if not self.groups.has_key(groupname):
18 self.groups[groupname] = Group(groupname, allowMattress)
19 self.groups[groupname].addUser(user)
20 return self.groups[groupname]
23 implements(portal.IRealm)
24 def requestAvatar(self, avatarID, mind, *interfaces):
25 assert pb.IPerspective in interfaces
26 avatar = User(avatarID)
27 avatar.server = self.server
29 return pb.IPerspective, avatar, lambda a=avatar:a.detached(mind)
31 class User(pb.Avatar):
32 def __init__(self, name):
34 def attached(self, mind):
36 def detached(self, mind):
38 def perspective_joinGroup(self, groupname, allowMattress=True):
39 return self.server.joinGroup(groupname, self, allowMattress)
40 def send(self, message):
41 self.remote.callRemote("print", message)
43 class Group(pb.Viewable):
44 def __init__(self, groupname, allowMattress):
46 self.allowMattress = allowMattress
48 def addUser(self, user):
49 self.users.append(user)
50 def view_send(self, from_user, message):
51 if not self.allowMattress and "mattress" in message:
52 raise ValueError, "Don't say that word"
53 for user in self.users:
54 user.send("<%s> says: %s" % (from_user.name, message))
57 realm.server = ChatServer()
58 checker = checkers.InMemoryUsernamePasswordDatabaseDontUse()
59 checker.addUser("alice", "1234")
60 checker.addUser("bob", "secret")
61 checker.addUser("carol", "fido")
62 p = portal.Portal(realm, [checker])
64 reactor.listenTCP(8800, pb.PBServerFactory(p))