mirror of
https://github.com/Leseratte10/acsm-calibre-plugin.git
synced 2024-12-22 09:19:55 +06:00
Initial commit
This commit is contained in:
commit
f0d9c07af3
23
.github/workflows/main.yml
vendored
Normal file
23
.github/workflows/main.yml
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
name: Build binaries
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
build-linux:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Compile
|
||||
run: |
|
||||
DOCKER_BUILDKIT=1 docker build -o final .
|
||||
cp calibre-plugin/* final/stretch/
|
||||
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: linux
|
||||
path: |
|
||||
final/stretch/
|
||||
|
67
Dockerfile
Normal file
67
Dockerfile
Normal file
@ -0,0 +1,67 @@
|
||||
# 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/
|
||||
|
8
README
Normal file
8
README
Normal file
@ -0,0 +1,8 @@
|
||||
- Linux x86_64 only
|
||||
|
||||
- Debian Stretch or newer (or comparable)
|
||||
|
||||
- You need these packages:
|
||||
- qtbase5-dev
|
||||
|
||||
|
108
calibre-plugin/__init__.py
Normal file
108
calibre-plugin/__init__.py
Normal file
@ -0,0 +1,108 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Calibre plugin for ACSM files.
|
||||
|
||||
|
||||
from calibre.customize import FileTypePlugin # type: ignore
|
||||
__version__ = '0.0.1'
|
||||
|
||||
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
|
||||
import traceback
|
||||
|
||||
from calibre.utils.config import config_dir # type: ignore
|
||||
from calibre.constants import iswindows, isosx # 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"
|
||||
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):
|
||||
"""
|
||||
Dynamic modules can't be imported/loaded from a zipfile.
|
||||
So this routine will extract the appropriate
|
||||
library for the target OS and copy it to the 'alfcrypto' subdirectory of
|
||||
calibre's configuration directory. That 'alfcrypto' directory is then
|
||||
inserted into the syspath (as the very first entry) in the run function
|
||||
so the CDLL stuff will work in the alfcrypto.py script.
|
||||
The extraction only happens once per version of the plugin
|
||||
Also perform upgrade of preferences once per version
|
||||
"""
|
||||
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:
|
||||
print("Windows not supported yet")
|
||||
return
|
||||
elif isosx:
|
||||
print("Mac not supported yet")
|
||||
return
|
||||
else:
|
||||
names = ["acsmdownloader", "adept_activate", "libgourou.so", "libzip.so.4"]
|
||||
|
||||
lib_dict = self.load_resources(names)
|
||||
print("{0} v{1}: Copying needed library files from plugin's zip".format(PLUGIN_NAME, PLUGIN_VERSION))
|
||||
|
||||
for entry, data in lib_dict.items():
|
||||
file_path = os.path.join(self.alfdir, 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
|
||||
|
||||
# mark that this version has been initialized
|
||||
os.mkdir(self.verdir)
|
||||
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)))
|
||||
|
||||
print("{0} v{1}: Failed, return original ...".format(PLUGIN_NAME, PLUGIN_VERSION))
|
||||
return path_to_ebook
|
||||
|
||||
|
||||
|
63
calibre-plugin/config.py
Normal file
63
calibre-plugin/config.py
Normal file
@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# pyright: reportUndefinedVariable=false
|
||||
|
||||
|
||||
from PyQt5.Qt import (Qt, QWidget, QHBoxLayout, QVBoxLayout, QLabel, QLineEdit,
|
||||
QGroupBox, QPushButton, QListWidget, QListWidgetItem,
|
||||
QAbstractItemView, QIcon, QDialog, QDialogButtonBox, QUrl)
|
||||
|
||||
from PyQt5 import Qt as QtGui
|
||||
from zipfile import ZipFile
|
||||
|
||||
# calibre modules and constants.
|
||||
from calibre.gui2 import (question_dialog, info_dialog) # 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
|
||||
|
||||
|
||||
class ConfigWidget(QWidget):
|
||||
def __init__(self, plugin_path):
|
||||
QWidget.__init__(self)
|
||||
|
||||
self.plugin_path = plugin_path
|
||||
|
||||
# get the prefs
|
||||
self.deacsmprefs = prefs.DeACSM_Prefs()
|
||||
|
||||
# make a local copy
|
||||
self.tempdeacsmprefs = {}
|
||||
self.tempdeacsmprefs['path_to_account_data'] = self.deacsmprefs['path_to_account_data']
|
||||
|
||||
|
||||
# Start Qt Gui dialog layout
|
||||
layout = QVBoxLayout(self)
|
||||
self.setLayout(layout)
|
||||
|
||||
|
||||
ua_group_box = QGroupBox(_('Path to account:'), self)
|
||||
layout.addWidget(ua_group_box)
|
||||
ua_group_box_layout = QVBoxLayout()
|
||||
ua_group_box.setLayout(ua_group_box_layout)
|
||||
|
||||
self.txtboxUA = QtGui.QLineEdit(self)
|
||||
self.txtboxUA.setToolTip(_("Enter folder path to account data"))
|
||||
self.txtboxUA.setText(self.tempdeacsmprefs['path_to_account_data'])
|
||||
ua_group_box_layout.addWidget(self.txtboxUA)
|
||||
|
||||
|
||||
self.resize(self.sizeHint())
|
||||
|
||||
|
||||
def save_settings(self):
|
||||
self.deacsmprefs.set('path_to_account_data', self.txtboxUA.text())
|
||||
self.deacsmprefs.writeprefs()
|
||||
|
||||
def load_resource(self, name):
|
||||
with ZipFile(self.plugin_path, 'r') as zf:
|
||||
if name in zf.namelist():
|
||||
return zf.read(name).decode('utf-8')
|
||||
return ""
|
||||
|
0
calibre-plugin/plugin-import-name-deacsm.txt
Normal file
0
calibre-plugin/plugin-import-name-deacsm.txt
Normal file
74
calibre-plugin/prefs.py
Normal file
74
calibre-plugin/prefs.py
Normal file
@ -0,0 +1,74 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
|
||||
# Standard Python modules.
|
||||
import os
|
||||
import traceback
|
||||
|
||||
from calibre.utils.config import JSONConfig, config_dir # type: ignore
|
||||
from calibre_plugins.deacsm.__init__ import PLUGIN_NAME # type: ignore
|
||||
from calibre.constants import isosx, islinux # type: ignore
|
||||
|
||||
|
||||
class DeACSM_Prefs():
|
||||
def __init__(self):
|
||||
JSON_PATH = os.path.join("plugins", PLUGIN_NAME.strip().lower().replace(' ', '_') + '.json')
|
||||
self.deacsmprefs = JSONConfig(JSON_PATH)
|
||||
|
||||
self.deacsmprefs.defaults['configured'] = False
|
||||
|
||||
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)
|
||||
self.accountdir = os.path.join(self.maindir,"account")
|
||||
if not os.path.exists(self.accountdir):
|
||||
os.mkdir(self.accountdir)
|
||||
|
||||
# Default to the builtin UA
|
||||
self.deacsmprefs.defaults['path_to_account_data'] = self.accountdir
|
||||
|
||||
|
||||
def __getitem__(self,kind = None):
|
||||
if kind is not None:
|
||||
return self.deacsmprefs[kind]
|
||||
return self.deacsmprefs
|
||||
|
||||
def set(self, kind, value):
|
||||
self.deacsmprefs[kind] = value
|
||||
|
||||
def writeprefs(self,value = True):
|
||||
self.deacsmprefs['configured'] = value
|
||||
|
||||
def addnamedvaluetoprefs(self, prefkind, keyname, keyvalue):
|
||||
try:
|
||||
if keyvalue not in self.deacsmprefs[prefkind].values():
|
||||
# ensure that the keyname is unique
|
||||
# by adding a number (starting with 2) to the name if it is not
|
||||
namecount = 1
|
||||
newname = keyname
|
||||
while newname in self.deacsmprefs[prefkind]:
|
||||
namecount += 1
|
||||
newname = "{0:s}_{1:d}".format(keyname,namecount)
|
||||
# add to the preferences
|
||||
self.deacsmprefs[prefkind][newname] = keyvalue
|
||||
return (True, newname)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
pass
|
||||
return (False, keyname)
|
||||
|
||||
def addvaluetoprefs(self, prefkind, prefsvalue):
|
||||
# ensure the keyvalue isn't already in the preferences
|
||||
try:
|
||||
if prefsvalue not in self.deacsmprefs[prefkind]:
|
||||
self.deacsmprefs[prefkind].append(prefsvalue)
|
||||
return True
|
||||
except:
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
Loading…
Reference in New Issue
Block a user