Mercurial > libervia-backend
changeset 106:138d82f64b6f
plugin CS: friends parsing
author | Goffi <goffi@goffi.org> |
---|---|
date | Sat, 26 Jun 2010 15:33:16 +0800 |
parents | d2630fba8dfd |
children | 5ae370c71803 |
files | frontends/wix/xmlui.py plugins/plugin_misc_cs.py sat.tac tools/memory.py tools/xml_tools.py |
diffstat | 5 files changed, 135 insertions(+), 40 deletions(-) [+] |
line wrap: on
line diff
--- a/frontends/wix/xmlui.py Wed Jun 23 17:26:21 2010 +0800 +++ b/frontends/wix/xmlui.py Sat Jun 26 15:33:16 2010 +0800 @@ -62,6 +62,7 @@ error(message) raise Exception(message) _proportion = 0 + id = elem.getAttribute("id") name = elem.getAttribute("name") type = elem.getAttribute("type") value = elem.getAttribute("value") if elem.hasAttribute('value') else u'' @@ -88,7 +89,10 @@ self.ctl_list.append({'name':name, 'type':type, 'control':ctrl}) _proportion = 1 elif type=="button": - pass + callback_id = elem.getAttribute("callback_id") + ctrl = wx.Button(parent, -1, value) + ctrl.param_id = callback_id + parent.Bind(wx.EVT_BUTTON, self.onButtonClicked, ctrl) else: error(_("FIXME FIXME FIXME: type [%s] is not implemented") % type) #FIXME ! raise NotImplementedError @@ -174,6 +178,16 @@ self.sizer.Add(panel, 1, flag=wx.EXPAND) cat_dom.unlink() + ###events + + def onButtonClicked(self, event): + """Called when a button is pushed""" + callback_id = event.GetEventObject().param_id + data = {"callback_id":callback_id} + id = self.host.bridge.launchAction("button", data) + self.host.current_action_ids.add(id) + event.Skip() + def onFormSubmitted(self, event): """Called when submit button is clicked""" debug(_("Submitting form"))
--- a/plugins/plugin_misc_cs.py Wed Jun 23 17:26:21 2010 +0800 +++ b/plugins/plugin_misc_cs.py Sat Jun 26 15:33:16 2010 +0800 @@ -33,11 +33,11 @@ from zope.interface import implements from wokkel import disco, iwokkel, data_form -from tools.xml_tools import dataForm2xml +from tools.xml_tools import XMLUI import urllib from BeautifulSoup import BeautifulSoup - +import re PLUGIN_INFO = { @@ -73,14 +73,13 @@ host.memory.importParams(CS_Plugin.params) #menu host.importMenu(_("Plugin"), "CouchSurfing", self.menuSelected, help_string = _("Launch CoushSurfing mangement interface")) - self.data={} #TODO: delete cookies/data after a while + self.data=self.host.memory.getPrivate('plugin_cs_data') or {} #TODO: delete cookies/data after a while def erroCB(self, e, id): """Called when something is going wrong when contacting CS website""" 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): """Called when the couchsurfing menu item is selected""" login = self.host.memory.getParamA("Login", "CouchSurfing", profile_key=profile) @@ -92,36 +91,113 @@ post_data = urllib.urlencode({'auth_login[un]':login,'auth_login[pw]':password,'auth_login[action]':'Login...'}) - self.data[profile] = {'cookies':{}} + if not self.data.has_key(profile): + self.data[profile] = {'cookies':{}} + else: + self.data[profile]['cookies'] = {} - def connectionCB(html): - print 'Response received' - soup = self.data[profile]['soup'] = BeautifulSoup(html) - user_nick = soup.find('a','item_link',href='/home.html').contents[0] - user_name = soup.html.head.title.string.split(' - ')[1] - unread_messages = int(soup.find('div','item_bubble').a.string) - form_xml = """ - <form> - <elem type='text' value='Welcome %(name)s, you have %(nb_message)i unread messages'/> - </form> - """ % {'name':user_name, 'nb_message':unread_messages} - self.host.bridge.actionResult("XMLUI", id, {"type":"window", "xml":form_xml}) - #d = getPage('http://www.couchsurfing.org/messages.html?message_status=inbox', agent=AGENT, cookies=self.session_cookies[profile]) - + #tmp f = open('/home/goffi/tmp/CS_principale.html','r') html = f.read() - connectionCB(html) + self.__connectionCB(html, id, profile) """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(connectionCB) + d.addCallback(self.__connectionCB, id, profile) d.addErrback(self.erroCB, id)""" - #self.host.bridge.actionResult("SUPPRESS", id, {}) + #self.host.bridge.actionResult("SUPPRESS", id, {}) + + +#pages parsing callbacks + def savePage(self, name, html): + f = open ('/home/goffi/tmp/CS_'+name+'.html','w') + f.write(html) + f.close() + print "page [%s] sauvee" % name + #pdb.set_trace() + + def __connectionCB(self, html, id, profile): + 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_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)) + 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)) + 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'): + self.data[profile]['friends'] = {} + """f = open('/home/goffi/tmp/CS_friends.html','r') + html = f.read() + self.__friendsPageCB(html, id, profile)""" + 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])}) + + def __buildUI(self, data): + """Build the XML UI of the plugin + @param data: data store for the profile""" + user_nick = data['user_nick'] + user_name = data['user_name'] + unread_mess = data['unread_messages'] + unread_CR_mess = data['unread_CR_messages'] + friends_list = data['friends'].keys() + friends_list.sort() + interface = XMLUI('window','tabs') + 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") % {'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.addList(friends_list, 'friends') + interface.addCategory(_("Events"), "vertical") + interface.addCategory(_("Couch search"), "vertical") + return interface.toXml() + + def __meetingPageCB(self, html): + """Called when the meeting page has been received""" + + 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"')) + 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 + friend_name = unicode(_nobr.string) + 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) + 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 ? + 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.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])}) + #and save the data + self.host.memory.setPrivate('plugin_cs_data', self.data) + +
--- a/sat.tac Wed Jun 23 17:26:21 2010 +0800 +++ b/sat.tac Sat Jun 26 15:33:16 2010 +0800 @@ -25,6 +25,8 @@ 'local_dir' : '~/.sat' } +import gettext +gettext.install('sat', "i18n", unicode=True) from twisted.application import internet, service from twisted.internet import glib2reactor, protocol, task @@ -50,9 +52,6 @@ from tools.xml_tools import tupleList2dataForm from glob import glob -import gettext -gettext.install('sat', "i18n", unicode=True) - try: from twisted.words.protocols.xmlstream import XMPPHandler except ImportError: @@ -568,7 +567,7 @@ """ if type=="button": try: - cb_name = self.memory.getParamA(data["name"], data["category"], "callback") + cb_name = data['callback_id'] except KeyError: error (_("Incomplete data")) return ""
--- a/tools/memory.py Wed Jun 23 17:26:21 2010 +0800 +++ b/tools/memory.py Sat Jun 26 15:33:16 2010 +0800 @@ -23,7 +23,7 @@ import os.path import time -import pickle +import cPickle as pickle from xml.dom import minidom from logging import debug, info, error import pdb @@ -46,13 +46,13 @@ <general> </general> <individual> - <category name="Connection"> + <category name='"""+_("Connection")+"""'> <param name="JabberID" value="goffi@necton2.int/TestScript" type="string" /> <param name="Password" value="toto" type="password" /> <param name="Server" value="necton2.int" type="string" /> - <param name="NewAccount" value="Register new account" type="button" callback="registerNewAccount"/> + <param name="NewAccount" value='"""+_("Register new account")+"""' type="button" callback_id="registerNewAccount"/> </category> - <category name="Misc"> + <category name='"""+_("Misc")+"""'> <param name="Watched" value="test@Jabber.goffi.int" type="string" /> </category> </individual>
--- a/tools/xml_tools.py Wed Jun 23 17:26:21 2010 +0800 +++ b/tools/xml_tools.py Sat Jun 26 15:33:16 2010 +0800 @@ -88,9 +88,12 @@ assert(False) type = param.getAttribute('type') value = param.getAttribute('value') or None - callback = param.getAttribute('callback') or None - param_ui.addLabel(name) - param_ui.addElement(name=name, type=type, value=value, callback=callback) + callback_id = param.getAttribute('callback_id') or None + if type == "button": + param_ui.addEmpty() + else: + param_ui.addLabel(name) + param_ui.addElement(name=name, type=type, value=value, callback_id=callback_id) return param_ui.toXml() @@ -200,15 +203,18 @@ if value: elem.setAttribute('value', value) - def addButton(self, callback, name): + def addButton(self, callback_id, name, value): """Add a button @param callback: callback which will be called if button is pressed - @param name: name shown on the button""" + @param name: name + @param value: label of the button""" elem = self.__createElem('button', name, self.currentLayout) - elem.setAttribute('callback', callback) + elem.setAttribute('callback_id', callback_id) + if value: + elem.setAttribute('value', value) - def addElement(self, type, name = None, content = None, value = None, options = None, callback = None): + def addElement(self, type, name = None, content = None, value = None, options = None, callback_id = None): """Convenience method to add element, the params correspond to the ones in addSomething methods""" if type == 'empty': self.addEmpty(name) @@ -224,8 +230,8 @@ elif type == 'list': self.addList(options, name, value) elif type == 'button': - assert(callback and name) - self.addButton(callback, name) + assert(callback_id and value) + self.addButton(callback_id, name, value) def addOptions(self, options, parent): """Add options to a multi-values element (e.g. list)