# HG changeset patch # User Goffi # Date 1306606694 -7200 # Node ID f25c4077f6b937325697fdea0c12a25b84d01a4a # Parent dc7861390f108dc6d945c472bfef9df218692d2f addind contact + subscription management + misc - removed bad html_sanitize (not needed in Label !) - added isContactInRoster method in ContactPanel diff -r dc7861390f10 -r f25c4077f6b9 browser_side/contact.py --- a/browser_side/contact.py Sat May 28 20:14:38 2011 +0200 +++ b/browser_side/contact.py Sat May 28 20:18:14 2011 +0200 @@ -30,7 +30,6 @@ from pyjamas.dnd import makeDraggable from pyjamas.ui.DragWidget import DragWidget, DragContainer from jid import JID -from tools import html_sanitize class DragLabel(DragWidget): @@ -66,7 +65,7 @@ class GroupLabel(DragLabel, Label): def __init__(self, group): self.group = group - Label.__init__(self, html_sanitize(group)) #, Element=DOM.createElement('div') + Label.__init__(self, group) #, Element=DOM.createElement('div') self.setStyleName('group') DragLabel.__init__(self, group, "GROUP") @@ -75,7 +74,7 @@ def __init__(self, jid, name=None): if not name: name=jid - Label.__init__(self, html_sanitize(name)) + Label.__init__(self, name) self.jid=jid self.setStyleName('contact') DragLabel.__init__(self, jid, "CONTACT") @@ -141,14 +140,14 @@ _title = ContactTitleLabel('Contacts') DOM.setStyleAttribute(_title.getElement(), "cursor", "pointer") - self._contactList = ContactList() - self._contactList.setStyleName('contactList') + self._contact_list = ContactList() + self._contact_list.setStyleName('contactList') self._groupList = GroupList(self) self._groupList.setStyleName('groupList') self.vPanel.add(_title) self.vPanel.add(self._groupList) - self.vPanel.add(self._contactList) + self.vPanel.add(self._contact_list) self.add(self.vPanel) self.setStyleName('contactBox') @@ -163,7 +162,7 @@ self._groupList.add(group) self.host.uni_box.addKey("@%s: " % group) self.groups[group].add(jid) - self._contactList.add(jid) + self._contact_list.add(jid) def setConnected(self, jid, resource, availability, priority, statuses): """Set connection status""" @@ -177,7 +176,7 @@ if not self.connected.has_key(jid): self.connected[jid] = {} self.connected[jid][resource] = (availability, priority, statuses) - self._contactList.setState(jid, availability) + self._contact_list.setState(jid, availability) def getConnected(self): """return a list of all jid (bare jid) connected""" @@ -192,6 +191,13 @@ return True return False + def isContactInRoster(self, contact_jid): + """Test if the contact is in our roster list""" + for _contact_label in self._contact_list: + if contact_jid == _contact_label.jid: + return True + return False + def getGroups(self): return self.groups.keys() @@ -206,12 +212,12 @@ def onMouseEnter(self, sender): if isinstance(sender, GroupLabel): - for contact in self._contactList: + for contact in self._contact_list: if contact.jid in self.groups[sender.group]: contact.addStyleName("selected") def onMouseLeave(self, sender): if isinstance(sender, GroupLabel): - for contact in self._contactList: + for contact in self._contact_list: if contact.jid in self.groups[sender.group]: contact.removeStyleName("selected") diff -r dc7861390f10 -r f25c4077f6b9 browser_side/dialog.py --- a/browser_side/dialog.py Sat May 28 20:14:38 2011 +0200 +++ b/browser_side/dialog.py Sat May 28 20:18:14 2011 +0200 @@ -208,6 +208,10 @@ self.setWidget(main_panel) + def getSelectedGroups(self): + """Return a list of selected groups""" + return self.list_box.getSelectedValues() + def setAvailableGroups(self, groups): _groups = list(set(groups)) _groups.sort() diff -r dc7861390f10 -r f25c4077f6b9 browser_side/panels.py --- a/browser_side/panels.py Sat May 28 20:14:38 2011 +0200 +++ b/browser_side/panels.py Sat May 28 20:18:14 2011 +0200 @@ -55,6 +55,7 @@ from datetime import datetime from time import time import dialog +import re class MenuCmd: @@ -120,9 +121,11 @@ edit = TextBox() def addContactCb(sender): - if not edit.getText(): - Window.alert('You must enter a contact JID') + if not re.match(r'^.+@.+\..+',edit.getText(), re.IGNORECASE): + Window.alert('You must enter a valid contact JID (like "contact@libervia.org")') _dialog.show() + else: + self.host.bridge.call('addContact', None, edit.getText(), '', _dialog.getSelectedGroups() ) label = Label("new contact identifier (JID):") edit.setText('@libervia.org') @@ -629,7 +632,7 @@ normal: general info like "toto has joined the room" me: "/me" information like "/me clenches his fist" ==> "toto clenches his fist" """ - _wid = Label(html_sanitize(msg)) + _wid = Label(msg) if type == 'normal': _wid.setStyleName('chatTextInfo') elif type == 'me': diff -r dc7861390f10 -r f25c4077f6b9 libervia.py --- a/libervia.py Sat May 28 20:14:38 2011 +0200 +++ b/libervia.py Sat May 28 20:18:14 2011 +0200 @@ -27,8 +27,9 @@ from pyjamas.JSONService import JSONProxy from browser_side.register import RegisterPanel, RegisterBox from browser_side.contact import ContactPanel -from browser_side import panels +from browser_side import panels, dialog from browser_side.jid import JID +from browser_side.tools import html_sanitize class LiberviaJsonProxy(JSONProxy): def __init__(self, *args, **kwargs): @@ -65,9 +66,9 @@ class BridgeCall(LiberviaJsonProxy): def __init__(self): LiberviaJsonProxy.__init__(self, "/json_api", - ["getContacts", "sendMessage", "sendMblog", "getMblogNodes", "getProfileJid", "getHistory", "getPresenceStatus", + ["getContacts", "addContact", "sendMessage", "sendMblog", "getMblogNodes", "getProfileJid", "getHistory", "getPresenceStatus", "joinMUC", "getRoomJoined", "launchTarotGame", "getTarotCardsPaths", "tarotGameReady", "tarotGameContratChoosed", - "tarotGamePlayCards"]) + "tarotGamePlayCards", "getWaitingSub", "subscription"]) class BridgeSignals(LiberviaJsonProxy): def __init__(self): @@ -154,6 +155,7 @@ self.bridge_signals.call('getSignals', self._getSignalsCB) #We want to know our own jid self.bridge.call('getProfileJid', self._getProfileJidCB) + def _getContactsCB(self, contacts_data): for contact in contacts_data: @@ -187,13 +189,17 @@ name == 'tarotGameYourTurn' or \ name == 'tarotGameScore': self._tarotGameGenericCb(name, args[0], args[1:]) + elif name == 'subscribe': + self._subscribeCb(*args) def _getProfileJidCB(self, jid): self.whoami = JID(jid) #we can now ask our status - self.bridge.call('getPresenceStatus', self._getPresenceStatusCB) - #and the rooms where we are - self.bridge.call('getRoomJoined', self._getRoomJoinedCB) + self.bridge.call('getPresenceStatus', self._getPresenceStatusCb) + #the rooms where we are + self.bridge.call('getRoomJoined', self._getRoomJoinedCb) + #and if there is any subscription request waiting for us + self.bridge.call('getWaitingSub', self._getWaitingSubCb) ## Signals callbacks ## @@ -261,16 +267,43 @@ if isinstance(panel,panels.ChatPanel) and panel.type == 'group' and panel.target.bare == room_jid: getattr(panel.getGame("Tarot"), event_name)(*args) - def _getPresenceStatusCB(self, presence_data): + def _getPresenceStatusCb(self, presence_data): for entity in presence_data: for resource in presence_data[entity]: args = presence_data[entity][resource] self._presenceUpdateCb("%s/%s" % (entity, resource), *args) - def _getRoomJoinedCB(self, room_data): + def _getRoomJoinedCb(self, room_data): for room in room_data: self._roomJoinedCb(*room) + def _getWaitingSubCb(self, waiting_sub): + for sub in waiting_sub: + self._subscribeCb(waiting_sub[sub], sub) + + def _subscribeCb(self, sub_type, entity): + if sub_type == 'subscribed': + dialog.SimpleDialog('Subscription confirmation', 'The contact %s has added you to his/her contact list' % html_sanitize(entity)).show() + + elif sub_type == 'unsubscribed': + dialog.SimpleDialog('Subscription refusal', 'The contact %s has refused to add you in his/her contact list' % html_sanitize(entity)).show() + + elif sub_type == 'subscribe': + #The user want to subscribe to our presence + _dialog = None + msg = HTML('The contact %s want to add you in his/her contact list, do you accept ?' % html_sanitize(entity)) + + def ok_cb(): + self.bridge.call('subscription', None, "subscribed", entity, '', _dialog.getSelectedGroups()) + def cancel_cb(): + self.bridge.call('subscription', None, "unsubscribed", entity, '', '') + + _dialog = dialog.GroupSelector([msg], self.contact_panel.getGroups(), [], ok_cb, cancel_cb) + _dialog.setHTML('Add contact request') + _dialog.show() + + + if __name__ == '__main__': pyjd.setup("http://localhost:8080/libervia.html") app = SatWebFrontend() diff -r dc7861390f10 -r f25c4077f6b9 libervia.tac --- a/libervia.tac Sat May 28 20:14:38 2011 +0200 +++ b/libervia.tac Sat May 28 20:18:14 2011 +0200 @@ -142,6 +142,25 @@ profile = ISATSession(self.session).profile return self.sat_host.bridge.getContacts(profile) + def jsonrpc_addContact(self, entity, name, groups): + """Subscribe to contact presence, and add it to the given groups""" + profile = ISATSession(self.session).profile + self.sat_host.bridge.addContact(entity, profile) + self.sat_host.bridge.updateContact(entity, name, groups, profile) + + def jsonrpc_subscription(self, sub_type, entity, name, groups): + """Confirm (or infirm) subscription, + and setup user roster in case of subscription""" + profile = ISATSession(self.session).profile + self.sat_host.bridge.subscription(sub_type, entity, profile) + if sub_type == 'subscribed': + self.sat_host.bridge.updateContact(entity, name, groups, profile) + + def jsonrpc_getWaitingSub(self): + """Return list of room already joined by user""" + profile = ISATSession(self.session).profile + return self.sat_host.bridge.getWaitingSub(profile) + def jsonrpc_setStatus(self, status): """Change the status""" profile = ISATSession(self.session).profile @@ -323,6 +342,8 @@ """Create a new account, or return error @param args: dict of args as given by the form @return: "REGISTRATION" in case of success""" + #TODO: must be moved in SàT core + try: profile = login = args['login'][0] email = args['email'][0] @@ -428,6 +449,7 @@ d = defer.Deferred() self.sat_host.bridge.getMblogNodes(profile, d.callback, d.errback) d.addCallback(self._fillMblogNodes, _session) + if finish: request.write('LOGGED') request.finish() @@ -556,7 +578,8 @@ self.bridge.register("connectionError", self.signal_handler.connectionError) self.bridge.register("actionResult", self.action_handler.actionResultCb, "request") for signal_name in ['presenceUpdate', 'personalEvent', 'newMessage', 'roomJoined', 'roomUserJoined', 'roomUserLeft', 'tarotGameStarted', 'tarotGameNew', - 'tarotGameChooseContrat', 'tarotGameShowCards', 'tarotGameInvalidCards', 'tarotGameCardsPlayed', 'tarotGameYourTurn', 'tarotGameScore']: + 'tarotGameChooseContrat', 'tarotGameShowCards', 'tarotGameInvalidCards', 'tarotGameCardsPlayed', 'tarotGameYourTurn', 'tarotGameScore', + 'subscribe']: self.bridge.register(signal_name, self.signal_handler.getGenericCb(signal_name)) root.putChild('json_signal_api', self.signal_handler) root.putChild('json_api', MethodHandler(self))