parent
447b4c5e5c
commit
03d3edfff6
6 changed files with 123 additions and 22 deletions
|
|
@ -51,7 +51,10 @@ RUN apk --no-cache add \
|
||||||
vips-jxl \
|
vips-jxl \
|
||||||
libjxl-tools \
|
libjxl-tools \
|
||||||
assimp \
|
assimp \
|
||||||
inkscape
|
inkscape \
|
||||||
|
poppler-utils
|
||||||
|
|
||||||
|
RUN apk --no-cache add calibre --repository=http://dl-cdn.alpinelinux.org/alpine/edge/testing/
|
||||||
|
|
||||||
# this might be needed for some latex use cases, will add it if needed.
|
# this might be needed for some latex use cases, will add it if needed.
|
||||||
# texmf-dist-fontsextra \
|
# texmf-dist-fontsextra \
|
||||||
|
|
|
||||||
32
compose.yaml
32
compose.yaml
|
|
@ -1,16 +1,16 @@
|
||||||
services:
|
services:
|
||||||
convertx:
|
convertx:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
# dockerfile: Debian.Dockerfile
|
# dockerfile: Debian.Dockerfile
|
||||||
volumes:
|
volumes:
|
||||||
- ./data:/app/data
|
- ./data:/app/data
|
||||||
environment: # Defaults are listed below. All are optional.
|
environment: # Defaults are listed below. All are optional.
|
||||||
- ACCOUNT_REGISTRATION=true # true or false, doesn't matter for the first account (e.g. keep this to false if you only want one account)
|
- ACCOUNT_REGISTRATION=true # true or false, doesn't matter for the first account (e.g. keep this to false if you only want one account)
|
||||||
- JWT_SECRET=aLongAndSecretStringUsedToSignTheJSONWebToken1234 # will use randomUUID() by default
|
- JWT_SECRET=aLongAndSecretStringUsedToSignTheJSONWebToken1234 # will use randomUUID() by default
|
||||||
- HTTP_ALLOWED=true # setting this to true is unsafe, only set this to true locally
|
- HTTP_ALLOWED=true # setting this to true is unsafe, only set this to true locally
|
||||||
- ALLOW_UNAUTHENTICATED=true # allows anyone to use the service without logging in, only set this to true locally
|
- ALLOW_UNAUTHENTICATED=true # allows anyone to use the service without logging in, only set this to true locally
|
||||||
- AUTO_DELETE_EVERY_N_HOURS=1 # checks every n hours for files older then n hours and deletes them, set to 0 to disable
|
- AUTO_DELETE_EVERY_N_HOURS=1 # checks every n hours for files older then n hours and deletes them, set to 0 to disable
|
||||||
- WEBROOT=/convertx # the root path of the web interface, leave empty to disable
|
# - WEBROOT=/convertx # the root path of the web interface, leave empty to disable
|
||||||
ports:
|
ports:
|
||||||
- 3000:3000
|
- 3000:3000
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
import { exec } from "node:child_process";
|
import { exec } from "node:child_process";
|
||||||
|
|
||||||
// This could be done dynamically by running `ffmpeg -formats` and parsing the output
|
|
||||||
export const properties = {
|
export const properties = {
|
||||||
from: {
|
from: {
|
||||||
muxer: [
|
object: [
|
||||||
"3d",
|
"3d",
|
||||||
"3ds",
|
"3ds",
|
||||||
"3mf",
|
"3mf",
|
||||||
|
|
@ -84,7 +83,7 @@ export const properties = {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
to: {
|
to: {
|
||||||
muxer: [
|
object: [
|
||||||
"3ds",
|
"3ds",
|
||||||
"3mf",
|
"3mf",
|
||||||
"assbin",
|
"assbin",
|
||||||
|
|
@ -120,8 +119,6 @@ export async function convert(
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
options?: unknown,
|
options?: unknown,
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
// let command = "ffmpeg";
|
|
||||||
|
|
||||||
const command = `assimp export "${filePath}" "${targetPath}"`;
|
const command = `assimp export "${filePath}" "${targetPath}"`;
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
|
|
||||||
86
src/converters/calibre.ts
Normal file
86
src/converters/calibre.ts
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
import { exec } from "node:child_process";
|
||||||
|
|
||||||
|
export const properties = {
|
||||||
|
from: {
|
||||||
|
document: [
|
||||||
|
"azw4",
|
||||||
|
"chm",
|
||||||
|
"cbr",
|
||||||
|
"cbz",
|
||||||
|
"cbt",
|
||||||
|
"cba",
|
||||||
|
"cb7",
|
||||||
|
"djvu",
|
||||||
|
"docx",
|
||||||
|
"epub",
|
||||||
|
"fb2",
|
||||||
|
"htlz",
|
||||||
|
"html",
|
||||||
|
"lit",
|
||||||
|
"lrf",
|
||||||
|
"mobi",
|
||||||
|
"odt",
|
||||||
|
"pdb",
|
||||||
|
"pdf",
|
||||||
|
"pml",
|
||||||
|
"rb",
|
||||||
|
"rtf",
|
||||||
|
"recipe",
|
||||||
|
"snb",
|
||||||
|
"tcr",
|
||||||
|
"txt",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
to: {
|
||||||
|
document: [
|
||||||
|
"azw3",
|
||||||
|
"docx",
|
||||||
|
"epub",
|
||||||
|
"fb2",
|
||||||
|
"html",
|
||||||
|
"htmlz",
|
||||||
|
"lit",
|
||||||
|
"lrf",
|
||||||
|
"mobi",
|
||||||
|
"oeb",
|
||||||
|
"pdb",
|
||||||
|
"pdf",
|
||||||
|
"pml",
|
||||||
|
"rb",
|
||||||
|
"rtf",
|
||||||
|
"snb",
|
||||||
|
"tcr",
|
||||||
|
"txt",
|
||||||
|
"txtz",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function convert(
|
||||||
|
filePath: string,
|
||||||
|
fileType: string,
|
||||||
|
convertTo: string,
|
||||||
|
targetPath: string,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
options?: unknown,
|
||||||
|
): Promise<string> {
|
||||||
|
const command = `ebook-convert "${filePath}" "${targetPath}"`;
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
exec(command, (error, stdout, stderr) => {
|
||||||
|
if (error) {
|
||||||
|
reject(`error: ${error}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stdout) {
|
||||||
|
console.log(`stdout: ${stdout}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stderr) {
|
||||||
|
console.error(`stderr: ${stderr}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve("Done");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -8,6 +8,7 @@ import { convert as convertPandoc, properties as propertiesPandoc } from "./pand
|
||||||
import { convert as convertresvg, properties as propertiesresvg } from "./resvg";
|
import { convert as convertresvg, properties as propertiesresvg } from "./resvg";
|
||||||
import { convert as convertImage, properties as propertiesImage } from "./vips";
|
import { convert as convertImage, properties as propertiesImage } from "./vips";
|
||||||
import { convert as convertxelatex, properties as propertiesxelatex } from "./xelatex";
|
import { convert as convertxelatex, properties as propertiesxelatex } from "./xelatex";
|
||||||
|
import { convert as convertCalibre, properties as propertiesCalibre } from "./calibre";
|
||||||
|
|
||||||
|
|
||||||
// This should probably be reconstructed so that the functions are not imported instead the functions hook into this to make the converters more modular
|
// This should probably be reconstructed so that the functions are not imported instead the functions hook into this to make the converters more modular
|
||||||
|
|
@ -56,6 +57,10 @@ const properties: Record<
|
||||||
properties: propertiesxelatex,
|
properties: propertiesxelatex,
|
||||||
converter: convertxelatex,
|
converter: convertxelatex,
|
||||||
},
|
},
|
||||||
|
calibre: {
|
||||||
|
properties: propertiesCalibre,
|
||||||
|
converter: convertCalibre,
|
||||||
|
},
|
||||||
pandoc: {
|
pandoc: {
|
||||||
properties: propertiesPandoc,
|
properties: propertiesPandoc,
|
||||||
converter: convertPandoc,
|
converter: convertPandoc,
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,16 @@ if (process.env.NODE_ENV === "production") {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
exec("ebook-convert --version", (error, stdout) => {
|
||||||
|
if (error) {
|
||||||
|
console.error("ebook-convert (calibre) is not installed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stdout) {
|
||||||
|
console.log(stdout.split("\n")[0]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
exec("bun -v", (error, stdout) => {
|
exec("bun -v", (error, stdout) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
console.error("Bun is not installed. wait what");
|
console.error("Bun is not installed. wait what");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue