acsm to pdf is working, removed aax for now
This commit is contained in:
parent
98faaa4579
commit
8fd6244db8
7 changed files with 98 additions and 91 deletions
57
flake.lock
57
flake.lock
|
@ -7,43 +7,26 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1633315458,
|
||||
"narHash": "sha256-CKlsbD3I+CduADnEbPZV+LD4ByQ0RiDy39F3z6DKOQc=",
|
||||
"type": "git",
|
||||
"url": "file:///home/benton/git/benpkgs"
|
||||
},
|
||||
"original": {
|
||||
"type": "git",
|
||||
"url": "file:///home/benton/git/benpkgs"
|
||||
}
|
||||
},
|
||||
"inept-epub": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1628616743,
|
||||
"narHash": "sha256-XNka+o/55SYOtDUXXOTmDvX4Qiqbaz4COq+JZ8MPoe8=",
|
||||
"lastModified": 1638237664,
|
||||
"narHash": "sha256-9SkZPl1EZ1ezWZoMdhYOzPm2HK0Ca5hkfphjlPNk/FY=",
|
||||
"owner": "BentonEdmondson",
|
||||
"repo": "inept-epub",
|
||||
"rev": "d6ba98a7159f61e7b77dc17c8c6bb62e193c8831",
|
||||
"repo": "benpkgs",
|
||||
"rev": "da71a3a488de3ae7ab8daff2c2a9354d2f0464bf",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "BentonEdmondson",
|
||||
"repo": "inept-epub",
|
||||
"repo": "benpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1633080050,
|
||||
"narHash": "sha256-T9I2WnlUzAIL70dk9V1jqaYk3nypy/cMkWR19S47ZHc=",
|
||||
"lastModified": 1638198142,
|
||||
"narHash": "sha256-plU9b8r4St6q4U7VHtG9V7oF8k9fIpfXl/KDaZLuY9k=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "82155ff501c7622cb2336646bb62f7624261f6d7",
|
||||
"rev": "8a308775674e178495767df90c419425474582a1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -53,11 +36,31 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"rmdrm": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1638240151,
|
||||
"narHash": "sha256-2FHEb4xaskyLdS5M/eILue74Idplve9g8FRxg9D1Z/4=",
|
||||
"owner": "BentonEdmondson",
|
||||
"repo": "rmdrm",
|
||||
"rev": "c60eaa0c4338be5ee6165f59f2a1816566aba8a0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "BentonEdmondson",
|
||||
"repo": "rmdrm",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"benpkgs": "benpkgs",
|
||||
"inept-epub": "inept-epub",
|
||||
"nixpkgs": "nixpkgs"
|
||||
"nixpkgs": "nixpkgs",
|
||||
"rmdrm": "rmdrm"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
20
flake.nix
20
flake.nix
|
@ -2,37 +2,37 @@
|
|||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
|
||||
inept-epub.url = "github:BentonEdmondson/inept-epub";
|
||||
inept-epub.inputs.nixpkgs.follows = "nixpkgs";
|
||||
rmdrm.url = "github:BentonEdmondson/rmdrm";
|
||||
rmdrm.inputs.nixpkgs.follows = "nixpkgs";
|
||||
|
||||
benpkgs.url = "git+file:///home/benton/git/benpkgs";
|
||||
benpkgs.url = "github:BentonEdmondson/benpkgs";
|
||||
benpkgs.inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
outputs = { self, ... }@flakes: let
|
||||
outputs = flakes: let
|
||||
nixpkgs = flakes.nixpkgs.legacyPackages.x86_64-linux;
|
||||
libgourou-utils = flakes.libgourou-utils.defaultPackage.x86_64-linux;
|
||||
inept-epub = flakes.inept-epub.defaultPackage.x86_64-linux;
|
||||
rmdrm = flakes.rmdrm.defaultPackage.x86_64-linux;
|
||||
benpkgs = flakes.benpkgs.packages.x86_64-linux;
|
||||
in {
|
||||
defaultPackage.x86_64-linux = nixpkgs.python3Packages.buildPythonApplication rec {
|
||||
pname = "knock";
|
||||
version = "1.0.0-alpha";
|
||||
version = "1.1.0-alpha";
|
||||
src = ./.;
|
||||
|
||||
nativeBuildInputs = [ nixpkgs.makeWrapper ];
|
||||
|
||||
buildInputs = [
|
||||
inept-epub
|
||||
rmdrm
|
||||
benpkgs.libgourou
|
||||
nixpkgs.ffmpeg
|
||||
];
|
||||
|
||||
propagatedBuildInputs = [
|
||||
benpkgs.Audible
|
||||
nixpkgs.python3Packages.python_magic
|
||||
nixpkgs.python3Packages.xdg
|
||||
nixpkgs.python3Packages.click
|
||||
benpkgs.Audible
|
||||
];
|
||||
|
||||
format = "other";
|
||||
|
@ -42,10 +42,10 @@
|
|||
cp lib/*.py $out/${nixpkgs.python3.sitePackages}
|
||||
cp src/knock.py $out/bin/knock
|
||||
wrapProgram $out/bin/knock --prefix PATH : ${nixpkgs.lib.makeBinPath buildInputs}
|
||||
'';
|
||||
#'';
|
||||
|
||||
meta = {
|
||||
description = "A CLI tool to convert ACSM files to DRM-free EPUB files";
|
||||
description = "A CLI tool to convert ACSM files to DRM-free EPUB/PDF files";
|
||||
homepage = "https://github.com/BentonEdmondson/knock";
|
||||
license = [ nixpkgs.lib.licenses.gpl3Only ];
|
||||
maintainers = [{
|
||||
|
|
|
@ -48,4 +48,4 @@ def handle_aax(aax_path):
|
|||
'-loglevel', 'error'
|
||||
])
|
||||
|
||||
click.secho(f'DRM-free M4B file created:\n{aax_path.with_suffix(".m4b")}', fg='green')
|
||||
click.secho(f'DRM-free M4B file created:\n{m4b_path}', fg='green')
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from xdg import xdg_config_home
|
||||
import click, sys, shutil, subprocess
|
||||
import click, sys, shutil, subprocess, magic
|
||||
from utils import run
|
||||
|
||||
def handle_acsm(acsm_path):
|
||||
|
@ -24,7 +24,7 @@ def handle_acsm(acsm_path):
|
|||
|
||||
run(
|
||||
[
|
||||
'adept-register',
|
||||
'adept_activate',
|
||||
'-u', email,
|
||||
'-O', str(adobe_dir)
|
||||
],
|
||||
|
@ -35,7 +35,7 @@ def handle_acsm(acsm_path):
|
|||
click.echo('Downloading the book from Adobe...')
|
||||
|
||||
run([
|
||||
'adept-download',
|
||||
'acsmdownloader',
|
||||
'-d', str(adobe_dir.joinpath('device.xml')),
|
||||
'-a', str(adobe_dir.joinpath('activation.xml')),
|
||||
'-k', str(adobe_dir.joinpath('devicesalt')),
|
||||
|
@ -45,11 +45,11 @@ def handle_acsm(acsm_path):
|
|||
|
||||
drm_path_type = magic.from_file(str(drm_path), mime=True)
|
||||
if drm_path_type == 'application/epub+zip':
|
||||
file_type = 'EPUB'
|
||||
file_type = 'epub'
|
||||
elif drm_path_type == 'application/pdf':
|
||||
file_type = 'PDF'
|
||||
file_type = 'pdf'
|
||||
else:
|
||||
click.echo(f'Error: Received file of media type {drm_path_type}.', err=True)
|
||||
click.echo(f'Error: Received file of media type {drm_path_type} from Adobe\' servers.', err=True)
|
||||
click.echo('Only the following ACSM conversions are currently supported:', err=True)
|
||||
click.echo(' * ACSM -> EPUB', err=True)
|
||||
click.echo(' * ACSM -> PDF', err=True)
|
||||
|
@ -57,20 +57,21 @@ def handle_acsm(acsm_path):
|
|||
click.echo(f' https://github.com/BentonEdmondson/knock/issues/new?title=Support%20{drm_path_type}%20Files&labels=enhancement', err=True)
|
||||
sys.exit(1)
|
||||
|
||||
output_file = acsm_path.with_suffix(file_type)
|
||||
if output_file.exists():
|
||||
click.echo(f"Error: {output_file} must be moved out of the way or deleted.", err=True)
|
||||
output_path = acsm_path.with_suffix('.' + file_type)
|
||||
if output_path.exists():
|
||||
drm_path.unlink()
|
||||
click.echo(f"Error: {output_path} must be moved out of the way or deleted.", err=True)
|
||||
sys.exit(1)
|
||||
|
||||
click.echo('Decrypting the file...')
|
||||
|
||||
run([
|
||||
'inept-' + file_type.lower(),
|
||||
'rmdrm-' + file_type,
|
||||
str(adobe_dir.joinpath('activation.xml')),
|
||||
str(drm_path),
|
||||
str(output_file)
|
||||
str(output_path)
|
||||
])
|
||||
|
||||
drm_path.unlink()
|
||||
|
||||
click.secho(f'DRM-free {file_type} file created:\n{output_file}', fg='green')
|
||||
click.secho(f'DRM-free {file_type.upper()} file created:\n{output_path}', fg='green')
|
|
@ -38,3 +38,8 @@ def close_fake_terminal(exit_code: int, cleanser = lambda: None):
|
|||
cleanser()
|
||||
click.echo(f'Error: Command returned error code {exit_code}.', err=True)
|
||||
sys.exit(1)
|
||||
|
||||
def verify_absence_of(file_path):
|
||||
if m4b_path.exists():
|
||||
click.echo(f"Error: {file_path} must be moved out of the way or deleted.", err=True)
|
||||
sys.exit(1)
|
45
readme.md
45
readme.md
|
@ -1,22 +1,25 @@
|
|||
# Knock
|
||||
|
||||
Convert ACSM files to DRM-free EPUB files using one command.
|
||||
Perform the following conversions with one command:
|
||||
* ACSM → EPUB
|
||||
* ACSM → PDF
|
||||
* (Soon: AAX → M4B)
|
||||
|
||||
![CLI demonstration](demo.png)
|
||||
|
||||
This software does not utilize Adobe Digital Editions nor Wine. It is completely free and open-source software written natively for Linux.
|
||||
*This software does not utilize Adobe Digital Editions nor Wine. It is completely free and open-source software written natively for Linux.*
|
||||
|
||||
## Setup and Installation
|
||||
|
||||
1. Create a free Adobe account [here](https://account.adobe.com) if you do not already have one.
|
||||
1. Install the software.
|
||||
* For NixOS, include this flake in your system `flake.nix`. Then run `knock ~/path/to/my-book.acsm` to use.
|
||||
* For NixOS users, include this flake in your system `flake.nix`. Then run `knock ~/path/to/my-book.acsm` to use.
|
||||
```nix
|
||||
inputs.knock.url = github:BentonEdmondson/knock
|
||||
outputs = { self, knock }: { /* knock.defaultPackage.x86_64-linux is the package */ }
|
||||
{
|
||||
inputs.knock.url = "github:BentonEdmondson/knock";
|
||||
outputs = { self, knock }: { /* knock.defaultPackage.x86_64-linux is the package */ };
|
||||
}
|
||||
```
|
||||
* For non-NixOS, use the latest [release](https://github.com/BentonEdmondson/knock/releases). It is large because it includes all dependencies, allowing it to run on any system with an x86_64 Linux kernel. It was built using [`nix bundle`](https://nixos.org/manual/nix/unstable/command-ref/new-cli/nix3-bundle.html). Use it by doing the following:
|
||||
1. Download `knock-version-x8664-linux` and open a terminal
|
||||
* For non-NixOS, use the latest [release](https://github.com/BentonEdmondson/knock/releases). It is large because it includes all dependencies, allowing it to run on any system with an x86_64 Linux kernel. It was built using [`nix bundle`](https://nixos.org/manual/nix/unstable/command-ref/new-cli/nix3-bundle.html). Use it by doing the following:
|
||||
1. Download `knock-version-x86_64-linux` and open a terminal
|
||||
1. Navigate to the folder within which `knock-version-x86_64-linux` resides (e.g. `cd ~/Downloads`)
|
||||
1. Run `mv knock-version-x86_64-linux knock` to rename it to `knock`
|
||||
1. Run `chmod +x knock` to make it executable
|
||||
|
@ -29,27 +32,23 @@ This software does not utilize Adobe Digital Editions nor Wine. It is completely
|
|||
sudo reboot
|
||||
```
|
||||
|
||||
1. Enter in your Adobe email and password when prompted
|
||||
1. Optionally move the executable to `~/bin` (for your user) or `/usr/local/bin/` (for all users) to allow it to run from anywhere (might not work on some distributions)
|
||||
|
||||
## Recommended Workflows
|
||||
|
||||
Before buying your ebook/audiobook, check if it is available for free on [Project Gutenberg](https://gutenberg.org/) (ebooks) or [LibriVox](https://librivox.org/) (audiobooks).
|
||||
|
||||
If you're looking for an ebook reader or audiobook player, I recommend [Foliate](https://johnfactotum.github.io/foliate/) for the former and [Cozy](https://cozy.sh/) for the latter.
|
||||
|
||||
## Verified Book Sources
|
||||
|
||||
Knock should work on any ACSM file, but it has been specifically verified to work on ACSM EPUB files from the following:
|
||||
Knock should work on any ACSM file, but it has been specifically verified to work on ACSM files from the following:
|
||||
|
||||
* [eBooks.com](https://www.ebooks.com/en-us/)
|
||||
* [Rakuten Kobo](https://www.kobo.com/us/en)
|
||||
* [Google Books](https://books.google.com/)
|
||||
* [Hugendubel.de](https://www.hugendubel.de/de/) (German)
|
||||
|
||||
The resulting EPUB file can be read with any EPUB reader.
|
||||
|
||||
## Legality
|
||||
|
||||
[It's Perfectly Legal to Tell People How to Remove DRM](https://gizmodo.com/its-perfectly-legal-to-tell-people-how-to-remove-drm-1670223538) (Gizmodo)
|
||||
|
||||
**Do not use this software for piracy; this software is not intended for piracy.** This software exists to allow readers to *legally* purchase and then legally and *freely* read ebooks. I suspect that the significant prevalence of ebook piracy is caused in large part by the restrictions put on legally purchased ebooks. This software exists to *incentivize* the legal purchase of ebooks by enabling their unrestricted and legal consumption.
|
||||
|
||||
## The Name
|
||||
|
||||
The name comes from the [D&D 5e spell](https://roll20.net/compendium/dnd5e/Knock#content) for freeing locked items:
|
||||
|
@ -65,11 +64,13 @@ The name comes from the [D&D 5e spell](https://roll20.net/compendium/dnd5e/Knock
|
|||
|
||||
## Dependencies
|
||||
|
||||
* [`libgourou-utils`](https://github.com/BentonEdmondson/libgourou-utils) for using the ACSM file to download the corresponding encrypted EPUB file from Adobe's servers
|
||||
* [`inept-epub`](https://github.com/BentonEdmondson/inept-epub/) for decrypting the EPUB file
|
||||
* [`libgourou`](http://indefero.soutade.fr/p/libgourou/) for using the ACSM file to download the corresponding encrypted EPUB/PDF file from Adobe's servers
|
||||
* [`rmdrm`](https://github.com/BentonEdmondson/rmdrm/) for decrypting the Adobe ADEPT-encrypted EPUB/PDF files
|
||||
* [`Audible`](https://github.com/mkb79/Audible) for fetching the Audible decryption key used to decrypt AAX files
|
||||
* [`ffmpeg`](https://www.ffmpeg.org/) for converting AAX files to M4B files using the Audible decryption key
|
||||
|
||||
These are already included in all releases and in the Nix flake of course.
|
||||
|
||||
## License
|
||||
|
||||
This software is licensed under GPLv3 because one of its dependencies is licensed under GPLv3.
|
||||
This software is licensed under GPLv3.
|
||||
|
|
13
src/knock.py
13
src/knock.py
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import subprocess, magic, shutil, click
|
||||
import subprocess, shutil, click
|
||||
from pathlib import Path
|
||||
from getpass import getpass
|
||||
from xdg import xdg_config_home
|
||||
|
@ -8,9 +8,6 @@ from xdg import xdg_config_home
|
|||
from handle_acsm import handle_acsm
|
||||
from handle_aax import handle_aax
|
||||
|
||||
__version__ = "1.0.0-alpha"
|
||||
|
||||
@click.version_option()
|
||||
@click.command()
|
||||
@click.argument(
|
||||
"path",
|
||||
|
@ -33,14 +30,14 @@ def main(path):
|
|||
if path_type == 'ACSM':
|
||||
click.echo('Received an ACSM (Adobe) file...')
|
||||
handle_acsm(path)
|
||||
elif path_type == 'AAX':
|
||||
click.echo('Received an AAX (Audible) file...')
|
||||
handle_aax(path)
|
||||
#elif path_type == 'AAX':
|
||||
# click.echo('Received an AAX (Audible) file...')
|
||||
# handle_aax(path)
|
||||
else:
|
||||
click.echo(f'Error: Files of type {path_type} are not supported.\n', err=True)
|
||||
click.echo('Only the following file types are currently supported:', err=True)
|
||||
click.echo(' * ACSM (Adobe)\n', err=True)
|
||||
click.echo(' * AAX (Audible)\n', err=True)
|
||||
#click.echo(' * AAX (Audible)\n', err=True)
|
||||
click.echo('Please open a feature request at:', err=True)
|
||||
click.echo(f' https://github.com/BentonEdmondson/knock/issues/new?title=Support%20{path_type}%20Files&labels=enhancement', err=True)
|
||||
sys.exit(1)
|
||||
|
|
Loading…
Reference in a new issue