node-hp-scan-to 1.6.1 → 1.7.1
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 +247 -143
- package/dist/Destination.js +17 -7
- package/dist/Destination.js.map +1 -1
- package/dist/DeviceCapabilities.d.ts +2 -0
- package/dist/DeviceCapabilities.js.map +1 -1
- package/dist/DiscoveryTree.js.map +1 -1
- package/dist/Event.js.map +1 -1
- package/dist/EventTable.js.map +1 -1
- package/dist/HPApi.js +23 -15
- package/dist/HPApi.js.map +1 -1
- package/dist/InputSource.js +1 -1
- package/dist/InputSource.js.map +1 -1
- package/dist/Job.js +6 -6
- package/dist/Job.js.map +1 -1
- package/dist/JpegUtil.d.ts +0 -2
- package/dist/JpegUtil.js.map +1 -1
- package/dist/KnownShortcut.js.map +1 -1
- package/dist/PathHelper.js +2 -0
- package/dist/PathHelper.js.map +1 -1
- package/dist/ScanCaps.d.ts +6 -0
- package/dist/ScanCaps.js +18 -0
- package/dist/ScanCaps.js.map +1 -1
- package/dist/ScanContent.js.map +1 -1
- package/dist/ScanJobManifest.js.map +1 -1
- package/dist/ScanJobSettings.js.map +1 -1
- package/dist/ScanStatus.js.map +1 -1
- package/dist/WalkupScanDestination.js.map +1 -1
- package/dist/WalkupScanDestinations.js.map +1 -1
- package/dist/WalkupScanManifest.js.map +1 -1
- package/dist/WalkupScanToCompCaps.js.map +1 -1
- package/dist/WalkupScanToCompDestination.js.map +1 -1
- package/dist/WalkupScanToCompDestinations.js.map +1 -1
- package/dist/WalkupScanToCompEvent.js.map +1 -1
- package/dist/WalkupScanToCompManifest.js.map +1 -1
- package/dist/commitInfo.json +1 -1
- package/dist/delay.js +1 -2
- package/dist/delay.js.map +1 -1
- package/dist/healthcheck.js +1 -2
- package/dist/healthcheck.js.map +1 -1
- package/dist/index.js +22 -12
- package/dist/index.js.map +1 -1
- package/dist/listening.js +5 -6
- package/dist/listening.js.map +1 -1
- package/dist/nextcloud/NextcloudConfig.js.map +1 -1
- package/dist/nextcloud/nextcloud.js +4 -6
- package/dist/nextcloud/nextcloud.js.map +1 -1
- package/dist/paperless/PaperlessConfig.js.map +1 -1
- package/dist/paperless/paperless.js +4 -5
- package/dist/paperless/paperless.js.map +1 -1
- package/dist/pdfProcessing.js +4 -5
- package/dist/pdfProcessing.js.map +1 -1
- package/dist/postProcessing.js +2 -4
- package/dist/postProcessing.js.map +1 -1
- package/dist/readDeviceCapabilities.js +24 -20
- package/dist/readDeviceCapabilities.js.map +1 -1
- package/dist/scanProcessing.d.ts +2 -2
- package/dist/scanProcessing.js +28 -30
- package/dist/scanProcessing.js.map +1 -1
- package/package.json +19 -17
- package/dist/PaperlessCOnfig.d.ts +0 -7
- package/dist/PaperlessCOnfig.js +0 -3
- package/dist/PaperlessCOnfig.js.map +0 -1
- package/dist/PaperlessConfig.d.ts +0 -7
- package/dist/PaperlessConfig.js +0 -3
- package/dist/PaperlessConfig.js.map +0 -1
- package/dist/paperless.d.ts +0 -7
- package/dist/paperless.js +0 -83
- package/dist/paperless.js.map +0 -1
- package/dist/test/DiscoveryTree.test.d.ts +0 -1
- package/dist/test/DiscoveryTree.test.js +0 -68
- package/dist/test/DiscoveryTree.test.js.map +0 -1
- package/dist/test/EtagEventTable.test.d.ts +0 -1
- package/dist/test/EtagEventTable.test.js +0 -93
- package/dist/test/EtagEventTable.test.js.map +0 -1
- package/dist/test/Job.test.d.ts +0 -1
- package/dist/test/Job.test.js +0 -104
- package/dist/test/Job.test.js.map +0 -1
- package/dist/test/JpegUtil.test.d.ts +0 -1
- package/dist/test/JpegUtil.test.js +0 -53
- package/dist/test/JpegUtil.test.js.map +0 -1
- package/dist/test/PathHelper.test.d.ts +0 -1
- package/dist/test/PathHelper.test.js +0 -98
- package/dist/test/PathHelper.test.js.map +0 -1
- package/dist/test/ScanCaps.test.d.ts +0 -1
- package/dist/test/ScanCaps.test.js +0 -96
- package/dist/test/ScanCaps.test.js.map +0 -1
- package/dist/test/ScanJobManifest.test.d.ts +0 -1
- package/dist/test/ScanJobManifest.test.js +0 -56
- package/dist/test/ScanJobManifest.test.js.map +0 -1
- package/dist/test/ScanJobSettings.test.d.ts +0 -1
- package/dist/test/ScanJobSettings.test.js +0 -59
- package/dist/test/ScanJobSettings.test.js.map +0 -1
- package/dist/test/ScanStatus.test.d.ts +0 -1
- package/dist/test/ScanStatus.test.js +0 -75
- package/dist/test/ScanStatus.test.js.map +0 -1
- package/dist/test/WalkupScanDestination.test.d.ts +0 -1
- package/dist/test/WalkupScanDestination.test.js +0 -80
- package/dist/test/WalkupScanDestination.test.js.map +0 -1
- package/dist/test/WalkupScanDestinations.test.d.ts +0 -1
- package/dist/test/WalkupScanDestinations.test.js +0 -68
- package/dist/test/WalkupScanDestinations.test.js.map +0 -1
- package/dist/test/WalkupScanManifest.test.d.ts +0 -1
- package/dist/test/WalkupScanManifest.test.js +0 -46
- package/dist/test/WalkupScanManifest.test.js.map +0 -1
- package/dist/test/WalkupScanToCompCaps.test.d.ts +0 -1
- package/dist/test/WalkupScanToCompCaps.test.js +0 -56
- package/dist/test/WalkupScanToCompCaps.test.js.map +0 -1
- package/dist/test/WalkupScanToCompDestination.test.d.ts +0 -1
- package/dist/test/WalkupScanToCompDestination.test.js +0 -58
- package/dist/test/WalkupScanToCompDestination.test.js.map +0 -1
- package/dist/test/WalkupScanToCompDestinations.test.d.ts +0 -1
- package/dist/test/WalkupScanToCompDestinations.test.js +0 -58
- package/dist/test/WalkupScanToCompDestinations.test.js.map +0 -1
- package/dist/test/WalkupScanToCompEvent.test.d.ts +0 -1
- package/dist/test/WalkupScanToCompEvent.test.js +0 -46
- package/dist/test/WalkupScanToCompEvent.test.js.map +0 -1
- package/dist/test/WalkupScanToCompManifest.test.d.ts +0 -1
- package/dist/test/WalkupScanToCompManifest.test.js +0 -46
- package/dist/test/WalkupScanToCompManifest.test.js.map +0 -1
- package/dist/test/clean.d.ts +0 -1
- package/dist/test/clean.js +0 -21
- package/dist/test/clean.js.map +0 -1
- package/dist/test/nextcloud.test.d.ts +0 -1
- package/dist/test/nextcloud.test.js +0 -165
- package/dist/test/nextcloud.test.js.map +0 -1
- package/dist/test/scanProcessing.test.d.ts +0 -1
- package/dist/test/scanProcessing.test.js +0 -105
- package/dist/test/scanProcessing.test.js.map +0 -1
- package/dist/test-bonjour.d.ts +0 -1
- package/dist/test-bonjour.js +0 -20
- package/dist/test-bonjour.js.map +0 -1
- package/nodemon.json +0 -6
- package/src/Destination.ts +0 -63
- package/src/DeviceCapabilities.ts +0 -8
- package/src/DiscoveryTree.ts +0 -56
- package/src/Event.ts +0 -55
- package/src/EventTable.ts +0 -45
- package/src/HPApi.ts +0 -510
- package/src/InputSource.ts +0 -4
- package/src/Job.ts +0 -134
- package/src/JpegUtil.ts +0 -327
- package/src/KnownShortcut.ts +0 -6
- package/src/PathHelper.ts +0 -106
- package/src/ScanCaps.ts +0 -81
- package/src/ScanContent.ts +0 -15
- package/src/ScanJobManifest.ts +0 -56
- package/src/ScanJobSettings.ts +0 -84
- package/src/ScanStatus.ts +0 -48
- package/src/WalkupScanDestination.ts +0 -74
- package/src/WalkupScanDestinations.ts +0 -46
- package/src/WalkupScanManifest.ts +0 -59
- package/src/WalkupScanToCompCaps.ts +0 -36
- package/src/WalkupScanToCompDestination.ts +0 -79
- package/src/WalkupScanToCompDestinations.ts +0 -47
- package/src/WalkupScanToCompEvent.ts +0 -30
- package/src/WalkupScanToCompManifest.ts +0 -59
- package/src/commitInfo.json +0 -3
- package/src/delay.ts +0 -5
- package/src/healthcheck.ts +0 -17
- package/src/index.ts +0 -588
- package/src/listening.ts +0 -144
- package/src/nextcloud/NextcloudConfig.ts +0 -7
- package/src/nextcloud/nextcloud.ts +0 -146
- package/src/paperless/PaperlessConfig.ts +0 -7
- package/src/paperless/paperless.ts +0 -110
- package/src/pdfProcessing.ts +0 -67
- package/src/postProcessing.ts +0 -165
- package/src/readDeviceCapabilities.ts +0 -52
- package/src/scanProcessing.ts +0 -570
- package/tsconfig.json +0 -34
package/src/listening.ts
DELETED
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import HPApi from "./HPApi";
|
|
2
|
-
import Event from "./Event";
|
|
3
|
-
import Destination from "./Destination";
|
|
4
|
-
import { DeviceCapabilities } from "./DeviceCapabilities";
|
|
5
|
-
|
|
6
|
-
export async function waitScanRequest(compEventURI: string): Promise<boolean> {
|
|
7
|
-
const waitMax = 50;
|
|
8
|
-
for (let i = 0; i < waitMax; i++) {
|
|
9
|
-
const walkupScanToCompEvent =
|
|
10
|
-
await HPApi.getWalkupScanToCompEvent(compEventURI);
|
|
11
|
-
const message = walkupScanToCompEvent.eventType;
|
|
12
|
-
if (message === "HostSelected") {
|
|
13
|
-
// this ok to wait
|
|
14
|
-
} else if (message === "ScanRequested") {
|
|
15
|
-
break;
|
|
16
|
-
} else if (message === "ScanNewPageRequested") {
|
|
17
|
-
break;
|
|
18
|
-
} else if (message === "ScanPagesComplete") {
|
|
19
|
-
console.log("no more page to scan, scan is finished");
|
|
20
|
-
return false;
|
|
21
|
-
} else {
|
|
22
|
-
console.log(`Unknown eventType: ${message}`);
|
|
23
|
-
return false;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
console.log(`Waiting user input: ${i + 1}/${waitMax}`);
|
|
27
|
-
await new Promise((resolve) => setTimeout(resolve, 1000)); //wait 1s
|
|
28
|
-
}
|
|
29
|
-
return true;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export async function waitForScanEvent(
|
|
33
|
-
resourceURI: string,
|
|
34
|
-
afterEtag: string | null = null,
|
|
35
|
-
): Promise<Event> {
|
|
36
|
-
console.log("Start listening for new ScanEvent");
|
|
37
|
-
|
|
38
|
-
let eventTable = await HPApi.getEvents(afterEtag ?? "");
|
|
39
|
-
let acceptedScanEvent = null;
|
|
40
|
-
let currentEtag = eventTable.etag;
|
|
41
|
-
while (acceptedScanEvent == null) {
|
|
42
|
-
eventTable = await HPApi.getEvents(currentEtag, 1200);
|
|
43
|
-
currentEtag = eventTable.etag;
|
|
44
|
-
|
|
45
|
-
acceptedScanEvent = eventTable.eventTable.events.find(
|
|
46
|
-
(ev) =>
|
|
47
|
-
ev.isScanEvent &&
|
|
48
|
-
ev.destinationURI &&
|
|
49
|
-
ev.destinationURI.indexOf(resourceURI) >= 0,
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
return acceptedScanEvent;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
async function registerWalkupScanToCompDestination(
|
|
56
|
-
registrationConfig: RegistrationConfig,
|
|
57
|
-
): Promise<string> {
|
|
58
|
-
const walkupScanDestinations = await HPApi.getWalkupScanToCompDestinations();
|
|
59
|
-
const destinations = walkupScanDestinations.destinations;
|
|
60
|
-
|
|
61
|
-
console.log(
|
|
62
|
-
"Host destinations fetched:",
|
|
63
|
-
destinations.map((d) => d.name).join(", "),
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
const hostname = registrationConfig.label;
|
|
67
|
-
const destination = destinations.find((x) => x.name === hostname);
|
|
68
|
-
|
|
69
|
-
let resourceURI;
|
|
70
|
-
if (destination) {
|
|
71
|
-
console.log(
|
|
72
|
-
`Re-using existing destination: ${hostname} - ${destination.resourceURI}`,
|
|
73
|
-
);
|
|
74
|
-
resourceURI = destination.resourceURI;
|
|
75
|
-
} else {
|
|
76
|
-
resourceURI = await HPApi.registerWalkupScanToCompDestination(
|
|
77
|
-
new Destination(hostname, hostname, true),
|
|
78
|
-
);
|
|
79
|
-
console.log(`New Destination registered: ${hostname} - ${resourceURI}`);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
console.log(`Using: ${hostname}`);
|
|
83
|
-
|
|
84
|
-
return resourceURI;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
async function registerWalkupScanDestination(
|
|
88
|
-
registrationConfig: RegistrationConfig,
|
|
89
|
-
): Promise<string> {
|
|
90
|
-
const walkupScanDestinations = await HPApi.getWalkupScanDestinations();
|
|
91
|
-
const destinations = walkupScanDestinations.destinations;
|
|
92
|
-
|
|
93
|
-
console.log(
|
|
94
|
-
"Host destinations fetched:",
|
|
95
|
-
destinations.map((d) => d.name).join(", "),
|
|
96
|
-
);
|
|
97
|
-
|
|
98
|
-
const hostname = registrationConfig.label;
|
|
99
|
-
const destination = destinations.find((x) => x.name === hostname);
|
|
100
|
-
|
|
101
|
-
let resourceURI;
|
|
102
|
-
if (destination) {
|
|
103
|
-
console.log(
|
|
104
|
-
`Re-using existing destination: ${hostname} - ${destination.resourceURI}`,
|
|
105
|
-
);
|
|
106
|
-
resourceURI = destination.resourceURI;
|
|
107
|
-
} else {
|
|
108
|
-
resourceURI = await HPApi.registerWalkupScanDestination(
|
|
109
|
-
new Destination(hostname, hostname, false),
|
|
110
|
-
);
|
|
111
|
-
console.log(`New Destination registered: ${hostname} - ${resourceURI}`);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
console.log(`Using: ${hostname}`);
|
|
115
|
-
|
|
116
|
-
return resourceURI;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export type RegistrationConfig = {
|
|
120
|
-
label: string;
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
export async function waitScanEvent(
|
|
124
|
-
deviceCapabilities: DeviceCapabilities,
|
|
125
|
-
registrationConfig: RegistrationConfig,
|
|
126
|
-
): Promise<Event> {
|
|
127
|
-
let resourceURI: string;
|
|
128
|
-
if (deviceCapabilities.useWalkupScanToComp) {
|
|
129
|
-
resourceURI = await registerWalkupScanToCompDestination(registrationConfig);
|
|
130
|
-
} else {
|
|
131
|
-
resourceURI = await registerWalkupScanDestination(registrationConfig);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
console.log("Waiting scan event for:", resourceURI);
|
|
135
|
-
return await waitForScanEvent(resourceURI);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
export async function clearRegistrations() {
|
|
139
|
-
const dests = await HPApi.getWalkupScanToCompDestinations();
|
|
140
|
-
for (let i = 0; i < dests.destinations.length; i++) {
|
|
141
|
-
console.log(`Removing: ${dests.destinations[i].name}`);
|
|
142
|
-
await HPApi.removeDestination(dests.destinations[i]);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import axios, { AxiosError } from "axios";
|
|
2
|
-
import { ScanContent } from "../ScanContent";
|
|
3
|
-
import { NextcloudConfig } from "./NextcloudConfig";
|
|
4
|
-
import fs from "fs/promises";
|
|
5
|
-
import path from "path";
|
|
6
|
-
|
|
7
|
-
export async function uploadImagesToNextcloud(
|
|
8
|
-
scanJobContent: ScanContent,
|
|
9
|
-
nextcloudConfig: NextcloudConfig,
|
|
10
|
-
) {
|
|
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
|
-
|
|
19
|
-
export async function uploadPdfToNextcloud(
|
|
20
|
-
pdfFilePath: string | null,
|
|
21
|
-
nextcloudConfig: NextcloudConfig,
|
|
22
|
-
) {
|
|
23
|
-
await checkFolderAndUpload(nextcloudConfig, async () => {
|
|
24
|
-
if (pdfFilePath) {
|
|
25
|
-
await uploadToNextcloud(pdfFilePath, nextcloudConfig);
|
|
26
|
-
} else {
|
|
27
|
-
console.log(
|
|
28
|
-
"Pdf generation has failed, nothing is going to be uploaded to Nextcloud",
|
|
29
|
-
);
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
async function uploadToNextcloud(
|
|
35
|
-
filePath: string,
|
|
36
|
-
nextcloudConfig: NextcloudConfig,
|
|
37
|
-
): Promise<void> {
|
|
38
|
-
const { baseUrl, username, password, uploadFolder } = nextcloudConfig;
|
|
39
|
-
const fileName = path.basename(filePath);
|
|
40
|
-
|
|
41
|
-
const folderUrl = buildFolderUrl(baseUrl, username, uploadFolder);
|
|
42
|
-
const uploadUrl = buildUrl(folderUrl, [fileName]);
|
|
43
|
-
|
|
44
|
-
let fileBuffer: Buffer;
|
|
45
|
-
try {
|
|
46
|
-
fileBuffer = await fs.readFile(filePath);
|
|
47
|
-
} catch (e) {
|
|
48
|
-
console.error("Fail to read file:", e);
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
const auth = { username, password };
|
|
52
|
-
|
|
53
|
-
console.log(`Start uploading to Nextcloud: ${fileName}`);
|
|
54
|
-
try {
|
|
55
|
-
const response = await axios({
|
|
56
|
-
method: "PUT",
|
|
57
|
-
url: uploadUrl,
|
|
58
|
-
auth,
|
|
59
|
-
data: fileBuffer,
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
let action: string;
|
|
63
|
-
if (response.status === 201) {
|
|
64
|
-
action = "created";
|
|
65
|
-
} else {
|
|
66
|
-
action = "updated";
|
|
67
|
-
}
|
|
68
|
-
console.log(
|
|
69
|
-
`Document successfully ${action} file at Nextcloud. (Folder: ${uploadFolder}, File: ${fileName})`,
|
|
70
|
-
);
|
|
71
|
-
} catch (error) {
|
|
72
|
-
console.error("Fail to upload document:", error);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
async function checkFolderAndUpload(
|
|
77
|
-
nextcloudConfig: NextcloudConfig,
|
|
78
|
-
uploadFunction: () => Promise<void>,
|
|
79
|
-
) {
|
|
80
|
-
const folderExists = await checkNextcloudFolderExists(nextcloudConfig);
|
|
81
|
-
if (!folderExists) {
|
|
82
|
-
console.log(
|
|
83
|
-
"Upload folder does not exist or user has no permission; skipping upload",
|
|
84
|
-
);
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
await uploadFunction();
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
async function checkNextcloudFolderExists(
|
|
92
|
-
nextcloudConfig: NextcloudConfig,
|
|
93
|
-
): Promise<boolean> {
|
|
94
|
-
const { baseUrl, username, password, uploadFolder } = nextcloudConfig;
|
|
95
|
-
const folderUrl = buildFolderUrl(baseUrl, username, uploadFolder);
|
|
96
|
-
const auth = { username, password };
|
|
97
|
-
|
|
98
|
-
console.log("Check if upload folder exists");
|
|
99
|
-
try {
|
|
100
|
-
// Check if the upload folder exists
|
|
101
|
-
await axios({
|
|
102
|
-
method: "PROPFIND",
|
|
103
|
-
url: folderUrl,
|
|
104
|
-
auth,
|
|
105
|
-
headers: { Depth: 0 },
|
|
106
|
-
});
|
|
107
|
-
console.log(`Found upload folder '${uploadFolder}' in Nextcloud`);
|
|
108
|
-
} catch (error) {
|
|
109
|
-
const axiosError = error as AxiosError;
|
|
110
|
-
if (axiosError.response?.status === 404) {
|
|
111
|
-
console.warn(`Upload folder '${uploadFolder}' not found in Nextcloud`);
|
|
112
|
-
} else if (axiosError.response?.status === 401) {
|
|
113
|
-
console.warn(
|
|
114
|
-
`User has no permission to access upload folder '${uploadFolder}' in Nextcloud`,
|
|
115
|
-
);
|
|
116
|
-
} else {
|
|
117
|
-
console.error("Fail to check upload folder exists:", axiosError.toJSON());
|
|
118
|
-
}
|
|
119
|
-
console.trace("Error response:", axiosError.response);
|
|
120
|
-
return false;
|
|
121
|
-
}
|
|
122
|
-
return true;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
function buildFolderUrl(
|
|
126
|
-
baseUrl: string,
|
|
127
|
-
username: string,
|
|
128
|
-
uploadFolder: string,
|
|
129
|
-
) {
|
|
130
|
-
return buildUrl(baseUrl, [
|
|
131
|
-
"remote.php",
|
|
132
|
-
"dav",
|
|
133
|
-
"files",
|
|
134
|
-
username,
|
|
135
|
-
uploadFolder,
|
|
136
|
-
]);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
function buildUrl(baseUrl: string, path: string[]): string {
|
|
140
|
-
const url = new URL(baseUrl);
|
|
141
|
-
const search = /^\/+|\/+$/g;
|
|
142
|
-
path.forEach((part) => {
|
|
143
|
-
url.pathname = `${url.pathname.replace(search, "")}/${encodeURIComponent(part.replace(search, ""))}`;
|
|
144
|
-
});
|
|
145
|
-
return url.toString();
|
|
146
|
-
}
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import fsSync from "fs";
|
|
2
|
-
import FormData from "form-data";
|
|
3
|
-
import axios from "axios";
|
|
4
|
-
import { ScanConfig } from "../scanProcessing";
|
|
5
|
-
import { ScanContent } from "../ScanContent";
|
|
6
|
-
import fs from "fs/promises";
|
|
7
|
-
import { convertToPdf, mergeToPdf } from "../pdfProcessing";
|
|
8
|
-
import { PaperlessConfig } from "./PaperlessConfig";
|
|
9
|
-
|
|
10
|
-
export async function uploadImagesAsSeparateDocumentsToPaperless(
|
|
11
|
-
scanJobContent: ScanContent,
|
|
12
|
-
paperlessConfig: PaperlessConfig,
|
|
13
|
-
) {
|
|
14
|
-
for (let i = 0; i < scanJobContent.elements.length; ++i) {
|
|
15
|
-
const filePath = scanJobContent.elements[i].path;
|
|
16
|
-
await uploadToPaperless(filePath, paperlessConfig);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export async function convertImagesToPdfAndUploadAsSeparateDocumentsToPaperless(
|
|
21
|
-
scanJobContent: ScanContent,
|
|
22
|
-
paperlessConfig: PaperlessConfig,
|
|
23
|
-
) {
|
|
24
|
-
for (let i = 0; i < scanJobContent.elements.length; ++i) {
|
|
25
|
-
const pdfFilePath = await convertToPdf(
|
|
26
|
-
scanJobContent.elements[i],
|
|
27
|
-
!paperlessConfig.keepFiles,
|
|
28
|
-
);
|
|
29
|
-
if (pdfFilePath) {
|
|
30
|
-
await uploadToPaperless(pdfFilePath, paperlessConfig);
|
|
31
|
-
await fs.unlink(pdfFilePath);
|
|
32
|
-
} else {
|
|
33
|
-
console.log(
|
|
34
|
-
"Pdf generation has failed, nothing is going to be uploaded to paperless for: " +
|
|
35
|
-
scanJobContent.elements[i].path,
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export async function mergeToPdfAndUploadAsSingleDocumentToPaperless(
|
|
42
|
-
folder: string,
|
|
43
|
-
scanCount: number,
|
|
44
|
-
scanJobContent: ScanContent,
|
|
45
|
-
scanConfig: ScanConfig,
|
|
46
|
-
scanDate: Date,
|
|
47
|
-
paperlessConfig: PaperlessConfig,
|
|
48
|
-
) {
|
|
49
|
-
const pdfFilePath = await mergeToPdf(
|
|
50
|
-
folder,
|
|
51
|
-
scanCount,
|
|
52
|
-
scanJobContent,
|
|
53
|
-
scanConfig.directoryConfig.filePattern,
|
|
54
|
-
scanDate,
|
|
55
|
-
!paperlessConfig.keepFiles,
|
|
56
|
-
);
|
|
57
|
-
if (pdfFilePath) {
|
|
58
|
-
await uploadToPaperless(pdfFilePath, paperlessConfig);
|
|
59
|
-
await fs.unlink(pdfFilePath);
|
|
60
|
-
console.log(
|
|
61
|
-
`Pdf document ${pdfFilePath} has been removed from the filesystem`,
|
|
62
|
-
);
|
|
63
|
-
} else {
|
|
64
|
-
console.log(
|
|
65
|
-
"Pdf generation has failed, nothing is going to be uploaded to paperless",
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export async function uploadPdfToPaperless(
|
|
71
|
-
pdfFilePath: string | null,
|
|
72
|
-
paperlessConfig: PaperlessConfig,
|
|
73
|
-
) {
|
|
74
|
-
if (pdfFilePath) {
|
|
75
|
-
await uploadToPaperless(pdfFilePath, paperlessConfig);
|
|
76
|
-
} else {
|
|
77
|
-
console.log(
|
|
78
|
-
"Pdf generation has failed, nothing is going to be uploaded to paperless",
|
|
79
|
-
);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
async function uploadToPaperless(
|
|
84
|
-
filePath: string,
|
|
85
|
-
paperlessConfig: PaperlessConfig,
|
|
86
|
-
): Promise<void> {
|
|
87
|
-
const url = paperlessConfig.postDocumentUrl;
|
|
88
|
-
|
|
89
|
-
const authToken = paperlessConfig.authToken;
|
|
90
|
-
|
|
91
|
-
const fileStream = fsSync.createReadStream(filePath);
|
|
92
|
-
|
|
93
|
-
const form = new FormData();
|
|
94
|
-
form.append("document", fileStream);
|
|
95
|
-
|
|
96
|
-
console.log(`Start uploading to paperless: ${filePath}`);
|
|
97
|
-
try {
|
|
98
|
-
const response = await axios.post(url, form, {
|
|
99
|
-
headers: {
|
|
100
|
-
...form.getHeaders(),
|
|
101
|
-
Authorization: `Token ${authToken}`,
|
|
102
|
-
},
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
console.log("Document successfully uploaded to paperless:", response.data);
|
|
106
|
-
} catch (error) {
|
|
107
|
-
console.error("Fail to upload document:", error);
|
|
108
|
-
}
|
|
109
|
-
fileStream.close();
|
|
110
|
-
}
|
package/src/pdfProcessing.ts
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { ScanContent, ScanPage } from "./ScanContent";
|
|
2
|
-
import PathHelper from "./PathHelper";
|
|
3
|
-
import fs from "fs/promises";
|
|
4
|
-
import path from "path";
|
|
5
|
-
import { jsPDF } from "jspdf";
|
|
6
|
-
|
|
7
|
-
export async function mergeToPdf(
|
|
8
|
-
folder: string,
|
|
9
|
-
scanCount: number,
|
|
10
|
-
scanJobContent: ScanContent,
|
|
11
|
-
filePattern: string | undefined,
|
|
12
|
-
date: Date,
|
|
13
|
-
deleteFiles: boolean,
|
|
14
|
-
): Promise<string | null> {
|
|
15
|
-
if (scanJobContent.elements.length > 0) {
|
|
16
|
-
const pdfFilePath: string = PathHelper.getFileForScan(
|
|
17
|
-
folder,
|
|
18
|
-
scanCount,
|
|
19
|
-
filePattern,
|
|
20
|
-
"pdf",
|
|
21
|
-
date,
|
|
22
|
-
);
|
|
23
|
-
await createPdfFrom(scanJobContent, pdfFilePath);
|
|
24
|
-
if (deleteFiles) {
|
|
25
|
-
await Promise.all(scanJobContent.elements.map((e) => fs.unlink(e.path)));
|
|
26
|
-
}
|
|
27
|
-
return pdfFilePath;
|
|
28
|
-
}
|
|
29
|
-
console.log(`No page available to build a pdf file`);
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export async function convertToPdf(
|
|
34
|
-
scanPage: ScanPage,
|
|
35
|
-
deleteFile: boolean,
|
|
36
|
-
): Promise<string | null> {
|
|
37
|
-
const fileName = path.basename(scanPage.path, path.extname(scanPage.path));
|
|
38
|
-
const pdfFilePath = path.join(path.dirname(scanPage.path), `${fileName}.pdf`);
|
|
39
|
-
|
|
40
|
-
await createPdfFrom({ elements: [scanPage] }, pdfFilePath);
|
|
41
|
-
if (deleteFile) {
|
|
42
|
-
await fs.unlink(scanPage.path);
|
|
43
|
-
}
|
|
44
|
-
return pdfFilePath;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export async function createPdfFrom(
|
|
48
|
-
scanContent: ScanContent,
|
|
49
|
-
destination: string,
|
|
50
|
-
) {
|
|
51
|
-
let doc: jsPDF | null = null;
|
|
52
|
-
for (const element of scanContent.elements) {
|
|
53
|
-
const widthInInches = element.width / element.xResolution;
|
|
54
|
-
const heightInInches = element.height / element.yResolution;
|
|
55
|
-
const format = [widthInInches, heightInInches];
|
|
56
|
-
|
|
57
|
-
if (doc == null) {
|
|
58
|
-
doc = new jsPDF({ unit: "in", floatPrecision: 3, format });
|
|
59
|
-
} else {
|
|
60
|
-
doc.addPage(format);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const imageByteBuffer = await fs.readFile(element.path);
|
|
64
|
-
doc.addImage(imageByteBuffer, "JPEG", 0, 0, widthInInches, heightInInches);
|
|
65
|
-
}
|
|
66
|
-
doc?.save(destination);
|
|
67
|
-
}
|
package/src/postProcessing.ts
DELETED
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
import { ScanContent } from "./ScanContent";
|
|
2
|
-
import { mergeToPdf } from "./pdfProcessing";
|
|
3
|
-
import {
|
|
4
|
-
convertImagesToPdfAndUploadAsSeparateDocumentsToPaperless,
|
|
5
|
-
mergeToPdfAndUploadAsSingleDocumentToPaperless,
|
|
6
|
-
uploadImagesAsSeparateDocumentsToPaperless,
|
|
7
|
-
uploadPdfToPaperless,
|
|
8
|
-
} from "./paperless/paperless";
|
|
9
|
-
import {
|
|
10
|
-
uploadPdfToNextcloud,
|
|
11
|
-
uploadImagesToNextcloud,
|
|
12
|
-
} from "./nextcloud/nextcloud";
|
|
13
|
-
import { ScanConfig } from "./scanProcessing";
|
|
14
|
-
import fs from "fs/promises";
|
|
15
|
-
import { PaperlessConfig } from "./paperless/PaperlessConfig";
|
|
16
|
-
import { NextcloudConfig } from "./nextcloud/NextcloudConfig";
|
|
17
|
-
|
|
18
|
-
export async function postProcessing(
|
|
19
|
-
scanConfig: ScanConfig,
|
|
20
|
-
folder: string,
|
|
21
|
-
tempFolder: string,
|
|
22
|
-
scanCount: number,
|
|
23
|
-
scanJobContent: ScanContent,
|
|
24
|
-
scanDate: Date,
|
|
25
|
-
toPdf: boolean,
|
|
26
|
-
) {
|
|
27
|
-
if (toPdf) {
|
|
28
|
-
await handlePdfPostProcessing(
|
|
29
|
-
folder,
|
|
30
|
-
tempFolder,
|
|
31
|
-
scanCount,
|
|
32
|
-
scanJobContent,
|
|
33
|
-
scanDate,
|
|
34
|
-
scanConfig,
|
|
35
|
-
);
|
|
36
|
-
} else {
|
|
37
|
-
await handleImagePostProcessing(
|
|
38
|
-
folder,
|
|
39
|
-
scanCount,
|
|
40
|
-
scanJobContent,
|
|
41
|
-
scanDate,
|
|
42
|
-
scanConfig,
|
|
43
|
-
);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
async function handlePdfPostProcessing(
|
|
48
|
-
folder: string,
|
|
49
|
-
tempFolder: string,
|
|
50
|
-
scanCount: number,
|
|
51
|
-
scanJobContent: ScanContent,
|
|
52
|
-
scanDate: Date,
|
|
53
|
-
scanConfig: ScanConfig,
|
|
54
|
-
) {
|
|
55
|
-
const paperlessConfig = scanConfig.paperlessConfig;
|
|
56
|
-
const nextcloudConfig = scanConfig.nextcloudConfig;
|
|
57
|
-
|
|
58
|
-
const pdfFilePath = await mergeToPdf(
|
|
59
|
-
paperlessConfig ? tempFolder : folder,
|
|
60
|
-
scanCount,
|
|
61
|
-
scanJobContent,
|
|
62
|
-
scanConfig.directoryConfig.filePattern,
|
|
63
|
-
scanDate,
|
|
64
|
-
true,
|
|
65
|
-
);
|
|
66
|
-
if (pdfFilePath != null) {
|
|
67
|
-
displayPdfScan(pdfFilePath, scanJobContent);
|
|
68
|
-
if (paperlessConfig) {
|
|
69
|
-
await uploadPdfToPaperless(pdfFilePath, paperlessConfig);
|
|
70
|
-
}
|
|
71
|
-
if (nextcloudConfig) {
|
|
72
|
-
await uploadPdfToNextcloud(pdfFilePath, nextcloudConfig);
|
|
73
|
-
}
|
|
74
|
-
await cleanUpFilesIfNeeded([pdfFilePath], paperlessConfig, nextcloudConfig);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
async function handleImagePostProcessing(
|
|
79
|
-
folder: string,
|
|
80
|
-
scanCount: number,
|
|
81
|
-
scanJobContent: ScanContent,
|
|
82
|
-
scanDate: Date,
|
|
83
|
-
scanConfig: ScanConfig,
|
|
84
|
-
) {
|
|
85
|
-
const paperlessConfig = scanConfig.paperlessConfig;
|
|
86
|
-
const nextcloudConfig = scanConfig.nextcloudConfig;
|
|
87
|
-
|
|
88
|
-
displayJpegScan(scanJobContent);
|
|
89
|
-
if (paperlessConfig) {
|
|
90
|
-
if (paperlessConfig.groupMultiPageScanIntoAPdf) {
|
|
91
|
-
await mergeToPdfAndUploadAsSingleDocumentToPaperless(
|
|
92
|
-
folder,
|
|
93
|
-
scanCount,
|
|
94
|
-
scanJobContent,
|
|
95
|
-
scanConfig,
|
|
96
|
-
scanDate,
|
|
97
|
-
paperlessConfig,
|
|
98
|
-
);
|
|
99
|
-
} else {
|
|
100
|
-
if (paperlessConfig.alwaysSendAsPdfFile) {
|
|
101
|
-
await convertImagesToPdfAndUploadAsSeparateDocumentsToPaperless(
|
|
102
|
-
scanJobContent,
|
|
103
|
-
paperlessConfig,
|
|
104
|
-
);
|
|
105
|
-
} else {
|
|
106
|
-
await uploadImagesAsSeparateDocumentsToPaperless(
|
|
107
|
-
scanJobContent,
|
|
108
|
-
paperlessConfig,
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
if (nextcloudConfig) {
|
|
114
|
-
await uploadImagesToNextcloud(scanJobContent, nextcloudConfig);
|
|
115
|
-
}
|
|
116
|
-
const filePaths = scanJobContent.elements.map((element) => element.path);
|
|
117
|
-
await cleanUpFilesIfNeeded(filePaths, paperlessConfig, nextcloudConfig);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function displayPdfScan(
|
|
121
|
-
pdfFilePath: string | null,
|
|
122
|
-
scanJobContent: ScanContent,
|
|
123
|
-
) {
|
|
124
|
-
if (pdfFilePath === null) {
|
|
125
|
-
console.log(`Pdf generated has not been generated`);
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
console.log(
|
|
129
|
-
`The following page(s) have been rendered inside '${pdfFilePath}': `,
|
|
130
|
-
);
|
|
131
|
-
scanJobContent.elements.forEach((e) =>
|
|
132
|
-
console.log(
|
|
133
|
-
`\t- page ${e.pageNumber.toString().padStart(3, " ")} - ${e.width}x${
|
|
134
|
-
e.height
|
|
135
|
-
}`,
|
|
136
|
-
),
|
|
137
|
-
);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
function displayJpegScan(scanJobContent: ScanContent) {
|
|
141
|
-
scanJobContent.elements.forEach((e) =>
|
|
142
|
-
console.log(
|
|
143
|
-
`\t- page ${e.pageNumber.toString().padStart(3, " ")} - ${e.width}x${
|
|
144
|
-
e.height
|
|
145
|
-
} - ${e.path}`,
|
|
146
|
-
),
|
|
147
|
-
);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
async function cleanUpFilesIfNeeded(
|
|
151
|
-
filePaths: string[],
|
|
152
|
-
paperlessConfig: PaperlessConfig | undefined,
|
|
153
|
-
nextcloudConfig: NextcloudConfig | undefined,
|
|
154
|
-
) {
|
|
155
|
-
let keepFiles: boolean =
|
|
156
|
-
paperlessConfig?.keepFiles ?? nextcloudConfig?.keepFiles ?? true;
|
|
157
|
-
if (!keepFiles) {
|
|
158
|
-
await Promise.all(
|
|
159
|
-
filePaths.map(async (filePath) => {
|
|
160
|
-
await fs.unlink(filePath);
|
|
161
|
-
console.log(`File ${filePath} has been removed from the filesystem`);
|
|
162
|
-
}),
|
|
163
|
-
);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { DeviceCapabilities } from "./DeviceCapabilities";
|
|
2
|
-
import HPApi from "./HPApi";
|
|
3
|
-
import WalkupScanToCompCaps from "./WalkupScanToCompCaps";
|
|
4
|
-
import ScanCaps from "./ScanCaps";
|
|
5
|
-
|
|
6
|
-
export async function readDeviceCapabilities(): Promise<DeviceCapabilities> {
|
|
7
|
-
let supportsMultiItemScanFromPlaten = true;
|
|
8
|
-
const discoveryTree = await HPApi.getDiscoveryTree();
|
|
9
|
-
let walkupScanToCompCaps: WalkupScanToCompCaps | null = null;
|
|
10
|
-
if (discoveryTree.WalkupScanToCompManifestURI != null) {
|
|
11
|
-
const walkupScanToCompManifest = await HPApi.getWalkupScanToCompManifest(
|
|
12
|
-
discoveryTree.WalkupScanToCompManifestURI,
|
|
13
|
-
);
|
|
14
|
-
if (walkupScanToCompManifest.WalkupScanToCompCapsURI != null) {
|
|
15
|
-
walkupScanToCompCaps = await HPApi.getWalkupScanToCompCaps(
|
|
16
|
-
walkupScanToCompManifest.WalkupScanToCompCapsURI,
|
|
17
|
-
);
|
|
18
|
-
supportsMultiItemScanFromPlaten =
|
|
19
|
-
walkupScanToCompCaps.supportsMultiItemScanFromPlaten;
|
|
20
|
-
}
|
|
21
|
-
} else if (discoveryTree.WalkupScanManifestURI != null) {
|
|
22
|
-
const walkupScanManifest = await HPApi.getWalkupScanManifest(
|
|
23
|
-
discoveryTree.WalkupScanManifestURI,
|
|
24
|
-
);
|
|
25
|
-
if (walkupScanManifest.walkupScanDestinationsURI != null) {
|
|
26
|
-
await HPApi.getWalkupScanDestinations(
|
|
27
|
-
walkupScanManifest.walkupScanDestinationsURI,
|
|
28
|
-
);
|
|
29
|
-
}
|
|
30
|
-
} else {
|
|
31
|
-
console.log("Unknown device!");
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
let scanCaps: ScanCaps | null = null;
|
|
35
|
-
if (discoveryTree.ScanJobManifestURI != null) {
|
|
36
|
-
const scanJobManifest = await HPApi.getScanJobManifest(
|
|
37
|
-
discoveryTree.ScanJobManifestURI,
|
|
38
|
-
);
|
|
39
|
-
if (scanJobManifest.ScanCapsURI != null) {
|
|
40
|
-
scanCaps = await HPApi.getScanCaps(scanJobManifest.ScanCapsURI);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return {
|
|
45
|
-
supportsMultiItemScanFromPlaten,
|
|
46
|
-
useWalkupScanToComp: walkupScanToCompCaps != null,
|
|
47
|
-
platenMaxWidth: scanCaps?.platenMaxWidth || null,
|
|
48
|
-
platenMaxHeight: scanCaps?.platenMaxHeight || null,
|
|
49
|
-
adfMaxWidth: scanCaps?.adfMaxWidth || null,
|
|
50
|
-
adfMaxHeight: scanCaps?.adfMaxHeight || null,
|
|
51
|
-
};
|
|
52
|
-
}
|