Mercurial > libervia-backend
diff frontends/src/jp/base.py @ 814:59c7bc51c323
jp: refactoring using ArgParse
author | Dal <kedals0@gmail.com> |
---|---|
date | Wed, 05 Feb 2014 14:35:26 +0100 |
parents | frontends/src/jp/jp@1fe00f0c9a91 |
children | c39117d00f35 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/frontends/src/jp/base.py Wed Feb 05 14:35:26 2014 +0100 @@ -0,0 +1,263 @@ +#! /usr/bin/python +# -*- coding: utf-8 -*- + +# jp: a SAT command line tool +# Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014 Jérôme Poisson (goffi@goffi.org) + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program 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 Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +from __future__ import with_statement +from sat.core.i18n import _ + +#consts +name = u"jp" +about = name+u""" v%s (c) Jérôme Poisson (aka Goffi) 2009, 2010, 2011, 2012, 2013, 2014 + +--- +"""+name+u""" Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014 Jérôme Poisson (aka Goffi) +This program comes with ABSOLUTELY NO WARRANTY; +This is free software, and you are welcome to redistribute it +under certain conditions. +--- + +This software is a command line tool for jabber +Get the latest version at http://www.goffi.org +""" + +global pbar_available +pbar_available = True #checked before using ProgressBar + +### logging ### +import logging +from logging import debug, info, error, warning +logging.basicConfig(level=logging.DEBUG, + format='%(message)s') +### + +import sys +import os +from os.path import abspath, basename, dirname +from argparse import ArgumentParser +from sat.tools.jid import JID +import gobject +from sat_frontends.bridge.DBus import DBusBridgeFrontend +from sat.core.exceptions import BridgeExceptionNoService, BridgeInitError +from sat.tools.utils import clean_ustr +import tarfile +import tempfile +import shutil +try: + from progressbar import ProgressBar, Percentage, Bar, ETA, FileTransferSpeed +except ImportError, e: + info (_('ProgressBar not available, please download it at http://pypi.python.org/pypi/progressbar')) + info (_('Progress bar deactivated\n--\n')) + pbar_available=False + + +#version = unicode(self.bridge.getVersion()) +version = "undefined" +parser = ArgumentParser() +parser.add_argument('--version', action='version', version=about % version) +subparser = parser.add_subparsers(dest='subparser_name') +# File managment + + + +class JP(object): + """ + This class can be use to establish a connection with the + bridge. Moreover, it should manage a main loop. + + To use it, you mainly have to redefine the method run to perform + specify what kind of operation you want to perform. + + """ + def __init__(self, start_mainloop = False): + try: + self.bridge=DBusBridgeFrontend() + except BridgeExceptionNoService: + print(_(u"Can't connect to SàT backend, are you sure it's launched ?")) + sys.exit(1) + except BridgeInitError: + print(_(u"Can't init bridge")) + sys.exit(1) + + self._start_loop = start_mainloop + + def run(self): + raise NotImplementedError + + def _run(self): + """Call run and lauch a loop if needed""" + print "You are connected!" + self.run() + if self._start_loop: + print "Exiting loop..." + self.loop.quit() + + def _loop_start(self): + self.loop = gobject.MainLoop() + try: + self.loop.run() + except KeyboardInterrupt: + info(_("User interruption: good bye")) + + def start_mainloop(self): + self._start_loop = True + + def go(self): + self.run() + if self._start_loop: + self._loop_start() + + +class JPWithProfile(JP): + """Manage a bridge (inherit from :class:`JP`), but it also adds + profile managment, ie, connection to the profile. + + Moreover, some useful methods are predefined such as + :py:meth:`check_jids`. The connection to XMPP is automatically + managed. + """ + + def __init__(self, profile_name, start_mainloop = False): + JP.__init__(self, start_mainloop) + self.profile_name = profile_name + + def check_jids(self, jids): + """Check jids validity, transform roster name to corresponding jids + + :param profile: A profile name + :param jids: A list of jids + :rtype: A list of jids + """ + names2jid = {} + nodes2jid = {} + + for contact in self.bridge.getContacts(self.profile): + _jid, attr, groups = contact + if attr.has_key("name"): + names2jid[attr["name"].lower()] = _jid + nodes2jid[JID(_jid).node.lower()] = _jid + + def expandJid(jid): + _jid = jid.lower() + if _jid in names2jid: + expanded = names2jid[_jid] + elif _jid in nodes2jid: + expanded = nodes2jid[_jid] + else: + expanded = jid + return unicode(expanded) + + def check(jid): + if not jid.is_valid: + error (_("%s is not a valid JID !"), jid) + exit(1) + + dest_jids=[] + try: + for i in range(len(jids)): + dest_jids.append(expandJid(jids[i])) + check(dest_jids[i]) + except AttributeError: + pass + + return dest_jids + + def check_jabber_connection(self): + """Check that jabber status is allright""" + def cantConnect(arg): + print arg + error(_(u"Can't connect profile")) + exit(1) + + self.profile = self.bridge.getProfileName(self.profile_name) + if not self.profile: + error(_("The profile asked doesn't exist")) + exit(1) + + if self.bridge.isConnected(self.profile): + print "Already connected" + else: + self._start_loop = True + self.bridge.asyncConnect(self.profile, self._run, cantConnect) + return + self.run() + + + def _getFullJid(self, param_jid): + """Return the full jid if possible (add last resource when find a bare jid""" + _jid = JID(param_jid) + if not _jid.resource: + #if the resource is not given, we try to add the last known resource + last_resource = self.bridge.getLastResource(param_jid, self.profile_name) + if last_resource: + return "%s/%s" % (_jid.bare, last_resource) + return param_jid + + def go(self): + self.check_jabber_connection() + if self._start_loop: + self._loop_start() + + + +class JPAsk(JPWithProfile): + def confirm_type(self): + """Must return a string containing the confirm type. For instance, + FILE_TRANSFER or PIPE_TRANSFER, etc. + + :rtype: str + """ + raise NotImplemented + + def dest_jids(self): + return None + + def _askConfirmation(self, confirm_id, confirm_type, data, profile): + if profile != self.profile: + debug("Ask confirmation ignored: not our profile") + return + if confirm_type == self.confirm_type(): + self._confirm_id = confirm_id + if self.dest_jids() and not JID(data['from']).bare in [JID(_jid).bare for _jid in self.dest_jids()]: + return #file is not sent by a filtered jid + else: + self.ask(data) + + def ask(self): + """ + The return value is used to answer to the bridge. + :rtype: (bool, dict) + """ + raise NotImplementedError + + def answer(self, accepted, answer_data): + """ + :param accepted: boolean + :param aswer_data: dict of answer datas + """ + self.bridge.confirmationAnswer(self._confirm_id, False, answer_data, self.profile) + + def run(self): + """Auto reply to confirmations requests""" + #we register incoming confirmation + self.bridge.register("askConfirmation", self._askConfirmation) + + #and we ask those we have missed + for confirm_id, confirm_type, data in self.bridge.getWaitingConf(self.profile): + self._askConfirmation(confirm_id, confirm_type, data, self.profile) + +