diff frontends/src/jp/jp @ 223:86d249b6d9b7

Files reorganisation
author Goffi <goffi@goffi.org>
date Wed, 29 Dec 2010 01:06:29 +0100
parents frontends/jp/jp@1438a1337732
children fd9b7834d98a
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/frontends/src/jp/jp	Wed Dec 29 01:06:29 2010 +0100
@@ -0,0 +1,272 @@
+#! /usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""
+jp: a SAT command line tool
+Copyright (C) 2009, 2010  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 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+
+#consts
+name = u"jp"
+about = name+u""" v%s (c) Jérôme Poisson (aka Goffi) 2009, 2010
+
+---
+"""+name+u""" Copyright (C) 2009, 2010  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 gettext
+gettext.install('jp', "i18n", unicode=True)
+
+import sys
+import os
+from os.path import abspath, basename, dirname
+from optparse import OptionParser
+import pdb
+from tools.jid import JID
+import gobject
+from sat_bridge_frontend.DBus import DBusBridgeFrontend,BridgeExceptionNoService
+import tarfile
+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
+
+
+
+
+class JP():
+    def __init__(self):
+        try:
+            self.bridge=DBusBridgeFrontend()
+        except BridgeExceptionNoService:
+            print(_(u"Can't connect to SàT backend, are you sure it's launched ?"))
+            import sys
+            sys.exit(1)
+        self.transfert_id = None
+
+    def check_options(self):
+        """Check command line options"""
+        usage=_("""
+        %prog [options] [FILE1 FILE2 ...] JID
+        %prog -w [options] [JID1 JID2 ...]
+
+        %prog --help for options list
+        """)
+        version = unicode(self.bridge.getVersion())
+        parser = OptionParser(usage=usage,version=about % version)
+
+        parser.add_option("-p", "--profile", action="store", type="string", default='@DEFAULT@',
+                    help=_("Use PROFILE profile key (default: %default)"))
+        parser.add_option("-b", "--bz2", action="store_true", default=False,
+                    help=_("Make a bzip2 tarball"))
+        parser.add_option("-w", "--wait-file", action="store_true", default=False,
+                    help=_("Wait for a file to be sent by a contact"))
+        parser.add_option("-m", "--multiple", action="store_true", default=False,
+                    help=_("Accept multiple files (you'll have to stop manually)"))
+        parser.add_option("-f", "--force", action="store_true", default=False,
+                    help=_("Force overwritting of existing files"))
+        parser.add_option("-g", "--progress", action="store_true", default=False,
+                    help=_("Show progress bar"))
+        parser.add_option("-s", "--separate", action="store_true", default=False,
+                    help=_("Separate xmpp messages: send one message per line instead of one message alone."))
+        parser.add_option("-n", "--new-line", action="store_true", default=False,
+                    help=_("Add a new line at the beginning of the input (usefull for ascii art ;))"))
+
+        (self.options, args) = parser.parse_args()
+
+        if len(args) < 1 and not self.options.wait_file:
+            parser.error(_("You must specify the destination JID (Jabber ID)").encode('utf-8'))
+
+        if self.options.wait_file:
+            #several jid
+            self.dest_jids = args
+        else:
+            #one dest_jid, other args are files
+            self.dest_jid = JID(args[-1])
+            if not self.dest_jid.is_valid:
+                error (_("%s is not a valid JID !"), self.dest_jid)
+                exit(1)
+            self.files = args[:-1]
+
+        if not pbar_available and self.options.progress:
+            self.options.progress = False
+            error (_("Option progress is not available, deactivated."))
+
+        if self.options.progress or self.options.wait_file:
+            self.start_loop = True  #We have to use loop for these options
+        else:
+            self.start_loop = False
+        
+            
+        return args
+
+    def check_jabber_status(self):
+        """Check that jabber status is allright"""
+        
+        self.profile = self.bridge.getProfileName(self.options.profile)
+        if not self.profile:
+            error(_("The profile asked doesn't exist"))
+            exit(1)
+
+        if not self.bridge.isConnected(self.profile):
+            error(_(u"SàT is not conneted, please connect before using jp"))
+            exit(1)
+
+
+    def send_stdin(self):
+        """Send incomming data on stdin to jabber contact"""
+        header = "\n" if self.options.new_line else ""
+
+        if self.options.separate:  #we send stdin in several messages
+            if header:
+                self.bridge.sendMessage(self.dest_jid, header, profile_key=self.profile)
+            while (True):
+                line = sys.stdin.readline()
+                if not line:
+                    break
+                self.bridge.sendMessage(self.dest_jid, line.replace("\n",""), profile_key=self.profile)
+        else:
+            self.bridge.sendMessage(self.dest_jid, header + "".join(sys.stdin.readlines()), profile_key=self.profile)
+
+    def send_files(self):
+        """Send files to jabber contact"""
+
+        for file in self.files:
+            if not os.path.exists(file):
+                error (_("File [%s] doesn't exist !") % file)
+                exit(1)
+            if not self.options.bz2 and os.path.isdir(file):
+                error (_("[%s] is a dir ! Please send files inside or use compression") % file)
+                exit(1)
+
+        if self.options.bz2:
+            tmpfile = (basename(self.files[0]) or basename(dirname(self.files[0])) ) + '.tar.bz2' #FIXME: tmp, need an algorithm to find a good name/path
+            if os.path.exists(tmpfile):
+                error (_("tmp file (%s) already exists ! Please remove it"), tmpfile)
+                exit(1)
+            warning(_("bz2 is an experimental option at an early dev stage, use with caution"))
+            #FIXME: check free space, writting perm, tmp dir, filename (watch for OS used)
+            info(_("Starting compression, please wait..."))
+            sys.stdout.flush()
+            bz2=tarfile.open(tmpfile, "w:bz2")
+            for file in self.files:
+                info(_("Adding %s"), file)
+                bz2.add(file)
+            bz2.close()
+            info(_("OK !"))
+            path = abspath(tmpfile)
+            self.transfert_id = self.bridge.sendFile(self.dest_jid, path, profile_key=self.profile)
+        else:
+            for file in self.files:
+                path = abspath(file)
+                self.transfert_id = self.bridge.sendFile(self.dest_jid, path, profile_key=self.profile) #FIXME: show progress only for last transfert_id
+
+        #TODO: manage ProgressBar
+
+    def askConfirmation(self, type, id, data):
+        """CB used for file transfert, accept files depending on parameters"""
+        answer_data={}
+        if type == "FILE_TRANSFERT":
+            if self.dest_jids and not data['from'] in self.dest_jids:
+                return #file is not sent by a filtered jid
+                
+            answer_data["dest_path"] = os.getcwd()+'/'+data['filename']
+
+            if self.options.force or not os.path.exists(answer_data["dest_path"]):
+                self.bridge.confirmationAnswer(id, True, answer_data)
+                info(_("Accepted file [%(filename)s] from %(sender)s") % {'filename':data['filename'], 'sender':data['from']})
+                self.transfert_id = id
+            else:
+                self.bridge.confirmationAnswer(id, False, answer_data)
+                warning(_("Refused file [%(filename)s] from %(sender)s: a file with the same name already exist") % {'filename':data['filename'], 'sender':data['from']})
+                
+
+            if not self.options.multiple and not self.options.progress:
+                #we just accept one file
+                self.loop.quit()
+                
+    def actionResult(self, type, id, data):
+        #FIXME
+        info (_("FIXME: actionResult not implemented"))
+
+    def wait_file(self):
+        """Wait for a file and write it on local dir"""
+        self.bridge.register("askConfirmation", self.askConfirmation, "request")
+
+    def progressCB(self):
+        if self.transfert_id:
+            data = self.bridge.getProgress(self.transfert_id)
+            if data:
+                if not data['position']:
+                    data['position'] = '0'
+                if not self.pbar:
+                    #first answer, we must construct the bar
+                    self.pbar = ProgressBar(int(data['size']),[_("Progress: "),Percentage()," ",Bar()," ",FileTransferSpeed()," ",ETA()])
+                    self.pbar.start()
+                    
+                self.pbar.update(int(data['position']))
+            elif self.pbar:
+                self.pbar.finish()
+                if not self.options.multiple:
+                    self.loop.quit()
+                return False
+
+        return True
+
+    def go(self):
+        self.check_options()
+        self.check_jabber_status()
+        if self.options.wait_file:
+            self.wait_file()
+        else:
+            if not self.files:  #we send message only if there are no files to send
+                self.send_stdin()
+            else:
+                self.send_files()
+
+        if self.start_loop:
+            self.loop = gobject.MainLoop()
+            if self.options.progress:
+                self.pbar = None
+                gobject.timeout_add(10, self.progressCB)
+            try:
+                self.loop.run()
+            except KeyboardInterrupt:
+                info(_("User interruption: good bye"))
+
+
+if __name__ == "__main__":
+    jp = JP()
+    jp.go()