# HG changeset patch # User Emmanuel Gil Peyrot # Date 1358528135 -3600 # Node ID e629371a28d3a19b2e12d02fb11cd8cc240fbcb4 # Parent 70bae685d05c208a9fb240ca1caa629bb5dd35df Fix pep8 support in src/plugins. diff -r 70bae685d05c -r e629371a28d3 src/plugins/deprecated_misc_cs.py --- a/src/plugins/deprecated_misc_cs.py Mon Jan 21 00:59:50 2013 +0100 +++ b/src/plugins/deprecated_misc_cs.py Fri Jan 18 17:55:35 2013 +0100 @@ -40,20 +40,20 @@ from BeautifulSoup import BeautifulSoup import re - PLUGIN_INFO = { -"name": "CouchSurfing plugin", -"import_name": "CS", -"type": "Misc", -"protocols": [], -"dependencies": [], -"main": "CS_Plugin", -"handler": "no", -"description": _(u"""This plugin allow to manage your CouchSurfing account throught your SàT frontend""") + "name": "CouchSurfing plugin", + "import_name": "CS", + "type": "Misc", + "protocols": [], + "dependencies": [], + "main": "CS_Plugin", + "handler": "no", + "description": _(u"""This plugin allow to manage your CouchSurfing account throught your SàT frontend""") } AGENT = 'Salut à Toi XMPP/CS Plugin' + class CS_Plugin(object): params = """ @@ -73,16 +73,17 @@ #parameters host.memory.importParams(CS_Plugin.params) #menu - host.importMenu(_("Plugin"), "CouchSurfing", self.menuSelected, help_string = _("Launch CoushSurfing management interface")) - self.data={} #TODO: delete cookies/data after a while + host.importMenu(_("Plugin"), "CouchSurfing", self.menuSelected, help_string=_("Launch CoushSurfing management interface")) + self.data = {} # TODO: delete cookies/data after a while self.host.registerGeneralCB("plugin_CS_sendMessage", self.sendMessage) self.host.registerGeneralCB("plugin_CS_showUnreadMessages", self.showUnreadMessages) def profileConnected(self, profile): self.data[profile] = PersistentBinaryDict("plugin_CS", profile) + def dataLoaded(ignore): if not self.data[profile]: - self.data[profile] = {'cookies':{}} + self.data[profile] = {'cookies': {}} self.data[profile].load().addCallback(dataLoaded) @@ -92,7 +93,7 @@ def erroCB(self, e, id): """Called when something is going wrong when contacting CS website""" #pdb.set_trace() - message_data={"reason": "connection error", "message":_(u"Impossible to contact CS website, please check your login/password, connection or try again later")} + message_data = {"reason": "connection error", "message": _(u"Impossible to contact CS website, please check your login/password, connection or try again later")} self.host.bridge.actionResult("ERROR", id, message_data) def menuSelected(self, id, profile): @@ -100,24 +101,24 @@ login = self.host.memory.getParamA("Login", "CouchSurfing", profile_key=profile) password = self.host.memory.getParamA("Password", "CouchSurfing", profile_key=profile) if not login or not password: - message_data={"reason": "uncomplete", "message":_(u"You have to fill your CouchSurfing login & password in parameters before using this interface")} + message_data = {"reason": "uncomplete", "message": _(u"You have to fill your CouchSurfing login & password in parameters before using this interface")} self.host.bridge.actionResult("ERROR", id, message_data) return - post_data = urllib.urlencode({'auth_login[un]':login,'auth_login[pw]':password,'auth_login[action]':'Login...'}) + post_data = urllib.urlencode({'auth_login[un]': login, 'auth_login[pw]': password, 'auth_login[action]': 'Login...'}) self.data[profile]['cookies'] = {} - d = getPage('http://www.couchsurfing.org/login.html', method='POST', postdata=post_data, headers={'Content-Type':'application/x-www-form-urlencoded'} , agent=AGENT, cookies=self.data[profile]['cookies']) + d = getPage('http://www.couchsurfing.org/login.html', method='POST', postdata=post_data, headers={'Content-Type': 'application/x-www-form-urlencoded'}, agent=AGENT, cookies=self.data[profile]['cookies']) d.addCallback(self.__connectionCB, id, profile) d.addErrback(self.erroCB, id) #self.host.bridge.actionResult("SUPPRESS", id, {}) +#pages parsing callbacks -#pages parsing callbacks def savePage(self, name, html): - f = open ('/tmp/CS_'+name+'.html','w') + f = open('/tmp/CS_' + name + '.html', 'w') f.write(html) f.close() print "page [%s] sauvee" % name @@ -127,27 +128,27 @@ print 'Response received' #self.savePage('principale',html) soup = BeautifulSoup(html) - self.data[profile]['user_nick'] = soup.find('a','item_link',href='/home.html').contents[0] + self.data[profile]['user_nick'] = soup.find('a', 'item_link', href='/home.html').contents[0] self.data[profile]['user_name'] = soup.html.head.title.string.split(' - ')[1] #unread messages try: - self.data[profile]['unread_messages'] = int(soup.find(lambda tag: tag.name=='div' and ('class','item_bubble') in tag.attrs and tag.find('a', href="/messages.html?message_status=inbox")).find(text=True)) + self.data[profile]['unread_messages'] = int(soup.find(lambda tag: tag.name == 'div' and ('class', 'item_bubble') in tag.attrs and tag.find('a', href="/messages.html?message_status=inbox")).find(text=True)) except: self.data[profile]['unread_messages'] = 0 #unread couchrequest messages try: - self.data[profile]['unread_CR_messages'] = int(soup.find(lambda tag: tag.name=='div' and ('class','item_bubble') in tag.attrs and tag.find('a', href="/couchmanager")).find(text=True)) + self.data[profile]['unread_CR_messages'] = int(soup.find(lambda tag: tag.name == 'div' and ('class', 'item_bubble') in tag.attrs and tag.find('a', href="/couchmanager")).find(text=True)) except: self.data[profile]['unread_CR_messages'] = 0 #if we have already the list of friend, no need to make new requests - if not self.data[profile].has_key('friends'): + if 'friends' not in self.data[profile]: self.data[profile]['friends'] = {} d = getPage('http://www.couchsurfing.org/connections.html?type=myfriends&show=10000', agent=AGENT, cookies=self.data[profile]['cookies']) d.addCallback(self.__friendsPageCB, id=id, profile=profile) d.addErrback(self.erroCB, id) else: - self.host.bridge.actionResult("XMLUI", id, {"type":"window", "xml":self.__buildUI(self.data[profile])}) + self.host.bridge.actionResult("XMLUI", id, {"type": "window", "xml": self.__buildUI(self.data[profile])}) def __buildUI(self, data): """Build the XML UI of the plugin @@ -158,11 +159,11 @@ unread_CR_mess = data['unread_CR_messages'] friends_list = data['friends'].keys() friends_list.sort() - interface = XMLUI('window','tabs', title='CouchSurfing management') + interface = XMLUI('window', 'tabs', title='CouchSurfing management') interface.addCategory(_("Messages"), "vertical") - interface.addText(_("G'day %(name)s, you have %(nb_message)i unread message%(plural_mess)s and %(unread_CR_mess)s unread couch request message%(plural_CR)s\nIf you want to send a message, select the recipient(s) in the list below") % {'name':user_name, 'nb_message':unread_mess, 'plural_mess':'s' if unread_mess>1 else '', 'unread_CR_mess': unread_CR_mess, 'plural_CR':'s' if unread_CR_mess>1 else ''}) + interface.addText(_("G'day %(name)s, you have %(nb_message)i unread message%(plural_mess)s and %(unread_CR_mess)s unread couch request message%(plural_CR)s\nIf you want to send a message, select the recipient(s) in the list below") % {'name': user_name, 'nb_message': unread_mess, 'plural_mess': 's' if unread_mess > 1 else '', 'unread_CR_mess': unread_CR_mess, 'plural_CR': 's' if unread_CR_mess > 1 else ''}) if unread_mess: - interface.addButton('plugin_CS_showUnreadMessages', 'showUnreadMessages', _('Show unread message%(plural)s in external web browser') % {'plural':'s' if unread_mess>1 else ''}) + interface.addButton('plugin_CS_showUnreadMessages', 'showUnreadMessages', _('Show unread message%(plural)s in external web browser') % {'plural': 's' if unread_mess > 1 else ''}) interface.addList(friends_list, 'friends', style=['multi']) interface.changeLayout('pairs') interface.addLabel(_("Subject")) @@ -171,7 +172,7 @@ interface.addLabel(_("Message")) interface.addText("(use %name% for contact name and %firstname% for guessed first name)") interface.addTextBox('message') - interface.addButton('plugin_CS_sendMessage', 'sendMessage', _('send'), fields_back=['friends','subject','message']) + interface.addButton('plugin_CS_sendMessage', 'sendMessage', _('send'), fields_back=['friends', 'subject', 'message']) #interface.addCategory(_("Events"), "vertical") #TODO: coming soon, hopefuly :) #interface.addCategory(_("Couch search"), "vertical") return interface.toXml() @@ -181,28 +182,28 @@ def __friendsPageCB(self, html, id, profile): """Called when the friends list page has been received""" - self.savePage('friends',html) - soup = BeautifulSoup(html.replace('"formtable width="400','"formtable" width="400"')) #CS html fix #TODO: report the bug to CS dev team + self.savePage('friends', html) + soup = BeautifulSoup(html.replace('"formtable width="400', '"formtable" width="400"')) # CS html fix #TODO: report the bug to CS dev team friends = self.data[profile]['friends'] - for _tr in soup.findAll('tr', {'class':re.compile("^msgRow*")}): #we parse the row with friends infos - _nobr = _tr.find('nobr') #contain the friend name + for _tr in soup.findAll('tr', {'class': re.compile("^msgRow*")}): # we parse the row with friends infos + _nobr = _tr.find('nobr') # contain the friend name friend_name = unicode(_nobr.string) - friend_link = u'http://www.couchsurfing.org'+_nobr.parent['href'] + friend_link = u'http://www.couchsurfing.org' + _nobr.parent['href'] regex_href = re.compile(r'/connections\.html\?id=([^&]+)') - a_tag = _tr.find('a',href=regex_href) + a_tag = _tr.find('a', href=regex_href) friend_id = regex_href.search(unicode(a_tag)).groups()[0] - debug(_("CS friend found: %(friend_name)s (id: %(friend_id)s, link: %(friend_link)s)") % {'friend_name':friend_name, 'friend_id':friend_id, 'friend_link':friend_link}) - friends[friend_name] = {'link':friend_link,'id':friend_id} - a = soup.find('td','barmiddle next').a #is there several pages ? + debug(_("CS friend found: %(friend_name)s (id: %(friend_id)s, link: %(friend_link)s)") % {'friend_name': friend_name, 'friend_id': friend_id, 'friend_link': friend_link}) + friends[friend_name] = {'link': friend_link, 'id': friend_id} + a = soup.find('td', 'barmiddle next').a # is there several pages ? if a: #yes, we parse the next page - d = getPage('http://www.couchsurfing.org/'+str(a['href']), agent=AGENT, cookies=self.data[profile]['cookies']) + d = getPage('http://www.couchsurfing.org/' + str(a['href']), agent=AGENT, cookies=self.data[profile]['cookies']) d.addCallback(self.__friendsPageCB, id=id, profile=profile) d.addErrback(self.erroCB, id) else: #no, we show the result - self.host.bridge.actionResult("XMLUI", id, {"type":"window", "xml":self.__buildUI(self.data[profile])}) + self.host.bridge.actionResult("XMLUI", id, {"type": "window", "xml": self.__buildUI(self.data[profile])}) def __sendMessage(self, answer, subject, message, data, recipient_list, id, profile): """Send actually the message @@ -224,18 +225,18 @@ friend_id = data['friends'][recipient]['id'] except KeyError: error('INTERNAL ERROR: unknown friend') - return #send an error to the frontend - mess = message.replace('%name%',recipient).replace('%firstname%',recipient.split(' ')[0]) + return # send an error to the frontend + mess = message.replace('%name%', recipient).replace('%firstname%', recipient.split(' ')[0]) info(_('Sending message to %s') % recipient) - debug(_("\nsubject: %(subject)s\nmessage: \n---\n%(message)s\n---\n\n") % {'subject':subject,'message':mess}) - post_data = urllib.urlencode({'email[subject]':subject.encode('utf-8'),'email[body]':mess.encode('utf-8'),'email[id]':friend_id,'email[action]':'Send Message','email[replied_id]':'','email[couchsurf]':'','email[directions_to_add]':''}) - d = getPage("http://www.couchsurfing.org/send_message.html", method='POST', postdata=post_data, headers={'Content-Type':'application/x-www-form-urlencoded'} , agent=AGENT, cookies=data['cookies']) + debug(_("\nsubject: %(subject)s\nmessage: \n---\n%(message)s\n---\n\n") % {'subject': subject, 'message': mess}) + post_data = urllib.urlencode({'email[subject]': subject.encode('utf-8'), 'email[body]': mess.encode('utf-8'), 'email[id]': friend_id, 'email[action]': 'Send Message', 'email[replied_id]': '', 'email[couchsurf]': '', 'email[directions_to_add]': ''}) + d = getPage("http://www.couchsurfing.org/send_message.html", method='POST', postdata=post_data, headers={'Content-Type': 'application/x-www-form-urlencoded'}, agent=AGENT, cookies=data['cookies']) d.addCallback(self.__sendMessage, subject, message, data, recipient_list, id, profile) d.addErrback(self.erroCB, id) else: - interface = XMLUI('window', title=_('Message sent')) #TODO: create particular actionResult for alerts ? + interface = XMLUI('window', title=_('Message sent')) # TODO: create particular actionResult for alerts ? interface.addText(_('The message has been sent to every recipients')) - self.host.bridge.actionResult("XMLUI", id, {"type":"window", "xml":interface.toXml()}) + self.host.bridge.actionResult("XMLUI", id, {"type": "window", "xml": interface.toXml()}) def sendMessage(self, id, data, profile): """Called to send a message to a friend @@ -247,26 +248,25 @@ - %firstname%: guessed first name of the friend (currently the first part of the name) """ if not data['friends']: - message_data={"reason": "bad data", "message":_(u"There is not recipient selected for this message !")} + message_data = {"reason": "bad data", "message": _(u"There is not recipient selected for this message !")} self.host.bridge.actionResult("ERROR", id, message_data) return friends = data['friends'].split('\t') subject = data['subject'] message = data['message'] - info(_("sending message to %(friends)s with subject [%(subject)s]" % {'friends':friends, 'subject':subject})) + info(_("sending message to %(friends)s with subject [%(subject)s]" % {'friends': friends, 'subject': subject})) self.__sendMessage(None, subject, message, self.data[profile], friends, id, profile) def __showUnreadMessages2(self, html, id, profile): """Called when the inbox page has been received""" #FIXME: that's really too fragile, only works if the unread messages are in the first page, and it would be too resources consuming for the website to DL each time all pages. In addition, the show attribute doesn't work as expected. soup = BeautifulSoup(html) - for tag in soup.findAll(lambda tag: tag.name=='strong' and tag.a and tag.a['href'].startswith('messages.html?message_status=inbox')): - link = "http://www.couchsurfing.org/"+str(tag.a['href']) - webbrowser.open_new_tab(link) #TODO: the web browser need to already have CS cookies (i.e. already be opened & logged on CS, or be permanently loggued), a warning to the user should be sent/or a balloon-tip + for tag in soup.findAll(lambda tag: tag.name == 'strong' and tag.a and tag.a['href'].startswith('messages.html?message_status=inbox')): + link = "http://www.couchsurfing.org/" + str(tag.a['href']) + webbrowser.open_new_tab(link) # TODO: the web browser need to already have CS cookies (i.e. already be opened & logged on CS, or be permanently loggued), a warning to the user should be sent/or a balloon-tip def showUnreadMessages(self, id, data, profile): """Called when user want to see all unread messages in the external browser""" d = getPage("http://www.couchsurfing.org/messages.html?message_status=inbox&show=10000", agent=AGENT, cookies=self.data[profile]['cookies']) d.addCallback(self.__showUnreadMessages2, id, profile) d.addErrback(self.erroCB, id) - diff -r 70bae685d05c -r e629371a28d3 src/plugins/plugin_exp_parrot.py --- a/src/plugins/plugin_exp_parrot.py Mon Jan 21 00:59:50 2013 +0100 +++ b/src/plugins/plugin_exp_parrot.py Fri Jan 18 17:55:35 2013 +0100 @@ -22,21 +22,21 @@ from logging import debug, info, warning, error from twisted.words.protocols.jabber import jid - from sat.core.exceptions import UnknownEntityError from sat.tools.misc import SkipOtherTriggers PLUGIN_INFO = { -"name": "Parrot Plugin", -"import_name": "EXP-PARROT", -"type": "EXP", -"protocols": [], -"dependencies": ["XEP-0045"], -"main": "Exp_Parrot", -"handler": "no", -"description": _("""Implementation of parrot mode (repeat messages between 2 entities)""") + "name": "Parrot Plugin", + "import_name": "EXP-PARROT", + "type": "EXP", + "protocols": [], + "dependencies": ["XEP-0045"], + "main": "Exp_Parrot", + "handler": "no", + "description": _("""Implementation of parrot mode (repeat messages between 2 entities)""") } + class Exp_Parrot(object): """Parrot mode plugin: repeat messages from one entity or MUC room to another one""" #XXX: This plugin can be potentially dangerous if we don't trust entities linked @@ -123,5 +123,3 @@ del client.parrot_links[source_jid.userhostJID()] except (AttributeError, KeyError): pass - - diff -r 70bae685d05c -r e629371a28d3 src/plugins/plugin_exp_pipe.py --- a/src/plugins/plugin_exp_pipe.py Mon Jan 21 00:59:50 2013 +0100 +++ b/src/plugins/plugin_exp_pipe.py Fri Jan 18 17:55:35 2013 +0100 @@ -23,7 +23,7 @@ from twisted.words.xish import domish from twisted.words.protocols.jabber import jid from twisted.words.protocols.jabber import error as jab_error -import os, os.path +import os from twisted.internet import reactor from sat.core.exceptions import ProfileNotInCacheError @@ -34,16 +34,17 @@ PROFILE = "http://jabber.org/protocol/si/profile/" + PROFILE_NAME PLUGIN_INFO = { -"name": "Pipe Plugin", -"import_name": "EXP-PIPE", -"type": "EXP", -"protocols": ["EXP-PIPE"], -"dependencies": ["XEP-0020", "XEP-0095", "XEP-0065", "XEP-0047"], -"main": "Exp_Pipe", -"handler": "no", -"description": _("""Implementation of SI Pipe Transfer""") + "name": "Pipe Plugin", + "import_name": "EXP-PIPE", + "type": "EXP", + "protocols": ["EXP-PIPE"], + "dependencies": ["XEP-0020", "XEP-0095", "XEP-0065", "XEP-0047"], + "main": "Exp_Pipe", + "handler": "no", + "description": _("""Implementation of SI Pipe Transfer""") } + class Exp_Pipe(object): """This is a modified version of XEP-0096 to work with named pipes instead of files""" @@ -51,13 +52,13 @@ info(_("Plugin Pipe initialization")) self.host = host self.managed_stream_m = [self.host.plugins["XEP-0065"].NAMESPACE, - self.host.plugins["XEP-0047"].NAMESPACE] #Stream methods managed + self.host.plugins["XEP-0047"].NAMESPACE] # Stream methods managed self.host.plugins["XEP-0095"].registerSIProfile(PROFILE_NAME, self.transferRequest) host.bridge.addMethod("pipeOut", ".plugin", in_sign='ssa{ss}s', out_sign='s', method=self.pipeOut) def profileConnected(self, profile): client = self.host.getClient(profile) - client._pipe_waiting_for_approval = {} #key = id, value = [transfer data, IdelayedCall Reactor timeout, + client._pipe_waiting_for_approval = {} # key = id, value = [transfer data, IdelayedCall Reactor timeout, # current stream method, [failed stream methods], profile] def _kill_id(self, approval_id, profile): @@ -78,7 +79,7 @@ @param si_mime_type: Mime type of the pipe (or default "application/octet-stream" if unknown) @param si_el: domish.Element of the request @param profile: %(doc_profile)s""" - info (_("EXP-PIPE file transfer requested")) + info(_("EXP-PIPE file transfer requested")) debug(si_el.toXml()) client = self.host.getClient(profile) if not client: @@ -95,7 +96,7 @@ feature_el = feature_elts[0] form = data_form.Form.fromElement(feature_el.firstChildElement()) try: - stream_method = self.host.plugins["XEP-0020"].negociate(feature_el, 'stream-method',self.managed_stream_m) + stream_method = self.host.plugins["XEP-0020"].negociate(feature_el, 'stream-method', self.managed_stream_m) except KeyError: warning(_("No stream method found")) self.host.plugins["XEP-0095"].sendBadRequestError(iq_id, from_jid, profile) @@ -110,12 +111,11 @@ return #if we are here, the transfer can start, we just need user's agreement - data={ "id": iq_id, "from":from_jid } + data = {"id": iq_id, "from": from_jid} client._pipe_waiting_for_approval[si_id] = [data, reactor.callLater(300, self._kill_id, si_id), stream_method, [], profile] self.host.askConfirmation(si_id, "PIPE_TRANSFER", data, self.confirmationCB, profile) - def confirmationCB(self, sid, accepted, frontend_data, profile): """Called on confirmation answer @param sid: file transfer session id @@ -146,13 +146,13 @@ return #we can send the iq result - feature_elt = self.host.plugins["XEP-0020"].chooseOption({'stream-method':stream_method}) + feature_elt = self.host.plugins["XEP-0020"].chooseOption({'stream-method': stream_method}) misc_elts = [] misc_elts.append(domish.Element((PROFILE, "file"))) self.host.plugins["XEP-0095"].acceptStream(data["id"], data['from'], feature_elt, misc_elts, profile) else: - debug (_("Transfer [%s] refused"), sid) - self.host.plugins["XEP-0095"].sendRejectedError (data["id"], data['from'], profile=profile) + debug(_("Transfer [%s] refused"), sid) + self.host.plugins["XEP-0095"].sendRejectedError(data["id"], data['from'], profile=profile) del(client._pipe_waiting_for_approval[sid]) def _transferSucceeded(self, sid, file_obj, stream_method, profile): @@ -173,8 +173,8 @@ if not client: raise ProfileNotInCacheError data, timeout, stream_method, failed_methods, profile = client._pipe_waiting_for_approval[sid] - warning(_('Transfer %(id)s failed with stream method %(s_method)s') % { 'id': sid, - 's_method': stream_method }) + warning(_('Transfer %(id)s failed with stream method %(s_method)s') % {'id': sid, + 's_method': stream_method}) filepath = file_obj.name file_obj.close() #TODO: session remenber (within a time limit) when a stream method fail, and avoid that stream method with full jid for the rest of the session @@ -211,15 +211,15 @@ return if stream_method == self.host.plugins["XEP-0065"].NAMESPACE: - #fd = os.open(filepath, os.O_RDONLY | os.O_NONBLOCK) #XXX: non blocking openingl cause issues with XEP-0065's FileSender - #file_obj = os.fdopen(fd, 'r') - file_obj = open(filepath, 'r') #XXX: we have to be sure that filepath is well opened, as reading can block it - self.host.plugins["XEP-0065"].startStream(file_obj, jid.JID(IQ['from']), sid, None, self.sendSuccessCb, self.sendFailureCb, None, profile) + #fd = os.open(filepath, os.O_RDONLY | os.O_NONBLOCK) #XXX: non blocking openingl cause issues with XEP-0065's FileSender + #file_obj = os.fdopen(fd, 'r') + file_obj = open(filepath, 'r') # XXX: we have to be sure that filepath is well opened, as reading can block it + self.host.plugins["XEP-0065"].startStream(file_obj, jid.JID(IQ['from']), sid, None, self.sendSuccessCb, self.sendFailureCb, None, profile) elif stream_method == self.host.plugins["XEP-0047"].NAMESPACE: - #fd = os.open(filepath, os.O_RDONLY | os.O_NONBLOCK) #XXX: non blocking openingl cause issues with XEP-0065's FileSender - #file_obj = os.fdopen(fd, 'r') - file_obj = open(filepath, 'r') #XXX: we have to be sure that filepath is well opened, as reading can block it - self.host.plugins["XEP-0047"].startStream(file_obj, jid.JID(IQ['from']), sid, None, self.sendSuccessCb, self.sendFailureCb, None, profile) + #fd = os.open(filepath, os.O_RDONLY | os.O_NONBLOCK) #XXX: non blocking openingl cause issues with XEP-0065's FileSender + #file_obj = os.fdopen(fd, 'r') + file_obj = open(filepath, 'r') # XXX: we have to be sure that filepath is well opened, as reading can block it + self.host.plugins["XEP-0047"].startStream(file_obj, jid.JID(IQ['from']), sid, None, self.sendSuccessCb, self.sendFailureCb, None, profile) else: warning(_("Invalid stream method received")) @@ -242,7 +242,7 @@ pipe_elt = domish.Element((PROFILE, 'pipe')) pipe_transfer_elts.append(pipe_elt) - sid, offer = self.host.plugins["XEP-0095"].proposeStream(jid.JID(to_jid), PROFILE, feature_elt, pipe_transfer_elts, profile_key = profile) + sid, offer = self.host.plugins["XEP-0095"].proposeStream(jid.JID(to_jid), PROFILE, feature_elt, pipe_transfer_elts, profile_key=profile) offer.addCallback(self.pipeCb, filepath, sid, profile) return sid @@ -252,5 +252,4 @@ def sendFailureCb(self, sid, file_obj, stream_method, reason, profile): file_obj.close() - warning(_('Transfer %(id)s failed with stream method %(s_method)s %(profile)s') % { 'id': sid, "s_method": stream_method, "profile": profile }) - + warning(_('Transfer %(id)s failed with stream method %(s_method)s %(profile)s') % {'id': sid, "s_method": stream_method, "profile": profile}) diff -r 70bae685d05c -r e629371a28d3 src/plugins/plugin_misc_account.py --- a/src/plugins/plugin_misc_account.py Mon Jan 21 00:59:50 2013 +0100 +++ b/src/plugins/plugin_misc_account.py Fri Jan 18 17:55:35 2013 +0100 @@ -28,14 +28,14 @@ from twisted.mail.smtp import sendmail PLUGIN_INFO = { -"name": "Account Plugin", -"import_name": "MISC-ACCOUNT", -"type": "MISC", -"protocols": [], -"dependencies": [], -"main": "MiscAccount", -"handler": "no", -"description": _(u"""SàT account creation""") + "name": "Account Plugin", + "import_name": "MISC-ACCOUNT", + "type": "MISC", + "protocols": [], + "dependencies": [], + "main": "MiscAccount", + "handler": "no", + "description": _(u"""SàT account creation""") } #You need do adapt the following consts to your server @@ -45,24 +45,24 @@ _NEW_ACCOUNT_SERVER = "localhost" _NEW_ACCOUNT_DOMAIN = "example.net" _NEW_ACCOUNT_RESOURCE = "libervia" -_PROSODY_PATH = None #prosody path (where prosodyctl will be executed from), or None to automaticaly find it +_PROSODY_PATH = None # prosody path (where prosodyctl will be executed from), or None to automaticaly find it _PROSODYCTL = "prosodyctl" RESERVED = ['libervia'] + class ProsodyRegisterProtocol(protocol.ProcessProtocol): """ Try to register an account with prosody """ - def __init__(self, password, deferred = None): + def __init__(self, password, deferred=None): self.password = password self.deferred = deferred self.data = '' def connectionMade(self): - self.transport.write("%s\n%s" % ((self.password.encode('utf-8'),)*2)) + self.transport.write("%s\n%s" % ((self.password.encode('utf-8'), ) * 2)) self.transport.closeStdin() - def outReceived(self, data): self.data += data @@ -87,14 +87,14 @@ def __init__(self, host): info(_(u"Plugin Account initialization")) self.host = host - host.bridge.addMethod("registerSatAccount", ".plugin", in_sign='sss', out_sign='', method=self._registerAccount, async = True) + host.bridge.addMethod("registerSatAccount", ".plugin", in_sign='sss', out_sign='', method=self._registerAccount, async=True) if not self._prosody_path: paths = which(_PROSODYCTL) if not paths: - error(_("Can't find %s") % (_PROSODYCTL,)) + error(_("Can't find %s") % (_PROSODYCTL, )) else: self._prosody_path = dirname(paths[0]) - info(_('Prosody path found: %s') % (self._prosody_path,)) + info(_('Prosody path found: %s') % (self._prosody_path, )) def _registerAccount(self, email, password, profile): @@ -128,7 +128,7 @@ # and just change the password if the account already exists d = defer.Deferred() prosody_reg = ProsodyRegisterProtocol(password, d) - prosody_exe = join (self._prosody_path, _PROSODYCTL) + prosody_exe = join(self._prosody_path, _PROSODYCTL) reactor.spawnProcess(prosody_reg, prosody_exe, [prosody_exe, 'adduser', "%s@%s" % (profile, _NEW_ACCOUNT_DOMAIN)], path=self._prosody_path) d.addCallback(self._accountCreated, profile, email, password) @@ -145,7 +145,7 @@ def email_ko(ignore): #TODO: return error code to user - error ("Failed to send email to %s" % email) + error("Failed to send email to %s" % email) body = (u"""Welcome to Libervia, a Salut à Toi project part @@ -165,7 +165,7 @@ Any feedback welcome Cheers -Goffi""" % { 'login': login, 'password': password, 'jid':"%s@%s" % (login, _NEW_ACCOUNT_DOMAIN) }).encode('utf-8') +Goffi""" % {'login': login, 'password': password, 'jid': "%s@%s" % (login, _NEW_ACCOUNT_DOMAIN)}).encode('utf-8') msg = MIMEText(body, 'plain', 'UTF-8') msg['Subject'] = 'Libervia account created' msg['From'] = _email_from @@ -173,10 +173,9 @@ d = sendmail(_email_host, _email_from, email, msg.as_string()) d.addCallbacks(email_ok, email_ko) - #email to the administrator - body = (u"""New account created: %(login)s [%(email)s]""" % { 'login': login, 'email': email }).encode('utf-8') + body = (u"""New account created: %(login)s [%(email)s]""" % {'login': login, 'email': email}).encode('utf-8') msg = MIMEText(body, 'plain', 'UTF-8') msg['Subject'] = 'Libervia new account created' msg['From'] = _email_from diff -r 70bae685d05c -r e629371a28d3 src/plugins/plugin_misc_groupblog.py --- a/src/plugins/plugin_misc_groupblog.py Mon Jan 21 00:59:50 2013 +0100 +++ b/src/plugins/plugin_misc_groupblog.py Fri Jan 18 17:55:35 2013 +0100 @@ -36,7 +36,7 @@ NS_GROUPBLOG = 'http://goffi.org/protocol/groupblog' NS_NODE_PREFIX = 'urn:xmpp:groupblog:' #NS_PUBSUB_EXP = 'http://goffi.org/protocol/pubsub' #for non official features -NS_PUBSUB_EXP = NS_PUBSUB #XXX: we can't use custom namespace as Wokkel's PubSubService use official NS +NS_PUBSUB_EXP = NS_PUBSUB # XXX: we can't use custom namespace as Wokkel's PubSubService use official NS NS_PUBSUB_ITEM_ACCESS = NS_PUBSUB_EXP + "#item-access" NS_PUBSUB_CREATOR_JID_CHECK = NS_PUBSUB_EXP + "#creator-jid-check" NS_PUBSUB_ITEM_CONFIG = NS_PUBSUB_EXP + "#item-config" @@ -51,28 +51,33 @@ TYPE_COLLECTION = 'collection' PLUGIN_INFO = { -"name": "Group blogging throught collections", -"import_name": "groupblog", -"type": "MISC", -"protocols": [], -"dependencies": ["XEP-0277"], -"main": "GroupBlog", -"handler": "yes", -"description": _("""Implementation of microblogging with roster access""") + "name": "Group blogging throught collections", + "import_name": "groupblog", + "type": "MISC", + "protocols": [], + "dependencies": ["XEP-0277"], + "main": "GroupBlog", + "handler": "yes", + "description": _("""Implementation of microblogging with roster access""") } + class NoCompatiblePubSubServerFound(Exception): pass + class BadAccessTypeError(Exception): pass + class BadAccessListError(Exception): pass + class UnknownType(Exception): pass + class GroupBlog(object): """This class use a SàT PubSub Service to manage access on microblog""" @@ -81,29 +86,28 @@ self.host = host host.bridge.addMethod("sendGroupBlog", ".plugin", in_sign='sasss', out_sign='', - method=self.sendGroupBlog) + method=self.sendGroupBlog) host.bridge.addMethod("getLastGroupBlogs", ".plugin", in_sign='sis', out_sign='aa{ss}', method=self.getLastGroupBlogs, - async = True) + async=True) host.bridge.addMethod("getMassiveLastGroupBlogs", ".plugin", in_sign='sasis', out_sign='a{saa{ss}}', method=self.getMassiveLastGroupBlogs, - async = True) + async=True) host.bridge.addMethod("subscribeGroupBlog", ".plugin", in_sign='ss', out_sign='', - method=self.subscribeGroupBlog, - async = True) + method=self.subscribeGroupBlog, + async=True) host.bridge.addMethod("massiveSubscribeGroupBlogs", ".plugin", in_sign='sass', out_sign='', - method=self.massiveSubscribeGroupBlogs, - async = True) + method=self.massiveSubscribeGroupBlogs, + async=True) host.trigger.add("PubSubItemsReceived", self.pubSubItemsReceivedTrigger) - def getHandler(self, profile): return GroupBlog_handler() @@ -121,10 +125,10 @@ if not client: error(_('No client for this profile key: %s') % profile_key) raise Exception("Unknown profile") - yield client.client_initialized #we want to be sure that the client is initialized + yield client.client_initialized # we want to be sure that the client is initialized #we first check that we have a item-access pubsub server - if not hasattr(client,"item_access_pubsub"): + if not hasattr(client, "item_access_pubsub"): debug(_('Looking for item-access power pubsub server')) #we don't have any pubsub server featuring item access yet client.item_access_pubsub = None @@ -137,7 +141,7 @@ client.item_access_pubsub = entity client._item_access_pubsub_pending.callback(None) - if hasattr(client,"_item_access_pubsub_pending"): + if hasattr(client, "_item_access_pubsub_pending"): #XXX: we need to wait for item access pubsub service check yield client._item_access_pubsub_pending del client._item_access_pubsub_pending @@ -157,8 +161,8 @@ #FIXME: basic origin check, must be improved #TODO: automatic security test if (not (origin_host) - or len(event_host) < len(origin_host) - or event_host[-len(origin_host):] != origin_host): + or len(event_host) < len(origin_host) + or event_host[-len(origin_host):] != origin_host): warning("Host incoherence between %s and %s (hack attempt ?)" % (unicode(event.sender), unicode(publisher))) return @@ -169,7 +173,6 @@ return False return True - def _parseAccessData(self, microblog_data, item): form_elts = filter(lambda elt: elt.name == "x", item.children) for form_elt in form_elts: @@ -192,15 +195,12 @@ self._parseAccessData(microblog_data, item) return microblog_data - def getNodeName(self, publisher): """Retrieve the name of publisher's node @param publisher: publisher's jid @return: node's name (string)""" return NS_NODE_PREFIX + publisher.userhost() - - def _publishMblog(self, service, client, access_type, access_list, message): """Actually publish the message on the group blog @param service: jid of the item-access pubsub service @@ -209,7 +209,7 @@ @param access_list: set of entities (empty list for all, groups or jids) allowed to see the item @param message: message to publish """ - mblog_item = self.host.plugins["XEP-0277"].data2entry({'content':message}, client.profile) + mblog_item = self.host.plugins["XEP-0277"].data2entry({'content': message}, client.profile) form = data_form.Form('submit', formNamespace=NS_PUBSUB_ITEM_CONFIG) if access_type == "PUBLIC": if access_list: @@ -243,6 +243,7 @@ @profile_key: %(doc_profile)s """ print "sendGroupBlog" + def initialised(result): profile, client = result if access_type == "PUBLIC": @@ -250,7 +251,7 @@ raise Exception("Publishers list must be empty when getting microblogs for all contacts") self._publishMblog(client.item_access_pubsub, client, "PUBLIC", [], message) elif access_type == "GROUP": - _groups = set(access_list).intersection(client.roster.getGroups()) #We only keep group which actually exist + _groups = set(access_list).intersection(client.roster.getGroups()) # We only keep group which actually exist if not _groups: raise BadAccessListError("No valid group") self._publishMblog(client.item_access_pubsub, client, "GROUP", _groups, message) @@ -262,8 +263,6 @@ self.initialise(profile_key).addCallback(initialised) - - def getLastGroupBlogs(self, pub_jid, max_items=10, profile_key='@DEFAULT@'): """Get the last published microblogs @param pub_jid: jid of the publisher @@ -277,7 +276,7 @@ d = self.host.plugins["XEP-0060"].getItems(client.item_access_pubsub, self.getNodeName(jid.JID(pub_jid)), max_items=max_items, profile_key=profile_key) d.addCallback(lambda items: map(self.item2gbdata, items)) - d.addErrback(lambda ignore: {}) #TODO: more complete error management (log !) + d.addErrback(lambda ignore: {}) # TODO: more complete error management (log !) return d #TODO: we need to use the server corresponding the the host of the jid @@ -290,6 +289,7 @@ @param max_items: how many microblogs we want to get @param profile_key: profile key """ + def sendResult(result): """send result of DeferredList (list of microblogs to the calling method""" @@ -329,11 +329,10 @@ return dlist - #TODO: custom exception if publishers_type not in ["GROUP", "JID", "ALL"]: raise Exception("Bad call, unknown publishers_type") - if publishers_type=="ALL" and publishers: + if publishers_type == "ALL" and publishers: raise Exception("Publishers list must be empty when getting microblogs for all contacts") return self.initialise(profile_key).addCallback(initialised) #TODO: we need to use the server corresponding the the host of the jid @@ -348,13 +347,13 @@ #TODO: we need to use the server corresponding the the host of the jid return self.initialise(profile_key).addCallback(initialised) - def massiveSubscribeGroupBlogs(self, publishers_type, publishers, profile_key='@DEFAULT@'): """Subscribe microblogs for a list of groups or jids @param publishers_type: type of the list of publishers (one of "GROUP" or "JID" or "ALL") @param publishers: list of publishers, according to "publishers_type" (list of groups or list of jids) @param profile_key: profile key """ + def initialised(result): profile, client = result @@ -378,17 +377,15 @@ dlist = defer.DeferredList(mblogs) return dlist - #TODO: custom exception if publishers_type not in ["GROUP", "JID", "ALL"]: raise Exception("Bad call, unknown publishers_type") - if publishers_type=="ALL" and publishers: + if publishers_type == "ALL" and publishers: raise Exception("Publishers list must be empty when getting microblogs for all contacts") return self.initialise(profile_key).addCallback(initialised) #TODO: we need to use the server corresponding the the host of the jid - class GroupBlog_handler(XMPPHandler): implements(iwokkel.IDisco) @@ -397,4 +394,3 @@ def getDiscoItems(self, requestor, target, nodeIdentifier=''): return [] - diff -r 70bae685d05c -r e629371a28d3 src/plugins/plugin_misc_imap.py --- a/src/plugins/plugin_misc_imap.py Mon Jan 21 00:59:50 2013 +0100 +++ b/src/plugins/plugin_misc_imap.py Fri Jan 18 17:55:35 2013 +0100 @@ -21,34 +21,33 @@ from logging import debug, info, error import warnings -from twisted.internet import protocol,defer +from twisted.internet import protocol, defer from twisted.words.protocols.jabber import error as jab_error -from twisted.cred import portal,checkers,credentials +from twisted.cred import portal, checkers, credentials from twisted.cred import error as cred_error from twisted.mail import imap4 from twisted.python import failure from email.parser import Parser import email.message -import os,os.path +import os from cStringIO import StringIO from twisted.internet import reactor import pdb - from zope.interface import implements - PLUGIN_INFO = { -"name": "IMAP server Plugin", -"import_name": "IMAP", -"type": "Misc", -"protocols": [], -"dependencies": ["Maildir"], -"main": "IMAP_server", -"handler": "no", -"description": _("""Create an Imap server that you can use to read your "normal" type messages""") + "name": "IMAP server Plugin", + "import_name": "IMAP", + "type": "Misc", + "protocols": [], + "dependencies": ["Maildir"], + "main": "IMAP_server", + "handler": "no", + "description": _("""Create an Imap server that you can use to read your "normal" type messages""") } + class IMAP_server(object): #TODO: connect profile on mailbox request, once password is accepted @@ -75,15 +74,16 @@ self.server_factory = ImapServerFactory(self.host) reactor.listenTCP(port, self.server_factory) + class Message(object): implements(imap4.IMessage) def __init__(self, uid, flags, mess_fp): debug('Message Init') - self.uid=uid - self.flags=flags - self.mess_fp=mess_fp - self.message=Parser().parse(mess_fp) + self.uid = uid + self.flags = flags + self.mess_fp = mess_fp + self.message = Parser().parse(mess_fp) def getUID(self): """Retrieve the unique identifier associated with this message. @@ -105,7 +105,6 @@ debug('getInternalDate') return self.message['Date'] - def getHeaders(self, negate, *names): """Retrieve a group of message headers. @param names: The names of the headers to retrieve or omit. @@ -114,12 +113,12 @@ @return: A mapping of header field names to header field values """ debug('getHeaders %s - %s' % (negate, names)) - final_dict={} - to_check=[name.lower() for name in names] + final_dict = {} + to_check = [name.lower() for name in names] for header in self.message.keys(): if (negate and not header.lower() in to_check) or \ - (not negate and header.lower() in to_check): - final_dict[header]=self.message[header] + (not negate and header.lower() in to_check): + final_dict[header] = self.message[header] return final_dict def getBodyFile(self): @@ -132,17 +131,16 @@ """Retrieve the total size, in octets, of this message. """ debug('getSize') - self.mess_fp.seek(0,os.SEEK_END) + self.mess_fp.seek(0, os.SEEK_END) return self.mess_fp.tell() - def isMultipart(self): """Indicate whether this message has subparts. """ debug('isMultipart') return False - def getSubPart(self,part): + def getSubPart(self, part): """Retrieve a MIME sub-message @param part: The number of the part to retrieve, indexed from 0. @return: The specified sub-part. @@ -154,39 +152,39 @@ class SatMailbox(object): implements(imap4.IMailbox) - def __init__(self,host,name,profile): + def __init__(self, host, name, profile): self.host = host - self.listeners=set() - debug ('Mailbox init (%s)', name) - if name!="INBOX": + self.listeners = set() + debug('Mailbox init (%s)', name) + if name != "INBOX": raise imap4.MailboxException("Only INBOX is managed for the moment") - self.mailbox=self.host.plugins["Maildir"].accessMessageBox(name,self.newMessage, profile) + self.mailbox = self.host.plugins["Maildir"].accessMessageBox(name, self.newMessage, profile) def newMessage(self): """Called when a new message is in the mailbox""" - debug ("newMessage signal received") - nb_messages=self.getMessageCount() + debug("newMessage signal received") + nb_messages = self.getMessageCount() for listener in self.listeners: - listener.newMessages(nb_messages,None) + listener.newMessages(nb_messages, None) def getUIDValidity(self): """Return the unique validity identifier for this mailbox. """ - debug ('getUIDValidity') + debug('getUIDValidity') return 0 def getUIDNext(self): """Return the likely UID for the next message added to this mailbox. """ - debug ('getUIDNext') + debug('getUIDNext') return self.mailbox.getNextUid() - def getUID(self,message): + def getUID(self, message): """Return the UID of a message in the mailbox @param message: The message sequence number @return: The UID of the message. """ - debug ('getUID (%i)' % message) + debug('getUID (%i)' % message) #return self.mailbox.getUid(message-1) #XXX: it seems that this method get uid and not message sequence number return message @@ -208,7 +206,7 @@ """Return the number of messages with the 'Unseen' flag. """ debug('getUnseenCount') - return self.getMessageCount()-len(self.mailbox.getMessageIdsWithFlag('\\SEEN')) + return self.getMessageCount() - len(self.mailbox.getMessageIdsWithFlag('\\SEEN')) def isWriteable(self): """Get the read/write status of the mailbox. @@ -222,7 +220,6 @@ """ debug('destroy') - def requestStatus(self, names): """Return status information about this mailbox. @param names: The status names to return information regarding. @@ -262,7 +259,7 @@ else: raise imap4.MailboxException('Trying to remove an unknown listener') - def addMessage(self, message, flags = (), date = None): + def addMessage(self, message, flags=(), date=None): """Add the given message to this mailbox. @param message: The RFC822 formatted message @param flags: The flags to associate with this message @@ -288,24 +285,24 @@ about @param uid: If true, the IDs specified in the query are UIDs; """ - debug('fetch (%s, %s)'%(messages,uid)) + debug('fetch (%s, %s)' % (messages, uid)) if uid: messages.last = self.mailbox.getMaxUid() messages.getnext = self.mailbox.getNextExistingUid for mess_uid in messages: - if mess_uid == None: - debug ('stopping iteration') + if mess_uid is None: + debug('stopping iteration') raise StopIteration try: - yield (mess_uid,Message(mess_uid,self.mailbox.getFlagsUid(mess_uid), self.mailbox.getMessageUid(mess_uid))) + yield (mess_uid, Message(mess_uid, self.mailbox.getFlagsUid(mess_uid), self.mailbox.getMessageUid(mess_uid))) except IndexError: continue else: messages.last = self.getMessageCount() for mess_idx in messages: - if mess_idx>self.getMessageCount(): + if mess_idx > self.getMessageCount(): raise StopIteration - yield (mess_idx,Message(mess_idx,self.mailbox.getFlags(mess_idx),self.mailbox.getMessage(mess_idx-1))) + yield (mess_idx, Message(mess_idx, self.mailbox.getFlags(mess_idx), self.mailbox.getMessage(mess_idx - 1))) def store(self, messages, flags, mode, uid): """Set the flags of one or more messages. @@ -324,19 +321,19 @@ """ debug('store') - flags=[flag.upper() for flag in flags] + flags = [flag.upper() for flag in flags] - def updateFlags(getF,setF): + def updateFlags(getF, setF): ret = {} for mess_id in messages: - if (uid and mess_id == None) or (not uid and mess_id>self.getMessageCount()): + if (uid and mess_id is None) or (not uid and mess_id > self.getMessageCount()): break - _flags=set(getF(mess_id) if mode else []) - if mode==-1: + _flags = set(getF(mess_id) if mode else []) + if mode == -1: _flags.difference_update(set(flags)) else: _flags.update(set(flags)) - new_flags=list(_flags) + new_flags = list(_flags) setF(mess_id, new_flags) ret[mess_id] = tuple(new_flags) return ret @@ -344,15 +341,15 @@ if uid: messages.last = self.mailbox.getMaxUid() messages.getnext = self.mailbox.getNextExistingUid - ret = updateFlags(self.mailbox.getFlagsUid,self.mailbox.setFlagsUid) + ret = updateFlags(self.mailbox.getFlagsUid, self.mailbox.setFlagsUid) for listener in self.listeners: listener.flagsChanged(ret) return ret else: messages.last = self.getMessageCount() - ret = updateFlags(self.mailbox.getFlags,self.mailbox.setFlags) - newFlags={} + ret = updateFlags(self.mailbox.getFlags, self.mailbox.setFlags) + newFlags = {} for idx in ret: #we have to convert idx to uid for the listeners newFlags[self.mailbox.getUid(idx)] = ret[idx] @@ -366,7 +363,7 @@ @return: A list of the flags that can be set on messages in this mailbox. """ debug('getFlags') - return ['\\SEEN','\\ANSWERED','\\FLAGGED','\\DELETED','\\DRAFT'] #TODO: add '\\RECENT' + return ['\\SEEN', '\\ANSWERED', '\\FLAGGED', '\\DELETED', '\\DRAFT'] # TODO: add '\\RECENT' def getHierarchicalDelimiter(self): """Get the character which delimits namespaces for in this mailbox. @@ -374,33 +371,35 @@ debug('getHierarchicalDelimiter') return '.' + class ImapSatAccount(imap4.MemoryAccount): #implements(imap4.IAccount) def __init__(self, host, profile): debug("ImapAccount init") - self.host=host - self.profile=profile - imap4.MemoryAccount.__init__(self,profile) - self.addMailbox("Inbox") #We only manage Inbox for the moment - debug ('INBOX added') + self.host = host + self.profile = profile + imap4.MemoryAccount.__init__(self, profile) + self.addMailbox("Inbox") # We only manage Inbox for the moment + debug('INBOX added') def _emptyMailbox(self, name, id): - return SatMailbox(self.host,name,self.profile) + return SatMailbox(self.host, name, self.profile) class ImapRealm(object): implements(portal.IRealm) - def __init__(self,host): + def __init__(self, host): self.host = host def requestAvatar(self, avatarID, mind, *interfaces): debug('requestAvatar') - profile=avatarID.decode('utf-8') + profile = avatarID.decode('utf-8') if imap4.IAccount not in interfaces: raise NotImplementedError - return imap4.IAccount, ImapSatAccount(self.host,profile), lambda:None + return imap4.IAccount, ImapSatAccount(self.host, profile), lambda: None + class SatProfileCredentialChecker(object): """ @@ -412,7 +411,6 @@ credentialInterfaces = (credentials.IUsernamePassword, credentials.IUsernameHashedPassword) - def __init__(self, host): self.host = host @@ -431,20 +429,21 @@ d.addCallback(self._cbPasswordMatch, credentials.username) return d + class ImapServerFactory(protocol.ServerFactory): protocol = imap4.IMAP4Server def __init__(self, host): - self.host=host + self.host = host def startedConnecting(self, connector): - debug (_("IMAP server connection started")) + debug(_("IMAP server connection started")) def clientConnectionLost(self, connector, reason): - debug (_("IMAP server connection lost (reason: %s)"), reason) + debug(_("IMAP server connection lost (reason: %s)"), reason) def buildProtocol(self, addr): - debug ("Building protocol") + debug("Building protocol") prot = protocol.ServerFactory.buildProtocol(self, addr) prot.portal = portal.Portal(ImapRealm(self.host)) prot.portal.registerChecker(SatProfileCredentialChecker(self.host)) diff -r 70bae685d05c -r e629371a28d3 src/plugins/plugin_misc_maildir.py --- a/src/plugins/plugin_misc_maildir.py Mon Jan 21 00:59:50 2013 +0100 +++ b/src/plugins/plugin_misc_maildir.py Fri Jan 18 17:55:35 2013 +0100 @@ -21,54 +21,54 @@ from logging import debug, info, error import warnings -warnings.filterwarnings('ignore','the MimeWriter',DeprecationWarning,'twisted' ) #FIXME: to be removed, see http://twistedmatrix.com/trac/ticket/4038 +warnings.filterwarnings('ignore', 'the MimeWriter', DeprecationWarning, 'twisted') # FIXME: to be removed, see http://twistedmatrix.com/trac/ticket/4038 from twisted.internet import protocol from twisted.words.protocols.jabber import error as jab_error -from twisted.cred import portal,checkers -from twisted.mail import imap4,maildir +from twisted.cred import portal, checkers +from twisted.mail import imap4, maildir from email.parser import Parser import email.message from email.charset import Charset -import os,os.path +import os from cStringIO import StringIO from twisted.internet import reactor import pdb from sat.core.exceptions import ProfileUnknownError from sat.memory.persistent import PersistentBinaryDict - from zope.interface import implements - PLUGIN_INFO = { -"name": "Maildir Plugin", -"import_name": "Maildir", -"type": "Misc", -"protocols": [], -"dependencies": [], -"main": "MaildirBox", -"handler": "no", -"description": _("""Intercept "normal" type messages, and put them in a Maildir type box""") + "name": "Maildir Plugin", + "import_name": "Maildir", + "type": "Misc", + "protocols": [], + "dependencies": [], + "main": "MaildirBox", + "handler": "no", + "description": _("""Intercept "normal" type messages, and put them in a Maildir type box""") } MAILDIR_PATH = "Maildir" + class MaildirError(Exception): pass + class MaildirBox(object): def __init__(self, host): info(_("Plugin Maildir initialization")) self.host = host - self.__observed={} - self.data={} #list of profile spectific data. key = profile, value = PersistentBinaryDict where key=mailbox name, + self.__observed = {} + self.data = {} # list of profile spectific data. key = profile, value = PersistentBinaryDict where key=mailbox name, # and value is a dictionnary with the following value # - cur_idx: value of the current unique integer increment (UID) # - message_id (as returned by MaildirMailbox): a tuple of (UID, [flag1, flag2, ...]) - pList=host.memory.getProfilesList #shorter :) - self.__mailboxes={} #key: profile, value: {boxname: MailboxUser instance} + pList = host.memory.getProfilesList # shorter :) + self.__mailboxes = {} # key: profile, value: {boxname: MailboxUser instance} #the triggers host.trigger.add("MessageReceived", self.messageReceivedTrigger) @@ -76,11 +76,12 @@ def profileConnected(self, profile): """Called on profile connection, create profile data""" self.data[profile] = PersistentBinaryDict("plugin_maildir", profile) - self.__mailboxes[profile]={} + self.__mailboxes[profile] = {} + def dataLoaded(ignore): if not self.data[profile]: #the mailbox is new, we initiate the data - self.data[profile]["INBOX"] = {"cur_idx":0} + self.data[profile]["INBOX"] = {"cur_idx": 0} self.data[profile].load().addCallback(dataLoaded) def profileDisconnected(self, profile): @@ -108,8 +109,8 @@ profile = self.host.memory.getProfileName(profile_key) if not profile: raise ProfileUnknownError(profile_key) - if not self.__mailboxes[profile].has_key(boxname): - self.__mailboxes[profile][boxname]=MailboxUser(self, boxname, observer, profile=profile) + if boxname not in self.__mailboxes[profile]: + self.__mailboxes[profile][boxname] = MailboxUser(self, boxname, observer, profile=profile) else: if observer: self.addObserver(observer, profile, boxname) @@ -118,33 +119,33 @@ def _getProfilePath(self, profile): """Return a unique path for profile's mailbox The path must be unique, usable as a dir name, and bijectional""" - return profile.replace('/','_').replace('..','_') #FIXME: this is too naive to work well, must be improved + return profile.replace('/', '_').replace('..', '_') # FIXME: this is too naive to work well, must be improved def _removeBoxAccess(self, boxname, mailboxUser, profile): """Remove a reference to a box @param name: name of the box @param mailboxUser: MailboxUser instance""" - if not self.__mailboxes.has_key(boxname): - err_msg=_("Trying to remove an mailboxUser not referenced") + if boxname not in self.__mailboxes: + err_msg = _("Trying to remove an mailboxUser not referenced") error(_("INTERNAL ERROR: ") + err_msg) raise MaildirError(err_msg) - assert self.__mailboxes[profile][boxname]==mailboxUser + assert self.__mailboxes[profile][boxname] == mailboxUser del __mailboxes[profile][boxname] def _checkBoxReference(self, boxname, profile): """Check if there is a reference on a box, and return it @param boxname: name of the box to check @return: MailboxUser instance or None""" - if self.__mailboxes.has_key(profile): - if self.__mailboxes[profile].has_key(boxname): + if profile in self.__mailboxes: + if boxname in self.__mailboxes[profile]: return self.__mailboxes[profile][boxname] def __getBoxData(self, boxname, profile): """Return the date of a box""" try: - return self.data[profile][boxname] #the boxname MUST exist in the data + return self.data[profile][boxname] # the boxname MUST exist in the data except KeyError: - err_msg=_("Boxname doesn't exist in internal data") + err_msg = _("Boxname doesn't exist in internal data") error(_("INTERNAL ERROR: ") + err_msg) raise MaildirError(err_msg) @@ -155,11 +156,11 @@ @param message_id: unique id of the message as given by MaildirMailbox @return: Integer UID""" box_data = self.__getBoxData(boxname, profile) - if box_data.has_key(message_id): + if message_id in box_data: ret = box_data[message_id][0] else: - box_data['cur_idx']+=1 - box_data[message_id]=[box_data['cur_idx'],[]] + box_data['cur_idx'] += 1 + box_data[message_id] = [box_data['cur_idx'], []] ret = box_data[message_id] self.data[profile].force(boxname) return ret @@ -170,7 +171,7 @@ @param boxname: name of the box where the message is @return: Integer UID""" box_data = self.__getBoxData(boxname, profile) - return box_data['cur_idx']+1 + return box_data['cur_idx'] + 1 def getNextExistingUid(self, boxname, uid, profile): """Give the next uid of existing message @@ -178,10 +179,10 @@ @param uid: uid to start from @return: uid or None if the is no more message""" box_data = self.__getBoxData(boxname, profile) - idx=uid+1 - while self.getIdFromUid(boxname, idx, profile) == None: #TODO: this is highly inefficient because getIdfromUid is inefficient, fix this - idx+=1 - if idx>box_data['cur_idx']: + idx = uid + 1 + while self.getIdFromUid(boxname, idx, profile) is None: # TODO: this is highly inefficient because getIdfromUid is inefficient, fix this + idx += 1 + if idx > box_data['cur_idx']: return None return idx @@ -198,7 +199,7 @@ @param message_uid: unique integer identifier @return: unique id of the message as given by MaildirMailbox or None if not found""" box_data = self.__getBoxData(boxname, profile) - for message_id in box_data.keys(): #TODO: this is highly inefficient on big mailbox, must be replaced in the future + for message_id in box_data.keys(): # TODO: this is highly inefficient on big mailbox, must be replaced in the future if message_id == 'cur_idx': continue if box_data[message_id][0] == message_uid: @@ -211,7 +212,7 @@ @param message_idx: message id as given by MaildirMailbox @return: list of strings""" box_data = self.__getBoxData(boxname, profile) - if not box_data.has_key(mess_id): + if mess_id not in box_data: raise MailboxException("Trying to get flags from an unexisting message") return box_data[mess_id][1] @@ -222,11 +223,11 @@ @param flags: list of strings """ box_data = self.__getBoxData(boxname, profile) - assert(type(flags)==list) - flags=[flag.upper() for flag in flags] #we store every flag UPPERCASE - if not box_data.has_key(mess_id): + assert(type(flags) == list) + flags = [flag.upper() for flag in flags] # we store every flag UPPERCASE + if mess_id not in box_data: raise MailboxException("Trying to set flags for an unexisting message") - box_data[mess_id][1]=flags + box_data[mess_id][1] = flags self.data[profile].force(boxname) def getMessageIdsWithFlag(self, boxname, flag, profile): @@ -235,11 +236,11 @@ @param flag: flag to check @return: list of id (as given by MaildirMailbox)""" box_data = self.__getBoxData(boxname, profile) - assert(isinstance(flag,basestring)) - flag=flag.upper() + assert(isinstance(flag, basestring)) + flag = flag.upper() result = [] for key in box_data: - if key=='cur_idx': + if key == 'cur_idx': continue if flag in box_data[key][1]: result.append(key) @@ -250,8 +251,8 @@ @param boxname: name of the box where the message is """ box_data = self.__getBoxData(boxname, profile) - for mess_id in self.getMessageIdsWithFlag(boxname,"\\Deleted", profile): - del(box_data[mess_id]) + for mess_id in self.getMessageIdsWithFlag(boxname, "\\Deleted", profile): + del(box_data[mess_id]) self.data[profile].force(boxname) def cleanTable(self, boxname, existant_id, profile): @@ -259,9 +260,9 @@ @param boxname: name of the box to clean @param existant_id: list of id which actually exist""" box_data = self.__getBoxData(boxname, profile) - to_remove=[] + to_remove = [] for key in box_data: - if key not in existant_id and key!="cur_idx": + if key not in existant_id and key != "cur_idx": to_remove.append(key) for key in to_remove: del box_data[key] @@ -271,34 +272,34 @@ @param callback: method to call when the the box is updated @param boxname: name of the box to observe @param signal: which signal is observed by the caller""" - if not self.__observed.has_key((profile,boxname)): - self.__observed[(profile,boxname)]={} - if not self.__observed[(profile,boxname)].has_key(signal): - self.__observed[(profile,boxname)][signal]=set() - self.__observed[(profile,boxname)][signal].add(callback) + if (profile, boxname) not in self.__observed: + self.__observed[(profile, boxname)] = {} + if signal not in self.__observed[(profile, boxname)]: + self.__observed[(profile, boxname)][signal] = set() + self.__observed[(profile, boxname)][signal].add(callback) def removeObserver(self, callback, profile, boxname, signal="NEW_MESSAGE"): """Remove an observer of maildir box changes @param callback: method to remove from obervers @param boxname: name of the box which was observed @param signal: which signal was observed by the caller""" - if not self.__observed.has_key((profile,boxname)): - err_msg=_("Trying to remove an observer for an inexistant mailbox") + if (profile, boxname) not in self.__observed: + err_msg = _("Trying to remove an observer for an inexistant mailbox") error(_("INTERNAL ERROR: ") + err_msg) raise MaildirError(err_msg) - if not self.__observed[(profile,boxname)].has_key(signal): - err_msg=_("Trying to remove an inexistant observer, no observer for this signal") + if signal not in self.__observed[(profile, boxname)]: + err_msg = _("Trying to remove an inexistant observer, no observer for this signal") error(_("INTERNAL ERROR: ") + err_msg) raise MaildirError(err_msg) - if not callback in self.__observed[(profile,boxname)][signal]: - err_msg=_("Trying to remove an inexistant observer") + if not callback in self.__observed[(profile, boxname)][signal]: + err_msg = _("Trying to remove an inexistant observer") error(_("INTERNAL ERROR: ") + err_msg) raise MaildirError(err_msg) - self.__observed[(profile,boxname)][signal].remove(callback) + self.__observed[(profile, boxname)][signal].remove(callback) def emitSignal(self, profile, boxname, signal_name): """Emit the signal to observer""" - debug('emitSignal %s %s %s' %(profile, boxname, signal_name)) + debug('emitSignal %s %s %s' % (profile, boxname, signal_name)) try: for observer_cb in self.__observed[(profile, boxname)][signal_name]: observer_cb() @@ -325,7 +326,7 @@ if e.name == "body": mail.set_payload(e.children[0].encode('utf-8')) elif e.name == "subject": - mail['Subject'] = e.children[0].encode('utf-8') + mail['Subject'] = e.children[0].encode('utf-8') return mail.as_string() def __init__(self, _maildir, name, observer=None, profile="@NONE@"): @@ -334,36 +335,35 @@ @param profile: real profile (ie not a profile_key) THIS OBJECT MUST NOT BE USED DIRECTLY: use MaildirBox.accessMessageBox instead""" if _maildir._checkBoxReference(name, profile): - error ("INTERNAL ERROR: MailboxUser MUST NOT be instancied directly") + error("INTERNAL ERROR: MailboxUser MUST NOT be instancied directly") raise MailboxException('double MailboxUser instanciation') - if name!="INBOX": + if name != "INBOX": raise NotImplementedError - self.name=name - self.profile=profile - self.maildir=_maildir + self.name = name + self.profile = profile + self.maildir = _maildir profile_path = self.maildir._getProfilePath(profile) - full_profile_path = os.path.join(self.maildir.host.memory.getConfig('','local_dir'), profile_path) + full_profile_path = os.path.join(self.maildir.host.memory.getConfig('', 'local_dir'), profile_path) if not os.path.exists(full_profile_path): - os.makedirs(full_profile_path,0700) + os.makedirs(full_profile_path, 0700) mailbox_path = os.path.join(full_profile_path, MAILDIR_PATH) - self.mailbox_path=mailbox_path + self.mailbox_path = mailbox_path self.mailbox = maildir.MaildirMailbox(mailbox_path) - self.observer=observer + self.observer = observer self.__uid_table_update() if observer: - debug("adding observer for %s (%s)" % (name,profile)) + debug("adding observer for %s (%s)" % (name, profile)) self.maildir.addObserver(observer, profile, name, "NEW_MESSAGE") def __uid_table_update(self): - existant_id=[] - for mess_idx in range (self.getMessageCount()): + existant_id = [] + for mess_idx in range(self.getMessageCount()): #we update the uid table existant_id.append(self.getId(mess_idx)) self.getUid(mess_idx) self.maildir.cleanTable(self.name, existant_id, profile=self.profile) - def __del__(self): if observer: debug("removing observer for %s" % self.name) @@ -377,8 +377,8 @@ def emitSignal(self, ignore, signal): """Emit the signal to the observers""" - if signal=="NEW_MESSAGE": - self.getUid(self.getMessageCount()-1) #XXX: we make an uid for the last message added + if signal == "NEW_MESSAGE": + self.getUid(self.getMessageCount() - 1) # XXX: we make an uid for the last message added self.maildir.emitSignal(self.profile, self.name, signal) def getId(self, mess_idx): @@ -388,8 +388,8 @@ def getUid(self, mess_idx): """Return a unique interger id for the message, always ascending""" - mess_id=self.getId(mess_idx) - return self.maildir.getUid(self.name,mess_id, profile=self.profile) + mess_id = self.getId(mess_idx) + return self.maildir.getUid(self.name, mess_id, profile=self.profile) def getNextUid(self): return self.maildir.getNextUid(self.name, profile=self.profile) @@ -413,7 +413,7 @@ """Return the message index from the uid @param mess_uid: message unique identifier @return: message index, as managed by MaildirMailbox""" - for mess_idx in range (self.getMessageCount()): + for mess_idx in range(self.getMessageCount()): if self.getUid(mess_idx) == mess_uid: return mess_idx raise IndexError @@ -422,7 +422,7 @@ """Return the message index from the unique index @param mess_id: message unique index as given by MaildirMailbox @return: message sequence index""" - for mess_idx in range (self.getMessageCount()): + for mess_idx in range(self.getMessageCount()): if self.mailbox.getUidl(mess_idx) == mess_id: return mess_idx raise IndexError @@ -448,7 +448,7 @@ """Return the flags of the message @param mess_uid: message unique identifier @return: list of strings""" - id = self.maildir.getIdFromUid(self.name,mess_uid, profile=self.profile) + id = self.maildir.getIdFromUid(self.name, mess_uid, profile=self.profile) return self.maildir.getFlags(self.name, id, profile=self.profile) def setFlags(self, mess_idx, flags): @@ -464,14 +464,14 @@ @param mess_uid: message unique identifier @param flags: list of strings """ - id = self.maildir.getIdFromUid(self.name,mess_uid, profile=self.profile) + id = self.maildir.getIdFromUid(self.name, mess_uid, profile=self.profile) return self.maildir.setFlags(self.name, id, flags, profile=self.profile) def getMessageIdsWithFlag(self, flag): """Return ids of messages where a flag is set @param flag: flag to check @return: list of id (as given by MaildirMailbox)""" - return self.maildir.getMessageIdsWithFlag(self.name,flag, profile=self.profile) + return self.maildir.getMessageIdsWithFlag(self.name, flag, profile=self.profile) def removeDeleted(self): """Actually delete message flagged "\\Deleted" @@ -480,11 +480,10 @@ for mess_id in self.getMessageIdsWithFlag("\\Deleted"): print ("Deleting %s" % mess_id) self.mailbox.deleteMessage(self.getIdxFromId(mess_id)) - self.mailbox = maildir.MaildirMailbox(self.mailbox_path) #We need to reparse the dir to have coherent indexing + self.mailbox = maildir.MaildirMailbox(self.mailbox_path) # We need to reparse the dir to have coherent indexing self.maildir.purgeDeleted(self.name, profile=self.profile) def emptyTrash(self): """Delete everything in the .Trash dir""" import shutils pdb.set_trace() - diff -r 70bae685d05c -r e629371a28d3 src/plugins/plugin_misc_quiz.py --- a/src/plugins/plugin_misc_quiz.py Mon Jan 21 00:59:50 2013 +0100 +++ b/src/plugins/plugin_misc_quiz.py Fri Jan 18 17:55:35 2013 +0100 @@ -46,14 +46,14 @@ QG_REQUEST = MESSAGE + '/' + QG_TAG + '[@xmlns="' + NS_QG + '"]' PLUGIN_INFO = { -"name": "Quiz game plugin", -"import_name": "Quiz", -"type": "Game", -"protocols": [], -"dependencies": ["XEP-0045", "XEP-0249"], -"main": "Quiz", -"handler": "yes", -"description": _("""Implementation of Quiz game""") + "name": "Quiz game plugin", + "import_name": "Quiz", + "type": "Game", + "protocols": [], + "dependencies": ["XEP-0045", "XEP-0249"], + "main": "Quiz", + "handler": "yes", + "description": _("""Implementation of Quiz game""") } @@ -62,66 +62,66 @@ def __init__(self, host): info(_("Plugin Quiz initialization")) self.host = host - self.games={} - self.waiting_inv = {} #Invitation waiting for people to join to launch a game - host.bridge.addMethod("quizGameLaunch", ".plugin", in_sign='ass', out_sign='', method=self.quizGameLaunch) #args: players, profile - host.bridge.addMethod("quizGameCreate", ".plugin", in_sign='sass', out_sign='', method=self.quizGameCreate) #args: room_jid, players, profile - host.bridge.addMethod("quizGameReady", ".plugin", in_sign='sss', out_sign='', method=self.newPlayerReady) #args: player, referee, profile + self.games = {} + self.waiting_inv = {} # Invitation waiting for people to join to launch a game + host.bridge.addMethod("quizGameLaunch", ".plugin", in_sign='ass', out_sign='', method=self.quizGameLaunch) # args: players, profile + host.bridge.addMethod("quizGameCreate", ".plugin", in_sign='sass', out_sign='', method=self.quizGameCreate) # args: room_jid, players, profile + host.bridge.addMethod("quizGameReady", ".plugin", in_sign='sss', out_sign='', method=self.newPlayerReady) # args: player, referee, profile host.bridge.addMethod("quizGameAnswer", ".plugin", in_sign='ssss', out_sign='', method=self.playerAnswer) - host.bridge.addSignal("quizGameStarted", ".plugin", signature='ssass') #args: room_jid, referee, players, profile + host.bridge.addSignal("quizGameStarted", ".plugin", signature='ssass') # args: room_jid, referee, players, profile host.bridge.addSignal("quizGameNew", ".plugin", signature='sa{ss}s', - doc = { 'summary': 'Start a new game', - 'param_0': "room_jid: jid of game's room", - 'param_1': "game_data: data of the game", - 'param_2': '%(doc_profile)s'}) + doc={'summary': 'Start a new game', + 'param_0': "room_jid: jid of game's room", + 'param_1': "game_data: data of the game", + 'param_2': '%(doc_profile)s'}) host.bridge.addSignal("quizGameQuestion", ".plugin", - signature = 'sssis', - doc = { 'summary': "Send the current question", - 'param_0': "room_jid: jid of game's room", - 'param_1': "question_id: question id", - 'param_2': "question: question to ask", - 'param_3': "timer: timer", - 'param_4': '%(doc_profile)s'}) + signature='sssis', + doc={'summary': "Send the current question", + 'param_0': "room_jid: jid of game's room", + 'param_1': "question_id: question id", + 'param_2': "question: question to ask", + 'param_3': "timer: timer", + 'param_4': '%(doc_profile)s'}) host.bridge.addSignal("quizGamePlayerBuzzed", ".plugin", - signature = 'ssbs', - doc = { 'summary': "A player just pressed the buzzer", - 'param_0': "room_jid: jid of game's room", - 'param_1': "player: player who pushed the buzzer", - 'param_2': "pause: should the game be paused ?", - 'param_3': '%(doc_profile)s'}) + signature='ssbs', + doc={'summary': "A player just pressed the buzzer", + 'param_0': "room_jid: jid of game's room", + 'param_1': "player: player who pushed the buzzer", + 'param_2': "pause: should the game be paused ?", + 'param_3': '%(doc_profile)s'}) host.bridge.addSignal("quizGamePlayerSays", ".plugin", - signature = 'sssis', - doc = { 'summary': "A player just pressed the buzzer", - 'param_0': "room_jid: jid of game's room", - 'param_1': "player: player who pushed the buzzer", - 'param_2': "text: what the player say", - 'param_3': "delay: how long, in seconds, the text must appear", - 'param_4': '%(doc_profile)s'}) + signature='sssis', + doc={'summary': "A player just pressed the buzzer", + 'param_0': "room_jid: jid of game's room", + 'param_1': "player: player who pushed the buzzer", + 'param_2': "text: what the player say", + 'param_3': "delay: how long, in seconds, the text must appear", + 'param_4': '%(doc_profile)s'}) host.bridge.addSignal("quizGameAnswerResult", ".plugin", - signature = 'ssba{si}s', - doc = { 'summary': "Result of the just given answer", - 'param_0': "room_jid: jid of game's room", - 'param_1': "player: player who gave the answer", - 'param_2': "good_answer: True if the answer is right", - 'param_3': "score: dict of score with player as key", - 'param_4': '%(doc_profile)s'}) + signature='ssba{si}s', + doc={'summary': "Result of the just given answer", + 'param_0': "room_jid: jid of game's room", + 'param_1': "player: player who gave the answer", + 'param_2': "good_answer: True if the answer is right", + 'param_3': "score: dict of score with player as key", + 'param_4': '%(doc_profile)s'}) host.bridge.addSignal("quizGameTimerExpired", ".plugin", - signature = 'ss', - doc = { 'summary': "Nobody answered the question in time", - 'param_0': "room_jid: jid of game's room", - 'param_1': '%(doc_profile)s'}) + signature='ss', + doc={'summary': "Nobody answered the question in time", + 'param_0': "room_jid: jid of game's room", + 'param_1': '%(doc_profile)s'}) host.bridge.addSignal("quizGameTimerRestarted", ".plugin", - signature = 'sis', - doc = { 'summary': "Nobody answered the question in time", - 'param_0': "room_jid: jid of game's room", - 'param_1': "time_left: time left before timer expiration", - 'param_2': '%(doc_profile)s'}) + signature='sis', + doc={'summary': "Nobody answered the question in time", + 'param_0': "room_jid: jid of game's room", + 'param_1': "time_left: time left before timer expiration", + 'param_2': '%(doc_profile)s'}) host.trigger.add("MUC user joined", self.userJoinedTrigger) def createGameElt(self, to_jid, type="normal"): type = "normal" if to_jid.resource else "groupchat" - elt = domish.Element((None,'message')) + elt = domish.Element((None, 'message')) elt["to"] = to_jid.full() elt["type"] = type elt.addElement((NS_QG, QG_TAG)) @@ -129,9 +129,9 @@ def __game_data_to_xml(self, game_data): """Convert a game data dict to domish element""" - game_data_elt = domish.Element((None,'game_data')) + game_data_elt = domish.Element((None, 'game_data')) for data in game_data: - data_elt = domish.Element((None,data)) + data_elt = domish.Element((None, data)) data_elt.addContent(game_data[data]) game_data_elt.addChild(data_elt) return game_data_elt @@ -162,12 +162,12 @@ for player in game_data['players']: score[player] = players_data[player]['score'] - answer_result_elt = domish.Element((None,'answer_result')) + answer_result_elt = domish.Element((None, 'answer_result')) answer_result_elt['player'] = player_answering answer_result_elt['good_answer'] = str(good_answer) for player in score: - score_elt = domish.Element((None,"score")) + score_elt = domish.Element((None, "score")) score_elt['player'] = player score_elt['score'] = str(score[player]) answer_result_elt.addChild(score_elt) @@ -176,19 +176,19 @@ def __create_started_elt(self, players): """Create a game_started domish element""" - started_elt = domish.Element((None,'started')) + started_elt = domish.Element((None, 'started')) idx = 0 for player in players: - player_elt = domish.Element((None,'player')) + player_elt = domish.Element((None, 'player')) player_elt.addContent(player) player_elt['index'] = str(idx) - idx+=1 + idx += 1 started_elt.addChild(player_elt) return started_elt def __ask_question(self, question_id, question, timer): """Create a element for asking a question""" - question_elt = domish.Element((None,'question')) + question_elt = domish.Element((None, 'question')) question_elt['id'] = question_id question_elt['timer'] = str(timer) question_elt.addContent(question) @@ -197,14 +197,13 @@ def __start_play(self, room_jid, game_data, profile): """Start the game (tell to the first player after dealer to play""" game_data['stage'] = "play" - next_player_idx = game_data['current_player'] = (game_data['init_player'] + 1) % len(game_data['players']) #the player after the dealer start + next_player_idx = game_data['current_player'] = (game_data['init_player'] + 1) % len(game_data['players']) # the player after the dealer start game_data['first_player'] = next_player = game_data['players'][next_player_idx] - to_jid = jid.JID(room_jid.userhost()+"/"+next_player) + to_jid = jid.JID(room_jid.userhost() + "/" + next_player) mess = self.createGameElt(to_jid) yourturn_elt = mess.firstChildElement().addElement('your_turn') self.host.profiles[profile].xmlstream.send(mess) - def userJoinedTrigger(self, room, user, profile): """This trigger is used to check if we are waiting people in this room, and to create a game if everybody is here""" @@ -229,8 +228,8 @@ def quizRoomJoined(room): _room = room.occupantJID.userhostJID() for player in players: - self.host.plugins["XEP-0249"].invite(jid.JID(player), room.occupantJID.userhostJID(), {"game":"Quiz"}, profile) - self.waiting_inv[_room] = (time(), players) #TODO: remove invitation waiting for too long, using the time data + self.host.plugins["XEP-0249"].invite(jid.JID(player), room.occupantJID.userhostJID(), {"game": "Quiz"}, profile) + self.waiting_inv[_room] = (time(), players) # TODO: remove invitation waiting for too long, using the time data def after_init(ignore): room_name = "sat_quiz_%s" % self.host.plugins["XEP-0045"].getUniqueName(profile_key) @@ -262,28 +261,28 @@ @param room_jid_param: jid of the room @param players: list of players nick (nick must exist in the room) @param profile_key: %(doc_profile_key)s""" - debug (_("Creating Quiz game")) + debug(_("Creating Quiz game")) room_jid = jid.JID(room_jid_param) profile = self.host.memory.getProfileName(profile_key) if not profile: - error (_("profile %s is unknown") % profile_key) + error(_("profile %s is unknown") % profile_key) return - if self.games.has_key(room_jid): - warning (_("Quiz game already started in room %s") % room_jid.userhost()) + if room_jid in self.games: + warning(_("Quiz game already started in room %s") % room_jid.userhost()) else: room_nick = self.host.plugins["XEP-0045"].getRoomNick(room_jid.userhost(), profile) if not room_nick: - error ('Internal error') + error('Internal error') return referee = room_jid.userhost() + '/' + room_nick status = {} players_data = {} for player in players: - players_data[player] = {'score':0} + players_data[player] = {'score': 0} status[player] = "init" - self.games[room_jid.userhost()] = {'referee':referee, 'players':players, 'status':status, 'players_data':players_data, 'stage': None} + self.games[room_jid.userhost()] = {'referee': referee, 'players': players, 'status': status, 'players_data': players_data, 'stage': None} for player in players: - mess = self.createGameElt(jid.JID(room_jid.userhost()+'/'+player)) + mess = self.createGameElt(jid.JID(room_jid.userhost() + '/' + player)) mess.firstChildElement().addChild(self.__create_started_elt(players)) self.host.profiles[profile].xmlstream.send(mess) @@ -291,9 +290,9 @@ """Must be called when player is ready to start a new game""" profile = self.host.memory.getProfileName(profile_key) if not profile: - error (_("profile %s is unknown") % profile_key) + error(_("profile %s is unknown") % profile_key) return - debug ('new player ready: %s' % profile) + debug('new player ready: %s' % profile) mess = self.createGameElt(jid.JID(referee)) ready_elt = mess.firstChildElement().addElement('player_ready') ready_elt['player'] = player @@ -303,9 +302,9 @@ """Called when a player give an answer""" profile = self.host.memory.getProfileName(profile_key) if not profile: - error (_("profile %s is unknown") % profile_key) + error(_("profile %s is unknown") % profile_key) return - debug ('new player answer (%(profile)s): %(answer)s' % {'profile':profile, 'answer':answer}) + debug('new player answer (%(profile)s): %(answer)s' % {'profile': profile, 'answer': answer}) mess = self.createGameElt(jid.JID(referee)) answer_elt = mess.firstChildElement().addElement('player_answer') answer_elt['player'] = player @@ -333,7 +332,7 @@ def restartTimer(self, room_jid, profile): """Restart a timer with the saved time""" game_data = self.games[room_jid.userhost()] - assert(game_data['time_left'] != None) + assert game_data['time_left'] is not None mess = self.createGameElt(room_jid) restarted_elt = mess.firstChildElement().addElement('timer_restarted') restarted_elt["time_left"] = str(game_data['time_left']) @@ -359,7 +358,7 @@ """Check if the answer given is right""" game_data = self.games[room_jid.userhost()] players_data = game_data['players_data'] - good_answer = game_data['question_id'] == "1" and answer=="42" + good_answer = game_data['question_id'] == "1" and answer == "42" players_data[player]['score'] += 1 if good_answer else -1 players_data[player]['score'] = min(9, max(0, players_data[player]['score'])) @@ -374,7 +373,7 @@ def newGame(self, room_jid, profile): """Launch a new round""" - debug (_('new Quiz game')) + debug(_('new Quiz game')) game_data = self.games[room_jid.userhost()] players = game_data['players'] players_data = game_data['players_data'] @@ -401,30 +400,30 @@ for elt in game_elt.elements(): - if elt.name == 'started': #new game created + if elt.name == 'started': # new game created players = [] for player in elt.elements(): players.append(unicode(player)) self.host.bridge.quizGameStarted(room_jid.userhost(), from_jid.full(), players, profile) - elif elt.name == 'player_ready': #ready to play + elif elt.name == 'player_ready': # ready to play player = elt['player'] status = self.games[room_jid.userhost()]['status'] nb_players = len(self.games[room_jid.userhost()]['players']) status[player] = 'ready' - debug (_('Player %(player)s is ready to start [status: %(status)s]') % {'player':player, 'status':status}) - if status.values().count('ready') == nb_players: #everybody is ready, we can start the game + debug(_('Player %(player)s is ready to start [status: %(status)s]') % {'player': player, 'status': status}) + if status.values().count('ready') == nb_players: # everybody is ready, we can start the game self.newGame(room_jid, profile) elif elt.name == 'game_data': self.host.bridge.quizGameNew(room_jid.userhost(), self.__xml_to_game_data(elt), profile) - elif elt.name == 'question': #A question is asked - self.host.bridge.quizGameQuestion(room_jid.userhost(), elt["id"], unicode(elt), int(elt["timer"]), profile ) + elif elt.name == 'question': # A question is asked + self.host.bridge.quizGameQuestion(room_jid.userhost(), elt["id"], unicode(elt), int(elt["timer"]), profile) elif elt.name == 'player_answer': player = elt['player'] - pause = game_data['stage'] == 'question' #we pause the game only if we are have a question at the moment + pause = game_data['stage'] == 'question' # we pause the game only if we are have a question at the moment #we first send a buzzer message mess = self.createGameElt(room_jid) buzzer_elt = mess.firstChildElement().addElement('player_buzzed') @@ -460,10 +459,11 @@ self.host.bridge.quizGameTimerRestarted(room_jid.userhost(), int(elt['time_left']), profile) else: - error (_('Unmanaged game element: %s') % elt.name) + error(_('Unmanaged game element: %s') % elt.name) def getHandler(self, profile): - return QuizGameHandler(self) + return QuizGameHandler(self) + class QuizGameHandler (XMPPHandler): implements(iwokkel.IDisco) @@ -473,11 +473,10 @@ self.host = plugin_parent.host def connectionInitialized(self): - self.xmlstream.addObserver(QG_REQUEST, self.plugin_parent.quiz_game_cmd, profile = self.parent.profile) + self.xmlstream.addObserver(QG_REQUEST, self.plugin_parent.quiz_game_cmd, profile=self.parent.profile) def getDiscoInfo(self, requestor, target, nodeIdentifier=''): return [disco.DiscoFeature(NS_QG)] def getDiscoItems(self, requestor, target, nodeIdentifier=''): return [] - diff -r 70bae685d05c -r e629371a28d3 src/plugins/plugin_misc_radiocol.py --- a/src/plugins/plugin_misc_radiocol.py Mon Jan 21 00:59:50 2013 +0100 +++ b/src/plugins/plugin_misc_radiocol.py Fri Jan 18 17:55:35 2013 +0100 @@ -43,14 +43,14 @@ RADIOC_REQUEST = MESSAGE + '/' + RADIOC_TAG + '[@xmlns="' + NC_RADIOCOL + '"]' PLUGIN_INFO = { -"name": "Radio collective plugin", -"import_name": "Radiocol", -"type": "Exp", -"protocols": [], -"dependencies": ["XEP-0045", "XEP-0249"], -"main": "Radiocol", -"handler": "yes", -"description": _("""Implementation of radio collective""") + "name": "Radio collective plugin", + "import_name": "Radiocol", + "type": "Exp", + "protocols": [], + "dependencies": ["XEP-0045", "XEP-0249"], + "main": "Radiocol", + "handler": "yes", + "description": _("""Implementation of radio collective""") } QUEUE_LIMIT = 2 @@ -61,21 +61,21 @@ def __init__(self, host): info(_("Radio collective initialization")) self.host = host - self.radios={} + self.radios = {} host.bridge.addMethod("radiocolLaunch", ".plugin", in_sign='ass', out_sign='', method=self.radiocolLaunch) host.bridge.addMethod("radiocolCreate", ".plugin", in_sign='ss', out_sign='', method=self.radiocolCreate) host.bridge.addMethod("radiocolSongAdded", ".plugin", in_sign='sss', out_sign='', method=self.radiocolSongAdded) - host.bridge.addSignal("radiocolStarted", ".plugin", signature='sss') #room_jid, referee, profile - host.bridge.addSignal("radiocolSongRejected", ".plugin", signature='sss') #room_jid, reason, profile - host.bridge.addSignal("radiocolPreload", ".plugin", signature='ssssss') #room_jid, filename, title, artist, album, profile - host.bridge.addSignal("radiocolPlay", ".plugin", signature='sss') #room_jid, filename, profile - host.bridge.addSignal("radiocolNoUpload", ".plugin", signature='ss') #room_jid, profile - host.bridge.addSignal("radiocolUploadOk", ".plugin", signature='ss') #room_jid, profile + host.bridge.addSignal("radiocolStarted", ".plugin", signature='sss') # room_jid, referee, profile + host.bridge.addSignal("radiocolSongRejected", ".plugin", signature='sss') # room_jid, reason, profile + host.bridge.addSignal("radiocolPreload", ".plugin", signature='ssssss') # room_jid, filename, title, artist, album, profile + host.bridge.addSignal("radiocolPlay", ".plugin", signature='sss') # room_jid, filename, profile + host.bridge.addSignal("radiocolNoUpload", ".plugin", signature='ss') # room_jid, profile + host.bridge.addSignal("radiocolUploadOk", ".plugin", signature='ss') # room_jid, profile host.trigger.add("MUC user joined", self.userJoinedTrigger) def createRadiocolElt(self, to_jid, type="normal"): type = "normal" if to_jid.resource else "groupchat" - elt = domish.Element((None,'message')) + elt = domish.Element((None, 'message')) elt["to"] = to_jid.full() elt["type"] = type elt.addElement((NC_RADIOCOL, RADIOC_TAG)) @@ -83,26 +83,25 @@ def __create_started_elt(self): """Create a game_started domish element""" - started_elt = domish.Element((None,'started')) + started_elt = domish.Element((None, 'started')) return started_elt def __create_preload_elt(self, sender, filename, title, artist, album): - preload_elt = domish.Element((None,'preload')) + preload_elt = domish.Element((None, 'preload')) preload_elt['sender'] = sender - preload_elt['filename'] = filename #XXX: the frontend should know the temporary directory where file is put + preload_elt['filename'] = filename # XXX: the frontend should know the temporary directory where file is put preload_elt['title'] = title preload_elt['artist'] = artist preload_elt['album'] = album return preload_elt - def userJoinedTrigger(self, room, user, profile): """This trigger is used to check if we are waiting people in this room, and to create a game if everybody is here""" room_jid = room.occupantJID.userhost() - if self.radios.has_key(room_jid) and self.radios[room_jid]["referee"] == room.occupantJID.full(): + if room_jid in self.radios and self.radios[room_jid]["referee"] == room.occupantJID.full(): #we are in a radiocol room, let's start the party ! - mess = self.createRadiocolElt(jid.JID(room_jid+'/'+user.nick)) + mess = self.createRadiocolElt(jid.JID(room_jid + '/' + user.nick)) mess.firstChildElement().addChild(self.__create_started_elt()) self.host.profiles[profile].xmlstream.send(mess) return True @@ -121,7 +120,7 @@ _room_jid = room.occupantJID.userhostJID() self.radiocolCreate(_room_jid.userhost(), profile_key=profile) for occupant in occupants: - self.host.plugins["XEP-0249"].invite(jid.JID(occupant), room.occupantJID.userhostJID(), {"game":"Radiocol"}, profile) + self.host.plugins["XEP-0249"].invite(jid.JID(occupant), room.occupantJID.userhostJID(), {"game": "Radiocol"}, profile) def after_init(ignore): room_name = "sat_radiocol_%s" % self.host.plugins["XEP-0045"].getUniqueName(profile_key) @@ -153,21 +152,21 @@ """Create a new game @param room_jid_param: jid of the room @param profile_key: %(doc_profile_key)s""" - debug (_("Creating Radiocol")) + debug(_("Creating Radiocol")) room_jid = jid.JID(room_jid_param) profile = self.host.memory.getProfileName(profile_key) if not profile: - error (_("profile %s is unknown") % profile_key) + error(_("profile %s is unknown") % profile_key) return - if self.radios.has_key(room_jid): - warning (_("Radiocol already started in room %s") % room_jid.userhost()) + if room_jid in self.radios: + warning(_("Radiocol already started in room %s") % room_jid.userhost()) else: room_nick = self.host.plugins["XEP-0045"].getRoomNick(room_jid.userhost(), profile) if not room_nick: - error ('Internal error') + error('Internal error') return referee = room_jid.userhost() + '/' + room_nick - self.radios[room_jid.userhost()] = {'referee':referee, 'queue':[], 'upload':True, 'playing': False, 'occupants_data':{}, 'to_delete':{}} + self.radios[room_jid.userhost()] = {'referee': referee, 'queue': [], 'upload': True, 'playing': False, 'occupants_data': {}, 'to_delete': {}} mess = self.createRadiocolElt(jid.JID(room_jid.userhost())) mess.firstChildElement().addChild(self.__create_started_elt()) self.host.profiles[profile].xmlstream.send(mess) @@ -189,8 +188,8 @@ song = OggVorbis(song_path) except OggVorbisHeaderError: #this file is not ogg vorbis, we reject it - unlink(song_path) # FIXME: same host trick (see note above) - self.host.bridge.radiocolSongRejected(jid.JID(referee).userhost(), \ + unlink(song_path) # FIXME: same host trick (see note above) + self.host.bridge.radiocolSongRejected(jid.JID(referee).userhost(), "Uploaded file is not Ogg Vorbis song, only Ogg Vorbis songs are acceptable", profile) """mess = self.createRadiocolElt(jid.JID(referee)) reject_elt = mess.firstChildElement().addElement(('','song_rejected')) @@ -204,7 +203,7 @@ album = song.get("album", ["Unknown"])[0] length = song.info.length mess = self.createRadiocolElt(jid.JID(referee)) - added_elt = mess.firstChildElement().addElement(('','song_added')) + added_elt = mess.firstChildElement().addElement(('', 'song_added')) added_elt['filename'] = filename = os.path.basename(song_path) added_elt['title'] = title added_elt['artist'] = artist @@ -212,8 +211,8 @@ added_elt['length'] = str(length) self.host.profiles[profile].xmlstream.send(mess) - radio_data = self.radios[jid.JID(referee).userhost()] #FIXME: referee comes from Libervia's client side, it's unsecure - radio_data['to_delete'][filename] = song_path #FIXME: works only because of the same host trick, see the note under the docstring + radio_data = self.radios[jid.JID(referee).userhost()] # FIXME: referee comes from Libervia's client side, it's unsecure + radio_data['to_delete'][filename] = song_path # FIXME: works only because of the same host trick, see the note under the docstring def playNext(self, room_jid, profile): """"Play next sont in queue if exists, and put a timer @@ -231,14 +230,14 @@ filename, length = queue.pop(0) mess = self.createRadiocolElt(room_jid) - play_elt = mess.firstChildElement().addElement(('','play')) + play_elt = mess.firstChildElement().addElement(('', 'play')) play_elt['filename'] = filename self.host.profiles[profile].xmlstream.send(mess) if not radio_data['upload'] and len(queue) < QUEUE_LIMIT: #upload is blocked and we now have resources to get more, we reactivate it mess = self.createRadiocolElt(room_jid) - no_upload_elt = mess.firstChildElement().addElement(('','upload_ok')) + no_upload_elt = mess.firstChildElement().addElement(('', 'upload_ok')) self.host.profiles[profile].xmlstream.send(mess) radio_data['upload'] = True @@ -250,8 +249,7 @@ return #we wait more than the song length to delete the file, to manage poorly reactive networks/clients - reactor.callLater(length + 90, unlink, file_to_delete) #FIXME: same host trick (see above) - + reactor.callLater(length + 90, unlink, file_to_delete) # FIXME: same host trick (see above) def radiocol_game_cmd(self, mess_elt, profile): #FIXME: we should check sender (is it referee ?) here before accepting commands @@ -264,26 +262,26 @@ for elt in radio_elt.elements(): - if elt.name == 'started': #new game created + if elt.name == 'started': # new game created self.host.bridge.radiocolStarted(room_jid.userhost(), from_jid.full(), profile) - elif elt.name == 'preload': #a song is in queue and must be preloaded + elif elt.name == 'preload': # a song is in queue and must be preloaded self.host.bridge.radiocolPreload(room_jid.userhost(), elt['filename'], elt['title'], elt['artist'], elt['album'], profile) elif elt.name == 'play': self.host.bridge.radiocolPlay(room_jid.userhost(), elt['filename'], profile) - elif elt.name == 'song_rejected': #a song has been refused + elif elt.name == 'song_rejected': # a song has been refused self.host.bridge.radiocolSongRejected(room_jid.userhost(), elt['reason'], profile) elif elt.name == 'no_upload': self.host.bridge.radiocolNoUpload(room_jid.userhost(), profile) elif elt.name == 'upload_ok': self.host.bridge.radiocolUploadOk(room_jid.userhost(), profile) - elif elt.name == 'song_added': #a song has been added + elif elt.name == 'song_added': # a song has been added #FIXME: we are KISS for the proof of concept: every song is added, to a limit of 3 in queue. # Need to manage some sort of rules to allow peoples to send songs if len(queue) >= QUEUE_LIMIT: #there are already too many songs in queue, we reject this one mess = self.createRadiocolElt(room_jid) - reject_elt = mess.firstChildElement().addElement(('','song_rejected')) + reject_elt = mess.firstChildElement().addElement(('', 'song_rejected')) reject_elt['sender'] = from_jid.resource reject_elt['reason'] = "Too many songs in queue" #FIXME: add an error code @@ -296,12 +294,11 @@ if len(queue) >= QUEUE_LIMIT: #We are at the limit, we refuse new upload until next play mess = self.createRadiocolElt(room_jid) - no_upload_elt = mess.firstChildElement().addElement(('','no_upload')) + no_upload_elt = mess.firstChildElement().addElement(('', 'no_upload')) #FIXME: add an error code self.host.profiles[profile].xmlstream.send(mess) radio_data['upload'] = False - mess = self.createRadiocolElt(room_jid) preload_elt = self.__create_preload_elt(from_jid.resource, elt['filename'], @@ -316,10 +313,11 @@ radio_data['playing'] = True self.playNext(room_jid, profile) else: - error (_('Unmanaged game element: %s') % elt.name) + error(_('Unmanaged game element: %s') % elt.name) def getHandler(self, profile): - return RadiocolHandler(self) + return RadiocolHandler(self) + class RadiocolHandler (XMPPHandler): implements(iwokkel.IDisco) @@ -329,11 +327,10 @@ self.host = plugin_parent.host def connectionInitialized(self): - self.xmlstream.addObserver(RADIOC_REQUEST, self.plugin_parent.radiocol_game_cmd, profile = self.parent.profile) + self.xmlstream.addObserver(RADIOC_REQUEST, self.plugin_parent.radiocol_game_cmd, profile=self.parent.profile) def getDiscoInfo(self, requestor, target, nodeIdentifier=''): return [disco.DiscoFeature(NC_RADIOCOL)] def getDiscoItems(self, requestor, target, nodeIdentifier=''): return [] - diff -r 70bae685d05c -r e629371a28d3 src/plugins/plugin_misc_smtp.py --- a/src/plugins/plugin_misc_smtp.py Mon Jan 21 00:59:50 2013 +0100 +++ b/src/plugins/plugin_misc_smtp.py Fri Jan 18 17:55:35 2013 +0100 @@ -21,33 +21,32 @@ from logging import debug, info, error import warnings -from twisted.internet import protocol,defer +from twisted.internet import protocol, defer from twisted.words.protocols.jabber import error as jab_error -from twisted.cred import portal,checkers,credentials +from twisted.cred import portal, checkers, credentials from twisted.cred import error as cred_error from twisted.mail import smtp from twisted.python import failure from email.parser import Parser from email.utils import parseaddr from twisted.mail.imap4 import LOGINCredentials, PLAINCredentials -import os,os.path +import os from twisted.internet import reactor import sys - from zope.interface import implements +PLUGIN_INFO = { + "name": "SMTP server Plugin", + "import_name": "SMTP", + "type": "Misc", + "protocols": [], + "dependencies": ["Maildir"], + "main": "SMTP_server", + "handler": "no", + "description": _("""Create a SMTP server that you can use to send your "normal" type messages""") +} -PLUGIN_INFO = { -"name": "SMTP server Plugin", -"import_name": "SMTP", -"type": "Misc", -"protocols": [], -"dependencies": ["Maildir"], -"main": "SMTP_server", -"handler": "no", -"description": _("""Create a SMTP server that you can use to send your "normal" type messages""") -} class SMTP_server(object): @@ -74,13 +73,14 @@ self.server_factory = SmtpServerFactory(self.host) reactor.listenTCP(port, self.server_factory) + class SatSmtpMessage(object): implements(smtp.IMessage) def __init__(self, host, profile): - self.host=host - self.profile=profile - self.message=[] + self.host = host + self.profile = profile + self.message = [] def lineReceived(self, line): """handle another line""" @@ -90,25 +90,26 @@ """handle end of message""" mail = Parser().parsestr("\n".join(self.message)) try: - self.host.sendMessage(parseaddr(mail['to'].decode('utf-8','replace'))[1], mail.get_payload().decode('utf-8','replace'), #TODO: manage other charsets - subject=mail['subject'].decode('utf-8','replace'), mess_type='normal', profile_key=self.profile) + self.host.sendMessage(parseaddr(mail['to'].decode('utf-8', 'replace'))[1], mail.get_payload().decode('utf-8', 'replace'), # TODO: manage other charsets + subject=mail['subject'].decode('utf-8', 'replace'), mess_type='normal', profile_key=self.profile) except: exc_type, exc_value, exc_traceback = sys.exc_info() - error(_("Can't send message: %s") % exc_value) #The email is invalid or incorreclty parsed + error(_("Can't send message: %s") % exc_value) # The email is invalid or incorreclty parsed return defer.fail() - self.message=None + self.message = None return defer.succeed(None) def connectionLost(self): """handle message truncated""" raise smtp.SMTPError + class SatSmtpDelivery(object): implements(smtp.IMessageDelivery) def __init__(self, host, profile): - self.host=host - self.profile=profile + self.host = host + self.profile = profile def receivedHeader(self, helo, origin, recipients): """ @@ -144,18 +145,20 @@ """ return origin + class SmtpRealm(object): implements(portal.IRealm) - def __init__(self,host): + def __init__(self, host): self.host = host def requestAvatar(self, avatarID, mind, *interfaces): debug('requestAvatar') - profile=avatarID.decode('utf-8') + profile = avatarID.decode('utf-8') if smtp.IMessageDelivery not in interfaces: raise NotImplementedError - return smtp.IMessageDelivery, SatSmtpDelivery(self.host,profile), lambda:None + return smtp.IMessageDelivery, SatSmtpDelivery(self.host, profile), lambda: None + class SatProfileCredentialChecker(object): """ @@ -167,7 +170,6 @@ credentialInterfaces = (credentials.IUsernamePassword, credentials.IUsernameHashedPassword) - def __init__(self, host): self.host = host @@ -182,26 +184,26 @@ if not credentials.username in profiles: return defer.fail(cred_error.UnauthorizedLogin()) password = self.host.memory.getParamA("Password", "Connection", profile_key=credentials.username) - return defer.maybeDeferred( - credentials.checkPassword, - password).addCallback( - self._cbPasswordMatch, credentials.username) + return defer.maybeDeferred(credentials.checkPassword, + password).addCallback(self._cbPasswordMatch, + credentials.username) + class SmtpServerFactory(smtp.SMTPFactory): def __init__(self, host): self.protocol = smtp.ESMTP - self.host=host + self.host = host _portal = portal.Portal(SmtpRealm(self.host)) _portal.registerChecker(SatProfileCredentialChecker(self.host)) smtp.SMTPFactory.__init__(self, _portal) def startedConnecting(self, connector): - debug (_("SMTP server connection started")) + debug(_("SMTP server connection started")) smtp.SMTPFactory.startedConnecting(self, connector) def clientConnectionLost(self, connector, reason): - debug (_("SMTP server connection lost (reason: %s)"), reason) + debug(_("SMTP server connection lost (reason: %s)"), reason) smtp.SMTPFactory.clientConnectionLost(self, connector, reason) def buildProtocol(self, addr): @@ -209,4 +211,3 @@ # add the challengers from imap4, more secure and complicated challengers are available p.challengers = {"LOGIN": LOGINCredentials, "PLAIN": PLAINCredentials} return p - diff -r 70bae685d05c -r e629371a28d3 src/plugins/plugin_misc_tarot.py --- a/src/plugins/plugin_misc_tarot.py Mon Jan 21 00:59:50 2013 +0100 +++ b/src/plugins/plugin_misc_tarot.py Fri Jan 18 17:55:35 2013 +0100 @@ -43,14 +43,14 @@ CG_REQUEST = MESSAGE + '/' + CG_TAG + '[@xmlns="' + NS_CG + '"]' PLUGIN_INFO = { -"name": "Tarot cards plugin", -"import_name": "Tarot", -"type": "Misc", -"protocols": [], -"dependencies": ["XEP-0045", "XEP-0249"], -"main": "Tarot", -"handler": "yes", -"description": _("""Implementation of Tarot card game""") + "name": "Tarot cards plugin", + "import_name": "Tarot", + "type": "Misc", + "protocols": [], + "dependencies": ["XEP-0045", "XEP-0249"], + "main": "Tarot", + "handler": "yes", + "description": _("""Implementation of Tarot card game""") } @@ -59,33 +59,33 @@ def __init__(self, host): info(_("Plugin Tarot initialization")) self.host = host - self.games={} - self.waiting_inv = {} #Invitation waiting for people to join to launch a game + self.games = {} + self.waiting_inv = {} # Invitation waiting for people to join to launch a game self.contrats = [_('Passe'), _('Petite'), _('Garde'), _('Garde Sans'), _('Garde Contre')] - host.bridge.addMethod("tarotGameLaunch", ".plugin", in_sign='ass', out_sign='', method=self.launchGame) #args: room_jid, players, profile - host.bridge.addMethod("tarotGameCreate", ".plugin", in_sign='sass', out_sign='', method=self.createGame) #args: room_jid, players, profile - host.bridge.addMethod("tarotGameReady", ".plugin", in_sign='sss', out_sign='', method=self.newPlayerReady) #args: player, referee, profile - host.bridge.addMethod("tarotGameContratChoosed", ".plugin", in_sign='ssss', out_sign='', method=self.contratChoosed) #args: player, referee, contrat, profile - host.bridge.addMethod("tarotGamePlayCards", ".plugin", in_sign='ssa(ss)s', out_sign='', method=self.play_cards) #args: player, referee, cards, profile - host.bridge.addSignal("tarotGameStarted", ".plugin", signature='ssass') #args: room_jid, referee, players, profile - host.bridge.addSignal("tarotGameNew", ".plugin", signature='sa(ss)s') #args: room_jid, hand, profile - host.bridge.addSignal("tarotGameChooseContrat", ".plugin", signature='sss') #args: room_jid, xml_data, profile - host.bridge.addSignal("tarotGameShowCards", ".plugin", signature='ssa(ss)a{ss}s') #args: room_jid, type ["chien", "poignée",...], cards, data[dict], profile - host.bridge.addSignal("tarotGameCardsPlayed", ".plugin", signature='ssa(ss)s') #args: room_jid, player, type ["chien", "poignée",...], cards, data[dict], profile - host.bridge.addSignal("tarotGameYourTurn", ".plugin", signature='ss') #args: room_jid, profile - host.bridge.addSignal("tarotGameScore", ".plugin", signature='ssasass') #args: room_jid, xml_data, winners (list of nicks), loosers (list of nicks), profile - host.bridge.addSignal("tarotGameInvalidCards", ".plugin", signature='ssa(ss)a(ss)s') #args: room_jid, game phase, played_cards, invalid_cards, profile + host.bridge.addMethod("tarotGameLaunch", ".plugin", in_sign='ass', out_sign='', method=self.launchGame) # args: room_jid, players, profile + host.bridge.addMethod("tarotGameCreate", ".plugin", in_sign='sass', out_sign='', method=self.createGame) # args: room_jid, players, profile + host.bridge.addMethod("tarotGameReady", ".plugin", in_sign='sss', out_sign='', method=self.newPlayerReady) # args: player, referee, profile + host.bridge.addMethod("tarotGameContratChoosed", ".plugin", in_sign='ssss', out_sign='', method=self.contratChoosed) # args: player, referee, contrat, profile + host.bridge.addMethod("tarotGamePlayCards", ".plugin", in_sign='ssa(ss)s', out_sign='', method=self.play_cards) # args: player, referee, cards, profile + host.bridge.addSignal("tarotGameStarted", ".plugin", signature='ssass') # args: room_jid, referee, players, profile + host.bridge.addSignal("tarotGameNew", ".plugin", signature='sa(ss)s') # args: room_jid, hand, profile + host.bridge.addSignal("tarotGameChooseContrat", ".plugin", signature='sss') # args: room_jid, xml_data, profile + host.bridge.addSignal("tarotGameShowCards", ".plugin", signature='ssa(ss)a{ss}s') # args: room_jid, type ["chien", "poignée",...], cards, data[dict], profile + host.bridge.addSignal("tarotGameCardsPlayed", ".plugin", signature='ssa(ss)s') # args: room_jid, player, type ["chien", "poignée",...], cards, data[dict], profile + host.bridge.addSignal("tarotGameYourTurn", ".plugin", signature='ss') # args: room_jid, profile + host.bridge.addSignal("tarotGameScore", ".plugin", signature='ssasass') # args: room_jid, xml_data, winners (list of nicks), loosers (list of nicks), profile + host.bridge.addSignal("tarotGameInvalidCards", ".plugin", signature='ssa(ss)a(ss)s') # args: room_jid, game phase, played_cards, invalid_cards, profile host.trigger.add("MUC user joined", self.userJoinedTrigger) self.deck_ordered = [] - for value in ['excuse']+map(str,range(1,22)): - self.deck_ordered.append(TarotCard(("atout",value))) + for value in ['excuse'] + map(str, range(1, 22)): + self.deck_ordered.append(TarotCard(("atout", value))) for suit in ["pique", "coeur", "carreau", "trefle"]: - for value in map(str,range(1,11))+["valet","cavalier","dame","roi"]: + for value in map(str, range(1, 11)) + ["valet", "cavalier", "dame", "roi"]: self.deck_ordered.append(TarotCard((suit, value))) def createGameElt(self, to_jid, type="normal"): type = "normal" if to_jid.resource else "groupchat" - elt = domish.Element((None,'message')) + elt = domish.Element((None, 'message')) elt["to"] = to_jid.full() elt["type"] = type elt.addElement((NS_CG, CG_TAG)) @@ -93,9 +93,9 @@ def __card_list_to_xml(self, cards_list, elt_name): """Convert a card list to domish element""" - cards_list_elt = domish.Element((None,elt_name)) + cards_list_elt = domish.Element((None, elt_name)) for card in cards_list: - card_elt = domish.Element((None,'card')) + card_elt = domish.Element((None, 'card')) card_elt['suit'] = card.suit card_elt['value'] = card.value cards_list_elt.addChild(card_elt) @@ -108,22 +108,21 @@ cards_list.append((card['suit'], card['value'])) return cards_list - def __create_started_elt(self, players): """Create a game_started domish element""" - started_elt = domish.Element((None,'started')) + started_elt = domish.Element((None, 'started')) idx = 0 for player in players: - player_elt = domish.Element((None,'player')) + player_elt = domish.Element((None, 'player')) player_elt.addContent(player) player_elt['index'] = str(idx) - idx+=1 + idx += 1 started_elt.addChild(player_elt) return started_elt def __ask_contrat(self): """Create a element for asking contrat""" - contrat_elt = domish.Element((None,'contrat')) + contrat_elt = domish.Element((None, 'contrat')) form = data_form.Form('form', title=_('contrat selection')) field = data_form.Field('list-single', 'contrat', options=map(data_form.Option, self.contrats), required=True) form.addField(field) @@ -136,18 +135,18 @@ @param winners: list of unicode nicks of winners @param loosers: list of unicode nicks of loosers""" - score_elt = domish.Element((None,'score')) + score_elt = domish.Element((None, 'score')) form = data_form.Form('form', title=_('scores')) for line in scores.split('\n'): - field = data_form.Field('fixed', value = line) + field = data_form.Field('fixed', value=line) form.addField(field) score_elt.addChild(form.toElement()) for winner in winners: - winner_elt = domish.Element((None,'winner')) + winner_elt = domish.Element((None, 'winner')) winner_elt.addContent(winner) score_elt.addChild(winner_elt) for looser in loosers: - looser_elt = domish.Element((None,'looser')) + looser_elt = domish.Element((None, 'looser')) looser_elt.addContent(looser) score_elt.addChild(looser_elt) return score_elt @@ -156,7 +155,7 @@ """Create a element for invalid_cards error @param list_cards: list of Card @param game_phase: phase of the game ['ecart', 'play']""" - error_elt = domish.Element((None,'error')) + error_elt = domish.Element((None, 'error')) played_elt = self.__card_list_to_xml(played_cards, 'played') invalid_elt = self.__card_list_to_xml(invalid_cards, 'invalid') error_elt['type'] = 'invalid_cards' @@ -165,7 +164,7 @@ error_elt.addChild(invalid_elt) return error_elt - def __next_player(self, game_data, next_pl = None): + def __next_player(self, game_data, next_pl=None): """Increment player number & return player name @param next_pl: if given, then next_player is forced to this one """ @@ -189,7 +188,7 @@ card = players_data[player]['played'] if card.value == "excuse": continue - if suit_asked == None: + if suit_asked is None: suit_asked = card.suit if (card.suit == suit_asked or card.suit == "atout") and card > strongest: strongest = card @@ -204,7 +203,7 @@ @param winner: nick of the trick winner""" #TODO: manage the case where excuse is played on the last trick (and lost) players_data = game_data['players_data'] - excuse = TarotCard(("atout","excuse")) + excuse = TarotCard(("atout", "excuse")) #we first check if the Excuse was already played #and if somebody is waiting for a card @@ -218,7 +217,7 @@ pl_waiting = players_data[player]['wait_for_low'] played.remove(card) players_data[pl_waiting]['levees'].append(card) - debug (_('Player %(excuse_owner)s give %(card_waited)s to %(player_waiting)s for Excuse compensation') % {"excuse_owner":player, "card_waited": card, "player_waiting":pl_waiting}) + debug(_('Player %(excuse_owner)s give %(card_waited)s to %(player_waiting)s for Excuse compensation') % {"excuse_owner": player, "card_waited": card, "player_waiting": pl_waiting}) return return @@ -226,14 +225,14 @@ #the Excuse is not on the table, nothing to do return - excuse_player = None #Who has played the Excuse ? + excuse_player = None # Who has played the Excuse ? for player in game_data['players']: if players_data[player]['played'] == excuse: excuse_player = player break if excuse_player == winner: - return #the excuse player win the trick, nothing to do + return # the excuse player win the trick, nothing to do #first we remove the excuse from played cards played.remove(excuse) @@ -244,18 +243,17 @@ low_card = None #We look backward in cards won by the Excuse owner to #find a low value card - for card_idx in range(len(owner_levees)-1, -1, -1): + for card_idx in range(len(owner_levees) - 1, -1, -1): if owner_levees[card_idx].points == 0.5: low_card = owner_levees[card_idx] del owner_levees[card_idx] players_data[winner]['levees'].append(low_card) - debug (_('Player %(excuse_owner)s give %(card_waited)s to %(player_waiting)s for Excuse compensation') % {"excuse_owner":excuse_player, "card_waited": low_card, "player_waiting":winner}) + debug(_('Player %(excuse_owner)s give %(card_waited)s to %(player_waiting)s for Excuse compensation') % {"excuse_owner": excuse_player, "card_waited": low_card, "player_waiting": winner}) break - if not low_card: #The player has no low card yet + if not low_card: # The player has no low card yet #TODO: manage case when player never win a trick with low card players_data[excuse_player]['wait_for_low'] = winner - debug(_("%(excuse_owner)s keep the Excuse but has not card to give, %(winner)s is waiting for one") % {'excuse_owner':excuse_player, 'winner':winner}) - + debug(_("%(excuse_owner)s keep the Excuse but has not card to give, %(winner)s is waiting for one") % {'excuse_owner': excuse_player, 'winner': winner}) def __draw_game(self, game_data): """The game is draw, no score change @@ -263,14 +261,13 @@ @return: tuple with (string victory message, list of winners, list of loosers)""" players_data = game_data['players_data'] scores_str = _('Draw game') - scores_str+='\n' + scores_str += '\n' for player in game_data['players']: - scores_str+=_("\n--\n%(player)s:\nscore for this game ==> %(score_game)i\ntotal score ==> %(total_score)i") % {'player':player, 'score_game':0, 'total_score': players_data[player]['score']} + scores_str += _("\n--\n%(player)s:\nscore for this game ==> %(score_game)i\ntotal score ==> %(total_score)i") % {'player': player, 'score_game': 0, 'total_score': players_data[player]['score']} debug(scores_str) return (scores_str, [], []) - def __calculate_scores(self, game_data): """The game is finished, time to know who won :) @param game_data: data of the game @@ -282,7 +279,7 @@ bouts = [] for card in levees: if card.bout: - nb_bouts +=1 + nb_bouts += 1 bouts.append(card.value) score += card.points @@ -292,10 +289,10 @@ defenseurs.remove(game_data['attaquant']) for defenseur in defenseurs: for card in players_data[defenseur]['levees']: - check_score+=card.points + check_score += card.points if game_data['contrat'] == "Garde Contre": for card in game_data['chien']: - check_score+=card.points + check_score += card.points assert (score + check_score == 91) point_limit = None @@ -329,16 +326,16 @@ #TODO: adjust this for 3 and 5 players variants #TODO: manage bonuses (petit au bout, poignée, chelem) player_score[player] = points_defenseur if player != game_data['attaquant'] else points_defenseur * -3 - players_data[player]['score'] += player_score[player] #we add score of this game to the global score + players_data[player]['score'] += player_score[player] # we add score of this game to the global score if player_score[player] > 0: winners.append(player) else: loosers.append(player) - scores_str = _('The attacker (%(attaquant)s) makes %(points)i and needs to make %(point_limit)i (%(nb_bouts)s oulder%(plural)s%(separator)s%(bouts)s): he %(victory)s') % {'attaquant':game_data['attaquant'], 'points':score, 'point_limit':point_limit, 'nb_bouts': nb_bouts, 'plural': 's' if nb_bouts>1 else '', 'separator':': ' if nb_bouts != 0 else '', 'bouts':','.join(map(str,bouts)), 'victory': 'win' if victory else 'loose'} - scores_str+='\n' + scores_str = _('The attacker (%(attaquant)s) makes %(points)i and needs to make %(point_limit)i (%(nb_bouts)s oulder%(plural)s%(separator)s%(bouts)s): he %(victory)s') % {'attaquant': game_data['attaquant'], 'points': score, 'point_limit': point_limit, 'nb_bouts': nb_bouts, 'plural': 's' if nb_bouts > 1 else '', 'separator': ': ' if nb_bouts != 0 else '', 'bouts': ','.join(map(str, bouts)), 'victory': 'win' if victory else 'loose'} + scores_str += '\n' for player in game_data['players']: - scores_str+=_("\n--\n%(player)s:\nscore for this game ==> %(score_game)i\ntotal score ==> %(total_score)i") % {'player':player, 'score_game':player_score[player], 'total_score': players_data[player]['score']} + scores_str += _("\n--\n%(player)s:\nscore for this game ==> %(score_game)i\ntotal score ==> %(total_score)i") % {'player': player, 'score_game': player_score[player], 'total_score': players_data[player]['score']} debug(scores_str) return (scores_str, winners, loosers) @@ -351,7 +348,7 @@ forbidden_cards = [] if game_data['stage'] == 'ecart': for card in cards: - if card.bout or card.value=="roi": + if card.bout or card.value == "roi": forbidden_cards.append(card) #TODO: manage case where atouts (trumps) are in the dog elif game_data['stage'] == 'play': @@ -373,7 +370,7 @@ if played_card.suit == "atout" and played_card > biggest_atout: biggest_atout = played_card idx = (idx + 1) % len(players) - has_suit = False #True if there is one card of the asked suit in the hand of the player + has_suit = False # True if there is one card of the asked suit in the hand of the player has_atout = False biggest_hand_atout = None @@ -399,18 +396,16 @@ error(_('Internal error: unmanaged game stage')) return forbidden_cards - def __start_play(self, room_jid, game_data, profile): """Start the game (tell to the first player after dealer to play""" game_data['stage'] = "play" - next_player_idx = game_data['current_player'] = (game_data['init_player'] + 1) % len(game_data['players']) #the player after the dealer start + next_player_idx = game_data['current_player'] = (game_data['init_player'] + 1) % len(game_data['players']) # the player after the dealer start game_data['first_player'] = next_player = game_data['players'][next_player_idx] - to_jid = jid.JID(room_jid.userhost()+"/"+next_player) #FIXME: gof: + to_jid = jid.JID(room_jid.userhost() + "/" + next_player) # FIXME: gof: mess = self.createGameElt(to_jid) yourturn_elt = mess.firstChildElement().addElement('your_turn') self.host.profiles[profile].xmlstream.send(mess) - def userJoinedTrigger(self, room, user, profile): """This trigger is used to check if we are waiting people in this room, and to create a game if everybody is here""" @@ -435,8 +430,8 @@ def tarotRoomJoined(room): _room = room.occupantJID.userhostJID() for player in players: - self.host.plugins["XEP-0249"].invite(jid.JID(player), room.occupantJID.userhostJID(), {"game":"Tarot"}, profile) - self.waiting_inv[_room] = (time(), players) #TODO: remove invitation waiting for too long, using the time data + self.host.plugins["XEP-0249"].invite(jid.JID(player), room.occupantJID.userhostJID(), {"game": "Tarot"}, profile) + self.waiting_inv[_room] = (time(), players) # TODO: remove invitation waiting for too long, using the time data def after_init(ignore): room_name = "sat_tarot_%s" % self.host.plugins["XEP-0045"].getUniqueName(profile_key) @@ -464,36 +459,33 @@ return client.client_initialized.addCallback(after_init) - - - def createGame(self, room_jid_param, players, profile_key='@NONE@'): """Create a new game @param room_jid_param: jid of the room @param players: list of players nick (nick must exist in the room) @param profile_key: %(doc_profile_key)s""" - debug (_("Creating Tarot game")) + debug(_("Creating Tarot game")) room_jid = jid.JID(room_jid_param) profile = self.host.memory.getProfileName(profile_key) if not profile: - error (_("profile %s is unknown") % profile_key) + error(_("profile %s is unknown") % profile_key) return - if self.games.has_key(room_jid): - warning (_("Tarot game already started in room %s") % room_jid.userhost()) + if room_jid in self.games: + warning(_("Tarot game already started in room %s") % room_jid.userhost()) else: room_nick = self.host.plugins["XEP-0045"].getRoomNick(room_jid.userhost(), profile) if not room_nick: - error ('Internal error') + error('Internal error') return referee = room_jid.userhost() + '/' + room_nick status = {} players_data = {} for player in players: - players_data[player] = {'score':0} + players_data[player] = {'score': 0} status[player] = "init" - self.games[room_jid.userhost()] = {'referee':referee, 'players':players, 'status':status, 'players_data':players_data, 'hand_size':18, 'init_player':0, 'current_player': None, 'contrat': None, 'stage': None} + self.games[room_jid.userhost()] = {'referee': referee, 'players': players, 'status': status, 'players_data': players_data, 'hand_size': 18, 'init_player': 0, 'current_player': None, 'contrat': None, 'stage': None} for player in players: - mess = self.createGameElt(jid.JID(room_jid.userhost()+'/'+player)) + mess = self.createGameElt(jid.JID(room_jid.userhost() + '/' + player)) mess.firstChildElement().addChild(self.__create_started_elt(players)) self.host.profiles[profile].xmlstream.send(mess) @@ -501,9 +493,9 @@ """Must be called when player is ready to start a new game""" profile = self.host.memory.getProfileName(profile_key) if not profile: - error (_("profile %s is unknown") % profile_key) + error(_("profile %s is unknown") % profile_key) return - debug ('new player ready: %s' % profile) + debug('new player ready: %s' % profile) mess = self.createGameElt(jid.JID(referee)) ready_elt = mess.firstChildElement().addElement('player_ready') ready_elt['player'] = player @@ -518,11 +510,11 @@ """ profile = self.host.memory.getProfileName(profile_key) if not profile: - error (_("profile %s is unknown") % profile_key) + error(_("profile %s is unknown") % profile_key) return - debug (_('contrat [%(contrat)s] choosed by %(profile)s') % {'contrat':contrat, 'profile':profile}) + debug(_('contrat [%(contrat)s] choosed by %(profile)s') % {'contrat': contrat, 'profile': profile}) mess = self.createGameElt(jid.JID(referee)) - contrat_elt = mess.firstChildElement().addElement(('','contrat_choosed'), content=contrat) + contrat_elt = mess.firstChildElement().addElement(('', 'contrat_choosed'), content=contrat) contrat_elt['player'] = player self.host.profiles[profile].xmlstream.send(mess) @@ -535,9 +527,9 @@ """ profile = self.host.memory.getProfileName(profile_key) if not profile: - error (_("profile %s is unknown") % profile_key) + error(_("profile %s is unknown") % profile_key) return - debug (_('Cards played by %(profile)s: [%(cards)s]') % {'profile':profile,'cards':cards}) + debug(_('Cards played by %(profile)s: [%(cards)s]') % {'profile': profile, 'cards': cards}) mess = self.createGameElt(jid.JID(referee)) playcard_elt = mess.firstChildElement().addChild(self.__card_list_to_xml(TarotCard.from_tuples(cards), 'cards_played')) playcard_elt['player'] = player @@ -545,7 +537,7 @@ def newGame(self, room_jid, profile): """Launch a new round""" - debug (_('new Tarot game')) + debug(_('new Tarot game')) deck = self.deck_ordered[:] random.shuffle(deck) game_data = self.games[room_jid.userhost()] @@ -553,7 +545,7 @@ players_data = game_data['players_data'] current_player = game_data['current_player'] game_data['stage'] = "init" - game_data['first_player'] = None #first player for the current trick + game_data['first_player'] = None # first player for the current trick game_data['contrat'] = None hand = game_data['hand'] = {} hand_size = game_data['hand_size'] @@ -565,23 +557,22 @@ del(deck[:]) for player in players: - to_jid = jid.JID(room_jid.userhost()+"/"+player) #FIXME: gof: + to_jid = jid.JID(room_jid.userhost() + "/" + player) # FIXME: gof: mess = self.createGameElt(to_jid) mess.firstChildElement().addChild(self.__card_list_to_xml(hand[player], 'hand')) self.host.profiles[profile].xmlstream.send(mess) players_data[player]['contrat'] = None - players_data[player]['levees'] = [] #cards won - players_data[player]['played'] = None #card on the table - players_data[player]['wait_for_low'] = None #Used when a player wait for a low card because of excuse + players_data[player]['levees'] = [] # cards won + players_data[player]['played'] = None # card on the table + players_data[player]['wait_for_low'] = None # Used when a player wait for a low card because of excuse - pl_idx = game_data['current_player'] = (game_data['init_player'] + 1) % len(players) #the player after the dealer start + pl_idx = game_data['current_player'] = (game_data['init_player'] + 1) % len(players) # the player after the dealer start player = players[pl_idx] - to_jid = jid.JID(room_jid.userhost()+"/"+player) #FIXME: gof: + to_jid = jid.JID(room_jid.userhost() + "/" + player) # FIXME: gof: mess = self.createGameElt(to_jid) mess.firstChildElement().addChild(self.__ask_contrat()) self.host.profiles[profile].xmlstream.send(mess) - def card_game_cmd(self, mess_elt, profile): from_jid = jid.JID(mess_elt['from']) room_jid = jid.JID(from_jid.userhost()) @@ -591,25 +582,25 @@ for elt in game_elt.elements(): - if elt.name == 'started': #new game created + if elt.name == 'started': # new game created players = [] for player in elt.elements(): players.append(unicode(player)) self.host.bridge.tarotGameStarted(room_jid.userhost(), from_jid.full(), players, profile) - elif elt.name == 'player_ready': #ready to play + elif elt.name == 'player_ready': # ready to play player = elt['player'] status = self.games[room_jid.userhost()]['status'] nb_players = len(self.games[room_jid.userhost()]['players']) status[player] = 'ready' - debug (_('Player %(player)s is ready to start [status: %(status)s]') % {'player':player, 'status':status}) - if status.values().count('ready') == nb_players: #everybody is ready, we can start the game + debug(_('Player %(player)s is ready to start [status: %(status)s]') % {'player': player, 'status': status}) + if status.values().count('ready') == nb_players: # everybody is ready, we can start the game self.newGame(room_jid, profile) - elif elt.name == 'hand': #a new hand has been received + elif elt.name == 'hand': # a new hand has been received self.host.bridge.tarotGameNew(room_jid.userhost(), self.__xml_to_list(elt), profile) - elif elt.name == 'contrat': #it's time to choose contrat + elif elt.name == 'contrat': # it's time to choose contrat form = data_form.Form.fromElement(elt.firstChildElement()) xml_data = dataForm2xml(form) self.host.bridge.tarotGameChooseContrat(room_jid.userhost(), xml_data, profile) @@ -623,7 +614,7 @@ if contrats.count(None): #not everybody has choosed his contrat, it's next one turn player = self.__next_player(game_data) - to_jid = jid.JID(room_jid.userhost()+"/"+player) #FIXME: gof: + to_jid = jid.JID(room_jid.userhost() + "/" + player) # FIXME: gof: mess = self.createGameElt(to_jid) mess.firstChildElement().addChild(self.__ask_contrat()) self.host.profiles[profile].xmlstream.send(mess) @@ -642,11 +633,11 @@ mess = self.createGameElt(to_jid) mess.firstChildElement().addChild(self.__give_scores(*self.__draw_game(game_data))) self.host.profiles[profile].xmlstream.send(mess) - game_data['init_player'] = (game_data['init_player'] + 1) % len(game_data['players']) #we change the dealer + game_data['init_player'] = (game_data['init_player'] + 1) % len(game_data['players']) # we change the dealer for player in game_data['players']: game_data['status'][player] = "init" return - debug (_("%(player)s win the bid with %(contrat)s") % {'player':best_contrat[0],'contrat':best_contrat[1]}) + debug(_("%(player)s win the bid with %(contrat)s") % {'player': best_contrat[0], 'contrat': best_contrat[1]}) game_data['contrat'] = best_contrat[1] if game_data['contrat'] == "Garde Sans" or game_data['contrat'] == "Garde Contre": @@ -654,7 +645,7 @@ game_data['attaquant'] = best_contrat[0] else: #Time to show the chien to everybody - to_jid = jid.JID(room_jid.userhost()) #FIXME: gof: + to_jid = jid.JID(room_jid.userhost()) # FIXME: gof: mess = self.createGameElt(to_jid) chien_elt = mess.firstChildElement().addChild(self.__card_list_to_xml(game_data['chien'], 'chien')) chien_elt['attaquant'] = best_contrat[0] @@ -668,10 +659,9 @@ players_data[best_contrat[0]]['levees'].extend(game_data['chien']) del game_data['chien'][:] - - elif elt.name == 'chien': #we have received the chien - debug (_("tarot: chien received")) - data = {"attaquant":elt['attaquant']} + elif elt.name == 'chien': # we have received the chien + debug(_("tarot: chien received")) + data = {"attaquant": elt['attaquant']} game_data['stage'] = "ecart" game_data['attaquant'] = elt['attaquant'] self.host.bridge.tarotGameShowCards(room_jid.userhost(), "chien", self.__xml_to_list(elt), data, profile) @@ -679,18 +669,18 @@ elif elt.name == 'cards_played': if game_data['stage'] == "ecart": #TODO: show atouts (trumps) if player put some in écart - assert (game_data['attaquant'] == elt['player']) #TODO: throw an xml error here + assert (game_data['attaquant'] == elt['player']) # TODO: throw an xml error here list_cards = TarotCard.from_tuples(self.__xml_to_list(elt)) #we now check validity of card invalid_cards = self.__invalid_cards(game_data, list_cards) if invalid_cards: - mess = self.createGameElt(jid.JID(room_jid.userhost()+'/'+elt['player'])) + mess = self.createGameElt(jid.JID(room_jid.userhost() + '/' + elt['player'])) mess.firstChildElement().addChild(self.__invalid_cards_elt(list_cards, invalid_cards, game_data['stage'])) self.host.profiles[profile].xmlstream.send(mess) return #FIXME: gof: manage Garde Sans & Garde Contre cases - players_data[elt['player']]['levees'].extend(list_cards) #we add the chien to attaquant's levées + players_data[elt['player']]['levees'].extend(list_cards) # we add the chien to attaquant's levées for card in list_cards: game_data['hand'][elt['player']].remove(card) @@ -706,7 +696,7 @@ #we first check validity of card invalid_cards = self.__invalid_cards(game_data, cards) if invalid_cards: - mess = self.createGameElt(jid.JID(room_jid.userhost()+'/'+current_player)) + mess = self.createGameElt(jid.JID(room_jid.userhost() + '/' + current_player)) mess.firstChildElement().addChild(self.__invalid_cards_elt(cards, invalid_cards, game_data['stage'])) self.host.profiles[profile].xmlstream.send(mess) return @@ -725,7 +715,7 @@ if all(played): #everybody has played winner = self.__winner(game_data) - debug (_('The winner of this trick is %s') % winner) + debug(_('The winner of this trick is %s') % winner) #the winner win the trick self.__excuse_hack(game_data, played, winner) players_data[elt['player']]['levees'].extend(played) @@ -738,7 +728,7 @@ mess = self.createGameElt(to_jid) chien_elt = mess.firstChildElement().addChild(self.__give_scores(*self.__calculate_scores(game_data))) self.host.profiles[profile].xmlstream.send(mess) - game_data['init_player'] = (game_data['init_player'] + 1) % len(game_data['players']) #we change the dealer + game_data['init_player'] = (game_data['init_player'] + 1) % len(game_data['players']) # we change the dealer for player in game_data['players']: game_data['status'][player] = "init" return @@ -748,7 +738,7 @@ next_player = self.__next_player(game_data) #finally, we tell to the next player to play - to_jid = jid.JID(room_jid.userhost()+"/"+next_player) + to_jid = jid.JID(room_jid.userhost() + "/" + next_player) mess = self.createGameElt(to_jid) yourturn_elt = mess.firstChildElement().addElement('your_turn') self.host.profiles[profile].xmlstream.send(mess) @@ -757,7 +747,7 @@ self.host.bridge.tarotGameYourTurn(room_jid.userhost(), profile) elif elt.name == 'score': - form_elt = elt.elements(name='x',uri='jabber:x:data').next() + form_elt = elt.elements(name='x', uri='jabber:x:data').next() winners = [] loosers = [] for winner in elt.elements(name='winner', uri=NS_CG): @@ -769,16 +759,17 @@ self.host.bridge.tarotGameScore(room_jid.userhost(), xml_data, winners, loosers, profile) elif elt.name == 'error': if elt['type'] == 'invalid_cards': - played_cards = self.__xml_to_list(elt.elements(name='played',uri=NS_CG).next()) - invalid_cards = self.__xml_to_list(elt.elements(name='invalid',uri=NS_CG).next()) + played_cards = self.__xml_to_list(elt.elements(name='played', uri=NS_CG).next()) + invalid_cards = self.__xml_to_list(elt.elements(name='invalid', uri=NS_CG).next()) self.host.bridge.tarotGameInvalidCards(room_jid.userhost(), elt['phase'], played_cards, invalid_cards, profile) else: - error (_('Unmanaged error type: %s') % elt['type']) + error(_('Unmanaged error type: %s') % elt['type']) else: - error (_('Unmanaged card game element: %s') % elt.name) + error(_('Unmanaged card game element: %s') % elt.name) def getHandler(self, profile): - return CardGameHandler(self) + return CardGameHandler(self) + class CardGameHandler (XMPPHandler): implements(iwokkel.IDisco) @@ -788,11 +779,10 @@ self.host = plugin_parent.host def connectionInitialized(self): - self.xmlstream.addObserver(CG_REQUEST, self.plugin_parent.card_game_cmd, profile = self.parent.profile) + self.xmlstream.addObserver(CG_REQUEST, self.plugin_parent.card_game_cmd, profile=self.parent.profile) def getDiscoInfo(self, requestor, target, nodeIdentifier=''): return [disco.DiscoFeature(NS_CG)] def getDiscoItems(self, requestor, target, nodeIdentifier=''): return [] - diff -r 70bae685d05c -r e629371a28d3 src/plugins/plugin_misc_text_commands.py --- a/src/plugins/plugin_misc_text_commands.py Mon Jan 21 00:59:50 2013 +0100 +++ b/src/plugins/plugin_misc_text_commands.py Fri Jan 18 17:55:35 2013 +0100 @@ -23,16 +23,17 @@ from logging import debug, info, warning, error PLUGIN_INFO = { -"name": "Text commands", -"import_name": "text-commands", -"type": "Misc", -"protocols": [], -"dependencies": ["XEP-0045", "EXP-PARROT"], -"main": "TextCommands", -"handler": "no", -"description": _("""IRC like text commands""") + "name": "Text commands", + "import_name": "text-commands", + "type": "Misc", + "protocols": [], + "dependencies": ["XEP-0045", "EXP-PARROT"], + "main": "TextCommands", + "handler": "no", + "description": _("""IRC like text commands""") } + class TextCommands(object): #FIXME: doc strings for commands have to be translatable # plugins need a dynamic translation system (translation @@ -52,13 +53,13 @@ if command.isalpha(): # looks like an actual command, we try to call the corresponding method try: - mess_data["unparsed"] = msg[1+len(command):] #part not yet parsed of the message - return getattr(self,"cmd_%s" % command)(mess_data,profile) + mess_data["unparsed"] = msg[1 + len(command):] # part not yet parsed of the message + return getattr(self, "cmd_%s" % command)(mess_data, profile) except AttributeError: pass - elif msg[0] == '\\': #we have escape char + elif msg[0] == '\\': # we have escape char try: - if msg[1] in ('/','\\'): # we have '\/' or '\\', we escape to '/' or '\' + if msg[1] in ('/', '\\'): # we have '\/' or '\\', we escape to '/' or '\' mess_data["message"] = msg[1:] except IndexError: pass @@ -72,9 +73,9 @@ """ nb_arobas = arg.count('@') if nb_arobas == 1: - if arg[-1] !='@': + if arg[-1] != '@': return jid.JID(arg) - return jid.JID(arg+service_jid) + return jid.JID(arg + service_jid) return jid.JID(u"%s@%s" % (arg, service_jid)) def _feedBack(self, message, mess_data, profile): @@ -99,7 +100,7 @@ nick = mess_data["unparsed"].strip() room = mess_data["to"] - self.host.plugins["XEP-0045"].nick(room,nick,profile) + self.host.plugins["XEP-0045"].nick(room, nick, profile) return False @@ -134,7 +135,7 @@ else: room = mess_data["to"] - self.host.plugins["XEP-0045"].leave(room,profile) + self.host.plugins["XEP-0045"].leave(room, profile) return False @@ -183,7 +184,7 @@ self.host.plugins["EXP-PARROT"].addParrot(link_left_jid, link_right_jid, profile) self.host.plugins["EXP-PARROT"].addParrot(link_right_jid, link_left_jid, profile) - self._feedBack("Parrot mode activated for %s" % (unicode(link_left_jid),), mess_data, profile) + self._feedBack("Parrot mode activated for %s" % (unicode(link_left_jid), ), mess_data, profile) return False @@ -210,7 +211,7 @@ def cmd_help(self, mess_data, profile): """show help on available commands""" - commands=filter(lambda method: method.startswith('cmd_'), dir(self)) + commands = filter(lambda method: method.startswith('cmd_'), dir(self)) longuest = max([len(command) for command in commands]) help_cmds = [] @@ -223,7 +224,5 @@ spaces = (longuest - len(command)) * ' ' help_cmds.append(" /%s: %s %s" % (command[4:], spaces, help_str)) - help_mess = _(u"Text commands available:\n%s") % (u'\n'.join(help_cmds),) + help_mess = _(u"Text commands available:\n%s") % (u'\n'.join(help_cmds), ) self._feedBack(help_mess, mess_data, profile) - - diff -r 70bae685d05c -r e629371a28d3 src/plugins/plugin_misc_xmllog.py --- a/src/plugins/plugin_misc_xmllog.py Mon Jan 21 00:59:50 2013 +0100 +++ b/src/plugins/plugin_misc_xmllog.py Fri Jan 18 17:55:35 2013 +0100 @@ -24,24 +24,25 @@ from twisted.words.xish import domish PLUGIN_INFO = { -"name": "Raw XML log Plugin", -"import_name": "XmlLog", -"type": "Misc", -"protocols": [], -"dependencies": [], -"main": "XmlLog", -"handler": "no", -"description": _("""Send raw XML logs to bridge""") + "name": "Raw XML log Plugin", + "import_name": "XmlLog", + "type": "Misc", + "protocols": [], + "dependencies": [], + "main": "XmlLog", + "handler": "no", + "description": _("""Send raw XML logs to bridge""") } + class LoggingXmlStream(XmlStream): """This class send the raw XML to the Bridge, for logging purpose""" def send(self, obj): - if isinstance(obj,basestring): - log=unicode(obj) + if isinstance(obj, basestring): + log = unicode(obj) elif isinstance(obj, domish.Element): - log=obj.toXml() + log = obj.toXml() else: error(_('INTERNAL ERROR: Unmanaged XML type')) self._host.bridge.xmlLog("OUT", log, self._profile) @@ -72,7 +73,7 @@ host.memory.importParams(self.params) #bridge - host.bridge.addSignal("xmlLog", ".plugin", signature='sss') #args: direction("IN" or "OUT"), xml_data, profile + host.bridge.addSignal("xmlLog", ".plugin", signature='sss') # args: direction("IN" or "OUT"), xml_data, profile do_log = self.host.memory.getParamA("Xml log", "Debug") if do_log: diff -r 70bae685d05c -r e629371a28d3 src/plugins/plugin_xep_0020.py --- a/src/plugins/plugin_xep_0020.py Mon Jan 21 00:59:50 2013 +0100 +++ b/src/plugins/plugin_xep_0020.py Fri Jan 18 17:55:35 2013 +0100 @@ -35,15 +35,16 @@ NS_FEATURE_NEG = 'http://jabber.org/protocol/feature-neg' PLUGIN_INFO = { -"name": "XEP 0020 Plugin", -"import_name": "XEP-0020", -"type": "XEP", -"protocols": ["XEP-0020"], -"main": "XEP_0020", -"handler": "yes", -"description": _("""Implementation of Feature Negotiation""") + "name": "XEP 0020 Plugin", + "import_name": "XEP-0020", + "type": "XEP", + "protocols": ["XEP-0020"], + "main": "XEP_0020", + "handler": "yes", + "description": _("""Implementation of Feature Negotiation""") } + class XEP_0020(object): def __init__(self, host): @@ -67,7 +68,7 @@ for field in form.fields: values = form.fields[field].values result[field] = values[0] if values else None - if len(values)>1: + if len(values) > 1: warning(_("More than one value choosed for %s, keeping the first one") % field) return result @@ -92,7 +93,7 @@ feature_elt.addChild(x_form.toElement()) return feature_elt - def proposeFeatures(self, options_dict, namespace = None): + def proposeFeatures(self, options_dict, namespace=None): """Build a feature element with options to propose @param options_dict: dict with feature as key and list of acceptable options as value @param namespace: feature namespace""" @@ -104,6 +105,7 @@ feature_elt.addChild(x_form.toElement()) return feature_elt + class XEP_0020_handler(XMPPHandler): implements(iwokkel.IDisco) @@ -112,4 +114,3 @@ def getDiscoItems(self, requestor, target, nodeIdentifier=''): return [] - diff -r 70bae685d05c -r e629371a28d3 src/plugins/plugin_xep_0045.py --- a/src/plugins/plugin_xep_0045.py Mon Jan 21 00:59:50 2013 +0100 +++ b/src/plugins/plugin_xep_0045.py Fri Jan 18 17:55:35 2013 +0100 @@ -36,53 +36,55 @@ from wokkel.subprotocols import XMPPHandler PLUGIN_INFO = { -"name": "XEP 0045 Plugin", -"import_name": "XEP-0045", -"type": "XEP", -"protocols": ["XEP-0045"], -"dependencies": [], -"main": "XEP_0045", -"handler": "yes", -"description": _("""Implementation of Multi-User Chat""") + "name": "XEP 0045 Plugin", + "import_name": "XEP-0045", + "type": "XEP", + "protocols": ["XEP-0045"], + "dependencies": [], + "main": "XEP_0045", + "handler": "yes", + "description": _("""Implementation of Multi-User Chat""") } + class UnknownRoom(Exception): pass + class XEP_0045(object): def __init__(self, host): info(_("Plugin XEP_0045 initialization")) self.host = host - self.clients={} + self.clients = {} host.bridge.addMethod("joinMUC", ".plugin", in_sign='ssa{ss}s', out_sign='', method=self._join) host.bridge.addMethod("mucNick", ".plugin", in_sign='sss', out_sign='', method=self.mucNick) host.bridge.addMethod("mucLeave", ".plugin", in_sign='ss', out_sign='', method=self.leave) host.bridge.addMethod("getRoomsJoined", ".plugin", in_sign='s', out_sign='a(sass)', method=self.getRoomsJoined) host.bridge.addMethod("getRoomsSubjects", ".plugin", in_sign='s', out_sign='a(ss)', method=self.getRoomsSubjects) host.bridge.addMethod("getUniqueRoomName", ".plugin", in_sign='s', out_sign='s', method=self.getUniqueName) - host.bridge.addSignal("roomJoined", ".plugin", signature='sasss') #args: room_jid, room_nicks, user_nick, profile - host.bridge.addSignal("roomLeft", ".plugin", signature='ss') #args: room_jid, profile - host.bridge.addSignal("roomUserJoined", ".plugin", signature='ssa{ss}s') #args: room_jid, user_nick, user_data, profile - host.bridge.addSignal("roomUserLeft", ".plugin", signature='ssa{ss}s') #args: room_jid, user_nick, user_data, profile - host.bridge.addSignal("roomUserChangedNick", ".plugin", signature='ssss') #args: room_jid, old_nick, new_nick, profile - host.bridge.addSignal("roomNewSubject", ".plugin", signature='sss') #args: room_jid, subject, profile - + host.bridge.addSignal("roomJoined", ".plugin", signature='sasss') # args: room_jid, room_nicks, user_nick, profile + host.bridge.addSignal("roomLeft", ".plugin", signature='ss') # args: room_jid, profile + host.bridge.addSignal("roomUserJoined", ".plugin", signature='ssa{ss}s') # args: room_jid, user_nick, user_data, profile + host.bridge.addSignal("roomUserLeft", ".plugin", signature='ssa{ss}s') # args: room_jid, user_nick, user_data, profile + host.bridge.addSignal("roomUserChangedNick", ".plugin", signature='ssss') # args: room_jid, old_nick, new_nick, profile + host.bridge.addSignal("roomNewSubject", ".plugin", signature='sss') # args: room_jid, subject, profile def __check_profile(self, profile): """check if profile is used and connected if profile known but disconnected, remove it from known profiles @param profile: profile to check @return: True if the profile is known and connected, else False""" - if not profile or not self.clients.has_key(profile) or not self.host.isConnected(profile): - error (_('Unknown or disconnected profile (%s)') % profile) - if self.clients.has_key(profile): + if not profile or profile not in self.clients or not self.host.isConnected(profile): + error(_('Unknown or disconnected profile (%s)') % profile) + if profile in self.clients: del self.clients[profile] return False return True def __room_joined(self, room, profile): """Called when the user is in the requested room""" + def _sendBridgeSignal(ignore=None): self.host.bridge.roomJoined(room.roomJID.userhost(), [user.nick for user in room.roster.values()], room.nick, profile) @@ -99,16 +101,15 @@ _sendBridgeSignal() return room - def __err_joining_room(self, failure, room_jid, nick, history_options, password, profile): """Called when something is going wrong when joining the room""" if failure.value.condition == 'conflict': # we have a nickname conflict, we try again with "_" suffixed to current nickname nick += '_' - return self.clients[profile].join(room_jid, nick, history_options, password).addCallbacks(self.__room_joined, self.__err_joining_room, callbackKeywords={'profile':profile}, errbackArgs=[room_jid, nick, history_options, password, profile]) + return self.clients[profile].join(room_jid, nick, history_options, password).addCallbacks(self.__room_joined, self.__err_joining_room, callbackKeywords={'profile': profile}, errbackArgs=[room_jid, nick, history_options, password, profile]) mess = _("Error when joining the room") - error (mess) + error(mess) self.host.bridge.newAlert(mess, _("Group chat error"), "ERROR", profile) raise failure @@ -128,7 +129,7 @@ @profile_key: profile @return: nick or empty string in case of error""" profile = self.host.memory.getProfileName(profile_key) - if not self.__check_profile(profile) or not self.clients[profile].joined_rooms.has_key(room_jid_s): + if not self.__check_profile(profile) or room_jid_s not in self.clients[profile].joined_rooms: return '' return self.clients[profile].joined_rooms[room_jid_s].nick @@ -137,7 +138,7 @@ profile = self.host.memory.getProfileName(profile) if not self.__check_profile(profile): raise exceptions.UnknownProfileError("Unknown or disconnected profile") - if not self.clients[profile].joined_rooms.has_key(room_jid.userhost()): + if room_jid.userhost() not in self.clients[profile].joined_rooms: raise UnknownRoom("This room has not been joined") return self.clients[profile].joined_rooms[room_jid.userhost()].inRoster(nick) @@ -155,7 +156,7 @@ return uuid.uuid1() def join(self, room_jid, nick, options, profile_key='@DEFAULT@'): - def _errDeferred(exc_obj = Exception, txt='Error while joining room'): + def _errDeferred(exc_obj=Exception, txt='Error while joining room'): d = defer.Deferred() d.errback(exc_obj(txt)) return d @@ -163,15 +164,15 @@ profile = self.host.memory.getProfileName(profile_key) if not self.__check_profile(profile): return _errDeferred() - if self.clients[profile].joined_rooms.has_key(room_jid.userhost()): - warning(_('%(profile)s is already in room %(room_jid)s') % {'profile':profile, 'room_jid':room_jid.userhost()}) + if room_jid.userhost() in self.clients[profile].joined_rooms: + warning(_('%(profile)s is already in room %(room_jid)s') % {'profile': profile, 'room_jid': room_jid.userhost()}) return _errDeferred() - info (_("[%(profile)s] is joining room %(room)s with nick %(nick)s") % {'profile':profile,'room':room_jid.userhost(), 'nick':nick}) + info(_("[%(profile)s] is joining room %(room)s with nick %(nick)s") % {'profile': profile, 'room': room_jid.userhost(), 'nick': nick}) - history_options = options["history"] == "True" if options.has_key("history") else None - password = options["password"] if options.has_key("password") else None + history_options = options["history"] == "True" if "history" in options else None + password = options["password"] if "password" in options else None - return self.clients[profile].join(room_jid, nick, history_options, password).addCallbacks(self.__room_joined, self.__err_joining_room, callbackKeywords={'profile':profile}, errbackArgs=[room_jid, nick, history_options, password, profile]) + return self.clients[profile].join(room_jid, nick, history_options, password).addCallbacks(self.__room_joined, self.__err_joining_room, callbackKeywords={'profile': profile}, errbackArgs=[room_jid, nick, history_options, password, profile]) def _join(self, room_jid_s, nick, options={}, profile_key='@DEFAULT@'): """join method used by bridge: use the _join method, but doesn't return any deferred""" @@ -186,13 +187,13 @@ self.host.bridge.newAlert(mess, _("Group chat error"), "ERROR", profile) return d = self.join(room_jid, nick, options, profile) - d.addErrback(lambda x: warning(_('Error while joining room'))) #TODO: error management + signal in bridge + d.addErrback(lambda x: warning(_('Error while joining room'))) # TODO: error management + signal in bridge def nick(self, room_jid, nick, profile_key): profile = self.host.memory.getProfileName(profile_key) if not self.__check_profile(profile): raise exceptions.UnknownProfileError("Unknown or disconnected profile") - if not self.clients[profile].joined_rooms.has_key(room_jid.userhost()): + if room_jid.userhost() not in self.clients[profile].joined_rooms: raise UnknownRoom("This room has not been joined") return self.clients[profile].nick(room_jid, nick) @@ -200,7 +201,7 @@ profile = self.host.memory.getProfileName(profile_key) if not self.__check_profile(profile): raise exceptions.UnknownProfileError("Unknown or disconnected profile") - if not self.clients[profile].joined_rooms.has_key(room_jid.userhost()): + if room_jid.userhost() not in self.clients[profile].joined_rooms: raise UnknownRoom("This room has not been joined") return self.clients[profile].leave(room_jid) @@ -208,7 +209,7 @@ profile = self.host.memory.getProfileName(profile_key) if not self.__check_profile(profile): raise exceptions.UnknownProfileError("Unknown or disconnected profile") - if not self.clients[profile].joined_rooms.has_key(room_jid.userhost()): + if room_jid.userhost() not in self.clients[profile].joined_rooms: raise UnknownRoom("This room has not been joined") return self.clients[profile].subject(room_jid, subject) @@ -232,9 +233,9 @@ self.plugin_parent = plugin_parent self.host = plugin_parent.host muc.MUCClient.__init__(self) - self.joined_rooms = {} #FIXME: seem to do the same thing as MUCClient's _rooms attribute, must be removed + self.joined_rooms = {} # FIXME: seem to do the same thing as MUCClient's _rooms attribute, must be removed self.rec_subjects = {} - self.__changing_nicks = set() # used to keep trace of who is changing nick, + self.__changing_nicks = set() # used to keep trace of who is changing nick, # and to discard userJoinedRoom signal in this case print "init SatMUCClient OK" @@ -271,35 +272,35 @@ if user.nick in self.__changing_nicks: self.__changing_nicks.remove(user.nick) else: - debug (_("user %(nick)s has joined room (%(room_id)s)") % {'nick':user.nick, 'room_id':room.occupantJID.userhost()}) + debug(_("user %(nick)s has joined room (%(room_id)s)") % {'nick': user.nick, 'room_id': room.occupantJID.userhost()}) if not self.host.trigger.point("MUC user joined", room, user, self.parent.profile): return - user_data={'entity':user.entity.full() if user.entity else '', 'affiliation':user.affiliation, 'role':user.role} + user_data = {'entity': user.entity.full() if user.entity else '', 'affiliation': user.affiliation, 'role': user.role} self.host.bridge.roomUserJoined(room.roomJID.userhost(), user.nick, user_data, self.parent.profile) def userLeftRoom(self, room, user): if user.nick == room.nick: # we left the room room_jid_s = room.roomJID.userhost() - info (_("Room [%(room)s] left (%(profile)s))") % { "room": room_jid_s, - "profile": self.parent.profile }) + info(_("Room [%(room)s] left (%(profile)s))") % {"room": room_jid_s, + "profile": self.parent.profile}) self.host.memory.delEntityCache(room.roomJID, self.parent.profile) del self.plugin_parent.clients[self.parent.profile].joined_rooms[room_jid_s] self.host.bridge.roomLeft(room.roomJID.userhost(), self.parent.profile) else: - debug (_("user %(nick)s left room (%(room_id)s)") % {'nick':user.nick, 'room_id':room.occupantJID.userhost()}) - user_data={'entity':user.entity.full() if user.entity else '', 'affiliation':user.affiliation, 'role':user.role} + debug(_("user %(nick)s left room (%(room_id)s)") % {'nick': user.nick, 'room_id': room.occupantJID.userhost()}) + user_data = {'entity': user.entity.full() if user.entity else '', 'affiliation': user.affiliation, 'role': user.role} self.host.bridge.roomUserLeft(room.roomJID.userhost(), user.nick, user_data, self.parent.profile) def userChangedNick(self, room, user, new_nick): - self.host.bridge.roomUserChangedNick(room.roomJID.userhost(), user.nick, new_nick, self.parent.profile) + self.host.bridge.roomUserChangedNick(room.roomJID.userhost(), user.nick, new_nick, self.parent.profile) def userUpdatedStatus(self, room, user, show, status): print("FIXME: MUC status not managed yet") #FIXME: def receivedSubject(self, room, user, subject): - debug (_("New subject for room (%(room_id)s): %(subject)s") % {'room_id':room.roomJID.full(),'subject':subject}) + debug(_("New subject for room (%(room_id)s): %(subject)s") % {'room_id': room.roomJID.full(), 'subject': subject}) self.rec_subjects[room.roomJID.userhost()] = (room.roomJID.userhost(), subject) self.host.bridge.roomNewSubject(room.roomJID.userhost(), subject, self.parent.profile) @@ -311,4 +312,3 @@ #def getDiscoItems(self, requestor, target, nodeIdentifier=''): #return [] - diff -r 70bae685d05c -r e629371a28d3 src/plugins/plugin_xep_0047.py --- a/src/plugins/plugin_xep_0047.py Mon Jan 21 00:59:50 2013 +0100 +++ b/src/plugins/plugin_xep_0047.py Fri Jan 18 17:55:35 2013 +0100 @@ -44,19 +44,20 @@ IBB_CLOSE = IQ_SET + '/close[@xmlns="' + NS_IBB + '" and @sid="%s"]' IBB_IQ_DATA = IQ_SET + '/data[@xmlns="' + NS_IBB + '" and @sid="%s"]' IBB_MESSAGE_DATA = MESSAGE + '/data[@xmlns="' + NS_IBB + '" and @sid="%s"]' -TIMEOUT = 60 #timeout for workflow +TIMEOUT = 60 # timeout for workflow BLOCK_SIZE = 4096 PLUGIN_INFO = { -"name": "In-Band Bytestream Plugin", -"import_name": "XEP-0047", -"type": "XEP", -"protocols": ["XEP-0047"], -"main": "XEP_0047", -"handler": "yes", -"description": _("""Implementation of In-Band Bytestreams""") + "name": "In-Band Bytestream Plugin", + "import_name": "XEP-0047", + "type": "XEP", + "protocols": ["XEP-0047"], + "main": "XEP_0047", + "handler": "yes", + "description": _("""Implementation of In-Band Bytestreams""") } + class XEP_0047(object): NAMESPACE = NS_IBB @@ -71,7 +72,7 @@ client = self.host.getClient(profile) if not client: raise ProfileNotInCacheError - client.xep_0047_current_stream = {} #key: stream_id, value: data(dict) + client.xep_0047_current_stream = {} # key: stream_id, value: data(dict) def _timeOut(self, sid, profile): """Delecte current_stream id, called after timeout @@ -87,14 +88,14 @@ if not client: warning(_("Client no more in cache")) return - if not client.xep_0047_current_stream.has_key(sid): + if sid not in client.xep_0047_current_stream: warning(_("kill id called on a non existant id")) return - if client.xep_0047_current_stream[sid].has_key("observer_cb"): + if "observer_cb" in client.xep_0047_current_stream[sid]: client.xmlstream.removeObserver(client.xep_0047_current_stream[sid]["event_data"], client.xep_0047_current_stream[sid]["observer_cb"]) if client.xep_0047_current_stream[sid]['timer'].active(): client.xep_0047_current_stream[sid]['timer'].cancel() - if client.xep_0047_current_stream[sid].has_key("size"): + if "size" in client.xep_0047_current_stream[sid]: self.host.removeProgressCB(sid, profile) file_obj = client.xep_0047_current_stream[sid]['file_obj'] @@ -145,7 +146,7 @@ def streamOpening(self, IQ, profile): debug(_("IBB stream opening")) - IQ.handled=True + IQ.handled = True client = self.host.getClient(profile) if not client: raise ProfileNotInCacheError @@ -153,7 +154,7 @@ block_size = open_elt.getAttribute('block-size') sid = open_elt.getAttribute('sid') stanza = open_elt.getAttribute('stanza', 'iq') - if not sid or not block_size or int(block_size)>65535: + if not sid or not block_size or int(block_size) > 65535: warning(_("malformed IBB transfer: %s" % IQ['id'])) self.sendNotAcceptableError(IQ['id'], IQ['from'], client.xmlstream) return @@ -173,12 +174,12 @@ client.xep_0047_current_stream[sid]["timer"].reset(TIMEOUT) #we save the xmlstream, events and observer data to allow observer removal - client.xep_0047_current_stream[sid]["event_data"] = event_data = (IBB_MESSAGE_DATA if stanza=='message' else IBB_IQ_DATA) % sid - client.xep_0047_current_stream[sid]["observer_cb"] = observer_cb = self.messageData if stanza=='message' else self.iqData + client.xep_0047_current_stream[sid]["event_data"] = event_data = (IBB_MESSAGE_DATA if stanza == 'message' else IBB_IQ_DATA) % sid + client.xep_0047_current_stream[sid]["observer_cb"] = observer_cb = self.messageData if stanza == 'message' else self.iqData event_close = IBB_CLOSE % sid #we now set the stream observer to look after data packet - client.xmlstream.addObserver(event_data, observer_cb, profile = profile) - client.xmlstream.addOnetimeObserver(event_close, self.streamClosing, profile = profile) + client.xmlstream.addObserver(event_data, observer_cb, profile=profile) + client.xmlstream.addOnetimeObserver(event_close, self.streamClosing, profile=profile) #finally, we send the accept stanza result = domish.Element((None, 'iq')) result['type'] = 'result' @@ -187,7 +188,7 @@ client.xmlstream.send(result) def streamClosing(self, IQ, profile): - IQ.handled=True + IQ.handled = True client = self.host.getClient(profile) if not client: raise ProfileNotInCacheError @@ -202,7 +203,7 @@ self._killId(sid, success=True, profile=profile) def iqData(self, IQ, profile): - IQ.handled=True + IQ.handled = True client = self.host.getClient(profile) if not client: raise ProfileNotInCacheError @@ -219,7 +220,7 @@ def messageData(self, message_elt, profile): data_elt = message_elt.firstChildElement() - sid = message_elt.getAttribute('id','') + sid = message_elt.getAttribute('id', '') self._manageDataElt(message_elt, 'message', sid, jid.JID(message_elt['from']), profile) def _manageDataElt(self, data_elt, stanza, sid, stanza_from_jid, profile): @@ -239,14 +240,14 @@ if stanza_from_jid != from_jid: warning(_("sended jid inconsistency (man in the middle attack attempt ?)")) - if stanza=='iq': + if stanza == 'iq': self.sendNotAcceptableError(sid, from_jid, client.xmlstream) return False - client.xep_0047_current_stream[sid]["seq"]+=1 - if int(data_elt.getAttribute("seq",-1)) != client.xep_0047_current_stream[sid]["seq"]: + client.xep_0047_current_stream[sid]["seq"] += 1 + if int(data_elt.getAttribute("seq", -1)) != client.xep_0047_current_stream[sid]["seq"]: warning(_("Sequence error")) - if stanza=='iq': + if stanza == 'iq': self.sendNotAcceptableError(data_elt["id"], from_jid, client.xmlstream) return False @@ -259,7 +260,7 @@ except TypeError: #The base64 data is invalid warning(_("Invalid base64 data")) - if stanza=='iq': + if stanza == 'iq': self.sendNotAcceptableError(data_elt["id"], from_jid, client.xmlstream) return False return True @@ -275,10 +276,10 @@ result['to'] = to_jid error_el = result.addElement('error') error_el['type'] = 'cancel' - error_el.addElement(('urn:ietf:params:xml:ns:xmpp-stanzas','not-acceptable')) + error_el.addElement(('urn:ietf:params:xml:ns:xmpp-stanzas', 'not-acceptable')) xmlstream.send(result) - def startStream(self, file_obj, to_jid, sid, length, successCb, failureCb, size = None, profile=None): + def startStream(self, file_obj, to_jid, sid, length, successCb, failureCb, size=None, profile=None): """Launch the stream workflow @param file_obj: file_obj to send @param to_jid: JID of the recipient @@ -290,7 +291,7 @@ client = self.host.getClient(profile) if not client: raise ProfileNotInCacheError - if length != None: + if length is not None: error(_('stream length not managed yet')) return data = client.xep_0047_current_stream[sid] = {} @@ -303,10 +304,10 @@ if size: data["size"] = size self.host.registerProgressCB(sid, self.getProgress, profile) - iq_elt = jabber_client.IQ(client.xmlstream,'set') + iq_elt = jabber_client.IQ(client.xmlstream, 'set') iq_elt['from'] = client.jid.full() iq_elt['to'] = to_jid.full() - open_elt = iq_elt.addElement('open',NS_IBB) + open_elt = iq_elt.addElement('open', NS_IBB) open_elt['block-size'] = str(BLOCK_SIZE) open_elt['sid'] = sid open_elt['stanza'] = 'iq' @@ -329,18 +330,18 @@ buffer = data["file_obj"].read(data["block_size"]) if buffer: - next_iq_elt = jabber_client.IQ(client.xmlstream,'set') + next_iq_elt = jabber_client.IQ(client.xmlstream, 'set') next_iq_elt['to'] = data["to"].full() data_elt = next_iq_elt.addElement('data', NS_IBB) data_elt['seq'] = str(seq) data_elt['sid'] = sid data_elt.addContent(base64.b64encode(buffer)) - next_iq_elt.addCallback(self.iqResult, sid, seq+1, length, profile) + next_iq_elt.addCallback(self.iqResult, sid, seq + 1, length, profile) next_iq_elt.send() else: self.terminateStream(sid, profile=profile) - def terminateStream(self, sid, failure_reason = None, profile=None): + def terminateStream(self, sid, failure_reason=None, profile=None): """Terminate the stream session @param to_jid: recipient @param sid: Session id @@ -353,9 +354,9 @@ if not client: raise ProfileNotInCacheError data = client.xep_0047_current_stream[sid] - iq_elt = jabber_client.IQ(client.xmlstream,'set') + iq_elt = jabber_client.IQ(client.xmlstream, 'set') iq_elt['to'] = data["to"].full() - close_elt = iq_elt.addElement('close',NS_IBB) + close_elt = iq_elt.addElement('close', NS_IBB) close_elt['sid'] = sid iq_elt.send() self.host.removeProgressCB(sid, profile) @@ -364,14 +365,15 @@ else: self._killId(sid, True, profile=profile) + class XEP_0047_handler(XMPPHandler): implements(iwokkel.IDisco) - def __init__(self,parent): + def __init__(self, parent): self.plugin_parent = parent def connectionInitialized(self): - self.xmlstream.addObserver(IBB_OPEN, self.plugin_parent.streamOpening, profile = self.parent.profile) + self.xmlstream.addObserver(IBB_OPEN, self.plugin_parent.streamOpening, profile=self.parent.profile) def getDiscoInfo(self, requestor, target, nodeIdentifier=''): return [disco.DiscoFeature(NS_IBB)] diff -r 70bae685d05c -r e629371a28d3 src/plugins/plugin_xep_0054.py --- a/src/plugins/plugin_xep_0054.py Mon Jan 21 00:59:50 2013 +0100 +++ b/src/plugins/plugin_xep_0054.py Fri Jan 18 17:55:35 2013 +0100 @@ -31,7 +31,7 @@ from wokkel import disco, iwokkel -from base64 import b64decode,b64encode +from base64 import b64decode, b64encode from hashlib import sha1 from sat.core import exceptions from sat.memory.persistent import PersistentDict @@ -47,23 +47,24 @@ IQ_GET = '/iq[@type="get"]' NS_VCARD = 'vcard-temp' -VCARD_REQUEST = IQ_GET + '/vCard[@xmlns="' + NS_VCARD + '"]' #TODO: manage requests +VCARD_REQUEST = IQ_GET + '/vCard[@xmlns="' + NS_VCARD + '"]' # TODO: manage requests PRESENCE = '/presence' NS_VCARD_UPDATE = 'vcard-temp:x:update' -VCARD_UPDATE = PRESENCE + '/x[@xmlns="' + NS_VCARD_UPDATE + '"]' +VCARD_UPDATE = PRESENCE + '/x[@xmlns="' + NS_VCARD_UPDATE + '"]' PLUGIN_INFO = { -"name": "XEP 0054 Plugin", -"import_name": "XEP-0054", -"type": "XEP", -"protocols": ["XEP-0054", "XEP-0153"], -"dependencies": [], -"main": "XEP_0054", -"handler": "yes", -"description": _("""Implementation of vcard-temp""") + "name": "XEP 0054 Plugin", + "import_name": "XEP-0054", + "type": "XEP", + "protocols": ["XEP-0054", "XEP-0153"], + "dependencies": [], + "main": "XEP_0054", + "handler": "yes", + "description": _("""Implementation of vcard-temp""") } + class XEP_0054(object): #TODO: - check that nickname is ok # - refactor the code/better use of Wokkel @@ -76,10 +77,10 @@ if not os.path.exists(self.avatar_path): os.makedirs(self.avatar_path) self.avatars_cache = PersistentDict(NS_VCARD) - self.avatars_cache.load() #FIXME: resulting deferred must be correctly managed + self.avatars_cache.load() # FIXME: resulting deferred must be correctly managed host.bridge.addMethod("getCard", ".plugin", in_sign='ss', out_sign='s', method=self.getCard) host.bridge.addMethod("getAvatarFile", ".plugin", in_sign='s', out_sign='s', method=self.getAvatarFile) - host.bridge.addMethod("setAvatar", ".plugin", in_sign='ss', out_sign='', method=self.setAvatar, async = True) + host.bridge.addMethod("setAvatar", ".plugin", in_sign='ss', out_sign='', method=self.setAvatar, async=True) host.trigger.add("presence_available", self.presenceTrigger) def getHandler(self, profile): @@ -144,9 +145,9 @@ debug(_('Decoding binary')) decoded = b64decode(str(elem)) image_hash = sha1(decoded).hexdigest() - filename = self.avatar_path+'/'+image_hash + filename = self.avatar_path + '/' + image_hash if not os.path.exists(filename): - with open(filename,'wb') as file: + with open(filename, 'wb') as file: file.write(decoded) debug(_("file saved to %s") % image_hash) else: @@ -156,7 +157,7 @@ @inlineCallbacks def vCard2Dict(self, vcard, target, profile): """Convert a VCard to a dict, and save binaries""" - debug (_("parsing vcard")) + debug(_("parsing vcard")) dictionary = {} for elem in vcard.elements(): @@ -173,18 +174,18 @@ dictionary['birthday'] = unicode(elem) elif elem.name == 'PHOTO': dictionary["avatar"] = yield threads.deferToThread(self.save_photo, elem) - if not dictionary["avatar"]: #can happen in case of e.g. empty photo elem + if not dictionary["avatar"]: # can happen in case of e.g. empty photo elem del dictionary['avatar'] else: self.update_cache(target, 'avatar', dictionary['avatar'], profile) else: - info (_('FIXME: [%s] VCard tag is not managed yet') % elem.name) + info(_('FIXME: [%s] VCard tag is not managed yet') % elem.name) returnValue(dictionary) def vcard_ok(self, answer, profile): """Called after the first get IQ""" - debug (_("VCard found")) + debug(_("VCard found")) if answer.firstChildElement().name == "vCard": _jid, steam = self.host.getJidNStream(profile) @@ -195,13 +196,13 @@ d = self.vCard2Dict(answer.firstChildElement(), from_jid, profile) d.addCallback(lambda data: self.host.bridge.actionResult("RESULT", answer['id'], data, profile)) else: - error (_("FIXME: vCard not found as first child element")) - self.host.bridge.actionResult("SUPPRESS", answer['id'], {}, profile) #FIXME: maybe an error message would be better + error(_("FIXME: vCard not found as first child element")) + self.host.bridge.actionResult("SUPPRESS", answer['id'], {}, profile) # FIXME: maybe an error message would be better def vcard_err(self, failure, profile): """Called when something is wrong with registration""" - error (_("Can't find VCard of %s") % failure.value.stanza['from']) - self.host.bridge.actionResult("SUPPRESS", failure.value.stanza['id'], {}, profile) #FIXME: maybe an error message would be better + error(_("Can't find VCard of %s") % failure.value.stanza['from']) + self.host.bridge.actionResult("SUPPRESS", failure.value.stanza['id'], {}, profile) # FIXME: maybe an error message would be better def getCard(self, target_s, profile_key='@DEFAULT@'): """Ask server for VCard @@ -209,13 +210,13 @@ @result: id to retrieve the profile""" current_jid, xmlstream = self.host.getJidNStream(profile_key) if not xmlstream: - error (_('Asking vcard for a non-existant or not connected profile')) + error(_('Asking vcard for a non-existant or not connected profile')) return "" profile = self.host.memory.getProfileName(profile_key) to_jid = jid.JID(target_s) debug(_("Asking for %s's VCard") % to_jid.userhost()) - reg_request=IQ(xmlstream,'get') - reg_request["from"]=current_jid.full() + reg_request = IQ(xmlstream, 'get') + reg_request["from"] = current_jid.full() reg_request["to"] = to_jid.userhost() reg_request.addElement('vCard', NS_VCARD) reg_request.send(to_jid.userhost()).addCallbacks(self.vcard_ok, self.vcard_err, callbackArgs=[profile], errbackArgs=[profile]) @@ -226,9 +227,9 @@ @param hash: SHA1 hash @return full_path """ - filename = self.avatar_path+'/'+avatar_hash + filename = self.avatar_path + '/' + avatar_hash if not os.path.exists(filename): - error (_("Asking for an uncached avatar [%s]") % avatar_hash) + error(_("Asking for an uncached avatar [%s]") % avatar_hash) return "" return filename @@ -259,13 +260,13 @@ if not client: raise exceptions.NotConnectedProfileError(_('Trying to set avatar for a non-existant or not connected profile')) - vcard_set = IQ(client.xmlstream,'set') + vcard_set = IQ(client.xmlstream, 'set') d = threads.deferToThread(self._buildSetAvatar, vcard_set, filepath) def elementBuilt(result): """Called once the image is at the right size/format, and the vcard set element is build""" set_avatar_elt, img_hash = result - self.avatars_cache[client.jid.userhost()] = img_hash # we need to update the hash, so we can send a new presence + self.avatars_cache[client.jid.userhost()] = img_hash # we need to update the hash, so we can send a new presence # element with the right hash return set_avatar_elt.send().addCallback(lambda ignore: client.presence.available()) @@ -296,7 +297,7 @@ """ from_jid = jid.JID(presence['from']) #FIXME: wokkel's data_form should be used here - x_elem = filter (lambda x:x.name == "x", presence.elements())[0] #We only want the "x" element + x_elem = filter(lambda x: x.name == "x", presence.elements())[0] # We only want the "x" element for elem in x_elem.elements(): if elem.name == 'photo': _hash = str(elem) diff -r 70bae685d05c -r e629371a28d3 src/plugins/plugin_xep_0060.py --- a/src/plugins/plugin_xep_0060.py Mon Jan 21 00:59:50 2013 +0100 +++ b/src/plugins/plugin_xep_0060.py Fri Jan 18 17:55:35 2013 +0100 @@ -30,23 +30,24 @@ from zope.interface import implements PLUGIN_INFO = { -"name": "Publish-Subscribe", -"import_name": "XEP-0060", -"type": "XEP", -"protocols": ["XEP-0060"], -"dependencies": [], -"main": "XEP_0060", -"handler": "yes", -"description": _("""Implementation of PubSub Protocol""") + "name": "Publish-Subscribe", + "import_name": "XEP-0060", + "type": "XEP", + "protocols": ["XEP-0060"], + "dependencies": [], + "main": "XEP_0060", + "handler": "yes", + "description": _("""Implementation of PubSub Protocol""") } + class XEP_0060(object): def __init__(self, host): info(_("PubSub plugin initialization")) self.host = host - self.managedNodes=[] - self.clients={} + self.managedNodes = [] + self.clients = {} """host.bridge.addMethod("getItems", ".plugin", in_sign='ssa{ss}s', out_sign='as', method=self.getItems, async = True, doc = { 'summary':'retrieve items', @@ -78,8 +79,8 @@ profile = self.host.memory.getProfileName(profile_key) if not profile: err_mess = _('Trying to %(action)s with an unknown profile key [%(profile_key)s]') % { - 'action':action, - 'profile_key':profile_key} + 'action': action, + 'profile_key': profile_key} error(err_mess) raise Exception(err_mess) try: @@ -91,31 +92,31 @@ return profile, client def publish(self, service, nodeIdentifier, items=None, profile_key='@DEFAULT@'): - profile,client = self.__getClientNProfile(profile_key, 'publish item') + profile, client = self.__getClientNProfile(profile_key, 'publish item') return client.publish(service, nodeIdentifier, items, client.parent.jid) def getItems(self, service, node, max_items=None, sub_id=None, profile_key='@DEFAULT@'): - profile,client = self.__getClientNProfile(profile_key, 'get items') + profile, client = self.__getClientNProfile(profile_key, 'get items') return client.items(service, node, max_items, sub_id, client.parent.jid) def getOptions(self, service, nodeIdentifier, subscriber, subscriptionIdentifier=None, profile_key='@DEFAULT@'): - profile,client = self.__getClientNProfile(profile_key, 'get options') + profile, client = self.__getClientNProfile(profile_key, 'get options') return client.getOptions(service, nodeIdentifier, subscriber, subscriptionIdentifier) def setOptions(self, service, nodeIdentifier, subscriber, options, subscriptionIdentifier=None, profile_key='@DEFAULT@'): - profile,client = self.__getClientNProfile(profile_key, 'set options') + profile, client = self.__getClientNProfile(profile_key, 'set options') return client.setOptions(service, nodeIdentifier, subscriber, options, subscriptionIdentifier) def createNode(self, service, nodeIdentifier, options, profile_key='@DEFAULT@'): - profile,client = self.__getClientNProfile(profile_key, 'create node') + profile, client = self.__getClientNProfile(profile_key, 'create node') return client.createNode(service, nodeIdentifier, options) def deleteNode(self, service, nodeIdentifier, profile_key='@DEFAULT@'): - profile,client = self.__getClientNProfile(profile_key, 'delete node') + profile, client = self.__getClientNProfile(profile_key, 'delete node') return client.deleteNode(service, nodeIdentifier) - def subscribe(self, service, nodeIdentifier, sub_jid = None, options=None, profile_key='@DEFAULT@'): - profile,client = self.__getClientNProfile(profile_key, 'subscribe node') + def subscribe(self, service, nodeIdentifier, sub_jid=None, options=None, profile_key='@DEFAULT@'): + profile, client = self.__getClientNProfile(profile_key, 'subscribe node') return client.subscribe(service, nodeIdentifier, sub_jid or client.parent.jid.userhostJID(), options=options) @@ -123,7 +124,7 @@ implements(disco.IDisco) def __init__(self, host, parent_plugin): - self.host=host + self.host = host self.parent_plugin = parent_plugin pubsub.PubSubClient.__init__(self) @@ -152,4 +153,3 @@ def getDiscoItems(self, requestor, target, nodeIdentifier=''): return [] - diff -r 70bae685d05c -r e629371a28d3 src/plugins/plugin_xep_0065.py --- a/src/plugins/plugin_xep_0065.py Mon Jan 21 00:59:50 2013 +0100 +++ b/src/plugins/plugin_xep_0065.py Fri Jan 18 17:55:35 2013 +0100 @@ -78,30 +78,28 @@ IQ_SET = '/iq[@type="set"]' NS_BS = 'http://jabber.org/protocol/bytestreams' BS_REQUEST = IQ_SET + '/query[@xmlns="' + NS_BS + '"]' -TIMEOUT = 60 #timeout for workflow - - +TIMEOUT = 60 # timeout for workflow PLUGIN_INFO = { -"name": "XEP 0065 Plugin", -"import_name": "XEP-0065", -"type": "XEP", -"protocols": ["XEP-0065"], -"main": "XEP_0065", -"handler": "yes", -"description": _("""Implementation of SOCKS5 Bytestreams""") + "name": "XEP 0065 Plugin", + "import_name": "XEP-0065", + "type": "XEP", + "protocols": ["XEP-0065"], + "main": "XEP_0065", + "handler": "yes", + "description": _("""Implementation of SOCKS5 Bytestreams""") } STATE_INITIAL = 0 -STATE_AUTH = 1 +STATE_AUTH = 1 STATE_REQUEST = 2 -STATE_READY = 3 +STATE_READY = 3 STATE_AUTH_USERPASS = 4 STATE_TARGET_INITIAL = 5 -STATE_TARGET_AUTH = 6 +STATE_TARGET_AUTH = 6 STATE_TARGET_REQUEST = 7 -STATE_TARGET_READY = 8 -STATE_LAST = 9 +STATE_TARGET_READY = 8 +STATE_LAST = 9 STATE_CONNECT_PENDING = STATE_LAST + 1 @@ -139,15 +137,14 @@ return hashlib.sha1((sid + from_jid.full() + to_jid.full()).encode('utf-8')).hexdigest() - class SOCKSv5(protocol.Protocol, FileSender): def __init__(self): debug(_("Protocol init")) self.state = STATE_INITIAL self.buf = "" - self.supportedAuthMechs = [ AUTHMECH_ANON ] - self.supportedAddrs = [ ADDR_DOMAINNAME ] - self.enabledCommands = [ CMD_CONNECT ] + self.supportedAuthMechs = [AUTHMECH_ANON] + self.supportedAddrs = [ADDR_DOMAINNAME] + self.enabledCommands = [CMD_CONNECT] self.peersock = None self.addressType = 0 self.requestType = 0 @@ -162,7 +159,7 @@ try: # Parse out data ver, nmethod = struct.unpack('!BB', self.buf[:2]) - methods = struct.unpack('%dB' % nmethod, self.buf[2:nmethod+2]) + methods = struct.unpack('%dB' % nmethod, self.buf[2:nmethod + 2]) # Ensure version is correct if ver != 5: @@ -171,7 +168,7 @@ return # Trim off front of the buffer - self.buf = self.buf[nmethod+2:] + self.buf = self.buf[nmethod + 2:] # Check for supported auth mechs for m in self.supportedAuthMechs: @@ -320,7 +317,7 @@ debug("connectRequested") # Check that this session is expected - if not self.factory.hash_sid_map.has_key(addr): + if addr not in self.factory.hash_sid_map: #no: we refuse it self.sendErrorReply(REPLY_CONN_REFUSED) return @@ -374,14 +371,13 @@ if self.state == STATE_TARGET_AUTH: ver, method = struct.unpack('!BB', buf) self.buf = self.buf[2:] - if ver!=SOCKS5_VER or method!=AUTHMECH_ANON: + if ver != SOCKS5_VER or method != AUTHMECH_ANON: self.transport.loseConnection() else: self._makeRequest() if self.state == STATE_TARGET_REQUEST: self._parseRequestReply() - def clientConnectionLost(self, reason): debug("clientConnectionLost") self.transport.loseConnection() @@ -390,7 +386,7 @@ debug("connectionLost") if self.state != STATE_CONNECT_PENDING: self.transport.unregisterProducer() - if self.peersock != None: + if self.peersock is not None: self.peersock.peersock = None self.peersock.transport.unregisterProducer() self.peersock = None @@ -405,10 +401,11 @@ self.finishedCb = finishedCb def startedConnecting(self, connector): - debug (_("Socks 5 server connection started")) + debug(_("Socks 5 server connection started")) def clientConnectionLost(self, connector, reason): - debug (_("Socks 5 server connection lost (reason: %s)"), reason) + debug(_("Socks 5 server connection lost (reason: %s)"), reason) + class Socks5ClientFactory(protocol.ClientFactory): protocol = SOCKSv5 @@ -432,11 +429,11 @@ self.profile = profile def startedConnecting(self, connector): - debug (_("Socks 5 client connection started")) + debug(_("Socks 5 client connection started")) def clientConnectionLost(self, connector, reason): - debug (_("Socks 5 client connection lost (reason: %s)"), reason) - self.finishedCb(self.sid, reason.type == jab_error.ConnectionDone, self.profile) #TODO: really check if the state is actually successful + debug(_("Socks 5 client connection lost (reason: %s)"), reason) + self.finishedCb(self.sid, reason.type == jab_error.ConnectionDone, self.profile) # TODO: really check if the state is actually successful class XEP_0065(object): @@ -465,7 +462,7 @@ info(_("Plugin XEP_0065 initialization")) #session data - self.hash_sid_map = {} #key: hash of the transfer session, value: (session id, profile) + self.hash_sid_map = {} # key: hash of the transfer session, value: (session id, profile) self.host = host debug(_("registering")) @@ -486,7 +483,7 @@ client = self.host.getClient(profile) if not client: raise ProfileNotInCacheError - client.xep_0065_current_stream = {} #key: stream_id, value: data(dict) + client.xep_0065_current_stream = {} # key: stream_id, value: data(dict) def getExternalIP(self): """Return IP visible from outside, by asking to a website""" @@ -518,15 +515,15 @@ if not client: warning(_("Client no more in cache")) return - if not client.xep_0065_current_stream.has_key(sid): + if sid not in client.xep_0065_current_stream: warning(_("kill id called on a non existant id")) return - if client.xep_0065_current_stream[sid].has_key("observer_cb"): + if "observer_cb" in client.xep_0065_current_stream[sid]: xmlstream = client.xep_0065_current_stream[sid]["xmlstream"] xmlstream.removeObserver(client.xep_0065_current_stream[sid]["event_data"], client.xep_0065_current_stream[sid]["observer_cb"]) if client.xep_0065_current_stream[sid]['timer'].active(): client.xep_0065_current_stream[sid]['timer'].cancel() - if client.xep_0065_current_stream[sid].has_key("size"): + if "size" in client.xep_0065_current_stream[sid]: self.host.removeProgressCB(sid, profile) file_obj = client.xep_0065_current_stream[sid]['file_obj'] @@ -544,7 +541,7 @@ else: failure_cb(sid, file_obj, NS_BS, failure_reason, profile) - def startStream(self, file_obj, to_jid, sid, length, successCb, failureCb, size = None, profile=None): + def startStream(self, file_obj, to_jid, sid, length, successCb, failureCb, size=None, profile=None): """Launch the stream workflow @param file_obj: file_obj to send @param to_jid: JID of the recipient @@ -559,7 +556,7 @@ error(_("Unknown profile, this should not happen")) raise ProfileNotInCacheError - if length != None: + if length is not None: error(_('stream length not managed yet')) return @@ -579,7 +576,7 @@ if size: data["size"] = size self.host.registerProgressCB(sid, self.getProgress, profile) - iq_elt = jabber_client.IQ(xmlstream,'set') + iq_elt = jabber_client.IQ(xmlstream, 'set') iq_elt["from"] = profile_jid.full() iq_elt["to"] = to_jid.full() query_elt = iq_elt.addElement('query', NS_BS) @@ -638,7 +635,7 @@ factory = Socks5ClientFactory(client.xep_0065_current_stream, sid, None, self.activateProxyStream, lambda sid, success, profile: self._killId(sid, success, profile=profile), True, profile) reactor.connectTCP(proxy_host, int(proxy_port), factory) else: - data["start_transfer_cb"](file_obj) #We now activate the stream + data["start_transfer_cb"](file_obj) # We now activate the stream def activateProxyStream(self, sid, iq_id, start_transfer_cb, profile): debug(_("activating stream")) @@ -648,7 +645,7 @@ data = client.xep_0065_current_stream[sid] profile_jid, xmlstream = self.host.getJidNStream(profile) - iq_elt = client.IQ(xmlstream,'set') + iq_elt = client.IQ(xmlstream, 'set') iq_elt["from"] = profile_jid.full() iq_elt["to"] = self.host.memory.getParamA("Proxy", "File Transfer", profile_key=profile) query_elt = iq_elt.addElement('query', NS_BS) @@ -687,7 +684,6 @@ data["success_cb"] = success_cb data["failure_cb"] = failure_cb - def streamQuery(self, iq_elt, profile): """Get file using byte stream""" debug(_("BS stream query")) @@ -717,7 +713,7 @@ self.sendBadRequestError(iq_elt['id'], iq_elt['from'], xmlstream) return - streamhost_elt = streamhost_elts[0] #TODO: manage several streamhost elements case + streamhost_elt = streamhost_elts[0] # TODO: manage several streamhost elements case sh_host = streamhost_elt.getAttribute("host") sh_port = streamhost_elt.getAttribute("port") sh_jid = streamhost_elt.getAttribute("jid") @@ -728,7 +724,7 @@ client.xep_0065_current_stream[sid]["streamhost"] = (sh_host, sh_port, sh_jid) - info (_("Stream proposed: host=[%(host)s] port=[%(port)s]") % {'host':sh_host, 'port':sh_port}) + info(_("Stream proposed: host=[%(host)s] port=[%(port)s]") % {'host': sh_host, 'port': sh_port}) factory = Socks5ClientFactory(client.xep_0065_current_stream, sid, iq_elt["id"], self.activateStream, lambda sid, success, profile: self._killId(sid, success, profile=profile), profile=profile) reactor.connectTCP(sh_host, int(sh_port), factory) @@ -760,7 +756,7 @@ result['to'] = to_jid error_el = result.addElement('error') error_el['type'] = 'modify' - error_el.addElement(('urn:ietf:params:xml:ns:xmpp-stanzas','not-acceptable')) + error_el.addElement(('urn:ietf:params:xml:ns:xmpp-stanzas', 'not-acceptable')) xmlstream.send(result) def sendBadRequestError(self, iq_id, to_jid, xmlstream): @@ -774,9 +770,10 @@ result['to'] = to_jid error_el = result.addElement('error') error_el['type'] = 'cancel' - error_el.addElement(('urn:ietf:params:xml:ns:xmpp-stanzas','bad-request')) + error_el.addElement(('urn:ietf:params:xml:ns:xmpp-stanzas', 'bad-request')) xmlstream.send(result) + class XEP_0065_handler(XMPPHandler): implements(iwokkel.IDisco) @@ -801,10 +798,9 @@ if len(streamhost_elts) != 1: warning(_("Multiple streamhost elements in proxy not managed, keeping only the first one")) streamhost_elt = streamhost_elts[0] - proxy = self.host.memory.setParam("Proxy", streamhost_elt.getAttribute("jid",""), "File Transfer", self.parent.profile) - proxy = self.host.memory.setParam("Proxy host", streamhost_elt.getAttribute("host",""), "File Transfer", self.parent.profile) - proxy = self.host.memory.setParam("Proxy port", streamhost_elt.getAttribute("port",""), "File Transfer", self.parent.profile) - + proxy = self.host.memory.setParam("Proxy", streamhost_elt.getAttribute("jid", ""), "File Transfer", self.parent.profile) + proxy = self.host.memory.setParam("Proxy host", streamhost_elt.getAttribute("host", ""), "File Transfer", self.parent.profile) + proxy = self.host.memory.setParam("Proxy port", streamhost_elt.getAttribute("port", ""), "File Transfer", self.parent.profile) def connectionInitialized(self): def after_init(ignore): @@ -812,20 +808,17 @@ if not proxy_ent: debug(_("No proxy found on this server")) return - iq_elt = jabber_client.IQ(self.parent.xmlstream,'get') + iq_elt = jabber_client.IQ(self.parent.xmlstream, 'get') iq_elt["to"] = proxy_ent.full() query_elt = iq_elt.addElement('query', NS_BS) iq_elt.addCallback(self._proxyDataResult) iq_elt.send() - - self.xmlstream.addObserver(BS_REQUEST, self.plugin_parent.streamQuery, profile = self.parent.profile) - proxy = self.host.memory.getParamA("Proxy", "File Transfer", profile_key = self.parent.profile) + self.xmlstream.addObserver(BS_REQUEST, self.plugin_parent.streamQuery, profile=self.parent.profile) + proxy = self.host.memory.getParamA("Proxy", "File Transfer", profile_key=self.parent.profile) if not proxy: self.parent.client_initialized.addCallback(after_init) - - def getDiscoInfo(self, requestor, target, nodeIdentifier=''): return [disco.DiscoFeature(NS_BS)] diff -r 70bae685d05c -r e629371a28d3 src/plugins/plugin_xep_0077.py --- a/src/plugins/plugin_xep_0077.py Mon Jan 21 00:59:50 2013 +0100 +++ b/src/plugins/plugin_xep_0077.py Fri Jan 18 17:55:35 2013 +0100 @@ -29,21 +29,22 @@ NS_REG = 'jabber:iq:register' PLUGIN_INFO = { -"name": "XEP 0077 Plugin", -"import_name": "XEP-0077", -"type": "XEP", -"protocols": ["XEP-0077"], -"dependencies": [], -"main": "XEP_0077", -"description": _("""Implementation of in-band registration""") + "name": "XEP 0077 Plugin", + "import_name": "XEP-0077", + "type": "XEP", + "protocols": ["XEP-0077"], + "dependencies": [], + "main": "XEP_0077", + "description": _("""Implementation of in-band registration""") } + class XEP_0077(object): def __init__(self, host): info(_("Plugin XEP_0077 initialization")) self.host = host - self.triggers = {} #used by other protocol (e.g. XEP-0100) to finish registration. key = target_jid + self.triggers = {} # used by other protocol (e.g. XEP-0100) to finish registration. key = target_jid host.bridge.addMethod("in_band_register", ".plugin", in_sign='ss', out_sign='s', method=self.in_band_register) host.bridge.addMethod("in_band_submit", ".plugin", in_sign='ssa(ss)s', out_sign='s', method=self.in_band_submit) @@ -54,65 +55,65 @@ def reg_ok(self, answer, profile): """Called after the first get IQ""" try: - x_elem = filter (lambda x:x.name == "x", answer.firstChildElement().elements())[0] #We only want the "x" element (data form) + x_elem = filter(lambda x: x.name == "x", answer.firstChildElement().elements())[0] # We only want the "x" element (data form) except IndexError: info(_("No data form found")) #TODO: manage registration without data form - answer_data={"reason": "unmanaged", "message":_("This gateway can't be managed by SàT, sorry :(")} + answer_data = {"reason": "unmanaged", "message": _("This gateway can't be managed by SàT, sorry :(")} answer_type = "ERROR" self.host.bridge.actionResult(answer_type, answer['id'], answer_data, profile) return form = data_form.Form.fromElement(x_elem) xml_data = dataForm2xml(form) - self.host.bridge.actionResult("XMLUI", answer['id'], {"target":answer["from"], "type":"registration", "xml":xml_data}, profile) + self.host.bridge.actionResult("XMLUI", answer['id'], {"target": answer["from"], "type": "registration", "xml": xml_data}, profile) def reg_err(self, failure, profile): """Called when something is wrong with registration""" - info (_("Registration failure: %s") % str(failure.value)) + info(_("Registration failure: %s") % str(failure.value)) answer_data = {} answer_data['reason'] = 'unknown' - answer_data={"message":"%s [code: %s]" % (failure.value.condition, unicode(failure.value))} + answer_data = {"message": "%s [code: %s]" % (failure.value.condition, unicode(failure.value))} answer_type = "ERROR" self.host.bridge.actionResult(answer_type, failure.value.stanza['id'], answer_data, profile) def unregistrationAnswer(self, answer, profile): - debug (_("registration answer: %s") % answer.toXml()) + debug(_("registration answer: %s") % answer.toXml()) answer_type = "SUCCESS" - answer_data={"message":_("Your are now unregistred")} + answer_data = {"message": _("Your are now unregistred")} self.host.bridge.actionResult(answer_type, answer['id'], answer_data, profile) def unregistrationFailure(self, failure, profile): - info (_("Unregistration failure: %s") % str(failure.value)) + info(_("Unregistration failure: %s") % str(failure.value)) answer_type = "ERROR" answer_data = {} answer_data['reason'] = 'unknown' - answer_data={"message":_("Unregistration failed: %s") % failure.value.condition} + answer_data = {"message": _("Unregistration failed: %s") % failure.value.condition} self.host.bridge.actionResult(answer_type, failure.value.stanza['id'], answer_data, profile) def registrationAnswer(self, answer, profile): - debug (_("registration answer: %s") % answer.toXml()) + debug(_("registration answer: %s") % answer.toXml()) answer_type = "SUCCESS" - answer_data={"message":_("Registration successfull")} + answer_data = {"message": _("Registration successfull")} self.host.bridge.actionResult(answer_type, answer['id'], answer_data, profile) - if self.triggers.has_key(answer["from"]): - callback,profile = self.triggers[answer["from"]] + if answer["from"] in self.triggers: + callback, profile = self.triggers[answer["from"]] callback(answer["from"], profile) del self.triggers[answer["from"]] def registrationFailure(self, failure, profile): - info (_("Registration failure: %s") % str(failure.value)) + info(_("Registration failure: %s") % str(failure.value)) print failure.value.stanza.toXml() answer_type = "ERROR" answer_data = {} if failure.value.condition == 'conflict': answer_data['reason'] = 'conflict' - answer_data={"message":_("Username already exists, please choose an other one")} + answer_data = {"message": _("Username already exists, please choose an other one")} else: answer_data['reason'] = 'unknown' - answer_data={"message":_("Registration failed")} + answer_data = {"message": _("Registration failed")} self.host.bridge.actionResult(answer_type, failure.value.stanza['id'], answer_data, profile) - if failure.value.stanza["from"] in self.triggers.has_key: + if failure.value.stanza["from"] in self.triggers: del self.triggers[failure.value.stanza["from"]] def in_band_submit(self, action, target, fields, profile): @@ -128,12 +129,12 @@ """register to a target JID""" client = self.host.getClient(profile_key) if not client: - error (_('Asking for an non-existant or not connected profile')) + error(_('Asking for an non-existant or not connected profile')) return "" to_jid = jid.JID(target) debug(_("Asking registration for [%s]") % to_jid.full()) - reg_request=IQ(client.xmlstream,'get') - reg_request["from"]=client.jid.full() + reg_request = IQ(client.xmlstream, 'get') + reg_request["from"] = client.jid.full() reg_request["to"] = to_jid.full() reg_request.addElement('query', NS_REG) reg_request.send(to_jid.full()).addCallbacks(self.reg_ok, self.reg_err, callbackArgs=[client.profile], errbackArgs=[client.profile]) diff -r 70bae685d05c -r e629371a28d3 src/plugins/plugin_xep_0095.py --- a/src/plugins/plugin_xep_0095.py Mon Jan 21 00:59:50 2013 +0100 +++ b/src/plugins/plugin_xep_0095.py Fri Jan 18 17:55:35 2013 +0100 @@ -43,21 +43,22 @@ SI_PROFILE_HEADER = "http://jabber.org/protocol/si/profile/" PLUGIN_INFO = { -"name": "XEP 0095 Plugin", -"import_name": "XEP-0095", -"type": "XEP", -"protocols": ["XEP-0095"], -"main": "XEP_0095", -"handler": "yes", -"description": _("""Implementation of Stream Initiation""") + "name": "XEP 0095 Plugin", + "import_name": "XEP-0095", + "type": "XEP", + "protocols": ["XEP-0095"], + "main": "XEP_0095", + "handler": "yes", + "description": _("""Implementation of Stream Initiation""") } + class XEP_0095(object): def __init__(self, host): info(_("Plugin XEP_0095 initialization")) self.host = host - self.si_profiles = {} #key: SI profile, value: callback + self.si_profiles = {} # key: SI profile, value: callback def getHandler(self, profile): return XEP_0095_handler(self) @@ -66,33 +67,33 @@ """Add a callback for a SI Profile param si_profile: SI profile name (e.g. file-transfer) param callback: method to call when the profile name is asked""" - self.si_profiles[si_profile] = callback + self.si_profiles[si_profile] = callback def streamInit(self, iq_el, profile): """This method is called on stream initiation (XEP-0095 #3.2) @param iq_el: IQ element @param profile: %(doc_profile)s""" - info (_("XEP-0095 Stream initiation")) - iq_el.handled=True + info(_("XEP-0095 Stream initiation")) + iq_el.handled = True si_el = iq_el.firstChildElement() si_id = si_el.getAttribute('id') si_mime_type = iq_el.getAttribute('mime-type', 'application/octet-stream') si_profile = si_el.getAttribute('profile') - si_profile_key = si_profile[len(SI_PROFILE_HEADER):] if si_profile.startswith(SI_PROFILE_HEADER) else si_profile - if self.si_profiles.has_key(si_profile_key): + si_profile_key = si_profile[len(SI_PROFILE_HEADER):] if si_profile.startswith(SI_PROFILE_HEADER) else si_profile + if si_profile_key in self.si_profiles: #We know this SI profile, we call the callback self.si_profiles[si_profile_key](iq_el['id'], iq_el['from'], si_id, si_mime_type, si_el, profile) else: #We don't know this profile, we send an error self.sendBadProfileError(iq_el['id'], iq_el['from'], profile) - def sendRejectedError(self, iq_id, to_jid, reason = 'Offer Declined', profile='@NONE@'): + def sendRejectedError(self, iq_id, to_jid, reason='Offer Declined', profile='@NONE@'): """Helper method to send when the stream is rejected @param iq_id: IQ id @param to_jid: recipient @param reason: human readable reason (string) @param profile: %(doc_profile)s""" - self.sendError(iq_id, to_jid, 403, 'cancel', {'text':reason}, profile=profile) + self.sendError(iq_id, to_jid, 403, 'cancel', {'text': reason}, profile=profile) def sendBadProfileError(self, iq_id, to_jid, profile): """Helper method to send when we don't know the SI profile @@ -113,7 +114,7 @@ @param iq_id: IQ id @param to_jid: recipient @param profile: %(doc_profile)s""" - self.sendError(iq_id, to_jid, 500, 'cancel', {'custom':'failed'}, profile=profile) #as there is no error code for failed transfer, we use 500 (undefined-condition) + self.sendError(iq_id, to_jid, 500, 'cancel', {'custom': 'failed'}, profile=profile) # as there is no error code for failed transfer, we use 500 (undefined-condition) def sendError(self, iq_id, to_jid, err_code, err_type='cancel', data={}, profile='@NONE@'): """Send IQ error as a result @@ -131,21 +132,21 @@ result['id'] = iq_id result['to'] = to_jid error_el = result.addElement('error') - error_el['err_code'] = str(err_code) + error_el['err_code'] = str(err_code) error_el['type'] = err_type - if err_code==400 and err_type=='cancel': - error_el.addElement(('urn:ietf:params:xml:ns:xmpp-stanzas','bad-request')) - error_el.addElement((NS_SI,'no-valid-streams')) - elif err_code==400 and err_type=='modify': - error_el.addElement(('urn:ietf:params:xml:ns:xmpp-stanzas','bad-request')) - error_el.addElement((NS_SI,'bad-profile')) - elif err_code==403 and err_type=='cancel': - error_el.addElement(('urn:ietf:params:xml:ns:xmpp-stanzas','forbidden')) - if data.has_key('text'): - error_el.addElement(('urn:ietf:params:xml:ns:xmpp-stanzas','text'), content=data['text']) - elif err_code==500 and err_type=='cancel': - condition_el = error_el.addElement((NS_SI,'undefined-condition')) - if data.has_key('custom') and data['custom']=='failed': + if err_code == 400 and err_type == 'cancel': + error_el.addElement(('urn:ietf:params:xml:ns:xmpp-stanzas', 'bad-request')) + error_el.addElement((NS_SI, 'no-valid-streams')) + elif err_code == 400 and err_type == 'modify': + error_el.addElement(('urn:ietf:params:xml:ns:xmpp-stanzas', 'bad-request')) + error_el.addElement((NS_SI, 'bad-profile')) + elif err_code == 403 and err_type == 'cancel': + error_el.addElement(('urn:ietf:params:xml:ns:xmpp-stanzas', 'forbidden')) + if 'text' in data: + error_el.addElement(('urn:ietf:params:xml:ns:xmpp-stanzas', 'text'), content=data['text']) + elif err_code == 500 and err_type == 'cancel': + condition_el = error_el.addElement((NS_SI, 'undefined-condition')) + if 'custom' in data and data['custom'] == 'failed': condition_el.addContent('Stream failed') _client.xmlstream.send(result) @@ -158,7 +159,7 @@ @param profile: %(doc_profile)s""" _client = self.host.getClient(profile) assert(_client) - info (_("sending stream initiation accept answer")) + info(_("sending stream initiation accept answer")) result = domish.Element((None, 'iq')) result['type'] = 'result' result['id'] = iq_id @@ -180,16 +181,16 @@ @return: session id, offer""" current_jid, xmlstream = self.host.getJidNStream(profile_key) if not xmlstream: - error (_('Asking for an non-existant or not connected profile')) + error(_('Asking for an non-existant or not connected profile')) return "" - offer = client.IQ(xmlstream,'set') + offer = client.IQ(xmlstream, 'set') sid = str(uuid.uuid4()) - debug (_("Stream Session ID: %s") % offer["id"]) + debug(_("Stream Session ID: %s") % offer["id"]) offer["from"] = current_jid.full() offer["to"] = to_jid.full() - si=offer.addElement('si',NS_SI) + si = offer.addElement('si', NS_SI) si['id'] = sid si["mime-type"] = mime_type si["profile"] = si_profile @@ -209,11 +210,10 @@ self.host = plugin_parent.host def connectionInitialized(self): - self.xmlstream.addObserver(SI_REQUEST, self.plugin_parent.streamInit, profile = self.parent.profile) + self.xmlstream.addObserver(SI_REQUEST, self.plugin_parent.streamInit, profile=self.parent.profile) def getDiscoInfo(self, requestor, target, nodeIdentifier=''): return [disco.DiscoFeature(NS_SI)] + [disco.DiscoFeature("http://jabber.org/protocol/si/profile/%s" % profile_name) for profile_name in self.plugin_parent.si_profiles] def getDiscoItems(self, requestor, target, nodeIdentifier=''): return [] - diff -r 70bae685d05c -r e629371a28d3 src/plugins/plugin_xep_0096.py --- a/src/plugins/plugin_xep_0096.py Mon Jan 21 00:59:50 2013 +0100 +++ b/src/plugins/plugin_xep_0096.py Fri Jan 18 17:55:35 2013 +0100 @@ -23,11 +23,10 @@ from twisted.words.xish import domish from twisted.words.protocols.jabber import jid from twisted.words.protocols.jabber import error as jab_error -import os, os.path +import os from twisted.internet import reactor from sat.core.exceptions import ProfileNotInCacheError - from wokkel import data_form IQ_SET = '/iq[@type="set"]' @@ -35,29 +34,30 @@ PROFILE = "http://jabber.org/protocol/si/profile/" + PROFILE_NAME PLUGIN_INFO = { -"name": "XEP 0096 Plugin", -"import_name": "XEP-0096", -"type": "XEP", -"protocols": ["XEP-0096"], -"dependencies": ["XEP-0020", "XEP-0095", "XEP-0065", "XEP-0047"], -"main": "XEP_0096", -"handler": "no", -"description": _("""Implementation of SI File Transfer""") + "name": "XEP 0096 Plugin", + "import_name": "XEP-0096", + "type": "XEP", + "protocols": ["XEP-0096"], + "dependencies": ["XEP-0020", "XEP-0095", "XEP-0065", "XEP-0047"], + "main": "XEP_0096", + "handler": "no", + "description": _("""Implementation of SI File Transfer""") } + class XEP_0096(object): def __init__(self, host): info(_("Plugin XEP_0096 initialization")) self.host = host self.managed_stream_m = [self.host.plugins["XEP-0065"].NAMESPACE, - self.host.plugins["XEP-0047"].NAMESPACE] #Stream methods managed + self.host.plugins["XEP-0047"].NAMESPACE] # Stream methods managed self.host.plugins["XEP-0095"].registerSIProfile(PROFILE_NAME, self.transferRequest) host.bridge.addMethod("sendFile", ".plugin", in_sign='ssa{ss}s', out_sign='s', method=self.sendFile) def profileConnected(self, profile): client = self.host.getClient(profile) - client._xep_0096_waiting_for_approval = {} #key = id, value = [transfer data, IdelayedCall Reactor timeout, + client._xep_0096_waiting_for_approval = {} # key = id, value = [transfer data, IdelayedCall Reactor timeout, # current stream method, [failed stream methods], profile] def _kill_id(self, approval_id, profile): @@ -78,7 +78,7 @@ @param si_mime_type: Mime type of the file (or default "application/octet-stream" if unknown) @param si_el: domish.Element of the request @param profile: %(doc_profile)s""" - info (_("XEP-0096 file transfer requested")) + info(_("XEP-0096 file transfer requested")) debug(si_el.toXml()) client = self.host.getClient(profile) if not client: @@ -98,7 +98,7 @@ file_size = file_el["size"] file_date = file_el.getAttribute("date", "") file_hash = file_el.getAttribute("hash", "") - info (_("File proposed: name=[%(name)s] size=%(size)s") % {'name':filename, 'size':file_size}) + info(_("File proposed: name=[%(name)s] size=%(size)s") % {'name': filename, 'size': file_size}) for file_child_el in file_el.elements(): if file_child_el.name == "desc": file_desc = unicode(file_child_el) @@ -113,7 +113,7 @@ feature_el = feature_elts[0] form = data_form.Form.fromElement(feature_el.firstChildElement()) try: - stream_method = self.host.plugins["XEP-0020"].negociate(feature_el, 'stream-method',self.managed_stream_m) + stream_method = self.host.plugins["XEP-0020"].negociate(feature_el, 'stream-method', self.managed_stream_m) except KeyError: warning(_("No stream method found")) self.host.plugins["XEP-0095"].sendBadRequestError(iq_id, from_jid, profile) @@ -128,13 +128,12 @@ return #if we are here, the transfer can start, we just need user's agreement - data={ "filename":filename, "id": iq_id, "from":from_jid, "size":file_size, "date":file_date, "hash":file_hash, "desc":file_desc, "can_range": str(can_range) } + data = {"filename": filename, "id": iq_id, "from": from_jid, "size": file_size, "date": file_date, "hash": file_hash, "desc": file_desc, "can_range": str(can_range)} client._xep_0096_waiting_for_approval[si_id] = [data, reactor.callLater(300, self._kill_id, si_id, profile), stream_method, []] self.host.askConfirmation(si_id, "FILE_TRANSFER", data, self.confirmationCB, profile) - - def _getFileObject(self, dest_path, can_range = False): + def _getFileObject(self, dest_path, can_range=False): """Open file, put file pointer to the end if the file if needed @param dest_path: path of the destination file @param can_range: True if the file pointer can be moved @@ -175,7 +174,7 @@ return #we can send the iq result - feature_elt = self.host.plugins["XEP-0020"].chooseOption({'stream-method':stream_method}) + feature_elt = self.host.plugins["XEP-0020"].chooseOption({'stream-method': stream_method}) misc_elts = [] misc_elts.append(domish.Element((PROFILE, "file"))) if can_range: @@ -185,8 +184,8 @@ misc_elts.append(range_elt) self.host.plugins["XEP-0095"].acceptStream(data["id"], data['from'], feature_elt, misc_elts, profile) else: - debug (_("Transfer [%s] refused"), sid) - self.host.plugins["XEP-0095"].sendRejectedError (data["id"], data['from'], profile=profile) + debug(_("Transfer [%s] refused"), sid) + self.host.plugins["XEP-0095"].sendRejectedError(data["id"], data['from'], profile=profile) del(client._xep_0096_waiting_for_approval[sid]) def _transferSucceeded(self, sid, file_obj, stream_method, profile): @@ -207,9 +206,10 @@ if not client: raise ProfileNotInCacheError data, timeout, stream_method, failed_methods = client._xep_0096_waiting_for_approval[sid] - warning(_('Transfer %(id)s failed with stream method %(s_method)s: %(reason)s') % { 'id': sid, - 's_method': stream_method, - 'reason': reason}) + warning(_('Transfer %(id)s failed with stream method %(s_method)s: %(reason)s') % { + 'id': sid, + 's_method': stream_method, + 'reason': reason}) filepath = file_obj.name file_obj.close() os.remove(filepath) @@ -255,15 +255,15 @@ range_length = range_elt.getAttribute("length") if stream_method == self.host.plugins["XEP-0065"].NAMESPACE: - file_obj = open(filepath, 'r') - if range_offset: - file_obj.seek(range_offset) - self.host.plugins["XEP-0065"].startStream(file_obj, jid.JID(IQ['from']), sid, range_length, self.sendSuccessCb, self.sendFailureCb, size, profile) + file_obj = open(filepath, 'r') + if range_offset: + file_obj.seek(range_offset) + self.host.plugins["XEP-0065"].startStream(file_obj, jid.JID(IQ['from']), sid, range_length, self.sendSuccessCb, self.sendFailureCb, size, profile) elif stream_method == self.host.plugins["XEP-0047"].NAMESPACE: - file_obj = open(filepath, 'r') - if range_offset: - file_obj.seek(range_offset) - self.host.plugins["XEP-0047"].startStream(file_obj, jid.JID(IQ['from']), sid, range_length, self.sendSuccessCb, self.sendFailureCb, size, profile) + file_obj = open(filepath, 'r') + if range_offset: + file_obj.seek(range_offset) + self.host.plugins["XEP-0047"].startStream(file_obj, jid.JID(IQ['from']), sid, range_length, self.sendSuccessCb, self.sendFailureCb, size, profile) else: warning(_("Invalid stream method received")) @@ -286,13 +286,13 @@ statinfo = os.stat(filepath) file_elt = domish.Element((PROFILE, 'file')) - file_elt['name']=os.path.basename(filepath) - size = file_elt['size']=str(statinfo.st_size) + file_elt['name'] = os.path.basename(filepath) + size = file_elt['size'] = str(statinfo.st_size) file_transfer_elts.append(file_elt) - file_transfer_elts.append(domish.Element((None,'range'))) + file_transfer_elts.append(domish.Element((None, 'range'))) - sid, offer = self.host.plugins["XEP-0095"].proposeStream(jid.JID(to_jid), PROFILE, feature_elt, file_transfer_elts, profile_key = profile) + sid, offer = self.host.plugins["XEP-0095"].proposeStream(jid.JID(to_jid), PROFILE, feature_elt, file_transfer_elts, profile_key=profile) offer.addCallback(self.fileCb, filepath, sid, size, profile) return sid @@ -302,4 +302,4 @@ def sendFailureCb(self, sid, file_obj, stream_method, reason, profile): file_obj.close() - warning(_('Transfer %(id)s failed with stream method %(s_method)s: %(reason)s [%(profile)s') % { 'id': sid, "s_method": stream_method, 'reason': reason, 'profile': profile }) + warning(_('Transfer %(id)s failed with stream method %(s_method)s: %(reason)s [%(profile)s') % {'id': sid, "s_method": stream_method, 'reason': reason, 'profile': profile}) diff -r 70bae685d05c -r e629371a28d3 src/plugins/plugin_xep_0100.py --- a/src/plugins/plugin_xep_0100.py Mon Jan 21 00:59:50 2013 +0100 +++ b/src/plugins/plugin_xep_0100.py Fri Jan 18 17:55:35 2013 +0100 @@ -25,86 +25,85 @@ import twisted.internet.error PLUGIN_INFO = { -"name": "Gateways Plugin", -"import_name": "XEP-0100", -"type": "XEP", -"protocols": ["XEP-0100"], -"dependencies": ["XEP-0077"], -"main": "XEP_0100", -"description": _("""Implementation of Gateways protocol""") + "name": "Gateways Plugin", + "import_name": "XEP-0100", + "type": "XEP", + "protocols": ["XEP-0100"], + "dependencies": ["XEP-0077"], + "main": "XEP_0100", + "description": _("""Implementation of Gateways protocol""") } + class XEP_0100(object): def __init__(self, host): info(_("Gateways plugin initialization")) self.host = host - self.__gateways = {} #dict used to construct the answer to findGateways. Key = target jid + self.__gateways = {} # dict used to construct the answer to findGateways. Key = target jid host.bridge.addMethod("findGateways", ".plugin", in_sign='ss', out_sign='s', method=self.findGateways) host.bridge.addMethod("gatewayRegister", ".plugin", in_sign='ssa(ss)s', out_sign='s', method=self.gatewayRegister) def __inc_handled_items(self, request_id, profile): - self.__gateways[request_id]['__handled_items']+=1 + self.__gateways[request_id]['__handled_items'] += 1 if self.__gateways[request_id]['__total_items'] == self.__gateways[request_id]['__handled_items']: - debug (_("All items checked for id [%s]") % str(request_id)) + debug(_("All items checked for id [%s]") % str(request_id)) del self.__gateways[request_id]['__total_items'] del self.__gateways[request_id]['__handled_items'] - self.host.actionResultExt(request_id,"DICT_DICT",self.__gateways[request_id], profile) + self.host.actionResultExt(request_id, "DICT_DICT", self.__gateways[request_id], profile) def discoInfo(self, disco, entity, request_id, profile): """Find disco infos about entity, to check if it is a gateway""" for identity in disco.identities: if identity[0] == 'gateway': - print (_("Found gateway (%(jid)s): %(identity)s") % {'jid':entity.full(), 'identity':disco.identities[identity]}) + print (_("Found gateway (%(jid)s): %(identity)s") % {'jid': entity.full(), 'identity': disco.identities[identity]}) self.__gateways[request_id][entity.full()] = { - 'name':disco.identities[identity], - 'type':identity[1] + 'name': disco.identities[identity], + 'type': identity[1] } self.__inc_handled_items(request_id, profile) def discoInfoErr(self, failure, entity, request_id, profile): """Something is going wrong with disco""" - failure.trap(jab_error.StanzaError,twisted.internet.error.ConnectionLost) - error(_("Error when discovering [%(jid)s]: %(error)s") % {'jid':entity.full(), 'error':failure.getErrorMessage()}) + failure.trap(jab_error.StanzaError, twisted.internet.error.ConnectionLost) + error(_("Error when discovering [%(jid)s]: %(error)s") % {'jid': entity.full(), 'error': failure.getErrorMessage()}) self.__inc_handled_items(request_id, profile) - def discoItems(self, disco, request_id, target, client): """Look for items with disco protocol, and ask infos for each one""" #FIXME: target is used as we can't find the original iq node (parent is None) # an other way would avoid this useless parameter (is there a way with wokkel ?) if len(disco._items) == 0: - debug (_("No gateway found")) - self.host.actionResultExt(request_id,"DICT_DICT",{}) + debug(_("No gateway found")) + self.host.actionResultExt(request_id, "DICT_DICT", {}) return - self.__gateways[request_id] = {'__total_items':len(disco._items), '__handled_items':0, '__private__':{'target':target.full()}} + self.__gateways[request_id] = {'__total_items': len(disco._items), '__handled_items': 0, '__private__': {'target': target.full()}} for item in disco._items: #TODO: need to set a timeout for theses requests - debug (_("item found: %s"), item.name) + debug(_("item found: %s"), item.name) client.disco.requestInfo(item.entity).addCallback(self.discoInfo, entity=item.entity, request_id=request_id, profile=client.profile).addErrback(self.discoInfoErr, entity=item.entity, request_id=request_id, profile=client.profile) def discoItemsErr(self, failure, request_id, target, client): """Something is going wrong with disco""" - error(_("Error when discovering [%(target)s]: %(condition)s") % {'target':target.full(), 'condition':unicode(failure.value)}) - message_data={"reason": "connection error", "message":_(u"Error while trying to discover %(target)s gateways: %(error_mess)s") % {'target':target.full(), 'error_mess':unicode(failure.value)}} + error(_("Error when discovering [%(target)s]: %(condition)s") % {'target': target.full(), 'condition': unicode(failure.value)}) + message_data = {"reason": "connection error", "message": _(u"Error while trying to discover %(target)s gateways: %(error_mess)s") % {'target': target.full(), 'error_mess': unicode(failure.value)}} self.host.bridge.actionResult("ERROR", request_id, message_data) - def registrationSuccessful(self, target, profile): """Called when in_band registration is ok, we must now follow the rest of procedure""" - debug (_("Registration successful, doing the rest")) + debug(_("Registration successful, doing the rest")) self.host.addContact(target, profile) self.host.setPresence(target, profile) def gatewayRegister(self, action, target, fields, profile_key='@DEFAULT@'): """Register gateway using in-band registration, then log-in to gateway""" profile = self.host.memory.getProfileName(profile_key) - assert(profile) #FIXME: return an error here + assert(profile) # FIXME: return an error here if action == 'SUBMIT': self.host.plugins["XEP-0077"].addTrigger(target, self.registrationSuccessful, profile) return self.host.plugins["XEP-0077"].in_band_submit(action, target, fields, profile) @@ -117,7 +116,7 @@ client = self.host.getClient(profile_key) assert(client) to_jid = jid.JID(target) - debug (_("find gateways (target = %(target)s, profile = %(profile)s)") % {'target':to_jid.full(), 'profile':profile}) + debug(_("find gateways (target = %(target)s, profile = %(profile)s)") % {'target': to_jid.full(), 'profile': profile}) request_id = self.host.get_next_id() - client.disco.requestItems(to_jid).addCallback(self.discoItems, request_id=request_id, target = to_jid, client = client).addErrback(self.discoItemsErr, request_id=request_id, target = to_jid, client = client) + client.disco.requestItems(to_jid).addCallback(self.discoItems, request_id=request_id, target=to_jid, client=client).addErrback(self.discoItemsErr, request_id=request_id, target=to_jid, client=client) return request_id diff -r 70bae685d05c -r e629371a28d3 src/plugins/plugin_xep_0115.py --- a/src/plugins/plugin_xep_0115.py Mon Jan 21 00:59:50 2013 +0100 +++ b/src/plugins/plugin_xep_0115.py Fri Jan 18 17:55:35 2013 +0100 @@ -42,22 +42,24 @@ PRESENCE = '/presence' NS_ENTITY_CAPABILITY = 'http://jabber.org/protocol/caps' -CAPABILITY_UPDATE = PRESENCE + '/c[@xmlns="' + NS_ENTITY_CAPABILITY + '"]' +CAPABILITY_UPDATE = PRESENCE + '/c[@xmlns="' + NS_ENTITY_CAPABILITY + '"]' PLUGIN_INFO = { -"name": "XEP 0115 Plugin", -"import_name": "XEP-0115", -"type": "XEP", -"protocols": ["XEP-0115"], -"dependencies": [], -"main": "XEP_0115", -"handler": "yes", -"description": _("""Implementation of entity capabilities""") + "name": "XEP 0115 Plugin", + "import_name": "XEP-0115", + "type": "XEP", + "protocols": ["XEP-0115"], + "dependencies": [], + "main": "XEP_0115", + "handler": "yes", + "description": _("""Implementation of entity capabilities""") } + class HashGenerationError(Exception): pass + class ByteIdentity(object): """This class manage identity as bytes (needed for i;octet sort), it is used for the hash generation""" @@ -74,16 +76,16 @@ class XEP_0115(object): - cap_hash = None #capabilities hash is class variable as it is common to all profiles + cap_hash = None # capabilities hash is class variable as it is common to all profiles #TODO: this code is really dirty, need to clean it and try to move it to Wokkel def __init__(self, host): info(_("Plugin XEP_0115 initialization")) self.host = host host.trigger.add("Disco Handled", self.checkHash) - self.hash_cache = PersistentBinaryDict(NS_ENTITY_CAPABILITY) #key = hash or jid, value = features + self.hash_cache = PersistentBinaryDict(NS_ENTITY_CAPABILITY) # key = hash or jid, value = features self.hash_cache.load() - self.jid_hash = {} #jid to hash mapping, map to a discoInfo features if the hash method is unknown + self.jid_hash = {} # jid to hash mapping, map to a discoInfo features if the hash method is unknown def checkHash(self, profile): if not XEP_0115.cap_hash: @@ -97,16 +99,17 @@ def presenceHack(self, profile): """modify SatPresenceProtocol to add capabilities data""" - client=self.host.getClient(profile) + client = self.host.getClient(profile) presenceInst = client.presence - c_elt = domish.Element((NS_ENTITY_CAPABILITY,'c')) - c_elt['hash']='sha-1' - c_elt['node']='http://wiki.goffi.org/wiki/Salut_%C3%A0_Toi' - c_elt['ver']=XEP_0115.cap_hash + c_elt = domish.Element((NS_ENTITY_CAPABILITY, 'c')) + c_elt['hash'] = 'sha-1' + c_elt['node'] = 'http://wiki.goffi.org/wiki/Salut_%C3%A0_Toi' + c_elt['ver'] = XEP_0115.cap_hash presenceInst._c_elt = c_elt if "_legacy_send" in dir(presenceInst): debug('capabilities already added to presence instance') return + def hacked_send(self, obj): obj.addChild(self._c_elt) self._legacy_send(obj) @@ -114,31 +117,30 @@ presenceInst._legacy_send = presenceInst.send presenceInst.send = new_send - def generateHash(self, profile_key="@DEFAULT@"): """This method generate a sha1 hash as explained in xep-0115 #5.1 it then store it in XEP_0115.cap_hash""" profile = self.host.memory.getProfileName(profile_key) if not profile: - error ('Requesting hash for an inexistant profile') + error('Requesting hash for an inexistant profile') raise HashGenerationError client = self.host.getClient(profile_key) if not client: - error ('Requesting hash for an inexistant client') + error('Requesting hash for an inexistant client') raise HashGenerationError def generateHash_2(services, profile): - _s=[] - byte_identities = [ByteIdentity(identity) for identity in filter(lambda x:isinstance(x,disco.DiscoIdentity),services)] #FIXME: lang must be managed here - byte_identities.sort(key=lambda i:i.lang) - byte_identities.sort(key=lambda i:i.idType) - byte_identities.sort(key=lambda i:i.category) + _s = [] + byte_identities = [ByteIdentity(identity) for identity in filter(lambda x: isinstance(x, disco.DiscoIdentity), services)] # FIXME: lang must be managed here + byte_identities.sort(key=lambda i: i.lang) + byte_identities.sort(key=lambda i: i.idType) + byte_identities.sort(key=lambda i: i.category) for identity in byte_identities: _s.append(str(identity)) _s.append('<') - byte_features = [feature.encode('utf-8') for feature in filter(lambda x:isinstance(x,disco.DiscoFeature),services)] - byte_features.sort() #XXX: the default sort has the same behaviour as the requested RFC 4790 i;octet sort + byte_features = [feature.encode('utf-8') for feature in filter(lambda x: isinstance(x, disco.DiscoFeature), services)] + byte_features.sort() # XXX: the default sort has the same behaviour as the requested RFC 4790 i;octet sort for feature in byte_features: _s.append(feature) _s.append('<') @@ -149,6 +151,7 @@ services = client.discoHandler.info(client.jid, client.jid, '').addCallback(generateHash_2, profile) + class XEP_0115_handler(XMPPHandler): implements(iwokkel.IDisco) @@ -176,7 +179,6 @@ #No key, that means unknown hash method self.plugin_parent.jid_hash[from_jid] = discoResult.features - def update(self, presence): """ Manage the capabilities of the entity @@ -184,11 +186,11 @@ and get the capibilities if necessary """ from_jid = jid.JID(presence['from']) - c_elem = filter (lambda x:x.name == "c", presence.elements())[0] #We only want the "c" element + c_elem = filter(lambda x: x.name == "c", presence.elements())[0] # We only want the "c" element try: - ver=c_elem['ver'] - hash=c_elem['hash'] - node=c_elem['node'] + ver = c_elem['ver'] + hash = c_elem['hash'] + node = c_elem['node'] except KeyError: warning('Received invalid capabilities tag') return @@ -197,9 +199,8 @@ #we know that hash, we just link it with the jid self.plugin_parent.jid_hash[from_jid] = ver else: - if hash!='sha-1': + if hash != 'sha-1': #unknown hash method warning('Unknown hash for entity capabilities: [%s]' % hash) - self.parent.disco.requestInfo(from_jid).addCallback(self._updateCache, from_jid, ver if hash=='sha-1' else None ) + self.parent.disco.requestInfo(from_jid).addCallback(self._updateCache, from_jid, ver if hash == 'sha-1' else None) #TODO: me must manage the full algorithm described at XEP-0115 #5.4 part 3 - diff -r 70bae685d05c -r e629371a28d3 src/plugins/plugin_xep_0163.py --- a/src/plugins/plugin_xep_0163.py Mon Jan 21 00:59:50 2013 +0100 +++ b/src/plugins/plugin_xep_0163.py Fri Jan 18 17:55:35 2013 +0100 @@ -26,32 +26,33 @@ import twisted.internet.error from twisted.words.xish import domish -from wokkel import disco,pubsub +from wokkel import disco, pubsub from wokkel.formats import Mood NS_USER_MOOD = 'http://jabber.org/protocol/mood' PLUGIN_INFO = { -"name": "Personal Eventing Protocol Plugin", -"import_name": "XEP-0163", -"type": "XEP", -"protocols": ["XEP-0163", "XEP-0107"], -"dependencies": ["XEP-0060"], -"main": "XEP_0163", -"handler": "no", -"description": _("""Implementation of Personal Eventing Protocol""") + "name": "Personal Eventing Protocol Plugin", + "import_name": "XEP-0163", + "type": "XEP", + "protocols": ["XEP-0163", "XEP-0107"], + "dependencies": ["XEP-0060"], + "main": "XEP_0163", + "handler": "no", + "description": _("""Implementation of Personal Eventing Protocol""") } + class XEP_0163(object): def __init__(self, host): info(_("PEP plugin initialization")) self.host = host - self.pep_events=set() - self.pep_out_cb={} + self.pep_events = set() + self.pep_out_cb = {} host.trigger.add("PubSub Disco Info", self.disoInfoTrigger) - host.bridge.addSignal("personalEvent", ".plugin", signature='ssa{ss}s') #args: from (jid), type(MOOD, TUNE, etc), data, profile - host.bridge.addMethod("sendPersonalEvent", ".plugin", in_sign='sa{ss}s', out_sign='i', method=self.sendPersonalEvent) #args: type(MOOD, TUNE, etc), data, profile_key; return 0 or error_code + host.bridge.addSignal("personalEvent", ".plugin", signature='ssa{ss}s') # args: from (jid), type(MOOD, TUNE, etc), data, profile + host.bridge.addMethod("sendPersonalEvent", ".plugin", in_sign='sa{ss}s', out_sign='i', method=self.sendPersonalEvent) # args: type(MOOD, TUNE, etc), data, profile_key; return 0 or error_code self.addPEPEvent("MOOD", NS_USER_MOOD, self.userMoodCB, self.sendMood) def disoInfoTrigger(self, disco_info, profile): @@ -62,7 +63,7 @@ disco_info.extend(map(disco.DiscoFeature, self.pep_events)) return True - def addPEPEvent(self, event_type, name, in_callback, out_callback = None, notify = True): + def addPEPEvent(self, event_type, name, in_callback, out_callback=None, notify=True): """Add a Personal Eventing Protocol event manager @param event_type: type of the event (always uppercase), can be MOOD, TUNE, etc @param name: namespace of the node (e.g. http://jabber.org/protocol/mood for User Mood) @@ -73,7 +74,7 @@ self.pep_out_cb[event_type] = out_callback self.pep_events.add(name) if notify: - self.pep_events.add(name+"+notify") + self.pep_events.add(name + "+notify") self.host.plugins["XEP-0060"].addManagedNode(name, in_callback) def sendPEPEvent(self, namespace, data, profile): @@ -83,7 +84,7 @@ @param profile: profile which send the data""" item = pubsub.Item(payload=data) - self.host.plugins["XEP-0060"].publish(None, namespace, [item], profile_key = profile) + self.host.plugins["XEP-0060"].publish(None, namespace, [item], profile_key=profile) def sendPersonalEvent(self, event_type, data, profile_key='@DEFAULT@'): """Send personal event after checking the data is alright @@ -96,7 +97,7 @@ error(_('Trying to send personal event with an unknown profile key [%s]') % profile_key) return 1 if not event_type in self.pep_out_cb.keys(): - error (_('Trying to send personal event for an unknown type')) + error(_('Trying to send personal event for an unknown type')) return 2 return self.pep_out_cb[event_type](data, profile) @@ -105,7 +106,7 @@ debug(_("No item found")) return try: - mood_elem = filter(lambda x:x.name == "mood", itemsEvent.items[0].children)[0] + mood_elem = filter(lambda x: x.name == "mood", itemsEvent.items[0].children)[0] except KeyError: error(_("Can't find mood element in mood event")) return @@ -113,7 +114,7 @@ if not _mood: debug(_("No mood found")) return - self.host.bridge.personalEvent(itemsEvent.sender.full(), "MOOD", {"mood":_mood.value or "", "text":_mood.text or ""}, profile) + self.host.bridge.personalEvent(itemsEvent.sender.full(), "MOOD", {"mood": _mood.value or "", "text": _mood.text or ""}, profile) def sendMood(self, data, profile): """Send XEP-0107's User Mood @@ -121,7 +122,7 @@ @param profile: profile which send the mood""" try: value = data['mood'].lower() - text = data['text'] if data.has_key('text') else '' + text = data['text'] if 'text' in data else '' except KeyError: error(_("Mood data must contain at least 'mood' key")) return 3 @@ -129,6 +130,7 @@ self.sendPEPEvent(NS_USER_MOOD, _mood, profile) return 0 + class UserMood(Mood, domish.Element): """Improved wokkel Mood which is also a domish.Element""" @@ -138,4 +140,3 @@ self.addElement(value) if text: self.addElement('text', content=text) - diff -r 70bae685d05c -r e629371a28d3 src/plugins/plugin_xep_0249.py --- a/src/plugins/plugin_xep_0249.py Mon Jan 21 00:59:50 2013 +0100 +++ b/src/plugins/plugin_xep_0249.py Fri Jan 18 17:55:35 2013 +0100 @@ -34,21 +34,22 @@ except ImportError: from wokkel.subprotocols import XMPPHandler -MESSAGE= '/message' +MESSAGE = '/message' NS_DIRECT_MUC_INVITATION = 'jabber:x:conference' DIRECT_MUC_INVITATION_REQUEST = MESSAGE + '/x[@xmlns="' + NS_DIRECT_MUC_INVITATION + '"]' PLUGIN_INFO = { -"name": "XEP 0249 Plugin", -"import_name": "XEP-0249", -"type": "XEP", -"protocols": ["XEP-0249"], -"dependencies": ["XEP-0045"], -"main": "XEP_0249", -"handler": "yes", -"description": _("""Implementation of Direct MUC Invitations""") + "name": "XEP 0249 Plugin", + "import_name": "XEP-0249", + "type": "XEP", + "protocols": ["XEP-0249"], + "dependencies": ["XEP-0045"], + "main": "XEP_0249", + "handler": "yes", + "description": _("""Implementation of Direct MUC Invitations""") } + class XEP_0249(object): def __init__(self, host): @@ -71,15 +72,15 @@ if not profile: error(_("Profile doesn't exists !")) return - message = domish.Element((None,'message')) + message = domish.Element((None, 'message')) message["to"] = target.full() - x_elt = message.addElement('x',NS_DIRECT_MUC_INVITATION) + x_elt = message.addElement('x', NS_DIRECT_MUC_INVITATION) x_elt['jid'] = room.userhost() for opt in options: x_elt[opt] = options[opt] self.host.profiles[profile].xmlstream.send(message) - def _invite(self, target, service, roomId, options = {}, profile_key='@DEFAULT@'): + def _invite(self, target, service, roomId, options={}, profile_key='@DEFAULT@'): """ Invite an user to a room @param target: jid of the user to invite @@ -90,14 +91,13 @@ #TODO: check parameters validity self.invite(jid.JID(target), jid.JID("%s@%s" % (roomId, service)), options, profile_key) - def onInvitation(self, message, profile): """ called when an invitation is received @param message: message element @profile: %(doc_profile)s """ - info(_('Invitation received for room %(room)s [%(profile)s]') % {'room':'','profile':profile}) + info(_('Invitation received for room %(room)s [%(profile)s]') % {'room': '', 'profile': profile}) try: room = jid.JID(message.firstChildElement()['jid']) except: @@ -116,7 +116,7 @@ self.host = plugin_parent.host def connectionInitialized(self): - self.xmlstream.addObserver(DIRECT_MUC_INVITATION_REQUEST, self.plugin_parent.onInvitation, profile = self.parent.profile) + self.xmlstream.addObserver(DIRECT_MUC_INVITATION_REQUEST, self.plugin_parent.onInvitation, profile=self.parent.profile) def getDiscoInfo(self, requestor, target, nodeIdentifier=''): return [disco.DiscoFeature(NS_DIRECT_MUC_INVITATION)] diff -r 70bae685d05c -r e629371a28d3 src/plugins/plugin_xep_0277.py --- a/src/plugins/plugin_xep_0277.py Mon Jan 21 00:59:50 2013 +0100 +++ b/src/plugins/plugin_xep_0277.py Fri Jan 18 17:55:35 2013 +0100 @@ -27,7 +27,7 @@ from twisted.words.xish import domish from sat.tools.xml_tools import ElementParser -from wokkel import disco,pubsub +from wokkel import disco, pubsub from feed.atom import Entry, Author import uuid from time import time @@ -40,19 +40,21 @@ OPT_SEND_ITEM_SUBSCRIBE = 'pubsub#send_item_subscribe' PLUGIN_INFO = { -"name": "Microblogging over XMPP Plugin", -"import_name": "XEP-0277", -"type": "XEP", -"protocols": [], -"dependencies": ["XEP-0163","XEP-0060"], -"main": "XEP_0277", -"handler": "no", -"description": _("""Implementation of microblogging Protocol""") + "name": "Microblogging over XMPP Plugin", + "import_name": "XEP-0277", + "type": "XEP", + "protocols": [], + "dependencies": ["XEP-0163", "XEP-0060"], + "main": "XEP_0277", + "handler": "no", + "description": _("""Implementation of microblogging Protocol""") } + class NodeAccessChangeException(Exception): pass + class XEP_0277(object): def __init__(self, host): @@ -62,30 +64,28 @@ host.bridge.addMethod("getLastMicroblogs", ".plugin", in_sign='sis', out_sign='aa{ss}', method=self.getLastMicroblogs, - async = True, - doc = { 'summary':'retrieve items', - 'param_0':'jid: publisher of wanted microblog', - 'param_1':'max_items: see XEP-0060 #6.5.7', - 'param_2':'%(doc_profile)s', - 'return':'list of microblog data (dict)' - }) + async=True, + doc={'summary': 'retrieve items', + 'param_0': 'jid: publisher of wanted microblog', + 'param_1': 'max_items: see XEP-0060 #6.5.7', + 'param_2': '%(doc_profile)s', + 'return': 'list of microblog data (dict)'}) host.bridge.addMethod("setMicroblogAccess", ".plugin", in_sign='ss', out_sign='', - method=self.setMicroblogAccess, - async = True, - doc = { - }) + method=self.setMicroblogAccess, + async=True, + doc={}) def item2mbdata(self, item): """Convert an XML Item to microblog data used in bridge API @param item: domish.Element of microblog item @return: microblog data (dictionary)""" try: - entry_elt = filter (lambda x:x.name == "entry", item.children)[0] + entry_elt = filter(lambda x: x.name == "entry", item.children)[0] except KeyError: warning(_('No entry element in microblog item')) return _entry = Entry().import_xml(entry_elt.toXml().encode('utf-8')) - microblog_data={} + microblog_data = {} try: microblog_data['content'] = _entry.title.text if len(_entry.authors): @@ -100,7 +100,7 @@ if not 'author' in microblog_data: from xe import NestElement try: - author=NestElement('author') + author = NestElement('author') author.import_xml(str(_entry)) microblog_data['author'] = author.nick.text except: @@ -123,8 +123,8 @@ #FIXME: need to escape html _entry.title = unicode(content).encode('utf-8') _entry.author = Author() - _entry.author.name = data.get('author',self.host.getJidNStream(profile)[0].userhost()).encode('utf-8') - _entry.updated = float(data.get('timestamp',time())) + _entry.author.name = data.get('author', self.host.getJidNStream(profile)[0].userhost()).encode('utf-8') + _entry.updated = float(data.get('timestamp', time())) _entry.id = str(_uuid) _entry_elt = ElementParser()(str(_entry).decode('utf-8')) item = pubsub.Item(payload=_entry_elt) @@ -135,7 +135,7 @@ """Send XEP-0277's microblog data @param data: must include content @param profile: profile which send the mood""" - if not data.has_key('content'): + if 'content' not in data: error(_("Microblog data must contain at least 'content' key")) return 3 content = data['content'] @@ -143,7 +143,7 @@ error(_("Microblog data's content value must not be empty")) return 3 item = self.data2entry(data, profile) - self.host.plugins["XEP-0060"].publish(None, NS_MICROBLOG, [item], profile_key = profile) + self.host.plugins["XEP-0060"].publish(None, NS_MICROBLOG, [item], profile_key=profile) return 0 def getLastMicroblogs(self, pub_jid, max_items=10, profile_key='@DEFAULT@'): @@ -168,7 +168,7 @@ if not _jid: error(_("Can't find profile's jid")) return - _options = {OPT_ACCESS_MODEL:access, OPT_PERSIST_ITEMS:1, OPT_MAX_ITEMS:-1, OPT_DELIVER_PAYLOADS:1, OPT_SEND_ITEM_SUBSCRIBE: 1} + _options = {OPT_ACCESS_MODEL: access, OPT_PERSIST_ITEMS: 1, OPT_MAX_ITEMS: -1, OPT_DELIVER_PAYLOADS: 1, OPT_SEND_ITEM_SUBSCRIBE: 1} def cb(result): #Node is created with right permission @@ -182,7 +182,7 @@ def err_cb(s_error): #If the node already exists, the condition is "conflict", #else we have an unmanaged error - if s_error.value.condition=='conflict': + if s_error.value.condition == 'conflict': #d = self.host.plugins["XEP-0060"].deleteNode(_jid.userhostJID(), NS_MICROBLOG, profile_key=profile_key) #d.addCallback(lambda x: create_node().addCallback(cb).addErrback(fatal_err)) change_node_options().addCallback(cb).addErrback(fatal_err) @@ -196,6 +196,3 @@ return self.host.plugins["XEP-0060"].setOptions(_jid.userhostJID(), NS_MICROBLOG, _jid.userhostJID(), _options, profile_key=profile_key) create_node().addCallback(cb).addErrback(err_cb) - - -