-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
executable file
·135 lines (125 loc) · 4.52 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import chalk from "chalk"
import exists from "elliotisms/exists"
import returnSafeFilePath from "elliotisms/return-safe-filepath"
import truncateFilename from "elliotisms/truncate-filename"
import fs from "node:fs/promises"
import path from "node:path"
import yargs from "yargs"
import { hideBin } from "yargs/helpers"
import addExifTags from "./lib/exif.js"
import config from "./config.js"
import { ask } from "./lib/ask.js"
import { validateAndFormatInput } from "./lib/file-path-argument.js"
import filterInputs from "./lib/filters.js"
import getContent from "./lib/get-content.js"
import ocr from "./lib/tesseract.js"
const main = async (input, dryrun = false, useXMP = true, useOCR = true) => {
if (!input) {
throw new Error("No input files selected")
}
const inputs = await validateAndFormatInput(input)
if (inputs.length === 0) {
throw new Error("No valid inputs")
}
const initialLength = inputs.length
const filteredInputs = await filterInputs(inputs)
const finalLength = filteredInputs.length
const filteredAmount = initialLength - finalLength
if (filteredAmount > 0) {
console.log(`Filtered ${filteredAmount} non-img files for a total of ${finalLength} files.`)
}
else {
console.log(`Found ${finalLength} files to rename.`)
}
if (dryrun) {
console.log("Querying API for new names...")
} else {
if (finalLength === 0) {
console.log("No files to rename.")
return
}
console.log("Renaming files...")
}
for (const file of filteredInputs) {
try {
const content = await getContent(file)
const { filename, time, prompt, result } = await ask(content, file)
const newFilename = path.join(path.dirname(file), `${filename}${path.extname(file)}`)
const finalFilename = await returnSafeFilePath(newFilename)
if (await exists(finalFilename)) {
console.warn(chalk.red(`File ${finalFilename} already exists, skipping`))
} else {
if (!dryrun) {
await fs.rename(file, finalFilename)
}
if (useXMP) {
const exifData = {
"DscImg_Prompt": prompt,
"DscImg_ContentDescription": result,
"DscImg_InferenceTime": time,
"DscImg_OriginalFilename": path.basename(file),
}
if (useOCR) {
const text = await ocr(finalFilename)
exifData.DscImg_Tesseract_OCR_Result = text
}
await addExifTags(exifData, finalFilename)
}
console.log(
chalk.green(
`${dryrun ? "This would rename" : "Renamed"} ${truncateFilename(path.basename(file))} to ${path.basename(finalFilename)} (${time})`
)
)
}
} catch (error) {
console.error(chalk.red(error.toString(), error.stack))
}
}
}
yargs(hideBin(process.argv))
.scriptName("dscimg")
.usage("$0 <cmd> [args]")
.command(
"$0 <path>",
"Default command with path of images to process",
(yargs) => {
yargs
.positional("path", {
demandOption: true,
describe: "Path to process",
type: "string",
})
.option("dryrun", {
default: false,
describe: "Run the command in dry run mode",
type: "boolean",
})
.option("exif", {
alias: "e",
default: true,
describe: "Save debug info as XMP metadata",
type: "boolean",
})
.option("ocr", {
alias: "o",
default: true,
describe: "Run OCR on images and save result as XMP metadata",
type: "boolean",
})
},
async (argv) => {
await main(argv.path, argv.dryrun, argv.exif, argv.ocr)
}
)
.command(
"config",
"Run the configuration command",
() => {},
async () => {
console.log("Running config command...")
await config.askAll()
}
)
.help("h")
.alias("h", "help")
.alias("v", "version").argv