node-hp-scan-to 1.5.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -4
- package/dist/commitInfo.json +1 -1
- package/dist/index.js +41 -8
- package/dist/index.js.map +1 -1
- package/dist/nextcloud/NextcloudConfig.d.ts +7 -0
- package/dist/nextcloud/NextcloudConfig.js +3 -0
- package/dist/nextcloud/NextcloudConfig.js.map +1 -0
- package/dist/nextcloud/nextcloud.d.ts +4 -0
- package/dist/nextcloud/nextcloud.js +122 -0
- package/dist/nextcloud/nextcloud.js.map +1 -0
- package/dist/paperless/paperless.js +0 -8
- package/dist/paperless/paperless.js.map +1 -1
- package/dist/postProcessing.js +50 -17
- package/dist/postProcessing.js.map +1 -1
- package/dist/scanProcessing.d.ts +2 -0
- package/dist/scanProcessing.js.map +1 -1
- package/dist/test/nextcloud.test.d.ts +1 -0
- package/dist/test/nextcloud.test.js +165 -0
- package/dist/test/nextcloud.test.js.map +1 -0
- package/dist/test/scanProcessing.test.js +2 -1
- package/dist/test/scanProcessing.test.js.map +1 -1
- package/package.json +2 -1
- package/src/commitInfo.json +1 -1
- package/src/index.ts +73 -10
- package/src/nextcloud/NextcloudConfig.ts +7 -0
- package/src/nextcloud/nextcloud.ts +146 -0
- package/src/paperless/paperless.ts +0 -12
- package/src/postProcessing.ts +100 -28
- package/src/scanProcessing.ts +2 -0
package/README.md
CHANGED
|
@@ -26,6 +26,7 @@ Additionally, it has been reported to work on several other HP printer models.
|
|
|
26
26
|
- HP DeskJet 3775 All-in-One
|
|
27
27
|
- HP DeskJet 4670 All-in-One
|
|
28
28
|
- HP DeskJet 5525
|
|
29
|
+
- HP Envy 4504 All-in-One
|
|
29
30
|
- HP OfficeJet 3830
|
|
30
31
|
- HP OfficeJet 5230
|
|
31
32
|
- HP OfficeJet 5740
|
|
@@ -33,6 +34,7 @@ Additionally, it has been reported to work on several other HP printer models.
|
|
|
33
34
|
- HP OfficeJet 6950
|
|
34
35
|
- HP OfficeJet 8010 series
|
|
35
36
|
- HP OfficeJet 8012
|
|
37
|
+
- HP OfficeJet 8014
|
|
36
38
|
- HP OfficeJet Pro 7720 Wide Format All-in-One
|
|
37
39
|
- HP OfficeJet Pro 8025e
|
|
38
40
|
- HP OfficeJet Pro 9012e
|
|
@@ -66,7 +68,7 @@ Please note that the `node-hp-scan-to` project is not endorsed by nor affiliated
|
|
|
66
68
|
### Command line
|
|
67
69
|
`npx node-hp-scan-to`
|
|
68
70
|
|
|
69
|
-
- `-
|
|
71
|
+
- `-a` or `--address` followed by the ip address of the printer, i.e. `-a 192.168.0.5`.
|
|
70
72
|
- `--device-up-polling-interval` is the polling interval in milliseconds to detect if the device is up or not
|
|
71
73
|
- `-l` or `--label` The label to display on the printer (default is the hostname).
|
|
72
74
|
- `-n` or `--name` followed by the printer name, it probably contains spaces, so it needs to be quoted, i.e. `-name "Officejet 6500 E710n-z"`
|
|
@@ -77,7 +79,13 @@ Please note that the `node-hp-scan-to` project is not endorsed by nor affiliated
|
|
|
77
79
|
- `-w` or `--width` followed by an integer, the with in pixel of the scans (default: 2481)
|
|
78
80
|
- `-h` or `--height` followed by an integer, the height in pixel of the scans (default: 3507)
|
|
79
81
|
- `-s` or `--paperless-post-document-url` followed by the paperless post document url (example: https://domain.tld/api/documents/post_document/)
|
|
80
|
-
- `
|
|
82
|
+
- `-o` or `--paperless-token` followed by te paperless-ngx api token
|
|
83
|
+
- `--nextcloud-url` followed by the nextcloud url (example: https://domain.tld)
|
|
84
|
+
- `--nextcloud-username` followed by the nextcloud username, must have write access to the upload folder
|
|
85
|
+
- `--nextcloud-password` followed by the nextcloud app password for the username. Either this or `nextcloud-password-file` is required. If both are provided, `nextcloud-password-file` is used.
|
|
86
|
+
- `--nextcloud-password-file` File name that contains the nextcloud app password for the username. Either this or `nextcloud-password` is required. If both are provided, `nextcloud-password-file` is used.
|
|
87
|
+
- `--nextcloud-upload-folder` followed by the upload folder where documents or images are uploaded (default: scan)
|
|
88
|
+
- `-k` or `--keep-files`: if set the scanned files will not be deleted, after uploading to paperless-ngx or nextcloud
|
|
81
89
|
- `-D, --debug"` enables debug logs.
|
|
82
90
|
|
|
83
91
|
#### `listen command`
|
|
@@ -113,7 +121,7 @@ For the correct permissions to the volume set the environment variables `PUID` a
|
|
|
113
121
|
Exhaustive list of supported environment variables and their meaning, or correspondence with [command-line flags](#command-line):
|
|
114
122
|
- `PUID`: id of user that will run the program
|
|
115
123
|
- `PGID`: id of group that will run the program
|
|
116
|
-
- `IP`: command-line flag `-
|
|
124
|
+
- `IP`: command-line flag `-a`/`--address`
|
|
117
125
|
- `PATTERN`: command-line flag `-p`/`--pattern`
|
|
118
126
|
- `LABEL`: command-line flag `-l`/`--label`
|
|
119
127
|
- `NAME`: command-line flag `-n`/`--name`
|
|
@@ -122,6 +130,12 @@ Exhaustive list of supported environment variables and their meaning, or corresp
|
|
|
122
130
|
- `RESOLUTION`: command-line flag `-r`/`--resolution`
|
|
123
131
|
- `PAPERLESS_POST_DOCUMENT_URL`: the paperless post document url (if provided with token, a pdf is uploaded to paperless-ngx) for example: `PAPERLESS_POST_DOCUMENT_URL= "http://<paperless-host>:<port>/api/documents/post_document/"`
|
|
124
132
|
- `PAPERLESS_TOKEN`: the paperless api token for example: `PAPERLESS_TOKEN= "xxxxxxxxxxxx..."`
|
|
133
|
+
- `NEXTCLOUD_URL`: the nextcloud URL, for example `https://nextcloud.example.tld`
|
|
134
|
+
- `NEXTCLOUD_UPLOAD_FOLDER`: upload folder where documents or images are uploaded. User must have write permission on this folder. If not provided, `scan` is used
|
|
135
|
+
- `NEXTCLOUD_USERNAME`: nextcloud user name
|
|
136
|
+
- `NEXTCLOUD_PASSWORD`: password of nextcloud user. Either this or `NEXTCLOUD_PASSWORD_FILE` is required. If both are provided, value of `NEXTCLOUD_PASSWORD_FILE` is used.
|
|
137
|
+
- `NEXTCLOUD_PASSWORD_FILE`: file name containing password of nextcloud user. Either this or `NEXTCLOUD_PASSWORD` is required. If both are provided, this value is used. For example: `NEXTCLOUD_PASSWORD_FILE=./nextcloud_password.secret`. Preferably for use in [docker compose secrets](https://docs.docker.com/reference/compose-file/secrets/)
|
|
138
|
+
- `$KEEP_FILES`: if set the scanned files will not be deleted, after uploading to paperless-ngx or nextcloud
|
|
125
139
|
- `CMDLINE`: additional command-line flags that will be put at the end of the command.
|
|
126
140
|
|
|
127
141
|
__To enable debug logs set the environment variable `CMDLINE` to `-D`.__
|
|
@@ -218,7 +232,7 @@ cd node-hp-scan-to
|
|
|
218
232
|
yarn install -d
|
|
219
233
|
yarn build
|
|
220
234
|
# now start the program with the ip or name of the desired printer
|
|
221
|
-
node dist/index.js -
|
|
235
|
+
node dist/index.js -a 192.168.1.4 # or -n "Officejet 6500 E710n-z"
|
|
222
236
|
```
|
|
223
237
|
|
|
224
238
|
#### Debugging
|
package/dist/commitInfo.json
CHANGED
package/dist/index.js
CHANGED
|
@@ -40,6 +40,7 @@ const listening_1 = require("./listening");
|
|
|
40
40
|
const scanProcessing_1 = require("./scanProcessing");
|
|
41
41
|
const commitInfo = __importStar(require("./commitInfo.json"));
|
|
42
42
|
const healthcheck_1 = require("./healthcheck");
|
|
43
|
+
const fs_1 = __importDefault(require("fs"));
|
|
43
44
|
let iteration = 0;
|
|
44
45
|
async function listenCmd(registrationConfig, scanConfig, deviceUpPollingInterval) {
|
|
45
46
|
// first make sure the device is reachable
|
|
@@ -169,11 +170,16 @@ function setupScanParameters(command) {
|
|
|
169
170
|
command.option("-o, --paperless-token <paperless_token>", "The paperless token");
|
|
170
171
|
command.option("--paperless-group-multi-page-scan-into-a-pdf", "Combine multiple scanned images into a single PDF document");
|
|
171
172
|
command.option("--paperless-always-send-as-pdf-file", "Always convert scan job to pdf before sending to paperless");
|
|
172
|
-
command.option("-k, --
|
|
173
|
+
command.option("-k, --keep-files", "Keep the scan files on the file system (default: false)");
|
|
174
|
+
command.option("--nextcloud-url <nextcloud_url>", "The nextcloud url (example: https://domain.tld)");
|
|
175
|
+
command.option("--nextcloud-username <nextcloud_username>", "The nextcloud username");
|
|
176
|
+
command.option("--nextcloud-password <nextcloud_app_password>", "The nextcloud app password for username. Either this or nextcloud-password-file is required");
|
|
177
|
+
command.option("--nextcloud-password-file <nextcloud_app_password_file>", "File name that contains the nextcloud app password for username. Either this or nextcloud-password is required");
|
|
178
|
+
command.option("--nextcloud-upload-folder <nextcloud_upload_folder>", "The upload folder where documents or images are uploaded (default: scan)");
|
|
173
179
|
return command;
|
|
174
180
|
}
|
|
175
181
|
function setupParameterOpts(command) {
|
|
176
|
-
command.option("-
|
|
182
|
+
command.option("-a, --address <ip>", "IP address of the device (this overrides -p)");
|
|
177
183
|
command.option("--device-up-polling-interval <deviceUpPollingInterval>", "Device up polling interval in milliseconds", parseFloat);
|
|
178
184
|
command.option("-n, --name <name>", "Name of the device for service discovery"); // i.e. 'Deskjet 3520 series'
|
|
179
185
|
command.option("-D, --debug", "Enable debug");
|
|
@@ -199,13 +205,8 @@ function getPaperlessConfig(parentOption) {
|
|
|
199
205
|
const paperlessPostDocumentUrl = parentOption.paperlessPostDocumentUrl ||
|
|
200
206
|
getConfig("paperless_post_document_url");
|
|
201
207
|
const configPaperlessToken = parentOption.paperlessToken || getConfig("paperless_token");
|
|
202
|
-
const configPaperlessKeepFiles = parentOption.paperlessKeepFiles ||
|
|
203
|
-
getConfig("paperless_keep_files") ||
|
|
204
|
-
false;
|
|
205
208
|
if (paperlessPostDocumentUrl && configPaperlessToken) {
|
|
206
|
-
const configPaperlessKeepFiles = parentOption.
|
|
207
|
-
getConfig("paperless_keep_files") ||
|
|
208
|
-
false;
|
|
209
|
+
const configPaperlessKeepFiles = parentOption.keepFiles || getConfig("keep_files") || false;
|
|
209
210
|
const groupMultiPageScanIntoAPdf = parentOption.paperlessGroupMultiPageScanIntoAPdf ||
|
|
210
211
|
getConfig("paperless_group_multi_page_scan_into_a_pdf") ||
|
|
211
212
|
false;
|
|
@@ -225,6 +226,36 @@ function getPaperlessConfig(parentOption) {
|
|
|
225
226
|
return undefined;
|
|
226
227
|
}
|
|
227
228
|
}
|
|
229
|
+
function getNextcloudConfig(parentOption) {
|
|
230
|
+
const configNextcloudUrl = parentOption.nextcloudUrl || getConfig("nextcloud_url");
|
|
231
|
+
const configNextcloudUsername = parentOption.nextcloudUsername || getConfig("nextcloud_username");
|
|
232
|
+
let configNextcloudPassword = parentOption.nextcloudPassword || getConfig("nextcloud_password");
|
|
233
|
+
const configNextcloudPasswordFile = parentOption.nextcloudPasswordFile || getConfig("nextcloud_password_file");
|
|
234
|
+
if (configNextcloudUrl &&
|
|
235
|
+
configNextcloudUsername &&
|
|
236
|
+
(configNextcloudPassword || configNextcloudPasswordFile)) {
|
|
237
|
+
const configNextcloudUploadFolder = parentOption.nextcloudUploadFolder ||
|
|
238
|
+
getConfig("nextcloud_upload_folder") ||
|
|
239
|
+
"scan";
|
|
240
|
+
const configNextcloudKeepFiles = parentOption.keepFiles || getConfig("keep_files") || false;
|
|
241
|
+
if (configNextcloudPasswordFile) {
|
|
242
|
+
configNextcloudPassword = fs_1.default
|
|
243
|
+
.readFileSync(configNextcloudPasswordFile, "utf8")
|
|
244
|
+
.trimEnd();
|
|
245
|
+
}
|
|
246
|
+
console.log(`Nextcloud configuration provided, url: ${configNextcloudUrl}, username: ${configNextcloudUsername}, password length: ${configNextcloudPassword.length}, upload folder: ${configNextcloudUploadFolder}, keepFiles: ${configNextcloudKeepFiles}`);
|
|
247
|
+
return {
|
|
248
|
+
baseUrl: configNextcloudUrl,
|
|
249
|
+
username: configNextcloudUsername,
|
|
250
|
+
password: configNextcloudPassword,
|
|
251
|
+
uploadFolder: configNextcloudUploadFolder,
|
|
252
|
+
keepFiles: configNextcloudKeepFiles,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
return undefined;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
228
259
|
function getHealthCheckSetting(option) {
|
|
229
260
|
const healthCheckEnabled = option.healthCheck || getConfig("enableHealthCheck") === true;
|
|
230
261
|
let healthCheckPort;
|
|
@@ -254,12 +285,14 @@ function getScanConfiguration(option) {
|
|
|
254
285
|
? Number.MAX_SAFE_INTEGER
|
|
255
286
|
: parseInt(configHeight, 10);
|
|
256
287
|
const paperlessConfig = getPaperlessConfig(option);
|
|
288
|
+
const nextcloudConfig = getNextcloudConfig(option);
|
|
257
289
|
const scanConfig = {
|
|
258
290
|
resolution: parseInt(option.resolution || getConfig("resolution") || "200", 10),
|
|
259
291
|
width: width,
|
|
260
292
|
height: height,
|
|
261
293
|
directoryConfig,
|
|
262
294
|
paperlessConfig,
|
|
295
|
+
nextcloudConfig,
|
|
263
296
|
};
|
|
264
297
|
return scanConfig;
|
|
265
298
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,sDAAsD;AAEtD,YAAY,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEb,4CAAoB;AACpB,yCAAmE;AACnE,qDAA0C;AAC1C,oDAA4B;AAC5B,oDAA4B;AAC5B,8DAAsC;AACtC,mCAAgC;AAChC,qEAAkE;AAClE,2CAIqB;AACrB,qDAO0B;AAC1B,8DAAgD;AAEhD,+CAAuD;AAGvD,IAAI,SAAS,GAAG,CAAC,CAAC;AAElB,KAAK,UAAU,SAAS,CACtB,kBAAsC,EACtC,UAAsB,EACtB,uBAA+B;IAE/B,0CAA0C;IAC1C,MAAM,eAAK,CAAC,YAAY,CAAC,uBAAuB,CAAC,CAAC;IAClD,IAAI,QAAQ,GAAG,IAAI,CAAC;IAEpB,MAAM,MAAM,GAAG,MAAM,oBAAU,CAAC,eAAe,CAC7C,UAAU,CAAC,eAAe,CAAC,SAAS,CACrC,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,kBAAkB,MAAM,EAAE,CAAC,CAAC;IAExC,MAAM,UAAU,GAAG,MAAM,oBAAU,CAAC,eAAe,CACjD,UAAU,CAAC,eAAe,CAAC,aAAa,CACzC,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,gBAAgB,UAAU,EAAE,CAAC,CAAC;IAE1C,MAAM,kBAAkB,GAAG,MAAM,IAAA,+CAAsB,GAAE,CAAC;IAE1D,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,UAAU,GAAG,IAAI,CAAC;IACtB,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,OAAO,UAAU,EAAE;QACjB,SAAS,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CAAC,sBAAsB,SAAS,kBAAkB,UAAU,EAAE,CAAC,CAAC;QAC3E,IAAI;YACF,MAAM,KAAK,GAAG,MAAM,IAAA,yBAAa,EAAC,kBAAkB,EAAE,kBAAkB,CAAC,CAAC;YAC1E,SAAS,GAAG,MAAM,oBAAU,CAAC,iBAAiB,CAC5C,MAAM,EACN,SAAS,EACT,UAAU,CAAC,eAAe,CAAC,WAAW,CACvC,CAAC;YACF,OAAO,CAAC,GAAG,CAAC,qCAAqC,SAAS,EAAE,CAAC,CAAC;YAC9D,MAAM,IAAA,kCAAiB,EACrB,KAAK,EACL,MAAM,EACN,UAAU,EACV,SAAS,EACT,kBAAkB,EAClB,UAAU,CACX,CAAC;SACH;QAAC,OAAO,CAAC,EAAE;YACV,IAAI,MAAM,eAAK,CAAC,OAAO,EAAE,EAAE;gBACzB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;gBACf,UAAU,EAAE,CAAC;aACd;iBAAM;gBACL,IAAI,eAAK,CAAC,OAAO,EAAE,EAAE;oBACnB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;iBAChB;gBACD,QAAQ,GAAG,KAAK,CAAC;aAClB;SACF;QAED,IAAI,UAAU,KAAK,EAAE,EAAE;YACrB,UAAU,GAAG,KAAK,CAAC;SACpB;QAED,IAAI,CAAC,QAAQ,EAAE;YACb,MAAM,eAAK,CAAC,YAAY,CAAC,uBAAuB,CAAC,CAAC;SACnD;aAAM;YACL,MAAM,IAAA,aAAK,EAAC,IAAI,CAAC,CAAC;SACnB;KACF;AACH,CAAC;AAED,KAAK,UAAU,cAAc,CAC3B,iBAAoC,EACpC,uBAA+B;IAE/B,0CAA0C;IAC1C,MAAM,eAAK,CAAC,YAAY,CAAC,uBAAuB,CAAC,CAAC;IAClD,IAAI,QAAQ,GAAG,IAAI,CAAC;IAEpB,MAAM,MAAM,GAAG,MAAM,oBAAU,CAAC,eAAe,CAC7C,iBAAiB,CAAC,eAAe,CAAC,SAAS,CAC5C,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,kBAAkB,MAAM,EAAE,CAAC,CAAC;IAExC,MAAM,UAAU,GAAG,MAAM,oBAAU,CAAC,eAAe,CACjD,iBAAiB,CAAC,eAAe,CAAC,aAAa,CAChD,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,gBAAgB,UAAU,EAAE,CAAC,CAAC;IAE1C,MAAM,kBAAkB,GAAG,MAAM,IAAA,+CAAsB,GAAE,CAAC;IAE1D,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,UAAU,GAAG,IAAI,CAAC;IACtB,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,OAAO,UAAU,EAAE;QACjB,SAAS,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CAAC,sBAAsB,SAAS,kBAAkB,UAAU,EAAE,CAAC,CAAC;QAC3E,IAAI;YACF,MAAM,IAAA,8BAAa,EACjB,iBAAiB,CAAC,eAAe,EACjC,iBAAiB,CAAC,cAAc,CACjC,CAAC;YAEF,SAAS,EAAE,CAAC;YAEZ,OAAO,CAAC,GAAG,CAAC,qCAAqC,SAAS,EAAE,CAAC,CAAC;YAE9D,MAAM,IAAA,4BAAW,EACf,SAAS,EACT,MAAM,EACN,UAAU,EACV,iBAAiB,EACjB,kBAAkB,EAClB,IAAI,IAAI,EAAE,CACX,CAAC;SACH;QAAC,OAAO,CAAC,EAAE;YACV,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACf,IAAI,MAAM,eAAK,CAAC,OAAO,EAAE,EAAE;gBACzB,UAAU,EAAE,CAAC;aACd;iBAAM;gBACL,QAAQ,GAAG,KAAK,CAAC;aAClB;SACF;QAED,IAAI,UAAU,KAAK,EAAE,EAAE;YACrB,UAAU,GAAG,KAAK,CAAC;SACpB;QAED,IAAI,CAAC,QAAQ,EAAE;YACb,MAAM,eAAK,CAAC,YAAY,CAAC,uBAAuB,CAAC,CAAC;SACnD;aAAM;YACL,MAAM,IAAA,aAAK,EAAC,IAAI,CAAC,CAAC;SACnB;KACF;AACH,CAAC;AAED,KAAK,UAAU,qBAAqB,CAAC,GAAY;IAC/C,MAAM,YAAY,GAAG,GAAG,CAAC,MAAO,CAAC,IAAI,EAAE,CAAC;IAExC,MAAM,EAAE,GAAG,MAAM,WAAW,CAAC,YAAY,CAAC,CAAC;IAC3C,eAAK,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;IAEtB,MAAM,OAAO,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;IACzC,eAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACxB,MAAM,IAAA,8BAAkB,GAAE,CAAC;AAC7B,CAAC;AAED,SAAS,eAAe,CAAC,gBAAwB;IAC/C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,OAAO,GAAG,IAAI,yBAAO,EAAE,CAAC;QAC9B,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QACnC,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAC1B;YACE,IAAI,EAAE,MAAM;SACb,EACD,CAAC,OAAO,EAAE,EAAE;YACV,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACjB,IACE,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC;gBACzC,OAAO,CAAC,IAAI,KAAK,EAAE;gBACnB,OAAO,CAAC,IAAI,KAAK,MAAM;gBACvB,OAAO,CAAC,SAAS,IAAI,IAAI,EACzB;gBACA,OAAO,CAAC,IAAI,EAAE,CAAC;gBACf,OAAO,CAAC,OAAO,EAAE,CAAC;gBAClB,OAAO,CAAC,GAAG,CAAC,UAAU,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;gBACtC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;aAC/B;QACH,CAAC,CACF,CAAC;QACF,OAAO,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,SAAS,CAAI,IAAY;IAChC,OAAO,gBAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,gBAAM,CAAC,GAAG,CAAI,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC5D,CAAC;AAED,SAAS,mBAAmB,CAAC,OAAgB;IAC3C,OAAO,CAAC,MAAM,CACZ,uBAAuB,EACvB,kEAAkE,CACnE,CAAC;IACF,OAAO,CAAC,MAAM,CACZ,4BAA4B,EAC5B,qEAAqE,CACtE,CAAC;IACF,OAAO,CAAC,MAAM,CACZ,yBAAyB,EACzB,yFAAyF,CAC1F,CAAC;IACF,OAAO,CAAC,MAAM,CACZ,wBAAwB,EACxB,+CAA+C,CAChD,CAAC;IACF,OAAO,CAAC,MAAM,CACZ,qBAAqB,EACrB,4CAA4C,CAC7C,CAAC;IACF,OAAO,CAAC,MAAM,CACZ,uBAAuB,EACvB,8CAA8C,CAC/C,CAAC;IACF,OAAO,CAAC,MAAM,CACZ,iEAAiE,EACjE,4FAA4F,CAC7F,CAAC;IAEF,OAAO,CAAC,MAAM,CACZ,yCAAyC,EACzC,qBAAqB,CACtB,CAAC;IACF,OAAO,CAAC,MAAM,CACZ,8CAA8C,EAC9C,4DAA4D,CAC7D,CAAC;IACF,OAAO,CAAC,MAAM,CACZ,qCAAqC,EACrC,4DAA4D,CAC7D,CAAC;IACF,OAAO,CAAC,MAAM,CACZ,4BAA4B,EAC5B,yDAAyD,CAC1D,CAAC;IACF,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,kBAAkB,CAAC,OAAgB;IAC1C,OAAO,CAAC,MAAM,CACZ,qBAAqB,EACrB,8CAA8C,CAC/C,CAAC;IACF,OAAO,CAAC,MAAM,CACZ,wDAAwD,EACxD,4CAA4C,EAC5C,UAAU,CACX,CAAC;IACF,OAAO,CAAC,MAAM,CACZ,mBAAmB,EACnB,0CAA0C,CAC3C,CAAC,CAAC,6BAA6B;IAEhC,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;IAC9C,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,OAAqB;IAC9C,IAAI,EAAE,GAAG,OAAO,CAAC,OAAO,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC;IAC5C,IAAI,CAAC,EAAE,EAAE;QACP,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC;QAC/C,EAAE,GAAG,MAAM,eAAe,CAAC,IAAI,IAAI,+BAA+B,CAAC,CAAC;KACrE;IACD,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAC;IACtC,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,UAAU,CAAC,OAAqB;IACvC,MAAM,KAAK,GACT,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAU,OAAO,CAAC,IAAI,KAAK,CAAC;IAEtE,IAAI,KAAK,EAAE;QACT,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,EAAE,CAAC,CAAC;KAClC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,kBAAkB,CACzB,YAA0B;IAE1B,MAAM,wBAAwB,GAC5B,YAAY,CAAC,wBAAwB;QACrC,SAAS,CAAC,6BAA6B,CAAC,CAAC;IAC3C,MAAM,oBAAoB,GACxB,YAAY,CAAC,cAAc,IAAI,SAAS,CAAC,iBAAiB,CAAC,CAAC;IAC9D,MAAM,wBAAwB,GAC5B,YAAY,CAAC,kBAAkB;QAC/B,SAAS,CAAC,sBAAsB,CAAC;QACjC,KAAK,CAAC;IAER,IAAI,wBAAwB,IAAI,oBAAoB,EAAE;QACpD,MAAM,wBAAwB,GAC5B,YAAY,CAAC,kBAAkB;YAC/B,SAAS,CAAC,sBAAsB,CAAC;YACjC,KAAK,CAAC;QACR,MAAM,0BAA0B,GAC9B,YAAY,CAAC,mCAAmC;YAChD,SAAS,CAAC,4CAA4C,CAAC;YACvD,KAAK,CAAC;QACR,MAAM,mBAAmB,GACvB,YAAY,CAAC,4BAA4B;YACzC,SAAS,CAAC,mCAAmC,CAAC;YAC9C,KAAK,CAAC;QAER,OAAO,CAAC,GAAG,CACT,wDAAwD,wBAAwB,uBAAuB,oBAAoB,CAAC,MAAM,gBAAgB,wBAAwB,EAAE,CAC7K,CAAC;QACF,OAAO;YACL,eAAe,EAAE,wBAAwB;YACzC,SAAS,EAAE,oBAAoB;YAC/B,SAAS,EAAE,wBAAwB;YACnC,0BAA0B,EAAE,0BAA0B;YACtD,mBAAmB,EAAE,mBAAmB;SACzC,CAAC;KACH;SAAM;QACL,OAAO,SAAS,CAAC;KAClB;AACH,CAAC;AAED,SAAS,qBAAqB,CAAC,MAAoB;IACjD,MAAM,kBAAkB,GACtB,MAAM,CAAC,WAAW,IAAI,SAAS,CAAC,mBAAmB,CAAC,KAAK,IAAI,CAAC;IAChE,IAAI,eAAuB,CAAC;IAC5B,IAAI,MAAM,CAAC,eAAe,EAAE;QAC1B,eAAe,GAAG,QAAQ,CAAC,MAAM,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;KACxD;SAAM;QACL,eAAe,GAAG,SAAS,CAAS,iBAAiB,CAAC,IAAI,IAAI,CAAC;KAChE;IACD,OAAO;QACL,oBAAoB,EAAE,kBAAkB;QACxC,eAAe,EAAE,eAAe;KACjC,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAAC,MAAoB;IAChD,MAAM,eAAe,GAAoB;QACvC,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,SAAS,CAAC,WAAW,CAAC;QACrD,aAAa,EAAE,MAAM,CAAC,aAAa,IAAI,SAAS,CAAC,eAAe,CAAC;QACjE,WAAW,EAAE,MAAM,CAAC,OAAO,IAAI,SAAS,CAAC,SAAS,CAAC;KACpD,CAAC;IAEF,MAAM,WAAW,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACzE,MAAM,KAAK,GACT,WAAW,CAAC,WAAW,EAAE,KAAK,KAAK;QACjC,CAAC,CAAC,MAAM,CAAC,gBAAgB;QACzB,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IAEhC,MAAM,YAAY,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,SAAS,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC7E,MAAM,MAAM,GACV,WAAW,CAAC,WAAW,EAAE,KAAK,KAAK;QACjC,CAAC,CAAC,MAAM,CAAC,gBAAgB;QACzB,CAAC,CAAC,QAAQ,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IAEjC,MAAM,eAAe,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAEnD,MAAM,UAAU,GAAe;QAC7B,UAAU,EAAE,QAAQ,CAClB,MAAM,CAAC,UAAU,IAAI,SAAS,CAAC,YAAY,CAAC,IAAI,KAAK,EACrD,EAAE,CACH;QACD,KAAK,EAAE,KAAK;QACZ,MAAM,EAAE,MAAM;QACd,eAAe;QACf,eAAe;KAChB,CAAC;IACF,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,SAAS,0BAA0B,CAAC,YAA0B;IAC5D,OAAO,CACL,YAAY,CAAC,uBAAuB;QACpC,SAAS,CAAC,yBAAyB,CAAC;QACpC,IAAI,CACL,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,kBAAkB,CAAC,mBAAO,CAAC,CAAC;IAC5B,MAAM,SAAS,GAAG,mBAAO,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAClD,mBAAmB,CAAC,SAAS,CAAC;SAC3B,WAAW,CAAC,2DAA2D,CAAC;SACxE,MAAM,CACL,qBAAqB,EACrB,kEAAkE,CACnE;SACA,SAAS,CACR,IAAI,kBAAM,CAAC,gBAAgB,EAAE,qCAAqC,CAAC,CACpE;SACA,SAAS,CACR,IAAI,kBAAM,CACR,yCAAyC,EACzC,qCAAqC,CACtC,CACF;SACA,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE;QAC7B,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAEvC,MAAM,EAAE,GAAG,MAAM,WAAW,CAAC,YAAY,CAAC,CAAC;QAC3C,eAAK,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QAEtB,MAAM,OAAO,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;QACzC,eAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAExB,MAAM,kBAAkB,GAAuB;YAC7C,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,SAAS,CAAC,OAAO,CAAC,IAAI,YAAE,CAAC,QAAQ,EAAE;SAC5D,CAAC;QAEF,MAAM,uBAAuB,GAAG,0BAA0B,CAAC,YAAY,CAAC,CAAC;QAEzE,MAAM,kBAAkB,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;QAC1D,IAAI,kBAAkB,CAAC,oBAAoB,EAAE;YAC3C,IAAA,oCAAsB,EAAC,kBAAkB,CAAC,eAAe,CAAC,CAAC;SAC5D;QAED,MAAM,UAAU,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAEjD,MAAM,SAAS,CAAC,kBAAkB,EAAE,UAAU,EAAE,uBAAuB,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;IACL,mBAAO,CAAC,UAAU,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEnD,MAAM,cAAc,GAAG,mBAAO,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;IAC7D,mBAAmB,CAAC,cAAc,CAAC;SAChC,SAAS,CACR,IAAI,kBAAM,CAAC,UAAU,EAAE,0CAA0C,CAAC,CACnE;SACA,SAAS,CACR,IAAI,kBAAM,CACR,OAAO,EACP,0FAA0F,CAC3F,CACF;SACA,SAAS,CACR,IAAI,kBAAM,CACR,qCAAqC,EACrC,+FAA+F,CAChG,CACF;SACA,WAAW,CACV,mHAAmH,CACpH;SACA,SAAS,CACR,IAAI,kBAAM,CACR,qCAAqC,EACrC,oHAAoH,CACrH,CACF;SACA,SAAS,CACR,IAAI,kBAAM,CAAC,gBAAgB,EAAE,qCAAqC,CAAC,CACpE;SACA,SAAS,CACR,IAAI,kBAAM,CACR,4BAA4B,EAC5B,qCAAqC,CACtC,CACF;SACA,WAAW,CACV,mHAAmH,CACpH;SACA,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE;QAC7B,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAEvC,MAAM,EAAE,GAAG,MAAM,WAAW,CAAC,YAAY,CAAC,CAAC;QAC3C,eAAK,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QAEtB,MAAM,OAAO,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;QACzC,eAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAExB,MAAM,uBAAuB,GAAG,0BAA0B,CAAC,YAAY,CAAC,CAAC;QAEzE,MAAM,kBAAkB,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;QAC1D,IAAI,kBAAkB,CAAC,oBAAoB,EAAE;YAC3C,IAAA,oCAAsB,EAAC,kBAAkB,CAAC,eAAe,CAAC,CAAC;SAC5D;QAED,MAAM,UAAU,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAEjD,MAAM,aAAa,GAAsB;YACvC,GAAG,UAAU;YACb,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,SAAS,CAAC,iBAAiB,CAAC,IAAI,KAAK;YACnE,WAAW,EAAE,OAAO,CAAC,GAAG,IAAI,SAAS,CAAC,cAAc,CAAC,IAAI,KAAK;YAC9D,eAAe,EACb,OAAO,CAAC,eAAe;gBACvB,SAAS,CAAC,0BAA0B,CAAC;gBACrC,IAAI;YACN,cAAc,EACZ,OAAO,CAAC,cAAc;gBACtB,SAAS,CAAC,yBAAyB,CAAC;gBACpC,IAAI;SACP,CAAC;QAEF,MAAM,cAAc,CAAC,aAAa,EAAE,uBAAuB,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IACL,mBAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;IAEnC,MAAM,qBAAqB,GAAG,mBAAO,CAAC,aAAa,CAAC,qBAAqB,CAAC,CAAC;IAC3E,qBAAqB;SAClB,WAAW,CAAC,mDAAmD,CAAC;SAChE,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE;QAC7B,MAAM,qBAAqB,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IACL,mBAAO,CAAC,UAAU,CAAC,qBAAqB,CAAC,CAAC;IAE1C,MAAM,mBAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC;AAED,OAAO,CAAC,GAAG,CAAC,sBAAsB,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC;AACzD,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\n// noinspection XmlDeprecatedElement,HtmlDeprecatedTag\n\n\"use strict\";\n\nimport os from \"os\";\nimport { Command, Option, OptionValues, program } from \"commander\";\nimport { Bonjour } from \"bonjour-service\";\nimport config from \"config\";\nimport HPApi from \"./HPApi\";\nimport PathHelper from \"./PathHelper\";\nimport { delay } from \"./delay\";\nimport { readDeviceCapabilities } from \"./readDeviceCapabilities\";\nimport {\n clearRegistrations,\n RegistrationConfig,\n waitScanEvent,\n} from \"./listening\";\nimport {\n AdfAutoScanConfig,\n DirectoryConfig,\n saveScanFromEvent,\n ScanConfig,\n scanFromAdf,\n waitAdfLoaded,\n} from \"./scanProcessing\";\nimport * as commitInfo from \"./commitInfo.json\";\nimport { PaperlessConfig } from \"./paperless/PaperlessConfig\";\nimport { startHealthCheckServer } from \"./healthcheck\";\n\n\nlet iteration = 0;\n\nasync function listenCmd(\n registrationConfig: RegistrationConfig,\n scanConfig: ScanConfig,\n deviceUpPollingInterval: number,\n) {\n // first make sure the device is reachable\n await HPApi.waitDeviceUp(deviceUpPollingInterval);\n let deviceUp = true;\n\n const folder = await PathHelper.getOutputFolder(\n scanConfig.directoryConfig.directory,\n );\n console.log(`Target folder: ${folder}`);\n\n const tempFolder = await PathHelper.getOutputFolder(\n scanConfig.directoryConfig.tempDirectory,\n );\n console.log(`Temp folder: ${tempFolder}`);\n\n const deviceCapabilities = await readDeviceCapabilities();\n\n let scanCount = 0;\n let keepActive = true;\n let errorCount = 0;\n while (keepActive) {\n iteration++;\n console.log(`Running iteration: ${iteration} - errorCount: ${errorCount}`);\n try {\n const event = await waitScanEvent(deviceCapabilities, registrationConfig);\n scanCount = await PathHelper.getNextScanNumber(\n folder,\n scanCount,\n scanConfig.directoryConfig.filePattern,\n );\n console.log(`Scan event captured, saving scan #${scanCount}`);\n await saveScanFromEvent(\n event,\n folder,\n tempFolder,\n scanCount,\n deviceCapabilities,\n scanConfig,\n );\n } catch (e) {\n if (await HPApi.isAlive()) {\n console.log(e);\n errorCount++;\n } else {\n if (HPApi.isDebug()) {\n console.log(e);\n }\n deviceUp = false;\n }\n }\n\n if (errorCount === 50) {\n keepActive = false;\n }\n\n if (!deviceUp) {\n await HPApi.waitDeviceUp(deviceUpPollingInterval);\n } else {\n await delay(1000);\n }\n }\n}\n\nasync function adfAutoscanCmd(\n adfAutoScanConfig: AdfAutoScanConfig,\n deviceUpPollingInterval: number,\n) {\n // first make sure the device is reachable\n await HPApi.waitDeviceUp(deviceUpPollingInterval);\n let deviceUp = true;\n\n const folder = await PathHelper.getOutputFolder(\n adfAutoScanConfig.directoryConfig.directory,\n );\n console.log(`Target folder: ${folder}`);\n\n const tempFolder = await PathHelper.getOutputFolder(\n adfAutoScanConfig.directoryConfig.tempDirectory,\n );\n console.log(`Temp folder: ${tempFolder}`);\n\n const deviceCapabilities = await readDeviceCapabilities();\n\n let scanCount = 0;\n let keepActive = true;\n let errorCount = 0;\n while (keepActive) {\n iteration++;\n console.log(`Running iteration: ${iteration} - errorCount: ${errorCount}`);\n try {\n await waitAdfLoaded(\n adfAutoScanConfig.pollingInterval,\n adfAutoScanConfig.startScanDelay,\n );\n\n scanCount++;\n\n console.log(`Scan event captured, saving scan #${scanCount}`);\n\n await scanFromAdf(\n scanCount,\n folder,\n tempFolder,\n adfAutoScanConfig,\n deviceCapabilities,\n new Date(),\n );\n } catch (e) {\n console.log(e);\n if (await HPApi.isAlive()) {\n errorCount++;\n } else {\n deviceUp = false;\n }\n }\n\n if (errorCount === 50) {\n keepActive = false;\n }\n\n if (!deviceUp) {\n await HPApi.waitDeviceUp(deviceUpPollingInterval);\n } else {\n await delay(1000);\n }\n }\n}\n\nasync function clearRegistrationsCmd(cmd: Command) {\n const parentOption = cmd.parent!.opts();\n\n const ip = await getDeviceIp(parentOption);\n HPApi.setDeviceIP(ip);\n\n const isDebug = getIsDebug(parentOption);\n HPApi.setDebug(isDebug);\n await clearRegistrations();\n}\n\nfunction findOfficejetIp(deviceNamePrefix: string): Promise<string> {\n return new Promise((resolve) => {\n const bonjour = new Bonjour();\n console.log(\"Searching device...\");\n const browser = bonjour.find(\n {\n type: \"http\",\n },\n (service) => {\n console.log(\".\");\n if (\n service.name.startsWith(deviceNamePrefix) &&\n service.port === 80 &&\n service.type === \"http\" &&\n service.addresses != null\n ) {\n browser.stop();\n bonjour.destroy();\n console.log(`Found: ${service.name}`);\n resolve(service.addresses[0]);\n }\n },\n );\n browser.start();\n });\n}\n\nfunction getConfig<T>(name: string): T | undefined {\n return config.has(name) ? config.get<T>(name) : undefined;\n}\n\nfunction setupScanParameters(command: Command): Command {\n command.option(\n \"-d, --directory <dir>\",\n \"Directory where scans are saved (default: /tmp/scan-to-pcRANDOM)\",\n );\n command.option(\n \"-t, --temp-directory <dir>\",\n \"Temp directory used for processing (default: /tmp/scan-to-pcRANDOM)\",\n );\n command.option(\n \"-p, --pattern <pattern>\",\n 'Pattern for filename (i.e. \"scan\"_dd.mm.yyyy_hh:MM:ss, without this its scanPageNUMBER)',\n );\n command.option(\n \"-r, --resolution <dpi>\",\n \"Resolution in DPI of the scans (default: 200)\",\n );\n command.option(\n \"-w, --width <width>\",\n \"With in pixel of the scans (default: 2481)\",\n );\n command.option(\n \"-h, --height <height>\",\n \"Height in pixel of the scans (default: 3507)\",\n );\n command.option(\n \"-s, --paperless-post-document-url <paperless_post_document_url>\",\n \"The paperless post document url (example: https://domain.tld/api/documents/post_document/)\",\n );\n\n command.option(\n \"-o, --paperless-token <paperless_token>\",\n \"The paperless token\",\n );\n command.option(\n \"--paperless-group-multi-page-scan-into-a-pdf\",\n \"Combine multiple scanned images into a single PDF document\",\n );\n command.option(\n \"--paperless-always-send-as-pdf-file\",\n \"Always convert scan job to pdf before sending to paperless\",\n );\n command.option(\n \"-k, --paperless-keep-files\",\n \"Keep the scan files on the file system (default: false)\",\n );\n return command;\n}\n\nfunction setupParameterOpts(command: Command): Command {\n command.option(\n \"-ip, --address <ip>\",\n \"IP address of the device (this overrides -p)\",\n );\n command.option(\n \"--device-up-polling-interval <deviceUpPollingInterval>\",\n \"Device up polling interval in milliseconds\",\n parseFloat,\n );\n command.option(\n \"-n, --name <name>\",\n \"Name of the device for service discovery\",\n ); // i.e. 'Deskjet 3520 series'\n\n command.option(\"-D, --debug\", \"Enable debug\");\n return command;\n}\n\nasync function getDeviceIp(options: OptionValues) {\n let ip = options.address || getConfig(\"ip\");\n if (!ip) {\n const name = options.name || getConfig(\"name\");\n ip = await findOfficejetIp(name || \"HP Smart Tank Plus 570 series\");\n }\n console.log(`Using device ip: ${ip}`);\n return ip;\n}\n\nfunction getIsDebug(options: OptionValues) {\n const debug =\n options.debug != null ? true : getConfig<boolean>(\"debug\") || false;\n\n if (debug) {\n console.log(`IsDebug: ${debug}`);\n }\n return debug;\n}\n\nfunction getPaperlessConfig(\n parentOption: OptionValues,\n): PaperlessConfig | undefined {\n const paperlessPostDocumentUrl: string =\n parentOption.paperlessPostDocumentUrl ||\n getConfig(\"paperless_post_document_url\");\n const configPaperlessToken: string =\n parentOption.paperlessToken || getConfig(\"paperless_token\");\n const configPaperlessKeepFiles =\n parentOption.paperlessKeepFiles ||\n getConfig(\"paperless_keep_files\") ||\n false;\n\n if (paperlessPostDocumentUrl && configPaperlessToken) {\n const configPaperlessKeepFiles: boolean =\n parentOption.paperlessKeepFiles ||\n getConfig(\"paperless_keep_files\") ||\n false;\n const groupMultiPageScanIntoAPdf: boolean =\n parentOption.paperlessGroupMultiPageScanIntoAPdf ||\n getConfig(\"paperless_group_multi_page_scan_into_a_pdf\") ||\n false;\n const alwaysSendAsPdfFile: boolean =\n parentOption.paperlessAlwaysSendAsPdfFile ||\n getConfig(\"paperless_always_send_as_pdf_file\") ||\n false;\n\n console.log(\n `Paperless configuration provided, post document url: ${paperlessPostDocumentUrl}, the token length: ${configPaperlessToken.length}, keepFiles: ${configPaperlessKeepFiles}`,\n );\n return {\n postDocumentUrl: paperlessPostDocumentUrl,\n authToken: configPaperlessToken,\n keepFiles: configPaperlessKeepFiles,\n groupMultiPageScanIntoAPdf: groupMultiPageScanIntoAPdf,\n alwaysSendAsPdfFile: alwaysSendAsPdfFile,\n };\n } else {\n return undefined;\n }\n}\n\nfunction getHealthCheckSetting(option: OptionValues) {\n const healthCheckEnabled: boolean =\n option.healthCheck || getConfig(\"enableHealthCheck\") === true;\n let healthCheckPort: number;\n if (option.healthCheckPort) {\n healthCheckPort = parseInt(option.healthCheckPort, 10);\n } else {\n healthCheckPort = getConfig<number>(\"healthCheckPort\") || 3000;\n }\n return {\n isHealthCheckEnabled: healthCheckEnabled,\n healthCheckPort: healthCheckPort,\n };\n}\n\nfunction getScanConfiguration(option: OptionValues) {\n const directoryConfig: DirectoryConfig = {\n directory: option.directory || getConfig(\"directory\"),\n tempDirectory: option.tempDirectory || getConfig(\"tempDirectory\"),\n filePattern: option.pattern || getConfig(\"pattern\"),\n };\n\n const configWidth = (option.width || getConfig(\"width\") || 0).toString();\n const width =\n configWidth.toLowerCase() === \"max\"\n ? Number.MAX_SAFE_INTEGER\n : parseInt(configWidth, 10);\n\n const configHeight = (option.width || getConfig(\"height\") || \"0\").toString();\n const height =\n configWidth.toLowerCase() === \"max\"\n ? Number.MAX_SAFE_INTEGER\n : parseInt(configHeight, 10);\n\n const paperlessConfig = getPaperlessConfig(option);\n\n const scanConfig: ScanConfig = {\n resolution: parseInt(\n option.resolution || getConfig(\"resolution\") || \"200\",\n 10,\n ),\n width: width,\n height: height,\n directoryConfig,\n paperlessConfig,\n };\n return scanConfig;\n}\n\nfunction getDeviceUpPollingInterval(parentOption: OptionValues) {\n return (\n parentOption.deviceUpPollingInterval ||\n getConfig(\"deviceUpPollingInterval\") ||\n 1000\n );\n}\n\nasync function main() {\n setupParameterOpts(program);\n const cmdListen = program.createCommand(\"listen\");\n setupScanParameters(cmdListen)\n .description(\"Listen the device for new scan job to save to this target\")\n .option(\n \"-l, --label <label>\",\n \"The label to display on the device (the default is the hostname)\",\n )\n .addOption(\n new Option(\"--health-check\", \"Start an http health check endpoint\"),\n )\n .addOption(\n new Option(\n \"--health-check-port <health-check-port>\",\n \"Start an http health check endpoint\",\n ),\n )\n .action(async (options, cmd) => {\n const parentOption = cmd.parent.opts();\n\n const ip = await getDeviceIp(parentOption);\n HPApi.setDeviceIP(ip);\n\n const isDebug = getIsDebug(parentOption);\n HPApi.setDebug(isDebug);\n\n const registrationConfig: RegistrationConfig = {\n label: options.label || getConfig(\"label\") || os.hostname(),\n };\n\n const deviceUpPollingInterval = getDeviceUpPollingInterval(parentOption);\n\n const healthCheckSetting = getHealthCheckSetting(options);\n if (healthCheckSetting.isHealthCheckEnabled) {\n startHealthCheckServer(healthCheckSetting.healthCheckPort);\n }\n\n const scanConfig = getScanConfiguration(options);\n\n await listenCmd(registrationConfig, scanConfig, deviceUpPollingInterval);\n });\n program.addCommand(cmdListen, { isDefault: true });\n\n const cmdAdfAutoscan = program.createCommand(\"adf-autoscan\");\n setupScanParameters(cmdAdfAutoscan)\n .addOption(\n new Option(\"--duplex\", \"If specified, the scan will be in duplex\"),\n )\n .addOption(\n new Option(\n \"--pdf\",\n \"If specified, the scan result will be a pdf document, the default is multiple jpeg files\",\n ),\n )\n .addOption(\n new Option(\n \"--pollingInterval <pollingInterval>\",\n \"Time interval in millisecond between each lookup for content in the automatic document feeder\",\n ),\n )\n .description(\n \"Automatically trigger a new scan job to this target once paper is detected in the automatic document feeder (adf)\",\n )\n .addOption(\n new Option(\n \"--start-scan-delay <startScanDelay>\",\n \"Once document are detected to be in the adf, this specify the wait delay in millisecond before triggering the scan\",\n ),\n )\n .addOption(\n new Option(\"--health-check\", \"Start an http health check endpoint\"),\n )\n .addOption(\n new Option(\n \"--health-check-port <port>\",\n \"Start an http health check endpoint\",\n ),\n )\n .description(\n \"Automatically trigger a new scan job to this target once paper is detected in the automatic document feeder (adf)\",\n )\n .action(async (options, cmd) => {\n const parentOption = cmd.parent.opts();\n\n const ip = await getDeviceIp(parentOption);\n HPApi.setDeviceIP(ip);\n\n const isDebug = getIsDebug(parentOption);\n HPApi.setDebug(isDebug);\n\n const deviceUpPollingInterval = getDeviceUpPollingInterval(parentOption);\n\n const healthCheckSetting = getHealthCheckSetting(options);\n if (healthCheckSetting.isHealthCheckEnabled) {\n startHealthCheckServer(healthCheckSetting.healthCheckPort);\n }\n\n const scanConfig = getScanConfiguration(options);\n\n const adfScanConfig: AdfAutoScanConfig = {\n ...scanConfig,\n isDuplex: options.isDuplex || getConfig(\"autoscan_duplex\") || false,\n generatePdf: options.pdf || getConfig(\"autoscan_pdf\") || false,\n pollingInterval:\n options.pollingInterval ||\n getConfig(\"autoscan_pollingInterval\") ||\n 1000,\n startScanDelay:\n options.startScanDelay ||\n getConfig(\"autoscan_startScanDelay\") ||\n 5000,\n };\n\n await adfAutoscanCmd(adfScanConfig, deviceUpPollingInterval);\n });\n program.addCommand(cmdAdfAutoscan);\n\n const cmdClearRegistrations = program.createCommand(\"clear-registrations\");\n cmdClearRegistrations\n .description(\"Clear the list or registered target on the device\")\n .action(async (options, cmd) => {\n await clearRegistrationsCmd(cmd);\n });\n program.addCommand(cmdClearRegistrations);\n\n await program.parseAsync(process.argv);\n}\n\nconsole.log(`Current commit ID: ${commitInfo.commitId}`);\nmain().catch((err) => console.log(err));\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n// noinspection XmlDeprecatedElement,HtmlDeprecatedTag\n\n\"use strict\";\n\nimport os from \"os\";\nimport { Command, Option, OptionValues, program } from \"commander\";\nimport { Bonjour } from \"bonjour-service\";\nimport config from \"config\";\nimport HPApi from \"./HPApi\";\nimport PathHelper from \"./PathHelper\";\nimport { delay } from \"./delay\";\nimport { readDeviceCapabilities } from \"./readDeviceCapabilities\";\nimport {\n clearRegistrations,\n RegistrationConfig,\n waitScanEvent,\n} from \"./listening\";\nimport {\n AdfAutoScanConfig,\n DirectoryConfig,\n saveScanFromEvent,\n ScanConfig,\n scanFromAdf,\n waitAdfLoaded,\n} from \"./scanProcessing\";\nimport * as commitInfo from \"./commitInfo.json\";\nimport { PaperlessConfig } from \"./paperless/PaperlessConfig\";\nimport { NextcloudConfig } from \"./nextcloud/NextcloudConfig\";\nimport { startHealthCheckServer } from \"./healthcheck\";\nimport fs from \"fs\";\n\nlet iteration = 0;\n\nasync function listenCmd(\n registrationConfig: RegistrationConfig,\n scanConfig: ScanConfig,\n deviceUpPollingInterval: number,\n) {\n // first make sure the device is reachable\n await HPApi.waitDeviceUp(deviceUpPollingInterval);\n let deviceUp = true;\n\n const folder = await PathHelper.getOutputFolder(\n scanConfig.directoryConfig.directory,\n );\n console.log(`Target folder: ${folder}`);\n\n const tempFolder = await PathHelper.getOutputFolder(\n scanConfig.directoryConfig.tempDirectory,\n );\n console.log(`Temp folder: ${tempFolder}`);\n\n const deviceCapabilities = await readDeviceCapabilities();\n\n let scanCount = 0;\n let keepActive = true;\n let errorCount = 0;\n while (keepActive) {\n iteration++;\n console.log(`Running iteration: ${iteration} - errorCount: ${errorCount}`);\n try {\n const event = await waitScanEvent(deviceCapabilities, registrationConfig);\n scanCount = await PathHelper.getNextScanNumber(\n folder,\n scanCount,\n scanConfig.directoryConfig.filePattern,\n );\n console.log(`Scan event captured, saving scan #${scanCount}`);\n await saveScanFromEvent(\n event,\n folder,\n tempFolder,\n scanCount,\n deviceCapabilities,\n scanConfig,\n );\n } catch (e) {\n if (await HPApi.isAlive()) {\n console.log(e);\n errorCount++;\n } else {\n if (HPApi.isDebug()) {\n console.log(e);\n }\n deviceUp = false;\n }\n }\n\n if (errorCount === 50) {\n keepActive = false;\n }\n\n if (!deviceUp) {\n await HPApi.waitDeviceUp(deviceUpPollingInterval);\n } else {\n await delay(1000);\n }\n }\n}\n\nasync function adfAutoscanCmd(\n adfAutoScanConfig: AdfAutoScanConfig,\n deviceUpPollingInterval: number,\n) {\n // first make sure the device is reachable\n await HPApi.waitDeviceUp(deviceUpPollingInterval);\n let deviceUp = true;\n\n const folder = await PathHelper.getOutputFolder(\n adfAutoScanConfig.directoryConfig.directory,\n );\n console.log(`Target folder: ${folder}`);\n\n const tempFolder = await PathHelper.getOutputFolder(\n adfAutoScanConfig.directoryConfig.tempDirectory,\n );\n console.log(`Temp folder: ${tempFolder}`);\n\n const deviceCapabilities = await readDeviceCapabilities();\n\n let scanCount = 0;\n let keepActive = true;\n let errorCount = 0;\n while (keepActive) {\n iteration++;\n console.log(`Running iteration: ${iteration} - errorCount: ${errorCount}`);\n try {\n await waitAdfLoaded(\n adfAutoScanConfig.pollingInterval,\n adfAutoScanConfig.startScanDelay,\n );\n\n scanCount++;\n\n console.log(`Scan event captured, saving scan #${scanCount}`);\n\n await scanFromAdf(\n scanCount,\n folder,\n tempFolder,\n adfAutoScanConfig,\n deviceCapabilities,\n new Date(),\n );\n } catch (e) {\n console.log(e);\n if (await HPApi.isAlive()) {\n errorCount++;\n } else {\n deviceUp = false;\n }\n }\n\n if (errorCount === 50) {\n keepActive = false;\n }\n\n if (!deviceUp) {\n await HPApi.waitDeviceUp(deviceUpPollingInterval);\n } else {\n await delay(1000);\n }\n }\n}\n\nasync function clearRegistrationsCmd(cmd: Command) {\n const parentOption = cmd.parent!.opts();\n\n const ip = await getDeviceIp(parentOption);\n HPApi.setDeviceIP(ip);\n\n const isDebug = getIsDebug(parentOption);\n HPApi.setDebug(isDebug);\n await clearRegistrations();\n}\n\nfunction findOfficejetIp(deviceNamePrefix: string): Promise<string> {\n return new Promise((resolve) => {\n const bonjour = new Bonjour();\n console.log(\"Searching device...\");\n const browser = bonjour.find(\n {\n type: \"http\",\n },\n (service) => {\n console.log(\".\");\n if (\n service.name.startsWith(deviceNamePrefix) &&\n service.port === 80 &&\n service.type === \"http\" &&\n service.addresses != null\n ) {\n browser.stop();\n bonjour.destroy();\n console.log(`Found: ${service.name}`);\n resolve(service.addresses[0]);\n }\n },\n );\n browser.start();\n });\n}\n\nfunction getConfig<T>(name: string): T | undefined {\n return config.has(name) ? config.get<T>(name) : undefined;\n}\n\nfunction setupScanParameters(command: Command): Command {\n command.option(\n \"-d, --directory <dir>\",\n \"Directory where scans are saved (default: /tmp/scan-to-pcRANDOM)\",\n );\n command.option(\n \"-t, --temp-directory <dir>\",\n \"Temp directory used for processing (default: /tmp/scan-to-pcRANDOM)\",\n );\n command.option(\n \"-p, --pattern <pattern>\",\n 'Pattern for filename (i.e. \"scan\"_dd.mm.yyyy_hh:MM:ss, without this its scanPageNUMBER)',\n );\n command.option(\n \"-r, --resolution <dpi>\",\n \"Resolution in DPI of the scans (default: 200)\",\n );\n command.option(\n \"-w, --width <width>\",\n \"With in pixel of the scans (default: 2481)\",\n );\n command.option(\n \"-h, --height <height>\",\n \"Height in pixel of the scans (default: 3507)\",\n );\n command.option(\n \"-s, --paperless-post-document-url <paperless_post_document_url>\",\n \"The paperless post document url (example: https://domain.tld/api/documents/post_document/)\",\n );\n\n command.option(\n \"-o, --paperless-token <paperless_token>\",\n \"The paperless token\",\n );\n command.option(\n \"--paperless-group-multi-page-scan-into-a-pdf\",\n \"Combine multiple scanned images into a single PDF document\",\n );\n command.option(\n \"--paperless-always-send-as-pdf-file\",\n \"Always convert scan job to pdf before sending to paperless\",\n );\n command.option(\n \"-k, --keep-files\",\n \"Keep the scan files on the file system (default: false)\",\n );\n\n command.option(\n \"--nextcloud-url <nextcloud_url>\",\n \"The nextcloud url (example: https://domain.tld)\",\n );\n command.option(\n \"--nextcloud-username <nextcloud_username>\",\n \"The nextcloud username\",\n );\n command.option(\n \"--nextcloud-password <nextcloud_app_password>\",\n \"The nextcloud app password for username. Either this or nextcloud-password-file is required\",\n );\n command.option(\n \"--nextcloud-password-file <nextcloud_app_password_file>\",\n \"File name that contains the nextcloud app password for username. Either this or nextcloud-password is required\",\n );\n command.option(\n \"--nextcloud-upload-folder <nextcloud_upload_folder>\",\n \"The upload folder where documents or images are uploaded (default: scan)\",\n );\n return command;\n}\n\nfunction setupParameterOpts(command: Command): Command {\n command.option(\n \"-a, --address <ip>\",\n \"IP address of the device (this overrides -p)\",\n );\n command.option(\n \"--device-up-polling-interval <deviceUpPollingInterval>\",\n \"Device up polling interval in milliseconds\",\n parseFloat,\n );\n command.option(\n \"-n, --name <name>\",\n \"Name of the device for service discovery\",\n ); // i.e. 'Deskjet 3520 series'\n\n command.option(\"-D, --debug\", \"Enable debug\");\n return command;\n}\n\nasync function getDeviceIp(options: OptionValues) {\n let ip = options.address || getConfig(\"ip\");\n if (!ip) {\n const name = options.name || getConfig(\"name\");\n ip = await findOfficejetIp(name || \"HP Smart Tank Plus 570 series\");\n }\n console.log(`Using device ip: ${ip}`);\n return ip;\n}\n\nfunction getIsDebug(options: OptionValues) {\n const debug =\n options.debug != null ? true : getConfig<boolean>(\"debug\") || false;\n\n if (debug) {\n console.log(`IsDebug: ${debug}`);\n }\n return debug;\n}\n\nfunction getPaperlessConfig(\n parentOption: OptionValues,\n): PaperlessConfig | undefined {\n const paperlessPostDocumentUrl: string =\n parentOption.paperlessPostDocumentUrl ||\n getConfig(\"paperless_post_document_url\");\n const configPaperlessToken: string =\n parentOption.paperlessToken || getConfig(\"paperless_token\");\n\n if (paperlessPostDocumentUrl && configPaperlessToken) {\n const configPaperlessKeepFiles: boolean =\n parentOption.keepFiles || getConfig(\"keep_files\") || false;\n const groupMultiPageScanIntoAPdf: boolean =\n parentOption.paperlessGroupMultiPageScanIntoAPdf ||\n getConfig(\"paperless_group_multi_page_scan_into_a_pdf\") ||\n false;\n const alwaysSendAsPdfFile: boolean =\n parentOption.paperlessAlwaysSendAsPdfFile ||\n getConfig(\"paperless_always_send_as_pdf_file\") ||\n false;\n\n console.log(\n `Paperless configuration provided, post document url: ${paperlessPostDocumentUrl}, the token length: ${configPaperlessToken.length}, keepFiles: ${configPaperlessKeepFiles}`,\n );\n return {\n postDocumentUrl: paperlessPostDocumentUrl,\n authToken: configPaperlessToken,\n keepFiles: configPaperlessKeepFiles,\n groupMultiPageScanIntoAPdf: groupMultiPageScanIntoAPdf,\n alwaysSendAsPdfFile: alwaysSendAsPdfFile,\n };\n } else {\n return undefined;\n }\n}\n\nfunction getNextcloudConfig(\n parentOption: OptionValues,\n): NextcloudConfig | undefined {\n const configNextcloudUrl: string =\n parentOption.nextcloudUrl || getConfig(\"nextcloud_url\");\n const configNextcloudUsername: string =\n parentOption.nextcloudUsername || getConfig(\"nextcloud_username\");\n let configNextcloudPassword: string =\n parentOption.nextcloudPassword || getConfig(\"nextcloud_password\");\n const configNextcloudPasswordFile: string =\n parentOption.nextcloudPasswordFile || getConfig(\"nextcloud_password_file\");\n\n if (\n configNextcloudUrl &&\n configNextcloudUsername &&\n (configNextcloudPassword || configNextcloudPasswordFile)\n ) {\n const configNextcloudUploadFolder =\n parentOption.nextcloudUploadFolder ||\n getConfig(\"nextcloud_upload_folder\") ||\n \"scan\";\n const configNextcloudKeepFiles: boolean =\n parentOption.keepFiles || getConfig(\"keep_files\") || false;\n\n if (configNextcloudPasswordFile) {\n configNextcloudPassword = fs\n .readFileSync(configNextcloudPasswordFile, \"utf8\")\n .trimEnd();\n }\n\n console.log(\n `Nextcloud configuration provided, url: ${configNextcloudUrl}, username: ${configNextcloudUsername}, password length: ${configNextcloudPassword.length}, upload folder: ${configNextcloudUploadFolder}, keepFiles: ${configNextcloudKeepFiles}`,\n );\n return {\n baseUrl: configNextcloudUrl,\n username: configNextcloudUsername,\n password: configNextcloudPassword,\n uploadFolder: configNextcloudUploadFolder,\n keepFiles: configNextcloudKeepFiles,\n };\n } else {\n return undefined;\n }\n}\n\nfunction getHealthCheckSetting(option: OptionValues) {\n const healthCheckEnabled: boolean =\n option.healthCheck || getConfig(\"enableHealthCheck\") === true;\n let healthCheckPort: number;\n if (option.healthCheckPort) {\n healthCheckPort = parseInt(option.healthCheckPort, 10);\n } else {\n healthCheckPort = getConfig<number>(\"healthCheckPort\") || 3000;\n }\n return {\n isHealthCheckEnabled: healthCheckEnabled,\n healthCheckPort: healthCheckPort,\n };\n}\n\nfunction getScanConfiguration(option: OptionValues) {\n const directoryConfig: DirectoryConfig = {\n directory: option.directory || getConfig(\"directory\"),\n tempDirectory: option.tempDirectory || getConfig(\"tempDirectory\"),\n filePattern: option.pattern || getConfig(\"pattern\"),\n };\n\n const configWidth = (option.width || getConfig(\"width\") || 0).toString();\n const width =\n configWidth.toLowerCase() === \"max\"\n ? Number.MAX_SAFE_INTEGER\n : parseInt(configWidth, 10);\n\n const configHeight = (option.width || getConfig(\"height\") || \"0\").toString();\n const height =\n configWidth.toLowerCase() === \"max\"\n ? Number.MAX_SAFE_INTEGER\n : parseInt(configHeight, 10);\n\n const paperlessConfig = getPaperlessConfig(option);\n const nextcloudConfig = getNextcloudConfig(option);\n\n const scanConfig: ScanConfig = {\n resolution: parseInt(\n option.resolution || getConfig(\"resolution\") || \"200\",\n 10,\n ),\n width: width,\n height: height,\n directoryConfig,\n paperlessConfig,\n nextcloudConfig,\n };\n return scanConfig;\n}\n\nfunction getDeviceUpPollingInterval(parentOption: OptionValues) {\n return (\n parentOption.deviceUpPollingInterval ||\n getConfig(\"deviceUpPollingInterval\") ||\n 1000\n );\n}\n\nasync function main() {\n setupParameterOpts(program);\n const cmdListen = program.createCommand(\"listen\");\n setupScanParameters(cmdListen)\n .description(\"Listen the device for new scan job to save to this target\")\n .option(\n \"-l, --label <label>\",\n \"The label to display on the device (the default is the hostname)\",\n )\n .addOption(\n new Option(\"--health-check\", \"Start an http health check endpoint\"),\n )\n .addOption(\n new Option(\n \"--health-check-port <health-check-port>\",\n \"Start an http health check endpoint\",\n ),\n )\n .action(async (options, cmd) => {\n const parentOption = cmd.parent.opts();\n\n const ip = await getDeviceIp(parentOption);\n HPApi.setDeviceIP(ip);\n\n const isDebug = getIsDebug(parentOption);\n HPApi.setDebug(isDebug);\n\n const registrationConfig: RegistrationConfig = {\n label: options.label || getConfig(\"label\") || os.hostname(),\n };\n\n const deviceUpPollingInterval = getDeviceUpPollingInterval(parentOption);\n\n const healthCheckSetting = getHealthCheckSetting(options);\n if (healthCheckSetting.isHealthCheckEnabled) {\n startHealthCheckServer(healthCheckSetting.healthCheckPort);\n }\n\n const scanConfig = getScanConfiguration(options);\n\n await listenCmd(registrationConfig, scanConfig, deviceUpPollingInterval);\n });\n program.addCommand(cmdListen, { isDefault: true });\n\n const cmdAdfAutoscan = program.createCommand(\"adf-autoscan\");\n setupScanParameters(cmdAdfAutoscan)\n .addOption(\n new Option(\"--duplex\", \"If specified, the scan will be in duplex\"),\n )\n .addOption(\n new Option(\n \"--pdf\",\n \"If specified, the scan result will be a pdf document, the default is multiple jpeg files\",\n ),\n )\n .addOption(\n new Option(\n \"--pollingInterval <pollingInterval>\",\n \"Time interval in millisecond between each lookup for content in the automatic document feeder\",\n ),\n )\n .description(\n \"Automatically trigger a new scan job to this target once paper is detected in the automatic document feeder (adf)\",\n )\n .addOption(\n new Option(\n \"--start-scan-delay <startScanDelay>\",\n \"Once document are detected to be in the adf, this specify the wait delay in millisecond before triggering the scan\",\n ),\n )\n .addOption(\n new Option(\"--health-check\", \"Start an http health check endpoint\"),\n )\n .addOption(\n new Option(\n \"--health-check-port <port>\",\n \"Start an http health check endpoint\",\n ),\n )\n .description(\n \"Automatically trigger a new scan job to this target once paper is detected in the automatic document feeder (adf)\",\n )\n .action(async (options, cmd) => {\n const parentOption = cmd.parent.opts();\n\n const ip = await getDeviceIp(parentOption);\n HPApi.setDeviceIP(ip);\n\n const isDebug = getIsDebug(parentOption);\n HPApi.setDebug(isDebug);\n\n const deviceUpPollingInterval = getDeviceUpPollingInterval(parentOption);\n\n const healthCheckSetting = getHealthCheckSetting(options);\n if (healthCheckSetting.isHealthCheckEnabled) {\n startHealthCheckServer(healthCheckSetting.healthCheckPort);\n }\n\n const scanConfig = getScanConfiguration(options);\n\n const adfScanConfig: AdfAutoScanConfig = {\n ...scanConfig,\n isDuplex: options.isDuplex || getConfig(\"autoscan_duplex\") || false,\n generatePdf: options.pdf || getConfig(\"autoscan_pdf\") || false,\n pollingInterval:\n options.pollingInterval ||\n getConfig(\"autoscan_pollingInterval\") ||\n 1000,\n startScanDelay:\n options.startScanDelay ||\n getConfig(\"autoscan_startScanDelay\") ||\n 5000,\n };\n\n await adfAutoscanCmd(adfScanConfig, deviceUpPollingInterval);\n });\n program.addCommand(cmdAdfAutoscan);\n\n const cmdClearRegistrations = program.createCommand(\"clear-registrations\");\n cmdClearRegistrations\n .description(\"Clear the list or registered target on the device\")\n .action(async (options, cmd) => {\n await clearRegistrationsCmd(cmd);\n });\n program.addCommand(cmdClearRegistrations);\n\n await program.parseAsync(process.argv);\n}\n\nconsole.log(`Current commit ID: ${commitInfo.commitId}`);\nmain().catch((err) => console.log(err));\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NextcloudConfig.js","sourceRoot":"","sources":["../../src/nextcloud/NextcloudConfig.ts"],"names":[],"mappings":"","sourcesContent":["export type NextcloudConfig = {\n baseUrl: string;\n username: string;\n password: string;\n uploadFolder: string;\n keepFiles: boolean;\n};\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ScanContent } from "../ScanContent";
|
|
2
|
+
import { NextcloudConfig } from "./NextcloudConfig";
|
|
3
|
+
export declare function uploadImagesToNextcloud(scanJobContent: ScanContent, nextcloudConfig: NextcloudConfig): Promise<void>;
|
|
4
|
+
export declare function uploadPdfToNextcloud(pdfFilePath: string | null, nextcloudConfig: NextcloudConfig): Promise<void>;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.uploadPdfToNextcloud = exports.uploadImagesToNextcloud = void 0;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
async function uploadImagesToNextcloud(scanJobContent, nextcloudConfig) {
|
|
11
|
+
await checkFolderAndUpload(nextcloudConfig, async () => {
|
|
12
|
+
for (const element of scanJobContent.elements) {
|
|
13
|
+
const { path: filePath } = element;
|
|
14
|
+
await uploadToNextcloud(filePath, nextcloudConfig);
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
exports.uploadImagesToNextcloud = uploadImagesToNextcloud;
|
|
19
|
+
async function uploadPdfToNextcloud(pdfFilePath, nextcloudConfig) {
|
|
20
|
+
await checkFolderAndUpload(nextcloudConfig, async () => {
|
|
21
|
+
if (pdfFilePath) {
|
|
22
|
+
await uploadToNextcloud(pdfFilePath, nextcloudConfig);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
console.log("Pdf generation has failed, nothing is going to be uploaded to Nextcloud");
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
exports.uploadPdfToNextcloud = uploadPdfToNextcloud;
|
|
30
|
+
async function uploadToNextcloud(filePath, nextcloudConfig) {
|
|
31
|
+
const { baseUrl, username, password, uploadFolder } = nextcloudConfig;
|
|
32
|
+
const fileName = path_1.default.basename(filePath);
|
|
33
|
+
const folderUrl = buildFolderUrl(baseUrl, username, uploadFolder);
|
|
34
|
+
const uploadUrl = buildUrl(folderUrl, [fileName]);
|
|
35
|
+
let fileBuffer;
|
|
36
|
+
try {
|
|
37
|
+
fileBuffer = await promises_1.default.readFile(filePath);
|
|
38
|
+
}
|
|
39
|
+
catch (e) {
|
|
40
|
+
console.error("Fail to read file:", e);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const auth = { username, password };
|
|
44
|
+
console.log(`Start uploading to Nextcloud: ${fileName}`);
|
|
45
|
+
try {
|
|
46
|
+
const response = await (0, axios_1.default)({
|
|
47
|
+
method: "PUT",
|
|
48
|
+
url: uploadUrl,
|
|
49
|
+
auth,
|
|
50
|
+
data: fileBuffer,
|
|
51
|
+
});
|
|
52
|
+
let action;
|
|
53
|
+
if (response.status === 201) {
|
|
54
|
+
action = "created";
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
action = "updated";
|
|
58
|
+
}
|
|
59
|
+
console.log(`Document successfully ${action} file at Nextcloud. (Folder: ${uploadFolder}, File: ${fileName})`);
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
console.error("Fail to upload document:", error);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async function checkFolderAndUpload(nextcloudConfig, uploadFunction) {
|
|
66
|
+
const folderExists = await checkNextcloudFolderExists(nextcloudConfig);
|
|
67
|
+
if (!folderExists) {
|
|
68
|
+
console.log("Upload folder does not exist or user has no permission; skipping upload");
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
await uploadFunction();
|
|
72
|
+
}
|
|
73
|
+
async function checkNextcloudFolderExists(nextcloudConfig) {
|
|
74
|
+
var _a, _b;
|
|
75
|
+
const { baseUrl, username, password, uploadFolder } = nextcloudConfig;
|
|
76
|
+
const folderUrl = buildFolderUrl(baseUrl, username, uploadFolder);
|
|
77
|
+
const auth = { username, password };
|
|
78
|
+
console.log("Check if upload folder exists");
|
|
79
|
+
try {
|
|
80
|
+
// Check if the upload folder exists
|
|
81
|
+
await (0, axios_1.default)({
|
|
82
|
+
method: "PROPFIND",
|
|
83
|
+
url: folderUrl,
|
|
84
|
+
auth,
|
|
85
|
+
headers: { Depth: 0 },
|
|
86
|
+
});
|
|
87
|
+
console.log(`Found upload folder '${uploadFolder}' in Nextcloud`);
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
const axiosError = error;
|
|
91
|
+
if (((_a = axiosError.response) === null || _a === void 0 ? void 0 : _a.status) === 404) {
|
|
92
|
+
console.warn(`Upload folder '${uploadFolder}' not found in Nextcloud`);
|
|
93
|
+
}
|
|
94
|
+
else if (((_b = axiosError.response) === null || _b === void 0 ? void 0 : _b.status) === 401) {
|
|
95
|
+
console.warn(`User has no permission to access upload folder '${uploadFolder}' in Nextcloud`);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
console.error("Fail to check upload folder exists:", axiosError.toJSON());
|
|
99
|
+
}
|
|
100
|
+
console.trace("Error response:", axiosError.response);
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
function buildFolderUrl(baseUrl, username, uploadFolder) {
|
|
106
|
+
return buildUrl(baseUrl, [
|
|
107
|
+
"remote.php",
|
|
108
|
+
"dav",
|
|
109
|
+
"files",
|
|
110
|
+
username,
|
|
111
|
+
uploadFolder,
|
|
112
|
+
]);
|
|
113
|
+
}
|
|
114
|
+
function buildUrl(baseUrl, path) {
|
|
115
|
+
const url = new URL(baseUrl);
|
|
116
|
+
const search = /^\/+|\/+$/g;
|
|
117
|
+
path.forEach((part) => {
|
|
118
|
+
url.pathname = `${url.pathname.replace(search, "")}/${encodeURIComponent(part.replace(search, ""))}`;
|
|
119
|
+
});
|
|
120
|
+
return url.toString();
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=nextcloud.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nextcloud.js","sourceRoot":"","sources":["../../src/nextcloud/nextcloud.ts"],"names":[],"mappings":"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","sourcesContent":["import axios, { AxiosError } from \"axios\";\nimport { ScanContent } from \"../ScanContent\";\nimport { NextcloudConfig } from \"./NextcloudConfig\";\nimport fs from \"fs/promises\";\nimport path from \"path\";\n\nexport async function uploadImagesToNextcloud(\n scanJobContent: ScanContent,\n nextcloudConfig: NextcloudConfig,\n) {\n await checkFolderAndUpload(nextcloudConfig, async () => {\n for (const element of scanJobContent.elements) {\n const { path: filePath } = element;\n await uploadToNextcloud(filePath, nextcloudConfig);\n }\n });\n}\n\nexport async function uploadPdfToNextcloud(\n pdfFilePath: string | null,\n nextcloudConfig: NextcloudConfig,\n) {\n await checkFolderAndUpload(nextcloudConfig, async () => {\n if (pdfFilePath) {\n await uploadToNextcloud(pdfFilePath, nextcloudConfig);\n } else {\n console.log(\n \"Pdf generation has failed, nothing is going to be uploaded to Nextcloud\",\n );\n }\n });\n}\n\nasync function uploadToNextcloud(\n filePath: string,\n nextcloudConfig: NextcloudConfig,\n): Promise<void> {\n const { baseUrl, username, password, uploadFolder } = nextcloudConfig;\n const fileName = path.basename(filePath);\n\n const folderUrl = buildFolderUrl(baseUrl, username, uploadFolder);\n const uploadUrl = buildUrl(folderUrl, [fileName]);\n\n let fileBuffer: Buffer;\n try {\n fileBuffer = await fs.readFile(filePath);\n } catch (e) {\n console.error(\"Fail to read file:\", e);\n return;\n }\n const auth = { username, password };\n\n console.log(`Start uploading to Nextcloud: ${fileName}`);\n try {\n const response = await axios({\n method: \"PUT\",\n url: uploadUrl,\n auth,\n data: fileBuffer,\n });\n\n let action: string;\n if (response.status === 201) {\n action = \"created\";\n } else {\n action = \"updated\";\n }\n console.log(\n `Document successfully ${action} file at Nextcloud. (Folder: ${uploadFolder}, File: ${fileName})`,\n );\n } catch (error) {\n console.error(\"Fail to upload document:\", error);\n }\n}\n\nasync function checkFolderAndUpload(\n nextcloudConfig: NextcloudConfig,\n uploadFunction: () => Promise<void>,\n) {\n const folderExists = await checkNextcloudFolderExists(nextcloudConfig);\n if (!folderExists) {\n console.log(\n \"Upload folder does not exist or user has no permission; skipping upload\",\n );\n return;\n }\n\n await uploadFunction();\n}\n\nasync function checkNextcloudFolderExists(\n nextcloudConfig: NextcloudConfig,\n): Promise<boolean> {\n const { baseUrl, username, password, uploadFolder } = nextcloudConfig;\n const folderUrl = buildFolderUrl(baseUrl, username, uploadFolder);\n const auth = { username, password };\n\n console.log(\"Check if upload folder exists\");\n try {\n // Check if the upload folder exists\n await axios({\n method: \"PROPFIND\",\n url: folderUrl,\n auth,\n headers: { Depth: 0 },\n });\n console.log(`Found upload folder '${uploadFolder}' in Nextcloud`);\n } catch (error) {\n const axiosError = error as AxiosError;\n if (axiosError.response?.status === 404) {\n console.warn(`Upload folder '${uploadFolder}' not found in Nextcloud`);\n } else if (axiosError.response?.status === 401) {\n console.warn(\n `User has no permission to access upload folder '${uploadFolder}' in Nextcloud`,\n );\n } else {\n console.error(\"Fail to check upload folder exists:\", axiosError.toJSON());\n }\n console.trace(\"Error response:\", axiosError.response);\n return false;\n }\n return true;\n}\n\nfunction buildFolderUrl(\n baseUrl: string,\n username: string,\n uploadFolder: string,\n) {\n return buildUrl(baseUrl, [\n \"remote.php\",\n \"dav\",\n \"files\",\n username,\n uploadFolder,\n ]);\n}\n\nfunction buildUrl(baseUrl: string, path: string[]): string {\n const url = new URL(baseUrl);\n const search = /^\\/+|\\/+$/g;\n path.forEach((part) => {\n url.pathname = `${url.pathname.replace(search, \"\")}/${encodeURIComponent(part.replace(search, \"\"))}`;\n });\n return url.toString();\n}\n"]}
|
|
@@ -13,10 +13,6 @@ async function uploadImagesAsSeparateDocumentsToPaperless(scanJobContent, paperl
|
|
|
13
13
|
for (let i = 0; i < scanJobContent.elements.length; ++i) {
|
|
14
14
|
const filePath = scanJobContent.elements[i].path;
|
|
15
15
|
await uploadToPaperless(filePath, paperlessConfig);
|
|
16
|
-
if (!paperlessConfig.keepFiles) {
|
|
17
|
-
await promises_1.default.unlink(filePath);
|
|
18
|
-
console.log(`Image document ${filePath} has been removed from the filesystem`);
|
|
19
|
-
}
|
|
20
16
|
}
|
|
21
17
|
}
|
|
22
18
|
exports.uploadImagesAsSeparateDocumentsToPaperless = uploadImagesAsSeparateDocumentsToPaperless;
|
|
@@ -49,10 +45,6 @@ exports.mergeToPdfAndUploadAsSingleDocumentToPaperless = mergeToPdfAndUploadAsSi
|
|
|
49
45
|
async function uploadPdfToPaperless(pdfFilePath, paperlessConfig) {
|
|
50
46
|
if (pdfFilePath) {
|
|
51
47
|
await uploadToPaperless(pdfFilePath, paperlessConfig);
|
|
52
|
-
if (!paperlessConfig.keepFiles) {
|
|
53
|
-
await promises_1.default.unlink(pdfFilePath);
|
|
54
|
-
console.log(`Pdf document ${pdfFilePath} has been removed from the filesystem`);
|
|
55
|
-
}
|
|
56
48
|
}
|
|
57
49
|
else {
|
|
58
50
|
console.log("Pdf generation has failed, nothing is going to be uploaded to paperless");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paperless.js","sourceRoot":"","sources":["../../src/paperless/paperless.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAwB;AACxB,0DAAiC;AACjC,kDAA0B;AAG1B,2DAA6B;AAC7B,oDAA4D;AAGrD,KAAK,UAAU,0CAA0C,CAC9D,cAA2B,EAC3B,eAAgC;IAEhC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE;QACvD,MAAM,QAAQ,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACjD,MAAM,iBAAiB,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"paperless.js","sourceRoot":"","sources":["../../src/paperless/paperless.ts"],"names":[],"mappings":"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","sourcesContent":["import fsSync from \"fs\";\nimport FormData from \"form-data\";\nimport axios from \"axios\";\nimport { ScanConfig } from \"../scanProcessing\";\nimport { ScanContent } from \"../ScanContent\";\nimport fs from \"fs/promises\";\nimport { convertToPdf, mergeToPdf } from \"../pdfProcessing\";\nimport { PaperlessConfig } from \"./PaperlessConfig\";\n\nexport async function uploadImagesAsSeparateDocumentsToPaperless(\n scanJobContent: ScanContent,\n paperlessConfig: PaperlessConfig,\n) {\n for (let i = 0; i < scanJobContent.elements.length; ++i) {\n const filePath = scanJobContent.elements[i].path;\n await uploadToPaperless(filePath, paperlessConfig);\n }\n}\n\nexport async function convertImagesToPdfAndUploadAsSeparateDocumentsToPaperless(\n scanJobContent: ScanContent,\n paperlessConfig: PaperlessConfig,\n) {\n for (let i = 0; i < scanJobContent.elements.length; ++i) {\n const pdfFilePath = await convertToPdf(\n scanJobContent.elements[i],\n !paperlessConfig.keepFiles,\n );\n if (pdfFilePath) {\n await uploadToPaperless(pdfFilePath, paperlessConfig);\n await fs.unlink(pdfFilePath);\n } else {\n console.log(\n \"Pdf generation has failed, nothing is going to be uploaded to paperless for: \" +\n scanJobContent.elements[i].path,\n );\n }\n }\n}\n\nexport async function mergeToPdfAndUploadAsSingleDocumentToPaperless(\n folder: string,\n scanCount: number,\n scanJobContent: ScanContent,\n scanConfig: ScanConfig,\n scanDate: Date,\n paperlessConfig: PaperlessConfig,\n) {\n const pdfFilePath = await mergeToPdf(\n folder,\n scanCount,\n scanJobContent,\n scanConfig.directoryConfig.filePattern,\n scanDate,\n !paperlessConfig.keepFiles,\n );\n if (pdfFilePath) {\n await uploadToPaperless(pdfFilePath, paperlessConfig);\n await fs.unlink(pdfFilePath);\n console.log(\n `Pdf document ${pdfFilePath} has been removed from the filesystem`,\n );\n } else {\n console.log(\n \"Pdf generation has failed, nothing is going to be uploaded to paperless\",\n );\n }\n}\n\nexport async function uploadPdfToPaperless(\n pdfFilePath: string | null,\n paperlessConfig: PaperlessConfig,\n) {\n if (pdfFilePath) {\n await uploadToPaperless(pdfFilePath, paperlessConfig);\n } else {\n console.log(\n \"Pdf generation has failed, nothing is going to be uploaded to paperless\",\n );\n }\n}\n\nasync function uploadToPaperless(\n filePath: string,\n paperlessConfig: PaperlessConfig,\n): Promise<void> {\n const url = paperlessConfig.postDocumentUrl;\n\n const authToken = paperlessConfig.authToken;\n\n const fileStream = fsSync.createReadStream(filePath);\n\n const form = new FormData();\n form.append(\"document\", fileStream);\n\n console.log(`Start uploading to paperless: ${filePath}`);\n try {\n const response = await axios.post(url, form, {\n headers: {\n ...form.getHeaders(),\n Authorization: `Token ${authToken}`,\n },\n });\n\n console.log(\"Document successfully uploaded to paperless:\", response.data);\n } catch (error) {\n console.error(\"Fail to upload document:\", error);\n }\n fileStream.close();\n}\n"]}
|
package/dist/postProcessing.js
CHANGED
|
@@ -1,35 +1,58 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.postProcessing = void 0;
|
|
4
7
|
const pdfProcessing_1 = require("./pdfProcessing");
|
|
5
8
|
const paperless_1 = require("./paperless/paperless");
|
|
9
|
+
const nextcloud_1 = require("./nextcloud/nextcloud");
|
|
10
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
6
11
|
async function postProcessing(scanConfig, folder, tempFolder, scanCount, scanJobContent, scanDate, toPdf) {
|
|
7
|
-
const paperlessConfig = scanConfig.paperlessConfig;
|
|
8
12
|
if (toPdf) {
|
|
9
|
-
|
|
10
|
-
displayPdfScan(pdfFilePath, scanJobContent);
|
|
11
|
-
if (paperlessConfig) {
|
|
12
|
-
await (0, paperless_1.uploadPdfToPaperless)(pdfFilePath, paperlessConfig);
|
|
13
|
-
}
|
|
13
|
+
await handlePdfProcessing(folder, tempFolder, scanCount, scanJobContent, scanDate, scanConfig);
|
|
14
14
|
}
|
|
15
15
|
else {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
await handleImageProcessing(folder, scanCount, scanJobContent, scanDate, scanConfig);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.postProcessing = postProcessing;
|
|
20
|
+
async function handlePdfProcessing(folder, tempFolder, scanCount, scanJobContent, scanDate, scanConfig) {
|
|
21
|
+
const paperlessConfig = scanConfig.paperlessConfig;
|
|
22
|
+
const nextcloudConfig = scanConfig.nextcloudConfig;
|
|
23
|
+
const pdfFilePath = await (0, pdfProcessing_1.mergeToPdf)(paperlessConfig ? tempFolder : folder, scanCount, scanJobContent, scanConfig.directoryConfig.filePattern, scanDate, true);
|
|
24
|
+
displayPdfScan(pdfFilePath, scanJobContent);
|
|
25
|
+
if (paperlessConfig) {
|
|
26
|
+
await (0, paperless_1.uploadPdfToPaperless)(pdfFilePath, paperlessConfig);
|
|
27
|
+
}
|
|
28
|
+
if (nextcloudConfig) {
|
|
29
|
+
await (0, nextcloud_1.uploadPdfToNextcloud)(pdfFilePath, nextcloudConfig);
|
|
30
|
+
}
|
|
31
|
+
await cleanUpFilesIfNeeded([pdfFilePath], paperlessConfig, nextcloudConfig);
|
|
32
|
+
}
|
|
33
|
+
async function handleImageProcessing(folder, scanCount, scanJobContent, scanDate, scanConfig) {
|
|
34
|
+
const paperlessConfig = scanConfig.paperlessConfig;
|
|
35
|
+
const nextcloudConfig = scanConfig.nextcloudConfig;
|
|
36
|
+
displayJpegScan(scanJobContent);
|
|
37
|
+
if (paperlessConfig) {
|
|
38
|
+
if (paperlessConfig.groupMultiPageScanIntoAPdf) {
|
|
39
|
+
await (0, paperless_1.mergeToPdfAndUploadAsSingleDocumentToPaperless)(folder, scanCount, scanJobContent, scanConfig, scanDate, paperlessConfig);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
if (paperlessConfig.alwaysSendAsPdfFile) {
|
|
43
|
+
await (0, paperless_1.convertImagesToPdfAndUploadAsSeparateDocumentsToPaperless)(scanJobContent, paperlessConfig);
|
|
20
44
|
}
|
|
21
45
|
else {
|
|
22
|
-
|
|
23
|
-
await (0, paperless_1.convertImagesToPdfAndUploadAsSeparateDocumentsToPaperless)(scanJobContent, paperlessConfig);
|
|
24
|
-
}
|
|
25
|
-
else {
|
|
26
|
-
await (0, paperless_1.uploadImagesAsSeparateDocumentsToPaperless)(scanJobContent, paperlessConfig);
|
|
27
|
-
}
|
|
46
|
+
await (0, paperless_1.uploadImagesAsSeparateDocumentsToPaperless)(scanJobContent, paperlessConfig);
|
|
28
47
|
}
|
|
29
48
|
}
|
|
30
49
|
}
|
|
50
|
+
if (nextcloudConfig) {
|
|
51
|
+
await (0, nextcloud_1.uploadImagesToNextcloud)(scanJobContent, nextcloudConfig);
|
|
52
|
+
}
|
|
53
|
+
const filePaths = scanJobContent.elements.map((element) => element.path);
|
|
54
|
+
await cleanUpFilesIfNeeded(filePaths, paperlessConfig, nextcloudConfig);
|
|
31
55
|
}
|
|
32
|
-
exports.postProcessing = postProcessing;
|
|
33
56
|
function displayPdfScan(pdfFilePath, scanJobContent) {
|
|
34
57
|
if (pdfFilePath === null) {
|
|
35
58
|
console.log(`Pdf generated has not been generated`);
|
|
@@ -41,4 +64,14 @@ function displayPdfScan(pdfFilePath, scanJobContent) {
|
|
|
41
64
|
function displayJpegScan(scanJobContent) {
|
|
42
65
|
scanJobContent.elements.forEach((e) => console.log(`\t- page ${e.pageNumber.toString().padStart(3, " ")} - ${e.width}x${e.height} - ${e.path}`));
|
|
43
66
|
}
|
|
67
|
+
async function cleanUpFilesIfNeeded(filePaths, paperlessConfig, nextcloudConfig) {
|
|
68
|
+
if (!(paperlessConfig === null || paperlessConfig === void 0 ? void 0 : paperlessConfig.keepFiles) && !(nextcloudConfig === null || nextcloudConfig === void 0 ? void 0 : nextcloudConfig.keepFiles)) {
|
|
69
|
+
await Promise.all(filePaths.map(async (filePath) => {
|
|
70
|
+
if (filePath) {
|
|
71
|
+
await promises_1.default.unlink(filePath);
|
|
72
|
+
console.log(`File ${filePath} has been removed from the filesystem`);
|
|
73
|
+
}
|
|
74
|
+
}));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
44
77
|
//# sourceMappingURL=postProcessing.js.map
|