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
steps:
- uses: actions/checkout@v2
- name: Compile
run: |
DOCKER_BUILDKIT=1 docker build -o final .
cp calibre-plugin/* final/stretch/
./bundle_calibre_plugin.sh
- name: Upload
uses: actions/upload-artifact@v2
with:
name: linux
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
- Debian Stretch or newer (or comparable)
- You need these packages:
- qtbase5-dev
- 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:
- libqt5core5a, libqt5network5, libzip5 (Ubuntu) / libzip4 (Debian)
- 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 traceback
import subprocess
from calibre.utils.config import config_dir # 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
self.verdir = os.path.join(self.maindir,PLUGIN_VERSION)
if not os.path.exists(self.verdir):
if iswindows:
print("Windows not supported yet")
return
elif isosx:
print("Mac not supported yet")
if iswindows or isosx:
print("Windows and MacOS not supported!")
return
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)
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():
file_path = os.path.join(self.alfdir, entry)
file_path = os.path.join(self.verdir, entry)
try:
os.remove(file_path)
except:
@ -79,8 +80,6 @@ class DeACSM(FileTypePlugin):
traceback.print_exc()
pass
# mark that this version has been initialized
os.mkdir(self.verdir)
except Exception as e:
traceback.print_exc()
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)))
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))
return path_to_ebook

View File

@ -3,6 +3,7 @@
# pyright: reportUndefinedVariable=false
import os, glob, shutil, tarfile, subprocess, time
from PyQt5.Qt import (Qt, QWidget, QHBoxLayout, QVBoxLayout, QLabel, QLineEdit,
QGroupBox, QPushButton, QListWidget, QListWidgetItem,
@ -12,10 +13,12 @@ from PyQt5 import Qt as QtGui
from zipfile import ZipFile
# 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.
from calibre_plugins.deacsm.__init__ import PLUGIN_NAME, PLUGIN_VERSION # type: ignore
import calibre_plugins.deacsm.prefs as prefs # type: ignore
from calibre.utils.config import config_dir # type: ignore
class ConfigWidget(QWidget):
@ -36,6 +39,12 @@ class ConfigWidget(QWidget):
layout = QVBoxLayout(self)
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)
layout.addWidget(ua_group_box)
@ -47,9 +56,106 @@ class ConfigWidget(QWidget):
self.txtboxUA.setText(self.tempdeacsmprefs['path_to_account_data'])
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())
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):
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