view frontends/jp/jp @ 22:bb72c29f3432

added action cb mechanism for buttons. Tested with a temporary new user registration button.
author Goffi <goffi@goffi.org>
date Tue, 01 Dec 2009 04:56:08 +0100
parents c4bc297b82f0
children a5b5fb5fc9fd
line wrap: on
line source

#! /usr/bin/python
# -*- coding: utf-8 -*-

"""
jp: a SAT command line tool
Copyright (C) 2009  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 = "jp"
version = "0.0.1"
about = name+" v"+version+""" (c) Jérôme Poisson (aka Goffi) 2009

---
"""+name+""" Copyright (C) 2009  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 optparse import OptionParser
import pdb
from tools.jid import JID
import gobject
from sat_bridge_frontend.DBus import DBusBridgeFrontend
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):
        self.bridge=DBusBridgeFrontend()
        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
        """
        parser = OptionParser(usage=usage,version=about)

        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("-p", "--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)")

        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"""
        if not self.bridge.isConnected():
            error("SAT 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)
            while (True):
                line = sys.stdin.readline()
                if not line:
                    break
                self.bridge.sendMessage(self.dest_jid, line.replace("\n",""))
        else:
            self.bridge.sendMessage(self.dest_jid, header + "".join(sys.stdin.readlines()))

    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)
        else:
            for file in self.files:
                path = abspath(file)
                self.transfert_id = self.bridge.sendFile(self.dest_jid, path) #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 [%s] from %s", data['filename'], data['from'])
                self.transfert_id = id
            else:
                self.bridge.confirmationAnswer(id, False, answer_data)
                warning("Refused file [%s] from %s: a file with the same name already exist", data['filename'], 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()