poezio/src/bookmark.py

216 lines
6.4 KiB
Python

import os
import logging
from sys import version_info
from sleekxmpp.plugins.xep_0048 import *
from common import safeJID
from config import config
log = logging.getLogger(__name__)
def iter(xml, tag=''):
if version_info[1] >= 2:
return xml.iter(tag)
else:
return xml.getiterator(tag)
preferred = config.get('use_bookmarks_method', 'pep').lower()
if preferred not in ('pep', 'privatexml'):
preferred = 'privatexml'
not_preferred = 'privatexml' if preferred == 'pep' else 'privatexml'
methods = ('local', preferred, not_preferred)
class Bookmark(object):
possible_methods = methods
def __init__(self, jid, name=None, autojoin=False, nick=None, password=None, method='privatexml'):
self.jid = jid
self.name = name or jid
self.autojoin = autojoin
if not nick:
default = os.environ.get('USER') if os.environ.get('USER') else 'poezio'
nick = config.get('default_nick', '') or default
self.nick = nick
self.password = password
self._method = method
@property
def method(self):
return self._method
@method.setter
def method(self, value):
if value not in self.possible_methods:
log.debug('Could not set bookmark storing method: %s', value)
return
self._method = value
def __repr__(self):
return '<%s>' % self.jid
def stanza(self):
"""
Generate a <conference/> stanza from the instance
"""
el = Conference()
el['name'] = self.name
el['jid'] = self.jid
el['autojoin'] = 'true' if self.autojoin else 'false'
if self.nick:
n = Nick().xml
n.text = self.nick
el.append(n)
if self.password:
p = Password().xml
p.text = self.password
el.append(p)
return el
def local(self):
"""Generate a str for local storage"""
local = self.jid
if self.nick:
local += '/%s' % self.nick
local += ':'
return local
def parse_from_element(el, method=None):
"""
Generate a Bookmark object from a <conference/> element
"""
jid = el.get('jid')
name = el.get('name')
autojoin = True if el.get('autojoin', 'false').lower() in ('true', '1') else False
nick = None
for n in iter(el, 'nick'):
nick = nick.text
password = None
for p in iter(el, 'password'):
password = p.text
return Bookmark(jid, name, autojoin, nick, password, method)
bookmarks = []
def get_by_jid(value):
"""
Get a bookmark by bare jid
"""
for item in bookmarks:
if item.jid == value:
return item
def remove(value):
"""
Remove a bookmark (with its jid or directly the Bookmark object).
"""
if isinstance(value, str):
value = get_by_jid(value)
bookmarks.remove(value)
def stanza_storage(method):
"""Generate a <storage/> stanza with the conference elements."""
storage = Storage()
for b in filter(lambda b: b.method == method, bookmarks):
storage.append(b.stanza())
return storage
def save_pep(xmpp):
"""Save the remote bookmarks via PEP."""
xmpp.plugin['xep_0048'].set_bookmarks(stanza_storage('pep'))
def save_privatexml(xmpp):
""""Save the remote bookmarks with privatexml."""
xmpp.plugin['xep_0048'].set_bookmarks_old(stanza_storage('privatexml'))
def save_remote(xmpp, method=preferred):
"""Save the remote bookmarks."""
method = "privatexml" if method != 'pep' else 'pep'
try:
if method is 'privatexml':
xmpp.plugin['xep_0048'].set_bookmarks_old(stanza_storage('privatexml'))
else:
xmpp.plugin['xep_0048'].set_bookmarks(stanza_storage('pep'))
except:
import traceback
log.debug("Could not save the bookmarks:\n%s" % traceback.format_exc())
return False
return True
def save_local():
"""Save the local bookmarks."""
all = ''.join(bookmark.local() for bookmark in bookmarks if bookmark.method is 'local')
config.set_and_save('rooms', all)
def save(xmpp, core=None):
"""Save all the bookmarks."""
save_local()
if config.get('use_remote_bookmarks', 'true').lower() != 'false':
preferred = config.get('use_bookmarks_method', 'privatexml')
if not save_remote(xmpp, method=preferred) and core:
core.information('Could not save bookmarks.', 'Error')
return False
elif core:
core.information('Bookmarks saved', 'Info')
return True
def get_pep(xmpp):
"""Add the remotely stored bookmarks via pep to the list."""
try:
iq = xmpp.plugin['xep_0048'].get_bookmarks()
except:
return False
for conf in iter(iq.xml, '{storage:bookmarks}conference'):
b = Bookmark.parse_from_element(conf, method='pep')
if not get_by_jid(b.jid):
bookmarks.append(b)
return True
def get_privatexml(xmpp):
"""Add the remotely stored bookmarks via privatexml to the list."""
try:
iq = xmpp.plugin['xep_0048'].get_bookmarks_old()
except:
return False
for conf in iter(iq.xml, '{storage:bookmarks}conference'):
b = Bookmark.parse_from_element(conf, method='privatexml')
if not get_by_jid(b.jid):
bookmarks.append(b)
return True
def get_remote(xmpp):
"""Add the remotely stored bookmarks to the list."""
if xmpp.anon:
return
pep, privatexml = True, True
for method in methods[1:]:
if method == 'pep':
pep = get_pep(xmpp)
else:
privatexml = get_privatexml(xmpp)
if pep and not privatexml:
config.set_and_save('use_bookmarks_method', 'pep')
elif privatexml and not pep:
config.set_and_save('use_bookmarks_method', 'privatexml')
elif not pep and not privatexml:
config.set_and_save('use_bookmarks_method', '')
def get_local():
"""Add the locally stored bookmarks to the list."""
rooms = config.get('rooms', '')
if not rooms:
return
rooms = rooms.split(':')
for room in rooms:
jid = safeJID(room)
if jid.bare == '':
continue
if jid.resource != '':
nick = jid.resource
else:
nick = None
b = Bookmark(jid.bare, autojoin=True, nick=nick, method='local')
if not get_by_jid(b.jid):
bookmarks.append(b)