mirror of
https://github.com/ciromattia/kcc
synced 2025-12-12 17:26:23 +00:00
Let 7-Zip handle all archive operations
This commit is contained in:
@@ -160,7 +160,6 @@ This script born as a cross-platform alternative to `KindleComicParser` by **Dc5
|
|||||||
The app relies and includes the following scripts:
|
The app relies and includes the following scripts:
|
||||||
|
|
||||||
- `DualMetaFix` script by **K. Hendricks**. Released with GPL-3 License.
|
- `DualMetaFix` script by **K. Hendricks**. Released with GPL-3 License.
|
||||||
- `rarfile.py` script © 2005-2014 **Marko Kreen** <markokr@gmail.com>. Released with ISC License.
|
|
||||||
- `image.py` class from **Alex Yatskov**'s [Mangle](https://github.com/FooSoft/mangle/) with subsequent [proDOOMman](https://github.com/proDOOMman/Mangle)'s and [Birua](https://github.com/Birua/Mangle)'s patches.
|
- `image.py` class from **Alex Yatskov**'s [Mangle](https://github.com/FooSoft/mangle/) with subsequent [proDOOMman](https://github.com/proDOOMman/Mangle)'s and [Birua](https://github.com/Birua/Mangle)'s patches.
|
||||||
- Icon is by **Nikolay Verin** ([http://ncrow.deviantart.com/](http://ncrow.deviantart.com/)) and released under [CC BY-NC-SA 3.0](http://creativecommons.org/licenses/by-nc-sa/3.0/) License.
|
- Icon is by **Nikolay Verin** ([http://ncrow.deviantart.com/](http://ncrow.deviantart.com/)) and released under [CC BY-NC-SA 3.0](http://creativecommons.org/licenses/by-nc-sa/3.0/) License.
|
||||||
|
|
||||||
|
|||||||
4
kcc.iss
4
kcc.iss
@@ -47,8 +47,8 @@ Name: "CB7association"; Description: "CB7"; GroupDescription: "File associations
|
|||||||
Source: "dist\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
|
Source: "dist\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
Source: "LICENSE.txt"; DestDir: "{app}"; Flags: ignoreversion solidbreak
|
Source: "LICENSE.txt"; DestDir: "{app}"; Flags: ignoreversion solidbreak
|
||||||
Source: "other\windows\Additional-LICENSE.txt"; DestDir: "{app}"; Flags: ignoreversion
|
Source: "other\windows\Additional-LICENSE.txt"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
Source: "other\windows\UnRAR.exe"; DestDir: "{app}"; Flags: ignoreversion
|
Source: "other\windows\7z.exe"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
Source: "other\windows\7za.exe"; DestDir: "{app}"; Flags: ignoreversion
|
Source: "other\windows\7z.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
|
|
||||||
[Icons]
|
[Icons]
|
||||||
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
|
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ class VersionThread(QtCore.QThread):
|
|||||||
move(path[0], path[0] + '.exe')
|
move(path[0], path[0] + '.exe')
|
||||||
MW.hideProgressBar.emit()
|
MW.hideProgressBar.emit()
|
||||||
MW.modeConvert.emit(1)
|
MW.modeConvert.emit(1)
|
||||||
Popen(path[0] + '.exe /SP- /silent /noicons', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
|
Popen(path[0] + '.exe /SP- /silent /noicons', stdout=PIPE, stderr=STDOUT, shell=True)
|
||||||
MW.forceShutdown.emit()
|
MW.forceShutdown.emit()
|
||||||
except Exception:
|
except Exception:
|
||||||
MW.addMessage.emit('Failed to download the update!', 'warning', False)
|
MW.addMessage.emit('Failed to download the update!', 'warning', False)
|
||||||
@@ -238,6 +238,7 @@ class WorkerThread(QtCore.QThread):
|
|||||||
MW.addTrayMessage.emit('Conversion interrupted.', 'Critical')
|
MW.addTrayMessage.emit('Conversion interrupted.', 'Critical')
|
||||||
MW.modeConvert.emit(1)
|
MW.modeConvert.emit(1)
|
||||||
|
|
||||||
|
# noinspection PyUnboundLocalVariable
|
||||||
def run(self):
|
def run(self):
|
||||||
MW.modeConvert.emit(0)
|
MW.modeConvert.emit(0)
|
||||||
|
|
||||||
@@ -477,20 +478,11 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
|
|||||||
if self.needClean:
|
if self.needClean:
|
||||||
self.needClean = False
|
self.needClean = False
|
||||||
GUI.jobList.clear()
|
GUI.jobList.clear()
|
||||||
if self.UnRAR:
|
if self.sevenzip:
|
||||||
if self.sevenza:
|
fnames = QtWidgets.QFileDialog.getOpenFileNames(MW, 'Select file', self.lastPath,
|
||||||
fnames = QtWidgets.QFileDialog.getOpenFileNames(MW, 'Select file', self.lastPath,
|
'Comic (*.cbz *.cbr *.cb7 *.zip *.rar *.7z *.pdf)')
|
||||||
'Comic (*.cbz *.cbr *.cb7 *.zip *.rar *.7z *.pdf)')
|
|
||||||
else:
|
|
||||||
fnames = QtWidgets.QFileDialog.getOpenFileNames(MW, 'Select file', self.lastPath,
|
|
||||||
'Comic (*.cbz *.cbr *.zip *.rar *.pdf)')
|
|
||||||
else:
|
else:
|
||||||
if self.sevenza:
|
fnames = QtWidgets.QFileDialog.getOpenFileNames(MW, 'Select file', self.lastPath, 'Comic (*.pdf)')
|
||||||
fnames = QtWidgets.QFileDialog.getOpenFileNames(MW, 'Select file', self.lastPath,
|
|
||||||
'Comic (*.cbz *.cb7 *.zip *.7z *.pdf)')
|
|
||||||
else:
|
|
||||||
fnames = QtWidgets.QFileDialog.getOpenFileNames(MW, 'Select file', self.lastPath,
|
|
||||||
'Comic (*.cbz *.zip *.pdf)')
|
|
||||||
for fname in fnames[0]:
|
for fname in fnames[0]:
|
||||||
if fname != '':
|
if fname != '':
|
||||||
if sys.platform.startswith('win'):
|
if sys.platform.startswith('win'):
|
||||||
@@ -509,20 +501,12 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
|
|||||||
sname = sname.replace('/', '\\')
|
sname = sname.replace('/', '\\')
|
||||||
self.lastPath = os.path.abspath(sname)
|
self.lastPath = os.path.abspath(sname)
|
||||||
else:
|
else:
|
||||||
if self.UnRAR:
|
if self.sevenzip:
|
||||||
if self.sevenza:
|
fname = QtWidgets.QFileDialog.getOpenFileName(MW, 'Select file', self.lastPath,
|
||||||
fname = QtWidgets.QFileDialog.getOpenFileName(MW, 'Select file', self.lastPath,
|
'Comic (*.cbz *.cbr *.cb7)')
|
||||||
'Comic (*.cbz *.cbr *.cb7)')
|
|
||||||
else:
|
|
||||||
fname = QtWidgets.QFileDialog.getOpenFileName(MW, 'Select file', self.lastPath,
|
|
||||||
'Comic (*.cbz *.cbr)')
|
|
||||||
else:
|
else:
|
||||||
if self.sevenza:
|
fname = ['']
|
||||||
fname = QtWidgets.QFileDialog.getOpenFileName(MW, 'Select file', self.lastPath,
|
self.showDialog("Editor is disabled due to a lack of 7z.", 'error')
|
||||||
'Comic (*.cbz *.cb7)')
|
|
||||||
else:
|
|
||||||
fname = QtWidgets.QFileDialog.getOpenFileName(MW, 'Select file', self.lastPath,
|
|
||||||
'Comic (*.cbz)')
|
|
||||||
if fname[0] != '':
|
if fname[0] != '':
|
||||||
if sys.platform.startswith('win'):
|
if sys.platform.startswith('win'):
|
||||||
sname = fname[0].replace('/', '\\')
|
sname = fname[0].replace('/', '\\')
|
||||||
@@ -812,11 +796,9 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
|
|||||||
if self.needClean:
|
if self.needClean:
|
||||||
self.needClean = False
|
self.needClean = False
|
||||||
GUI.jobList.clear()
|
GUI.jobList.clear()
|
||||||
formats = ['.cbz', '.zip', '.pdf']
|
formats = ['.pdf']
|
||||||
if self.UnRAR:
|
if self.sevenzip:
|
||||||
formats.extend(['.cbr', '.rar'])
|
formats.extend(['.cb7', '.7z', '.cbz', '.zip', '.cbr', '.rar'])
|
||||||
if self.sevenza:
|
|
||||||
formats.extend(['.cb7', '.7z'])
|
|
||||||
if os.path.isdir(message):
|
if os.path.isdir(message):
|
||||||
GUI.jobList.addItem(message)
|
GUI.jobList.addItem(message)
|
||||||
GUI.jobList.scrollToBottom()
|
GUI.jobList.scrollToBottom()
|
||||||
@@ -852,10 +834,11 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
|
|||||||
os.chmod('/usr/local/bin/kindlegen', 0o755)
|
os.chmod('/usr/local/bin/kindlegen', 0o755)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
kindleGenExitCode = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
|
kindleGenExitCode = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, shell=True)
|
||||||
if kindleGenExitCode.wait() == 0:
|
kindleGenExitCode.communicate()
|
||||||
|
if kindleGenExitCode.returncode == 0:
|
||||||
self.kindleGen = True
|
self.kindleGen = True
|
||||||
versionCheck = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
|
versionCheck = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, shell=True)
|
||||||
for line in versionCheck.stdout:
|
for line in versionCheck.stdout:
|
||||||
line = line.decode("utf-8")
|
line = line.decode("utf-8")
|
||||||
if 'Amazon kindlegen' in line:
|
if 'Amazon kindlegen' in line:
|
||||||
@@ -1002,22 +985,14 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
|
|||||||
self.addMessage('Since you are a new user of <b>KCC</b> please see few '
|
self.addMessage('Since you are a new user of <b>KCC</b> please see few '
|
||||||
'<a href="https://github.com/ciromattia/kcc/wiki/Important-tips">important tips</a>.',
|
'<a href="https://github.com/ciromattia/kcc/wiki/Important-tips">important tips</a>.',
|
||||||
'info')
|
'info')
|
||||||
rarExitCode = Popen('unrar', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
|
process = Popen('7z', stdout=PIPE, stderr=STDOUT, shell=True)
|
||||||
rarExitCode = rarExitCode.wait()
|
process.communicate()
|
||||||
if rarExitCode == 0 or rarExitCode == 1 or rarExitCode == 7:
|
if process.returncode == 0 or process.returncode == 7:
|
||||||
self.UnRAR = True
|
self.sevenzip = True
|
||||||
else:
|
else:
|
||||||
self.UnRAR = False
|
self.sevenzip = False
|
||||||
self.addMessage('Cannot find <a href="http://www.rarlab.com/rar_add.htm">UnRAR</a>!'
|
self.addMessage('Cannot find <a href="http://www.7-zip.org/download.html">7z</a>!'
|
||||||
' Processing of CBR/RAR files will be disabled.', 'warning')
|
' Processing of archives will be disabled.', 'warning')
|
||||||
sevenzaExitCode = Popen('7za', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
|
|
||||||
sevenzaExitCode = sevenzaExitCode.wait()
|
|
||||||
if sevenzaExitCode == 0 or sevenzaExitCode == 7:
|
|
||||||
self.sevenza = True
|
|
||||||
else:
|
|
||||||
self.sevenza = False
|
|
||||||
self.addMessage('Cannot find <a href="http://www.7-zip.org/download.html">7za</a>!'
|
|
||||||
' Processing of CB7/7Z files will be disabled.', 'warning')
|
|
||||||
self.detectKindleGen(True)
|
self.detectKindleGen(True)
|
||||||
|
|
||||||
APP.messageFromOtherInstance.connect(self.handleMessage)
|
APP.messageFromOtherInstance.connect(self.handleMessage)
|
||||||
@@ -1098,7 +1073,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
|
|||||||
class KCCGUI_MetaEditor(KCC_ui_editor.Ui_editorDialog):
|
class KCCGUI_MetaEditor(KCC_ui_editor.Ui_editorDialog):
|
||||||
def loadData(self, file):
|
def loadData(self, file):
|
||||||
self.parser = metadata.MetadataParser(file)
|
self.parser = metadata.MetadataParser(file)
|
||||||
if self.parser.compressor == 'rar':
|
if self.parser.format == 'RAR':
|
||||||
self.editorWidget.setEnabled(False)
|
self.editorWidget.setEnabled(False)
|
||||||
self.okButton.setEnabled(False)
|
self.okButton.setEnabled(False)
|
||||||
self.statusLabel.setText('CBR metadata are read-only.')
|
self.statusLabel.setText('CBR metadata are read-only.')
|
||||||
|
|||||||
@@ -1,89 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
|
||||||
# Copyright (c) 2013-2018 Pawel Jastrzebski <pawelj@iosphe.re>
|
|
||||||
#
|
|
||||||
# Permission to use, copy, modify, and/or distribute this software for
|
|
||||||
# any purpose with or without fee is hereby granted, provided that the
|
|
||||||
# above copyright notice and this permission notice appear in all
|
|
||||||
# copies.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
|
||||||
# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
|
||||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
|
||||||
# AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
|
|
||||||
# OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
||||||
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
||||||
# PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
import os
|
|
||||||
from zipfile import is_zipfile, ZipFile
|
|
||||||
from subprocess import STDOUT, PIPE
|
|
||||||
from psutil import Popen
|
|
||||||
from shutil import move
|
|
||||||
from . import rarfile
|
|
||||||
from .shared import check7ZFile as is_7zfile
|
|
||||||
|
|
||||||
|
|
||||||
class CBxArchive:
|
|
||||||
def __init__(self, fname):
|
|
||||||
self.fname = fname
|
|
||||||
if is_zipfile(fname):
|
|
||||||
self.compressor = 'zip'
|
|
||||||
elif rarfile.is_rarfile(fname):
|
|
||||||
self.compressor = 'rar'
|
|
||||||
elif is_7zfile(fname):
|
|
||||||
self.compressor = '7z'
|
|
||||||
else:
|
|
||||||
self.compressor = None
|
|
||||||
|
|
||||||
def isCbxFile(self):
|
|
||||||
return self.compressor is not None
|
|
||||||
|
|
||||||
def extractCBZ(self, targetdir):
|
|
||||||
cbzFile = ZipFile(self.fname)
|
|
||||||
filelist = []
|
|
||||||
for f in cbzFile.namelist():
|
|
||||||
if f.startswith('__MACOSX') or f.endswith('.DS_Store') or f.endswith('humbs.db'):
|
|
||||||
pass
|
|
||||||
elif f.endswith('/'):
|
|
||||||
os.makedirs(os.path.join(targetdir, f), exist_ok=True)
|
|
||||||
else:
|
|
||||||
filelist.append(f)
|
|
||||||
cbzFile.extractall(targetdir, filelist)
|
|
||||||
|
|
||||||
def extractCBR(self, targetdir):
|
|
||||||
cbrFile = rarfile.RarFile(self.fname)
|
|
||||||
cbrFile.extractall(targetdir)
|
|
||||||
for root, _, filenames in os.walk(targetdir):
|
|
||||||
for filename in filenames:
|
|
||||||
if filename.startswith('__MACOSX') or filename.endswith('.DS_Store') or filename.endswith('humbs.db'):
|
|
||||||
os.remove(os.path.join(root, filename))
|
|
||||||
|
|
||||||
def extractCB7(self, targetdir):
|
|
||||||
output = Popen('7za x "' + self.fname + '" -xr!__MACOSX -xr!.DS_Store -xr!thumbs.db -xr!Thumbs.db -o"' +
|
|
||||||
targetdir + '"', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
|
|
||||||
extracted = False
|
|
||||||
for line in output.stdout:
|
|
||||||
if b"Everything is Ok" in line:
|
|
||||||
extracted = True
|
|
||||||
if not extracted:
|
|
||||||
raise OSError
|
|
||||||
|
|
||||||
def extract(self, targetdir):
|
|
||||||
if self.compressor == 'rar':
|
|
||||||
self.extractCBR(targetdir)
|
|
||||||
elif self.compressor == 'zip':
|
|
||||||
self.extractCBZ(targetdir)
|
|
||||||
elif self.compressor == '7z':
|
|
||||||
self.extractCB7(targetdir)
|
|
||||||
adir = os.listdir(targetdir)
|
|
||||||
if 'ComicInfo.xml' in adir:
|
|
||||||
adir.remove('ComicInfo.xml')
|
|
||||||
if len(adir) == 1 and os.path.isdir(os.path.join(targetdir, adir[0])):
|
|
||||||
for f in os.listdir(os.path.join(targetdir, adir[0])):
|
|
||||||
move(os.path.join(targetdir, adir[0], f), targetdir)
|
|
||||||
os.rmdir(os.path.join(targetdir, adir[0]))
|
|
||||||
return targetdir
|
|
||||||
@@ -45,7 +45,7 @@ except ImportError:
|
|||||||
from .shared import md5Checksum, getImageFileName, walkSort, walkLevel, sanitizeTrace
|
from .shared import md5Checksum, getImageFileName, walkSort, walkLevel, sanitizeTrace
|
||||||
from . import comic2panel
|
from . import comic2panel
|
||||||
from . import image
|
from . import image
|
||||||
from . import cbxarchive
|
from . import comicarchive
|
||||||
from . import pdfjpgextract
|
from . import pdfjpgextract
|
||||||
from . import dualmetafix
|
from . import dualmetafix
|
||||||
from . import metadata
|
from . import metadata
|
||||||
@@ -597,16 +597,12 @@ def getWorkFolder(afile):
|
|||||||
raise UserWarning("Failed to extract images from PDF file.")
|
raise UserWarning("Failed to extract images from PDF file.")
|
||||||
else:
|
else:
|
||||||
workdir = mkdtemp('', 'KCC-')
|
workdir = mkdtemp('', 'KCC-')
|
||||||
cbx = cbxarchive.CBxArchive(afile)
|
try:
|
||||||
if cbx.isCbxFile():
|
cbx = comicarchive.ComicArchive(afile)
|
||||||
try:
|
path = cbx.extract(workdir)
|
||||||
path = cbx.extract(workdir)
|
except OSError as e:
|
||||||
except Exception:
|
|
||||||
rmtree(workdir, True)
|
|
||||||
raise UserWarning("Failed to extract archive.")
|
|
||||||
else:
|
|
||||||
rmtree(workdir, True)
|
rmtree(workdir, True)
|
||||||
raise UserWarning("Failed to detect archive format.")
|
raise UserWarning(e.strerror)
|
||||||
else:
|
else:
|
||||||
raise UserWarning("Failed to open source file/directory.")
|
raise UserWarning("Failed to open source file/directory.")
|
||||||
sanitizePermissions(path)
|
sanitizePermissions(path)
|
||||||
@@ -1054,21 +1050,17 @@ def checkOptions():
|
|||||||
|
|
||||||
def checkTools(source):
|
def checkTools(source):
|
||||||
source = source.upper()
|
source = source.upper()
|
||||||
if source.endswith('.CBR') or source.endswith('.RAR'):
|
if source.endswith('.CB7') or source.endswith('.7Z') or source.endswith('.RAR') or source.endswith('.CBR') or \
|
||||||
rarExitCode = Popen('unrar', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
|
source.endswith('.ZIP') or source.endswith('.CBZ'):
|
||||||
rarExitCode = rarExitCode.wait()
|
process = Popen('7z', stdout=PIPE, stderr=STDOUT, shell=True)
|
||||||
if rarExitCode != 0 and rarExitCode != 1 and rarExitCode != 7:
|
process.communicate()
|
||||||
print('ERROR: UnRAR is missing!')
|
if process.returncode != 0 and process.returncode != 7:
|
||||||
exit(1)
|
print('ERROR: 7z is missing!')
|
||||||
elif source.endswith('.CB7') or source.endswith('.7Z'):
|
|
||||||
sevenzaExitCode = Popen('7za', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
|
|
||||||
sevenzaExitCode = sevenzaExitCode.wait()
|
|
||||||
if sevenzaExitCode != 0 and sevenzaExitCode != 7:
|
|
||||||
print('ERROR: 7za is missing!')
|
|
||||||
exit(1)
|
exit(1)
|
||||||
if options.format == 'MOBI':
|
if options.format == 'MOBI':
|
||||||
kindleGenExitCode = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
|
kindleGenExitCode = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, shell=True)
|
||||||
if kindleGenExitCode.wait() != 0:
|
kindleGenExitCode.communicate()
|
||||||
|
if kindleGenExitCode.returncode != 0:
|
||||||
print('ERROR: KindleGen is missing!')
|
print('ERROR: KindleGen is missing!')
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
@@ -1215,7 +1207,7 @@ def makeMOBIWorker(item):
|
|||||||
try:
|
try:
|
||||||
if os.path.getsize(item) < 629145600:
|
if os.path.getsize(item) < 629145600:
|
||||||
output = Popen('kindlegen -dont_append_source -locale en "' + item + '"',
|
output = Popen('kindlegen -dont_append_source -locale en "' + item + '"',
|
||||||
stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
|
stdout=PIPE, stderr=STDOUT, shell=True)
|
||||||
for line in output.stdout:
|
for line in output.stdout:
|
||||||
line = line.decode('utf-8')
|
line = line.decode('utf-8')
|
||||||
# ERROR: Generic error
|
# ERROR: Generic error
|
||||||
|
|||||||
81
kindlecomicconverter/comicarchive.py
Normal file
81
kindlecomicconverter/comicarchive.py
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
|
# Copyright (c) 2013-2018 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||||
|
#
|
||||||
|
# Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
# any purpose with or without fee is hereby granted, provided that the
|
||||||
|
# above copyright notice and this permission notice appear in all
|
||||||
|
# copies.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
# AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
|
||||||
|
# OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
# PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
#
|
||||||
|
|
||||||
|
import os
|
||||||
|
from psutil import Popen
|
||||||
|
from shutil import move
|
||||||
|
from subprocess import STDOUT, PIPE
|
||||||
|
from xml.dom.minidom import parseString
|
||||||
|
from xml.parsers.expat import ExpatError
|
||||||
|
|
||||||
|
|
||||||
|
class ComicArchive:
|
||||||
|
def __init__(self, filepath):
|
||||||
|
self.filepath = filepath
|
||||||
|
self.type = None
|
||||||
|
if not os.path.isfile(self.filepath):
|
||||||
|
raise OSError('File not found.')
|
||||||
|
process = Popen('7z l -y -p1 "' + self.filepath + '"', stderr=STDOUT, stdout=PIPE, shell=True)
|
||||||
|
for line in process.stdout:
|
||||||
|
if b'Type =' in line:
|
||||||
|
self.type = line.rstrip().decode().split(' = ')[1].upper()
|
||||||
|
break
|
||||||
|
process.communicate()
|
||||||
|
if process.returncode != 0:
|
||||||
|
raise OSError('Archive is corrupted or encrypted.')
|
||||||
|
elif self.type not in ['7Z', 'RAR', 'ZIP']:
|
||||||
|
raise OSError('Unsupported archive format.')
|
||||||
|
|
||||||
|
def extract(self, targetdir):
|
||||||
|
if not os.path.isdir(targetdir):
|
||||||
|
raise OSError('Target directory don\'t exist.')
|
||||||
|
process = Popen('7z x -y -xr!__MACOSX -xr!.DS_Store -xr!thumbs.db -xr!Thumbs.db -o"' + targetdir + '" "' +
|
||||||
|
self.filepath + '"', stdout=PIPE, stderr=STDOUT, shell=True)
|
||||||
|
process.communicate()
|
||||||
|
if process.returncode != 0:
|
||||||
|
raise OSError('Failed to extract archive.')
|
||||||
|
tdir = os.listdir(targetdir)
|
||||||
|
if 'ComicInfo.xml' in tdir:
|
||||||
|
tdir.remove('ComicInfo.xml')
|
||||||
|
if len(tdir) == 1 and os.path.isdir(os.path.join(targetdir, tdir[0])):
|
||||||
|
for f in os.listdir(os.path.join(targetdir, tdir[0])):
|
||||||
|
move(os.path.join(targetdir, tdir[0], f), targetdir)
|
||||||
|
os.rmdir(os.path.join(targetdir, tdir[0]))
|
||||||
|
return targetdir
|
||||||
|
|
||||||
|
def addFile(self, sourcefile):
|
||||||
|
if self.type == 'RAR':
|
||||||
|
raise NotImplementedError
|
||||||
|
process = Popen('7z a -y "' + self.filepath + '" "' + sourcefile + '"',
|
||||||
|
stdout=PIPE, stderr=STDOUT, shell=True)
|
||||||
|
process.communicate()
|
||||||
|
if process.returncode != 0:
|
||||||
|
raise OSError('Failed to add the file.')
|
||||||
|
|
||||||
|
def extractMetadata(self):
|
||||||
|
process = Popen('7z x -y -so "' + self.filepath + '" ComicInfo.xml',
|
||||||
|
stdout=PIPE, stderr=STDOUT, shell=True)
|
||||||
|
xml = process.communicate()
|
||||||
|
if process.returncode != 0:
|
||||||
|
raise OSError('Failed to extract archive.')
|
||||||
|
try:
|
||||||
|
return parseString(xml[0])
|
||||||
|
except ExpatError:
|
||||||
|
return None
|
||||||
@@ -19,13 +19,11 @@
|
|||||||
import os
|
import os
|
||||||
from xml.dom.minidom import parse, Document
|
from xml.dom.minidom import parse, Document
|
||||||
from re import compile
|
from re import compile
|
||||||
from zipfile import is_zipfile, ZipFile, ZIP_DEFLATED
|
|
||||||
from subprocess import STDOUT, PIPE
|
from subprocess import STDOUT, PIPE
|
||||||
from psutil import Popen
|
from psutil import Popen
|
||||||
from tempfile import mkdtemp
|
from tempfile import mkdtemp
|
||||||
from shutil import rmtree
|
from shutil import rmtree
|
||||||
from .shared import removeFromZIP, check7ZFile as is_7zfile
|
from . import comicarchive
|
||||||
from . import rarfile
|
|
||||||
|
|
||||||
|
|
||||||
class MetadataParser:
|
class MetadataParser:
|
||||||
@@ -42,47 +40,19 @@ class MetadataParser:
|
|||||||
'MUid': '',
|
'MUid': '',
|
||||||
'Bookmarks': []}
|
'Bookmarks': []}
|
||||||
self.rawdata = None
|
self.rawdata = None
|
||||||
self.compressor = None
|
self.format = None
|
||||||
if self.source.endswith('.xml') and os.path.exists(self.source):
|
if self.source.endswith('.xml') and os.path.exists(self.source):
|
||||||
self.rawdata = parse(self.source)
|
self.rawdata = parse(self.source)
|
||||||
self.parseXML()
|
self.parseXML()
|
||||||
elif not self.source.endswith('.xml'):
|
elif not self.source.endswith('.xml'):
|
||||||
if is_zipfile(self.source):
|
try:
|
||||||
self.compressor = 'zip'
|
cbx = comicarchive.ComicArchive(self.source)
|
||||||
with ZipFile(self.source) as zip_file:
|
self.rawdata = cbx.extractMetadata()
|
||||||
for member in zip_file.namelist():
|
self.format = cbx.type
|
||||||
if member != 'ComicInfo.xml':
|
except OSError as e:
|
||||||
continue
|
raise UserWarning(e.strerror)
|
||||||
with zip_file.open(member) as xml_file:
|
if self.rawdata:
|
||||||
self.rawdata = parse(xml_file)
|
self.parseXML()
|
||||||
elif rarfile.is_rarfile(self.source):
|
|
||||||
self.compressor = 'rar'
|
|
||||||
with rarfile.RarFile(self.source) as rar_file:
|
|
||||||
for member in rar_file.namelist():
|
|
||||||
if member != 'ComicInfo.xml':
|
|
||||||
continue
|
|
||||||
with rar_file.open(member) as xml_file:
|
|
||||||
self.rawdata = parse(xml_file)
|
|
||||||
elif is_7zfile(self.source):
|
|
||||||
self.compressor = '7z'
|
|
||||||
workdir = mkdtemp('', 'KCC-')
|
|
||||||
tmpXML = os.path.join(workdir, 'ComicInfo.xml')
|
|
||||||
output = Popen('7za e "' + self.source + '" ComicInfo.xml -o"' + workdir + '"',
|
|
||||||
stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
|
|
||||||
extracted = False
|
|
||||||
for line in output.stdout:
|
|
||||||
if b"Everything is Ok" in line or b"No files to process" in line:
|
|
||||||
extracted = True
|
|
||||||
if not extracted:
|
|
||||||
rmtree(workdir)
|
|
||||||
raise OSError('Failed to extract 7ZIP file.')
|
|
||||||
if os.path.isfile(tmpXML):
|
|
||||||
self.rawdata = parse(tmpXML)
|
|
||||||
rmtree(workdir)
|
|
||||||
else:
|
|
||||||
raise OSError('Failed to detect archive format.')
|
|
||||||
if self.rawdata:
|
|
||||||
self.parseXML()
|
|
||||||
|
|
||||||
def parseXML(self):
|
def parseXML(self):
|
||||||
if len(self.rawdata.getElementsByTagName('Series')) != 0:
|
if len(self.rawdata.getElementsByTagName('Series')) != 0:
|
||||||
@@ -154,20 +124,9 @@ class MetadataParser:
|
|||||||
tmpXML = os.path.join(workdir, 'ComicInfo.xml')
|
tmpXML = os.path.join(workdir, 'ComicInfo.xml')
|
||||||
with open(tmpXML, 'w', encoding='utf-8') as f:
|
with open(tmpXML, 'w', encoding='utf-8') as f:
|
||||||
self.rawdata.writexml(f, encoding='utf-8')
|
self.rawdata.writexml(f, encoding='utf-8')
|
||||||
if is_zipfile(self.source):
|
try:
|
||||||
removeFromZIP(self.source, 'ComicInfo.xml')
|
cbx = comicarchive.ComicArchive(self.source)
|
||||||
with ZipFile(self.source, mode='a', compression=ZIP_DEFLATED) as zip_file:
|
cbx.addFile(tmpXML)
|
||||||
zip_file.write(tmpXML, arcname=tmpXML.split(os.sep)[-1])
|
except OSError as e:
|
||||||
elif rarfile.is_rarfile(self.source):
|
raise UserWarning(e.strerror)
|
||||||
raise NotImplementedError
|
|
||||||
elif is_7zfile(self.source):
|
|
||||||
output = Popen('7za a "' + self.source + '" "' + tmpXML + '"',
|
|
||||||
stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
|
|
||||||
extracted = False
|
|
||||||
for line in output.stdout:
|
|
||||||
if b"Everything is Ok" in line:
|
|
||||||
extracted = True
|
|
||||||
if not extracted:
|
|
||||||
rmtree(workdir)
|
|
||||||
raise OSError('Failed to modify 7ZIP file.')
|
|
||||||
rmtree(workdir)
|
rmtree(workdir)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -24,7 +24,6 @@ from html.parser import HTMLParser
|
|||||||
from distutils.version import StrictVersion
|
from distutils.version import StrictVersion
|
||||||
from shutil import rmtree, copy
|
from shutil import rmtree, copy
|
||||||
from tempfile import mkdtemp
|
from tempfile import mkdtemp
|
||||||
from zipfile import ZipFile, ZIP_DEFLATED
|
|
||||||
from re import split
|
from re import split
|
||||||
from traceback import format_tb
|
from traceback import format_tb
|
||||||
|
|
||||||
@@ -87,26 +86,6 @@ def md5Checksum(fpath):
|
|||||||
return m.hexdigest()
|
return m.hexdigest()
|
||||||
|
|
||||||
|
|
||||||
def check7ZFile(fpath):
|
|
||||||
with open(fpath, 'rb') as fh:
|
|
||||||
header = fh.read(6)
|
|
||||||
return header == b"7z\xbc\xaf'\x1c"
|
|
||||||
|
|
||||||
|
|
||||||
def removeFromZIP(zipfname, *filenames):
|
|
||||||
tempdir = mkdtemp('', 'KCC-')
|
|
||||||
try:
|
|
||||||
tempname = os.path.join(tempdir, 'KCC.zip')
|
|
||||||
with ZipFile(zipfname, 'r') as zipread:
|
|
||||||
with ZipFile(tempname, 'w', compression=ZIP_DEFLATED) as zipwrite:
|
|
||||||
for item in zipread.infolist():
|
|
||||||
if item.filename not in filenames:
|
|
||||||
zipwrite.writestr(item, zipread.read(item.filename))
|
|
||||||
copy(tempname, zipfname)
|
|
||||||
finally:
|
|
||||||
rmtree(tempdir, True)
|
|
||||||
|
|
||||||
|
|
||||||
def sanitizeTrace(traceback):
|
def sanitizeTrace(traceback):
|
||||||
return ''.join(format_tb(traceback))\
|
return ''.join(format_tb(traceback))\
|
||||||
.replace('C:/projects/kcc/', '') \
|
.replace('C:/projects/kcc/', '') \
|
||||||
|
|||||||
@@ -30,14 +30,14 @@ def start():
|
|||||||
os.environ['QT_AUTO_SCREEN_SCALE_FACTOR'] = "1"
|
os.environ['QT_AUTO_SCREEN_SCALE_FACTOR'] = "1"
|
||||||
KCCAplication = KCC_gui.QApplicationMessaging(sys.argv)
|
KCCAplication = KCC_gui.QApplicationMessaging(sys.argv)
|
||||||
if KCCAplication.isRunning():
|
if KCCAplication.isRunning():
|
||||||
for i in range (1, len(sys.argv)):
|
for i in range(1, len(sys.argv)):
|
||||||
KCCAplication.sendMessage(sys.argv[i])
|
KCCAplication.sendMessage(sys.argv[i])
|
||||||
else:
|
else:
|
||||||
KCCAplication.sendMessage('ARISE')
|
KCCAplication.sendMessage('ARISE')
|
||||||
else:
|
else:
|
||||||
KCCWindow = KCC_gui.QMainWindowKCC()
|
KCCWindow = KCC_gui.QMainWindowKCC()
|
||||||
KCCUI = KCC_gui.KCCGUI(KCCAplication, KCCWindow)
|
KCCUI = KCC_gui.KCCGUI(KCCAplication, KCCWindow)
|
||||||
for i in range (1, len(sys.argv)):
|
for i in range(1, len(sys.argv)):
|
||||||
KCCUI.handleMessage(sys.argv[i])
|
KCCUI.handleMessage(sys.argv[i])
|
||||||
sys.exit(KCCAplication.exec_())
|
sys.exit(KCCAplication.exec_())
|
||||||
|
|
||||||
|
|||||||
BIN
other/osx/7z
Normal file
BIN
other/osx/7z
Normal file
Binary file not shown.
BIN
other/osx/7z.so
Normal file
BIN
other/osx/7z.so
Normal file
Binary file not shown.
BIN
other/osx/7za
BIN
other/osx/7za
Binary file not shown.
BIN
other/osx/unrar
BIN
other/osx/unrar
Binary file not shown.
BIN
other/windows/7z.dll
Normal file
BIN
other/windows/7z.dll
Normal file
Binary file not shown.
BIN
other/windows/7z.exe
Normal file
BIN
other/windows/7z.exe
Normal file
Binary file not shown.
Binary file not shown.
@@ -1,56 +1,22 @@
|
|||||||
****** ***** ****** UnRAR - free utility for RAR archives
|
|
||||||
** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
****** ******* ****** License for use and distribution of
|
|
||||||
** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
** ** ** ** ** ** FREEWARE version
|
|
||||||
~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
The UnRAR utility is freeware. This means:
|
|
||||||
|
|
||||||
1. All copyrights to RAR and the utility UnRAR are exclusively
|
|
||||||
owned by the author - Alexander Roshal.
|
|
||||||
|
|
||||||
2. The UnRAR utility may be freely distributed. It is allowed
|
|
||||||
to distribute UnRAR inside of other software packages.
|
|
||||||
|
|
||||||
3. THE RAR ARCHIVER AND THE UnRAR UTILITY ARE DISTRIBUTED "AS IS".
|
|
||||||
NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED. YOU USE AT
|
|
||||||
YOUR OWN RISK. THE AUTHOR WILL NOT BE LIABLE FOR DATA LOSS,
|
|
||||||
DAMAGES, LOSS OF PROFITS OR ANY OTHER KIND OF LOSS WHILE USING
|
|
||||||
OR MISUSING THIS SOFTWARE.
|
|
||||||
|
|
||||||
4. Neither RAR binary code, WinRAR binary code, UnRAR source or UnRAR
|
|
||||||
binary code may be used or reverse engineered to re-create the RAR
|
|
||||||
compression algorithm, which is proprietary, without written
|
|
||||||
permission of the author.
|
|
||||||
|
|
||||||
5. If you don't agree with terms of the license you must remove
|
|
||||||
UnRAR files from your storage devices and cease to use the
|
|
||||||
utility.
|
|
||||||
|
|
||||||
Thank you for your interest in RAR and UnRAR.
|
|
||||||
|
|
||||||
|
|
||||||
Alexander L. Roshal
|
|
||||||
|
|
||||||
7-Zip
|
7-Zip
|
||||||
~~~~~
|
~~~~~
|
||||||
License for use and distribution
|
License for use and distribution
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
7-Zip Copyright (C) 1999-2012 Igor Pavlov.
|
7-Zip Copyright (C) 1999-2018 Igor Pavlov.
|
||||||
|
|
||||||
Licenses for files are:
|
The licenses for files are:
|
||||||
|
|
||||||
1) 7z.dll: GNU LGPL + unRAR restriction
|
1) 7z.dll:
|
||||||
2) All other files: GNU LGPL
|
- The "GNU LGPL" as main license for most of the code
|
||||||
|
- The "GNU LGPL" with "unRAR license restriction" for some code
|
||||||
|
- The "BSD 3-clause License" for some code
|
||||||
|
2) All other files: the "GNU LGPL".
|
||||||
|
|
||||||
The GNU LGPL + unRAR restriction means that you must follow both
|
Redistributions in binary form must reproduce related license information from this file.
|
||||||
GNU LGPL rules and unRAR restriction rules.
|
|
||||||
|
|
||||||
|
Note:
|
||||||
Note:
|
You can use 7-Zip on any computer, including a computer in a commercial
|
||||||
You can use 7-Zip on any computer, including a computer in a commercial
|
|
||||||
organization. You don't need to register or pay for 7-Zip.
|
organization. You don't need to register or pay for 7-Zip.
|
||||||
|
|
||||||
|
|
||||||
@@ -67,21 +33,54 @@
|
|||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
Lesser General Public License for more details.
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
You can receive a copy of the GNU Lesser General Public License from
|
You can receive a copy of the GNU Lesser General Public License from
|
||||||
http://www.gnu.org/
|
http://www.gnu.org/
|
||||||
|
|
||||||
|
|
||||||
unRAR restriction
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
The decompression engine for RAR archives was developed using source
|
|
||||||
|
BSD 3-clause License
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
The "BSD 3-clause License" is used for the code in 7z.dll that implements LZFSE data decompression.
|
||||||
|
That code was derived from the code in the "LZFSE compression library" developed by Apple Inc,
|
||||||
|
that also uses the "BSD 3-clause License":
|
||||||
|
|
||||||
|
----
|
||||||
|
Copyright (c) 2015-2016, Apple Inc. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder(s) nor the names of any contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
----
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
unRAR license restriction
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
The decompression engine for RAR archives was developed using source
|
||||||
code of unRAR program.
|
code of unRAR program.
|
||||||
All copyrights to original unRAR code are owned by Alexander Roshal.
|
All copyrights to original unRAR code are owned by Alexander Roshal.
|
||||||
|
|
||||||
The license for original unRAR code has the following restriction:
|
The license for original unRAR code has the following restriction:
|
||||||
|
|
||||||
The unRAR sources cannot be used to re-create the RAR compression algorithm,
|
The unRAR sources cannot be used to re-create the RAR compression algorithm,
|
||||||
which is proprietary. Distribution of modified unRAR sources in separate form
|
which is proprietary. Distribution of modified unRAR sources in separate form
|
||||||
or as a part of other software is permitted, provided that it is clearly
|
or as a part of other software is permitted, provided that it is clearly
|
||||||
stated in the documentation and source comments that the code may
|
stated in the documentation and source comments that the code may
|
||||||
not be used to develop a RAR (WinRAR) compatible archiver.
|
not be used to develop a RAR (WinRAR) compatible archiver.
|
||||||
|
|||||||
Binary file not shown.
9
setup.py
9
setup.py
@@ -37,13 +37,12 @@ class BuildBinaryCommand(distutils.cmd.Command):
|
|||||||
VERSION = __version__
|
VERSION = __version__
|
||||||
if sys.platform == 'darwin':
|
if sys.platform == 'darwin':
|
||||||
os.system('pyinstaller -y -F -i icons/comic2ebook.icns -n "Kindle Comic Converter" -w -s kcc.py')
|
os.system('pyinstaller -y -F -i icons/comic2ebook.icns -n "Kindle Comic Converter" -w -s kcc.py')
|
||||||
shutil.copy('other/osx/7za', 'dist/Kindle Comic Converter.app/Contents/Resources')
|
shutil.copy('other/osx/7z', 'dist/Kindle Comic Converter.app/Contents/Resources')
|
||||||
shutil.copy('other/osx/unrar', 'dist/Kindle Comic Converter.app/Contents/Resources')
|
shutil.copy('other/osx/7z.so', 'dist/Kindle Comic Converter.app/Contents/Resources')
|
||||||
shutil.copy('other/osx/Info.plist', 'dist/Kindle Comic Converter.app/Contents')
|
shutil.copy('other/osx/Info.plist', 'dist/Kindle Comic Converter.app/Contents')
|
||||||
shutil.copy('LICENSE.txt', 'dist/Kindle Comic Converter.app/Contents/Resources')
|
shutil.copy('LICENSE.txt', 'dist/Kindle Comic Converter.app/Contents/Resources')
|
||||||
shutil.copy('other/windows/Additional-LICENSE.txt', 'dist/Kindle Comic Converter.app/Contents/Resources')
|
shutil.copy('other/windows/Additional-LICENSE.txt', 'dist/Kindle Comic Converter.app/Contents/Resources')
|
||||||
os.chmod('dist/Kindle Comic Converter.app/Contents/Resources/unrar', 0o777)
|
os.chmod('dist/Kindle Comic Converter.app/Contents/Resources/7z', 0o777)
|
||||||
os.chmod('dist/Kindle Comic Converter.app/Contents/Resources/7za', 0o777)
|
|
||||||
os.system('appdmg kcc.json dist/KindleComicConverter_osx_' + VERSION + '.dmg')
|
os.system('appdmg kcc.json dist/KindleComicConverter_osx_' + VERSION + '.dmg')
|
||||||
exit(0)
|
exit(0)
|
||||||
elif sys.platform == 'win32':
|
elif sys.platform == 'win32':
|
||||||
@@ -65,7 +64,7 @@ class BuildBinaryCommand(distutils.cmd.Command):
|
|||||||
'readers.\nThis app allows you to transform your PNG, JPG, GIF, '
|
'readers.\nThis app allows you to transform your PNG, JPG, GIF, '
|
||||||
'CBZ, CBR and CB7 files\ninto EPUB or MOBI format e-books.")" '
|
'CBZ, CBR and CB7 files\ninto EPUB or MOBI format e-books.")" '
|
||||||
'--url "https://kcc.iosphe.re/" --deb-priority "optional" --vendor "" '
|
'--url "https://kcc.iosphe.re/" --deb-priority "optional" --vendor "" '
|
||||||
'--category "graphics" -d "unrar | unrar-free" -d "p7zip-full" -d "libc6" usr')
|
'--category "graphics" -d "p7zip-full" -d "p7zip-rar" -d "libc6" usr')
|
||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user