mirror of
https://github.com/C4illin/ConvertX.git
synced 2025-11-05 06:23:18 +00:00
Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b28977ffe2 | ||
|
|
a47bb682a5 | ||
|
|
a17eca0a09 | ||
|
|
ea9250543e | ||
|
|
317c932c2a | ||
|
|
5b1703db68 | ||
|
|
60ba7c93fb | ||
|
|
22227130dd | ||
|
|
5daf66f5d0 | ||
|
|
aee1962607 | ||
|
|
0d42762b36 | ||
|
|
b97b12b449 | ||
|
|
bdf651df82 | ||
|
|
267ef14789 | ||
|
|
905adc5e1c | ||
|
|
52ed7274e9 | ||
|
|
a29238c265 | ||
|
|
48c6fb79fc | ||
|
|
8358396656 | ||
|
|
b30e5800c3 | ||
|
|
21a1b50ed8 | ||
|
|
e6a94fb21d | ||
|
|
bef1710e33 | ||
|
|
16b322d4e6 | ||
|
|
9bf64e42d5 | ||
|
|
5988fe8212 | ||
|
|
5df9c0b751 | ||
|
|
136a8b2d74 | ||
|
|
ccfb574d5d | ||
|
|
ad6eedea69 |
7
.deepsource.toml
Normal file
7
.deepsource.toml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
version = 1
|
||||||
|
|
||||||
|
[[analyzers]]
|
||||||
|
name = "javascript"
|
||||||
|
|
||||||
|
[analyzers.meta]
|
||||||
|
environment = ["nodejs"]
|
||||||
19
CHANGELOG.md
19
CHANGELOG.md
@@ -1,5 +1,24 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [0.5.0](https://github.com/C4illin/ConvertX/compare/v0.4.1...v0.5.0) (2024-09-20)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add option to customize how often files are automatically deleted ([317c932](https://github.com/C4illin/ConvertX/commit/317c932c2a26280bf37ed3d3bf9b879413590f5a))
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* improve file name replacement logic ([60ba7c9](https://github.com/C4illin/ConvertX/commit/60ba7c93fbdc961f3569882fade7cc13dee7a7a5))
|
||||||
|
|
||||||
|
## [0.4.1](https://github.com/C4illin/ConvertX/compare/v0.4.0...v0.4.1) (2024-09-15)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* allow non lowercase true and false values, fixes [#122](https://github.com/C4illin/ConvertX/issues/122) ([bef1710](https://github.com/C4illin/ConvertX/commit/bef1710e3376baa7e25c107ded20a40d18b8c6b0))
|
||||||
|
|
||||||
## [0.4.0](https://github.com/C4illin/ConvertX/compare/v0.3.3...v0.4.0) (2024-08-26)
|
## [0.4.0](https://github.com/C4illin/ConvertX/compare/v0.3.3...v0.4.0) (2024-08-26)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM oven/bun:1.1.26-alpine AS base
|
FROM oven/bun:1.1.29-alpine AS base
|
||||||
LABEL org.opencontainers.image.source="https://github.com/C4illin/ConvertX"
|
LABEL org.opencontainers.image.source="https://github.com/C4illin/ConvertX"
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
|||||||
11
README.md
11
README.md
@@ -47,6 +47,7 @@ services:
|
|||||||
- JWT_SECRET=aLongAndSecretStringUsedToSignTheJSONWebToken1234 # will use randomUUID() by default
|
- JWT_SECRET=aLongAndSecretStringUsedToSignTheJSONWebToken1234 # will use randomUUID() by default
|
||||||
- HTTP_ALLOWED=false # setting this to true is unsafe, only set this to true locally
|
- HTTP_ALLOWED=false # setting this to true is unsafe, only set this to true locally
|
||||||
- ALLOW_UNAUTHENTICATED=false # allows anyone to use the service without logging in, only set this to true locally
|
- ALLOW_UNAUTHENTICATED=false # allows anyone to use the service without logging in, only set this to true locally
|
||||||
|
- AUTO_DELETE_EVERY_N_HOURS=24 # checks every n hours for files older then n hours and deletes them, set to 0 to disable
|
||||||
volumes:
|
volumes:
|
||||||
- convertx:/app/data
|
- convertx:/app/data
|
||||||
```
|
```
|
||||||
@@ -54,7 +55,7 @@ services:
|
|||||||
or
|
or
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run ghcr.io/c4illin/convertx -p 3000:3000 -v ./data:/app/data
|
docker run -p 3000:3000 -v ./data:/app/data ghcr.io/c4illin/convertx
|
||||||
```
|
```
|
||||||
|
|
||||||
Then visit `http://localhost:3000` in your browser and create your account. Don't leave it unconfigured and open, as anyone can register the first account.
|
Then visit `http://localhost:3000` in your browser and create your account. Don't leave it unconfigured and open, as anyone can register the first account.
|
||||||
@@ -65,6 +66,10 @@ If you get unable to open database file run `chown -R $USER:$USER path` on the p
|
|||||||
|
|
||||||
Tutorial in french: https://belginux.com/installer-convertx-avec-docker/
|
Tutorial in french: https://belginux.com/installer-convertx-avec-docker/
|
||||||
|
|
||||||
|
## Screenshots
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
0. Install [Bun](https://bun.sh/) and Git
|
0. Install [Bun](https://bun.sh/) and Git
|
||||||
@@ -76,12 +81,12 @@ Pull requests are welcome! See below and open issues for the list of todos.
|
|||||||
|
|
||||||
## Todo
|
## Todo
|
||||||
- [x] Add messages for errors in converters
|
- [x] Add messages for errors in converters
|
||||||
|
- [x] Add searchable list of formats
|
||||||
- [ ] Add options for converters
|
- [ ] Add options for converters
|
||||||
- [ ] Add more converters
|
|
||||||
- [ ] Divide index.tsx into smaller components
|
- [ ] Divide index.tsx into smaller components
|
||||||
- [ ] Add tests
|
- [ ] Add tests
|
||||||
- [ ] Add searchable list of formats
|
|
||||||
- [ ] Make the upload button nicer and more easy to drop files on. Support copy paste as well if possible.
|
- [ ] Make the upload button nicer and more easy to drop files on. Support copy paste as well if possible.
|
||||||
|
- [ ] Make errors logs visible from the web ui
|
||||||
- [ ] Add more converters:
|
- [ ] Add more converters:
|
||||||
- [ ] [deark](https://github.com/jsummers/deark)
|
- [ ] [deark](https://github.com/jsummers/deark)
|
||||||
- [ ] LibreOffice
|
- [ ] LibreOffice
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
"attributePosition": "auto"
|
"attributePosition": "auto"
|
||||||
},
|
},
|
||||||
"files": {
|
"files": {
|
||||||
"ignore": ["**/node_modules/**"]
|
"ignore": ["**/node_modules/**", "**/pico.lime.min.css"]
|
||||||
},
|
},
|
||||||
"organizeImports": { "enabled": true },
|
"organizeImports": { "enabled": true },
|
||||||
"linter": {
|
"linter": {
|
||||||
|
|||||||
BIN
images/preview.png
Normal file
BIN
images/preview.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 52 KiB |
32
package.json
32
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "convertx-frontend",
|
"name": "convertx-frontend",
|
||||||
"version": "0.4.0",
|
"version": "0.5.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "bun run --watch src/index.tsx",
|
"dev": "bun run --watch src/index.tsx",
|
||||||
"hot": "bun run --hot src/index.tsx",
|
"hot": "bun run --hot src/index.tsx",
|
||||||
@@ -14,9 +14,9 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@elysiajs/cookie": "^0.8.0",
|
"@elysiajs/cookie": "^0.8.0",
|
||||||
"@elysiajs/html": "1.0.2",
|
"@elysiajs/html": "1.0.2",
|
||||||
"@elysiajs/jwt": "^1.1.0",
|
"@elysiajs/jwt": "^1.1.1",
|
||||||
"@elysiajs/static": "1.0.3",
|
"@elysiajs/static": "1.0.3",
|
||||||
"elysia": "^1.1.7"
|
"elysia": "^1.1.12"
|
||||||
},
|
},
|
||||||
"module": "src/index.tsx",
|
"module": "src/index.tsx",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -24,32 +24,32 @@
|
|||||||
"start": "bun run src/index.tsx"
|
"start": "bun run src/index.tsx"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "1.8.3",
|
"@biomejs/biome": "1.9.2",
|
||||||
"@eslint/compat": "^1.1.1",
|
"@eslint/compat": "^1.1.1",
|
||||||
"@eslint/js": "^9.9.0",
|
"@eslint/js": "^9.9.1",
|
||||||
"@ianvs/prettier-plugin-sort-imports": "^4.3.1",
|
"@ianvs/prettier-plugin-sort-imports": "^4.3.1",
|
||||||
"@kitajs/ts-html-plugin": "^4.0.2",
|
"@kitajs/ts-html-plugin": "^4.0.2",
|
||||||
"@picocss/pico": "^2.0.6",
|
"@picocss/pico": "^2.0.6",
|
||||||
"@total-typescript/ts-reset": "^0.6.0",
|
"@total-typescript/ts-reset": "^0.6.1",
|
||||||
"@types/bun": "^1.1.6",
|
"@types/bun": "^1.1.8",
|
||||||
"@types/eslint": "^9.6.0",
|
"@types/eslint": "^9.6.1",
|
||||||
"@types/node": "^22.5.0",
|
"@types/node": "^22.5.4",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.2.0",
|
"@typescript-eslint/eslint-plugin": "^8.4.0",
|
||||||
"@typescript-eslint/parser": "^8.2.0",
|
"@typescript-eslint/parser": "^8.4.0",
|
||||||
"cpy-cli": "^5.0.0",
|
"cpy-cli": "^5.0.0",
|
||||||
"eslint": "^9.9.0",
|
"eslint": "^9.9.1",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-deprecation": "^3.0.0",
|
"eslint-plugin-deprecation": "^3.0.0",
|
||||||
"eslint-plugin-eslint-comments": "^3.2.0",
|
"eslint-plugin-eslint-comments": "^3.2.0",
|
||||||
"eslint-plugin-import": "^2.29.1",
|
"eslint-plugin-import": "^2.30.0",
|
||||||
"eslint-plugin-isaacscript": "^3.12.2",
|
"eslint-plugin-isaacscript": "^4.0.0",
|
||||||
"eslint-plugin-prettier": "^5.2.1",
|
"eslint-plugin-prettier": "^5.2.1",
|
||||||
"eslint-plugin-simple-import-sort": "^12.1.1",
|
"eslint-plugin-simple-import-sort": "^12.1.1",
|
||||||
"knip": "^5.27.3",
|
"knip": "^5.29.2",
|
||||||
"npm-run-all2": "^6.2.2",
|
"npm-run-all2": "^6.2.2",
|
||||||
"prettier": "^3.3.3",
|
"prettier": "^3.3.3",
|
||||||
"typescript": "^5.5.4",
|
"typescript": "^5.5.4",
|
||||||
"typescript-eslint": "^8.2.0"
|
"typescript-eslint": "^8.4.0"
|
||||||
},
|
},
|
||||||
"trustedDependencies": [
|
"trustedDependencies": [
|
||||||
"@biomejs/biome"
|
"@biomejs/biome"
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ export const properties = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export function convert(
|
export function convert(
|
||||||
filePath: string,
|
filePath: string,
|
||||||
fileType: string,
|
fileType: string,
|
||||||
@@ -19,23 +18,20 @@ export function convert(
|
|||||||
options?: any,
|
options?: any,
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
exec(
|
exec(`resvg "${filePath}" "${targetPath}"`, (error, stdout, stderr) => {
|
||||||
`resvg "${filePath}" "${targetPath}"`,
|
if (error) {
|
||||||
(error, stdout, stderr) => {
|
reject(`error: ${error}`);
|
||||||
if (error) {
|
}
|
||||||
reject(`error: ${error}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stdout) {
|
if (stdout) {
|
||||||
console.log(`stdout: ${stdout}`);
|
console.log(`stdout: ${stdout}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stderr) {
|
if (stderr) {
|
||||||
console.error(`stderr: ${stderr}`);
|
console.error(`stderr: ${stderr}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve("success");
|
resolve("success");
|
||||||
},
|
});
|
||||||
);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,11 +27,15 @@ const uploadsDir = "./data/uploads/";
|
|||||||
const outputDir = "./data/output/";
|
const outputDir = "./data/output/";
|
||||||
|
|
||||||
const ACCOUNT_REGISTRATION =
|
const ACCOUNT_REGISTRATION =
|
||||||
process.env.ACCOUNT_REGISTRATION === "true" || false;
|
process.env.ACCOUNT_REGISTRATION?.toLowerCase() === "true" || false;
|
||||||
|
|
||||||
const HTTP_ALLOWED = process.env.HTTP_ALLOWED === "true" || false;
|
const HTTP_ALLOWED =
|
||||||
|
process.env.HTTP_ALLOWED?.toLowerCase() === "true" || false;
|
||||||
const ALLOW_UNAUTHENTICATED =
|
const ALLOW_UNAUTHENTICATED =
|
||||||
process.env.ALLOW_UNAUTHENTICATED === "true" || false;
|
process.env.ALLOW_UNAUTHENTICATED?.toLowerCase() === "true" || false;
|
||||||
|
const AUTO_DELETE_EVERY_N_HOURS = process.env.AUTO_DELETE_EVERY_N_HOURS
|
||||||
|
? Number(process.env.AUTO_DELETE_EVERY_N_HOURS)
|
||||||
|
: 24;
|
||||||
|
|
||||||
// fileNames: fileNames,
|
// fileNames: fileNames,
|
||||||
// filesToConvert: fileNames.length,
|
// filesToConvert: fileNames.length,
|
||||||
@@ -542,9 +546,11 @@ const app = new Elysia({
|
|||||||
style={{
|
style={{
|
||||||
borderColor: "gray",
|
borderColor: "gray",
|
||||||
padding: "2px",
|
padding: "2px",
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
<header
|
<header
|
||||||
style={{ fontSize: "20px", fontWeight: "bold" }}>
|
style={{ fontSize: "20px", fontWeight: "bold" }}
|
||||||
|
safe>
|
||||||
{converter}
|
{converter}
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
@@ -566,7 +572,9 @@ const app = new Elysia({
|
|||||||
data-target={target}
|
data-target={target}
|
||||||
data-converter={converter}
|
data-converter={converter}
|
||||||
style={{ fontSize: "15px", padding: "5px" }}
|
style={{ fontSize: "15px", padding: "5px" }}
|
||||||
type="button">
|
type="button"
|
||||||
|
safe
|
||||||
|
>
|
||||||
{target}
|
{target}
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
@@ -637,8 +645,9 @@ const app = new Elysia({
|
|||||||
style={{
|
style={{
|
||||||
borderColor: "gray",
|
borderColor: "gray",
|
||||||
padding: "2px",
|
padding: "2px",
|
||||||
}}>
|
}}
|
||||||
<header style={{ fontSize: "20px", fontWeight: "bold" }}>
|
>
|
||||||
|
<header style={{ fontSize: "20px", fontWeight: "bold" }} safe>
|
||||||
{converter}
|
{converter}
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
@@ -660,7 +669,9 @@ const app = new Elysia({
|
|||||||
data-target={target}
|
data-target={target}
|
||||||
data-converter={converter}
|
data-converter={converter}
|
||||||
style={{ fontSize: "15px", padding: "5px" }}
|
style={{ fontSize: "15px", padding: "5px" }}
|
||||||
type="button">
|
type="button"
|
||||||
|
safe
|
||||||
|
>
|
||||||
{target}
|
{target}
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
@@ -827,7 +838,10 @@ const app = new Elysia({
|
|||||||
const fileTypeOrig = fileName.split(".").pop() ?? "";
|
const fileTypeOrig = fileName.split(".").pop() ?? "";
|
||||||
const fileType = normalizeFiletype(fileTypeOrig);
|
const fileType = normalizeFiletype(fileTypeOrig);
|
||||||
const newFileExt = normalizeOutputFiletype(convertTo);
|
const newFileExt = normalizeOutputFiletype(convertTo);
|
||||||
const newFileName = fileName.replace(fileTypeOrig, newFileExt);
|
const newFileName = fileName.replace(
|
||||||
|
new RegExp(`${fileTypeOrig}(?!.*${fileTypeOrig})`),
|
||||||
|
newFileExt,
|
||||||
|
);
|
||||||
const targetPath = `${userOutputDir}${newFileName}`;
|
const targetPath = `${userOutputDir}${newFileName}`;
|
||||||
|
|
||||||
const result = await mainConverter(
|
const result = await mainConverter(
|
||||||
@@ -1252,12 +1266,14 @@ console.log(
|
|||||||
);
|
);
|
||||||
|
|
||||||
const clearJobs = () => {
|
const clearJobs = () => {
|
||||||
// clear all jobs older than 24 hours
|
|
||||||
// get all files older than 24 hours
|
|
||||||
const jobs = db
|
const jobs = db
|
||||||
.query("SELECT * FROM jobs WHERE date_created < ?")
|
.query("SELECT * FROM jobs WHERE date_created < ?")
|
||||||
.as(Jobs)
|
.as(Jobs)
|
||||||
.all(new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString());
|
.all(
|
||||||
|
new Date(
|
||||||
|
Date.now() - AUTO_DELETE_EVERY_N_HOURS * 60 * 60 * 1000,
|
||||||
|
).toISOString(),
|
||||||
|
);
|
||||||
|
|
||||||
for (const job of jobs) {
|
for (const job of jobs) {
|
||||||
// delete the directories
|
// delete the directories
|
||||||
@@ -1268,7 +1284,9 @@ const clearJobs = () => {
|
|||||||
db.query("DELETE FROM jobs WHERE id = ?").run(job.id);
|
db.query("DELETE FROM jobs WHERE id = ?").run(job.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// run every 24 hours
|
setTimeout(clearJobs, AUTO_DELETE_EVERY_N_HOURS * 60 * 60 * 1000);
|
||||||
setTimeout(clearJobs, 24 * 60 * 60 * 1000);
|
|
||||||
};
|
};
|
||||||
clearJobs();
|
|
||||||
|
if (AUTO_DELETE_EVERY_N_HOURS > 0) {
|
||||||
|
clearJobs();
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ div.icon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
button[type="submit"] {
|
button[type="submit"] {
|
||||||
width: 50%
|
width: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.center {
|
div.center {
|
||||||
|
|||||||
Reference in New Issue
Block a user