<filename>duoMain.py
__author__ = '<EMAIL>'

import os, webbrowser, ConfigParser, traceback
from pyvin.core import Commading
from duoPdf import DuoPdf
from duoPersist import Persist
from pyvin.core import Log

class Duokan:
    def __init__(self):
        self.TAG = Duokan.__name__
        Duokan.ensureDir(os.path.join(os.path.curdir, 'tmp'))
        Duokan.ensureDir(os.path.join(os.path.curdir, 'books'))
        Duokan.ensureDir(os.path.join(os.path.curdir, 'books', 'new'))
        Duokan.ensureDir(os.path.join(os.path.curdir, 'cache'))

        self.persist = Persist()

    def openInNewTab(self, url):
        '''open in browser with new tab'''
        if len(url) > 0:
            webbrowser.open(url, new=2, autoraise=True)
        else:
            Log.e(self.TAG, 'url is empty')

    def cleanTmp(self):
        '''clean the tmp dir'''
        path = os.path.join(os.path.curdir, 'tmp')
        for item in os.listdir(path):
            filename = os.path.join(path, item)
            Log.e(self.TAG, 'deleting %s' % (filename, ))
            self.deleteFileFolder(filename)

    def deleteFileFolder(self, src):
        '''delete files and folders'''
        if os.path.isfile(src):
            try:
                os.remove(src)
            except:
                Log.e(self.TAG, 'delete [%s] failed...' % (src, ))
        elif os.path.isdir(src):
            for item in os.listdir(src):
                itemsrc=os.path.join(src,item)
                self.deleteFileFolder(itemsrc)
            try:
                os.rmdir(src)
            except:
                Log.e(self.TAG, 'delete [%s] failed...' % (src, ))

    def rename(self, id, title = ''):
        if len(title) < 1:
            title = self.persist.getTitle(id)
        path = os.path.join(os.path.curdir, 'books', 'new', id+'.pdf')
        newPath = os.path.join(os.path.curdir, 'books', 'new', title+'.pdf')
        if os.path.exists(path):
            os.rename(path, newPath)

    def renameAll(self):
        path = os.path.join(os.path.curdir, 'books', 'new')
        for item in os.listdir(path):
            bid, extname = os.path.splitext(item)
            title = self.persist.getTitle(bid)
            if title:
                newName = '%s%s' % (title, extname)
                os.rename(os.path.join(path, item), os.path.join(path, newName))
                Log.i(self.TAG, '%s -> %s' % (item, newName))

    def openNewFolder(self):
        path = os.path.join(os.path.curdir, 'books', 'new')
        self.openInNewTab(path)

    @staticmethod
    def ensureDir(path):
        '''check dir exist or not, create it if not exist'''
        if not os.path.exists(path):
            os.mkdir(path)

    @staticmethod
    def merge(id):
        '''merge pdf files in tmp/${id}, to books/new/${id}.pdf'''
        srcPath = os.path.join(os.path.curdir, 'tmp', id)
        destPath = os.path.join(os.path.curdir, 'books', 'new', id+'.pdf')
        DuoPdf.clean(srcPath)   # clean pdf
        DuoPdf.merge(destPath, srcPath)

    @staticmethod
    def mergeSingle(src):
        if not os.path.isdir(src):
            Log.w(Duokan.__name__, '[%s] is not a diractory, exit...' % (src, ))
            return
        path = os.path.split(src)
        id = path[1]
        destPath = os.path.join(path[0], id+'.pdf')
        DuoPdf.clean(src)
        DuoPdf.merge(destPath, src)

    @staticmethod
    def crop(id):
        '''crop pdf file in books/new/${id}.pdf'''
        srcPath = os.path.join(os.path.curdir, 'books', 'new', id+'.pdf')
        destPath = os.path.join(os.path.curdir, 'books', 'new', id+'.cropped.pdf')
        DuoPdf.cropWH(destPath, srcPath, 500, 666)
        os.remove(srcPath)
        os.rename(destPath, srcPath)

    @staticmethod
    def cropSingle(src):
        '''crop pdf file'''
        srcPath, ext = os.path.splitext(src)
        destPath = srcPath + '_c' + ext
        DuoPdf.cropWH(destPath, src, 500, 666)

    @staticmethod
    def crop4Print(src):
        '''crop blank edge except first page'''
        srcPath, ext = os.path.splitext(src)
        destPath = srcPath + '_p' + ext
        # print destPath
        DuoPdf.crop2(destPath, src, (0, 12, 48, 12), (48, 12, 0, 12))

    @staticmethod
    def crop4Kindle(src):
        '''crop blank edge'''
        srcPath, ext = os.path.splitext(src)
        destPath = srcPath + '_k' + ext
        # print destPath
        DuoPdf.crop(destPath, src, 50, 12, 50, 12)

    @staticmethod
    def crop4Nook(src):
        '''crop blank edge'''
        srcPath, ext = os.path.splitext(src)
        destPath = srcPath + '_n' + ext
        # print destPath
        DuoPdf.crop(destPath, src, 56, 40, 56, 40)

    def addBook(self, id, title, author, link):
        return self.persist.addBook(id, title, author, link)

    def isDownload(self, id):
        return self.persist.isDownload(id)

    def setDownload(self, id):
        self.persist.setDownload(id)

class Downloader(Commading):
    EVT_LOG = 11
    EVT_PROG = 12
    EVT_START = Commading.ON_START
    EVT_STOP = 14

    def __init__(self, bid, name, proxyHost='', proxyAuthUser='', proxyAuthPswd=''):
        '''phantomjs --proxy=host --proxy-auth=username:password duokan.js %1 %ddd%/%2 4'''
        self.TAG = Downloader.__name__
        cmd = ['plugin/phantomjs',]
        if len(proxyHost) > 0:
            cmd.append('--proxy=%s' % (proxyHost, ))
            if len(proxyAuthUser) > 0 and len(proxyAuthPswd):
                cmd.append('--proxy-auth=%s:%s' % (proxyAuthUser, proxyAuthPswd))
        cmd.append('--disk-cache=true')         # enable cache to speed up downloading
        cmd.append('--disk-cache-path=cache')   # set cache path
        # cmd.append('--debug=true')
        cmd.append('duokan.js')
        cmd.append(bid)
        cmd.append('tmp/%s' % (name, ))
        cmd.append('4')

        print cmd

        Commading.__init__(self, cmd)
        self.init([Downloader.EVT_LOG, Downloader.EVT_PROG, Downloader.EVT_START, Downloader.EVT_STOP])
        self.bind(Commading.ON_LOG, self.onLog)
        self.bind(Commading.ON_STOP, self.onStop)
        self.persist = Persist()
        self.id = bid

    def onStop(self, event):
        Log.i(self.TAG, 'phantomjs finished...')
        self.persist.setDownload(self.id)
        Duokan.merge(self.id)
        Log.i(self.TAG, 'merged pdf...')
        Duokan.crop(self.id)
        Log.i(self.TAG, 'croped pdf...')
        self.dispatch(Downloader.EVT_STOP)

    def onLog(self, event, str):
        # self.hdl.cbLog(str)
        self.dispatch(Downloader.EVT_LOG, str)
        prefix = 'progress, '
        if str.startswith(prefix):
            str = str[len(prefix):]
            str = str.lstrip('\n').lstrip('\r')
            str = str.split('/')
            prog = int(str[0]) * 100 / int(str[1])
            # self.hdl.cbProgress(prog)
            self.dispatch(Downloader.EVT_PROG, prog)

class Config:
    KEY_PROXY = 'proxy'
    KEY_PROXY_HOST = 'host'
    KEY_PROXY_USER = 'user'
    KEY_PROXY_PAWD = 'pswd'

    def __init__(self, name = 'config.conf'):
        self.TAG = Config.__name__
        self.conf = ConfigParser.ConfigParser()
        self.conf.read(name)

        self._getProxy()

    def _getProxy(self):
        self.host = ''
        self.user = ''
        self.pswd = ''
        try:
            self.host = self.conf.get(Config.KEY_PROXY, Config.KEY_PROXY_HOST)
            self.user = self.conf.get(Config.KEY_PROXY, Config.KEY_PROXY_USER)
            self.pswd = self.conf.get(Config.KEY_PROXY, Config.KEY_PROXY_PAWD)
        except:
            Log.w(self.TAG, 'read proxy failed')
            traceback.print_exc()

    def getProxy(self):
        return (self.host, self.user, self.pswd)


<filename>duoMain.py
__author__ = '<EMAIL>'

import os, webbrowser, ConfigParser, traceback
from pyvin.core import Commading
from duoPdf import DuoPdf
from duoPersist import Persist
from pyvin.core import Log

class Duokan:
    def __init__(self):
        self.TAG = Duokan.__name__
        Duokan.ensureDir(os.path.join(os.path.curdir, 'tmp'))
        Duokan.ensureDir(os.path.join(os.path.curdir, 'books'))
        Duokan.ensureDir(os.path.join(os.path.curdir, 'books', 'new'))
        Duokan.ensureDir(os.path.join(os.path.curdir, 'cache'))

        self.persist = Persist()

    def openInNewTab(self, url):
        '''open in browser with new tab'''
        if len(url) > 0:
            webbrowser.open(url, new=2, autoraise=True)
        else:
            Log.e(self.TAG, 'url is empty')

    def cleanTmp(self):
        '''clean the tmp dir'''
        path = os.path.join(os.path.curdir, 'tmp')
        for item in os.listdir(path):
            filename = os.path.join(path, item)
            Log.e(self.TAG, 'deleting %s' % (filename, ))
            self.deleteFileFolder(filename)

    def deleteFileFolder(self, src):
        '''delete files and folders'''
        if os.path.isfile(src):
            try:
                os.remove(src)
            except:
                Log.e(self.TAG, 'delete [%s] failed...' % (src, ))
        elif os.path.isdir(src):
            for item in os.listdir(src):
                itemsrc=os.path.join(src,item)
                self.deleteFileFolder(itemsrc)
            try:
                os.rmdir(src)
            except:
                Log.e(self.TAG, 'delete [%s] failed...' % (src, ))

    def rename(self, id, title = ''):
        if len(title) < 1:
            title = self.persist.getTitle(id)
        path = os.path.join(os.path.curdir, 'books', 'new', id+'.pdf')
        newPath = os.path.join(os.path.curdir, 'books', 'new', title+'.pdf')
        if os.path.exists(path):
            os.rename(path, newPath)

    def renameAll(self):
        path = os.path.join(os.path.curdir, 'books', 'new')
        for item in os.listdir(path):
            bid, extname = os.path.splitext(item)
            title = self.persist.getTitle(bid)
            if title:
                newName = '%s%s' % (title, extname)
                os.rename(os.path.join(path, item), os.path.join(path, newName))
                Log.i(self.TAG, '%s -> %s' % (item, newName))

    def openNewFolder(self):
        path = os.path.join(os.path.curdir, 'books', 'new')
        self.openInNewTab(path)

    @staticmethod
    def ensureDir(path):
        '''check dir exist or not, create it if not exist'''
        if not os.path.exists(path):
            os.mkdir(path)

    @staticmethod
    def merge(id):
        '''merge pdf files in tmp/${id}, to books/new/${id}.pdf'''
        srcPath = os.path.join(os.path.curdir, 'tmp', id)
        destPath = os.path.join(os.path.curdir, 'books', 'new', id+'.pdf')
        DuoPdf.clean(srcPath)   # clean pdf
        DuoPdf.merge(destPath, srcPath)

    @staticmethod
    def mergeSingle(src):
        if not os.path.isdir(src):
            Log.w(Duokan.__name__, '[%s] is not a diractory, exit...' % (src, ))
            return
        path = os.path.split(src)
        id = path[1]
        destPath = os.path.join(path[0], id+'.pdf')
        DuoPdf.clean(src)
        DuoPdf.merge(destPath, src)

    @staticmethod
    def crop(id):
        '''crop pdf file in books/new/${id}.pdf'''
        srcPath = os.path.join(os.path.curdir, 'books', 'new', id+'.pdf')
        destPath = os.path.join(os.path.curdir, 'books', 'new', id+'.cropped.pdf')
        DuoPdf.cropWH(destPath, srcPath, 500, 666)
        os.remove(srcPath)
        os.rename(destPath, srcPath)

    @staticmethod
    def cropSingle(src):
        '''crop pdf file'''
        srcPath, ext = os.path.splitext(src)
        destPath = srcPath + '_c' + ext
        DuoPdf.cropWH(destPath, src, 500, 666)

    @staticmethod
    def crop4Print(src):
        '''crop blank edge except first page'''
        srcPath, ext = os.path.splitext(src)
        destPath = srcPath + '_p' + ext
        # print destPath
        DuoPdf.crop2(destPath, src, (0, 12, 48, 12), (48, 12, 0, 12))

    @staticmethod
    def crop4Kindle(src):
        '''crop blank edge'''
        srcPath, ext = os.path.splitext(src)
        destPath = srcPath + '_k' + ext
        # print destPath
        DuoPdf.crop(destPath, src, 50, 12, 50, 12)

    @staticmethod
    def crop4Nook(src):
        '''crop blank edge'''
        srcPath, ext = os.path.splitext(src)
        destPath = srcPath + '_n' + ext
        # print destPath
        DuoPdf.crop(destPath, src, 56, 40, 56, 40)

    def addBook(self, id, title, author, link):
        return self.persist.addBook(id, title, author, link)

    def isDownload(self, id):
        return self.persist.isDownload(id)

    def setDownload(self, id):
        self.persist.setDownload(id)

class Downloader(Commading):
    EVT_LOG = 11
    EVT_PROG = 12
    EVT_START = Commading.ON_START
    EVT_STOP = 14

    def __init__(self, bid, name, proxyHost='', proxyAuthUser='', proxyAuthPswd=''):
        '''phantomjs --proxy=host --proxy-auth=username:password duokan.js %1 %ddd%/%2 4'''
        self.TAG = Downloader.__name__
        cmd = ['plugin/phantomjs',]
        if len(proxyHost) > 0:
            cmd.append('--proxy=%s' % (proxyHost, ))
            if len(proxyAuthUser) > 0 and len(proxyAuthPswd):
                cmd.append('--proxy-auth=%s:%s' % (proxyAuthUser, proxyAuthPswd))
        cmd.append('--disk-cache=true')         # enable cache to speed up downloading
        cmd.append('--disk-cache-path=cache')   # set cache path
        # cmd.append('--debug=true')
        cmd.append('duokan.js')
        cmd.append(bid)
        cmd.append('tmp/%s' % (name, ))
        cmd.append('4')

        print cmd

        Commading.__init__(self, cmd)
        self.init([Downloader.EVT_LOG, Downloader.EVT_PROG, Downloader.EVT_START, Downloader.EVT_STOP])
        self.bind(Commading.ON_LOG, self.onLog)
        self.bind(Commading.ON_STOP, self.onStop)
        self.persist = Persist()
        self.id = bid

    def onStop(self, event):
        Log.i(self.TAG, 'phantomjs finished...')
        self.persist.setDownload(self.id)
        Duokan.merge(self.id)
        Log.i(self.TAG, 'merged pdf...')
        Duokan.crop(self.id)
        Log.i(self.TAG, 'croped pdf...')
        self.dispatch(Downloader.EVT_STOP)

    def onLog(self, event, str):
        # self.hdl.cbLog(str)
        self.dispatch(Downloader.EVT_LOG, str)
        prefix = 'progress, '
        if str.startswith(prefix):
            str = str[len(prefix):]
            str = str.lstrip('\n').lstrip('\r')
            str = str.split('/')
            prog = int(str[0]) * 100 / int(str[1])
            # self.hdl.cbProgress(prog)
            self.dispatch(Downloader.EVT_PROG, prog)

class Config:
    KEY_PROXY = 'proxy'
    KEY_PROXY_HOST = 'host'
    KEY_PROXY_USER = 'user'
    KEY_PROXY_PAWD = 'pswd'

    def __init__(self, name = 'config.conf'):
        self.TAG = Config.__name__
        self.conf = ConfigParser.ConfigParser()
        self.conf.read(name)

        self._getProxy()

    def _getProxy(self):
        self.host = ''
        self.user = ''
        self.pswd = ''
        try:
            self.host = self.conf.get(Config.KEY_PROXY, Config.KEY_PROXY_HOST)
            self.user = self.conf.get(Config.KEY_PROXY, Config.KEY_PROXY_USER)
            self.pswd = self.conf.get(Config.KEY_PROXY, Config.KEY_PROXY_PAWD)
        except:
            Log.w(self.TAG, 'read proxy failed')
            traceback.print_exc()

    def getProxy(self):
        return (self.host, self.user, self.pswd)


open in browser with new tab clean the tmp dir delete files and folders check dir exist or not, create it if not exist merge pdf files in tmp/${id}, to books/new/${id}.pdf # clean pdf crop pdf file in books/new/${id}.pdf crop pdf file crop blank edge except first page # print destPath crop blank edge # print destPath crop blank edge # print destPath phantomjs --proxy=host --proxy-auth=username:password duokan.js %1 %ddd%/%2 4 # enable cache to speed up downloading # set cache path # cmd.append('--debug=true') # self.hdl.cbLog(str) # self.hdl.cbProgress(prog)