Welcome to mirror list, hosted at ThFree Co, Russian Federation.

dev.gajim.org/gajim/gajim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomasz Melcer <liori@exroot.org>2006-07-21 17:52:36 +0400
committerTomasz Melcer <liori@exroot.org>2006-07-21 17:52:36 +0400
commitfa6ae3b4be40d5eaa12a9f5ecf6794856342cfca (patch)
tree8557f0f8fa31e69e96e48515485b70bbfa2b2284
parentfd5294bd210c597192850b6014a047b760fe7860 (diff)
Simple support for pubsub.com notifications.
-rw-r--r--data/glade/atom_entry_window.glade371
-rw-r--r--src/atom_window.py115
-rw-r--r--src/common/atom.py138
-rw-r--r--src/common/connection_handlers.py31
-rwxr-xr-xsrc/gajim.py6
5 files changed, 661 insertions, 0 deletions
diff --git a/data/glade/atom_entry_window.glade b/data/glade/atom_entry_window.glade
new file mode 100644
index 000000000..97f893363
--- /dev/null
+++ b/data/glade/atom_entry_window.glade
@@ -0,0 +1,371 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
+
+<glade-interface>
+
+<widget class="GtkWindow" id="atom_entry_window">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">New entry received</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">False</property>
+ <property name="decorated">True</property>
+ <property name="skip_taskbar_hint">False</property>
+ <property name="skip_pager_hint">False</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+ <property name="focus_on_map">True</property>
+
+ <child>
+ <widget class="GtkVBox" id="vbox112">
+ <property name="border_width">6</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkLabel" id="new_entry_label">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">You have received new entry:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHSeparator" id="hseparator14">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkTable" id="table4">
+ <property name="visible">True</property>
+ <property name="n_rows">4</property>
+ <property name="n_columns">2</property>
+ <property name="homogeneous">False</property>
+ <property name="row_spacing">0</property>
+ <property name="column_spacing">6</property>
+
+ <child>
+ <widget class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Feed name:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_RIGHT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Entry:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Last modified:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="feed_tagline_label">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;small&gt;Romeo and Juliet&lt;/small&gt;</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="last_modified_label">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">2003-12-13T18:30:02Z</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEventBox" id="feed_title_eventbox">
+ <property name="visible">True</property>
+ <property name="visible_window">True</property>
+ <property name="above_child">False</property>
+ <signal name="button_press_event" handler="on_feed_title_eventbox_button_press_event" last_modification_time="Thu, 20 Jul 2006 21:53:07 GMT"/>
+
+ <child>
+ <widget class="GtkLabel" id="feed_title_label">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Old stories</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="x_options">fill</property>
+ <property name="y_options">fill</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEventBox" id="entry_title_eventbox">
+ <property name="visible">True</property>
+ <property name="visible_window">True</property>
+ <property name="above_child">False</property>
+ <signal name="button_press_event" handler="on_entry_title_eventbox_button_press_event" last_modification_time="Thu, 20 Jul 2006 21:53:12 GMT"/>
+
+ <child>
+ <widget class="GtkLabel" id="entry_title_label">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Soliloquy</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">fill</property>
+ <property name="y_options">fill</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHSeparator" id="hseparator15">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="hbox1">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox2">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkButton" id="close_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-close</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_close_button_clicked" last_modification_time="Thu, 20 Jul 2006 21:29:17 GMT"/>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="next_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">Next entry</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_next_button_clicked" last_modification_time="Thu, 20 Jul 2006 21:29:21 GMT"/>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+</glade-interface>
diff --git a/src/atom_window.py b/src/atom_window.py
new file mode 100644
index 000000000..54bf32806
--- /dev/null
+++ b/src/atom_window.py
@@ -0,0 +1,115 @@
+'''atom_window.py - a window to display atom entries from pubsub. For now greatly simplified,
+supports only simple feeds like the one from pubsub.com. '''
+
+import gtk
+import gtk.gdk
+
+import gtkgui_helpers
+from common import helpers
+
+class AtomWindow:
+ window = None
+ entries = []
+
+ @classmethod # python2.4 decorator
+ def newAtomEntry(cls, entry):
+ ''' Queue new entry, open window if there's no one opened. '''
+ cls.entries.append(entry)
+
+ if cls.window is None:
+ cls.window = AtomWindow()
+ else:
+ cls.window.updateCounter()
+
+ def __init__(self):
+ ''' Create new window... only if we have anything to show. '''
+ assert len(self.__class__.entries)>0
+
+ self.entry = None # the entry actually displayed
+
+ self.xml = gtkgui_helpers.get_glade('atom_entry_window.glade')
+ self.window = self.xml.get_widget('atom_entry_window')
+ for name in ('new_entry_label', 'feed_title_label', 'feed_title_eventbox',
+ 'feed_tagline_label', 'entry_title_label', 'entry_title_eventbox',
+ 'last_modified_label', 'close_button', 'next_button'):
+ self.__dict__[name] = self.xml.get_widget(name)
+
+ self.displayNextEntry()
+
+ self.xml.signal_autoconnect(self)
+ self.window.show_all()
+
+ self.entry_title_eventbox.add_events(gtk.gdk.BUTTON_PRESS_MASK)
+ self.feed_title_eventbox.add_events(gtk.gdk.BUTTON_PRESS_MASK)
+
+ def displayNextEntry(self):
+ ''' Get next entry from the queue and display it in the window. '''
+ assert len(self.__class__.entries)>0
+
+ newentry = self.__class__.entries.pop(0)
+
+ # fill the fields
+ if newentry.feed_link is not None:
+ self.feed_title_label.set_markup(
+ u'<span foreground="blue" underline="single">%s</span>' % \
+ gtkgui_helpers.escape_for_pango_markup(newentry.feed_title))
+ else:
+ self.feed_title_label.set_markup(
+ gtkgui_helpers.escape_for_pango_markup(newentry.feed_title))
+
+ self.feed_tagline_label.set_markup(
+ u'<small>%s</small>' % \
+ gtkgui_helpers.escape_for_pango_markup(newentry.feed_tagline))
+
+ if newentry.uri is not None:
+ self.entry_title_label.set_markup(
+ u'<span foreground="blue" underline="single">%s</span>' % \
+ gtkgui_helpers.escape_for_pango_markup(newentry.title))
+ else:
+ self.entry_title_label.set_markup(
+ gtkgui_helpers.escape_for_pango_markup(newentry.title))
+
+ self.last_modified_label.set_text(newentry.updated)
+
+ # update the counters
+ self.updateCounter()
+
+ self.entry = newentry
+
+ def updateCounter(self):
+ ''' We display number of events on the top of window, sometimes it needs to be
+ changed...'''
+ count = len(self.__class__.entries)
+ # TODO: translate
+ if count>0:
+ self.new_entry_label.set_text( \
+ 'You have received new entries (and %(count)d not displayed):' % \
+ {'count': count})
+ self.next_button.set_sensitive(True)
+ else:
+ self.new_entry_label.set_text('You have received new entry:')
+ self.next_button.set_sensitive(False)
+
+ def on_close_button_clicked(self, widget):
+ self.window.destroy()
+
+ def on_next_button_clicked(self, widget):
+ self.displayNextEntry()
+
+ def on_entry_title_button_press_event(self, widget, event):
+ # TODO: make it using special gtk2.10 widget
+ print 1
+ if event.button == 1: # left click
+ uri = self.entry.uri
+ if uri is not None:
+ helpers.launch_browser_mailer('url', uri)
+ return True
+
+ def on_feed_title_button_press_event(self, widget, event):
+ # TODO: make it using special gtk2.10 widget
+ print 2
+ if event.button == 1: # left click
+ uri = self.entry.feed_uri
+ if uri is not None:
+ helpers.launch_browser_mailer('url', uri)
+ return True
diff --git a/src/common/atom.py b/src/common/atom.py
new file mode 100644
index 000000000..508b3db5c
--- /dev/null
+++ b/src/common/atom.py
@@ -0,0 +1,138 @@
+# -*- coding: utf-8 -*-
+''' Atom (rfc 4287) feed parser, used to read data from atom-over-pubsub transports
+and services. Very simple. Actually implements only atom:entry. Implement more features
+if you need. '''
+
+# suggestion: rewrite functions that return dates to return standard python time tuples,
+# exteneded to contain timezone
+
+import xmpp
+import time
+
+class PersonConstruct(xmpp.Node, object):
+ ''' Not used for now, as we don't need authors/contributors in pubsub.com feeds.
+ They rarely exist there. '''
+ def __init__(self, node):
+ ''' Create person construct from node. '''
+ xmpp.Node.__init__(self, node=node)
+
+ def get_name(self):
+ return self.getTagData('name')
+
+ name = property(get_name, None, None,
+ '''Conveys a human-readable name for the person. Should not be None,
+ although some badly generated atom feeds don't put anything here
+ (this is non-standard behavior, still pubsub.com sometimes does that.)''')
+
+ def get_uri(self):
+ return self.getTagData('uri')
+
+ uri = property(get_uri, None, None,
+ '''Conveys an IRI associated with the person. Might be None when not set.''')
+
+ def get_email(self):
+ return self.getTagData('email')
+
+ email = property(get_email, None, None,
+ '''Conveys an e-mail address associated with the person. Might be None when
+ not set.''')
+
+class Entry(xmpp.Node, object):
+ def __init__(self, node=None):
+ ''' Create new atom entry object. '''
+ xmpp.Node.__init__(self, 'entry', node=node)
+
+ def __repr__(self):
+ return '<Atom:Entry object of id="%r">' % self.id
+
+class OldEntry(xmpp.Node, object):
+ ''' Parser for feeds from pubsub.com. They use old Atom 0.3 format with
+ their extensions. '''
+ def __init__(self, node=None):
+ ''' Create new Atom 0.3 entry object. '''
+ xmpp.Node.__init__(self, 'entry', node=node)
+
+ def __repr__(self):
+ return '<Atom0.3:Entry object of id="%r">' % self.id
+
+ def get_feed_title(self):
+ ''' Returns title of feed, where the entry was created. The result is the feed name
+ concatenated with source-feed title. '''
+ title = u''
+
+ if self.parent is not None:
+ main_feed = self.parent.getTagData('title')
+ else:
+ main_feed = None
+
+ if self.getTag('source-feed') is not None:
+ source_feed = self.getTag('source-feed').getTagData('title')
+ else:
+ source_feed = None
+
+ if main_feed is not None and source_feed is not None:
+ return u'%s: %s' % (main_feed, source_feed)
+ elif main_feed is not None:
+ return main_feed
+ elif source_feed is not None:
+ return source_feed
+ else:
+ return u''
+
+ feed_title = property(get_feed_title, None, None,
+ ''' Title of feed. It is built from entry's original feed title and title of feed
+ which delivered this entry. ''')
+
+ def get_feed_link(self):
+ ''' Get a link to main page of feed (in pubsub.com: second link of rel='alternate',
+ first contains raw xml data). '''
+ try:
+ return self.getTag('source-feed').getTags('link', {'rel':'alternate'})[1].getData()
+ except:
+ return None
+
+ feed_link = property(get_feed_link, None, None,
+ ''' Link to main webpage of the feed. ''')
+
+ def get_title(self):
+ ''' Get an entry's title. '''
+ return self.getTagData('title')
+
+ title = property(get_title, None, None,
+ ''' Entry's title. ''')
+
+ def get_uri(self):
+ ''' Get the uri the entry points to (entry's first link element with rel='alternate'
+ or without rel attribute). '''
+ for element in self.getTags('link'):
+ if element.attrs.has_key('rel') and element.attrs['rel']<>'alternate': continue
+ try:
+ return element.attrs['href']
+ except AttributeError:
+ pass
+ return None
+
+ uri = property(get_uri, None, None,
+ ''' URI that is pointed by the entry. ''')
+
+ def get_updated(self):
+ ''' Get the time the entry was updated last time. This should be standarized,
+ but pubsub.com sends it in human-readable format. We won't try to parse it.
+ (Atom 0.3 uses the word «modified» for that).
+
+ If there's no time given in the entry, we try with <published>
+ and <issued> elements. '''
+ for name in ('updated', 'modified', 'published', 'issued'):
+ date = self.getTagData(name)
+ if date is not None: break
+
+ if date is None:
+ # it is not in the standard format
+ return time.asctime()
+
+ return date
+
+ updated = property(get_updated, None, None,
+ ''' Last significant modification time. ''')
+
+ feed_tagline = u''
diff --git a/src/common/connection_handlers.py b/src/common/connection_handlers.py
index 29b5bac6c..bc43958e9 100644
--- a/src/common/connection_handlers.py
+++ b/src/common/connection_handlers.py
@@ -33,6 +33,7 @@ from common import GnuPG
from common import helpers
from common import gajim
from common import dataforms
+from common import atom
from common.commands import ConnectionCommands
STATUS_LIST = ['offline', 'connecting', 'online', 'chat', 'away', 'xa', 'dnd',
@@ -1275,6 +1276,10 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
def _messageCB(self, con, msg):
'''Called when we receive a message'''
+ # check if the message is pubsub#event
+ if msg.getTag('event') is not None:
+ self._pubsubEventCB(con, msg)
+ return
msgtxt = msg.getBody()
mtype = msg.getType()
subject = msg.getSubject() # if not there, it's None
@@ -1394,6 +1399,32 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
subject, chatstate, msg_id, composing_jep, user_nick))
# END messageCB
+ def _pubsubEventCB(self, con, msg):
+ ''' Called when we receive <message/> with pubsub event. '''
+ # TODO: Logging? (actually services where logging would be useful, should
+ # TODO: allow to access archives remotely...)
+ event = msg.getTag('event')
+
+ items = event.getTag('items')
+ if items is None: return
+
+ for item in items.getTags('item'):
+ # check for event type (for now only one type supported: pubsub.com events)
+ child = item.getTag('pubsub-message')
+ if child is not None:
+ # we have pubsub.com notification
+ child = child.getTag('feed')
+ if child is None: continue
+
+ for entry in child.getTags('entry'):
+ # for each entry in feed (there shouldn't be more than one,
+ # but to be sure...
+ self.dispatch('ATOM_ENTRY', (atom.OldEntry(node=entry),))
+ continue
+ # unknown type... probably user has another client who understands that event
+
+ raise common.xmpp.NodeProcessed
+
def _presenceCB(self, con, prs):
'''Called when we receive a presence'''
ptype = prs.getType()
diff --git a/src/gajim.py b/src/gajim.py
index d0fd625cb..1d2e6fa16 100755
--- a/src/gajim.py
+++ b/src/gajim.py
@@ -38,6 +38,7 @@ from common import i18n
import message_control
from chat_control import ChatControlBase
+from atom_window import AtomWindow
from common import exceptions
@@ -1346,6 +1347,10 @@ class Interface:
def handle_event_metacontacts(self, account, tags_list):
gajim.contacts.define_metacontacts(account, tags_list)
+ def handle_atom_entry(self, account, data):
+ atom_entry, = data
+ AtomWindow.newAtomEntry(atom_entry)
+
def handle_event_privacy_lists_received(self, account, data):
# ('PRIVACY_LISTS_RECEIVED', account, list)
if not self.instances.has_key(account):
@@ -1671,6 +1676,7 @@ class Interface:
'ASK_NEW_NICK': self.handle_event_ask_new_nick,
'SIGNED_IN': self.handle_event_signed_in,
'METACONTACTS': self.handle_event_metacontacts,
+ 'ATOM_ENTRY': self.handle_atom_entry,
'PRIVACY_LISTS_RECEIVED': self.handle_event_privacy_lists_received,
'PRIVACY_LIST_RECEIVED': self.handle_event_privacy_list_received,
'PRIVACY_LISTS_ACTIVE_DEFAULT': \