Remove atom modules
This commit is contained in:
parent
67ddbf73cd
commit
54a9992696
3 changed files with 0 additions and 387 deletions
|
@ -1,226 +0,0 @@
|
||||||
# Copyright (C) 2006 Jean-Marie Traissard <jim AT lapin.org>
|
|
||||||
# Tomasz Melcer <liori AT exroot.org>
|
|
||||||
# Copyright (C) 2006-2014 Yann Leboulanger <asterix AT lagaule.org>
|
|
||||||
#
|
|
||||||
# This file is part of Gajim.
|
|
||||||
#
|
|
||||||
# Gajim is free software; you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published
|
|
||||||
# by the Free Software Foundation; version 3 only.
|
|
||||||
#
|
|
||||||
# Gajim is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
"""
|
|
||||||
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
|
|
||||||
"""
|
|
||||||
|
|
||||||
# XEP-0277: Microblogging over XMPP
|
|
||||||
|
|
||||||
# Module is disabled for now because Gajim lacks a good UI for that
|
|
||||||
# register the module in connection.py with register_module() to activate again
|
|
||||||
|
|
||||||
import logging
|
|
||||||
import time
|
|
||||||
|
|
||||||
import nbxmpp
|
|
||||||
|
|
||||||
from gajim.common.const import PEPEventType
|
|
||||||
from gajim.common.exceptions import StanzaMalformed
|
|
||||||
from gajim.common.modules.pep import AbstractPEPModule, AbstractPEPData
|
|
||||||
|
|
||||||
log = logging.getLogger('gajim.c.m.atom')
|
|
||||||
|
|
||||||
|
|
||||||
class AtomData(AbstractPEPData):
|
|
||||||
|
|
||||||
type_ = PEPEventType.ATOM
|
|
||||||
|
|
||||||
def __init__(self, atom):
|
|
||||||
self.data = atom
|
|
||||||
|
|
||||||
def get_entry(self):
|
|
||||||
return self.data
|
|
||||||
|
|
||||||
|
|
||||||
class Atom(AbstractPEPModule):
|
|
||||||
|
|
||||||
name = 'atom'
|
|
||||||
namespace = 'urn:xmpp:microblog:0'
|
|
||||||
pep_class = AtomData
|
|
||||||
store_publish = False
|
|
||||||
_log = log
|
|
||||||
|
|
||||||
def _extract_info(self, item):
|
|
||||||
entry = item.getTag('entry', namespace=nbxmpp.NS_ATOM)
|
|
||||||
if entry is None:
|
|
||||||
StanzaMalformed('no entry node')
|
|
||||||
|
|
||||||
return OldEntry(node=entry) or None
|
|
||||||
|
|
||||||
def _build_node(self, data):
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
|
|
||||||
class PersonConstruct(nbxmpp.Node):
|
|
||||||
"""
|
|
||||||
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. '''
|
|
||||||
nbxmpp.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(nbxmpp.Node):
|
|
||||||
def __init__(self, node=None):
|
|
||||||
nbxmpp.Node.__init__(self, 'entry', node=node)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return '<Atom:Entry object of id="%r">' % self.getAttr('id')
|
|
||||||
|
|
||||||
|
|
||||||
class OldEntry(nbxmpp.Node):
|
|
||||||
"""
|
|
||||||
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. '''
|
|
||||||
nbxmpp.Node.__init__(self, 'entry', node=node)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return '<Atom0.3:Entry object of id="%r">' % self.getAttr('id')
|
|
||||||
|
|
||||||
def get_feed_title(self):
|
|
||||||
"""
|
|
||||||
Return title of feed, where the entry was created.
|
|
||||||
The result is the feed name concatenated with source-feed title
|
|
||||||
"""
|
|
||||||
if self.parent is not None:
|
|
||||||
main_feed = self.parent.getTagData('title')
|
|
||||||
else:
|
|
||||||
main_feed = None
|
|
||||||
|
|
||||||
if self.getTag('feed') is not None:
|
|
||||||
source_feed = self.getTag('feed').getTagData('title')
|
|
||||||
else:
|
|
||||||
source_feed = None
|
|
||||||
|
|
||||||
if main_feed is not None and source_feed is not None:
|
|
||||||
return '%s: %s' % (main_feed, source_feed)
|
|
||||||
if main_feed is not None:
|
|
||||||
return main_feed
|
|
||||||
if source_feed is not None:
|
|
||||||
return source_feed
|
|
||||||
return ''
|
|
||||||
|
|
||||||
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 source link
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
link = self.getTag('feed').getTags('link', {'rel': 'alternate'})
|
|
||||||
return link[1].getData()
|
|
||||||
except Exception:
|
|
||||||
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 'rel' in element.attrs 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 = ''
|
|
|
@ -1,152 +0,0 @@
|
||||||
# Copyright (C) 2006 Tomasz Melcer <liori AT exroot.org>
|
|
||||||
# Copyright (C) 2006-2014 Yann Leboulanger <asterix AT lagaule.org>
|
|
||||||
# Copyright (C) 2007 Nikos Kouremenos <kourem AT gmail.com>
|
|
||||||
# Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org>
|
|
||||||
#
|
|
||||||
# This file is part of Gajim.
|
|
||||||
#
|
|
||||||
# Gajim is free software; you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published
|
|
||||||
# by the Free Software Foundation; version 3 only.
|
|
||||||
#
|
|
||||||
# Gajim is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
from typing import List # pylint: disable=unused-import
|
|
||||||
from typing import Any # pylint: disable=unused-import
|
|
||||||
|
|
||||||
from gi.repository import Gdk
|
|
||||||
from gi.repository import GLib
|
|
||||||
|
|
||||||
from gajim.common import helpers
|
|
||||||
from gajim.common import i18n
|
|
||||||
from gajim.common.i18n import _
|
|
||||||
|
|
||||||
from gajim.gtk.util import get_builder
|
|
||||||
|
|
||||||
class AtomWindow:
|
|
||||||
window = None
|
|
||||||
entries = [] # type: List[Any]
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
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()
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def windowClosed(cls):
|
|
||||||
cls.window = None
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
"""
|
|
||||||
Create new window... only if we have anything to show
|
|
||||||
"""
|
|
||||||
assert self.__class__.entries
|
|
||||||
|
|
||||||
self.entry = None # the entry actually displayed
|
|
||||||
|
|
||||||
self.xml = get_builder('atom_entry_window.ui')
|
|
||||||
self.window = self.xml.get_object('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_object(name)
|
|
||||||
|
|
||||||
self.displayNextEntry()
|
|
||||||
|
|
||||||
self.xml.connect_signals(self)
|
|
||||||
self.window.show_all()
|
|
||||||
|
|
||||||
self.entry_title_eventbox.add_events(Gdk.EventMask.BUTTON_PRESS_MASK)
|
|
||||||
self.feed_title_eventbox.add_events(Gdk.EventMask.BUTTON_PRESS_MASK)
|
|
||||||
|
|
||||||
def displayNextEntry(self):
|
|
||||||
"""
|
|
||||||
Get next entry from the queue and display it in the window
|
|
||||||
"""
|
|
||||||
assert self.__class__.entries
|
|
||||||
|
|
||||||
newentry = self.__class__.entries.pop(0)
|
|
||||||
|
|
||||||
# fill the fields
|
|
||||||
if newentry.feed_link is not None:
|
|
||||||
self.feed_title_label.set_markup(
|
|
||||||
'<span foreground="blue" underline="single">%s</span>' % \
|
|
||||||
GLib.markup_escape_text(newentry.feed_title))
|
|
||||||
else:
|
|
||||||
self.feed_title_label.set_markup(GLib.markup_escape_text(
|
|
||||||
newentry.feed_title))
|
|
||||||
|
|
||||||
self.feed_tagline_label.set_markup(
|
|
||||||
'<small>%s</small>' % GLib.markup_escape_text(
|
|
||||||
newentry.feed_tagline))
|
|
||||||
|
|
||||||
if newentry.title:
|
|
||||||
if newentry.uri is not None:
|
|
||||||
self.entry_title_label.set_markup(
|
|
||||||
'<span foreground="blue" underline="single">%s</span>' % \
|
|
||||||
GLib.markup_escape_text(newentry.title))
|
|
||||||
else:
|
|
||||||
self.entry_title_label.set_markup(GLib.markup_escape_text(
|
|
||||||
newentry.title))
|
|
||||||
else:
|
|
||||||
self.entry_title_label.set_markup('')
|
|
||||||
|
|
||||||
self.last_modified_label.set_text(newentry.updated)
|
|
||||||
|
|
||||||
# update the counters
|
|
||||||
self.updateCounter()
|
|
||||||
|
|
||||||
self.entry = newentry
|
|
||||||
|
|
||||||
def updateCounter(self):
|
|
||||||
"""
|
|
||||||
Display number of events on the top of window, sometimes it needs to be
|
|
||||||
changed
|
|
||||||
"""
|
|
||||||
count = len(self.__class__.entries)
|
|
||||||
if count:
|
|
||||||
self.new_entry_label.set_text(i18n.ngettext(
|
|
||||||
'You have received new entries (and %d not displayed):',
|
|
||||||
'You have received new entries (and %d not displayed):', count,
|
|
||||||
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()
|
|
||||||
self.windowClosed()
|
|
||||||
|
|
||||||
def on_next_button_clicked(self, widget):
|
|
||||||
self.displayNextEntry()
|
|
||||||
|
|
||||||
def on_entry_title_eventbox_button_press_event(self, widget, event):
|
|
||||||
#FIXME: make it using special gtk2.10 widget
|
|
||||||
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_eventbox_button_press_event(self, widget, event):
|
|
||||||
#FIXME: make it using special gtk2.10 widget
|
|
||||||
if event.button == 1: # left click
|
|
||||||
uri = self.entry.feed_uri
|
|
||||||
if uri is not None:
|
|
||||||
helpers.launch_browser_mailer('url', uri)
|
|
||||||
return True
|
|
|
@ -117,7 +117,6 @@ from gajim.gtk.filechoosers import FileChooserDialog
|
||||||
from gajim.gtk.emoji_data import emoji_data
|
from gajim.gtk.emoji_data import emoji_data
|
||||||
from gajim.gtk.emoji_data import emoji_ascii_data
|
from gajim.gtk.emoji_data import emoji_ascii_data
|
||||||
from gajim.gtk.groupchat_config import GroupchatConfig
|
from gajim.gtk.groupchat_config import GroupchatConfig
|
||||||
from gajim.gtk.atom import AtomWindow
|
|
||||||
from gajim.gtk.filetransfer import FileTransfersWindow
|
from gajim.gtk.filetransfer import FileTransfersWindow
|
||||||
from gajim.gtk.util import get_show_in_roster
|
from gajim.gtk.util import get_show_in_roster
|
||||||
from gajim.gtk.util import get_show_in_systray
|
from gajim.gtk.util import get_show_in_systray
|
||||||
|
@ -1035,13 +1034,6 @@ class Interface:
|
||||||
def handle_event_metacontacts(obj):
|
def handle_event_metacontacts(obj):
|
||||||
app.contacts.define_metacontacts(obj.conn.name, obj.meta_list)
|
app.contacts.define_metacontacts(obj.conn.name, obj.meta_list)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def handle_atom_entry(obj):
|
|
||||||
if obj != PEPEventType.ATOM:
|
|
||||||
return
|
|
||||||
if obj.get_entry():
|
|
||||||
AtomWindow.newAtomEntry(obj.get_entry())
|
|
||||||
|
|
||||||
def handle_event_zc_name_conflict(self, obj):
|
def handle_event_zc_name_conflict(self, obj):
|
||||||
def on_ok(new_name):
|
def on_ok(new_name):
|
||||||
app.config.set_per('accounts', obj.conn.name, 'name', new_name)
|
app.config.set_per('accounts', obj.conn.name, 'name', new_name)
|
||||||
|
@ -1292,7 +1284,6 @@ class Interface:
|
||||||
self.handlers = {
|
self.handlers = {
|
||||||
'DB_ERROR': [self.handle_event_db_error],
|
'DB_ERROR': [self.handle_event_db_error],
|
||||||
'file-send-error': [self.handle_event_file_send_error],
|
'file-send-error': [self.handle_event_file_send_error],
|
||||||
'pep-received': [self.handle_atom_entry],
|
|
||||||
'bad-gpg-passphrase': [self.handle_event_bad_gpg_passphrase],
|
'bad-gpg-passphrase': [self.handle_event_bad_gpg_passphrase],
|
||||||
'bookmarks-received': [self.handle_event_bookmarks],
|
'bookmarks-received': [self.handle_event_bookmarks],
|
||||||
'client-cert-passphrase': [
|
'client-cert-passphrase': [
|
||||||
|
|
Loading…
Add table
Reference in a new issue