#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Calibre plugin for ACSM files. # Revision history: # v0.0.1: First version. # v0.0.2: Allow key extraction without extra binary call. from calibre.customize import FileTypePlugin # type: ignore __version__ = '0.0.2' PLUGIN_NAME = "DeACSM" PLUGIN_VERSION_TUPLE = tuple([int(x) for x in __version__.split(".")]) PLUGIN_VERSION = ".".join([str(x)for x in PLUGIN_VERSION_TUPLE]) import os, shutil import traceback import subprocess from calibre.utils.config import config_dir # type: ignore from calibre.constants import iswindows, isosx # type: ignore from calibre.gui2 import (question_dialog, error_dialog, info_dialog, choose_save_file) # type: ignore class DeACSM(FileTypePlugin): name = PLUGIN_NAME description = "Takes an Adobe ACSM file and converts that into a useable EPUB file." supported_platforms = ['linux'] author = "Leseratte10 (Plugin), Grégory Soutadé (libgourou)" version = PLUGIN_VERSION_TUPLE minimum_calibre_version = (5, 0, 0) file_types = set(['acsm']) on_import = True on_preprocess = True priority = 2000 def initialize(self): """ On initialization, make sure the libgourou code is present for compilation. """ try: self.pluginsdir = os.path.join(config_dir,"plugins") if not os.path.exists(self.pluginsdir): os.mkdir(self.pluginsdir) self.maindir = os.path.join(self.pluginsdir,"DeACSM") if not os.path.exists(self.maindir): os.mkdir(self.maindir) # 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 or isosx: print("Windows and MacOS not supported!") return else: 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 zip".format(PLUGIN_NAME, PLUGIN_VERSION)) for entry, data in lib_dict.items(): file_path = os.path.join(self.verdir, entry) try: os.remove(file_path) except: pass try: open(file_path,'wb').write(data) except: print("{0} v{1}: Exception when copying needed library files".format(PLUGIN_NAME, PLUGIN_VERSION)) traceback.print_exc() pass except Exception as e: traceback.print_exc() raise def is_customizable(self): return True def config_widget(self): import calibre_plugins.deacsm.config as config # type: ignore return config.ConfigWidget(self.plugin_path) def save_settings(self, config_widget): config_widget.save_settings() def run(self, path_to_ebook: str): # This code gets called by Calibre with a path to the new book file. # We need to check if it's an ACSM file 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) if not (os.path.exists(outputname)): error_dialog(None, "ACSM->EPUB failed", "Could not convert ACSM to EPUB:", det_msg=str(ret), show=True, show_copy_button=True) print("{0} v{1}: Failed, return original ...".format(PLUGIN_NAME, PLUGIN_VERSION)) return path_to_ebook if ("Parse PDF" in ret.stdout.decode("latin-1") or "Parse PDF" in ret.stderr.decode("latin-1")): # Looks like this is a PDF, move to PDF ... print("{0} v{1}: That's a PDF".format(PLUGIN_NAME, PLUGIN_VERSION)) outputname2 = self.temporary_file(".pdf").name os.rename(outputname, outputname2) shutil.copy(outputname2, "/tmp/test.pdf") return outputname2 return outputname