Skip to content

Commit

Permalink
Merge branch 'retract-event'
Browse files Browse the repository at this point in the history
* retract-event:
  Handle PubSub retract events

Conflicts:
	bccc/ui/sidebar.py
  • Loading branch information
Schnouki committed Jul 1, 2012
2 parents fc7d581 + f369d3f commit 9e0e061
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 17 deletions.
26 changes: 18 additions & 8 deletions bccc/client/channel.py
Expand Up @@ -65,21 +65,24 @@ def __init__(self, client, jid):
self.oldest_id = None

# Callbacks
self.callback_config = None
self.callback_post = None
self.callback_status = None
self.callback_config = None
self.callback_post = None
self.callback_retract = None
self.callback_status = None

def __iter__(self):
return iter(self.atoms)

def __repr__(self):
return "<bccc.client.Channel {}>".format(self.jid)

def set_callbacks(self, cb_config=None, cb_post=None, cb_status=None):
def set_callbacks(self, cb_config=None, cb_post=None, cb_retract=None, cb_status=None):
if cb_config is not None:
self.callback_config = cb_config
if cb_post is not None:
self.callback_post = cb_post
if cb_retract is not None:
self.callback_retract = cb_retract
if cb_status is not None:
self.callback_status = cb_status
# }}}
Expand Down Expand Up @@ -109,6 +112,16 @@ def handle_post_event(self, entries):
if len(atoms) > 0 and self.callback_post is not None:
self.callback_post(atoms)

def handle_retract_event(self, entries):
if len(entries) == 0:
return
# Remove retracted items from self.atoms
with self.atoms_lock:
for id_ in entries:
self.atoms.remove(id_)
if self.callback_retract is not None:
self.callback_retract(entries)

def handle_status_event(self, entries):
if len(entries) == 0:
return
Expand Down Expand Up @@ -264,10 +277,7 @@ def publish(self, text, author_name=None, in_reply_to=None):
def retract(self, id_):
log.debug("Retracting %s from channel %s", id_, self.jid)
node = "/user/{}/posts".format(self.jid)
res = self.client.ps.retract(self.client.channels_jid, node, id_, notify=True)
with self.atoms_lock:
self.atoms.remove(id_)
return res
self.client.ps.retract(self.client.channels_jid, node, id_, notify=True)

def set_status(self, text, author_name=None):
log.debug("Setting status for channel %s...", self.jid)
Expand Down
35 changes: 30 additions & 5 deletions bccc/client/client.py
Expand Up @@ -128,29 +128,52 @@ def get_channel(self, jid=None, force_new=False):
def handle_pubsub_event(self, msg):
evt = msg["pubsub_event"]

EVENT_POST = 1
EVENT_STATUS = 2
EVENT_CONFIG = 3
EVENT_POST = 1
EVENT_RETRACT = 2
EVENT_STATUS = 3
EVENT_CONFIG = 4

# Data about the event
evt_type, data, jid = None, None, None

if "items" in evt.keys():
items = evt["items"]
if len(items) == 0:
return

node = items["node"]
if not node.startswith("/user/"):
return

# Make sure that all items have the same type (not a mix of posts
# and retract...)
# It's not required by any XEP, but handling different types in the
# same event would be much more complicated :/
items_types = set(type(it) for it in items)
if len(items_types) > 1:
log.error("PubSub event with several item types are not supported")
log.debug("Unsupported event: %s", str(evt))
raise ClientError("Got PubSub event with several item types")
items_type = items_types.pop()

jid, chan_type = node[6:].rsplit("/", 1)

if chan_type == "posts":
evt_type = EVENT_POST
if items_type is xep_0060.stanza.pubsub_event.EventItem:
evt_type = EVENT_POST
data = [item.get_payload() for item in items]
elif items_type is xep_0060.stanza.pubsub_event.EventRetract:
evt_type = EVENT_RETRACT
data = [item["id"] for item in items]
else:
log.error("Unsupported items type: %s", str(items_type))
raise ClientError("Got PubSub event in posts channel with unknown items type")
elif chan_type == "status":
evt_type = EVENT_STATUS
data = [item.get_payload() for item in items]
else:
log.debug("Unsupported node type for items event: %s", node)
return
data = [item.get_payload() for item in items]

elif "configuration" in evt.keys():
evt_type = EVENT_CONFIG
Expand All @@ -170,6 +193,8 @@ def handle_pubsub_event(self, msg):

if evt_type == EVENT_POST:
chan.handle_post_event(data)
elif evt_type == EVENT_RETRACT:
chan.handle_retract_event(data)
elif evt_type == EVENT_STATUS:
chan.handle_status_event(data)
elif evt_type == EVENT_CONFIG:
Expand Down
15 changes: 12 additions & 3 deletions bccc/ui/sidebar.py
Expand Up @@ -57,9 +57,10 @@ def __init__(self, ui, channel):

# Channel callbacks
_callbacks = {
"cb_post": ui.safe_callback(self.pubsub_posts_callback),
"cb_status": ui.safe_callback(self.pubsub_status_callback),
"cb_config": ui.safe_callback(self.pubsub_config_clalback),
"cb_post": ui.safe_callback(self.pubsub_posts_callback),
"cb_retract": ui.safe_callback(self.pubsub_retract_callback),
"cb_status": ui.safe_callback(self.pubsub_status_callback),
"cb_config": ui.safe_callback(self.pubsub_config_clalback),
}
channel.set_callbacks(**_callbacks)

Expand Down Expand Up @@ -101,6 +102,14 @@ def pubsub_posts_callback(self, atoms):

self.ui.notify()

def pubsub_retract_callback(self, item_ids):
for id_ in item_ids:
self.unread_ids.discard(id_)
if self.active:
self.ui.threads_list.remove_items(item_ids)
self.ui.channels.sort_channels()
# Don't notify the user...

def pubsub_status_callback(self, atom):
self.widget_status.original_widget.set_text(atom.content)
self._invalidate()
Expand Down
6 changes: 5 additions & 1 deletion bccc/ui/thread.py
Expand Up @@ -295,7 +295,6 @@ def _delete_item(text):
id_ = w.id
log.info("Deleting post %s", id_)
self.channel.retract(id_)
self.remove(id_)
self.ui.status.set_text("Post {} deleted.".format(id_))

question = "Really delete this? ({} - {}) [y/N]: ".format(w.author, w.date)
Expand Down Expand Up @@ -388,6 +387,11 @@ def add_new_items(self, items):
self.content.add(item)
self.content._modified()

def remove_items(self, item_ids):
for id_ in item_ids:
self.content.remove(id_)
self.content._modified()

def cancel_new_item(self):
self.content.remove_extra_widget()

Expand Down

0 comments on commit 9e0e061

Please sign in to comment.