diff --git a/Dockerfile b/Dockerfile index 8917a84..1905ed9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -51,7 +51,10 @@ RUN apk --no-cache add \ vips-jxl \ libjxl-tools \ 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. # texmf-dist-fontsextra \ diff --git a/compose.yaml b/compose.yaml index 0238bf6..82e127f 100644 --- a/compose.yaml +++ b/compose.yaml @@ -1,16 +1,16 @@ -services: - convertx: - build: - context: . - # dockerfile: Debian.Dockerfile - volumes: - - ./data:/app/data - 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) - - JWT_SECRET=aLongAndSecretStringUsedToSignTheJSONWebToken1234 # will use randomUUID() by default - - 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 - - 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 - ports: - - 3000:3000 +services: + convertx: + build: + context: . + # dockerfile: Debian.Dockerfile + volumes: + - ./data:/app/data + 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) + - JWT_SECRET=aLongAndSecretStringUsedToSignTheJSONWebToken1234 # will use randomUUID() by default + - 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 + - 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 + ports: + - 3000:3000 diff --git a/src/converters/assimp.ts b/src/converters/assimp.ts index aa87811..0ec338a 100644 --- a/src/converters/assimp.ts +++ b/src/converters/assimp.ts @@ -1,9 +1,8 @@ import { exec } from "node:child_process"; -// This could be done dynamically by running `ffmpeg -formats` and parsing the output export const properties = { from: { - muxer: [ + object: [ "3d", "3ds", "3mf", @@ -84,7 +83,7 @@ export const properties = { ], }, to: { - muxer: [ + object: [ "3ds", "3mf", "assbin", @@ -120,8 +119,6 @@ export async function convert( // eslint-disable-next-line @typescript-eslint/no-unused-vars options?: unknown, ): Promise { - // let command = "ffmpeg"; - const command = `assimp export "${filePath}" "${targetPath}"`; return new Promise((resolve, reject) => { diff --git a/src/converters/calibre.ts b/src/converters/calibre.ts new file mode 100644 index 0000000..2d368ab --- /dev/null +++ b/src/converters/calibre.ts @@ -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 { + 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"); + }); + }); +} diff --git a/src/converters/main.ts b/src/converters/main.ts index 7169cf0..e082e2a 100644 --- a/src/converters/main.ts +++ b/src/converters/main.ts @@ -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 convertImage, properties as propertiesImage } from "./vips"; 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 @@ -56,6 +57,10 @@ const properties: Record< properties: propertiesxelatex, converter: convertxelatex, }, + calibre: { + properties: propertiesCalibre, + converter: convertCalibre, + }, pandoc: { properties: propertiesPandoc, converter: convertPandoc, diff --git a/src/helpers/printVersions.ts b/src/helpers/printVersions.ts index 5372f4a..9110487 100644 --- a/src/helpers/printVersions.ts +++ b/src/helpers/printVersions.ts @@ -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) => { if (error) { console.error("Bun is not installed. wait what");