aboutsummaryrefslogtreecommitdiff
path: root/src/server/ApiManagers/FireflyManager.ts
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2025-08-04 09:56:12 -0400
committerbobzel <zzzman@gmail.com>2025-08-04 09:56:12 -0400
commit8ec4e4fbd42be8ba6606d78da25c33f69d30ed63 (patch)
treec5bc08a54af8e76138cc4479604a8d911c6535fa /src/server/ApiManagers/FireflyManager.ts
parent08d3b5c0208f8ec8e8c42a822c1793a30d107c3b (diff)
switched to use firefly for image fill
Diffstat (limited to 'src/server/ApiManagers/FireflyManager.ts')
-rw-r--r--src/server/ApiManagers/FireflyManager.ts112
1 files changed, 85 insertions, 27 deletions
diff --git a/src/server/ApiManagers/FireflyManager.ts b/src/server/ApiManagers/FireflyManager.ts
index 6393a1f74..fbf7d7202 100644
--- a/src/server/ApiManagers/FireflyManager.ts
+++ b/src/server/ApiManagers/FireflyManager.ts
@@ -7,8 +7,9 @@ import { DashUserModel } from '../authentication/DashUserModel';
import { DashUploadUtils } from '../DashUploadUtils';
import { _error, _invalid, _success, Method } from '../RouteManager';
import { Upload } from '../SharedMediaTypes';
-import { Directory, filesDirectory } from '../SocketData';
+import { Directory, filesDirectory, pathToDirectory } from '../SocketData';
import ApiManager, { Registration } from './ApiManager';
+import * as formidable from 'formidable';
export default class FireflyManager extends ApiManager {
getBearerToken = () =>
@@ -23,6 +24,44 @@ export default class FireflyManager extends ApiManager {
return undefined;
});
+ generateImageFillWithMask = (prompt: string = 'a realistic illustration of a cat coding', uploadUrl: string, maskUrl: string | undefined, width: number = 2048, height: number = 2048, variations: number = 1) =>
+ this.getBearerToken().then(response =>
+ response?.json().then((data: { access_token: string }) =>
+ //prettier-ignore
+ fetch('https://firefly-api.adobe.io/v3/images/fill', {
+ method: 'POST',
+ headers: [
+ ['Content-Type', 'application/json'],
+ ['Accept', 'application/json'],
+ ['x-api-key', process.env._CLIENT_FIREFLY_CLIENT_ID ?? ''],
+ ['Authorization', `Bearer ${data.access_token}`],
+ ],
+ body: JSON.stringify({
+ image: {
+ source: { url: uploadUrl },
+ mask: {
+ invert: true,
+ url: maskUrl
+ },
+ },
+ size: {
+ width: Math.round(width),
+ height: Math.round(height),
+ },
+ prompt: prompt ?? '',
+ numVariations: variations,
+ }),
+ })
+ .then(response2 => response2.json().then(json =>
+ {
+ if (json.outputs?.length)
+ return (json.outputs as {image: {url:string }}[]).map(output => output.image);
+ throw new Error(JSON.stringify(json));
+ })
+ )
+ )
+ );
+
generateImageFromStructure = (
prompt: string = 'a realistic illustration of a cat coding',
width: number = 2048,
@@ -79,6 +118,30 @@ export default class FireflyManager extends ApiManager {
)
);
+ uploadToDropbox = (dropboxClient: Dropbox, user: DashUserModel | undefined, fileUrl: string, contents: NonSharedBuffer, recursed?: boolean): Promise<string | Error> =>
+ dropboxClient
+ .filesUpload({ path: `/Apps/browndash/${path.basename(fileUrl)}`, contents, mode: { '.tag': 'overwrite' } })
+ .then(response =>
+ dropboxClient
+ .filesGetTemporaryLink({ path: response.result.path_display ?? '' })
+ .then(link => link.result.link)
+ .catch(linkErr => new Error('Failed to get temporary link: ' + linkErr.message))
+ )
+ .catch(uploadErr => {
+ if (user?.dropboxRefresh && !recursed) {
+ console.log('Attempting to refresh Dropbox token for user:', user.email);
+ return this.refreshDropboxToken(user)
+ .then(token => {
+ if (!token) return new Error('Failed to refresh Dropbox token.' + user.email);
+
+ const dbxNew = new Dropbox({ accessToken: token });
+ return this.uploadToDropbox(dbxNew, user, fileUrl, contents, true).catch(finalErr => new Error('Failed to refresh Dropbox token:' + finalErr.message));
+ })
+ .catch(refreshErr => new Error('Failed to refresh Dropbox token: ' + refreshErr.message));
+ }
+ return new Error('Dropbox error: ' + uploadErr.message);
+ });
+
uploadImageToDropbox = (fileUrl: string, user: DashUserModel | undefined, dbx = new Dropbox({ accessToken: user?.dropboxToken || '' })) =>
new Promise<string>((resolve, reject) => {
fs.readFile(path.join(filesDirectory, `${Directory.images}/${path.basename(fileUrl)}`), undefined, (err, contents) => {
@@ -86,32 +149,7 @@ export default class FireflyManager extends ApiManager {
return reject(new Error('Error reading file:' + err.message));
}
- const uploadToDropbox = (dropboxClient: Dropbox) =>
- dropboxClient
- .filesUpload({ path: `/Apps/browndash/${path.basename(fileUrl)}`, contents })
- .then(response =>
- dropboxClient
- .filesGetTemporaryLink({ path: response.result.path_display ?? '' })
- .then(link => resolve(link.result.link))
- .catch(linkErr => reject(new Error('Failed to get temporary link: ' + linkErr.message)))
- )
- .catch(uploadErr => {
- if (user?.dropboxRefresh) {
- console.log('Attempting to refresh Dropbox token for user:', user.email);
- this.refreshDropboxToken(user)
- .then(token => {
- if (!token) return reject(new Error('Failed to refresh Dropbox token.' + user.email));
-
- const dbxNew = new Dropbox({ accessToken: token });
- uploadToDropbox(dbxNew).catch(finalErr => reject(new Error('Failed to refresh Dropbox token:' + finalErr.message)));
- })
- .catch(refreshErr => reject(new Error('Failed to refresh Dropbox token: ' + refreshErr.message)));
- } else {
- reject(new Error('Dropbox error: ' + uploadErr.message));
- }
- });
-
- uploadToDropbox(dbx);
+ this.uploadToDropbox(dbx, user, fileUrl, contents).then(value => (value instanceof Error ? reject(value) : resolve(value)));
});
});
@@ -318,6 +356,26 @@ export default class FireflyManager extends ApiManager {
})
), // prettier-ignore
});
+ register({
+ method: Method.POST,
+ subscription: '/queryFireflyImageFillWithMask',
+ secureHandler: ({ req, res }) =>
+ new Promise<string>(resolve => {
+ const user = req.user as DashUserModel;
+ const accessToken = user?.dropboxToken || '';
+ const dbx = new Dropbox({ accessToken });
+ const form = new formidable.IncomingForm({ keepExtensions: true, uploadDir: pathToDirectory(Directory.parsed_files) });
+ form.parse(req, async (err, fields, files) => {
+ if (files.source && files.mask) {
+ Promise.all([this.uploadToDropbox(dbx, user, 'source.png', fs.readFileSync(files.source[0].filepath)),
+ this.uploadToDropbox(dbx, user, 'mask.png', fs.readFileSync(files.mask[0].filepath))])
+ .then(stuff =>
+ stuff.some(s => s instanceof Error) ? resolve("") : this.generateImageFillWithMask(fields["prompt"]?.[0], stuff[0] as string, stuff[1] as string, 2048, 2048, 1).then(url => resolve(url![0].url))
+ ).catch(() => resolve("") ); // prettier-ignore
+ }
+ });
+ }).then(url => (url ? _success(res, { urls: [url] }) : _invalid(res, 'Failed to fill image'))),
+ });
register({
method: Method.POST,