aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2024-12-14 14:39:56 -0500
committerbobzel <zzzman@gmail.com>2024-12-14 14:39:56 -0500
commit4826ac1b3223376493ea22c0f23095bc0797cd9c (patch)
treeeca3924148c9baedf8f2d0734627d45fe32d1354
parent38b8c63d374415142acefcf6b6f736646f78de44 (diff)
parentf7c7f5f77f1170a84a22eb8b337db7c37a52a5da (diff)
Merge branch 'master' into eleanor-gptdraw
-rw-r--r--.env24
-rw-r--r--package-lock.json29
-rw-r--r--package.json4
-rw-r--r--src/.DS_Storebin10244 -> 10244 bytes
-rw-r--r--src/client/views/nodes/ImageBox.tsx31
-rw-r--r--src/server/ApiManagers/FireflyManager.ts6
-rw-r--r--src/server/ApiManagers/UploadManager.ts13
-rw-r--r--src/server/DashUploadUtils.ts41
8 files changed, 98 insertions, 30 deletions
diff --git a/.env2 b/.env2
new file mode 100644
index 000000000..08ee154e1
--- /dev/null
+++ b/.env2
@@ -0,0 +1,4 @@
+
+export _CLIENT_FIREFLY_CLIENT_ID='62eb3cc56d8d47c88ff67103ded0003f'
+export _CLIENT_FIREFLY_SECRET='p8e-4JxcVXG6izNEnf0ceEPO1zSZ7U13TMUQ'
+export _CLIENT_FIREFLY_TOKEN='eyJhbGciOiJSUzI1NiIsIng1dSI6Imltc19uYTEta2V5LWF0LTEuY2VyIiwia2lkIjoiaW1zX25hMS1rZXktYXQtMSIsIml0dCI6ImF0In0.eyJpZCI6IjE3MzMyMzgwMjg3NDVfNDg0ODM3ZTAtMmU3Zi00NWFkLTkzZjEtZjM0NWRkNDM3MzAwX3VlMSIsIm9yZyI6IjVEOEUxREMzNjcyNTQ2MDIwQTQ5NUZGMEBBZG9iZU9yZyIsInR5cGUiOiJhY2Nlc3NfdG9rZW4iLCJjbGllbnRfaWQiOiI2MmViM2NjNTZkOGQ0N2M4OGZmNjcxMDNkZWQwMDAzZiIsInVzZXJfaWQiOiI2MzQ1MUQ5RTY3MjU1MEQ4MEE0OTVFQ0FAdGVjaGFjY3QuYWRvYmUuY29tIiwiYXMiOiJpbXMtbmExIiwiYWFfaWQiOiI2MzQ1MUQ5RTY3MjU1MEQ4MEE0OTVFQ0FAdGVjaGFjY3QuYWRvYmUuY29tIiwiY3RwIjozLCJtb2kiOiI3NDc2MDZiZCIsImV4cGlyZXNfaW4iOiI4NjQwMDAwMCIsInNjb3BlIjoiZmlyZWZseV9hcGksYWRkaXRpb25hbF9pbmZvLG9wZW5pZCxzZXNzaW9uLEFkb2JlSUQsZmZfYXBpcyxyZWFkX29yZ2FuaXphdGlvbnMiLCJjcmVhdGVkX2F0IjoiMTczMzIzODAyODc0NSJ9.O-HGx7ji_-RZJXmCnsPVzdTmJA4s_fA0Gj0s7z1FZ6MPtzdXa9MSYkMYdo4ImfiYZGf73SeJACEpfTdgyd7shG3qXBydeZV2exGQcN6eve88zXMBsc98aCi0mPz2eql4MomJk9xGXuk3ZuZmVAbsAVfwScPU_uyl75DZAq4_4e6lyXakEti9ACYnEl-7TQQeEgK6Mr4R8giUWvYVAdmSK4xOq67yjBToj6S-fv_s2dBRY58x_fMkORCrJnDLEnSdXS2LXHXAyM_Up9EaezIovlVhwz04BuwrH0vVOJN7uHgFOeWbjULaGGYy2Wzb1hPeRVd7VIRiw3sHavthTSJ3KA'
diff --git a/package-lock.json b/package-lock.json
index 8c2cf0694..46057f615 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -100,6 +100,7 @@
"depcheck": "^1.4.7",
"dompurify": "^3.1.7",
"dotenv": "^16.4.5",
+ "dropbox": "^10.34.0",
"eslint-webpack-plugin": "^4.1.0",
"exif": "^0.6.0",
"exifr": "^7.1.3",
@@ -128,7 +129,7 @@
"google-auth-library": "^9.4.1",
"googleapis": "^144.0.0",
"googlephotos": "^0.3.5",
- "got": "^14.0.0",
+ "got": "^14.4.5",
"howler": "^2.2.4",
"html-to-image": "^1.11.11",
"html-to-text": "^9.0.5",
@@ -171,6 +172,7 @@
"npm": "^10.8.1",
"openai": "^4.26.0",
"p-limit": "^6.1.0",
+ "parse-multipart-data": "^1.5.0",
"passport": "^0.7.0",
"passport-google-oauth20": "^2.0.0",
"passport-local": "^1.0.0",
@@ -19700,6 +19702,20 @@
"resolved": "https://registry.npmjs.org/double-bits/-/double-bits-1.1.1.tgz",
"integrity": "sha512-BCLEIBq0O/DWoA7BsCu/R+RP0ZXiowP8BhtJT3qeuuQEBpnS8LK/Wo6UTJQv6v8mK1fj8n90YziHLwGdM5whSg=="
},
+ "node_modules/dropbox": {
+ "version": "10.34.0",
+ "resolved": "https://registry.npmjs.org/dropbox/-/dropbox-10.34.0.tgz",
+ "integrity": "sha512-5jb5/XzU0fSnq36/hEpwT5/QIep7MgqKuxghEG44xCu7HruOAjPdOb3x0geXv5O/hd0nHpQpWO+r5MjYTpMvJg==",
+ "dependencies": {
+ "node-fetch": "^2.6.1"
+ },
+ "engines": {
+ "node": ">=0.10.3"
+ },
+ "peerDependencies": {
+ "@types/node-fetch": "^2.5.7"
+ }
+ },
"node_modules/dynamic-dedupe": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz",
@@ -22148,9 +22164,9 @@
}
},
"node_modules/got": {
- "version": "14.4.4",
- "resolved": "https://registry.npmjs.org/got/-/got-14.4.4.tgz",
- "integrity": "sha512-tqiF7eSgTBwQkxb1LxsEpva8TaMYVisbhplrFVmw9GQE3855Z+MH/mnsXLLOkDxR6hZJRFMj5VTAZ8lmTF8ZOA==",
+ "version": "14.4.5",
+ "resolved": "https://registry.npmjs.org/got/-/got-14.4.5.tgz",
+ "integrity": "sha512-sq+uET8TnNKRNnjEOPJzMcxeI0irT8BBNmf+GtZcJpmhYsQM1DSKmCROUjPWKsXZ5HzwD5Cf5/RV+QD9BSTxJg==",
"dependencies": {
"@sindresorhus/is": "^7.0.1",
"@szmarczak/http-timer": "^5.0.1",
@@ -30590,6 +30606,11 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/parse-multipart-data": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/parse-multipart-data/-/parse-multipart-data-1.5.0.tgz",
+ "integrity": "sha512-ck5zaMF0ydjGfejNMnlo5YU2oJ+pT+80Jb1y4ybanT27j+zbVP/jkYmCrUGsEln0Ox/hZmuvgy8Ra7AxbXP2Mw=="
+ },
"node_modules/parse-passwd": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
diff --git a/package.json b/package.json
index 7c2730245..7ca0c8b38 100644
--- a/package.json
+++ b/package.json
@@ -183,6 +183,7 @@
"depcheck": "^1.4.7",
"dompurify": "^3.1.7",
"dotenv": "^16.4.5",
+ "dropbox": "^10.34.0",
"eslint-webpack-plugin": "^4.1.0",
"exif": "^0.6.0",
"exifr": "^7.1.3",
@@ -211,7 +212,7 @@
"google-auth-library": "^9.4.1",
"googleapis": "^144.0.0",
"googlephotos": "^0.3.5",
- "got": "^14.0.0",
+ "got": "^14.4.5",
"howler": "^2.2.4",
"html-to-image": "^1.11.11",
"html-to-text": "^9.0.5",
@@ -254,6 +255,7 @@
"npm": "^10.8.1",
"openai": "^4.26.0",
"p-limit": "^6.1.0",
+ "parse-multipart-data": "^1.5.0",
"passport": "^0.7.0",
"passport-google-oauth20": "^2.0.0",
"passport-local": "^1.0.0",
diff --git a/src/.DS_Store b/src/.DS_Store
index 9b66f8d8e..1ef749033 100644
--- a/src/.DS_Store
+++ b/src/.DS_Store
Binary files differ
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 4d35068ee..d847b7940 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -39,6 +39,8 @@ import { FieldView, FieldViewProps } from './FieldView';
import { FocusViewOptions } from './FocusViewOptions';
import './ImageBox.scss';
import { OpenWhere } from './OpenWhere';
+import { Upload } from '../../../server/SharedMediaTypes';
+import { ImageUtils } from '../../util/Import & Export/ImageUtils';
export class ImageEditorData {
// eslint-disable-next-line no-use-before-define
@@ -310,6 +312,35 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
funcs.push({ description: 'Rotate Clockwise 90', event: this.rotate, icon: 'redo-alt' });
funcs.push({ description: `Show ${this.layoutDoc._showFullRes ? 'Dynamic Res' : 'Full Res'}`, event: this.resolution, icon: 'expand' });
funcs.push({ description: 'Set Native Pixel Size', event: this.setNativeSize, icon: 'expand-arrows-alt' });
+ funcs.push({
+ description: 'GetImageText',
+ event: () => {
+ Networking.PostToServer('/queryFireflyImageText', {
+ file: (file => {
+ const ext = extname(file);
+ return file.replace(ext, (this._error ? '_o' : this._curSuffix) + ext);
+ })(ImageCast(this.Document[Doc.LayoutFieldKey(this.Document)])?.url.href),
+ }).then(text => alert(text));
+ },
+ icon: 'expand-arrows-alt',
+ });
+ funcs.push({
+ description: 'Expand Image',
+ event: () => {
+ Networking.PostToServer('/expandImage', {
+ prompt: 'sunny skies',
+ file: (file => {
+ const ext = extname(file);
+ return file.replace(ext, (this._error ? '_o' : this._curSuffix) + ext);
+ })(ImageCast(this.Document[Doc.LayoutFieldKey(this.Document)])?.url.href),
+ }).then((info: Upload.ImageInformation) => {
+ const img = Docs.Create.ImageDocument(info.accessPaths.agnostic.client, { title: 'expand:' + this.Document.title });
+ DocUtils.assignImageInfo(info, img);
+ this._props.addDocTab(img, OpenWhere.addRight);
+ });
+ },
+ icon: 'expand-arrows-alt',
+ });
funcs.push({ description: 'Copy path', event: () => ClientUtils.CopyText(this.choosePath(field.url)), icon: 'copy' });
funcs.push({
description: 'Open Image Editor',
diff --git a/src/server/ApiManagers/FireflyManager.ts b/src/server/ApiManagers/FireflyManager.ts
index 4425aff43..73cf94206 100644
--- a/src/server/ApiManagers/FireflyManager.ts
+++ b/src/server/ApiManagers/FireflyManager.ts
@@ -1,4 +1,4 @@
-import { Dropbox, files } from 'dropbox';
+import { Dropbox } from 'dropbox';
import * as fs from 'fs';
import * as multipart from 'parse-multipart-data';
import * as path from 'path';
@@ -227,9 +227,9 @@ export default class FireflyManager extends ApiManager {
const { prompt, imageBlob, strength = 0.5 } = req.body;
const uploadId = imageBlob ? await this.uploadImageToFirefly(imageBlob) : null;
this.askFireflyOld(prompt, uploadId, strength).then(fire =>
- DashUploadUtils.UploadImage(JSON.parse(fire).url).then(info => {
+ DashUploadUtils.UploadImage(JSON.parse(fire ?? '').url).then(info => {
if (info instanceof Error) _invalid(res, info.message);
- else _success(res, info.accessPaths.agnostic.client);
+ else _success(res, info);
})
);
},
diff --git a/src/server/ApiManagers/UploadManager.ts b/src/server/ApiManagers/UploadManager.ts
index 868373474..5a880901b 100644
--- a/src/server/ApiManagers/UploadManager.ts
+++ b/src/server/ApiManagers/UploadManager.ts
@@ -70,10 +70,16 @@ export default class UploadManager extends ApiManager {
]);
} else {
fileguids.split(';').map(guid => DashUploadUtils.uploadProgress.set(guid, `resampling images`));
+ // original filenames with '.'s, such as a Macbook screenshot, can be a problem - their extension is not kept in formidable's newFilename.
+ // This makes sure that the extension is preserved in the newFilename.
+ const fixNewFilename = (f: formidable.File) => {
+ if (path.extname(f.originalFilename ?? '') !== path.extname(f.newFilename)) f.newFilename = f.newFilename + path.extname(f.originalFilename ?? '');
+ return f;
+ };
const results = (
await Promise.all(
Array.from(Object.keys(files)).map(
- async key => (!files[key] ? undefined : DashUploadUtils.upload(files[key]![0] /* , key */)) // key is the guid used by the client to track upload progress.
+ async key => (!files[key] ? undefined : DashUploadUtils.upload(fixNewFilename(files[key][0]) /* , key */)) // key is the guid used by the client to track upload progress.
)
)
).filter(result => result && !(result.result instanceof Error));
@@ -147,13 +153,10 @@ export default class UploadManager extends ApiManager {
if (doc.id) {
doc.id = getId(doc.id);
}
- // eslint-disable-next-line no-restricted-syntax
for (const key in doc.fields) {
- // eslint-disable-next-line no-continue
if (!Object.prototype.hasOwnProperty.call(doc.fields, key)) continue;
const field = doc.fields[key];
- // eslint-disable-next-line no-continue
if (field === undefined || field === null) continue;
if (field.__type === 'Doc') {
@@ -182,11 +185,9 @@ export default class UploadManager extends ApiManager {
let docids: string[] = [];
let linkids: string[] = [];
try {
- // eslint-disable-next-line no-restricted-syntax
for (const name in files) {
if (Object.prototype.hasOwnProperty.call(files, name)) {
const f = files[name];
- // eslint-disable-next-line no-continue
if (!f) continue;
const path2 = f[0]; // what about the rest of the array? are we guaranteed only one value is set?
const zip = new AdmZip(path2.filepath);
diff --git a/src/server/DashUploadUtils.ts b/src/server/DashUploadUtils.ts
index 351351ca5..a06fa3b6e 100644
--- a/src/server/DashUploadUtils.ts
+++ b/src/server/DashUploadUtils.ts
@@ -22,7 +22,6 @@ import { AzureManager } from './ApiManagers/AzureManager';
import { AcceptableMedia, Upload } from './SharedMediaTypes';
import { Directory, clientPathToFile, filesDirectory, pathToDirectory, publicDirectory, serverPathToFile } from './SocketData';
import { resolvedServerUrl } from './server_Initialization';
-
import { Worker, isMainThread, parentPort } from 'worker_threads';
// Create an array to store worker threads
@@ -55,7 +54,8 @@ if (isMainThread) {
.then(img =>
sizes.forEach(({ width, suffix }) =>
img.resize({ w: width || img.bitmap.width })
- .write(InjectSize(outputPath, suffix) as `${string}.${string}`)
+ .write(InjectSize(outputPath, suffix) as `${string}.${string}`)
+ .catch(e => console.log("Jimp error:", e))
))
.catch(e => console.log('Error Jimp:', e))
.finally(() => unlinkSource && unlinkSync(imgSourcePath));
@@ -223,7 +223,6 @@ export namespace DashUploadUtils {
const parseExifData = async (source: string) => {
const image = await request.get(source, { encoding: null });
const { /* data, */ error } = await new Promise<{ data: ExifData; error: string | undefined }>(resolve => {
- // eslint-disable-next-line no-new
new ExifImage({ image }, (exifError, data) => {
resolve({ data, error: exifError?.message });
});
@@ -302,7 +301,6 @@ export namespace DashUploadUtils {
// Bundle up the information into an object
return {
source,
- // eslint-disable-next-line radix
contentSize: parseInt(headers[size]),
contentType: headers[type],
nativeWidth,
@@ -345,15 +343,24 @@ export namespace DashUploadUtils {
const outputPath = path.resolve(pathToDirectory(Directory.images), outputFileName);
const sizes = imageResampleSizes(path.extname(outputFileName));
- const imgReadStream = new Duplex();
- imgReadStream.push(fs.readFileSync(imgSourcePath));
- imgReadStream.push(null);
- await Promise.all(
- sizes.map(({ suffix }) =>
- new Promise<unknown>(res =>
- imgReadStream.pipe(createWriteStream(writtenFiles[suffix] = InjectSize(outputPath, suffix))).on('close', res)
- )
- )); // prettier-ignore
+ if (unlinkSource) {
+ const imgReadStream = new Duplex();
+ imgReadStream.push(fs.readFileSync(imgSourcePath));
+ imgReadStream.push(null);
+ await Promise.all(
+ sizes.map(({ suffix }) =>
+ new Promise<unknown>(res =>
+ imgReadStream.pipe(createWriteStream(writtenFiles[suffix] = InjectSize(outputPath, suffix))).on('close', res)
+ )
+ )); // prettier-ignore
+ } else {
+ await Promise.all(
+ sizes.map(({ suffix }) =>
+ new Promise<unknown>(res =>
+ request.get(imgSourcePath).pipe(createWriteStream(writtenFiles[suffix] = InjectSize(outputPath, suffix))).on('close', res)
+ )
+ )); // prettier-ignore
+ }
workerResample(imgSourcePath, outputPath, SizeSuffix.Original, unlinkSource);
return writtenFiles;
@@ -370,7 +377,7 @@ export namespace DashUploadUtils {
* @returns the accessPaths for the resized files.
*/
export const UploadInspectedImage = async (metadata: Upload.InspectionResults, filename: string, prefix = '', cleanUp = true): Promise<Upload.ImageInformation> => {
- const { requestable, source, ...remaining } = metadata;
+ const { requestable, ...remaining } = metadata;
const dfltSuffix = remaining.contentType.split('/')[1].toLowerCase();
const resolved = filename || `${prefix}upload_${Utils.GenerateGuid()}.${dfltSuffix === 'xml' ? 'jpg' : dfltSuffix}`;
const { images } = Directory;
@@ -452,7 +459,7 @@ export namespace DashUploadUtils {
}
const outputFile = filename || result.filename || '';
- return UploadInspectedImage(result, outputFile, prefix);
+ return UploadInspectedImage(result, outputFile, prefix, isLocal().exec(source) ? true : false);
};
type md5 = 'md5';
@@ -570,7 +577,9 @@ export namespace DashUploadUtils {
switch (category) {
case 'image':
if (imageFormats.includes(format)) {
- const result = await UploadImage(filepath, basename(filepath));
+ const outputName = basename(filepath);
+ const extname = path.extname(originalFilename ?? '');
+ const result = await UploadImage(filepath, outputName.endsWith(extname) ? outputName : outputName + extname, undefined);
return { source: file, result };
}
fs.unlink(filepath, () => {});