Make plugin compile itself

This commit is contained in:
Florian Bach 2021-09-20 11:24:11 +02:00
parent f0d9c07af3
commit 4f5f22a63d
7 changed files with 213 additions and 87 deletions

View File

@ -9,15 +9,16 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Compile - name: Compile
run: | run: |
DOCKER_BUILDKIT=1 docker build -o final . ./bundle_calibre_plugin.sh
cp calibre-plugin/* final/stretch/
- name: Upload - name: Upload
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v2
with: with:
name: linux name: linux
path: | path: |
final/stretch/ calibre-plugin.zip
libgourou_bundle_raw.tar.xz

View File

@ -1,67 +0,0 @@
# Clear cache:
# docker builder prune
# Build:
# DOCKER_BUILDKIT=1 docker build -o output .
# for Windows, use
# { "features": { "buildkit": true } }
# instead of the environment variable
# Build a container
#FROM debian:bullseye as main_bullseye
#ENV DEBIAN_FRONTEND="noninteractive" TZ="Europe/London"
#RUN apt-get update -y && apt-get install -y \
# git && apt-get install -y --no-install-recommends make g++ pkg-config qtbase5-dev libssl-dev libzip-dev
#
#FROM debian:buster as main_buster
#ENV DEBIAN_FRONTEND="noninteractive" TZ="Europe/London"
#RUN apt-get update -y && apt-get install -y \
# git && apt-get install -y --no-install-recommends make g++ pkg-config qtbase5-dev libssl-dev libzip-dev
FROM debian:stretch as main_stretch
ENV DEBIAN_FRONTEND="noninteractive" TZ="Europe/London"
RUN apt-get update -y && apt-get install -y \
git && apt-get install -y --no-install-recommends make g++ pkg-config qtbase5-dev libssl-dev libzip-dev
#FROM main_bullseye as compile_bullseye
#RUN git clone git://soutade.fr/libgourou.git && \
# cd libgourou && \
# make BUILD_SHARED=1 BUILD_UTILS=1
# mkdir final && \
# cp utils/acsmdownloader final/ && \
# cp utils/adept_activate final/ && \
# cp libgourou.so final/ && \
# cp /usr/lib/x86_64-linux-gnu/libzip.so.4 final/ && \
# true
#
#FROM main_buster as compile_buster
#RUN git clone git://soutade.fr/libgourou.git && \
# cd libgourou && \
# make BUILD_SHARED=1 BUILD_UTILS=1
# mkdir final && \
# cp utils/acsmdownloader final/ && \
# cp utils/adept_activate final/ && \
# cp libgourou.so final/ && \
# cp /usr/lib/x86_64-linux-gnu/libzip.so.4 final/ && \
# true
FROM main_stretch as compile_stretch
RUN git clone git://soutade.fr/libgourou.git && \
cd libgourou && \
make BUILD_SHARED=1 BUILD_UTILS=1 && \
mkdir final && \
cp utils/acsmdownloader final/ && \
cp utils/adept_activate final/ && \
cp libgourou.so final/ && \
cp /usr/lib/x86_64-linux-gnu/libzip.so.4 final/ && \
true
FROM scratch AS export-stage
#COPY --from=compile_bullseye /libgourou/final/ /bullseye/
#COPY --from=compile_buster /libgourou/final/ /buster/
COPY --from=compile_stretch /libgourou/final/ /stretch/

14
README
View File

@ -1,8 +1,10 @@
- Linux x86_64 only - Needed packages to compile (Debian Bullseye or Ubuntu 20.04): make, g++, libssl-dev, pkg-config, qtbase5-dev, libzip-dev
- Needed packages to run: Either just keep the above installed, or if you want to cleanup the dev stuff, you'll need:
- Debian Stretch or newer (or comparable) - libqt5core5a, libqt5network5, libzip5 (Ubuntu) / libzip4 (Debian)
- You need these packages:
- qtbase5-dev
- Run "package_sources.sh" to checkout source code bundle. That bundle (tar.xz) should be included in the plugin.
- Run "bundle_calibre_plugin.sh" to create the Calibre Plugin using the source code.
- In folder "libgourou", run "scripts/setup.sh" then run "make BUILD_SHARED=1 BUILD_UTILS=1"

13
bundle_calibre_plugin.sh Executable file
View File

@ -0,0 +1,13 @@
#!/bin/bash
[ ! -f libgourou_bundle_release.tar.xz ] && ./package_sources.sh
cp libgourou_bundle_release.tar.xz calibre-plugin/
pushd calibre-plugin
zip -r ../calibre-plugin.zip *
popd
rm calibre-plugin/libgourou_bundle_release.tar.xz

View File

@ -13,6 +13,7 @@ PLUGIN_VERSION = ".".join([str(x)for x in PLUGIN_VERSION_TUPLE])
import os import os
import traceback import traceback
import subprocess
from calibre.utils.config import config_dir # type: ignore from calibre.utils.config import config_dir # type: ignore
from calibre.constants import iswindows, isosx # type: ignore from calibre.constants import iswindows, isosx # type: ignore
@ -53,20 +54,20 @@ class DeACSM(FileTypePlugin):
# only continue if we've never run this version of the plugin before # only continue if we've never run this version of the plugin before
self.verdir = os.path.join(self.maindir,PLUGIN_VERSION) self.verdir = os.path.join(self.maindir,PLUGIN_VERSION)
if not os.path.exists(self.verdir): if not os.path.exists(self.verdir):
if iswindows: if iswindows or isosx:
print("Windows not supported yet") print("Windows and MacOS not supported!")
return
elif isosx:
print("Mac not supported yet")
return return
else: else:
names = ["acsmdownloader", "adept_activate", "libgourou.so", "libzip.so.4"] names = ["libgourou_bundle_release.tar.xz"]
# mark that this version has been initialized
os.mkdir(self.verdir)
lib_dict = self.load_resources(names) lib_dict = self.load_resources(names)
print("{0} v{1}: Copying needed library files from plugin's zip".format(PLUGIN_NAME, PLUGIN_VERSION)) print("{0} v{1}: Copying needed library files from plugin zip".format(PLUGIN_NAME, PLUGIN_VERSION))
for entry, data in lib_dict.items(): for entry, data in lib_dict.items():
file_path = os.path.join(self.alfdir, entry) file_path = os.path.join(self.verdir, entry)
try: try:
os.remove(file_path) os.remove(file_path)
except: except:
@ -79,8 +80,6 @@ class DeACSM(FileTypePlugin):
traceback.print_exc() traceback.print_exc()
pass pass
# mark that this version has been initialized
os.mkdir(self.verdir)
except Exception as e: except Exception as e:
traceback.print_exc() traceback.print_exc()
raise raise
@ -101,6 +100,36 @@ class DeACSM(FileTypePlugin):
print("{0} v{1}: Trying to parse file {2}".format(PLUGIN_NAME, PLUGIN_VERSION, os.path.basename(path_to_ebook))) print("{0} v{1}: Trying to parse file {2}".format(PLUGIN_NAME, PLUGIN_VERSION, os.path.basename(path_to_ebook)))
ext = os.path.splitext(path_to_ebook)[1].lower()
if (ext != ".acsm"):
print("{0} v{1}: That's not an ACSM, returning (is {2} instead)... ".format(PLUGIN_NAME, PLUGIN_VERSION, ext))
return path_to_ebook
import calibre_plugins.deacsm.prefs as prefs # type: ignore
deacsmprefs = prefs.DeACSM_Prefs()
print("{0} v{1}: Try to execute {2} ".format(PLUGIN_NAME, PLUGIN_VERSION, os.path.join(self.verdir, "acsmdownloader")))
outputname = self.temporary_file(".epub").name
my_env = os.environ.copy()
my_env["LD_LIBRARY_PATH"] = ".:" + my_env["LD_LIBRARY_PATH"]
os.chmod(os.path.join(self.verdir, "acsmdownloader"), 0o775)
ret = subprocess.run([os.path.join(self.verdir, "acsmdownloader"), "-d", os.path.join(deacsmprefs["path_to_account_data"], "device.xml"),
"-a", os.path.join(deacsmprefs["path_to_account_data"], "activation.xml"),
"-k", os.path.join(deacsmprefs["path_to_account_data"], "devicesalt"),
"-o", outputname,
"-v", "-v",
"-f", path_to_ebook ], capture_output=True, shell=False, cwd=self.verdir, env=my_env)
print(ret)
return outputname
print("{0} v{1}: Failed, return original ...".format(PLUGIN_NAME, PLUGIN_VERSION)) print("{0} v{1}: Failed, return original ...".format(PLUGIN_NAME, PLUGIN_VERSION))
return path_to_ebook return path_to_ebook

View File

@ -3,6 +3,7 @@
# pyright: reportUndefinedVariable=false # pyright: reportUndefinedVariable=false
import os, glob, shutil, tarfile, subprocess, time
from PyQt5.Qt import (Qt, QWidget, QHBoxLayout, QVBoxLayout, QLabel, QLineEdit, from PyQt5.Qt import (Qt, QWidget, QHBoxLayout, QVBoxLayout, QLabel, QLineEdit,
QGroupBox, QPushButton, QListWidget, QListWidgetItem, QGroupBox, QPushButton, QListWidget, QListWidgetItem,
@ -12,10 +13,12 @@ from PyQt5 import Qt as QtGui
from zipfile import ZipFile from zipfile import ZipFile
# calibre modules and constants. # calibre modules and constants.
from calibre.gui2 import (question_dialog, info_dialog) # type: ignore from calibre.gui2 import (question_dialog, error_dialog, info_dialog, choose_save_file) # type: ignore
# modules from this plugin's zipfile. # modules from this plugin's zipfile.
from calibre_plugins.deacsm.__init__ import PLUGIN_NAME, PLUGIN_VERSION # type: ignore from calibre_plugins.deacsm.__init__ import PLUGIN_NAME, PLUGIN_VERSION # type: ignore
import calibre_plugins.deacsm.prefs as prefs # type: ignore import calibre_plugins.deacsm.prefs as prefs # type: ignore
from calibre.utils.config import config_dir # type: ignore
class ConfigWidget(QWidget): class ConfigWidget(QWidget):
@ -36,6 +39,12 @@ class ConfigWidget(QWidget):
layout = QVBoxLayout(self) layout = QVBoxLayout(self)
self.setLayout(layout) self.setLayout(layout)
self.button_compile = QtGui.QPushButton(self)
self.button_compile.setToolTip(_("Click to compile"))
self.button_compile.setText(_("Compile"))
self.button_compile.clicked.connect(self.compile)
layout.addWidget(self.button_compile)
ua_group_box = QGroupBox(_('Path to account:'), self) ua_group_box = QGroupBox(_('Path to account:'), self)
layout.addWidget(ua_group_box) layout.addWidget(ua_group_box)
@ -47,9 +56,106 @@ class ConfigWidget(QWidget):
self.txtboxUA.setText(self.tempdeacsmprefs['path_to_account_data']) self.txtboxUA.setText(self.tempdeacsmprefs['path_to_account_data'])
ua_group_box_layout.addWidget(self.txtboxUA) ua_group_box_layout.addWidget(self.txtboxUA)
self.button_export_key = QtGui.QPushButton(self)
self.button_export_key.setText(_("Export account key"))
self.button_export_key.clicked.connect(self.export_key)
ua_group_box_layout.addWidget(self.button_export_key)
self.resize(self.sizeHint()) self.resize(self.sizeHint())
def export_key(self):
pluginsdir = os.path.join(config_dir,"plugins")
maindir = os.path.join(pluginsdir,"DeACSM")
verdir = os.path.join(maindir,PLUGIN_VERSION)
filters = [("DER Files", ["der"])]
filename = choose_save_file(self, "Export ADE keys", _("Export ADE keys"), filters, all_files=False)
print("would export to " + filename)
my_env = os.environ.copy()
my_env["LD_LIBRARY_PATH"] = ".:" + my_env["LD_LIBRARY_PATH"]
old_files = glob.glob(os.path.join(verdir, "*.der"))
for file in old_files:
try:
os.remove(file)
except:
pass
try:
os.chmod(os.path.join(verdir, "acsmdownloader"), 0o775)
except FileNotFoundError:
return error_dialog(None, "Tool not found", "Helper tool not found. Press \"Compile\" then try again.", show=True, show_copy_button=False)
ret = None
import calibre_plugins.deacsm.prefs as prefs # type: ignore
deacsmprefs = prefs.DeACSM_Prefs()
try:
ret = subprocess.run([os.path.join(verdir, "acsmdownloader"), "-d", os.path.join(deacsmprefs["path_to_account_data"], "device.xml"),
"-a", os.path.join(deacsmprefs["path_to_account_data"], "activation.xml"),
"-k", os.path.join(deacsmprefs["path_to_account_data"], "devicesalt"),
"-e"
], capture_output=True, shell=False, cwd=verdir, env=my_env)
except:
return error_dialog(None, "Export failed", "Export failed.", det_msg=str(ret), show=True, show_copy_button=True)
try:
new_key = glob.glob(os.path.join(verdir, "*.der"))[0]
shutil.move(new_key, filename)
info_dialog(None, "Done", "Key successfully exported", show=True, show_copy_button=False)
except IndexError:
return error_dialog(None, "Export failed", "Export failed.", det_msg=str(ret), show=True, show_copy_button=True)
print(ret)
def compile(self):
# Get path to source code:
pluginsdir = os.path.join(config_dir,"plugins")
maindir = os.path.join(pluginsdir,"DeACSM")
verdir = os.path.join(maindir,PLUGIN_VERSION)
# Delete old version
try:
shutil.rmtree(os.path.join(verdir, "libgourou"))
except:
pass
# extract source
with tarfile.open(os.path.join(verdir, "libgourou_bundle_release.tar.xz")) as f:
f.extractall(verdir)
# Run script, compile 1st:
os.chmod(os.path.join(verdir, "libgourou", "scripts", "setup.sh"), 0o775)
ret1 = subprocess.run([ os.path.join(verdir, "libgourou", "scripts", "setup.sh") ], capture_output=True, shell=True, cwd=os.path.join(verdir, "libgourou"))
print(ret1)
ret2 = subprocess.run([ "make", "BUILD_SHARED=1", "BUILD_UTILS=1" ], capture_output=True, shell=True, cwd=os.path.join(verdir, "libgourou"))
print(ret2)
try:
shutil.copy(os.path.join(verdir, "libgourou", "AAlibgourou.so"), verdir)
shutil.copy(os.path.join(verdir, "libgourou", "utils", "acsmdownloader"), verdir)
shutil.copy(os.path.join(verdir, "libgourou", "utils", "adept_activate"), verdir)
info_dialog(None, "Done", "Compiling successful", show=True, show_copy_button=False)
except:
print("Can't copy ...")
error_dialog(None, "Compiling failed", "Compiling failed. Did you install all dependencies?", det_msg=str(ret1) + "\n" + str(ret2), show=True, show_copy_button=True)
def save_settings(self): def save_settings(self):
self.deacsmprefs.set('path_to_account_data', self.txtboxUA.text()) self.deacsmprefs.set('path_to_account_data', self.txtboxUA.text())

42
package_sources.sh Executable file
View File

@ -0,0 +1,42 @@
#!/bin/bash
rm -rf libgourou
git clone git://soutade.fr/libgourou.git
pushd libgourou
# Pugixml
git clone https://github.com/zeux/pugixml.git lib/pugixml
pushd lib/pugixml
git checkout latest
popd
# Base64
git clone https://gist.github.com/f0fd86b6c73063283afe550bc5d77594.git lib/base64
# uPDFParser
git clone git://soutade.fr/updfparser.git lib/updfparser
popd
rm -f libgourou_bundle_raw.tar.xz 2>/dev/null
XZ_OPT=-9 tar -Jcvf libgourou_bundle_raw.tar.xz libgourou
pushd libgourou
# Delete unnecessary stuff from release archive so the file stays small.
rm -rf ./.git/
rm -rf ./lib/*/.git/
rm -rf ./lib/pugixml/docs/
# Now patch the setup file:
echo "#!/bin/bash" > scripts/setup.sh
echo "pushd lib/updfparser" >> scripts/setup.sh
echo "make BUILD_STATIC=1 BUILD_SHARED=0" >> scripts/setup.sh
echo "popd" >> scripts/setup.sh
popd
rm -f libgourou_bundle_release.tar.xz 2>/dev/null
XZ_OPT=-9 tar -Jcvf libgourou_bundle_release.tar.xz libgourou