Skip to content
15 changes: 14 additions & 1 deletion hookbox/channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ class Channel(object):
'moderated_subscribe': False,
'moderated_unsubscribe': False,
'presenceful': False,
'server_presenceful': False,
'server_user_presence': [],
'anonymous': False,
'polling': {
'mode': "",
Expand Down Expand Up @@ -242,7 +244,18 @@ def state_set(self, key, val):
return
self.state[key] = val
self.state_broadcast(updates={ key: val })


def state_multi_set(self, state):
#Set multiple state values at once
updates = {}
for k,v in state.iteritems():
if k in self.state and self.state[k]==v:
pass
else:
self.state[k] = v
updates[k] = v
self.state_broadcast(updates=updates)

def state_broadcast(self, updates={}, deletes=[]):
frame = {
"channel_name": self.name,
Expand Down
35 changes: 31 additions & 4 deletions hookbox/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ def __init__(self, bound_socket, bound_api_socket, config, outputter):
self.conns_by_cookie = {}
self.conns = {}
self.users = {}
self.user_channel_presence = {}
self.pool = EventletPool()

def _ws_wrapper(self, environ, start_response):
Expand Down Expand Up @@ -284,6 +285,9 @@ def get_user(self, name):
if name not in self.users:
self.users[name] = User(self, name)
self.admin.user_event('create', name, self.users[name].serialize())
if name in self.user_channel_presence:
for channel in self.user_channel_presence[name]:
channel.state_set(name, True)
return self.users[name]

def remove_user(self, name):
Expand All @@ -298,8 +302,13 @@ def remove_user(self, name):
pass
except Exception, e:
self.logger.warn("Unexpected error when removing user: %s", e, exc_info=True)

if name in self.user_channel_presence:
for channel in self.user_channel_presence[name]:
channel.state_set(name, False)

def create_channel(self, conn, channel_name, options={}, needs_auth=True):
local_options = options.copy()
if channel_name in self.channels:
raise ExpectedException("Channel already exists")
if needs_auth:
Expand All @@ -309,17 +318,34 @@ def create_channel(self, conn, channel_name, options={}, needs_auth=True):
}
success, callback_options = self.http_request('create_channel', cookie_string, form)
if success:
options.update(callback_options)
local_options.update(callback_options)
else:
raise ExpectedException(callback_options.get('error', 'Unauthorized'))
chan = self.channels[channel_name] = channel.Channel(self, channel_name, **options)

chan = self.channels[channel_name] = channel.Channel(self, channel_name, **local_options)

#If channel needs to know about server presence, register channel with users
if chan.server_presenceful:
user_state = {}
for user in chan.server_user_presence:
user_state[user] = user in self.users
if user not in self.user_channel_presence:
self.user_channel_presence[user] = [chan]
else:
self.user_channel_presence[user].append(chan)
chan.state_multi_set(user_state)

self.admin.channel_event('create_channel', channel_name, chan.serialize())

def destroy_channel(self, channel_name, needs_auth=True):
if channel_name not in self.channels:
return None
channel = self.channels[channel_name]
if channel.destroy(needs_auth):
if channel.server_presenceful:
for user in channel.server_user_presence:
self.user_channel_presence[user].remove(channel)

del self.channels[channel_name]
self.admin.channel_event('destroy_channel', channel_name, None)

Expand All @@ -333,12 +359,13 @@ def get_channel(self, conn, channel_name):

def maybe_auto_subscribe(self, user, options, conn=None):
#print 'maybe autosubscribe....'
use_conn = conn if conn else user
for destination in options.get('auto_subscribe', ()):
#print 'subscribing to', destination
channel = self.get_channel(user, destination)
channel = self.get_channel(use_conn, destination)
channel.subscribe(user, conn=conn, needs_auth=False)
for destination in options.get('auto_unsubscribe', ()):
channel = self.get_channel(user, destination)
channel = self.get_channel(use_conn, destination)
channel.unsubscribe(user, conn=conn, needs_auth=False)


Expand Down
1 change: 1 addition & 0 deletions hookbox/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class User(object):
_options = {
'reflective': True,
'moderated_message': True,
'auto_subscribe': []
}

def __init__(self, server, name, **options):
Expand Down