From 63f514893d429195afa338344b3132e21ad1da8f Mon Sep 17 00:00:00 2001 From: autemox Date: Fri, 28 Jul 2023 14:11:17 -0700 Subject: [PATCH 1/4] added pan-right, works with remix prompt --- .vscode/launch.json | 20 ++++ example/custompan.ts | 94 +++++++++++++++ package-lock.json | 248 ++++------------------------------------ package.json | 2 +- package.json.bak | 56 +++++++++ savedUpscale.json | 71 ++++++++++++ src/interfaces/modal.ts | 3 +- src/midjourne.api.ts | 32 ++++++ src/midjourney.ts | 23 +++- src/utils/index.ts | 2 + yarn.lock | 125 +------------------- 11 files changed, 323 insertions(+), 353 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 example/custompan.ts create mode 100644 package.json.bak create mode 100644 savedUpscale.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..3cd83e4 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,20 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Launch example:pan", + "runtimeExecutable": "npm", + "runtimeArgs": [ + "run", + "example:pan" + ], + "skipFiles": [ + "/**" + ], + "console": "integratedTerminal", // this will run the script in the integrated terminal + "internalConsoleOptions": "neverOpen" // prevents the debug console from taking focus + } + ] +} diff --git a/example/custompan.ts b/example/custompan.ts new file mode 100644 index 0000000..199f499 --- /dev/null +++ b/example/custompan.ts @@ -0,0 +1,94 @@ +import "dotenv/config"; +import fs from 'fs'; +import { Midjourney } from "../src"; +/** + * + * a simple example of how to use the (custom pan) options with ws command + * ``` + * npx tsx example/custompan.ts + * ``` + */ +async function main() { + const client = new Midjourney({ + ServerId: process.env.SERVER_ID, + ChannelId: process.env.CHANNEL_ID, + SalaiToken: process.env.SALAI_TOKEN, + Debug: true, + Ws: true, //enable ws is required for custom pan + }); + await client.init(); + const prompt = + "Blonde Boy plays with Golden Retreiever in dream-like grassy field ::3 happy :: blonde :: golden retriever :: green nature :: simple yellow and orange illustration"; + const remixPrompt = + "dream-like grassy field ::3 happy :: green nature :: simple yellow and orange illustration"; + + /* comment out imagine and upscale if using load from file */ + //imagine + const Imagine = await client.Imagine( + prompt, + (uri: string, progress: string) => { + console.log("loading", uri, "progress", progress); + } + ); + console.log(Imagine); + if (!Imagine) { + console.log("no message"); + return; + } + + // Upscale U1 + const U1CustomID = Imagine.options?.find((o) => o.label === "U1")?.custom; + if (!U1CustomID) { + console.log("no U1"); + return; + } + const Upscale = await client.Custom({ + msgId: Imagine.id, + flags: Imagine.flags, + customId: U1CustomID, + loading: (uri: string, progress: string) => { + console.log("loading", uri, "progress", progress); + }, + }); + + /* comment out save and load if using imagine and upscale + // save Upscale post-imagine so image doesnt have to be generated every time testing on custom pan is run + fs.writeFileSync('savedUpscale.json', JSON.stringify(Upscale, null, 2)); + + // load from file + const jsonString = fs.readFileSync('savedUpscale.json', 'utf-8'); + const Upscale = JSON.parse(jsonString); + */ + + if(!Upscale){ + console.log("no Upscale"); + return; + } + console.log("UPSCALE:", Upscale); + + // Custom Pan + const pan = Upscale?.options?.find((o) => o.label === "➡️"); + if (!pan) { + console.log("no pan"); + return; + } + const CustomPan = await client.Custom({ + msgId: Upscale.id, + flags: Upscale.flags, + content: `${remixPrompt}`, + customId: pan.custom, + loading: (uri: string, progress: string) => { + console.log("loading", uri, "progress", progress); + }, + }); + console.log("Custom Pan", CustomPan); + client.Close(); +} +main() + .then(() => { + console.log("done"); + }) + .catch((err) => { + console.error(err); + process.exit(1); + }); diff --git a/package-lock.json b/package-lock.json index 0ffbfe2..54a9d3d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,30 +1,25 @@ { "name": "midjourney", - "version": "2.5.0", + "version": "4.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "midjourney", - "version": "2.5.0", + "version": "4.0.0", "license": "ISC", "dependencies": { "@huggingface/inference": "^2.5.0", - "https-proxy-agent": "^7.0.0", + "async": "^3.2.4", "isomorphic-ws": "^5.0.0", - "mime": "^3.0.0", - "node-fetch": "^2.6.11", - "p-queue": "^6.6.2", + "semiver": "^1.1.0", "snowyflake": "^2.0.0", - "throat": "^6.0.2", "tslib": "^2.5.0", - "websocket-ts": "^1.1.1", "ws": "^8.13.0" }, "devDependencies": { - "@types/mime": "^3.0.1", + "@types/async": "^3.2.20", "@types/node": "^18.16.0", - "@types/node-fetch": "^2.6.4", "@types/ws": "^8.5.4", "dotenv": "^16.0.3", "prettier": "^2.8.8", @@ -155,10 +150,10 @@ "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", "dev": true }, - "node_modules/@types/mime": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", - "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==", + "node_modules/@types/async": { + "version": "3.2.20", + "resolved": "https://registry.npmjs.org/@types/async/-/async-3.2.20.tgz", + "integrity": "sha512-6jSBQQugzyX1aWto0CbvOnmxrU9tMoXfA9gc4IrLEtvr3dTwSg5GLGoWiZnGLI6UG/kqpB3JOQKQrqnhUWGKQA==", "dev": true }, "node_modules/@types/node": { @@ -168,16 +163,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/node-fetch": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.4.tgz", - "integrity": "sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "form-data": "^3.0.0" - } - }, "node_modules/@types/ws": { "version": "8.5.4", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz", @@ -208,28 +193,16 @@ "node": ">=0.4.0" } }, - "node_modules/agent-base": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", - "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" }, "node_modules/buffer-from": { "version": "1.1.2", @@ -238,49 +211,12 @@ "dev": true, "license": "MIT" }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -338,25 +274,6 @@ "@esbuild/win32-x64": "0.17.18" } }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" - }, - "node_modules/form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", @@ -381,18 +298,6 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/https-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.0.tgz", - "integrity": "sha512-0euwPCRyAPSgGdzD1IVN9nJYHtBhJwb6XPfbpQcYbPCwrBidX6GzxmchnaF4sfF/jPb74Ojx5g4yTg3sixlyPw==", - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/isomorphic-ws": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", @@ -407,96 +312,6 @@ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, - "node_modules/mime": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", - "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/node-fetch": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", - "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", - "engines": { - "node": ">=4" - } - }, - "node_modules/p-queue": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", - "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", - "dependencies": { - "eventemitter3": "^4.0.4", - "p-timeout": "^3.2.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-timeout": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", - "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", - "dependencies": { - "p-finally": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/prettier": { "version": "2.8.8", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", @@ -513,6 +328,14 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/semiver": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semiver/-/semiver-1.1.0.tgz", + "integrity": "sha512-QNI2ChmuioGC1/xjyYwyZYADILWyW6AmS1UH6gDj/SFUUUS4MBAWs/7mxnkRPc/F4iHezDP+O8t0dO8WHiEOdg==", + "engines": { + "node": ">=6" + } + }, "node_modules/snowyflake": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/snowyflake/-/snowyflake-2.0.0.tgz", @@ -542,16 +365,6 @@ "source-map": "^0.6.0" } }, - "node_modules/throat": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.2.tgz", - "integrity": "sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==" - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, "node_modules/ts-node": { "version": "10.9.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", @@ -638,25 +451,6 @@ "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", "dev": true }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "node_modules/websocket-ts": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/websocket-ts/-/websocket-ts-1.1.1.tgz", - "integrity": "sha512-rm+S60J74Ckw5iizzgID12ju+OfaHAa6dhXhULIOrXkl0e05RzxfY42/vMStpz5jWL3iz9mkyjPcFUY1IgI0fw==" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "node_modules/ws": { "version": "8.13.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", diff --git a/package.json b/package.json index 1557ffe..de66dfb 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "build": "tsc", "prettier": "prettier --write .", "prettier:check": "prettier --check .", - "example:imagine": "tsx ./examples/imagine-ws.ts" + "example:pan": "tsx ./example/custompan.ts" }, "files": [ "libs/*", diff --git a/package.json.bak b/package.json.bak new file mode 100644 index 0000000..10ae5b8 --- /dev/null +++ b/package.json.bak @@ -0,0 +1,56 @@ +{ + "name": "midjourney", + "version": "4.0.0", + "description": "Node.js client for the unofficial MidJourney API.", + "main": "libs/index.js", + "types": "libs/index.d.ts", + "source": "./src/index.ts", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "build": "tsc", + "prettier": "prettier --write .", + "prettier:check": "prettier --check .", + "example:imagine": "tsx ./example/custompan.ts" + }, + "files": [ + "libs/*", + "src/*", + "*.md" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/erictik/midjourney-client.git" + }, + "keywords": [ + "midjourney-client", + "midjourney" + ], + "engines": { + "node": ">=18" + }, + "author": "Eric Yang ", + "license": "ISC", + "bugs": { + "url": "https://github.com/erictik/midjourney-client/issues" + }, + "homepage": "https://github.com/erictik/midjourney-client#readme", + "devDependencies": { + "@types/async": "^3.2.20", + "@types/node": "^18.16.0", + "@types/ws": "^8.5.4", + "dotenv": "^16.0.3", + "prettier": "^2.8.8", + "ts-node": "^10.9.1", + "tsx": "^3.12.6", + "typescript": "^5.0.4" + }, + "dependencies": { + "@huggingface/inference": "^2.5.0", + "async": "^3.2.4", + "isomorphic-ws": "^5.0.0", + "semiver": "^1.1.0", + "snowyflake": "^2.0.0", + "tslib": "^2.5.0", + "ws": "^8.13.0" + } +} diff --git a/savedUpscale.json b/savedUpscale.json new file mode 100644 index 0000000..44bbeb0 --- /dev/null +++ b/savedUpscale.json @@ -0,0 +1,71 @@ +{ + "id": "1134585311494688879", + "flags": 0, + "content": "**Blonde Boy plays with Golden Retreiever in dream-like grassy field ::3 happy :: blonde :: golden retriever :: green nature :: simple yellow and orange illustration** - Image #1 <@837174620934242314>", + "hash": "ad103d4c-1e5e-4726-b809-00a12f6ec6b6", + "progress": "done", + "uri": "https://cdn.discordapp.com/attachments/1093833579471065128/1134585310186065960/Stew_Blonde_Boy_plays_with_Golden_Retreiever_in_dream-like_gras_ad103d4c-1e5e-4726-b809-00a12f6ec6b6.png", + "proxy_url": "https://media.discordapp.net/attachments/1093833579471065128/1134585310186065960/Stew_Blonde_Boy_plays_with_Golden_Retreiever_in_dream-like_gras_ad103d4c-1e5e-4726-b809-00a12f6ec6b6.png", + "options": [ + { + "type": 2, + "style": 2, + "label": "Vary (Strong)", + "custom": "MJ::JOB::high_variation::1::ad103d4c-1e5e-4726-b809-00a12f6ec6b6::SOLO" + }, + { + "type": 2, + "style": 2, + "label": "Vary (Subtle)", + "custom": "MJ::JOB::low_variation::1::ad103d4c-1e5e-4726-b809-00a12f6ec6b6::SOLO" + }, + { + "type": 2, + "style": 2, + "label": "Zoom Out 2x", + "custom": "MJ::Outpaint::50::1::ad103d4c-1e5e-4726-b809-00a12f6ec6b6::SOLO" + }, + { + "type": 2, + "style": 2, + "label": "Zoom Out 1.5x", + "custom": "MJ::Outpaint::75::1::ad103d4c-1e5e-4726-b809-00a12f6ec6b6::SOLO" + }, + { + "type": 2, + "style": 2, + "label": "Custom Zoom", + "custom": "MJ::CustomZoom::ad103d4c-1e5e-4726-b809-00a12f6ec6b6" + }, + { + "type": 2, + "style": 2, + "label": "⬅️", + "custom": "MJ::JOB::pan_left::1::ad103d4c-1e5e-4726-b809-00a12f6ec6b6::SOLO" + }, + { + "type": 2, + "style": 2, + "label": "➡️", + "custom": "MJ::JOB::pan_right::1::ad103d4c-1e5e-4726-b809-00a12f6ec6b6::SOLO" + }, + { + "type": 2, + "style": 2, + "label": "⬆️", + "custom": "MJ::JOB::pan_up::1::ad103d4c-1e5e-4726-b809-00a12f6ec6b6::SOLO" + }, + { + "type": 2, + "style": 2, + "label": "⬇️", + "custom": "MJ::JOB::pan_down::1::ad103d4c-1e5e-4726-b809-00a12f6ec6b6::SOLO" + }, + { + "type": 2, + "style": 2, + "label": "❤️", + "custom": "MJ::BOOKMARK::ad103d4c-1e5e-4726-b809-00a12f6ec6b6" + } + ] +} \ No newline at end of file diff --git a/src/interfaces/modal.ts b/src/interfaces/modal.ts index ad3a72e..1c71223 100644 --- a/src/interfaces/modal.ts +++ b/src/interfaces/modal.ts @@ -1,7 +1,8 @@ export const RemixModalSubmitID = "MJ::RemixModal::new_prompt" export const CustomZoomModalSubmitID = "MJ::OutpaintCustomZoomModal::prompt" +export const CustomPanModalSubmitID = "MJ::PanModal::prompt" export const ShortenModalSubmitID = "MJ::ImagineModal::new_prompt" export const DescribeModalSubmitID = "MJ::Picreader::Modal::PromptField" -export type ModalSubmitID = typeof RemixModalSubmitID | typeof CustomZoomModalSubmitID | typeof ShortenModalSubmitID | typeof DescribeModalSubmitID \ No newline at end of file +export type ModalSubmitID = typeof RemixModalSubmitID | typeof CustomPanModalSubmitID | typeof CustomZoomModalSubmitID | typeof ShortenModalSubmitID | typeof DescribeModalSubmitID \ No newline at end of file diff --git a/src/midjourne.api.ts b/src/midjourne.api.ts index 1b1fde9..35a8363 100644 --- a/src/midjourne.api.ts +++ b/src/midjourne.api.ts @@ -5,6 +5,7 @@ import { MJConfig, ModalSubmitID, RemixModalSubmitID, + CustomPanModalSubmitID, ShortenModalSubmitID, UploadParam, UploadSlot, @@ -180,6 +181,7 @@ export class MidjourneyApi extends Command { custom_id: customId, }, }; + console.log("CustomApi payload for safeIteractions: ", payload) return this.safeIteractions(payload); } @@ -309,6 +311,36 @@ export class MidjourneyApi extends Command { }); } + async CustomPanImagineApi({ + nonce, + msgId, + customId, + prompt, + }: { + nonce: string; + msgId: string; + customId: string; + prompt: string; + }) { + customId = customId.replace( + "MJ::JOB::pan_right::1", + "MJ::PanModal::right" + ); + + customId = customId.replace( + "::SOLO", + "" + ); + console.log("Reformatted custom for modal (removed SOLO, etc): ", customId); + return this.ModalSubmitApi({ + nonce, + msgId, + customId, + prompt, + submitCustomId: CustomPanModalSubmitID, + }); + } + async InfoApi(nonce?: string) { const payload = await this.infoPayload(nonce); return this.safeIteractions(payload); diff --git a/src/midjourney.ts b/src/midjourney.ts index b8eb59c..bf8fb88 100644 --- a/src/midjourney.ts +++ b/src/midjourney.ts @@ -268,6 +268,7 @@ export class Midjourney extends MidjourneyMessage { throw new Error(`CustomApi failed with status ${httpStatus}`); } if (this.wsClient) { + console.log("Awaiting ImageMessage"); return await this.wsClient.waitImageMessage({ nonce, loading, @@ -278,20 +279,34 @@ export class Midjourney extends MidjourneyMessage { return ""; } const newNonce = nextNonce(); + console.log("Got ImageMessage. Type: "+custom2Type(customId)); switch (custom2Type(customId)) { - case "customZoom": - const httpStatus = await this.MJApi.CustomZoomImagineApi({ + case "customPan": + const panHttpStatus = await this.MJApi.CustomPanImagineApi({ msgId: id, customId, prompt: content, nonce: newNonce, }); - if (httpStatus !== 204) { + if (panHttpStatus !== 204) { throw new Error( - `CustomZoomImagineApi failed with status ${httpStatus}` + `CustomPanImagineApi failed with status ${panHttpStatus}` ); } return newNonce; + case "customZoom": + const httpStatus = await this.MJApi.CustomZoomImagineApi({ + msgId: id, + customId, + prompt: content, + nonce: newNonce, + }); + if (httpStatus !== 204) { + throw new Error( + `CustomZoomImagineApi failed with status ${httpStatus}` + ); + } + return newNonce; case "variation": if (this.config.Remix !== true) { return ""; diff --git a/src/utils/index.ts b/src/utils/index.ts index f912e4f..b25ae06 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -139,6 +139,8 @@ export function custom2Type(custom: string) { return "reroll"; } else if (custom.includes("CustomZoom")) { return "customZoom"; + } else if (custom.includes("pan")) { + return "customPan"; } else if (custom.includes("Outpaint")) { return "variation"; } else if (custom.includes("remaster")) { diff --git a/yarn.lock b/yarn.lock index ed5462e..38e6f6e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -33,116 +33,6 @@ "@esbuild-kit/core-utils" "^3.0.0" get-tsconfig "^4.4.0" -"@esbuild/android-arm64@0.17.18": - version "0.17.18" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.17.18.tgz#4aa8d8afcffb4458736ca9b32baa97d7cb5861ea" - integrity sha512-/iq0aK0eeHgSC3z55ucMAHO05OIqmQehiGay8eP5l/5l+iEr4EIbh4/MI8xD9qRFjqzgkc0JkX0LculNC9mXBw== - -"@esbuild/android-arm@0.17.18": - version "0.17.18" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.17.18.tgz#74a7e95af4ee212ebc9db9baa87c06a594f2a427" - integrity sha512-EmwL+vUBZJ7mhFCs5lA4ZimpUH3WMAoqvOIYhVQwdIgSpHC8ImHdsRyhHAVxpDYUSm0lWvd63z0XH1IlImS2Qw== - -"@esbuild/android-x64@0.17.18": - version "0.17.18" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.17.18.tgz#1dcd13f201997c9fe0b204189d3a0da4eb4eb9b6" - integrity sha512-x+0efYNBF3NPW2Xc5bFOSFW7tTXdAcpfEg2nXmxegm4mJuVeS+i109m/7HMiOQ6M12aVGGFlqJX3RhNdYM2lWg== - -"@esbuild/darwin-arm64@0.17.18": - version "0.17.18" - resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.18.tgz" - integrity sha512-6tY+djEAdF48M1ONWnQb1C+6LiXrKjmqjzPNPWXhu/GzOHTHX2nh8Mo2ZAmBFg0kIodHhciEgUBtcYCAIjGbjQ== - -"@esbuild/darwin-x64@0.17.18": - version "0.17.18" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.17.18.tgz#a6da308d0ac8a498c54d62e0b2bfb7119b22d315" - integrity sha512-Qq84ykvLvya3dO49wVC9FFCNUfSrQJLbxhoQk/TE1r6MjHo3sFF2tlJCwMjhkBVq3/ahUisj7+EpRSz0/+8+9A== - -"@esbuild/freebsd-arm64@0.17.18": - version "0.17.18" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.18.tgz#b83122bb468889399d0d63475d5aea8d6829c2c2" - integrity sha512-fw/ZfxfAzuHfaQeMDhbzxp9mc+mHn1Y94VDHFHjGvt2Uxl10mT4CDavHm+/L9KG441t1QdABqkVYwakMUeyLRA== - -"@esbuild/freebsd-x64@0.17.18": - version "0.17.18" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.17.18.tgz#af59e0e03fcf7f221b34d4c5ab14094862c9c864" - integrity sha512-FQFbRtTaEi8ZBi/A6kxOC0V0E9B/97vPdYjY9NdawyLd4Qk5VD5g2pbWN2VR1c0xhzcJm74HWpObPszWC+qTew== - -"@esbuild/linux-arm64@0.17.18": - version "0.17.18" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.17.18.tgz#8551d72ba540c5bce4bab274a81c14ed01eafdcf" - integrity sha512-R7pZvQZFOY2sxUG8P6A21eq6q+eBv7JPQYIybHVf1XkQYC+lT7nDBdC7wWKTrbvMXKRaGudp/dzZCwL/863mZQ== - -"@esbuild/linux-arm@0.17.18": - version "0.17.18" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.17.18.tgz#e09e76e526df4f665d4d2720d28ff87d15cdf639" - integrity sha512-jW+UCM40LzHcouIaqv3e/oRs0JM76JfhHjCavPxMUti7VAPh8CaGSlS7cmyrdpzSk7A+8f0hiedHqr/LMnfijg== - -"@esbuild/linux-ia32@0.17.18": - version "0.17.18" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.17.18.tgz#47878860ce4fe73a36fd8627f5647bcbbef38ba4" - integrity sha512-ygIMc3I7wxgXIxk6j3V00VlABIjq260i967Cp9BNAk5pOOpIXmd1RFQJQX9Io7KRsthDrQYrtcx7QCof4o3ZoQ== - -"@esbuild/linux-loong64@0.17.18": - version "0.17.18" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.17.18.tgz#3f8fbf5267556fc387d20b2e708ce115de5c967a" - integrity sha512-bvPG+MyFs5ZlwYclCG1D744oHk1Pv7j8psF5TfYx7otCVmcJsEXgFEhQkbhNW8otDHL1a2KDINW20cfCgnzgMQ== - -"@esbuild/linux-mips64el@0.17.18": - version "0.17.18" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.17.18.tgz#9d896d8f3c75f6c226cbeb840127462e37738226" - integrity sha512-oVqckATOAGuiUOa6wr8TXaVPSa+6IwVJrGidmNZS1cZVx0HqkTMkqFGD2HIx9H1RvOwFeWYdaYbdY6B89KUMxA== - -"@esbuild/linux-ppc64@0.17.18": - version "0.17.18" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.17.18.tgz#3d9deb60b2d32c9985bdc3e3be090d30b7472783" - integrity sha512-3dLlQO+b/LnQNxgH4l9rqa2/IwRJVN9u/bK63FhOPB4xqiRqlQAU0qDU3JJuf0BmaH0yytTBdoSBHrb2jqc5qQ== - -"@esbuild/linux-riscv64@0.17.18": - version "0.17.18" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.17.18.tgz#8a943cf13fd24ff7ed58aefb940ef178f93386bc" - integrity sha512-/x7leOyDPjZV3TcsdfrSI107zItVnsX1q2nho7hbbQoKnmoeUWjs+08rKKt4AUXju7+3aRZSsKrJtaRmsdL1xA== - -"@esbuild/linux-s390x@0.17.18": - version "0.17.18" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.17.18.tgz#66cb01f4a06423e5496facabdce4f7cae7cb80e5" - integrity sha512-cX0I8Q9xQkL/6F5zWdYmVf5JSQt+ZfZD2bJudZrWD+4mnUvoZ3TDDXtDX2mUaq6upMFv9FlfIh4Gfun0tbGzuw== - -"@esbuild/linux-x64@0.17.18": - version "0.17.18" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.17.18.tgz#23c26050c6c5d1359c7b774823adc32b3883b6c9" - integrity sha512-66RmRsPlYy4jFl0vG80GcNRdirx4nVWAzJmXkevgphP1qf4dsLQCpSKGM3DUQCojwU1hnepI63gNZdrr02wHUA== - -"@esbuild/netbsd-x64@0.17.18": - version "0.17.18" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.17.18.tgz#789a203d3115a52633ff6504f8cbf757f15e703b" - integrity sha512-95IRY7mI2yrkLlTLb1gpDxdC5WLC5mZDi+kA9dmM5XAGxCME0F8i4bYH4jZreaJ6lIZ0B8hTrweqG1fUyW7jbg== - -"@esbuild/openbsd-x64@0.17.18": - version "0.17.18" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.17.18.tgz#d7b998a30878f8da40617a10af423f56f12a5e90" - integrity sha512-WevVOgcng+8hSZ4Q3BKL3n1xTv5H6Nb53cBrtzzEjDbbnOmucEVcZeGCsCOi9bAOcDYEeBZbD2SJNBxlfP3qiA== - -"@esbuild/sunos-x64@0.17.18": - version "0.17.18" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.17.18.tgz#ecad0736aa7dae07901ba273db9ef3d3e93df31f" - integrity sha512-Rzf4QfQagnwhQXVBS3BYUlxmEbcV7MY+BH5vfDZekU5eYpcffHSyjU8T0xucKVuOcdCsMo+Ur5wmgQJH2GfNrg== - -"@esbuild/win32-arm64@0.17.18": - version "0.17.18" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.17.18.tgz#58dfc177da30acf956252d7c8ae9e54e424887c4" - integrity sha512-Kb3Ko/KKaWhjeAm2YoT/cNZaHaD1Yk/pa3FTsmqo9uFh1D1Rfco7BBLIPdDOozrObj2sahslFuAQGvWbgWldAg== - -"@esbuild/win32-ia32@0.17.18": - version "0.17.18" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.17.18.tgz#340f6163172b5272b5ae60ec12c312485f69232b" - integrity sha512-0/xUMIdkVHwkvxfbd5+lfG7mHOf2FRrxNbPiKWg9C4fFrB8H0guClmaM3BFiRUYrznVoyxTIyC/Ou2B7QQSwmw== - -"@esbuild/win32-x64@0.17.18": - version "0.17.18" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.17.18.tgz#3a8e57153905308db357fd02f57c180ee3a0a1fa" - integrity sha512-qU25Ma1I3NqTSHJUOKi9sAH1/Mzuvlke0ioMJRthLXKm7JiSKVwFghlGbDLOO2sARECGhja4xYfRAZNPAkooYg== - "@huggingface/inference@^2.5.0": version "2.5.0" resolved "https://registry.npmjs.org/@huggingface/inference/-/inference-2.5.0.tgz" @@ -188,7 +78,7 @@ "@types/async@^3.2.20": version "3.2.20" - resolved "https://registry.yarnpkg.com/@types/async/-/async-3.2.20.tgz#53517caaa68c94f99da1c4e986cf7f2954981515" + resolved "https://registry.npmjs.org/@types/async/-/async-3.2.20.tgz" integrity sha512-6jSBQQugzyX1aWto0CbvOnmxrU9tMoXfA9gc4IrLEtvr3dTwSg5GLGoWiZnGLI6UG/kqpB3JOQKQrqnhUWGKQA== "@types/node@*", "@types/node@^18.16.0": @@ -220,7 +110,7 @@ arg@^4.1.0: async@^3.2.4: version "3.2.4" - resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" + resolved "https://registry.npmjs.org/async/-/async-3.2.4.tgz" integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== buffer-from@^1.0.0: @@ -271,11 +161,6 @@ esbuild@~0.17.6: "@esbuild/win32-ia32" "0.17.18" "@esbuild/win32-x64" "0.17.18" -fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== - get-tsconfig@^4.4.0: version "4.5.0" resolved "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.5.0.tgz" @@ -298,7 +183,7 @@ prettier@^2.8.8: semiver@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/semiver/-/semiver-1.1.0.tgz#9c97fb02c21c7ce4fcf1b73e2c7a24324bdddd5f" + resolved "https://registry.npmjs.org/semiver/-/semiver-1.1.0.tgz" integrity sha512-QNI2ChmuioGC1/xjyYwyZYADILWyW6AmS1UH6gDj/SFUUUS4MBAWs/7mxnkRPc/F4iHezDP+O8t0dO8WHiEOdg== snowyflake@^2.0.0: @@ -354,7 +239,7 @@ tsx@^3.12.6: optionalDependencies: fsevents "~2.3.2" -typescript@^5.0.4: +typescript@^5.0.4, typescript@>=2.7: version "5.0.4" resolved "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz" integrity sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw== @@ -364,7 +249,7 @@ v8-compile-cache-lib@^3.0.1: resolved "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz" integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== -ws@^8.13.0: +ws@*, ws@^8.13.0: version "8.13.0" resolved "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz" integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== From 149733b358c5216f5cbe7521300bfdf086da053f Mon Sep 17 00:00:00 2001 From: autemox Date: Fri, 28 Jul 2023 14:15:54 -0700 Subject: [PATCH 2/4] fixed readme to reflect recent outside push --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 05b086b..1b45ee1 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ English / [中文文档](README_zh.md) - [face swap](https://github.com/erictik/midjourney-client/blob/main/example/faceswap.ts) - [niji bot](https://github.com/erictik/midjourney-client/blob/main/example/imagine-niji.ts) - [custom zoom](https://github.com/erictik/midjourney-client/blob/main/example/customzoom.ts) +- [pan right](https://github.com/erictik/midjourney-client/blob/main/example/custompan.ts) - [remix mode](https://github.com/erictik/midjourney-client/blob/main/example/variation-ws.ts) ## Example @@ -254,11 +255,11 @@ To run the included example, you must have [Node.js](https://nodejs.org/en/) ins If you find it valuable and would like to show your support, any donations would be greatly appreciated. Your contribution helps me maintain and improve the program. -   + Buy Me a Coffee ## Star History -[![Star History Chart](https://api.star-history.com/svg?repos=erictik/midjourney-client&type=Date)](https://star-history.com/#erictik/midjourney-client&Date) +[![Star History Chart](https://api.star-history.com/svg?repos=erictik/midjourney-client&type=Date)](https://star-history.com/#erictik/midjourney-client&Date) \ No newline at end of file From 6f979bda84fb46f3d350fbeb8cc2c259cb298d34 Mon Sep 17 00:00:00 2001 From: autemox <31908955+autemox@users.noreply.github.com> Date: Fri, 28 Jul 2023 18:24:24 -0700 Subject: [PATCH 3/4] fixed removewaitmjevent failure and getting stuck awaiting --- src/discord.ws.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/discord.ws.ts b/src/discord.ws.ts index 058bdd7..1ee03d1 100644 --- a/src/discord.ws.ts +++ b/src/discord.ws.ts @@ -598,7 +598,7 @@ export class WsMessage { } } private removeWaitMjEvent(nonce: string) { - this.waitMjEvents.delete(nonce); + this.waitMjEvents.clear(); } onceImage(nonce: string, callback: (data: MJEmit) => void) { const once = (data: MJEmit) => { From d058e340a72014096836bc67383fbf7571f98782 Mon Sep 17 00:00:00 2001 From: autemox Date: Mon, 23 Oct 2023 22:56:25 -0700 Subject: [PATCH 4/4] fixed error stopping this from working, did midjourney change something? --- README.md | 28 ++++++++++++++++ example/custompan.ts | 47 +++++++++++++++++++++------ savedUpscale WORKS.json | 71 +++++++++++++++++++++++++++++++++++++++++ savedUpscale.json | 48 +++++++++++++++++++--------- src/discord.message.ts | 10 ++++++ src/discord.ws.ts | 54 +++++++++++++++++++++++++++---- src/midjourne.api.ts | 14 ++++++-- src/midjourney.ts | 7 ++-- 8 files changed, 243 insertions(+), 36 deletions(-) create mode 100644 savedUpscale WORKS.json diff --git a/README.md b/README.md index 1b45ee1..9d8bff1 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,31 @@ +HOW TO USE A CUSTOM PACKAGE + +Compile the TypeScript Code: + +Based on the package.json you've shared, there is a build script that uses the TypeScript Compiler (tsc). This will compile the .ts files from the src directory to .js files in the libs directory. + +In the root directory of the midjourney project, run: + +bash +Copy code +npm run build +Package and Install in Your Own Project: + +If your main project is located in a different directory, you can package the improved midjourney module and install it in your project. + +Navigate to the midjourney directory and run: + +bash +Copy code +npm pack +This will create a .tgz file, for instance, midjourney-4.0.0.tgz. + +Then, in your main project directory, install the .tgz file: + +bash +Copy code +npm install path_to_tgz_file/midjourney-4.0.0.tgz + # midjourney-client Node.js client for the unofficial MidJourney api. diff --git a/example/custompan.ts b/example/custompan.ts index 199f499..4f689ea 100644 --- a/example/custompan.ts +++ b/example/custompan.ts @@ -18,9 +18,9 @@ async function main() { }); await client.init(); const prompt = - "Blonde Boy plays with Golden Retreiever in dream-like grassy field ::3 happy :: blonde :: golden retriever :: green nature :: simple yellow and orange illustration"; + "Blonde Boy plays with Golden Retreiever in dream-like grassy field ::3 happy :: blonde :: golden retriever :: green nature :: simple illustration"; const remixPrompt = - "dream-like grassy field ::3 happy :: green nature :: simple yellow and orange illustration"; + "empty ::5 grass ::2 dream-like grassy field ::3 green nature :: illustration --no woman, girl, human, dog, person"; /* comment out imagine and upscale if using load from file */ //imagine @@ -37,7 +37,7 @@ async function main() { } // Upscale U1 - const U1CustomID = Imagine.options?.find((o) => o.label === "U1")?.custom; + let U1CustomID = Imagine.options?.find((o) => o.label === "U1")?.custom; if (!U1CustomID) { console.log("no U1"); return; @@ -51,14 +51,13 @@ async function main() { }, }); - /* comment out save and load if using imagine and upscale + // comment out save and load if using imagine and upscale // save Upscale post-imagine so image doesnt have to be generated every time testing on custom pan is run - fs.writeFileSync('savedUpscale.json', JSON.stringify(Upscale, null, 2)); + //fs.writeFileSync('savedUpscale.json', JSON.stringify(Upscale, null, 2)); // load from file - const jsonString = fs.readFileSync('savedUpscale.json', 'utf-8'); - const Upscale = JSON.parse(jsonString); - */ + //const jsonString = fs.readFileSync('savedUpscale.json', 'utf-8'); + //const Upscale = JSON.parse(jsonString); if(!Upscale){ console.log("no Upscale"); @@ -81,8 +80,38 @@ async function main() { console.log("loading", uri, "progress", progress); }, }); + if (!CustomPan) { + console.log("no CustomPan"); + return; + } console.log("Custom Pan", CustomPan); - client.Close(); + + + // UPSCALE AGAIN + U1CustomID = CustomPan.options?.find((o) => o.label === "U1")?.custom; + if (!U1CustomID) { + console.log("no U1"); + return; + } + const Upscale2 = await client.Custom({ + msgId: CustomPan.id, + flags: CustomPan.flags, + customId: U1CustomID, + loading: (uri: string, progress: string) => { + console.log("loading", uri, "progress", progress); + }, + }); + if(!Upscale2){ + console.log("no Upscale2"); + return; + } + console.log("UPSCALE2:", Upscale2); + + + console.log("FINISHED"); + + + // client.Close(); } main() .then(() => { diff --git a/savedUpscale WORKS.json b/savedUpscale WORKS.json new file mode 100644 index 0000000..c324ac8 --- /dev/null +++ b/savedUpscale WORKS.json @@ -0,0 +1,71 @@ +{ + "id": "1134650512625635418", + "flags": 0, + "content": "**Blonde Boy plays with Golden Retreiever in dream-like grassy field ::3 happy :: blonde :: golden retriever :: green nature :: simple yellow and orange illustration** - Image #1 <@837174620934242314>", + "hash": "588d8344-1e5e-47c5-b8ee-8f36811bd88f", + "progress": "done", + "uri": "https://cdn.discordapp.com/attachments/1093833579471065128/1134650512311074846/Stew_Blonde_Boy_plays_with_Golden_Retreiever_in_dream-like_gras_588d8344-1e5e-47c5-b8ee-8f36811bd88f.png", + "proxy_url": "https://media.discordapp.net/attachments/1093833579471065128/1134650512311074846/Stew_Blonde_Boy_plays_with_Golden_Retreiever_in_dream-like_gras_588d8344-1e5e-47c5-b8ee-8f36811bd88f.png", + "options": [ + { + "type": 2, + "style": 2, + "label": "Vary (Strong)", + "custom": "MJ::JOB::high_variation::1::588d8344-1e5e-47c5-b8ee-8f36811bd88f::SOLO" + }, + { + "type": 2, + "style": 2, + "label": "Vary (Subtle)", + "custom": "MJ::JOB::low_variation::1::588d8344-1e5e-47c5-b8ee-8f36811bd88f::SOLO" + }, + { + "type": 2, + "style": 2, + "label": "Zoom Out 2x", + "custom": "MJ::Outpaint::50::1::588d8344-1e5e-47c5-b8ee-8f36811bd88f::SOLO" + }, + { + "type": 2, + "style": 2, + "label": "Zoom Out 1.5x", + "custom": "MJ::Outpaint::75::1::588d8344-1e5e-47c5-b8ee-8f36811bd88f::SOLO" + }, + { + "type": 2, + "style": 2, + "label": "Custom Zoom", + "custom": "MJ::CustomZoom::588d8344-1e5e-47c5-b8ee-8f36811bd88f" + }, + { + "type": 2, + "style": 2, + "label": "⬅️", + "custom": "MJ::JOB::pan_left::1::588d8344-1e5e-47c5-b8ee-8f36811bd88f::SOLO" + }, + { + "type": 2, + "style": 2, + "label": "➡️", + "custom": "MJ::JOB::pan_right::1::588d8344-1e5e-47c5-b8ee-8f36811bd88f::SOLO" + }, + { + "type": 2, + "style": 2, + "label": "⬆️", + "custom": "MJ::JOB::pan_up::1::588d8344-1e5e-47c5-b8ee-8f36811bd88f::SOLO" + }, + { + "type": 2, + "style": 2, + "label": "⬇️", + "custom": "MJ::JOB::pan_down::1::588d8344-1e5e-47c5-b8ee-8f36811bd88f::SOLO" + }, + { + "type": 2, + "style": 2, + "label": "❤️", + "custom": "MJ::BOOKMARK::588d8344-1e5e-47c5-b8ee-8f36811bd88f" + } + ] +} \ No newline at end of file diff --git a/savedUpscale.json b/savedUpscale.json index 44bbeb0..ce75c07 100644 --- a/savedUpscale.json +++ b/savedUpscale.json @@ -1,71 +1,89 @@ { - "id": "1134585311494688879", + "id": "1166252937849348106", "flags": 0, - "content": "**Blonde Boy plays with Golden Retreiever in dream-like grassy field ::3 happy :: blonde :: golden retriever :: green nature :: simple yellow and orange illustration** - Image #1 <@837174620934242314>", - "hash": "ad103d4c-1e5e-4726-b809-00a12f6ec6b6", + "content": "**Blonde Boy plays with Golden Retreiever in dream-like grassy field ::3 happy :: blonde :: golden retriever :: green nature :: simple illustration** - Image #1 <@837174620934242314>", + "hash": "4da0778d-9c4c-40a8-a8dc-ce2f3650c658", "progress": "done", - "uri": "https://cdn.discordapp.com/attachments/1093833579471065128/1134585310186065960/Stew_Blonde_Boy_plays_with_Golden_Retreiever_in_dream-like_gras_ad103d4c-1e5e-4726-b809-00a12f6ec6b6.png", - "proxy_url": "https://media.discordapp.net/attachments/1093833579471065128/1134585310186065960/Stew_Blonde_Boy_plays_with_Golden_Retreiever_in_dream-like_gras_ad103d4c-1e5e-4726-b809-00a12f6ec6b6.png", + "uri": "https://cdn.discordapp.com/attachments/1093833579471065128/1166252937568342087/stewod50_Blonde_Boy_plays_with_Golden_Retreiever_in_dream-like__4da0778d-9c4c-40a8-a8dc-ce2f3650c658.png?ex=6549d0b0&is=65375bb0&hm=0ae07efa5e6e09a3ec8a1f5cd2f00801787ebe680055ffcb8b975c1390e341a9&", + "proxy_url": "https://media.discordapp.net/attachments/1093833579471065128/1166252937568342087/stewod50_Blonde_Boy_plays_with_Golden_Retreiever_in_dream-like__4da0778d-9c4c-40a8-a8dc-ce2f3650c658.png?ex=6549d0b0&is=65375bb0&hm=0ae07efa5e6e09a3ec8a1f5cd2f00801787ebe680055ffcb8b975c1390e341a9&", "options": [ { "type": 2, "style": 2, "label": "Vary (Strong)", - "custom": "MJ::JOB::high_variation::1::ad103d4c-1e5e-4726-b809-00a12f6ec6b6::SOLO" + "custom": "MJ::JOB::high_variation::1::4da0778d-9c4c-40a8-a8dc-ce2f3650c658::SOLO" }, { "type": 2, "style": 2, "label": "Vary (Subtle)", - "custom": "MJ::JOB::low_variation::1::ad103d4c-1e5e-4726-b809-00a12f6ec6b6::SOLO" + "custom": "MJ::JOB::low_variation::1::4da0778d-9c4c-40a8-a8dc-ce2f3650c658::SOLO" + }, + { + "type": 2, + "style": 2, + "label": "Vary (Region)", + "custom": "MJ::Inpaint::1::4da0778d-9c4c-40a8-a8dc-ce2f3650c658::SOLO" + }, + { + "type": 2, + "style": 2, + "label": "Upscale (2x)", + "custom": "MJ::JOB::upsample_v5_2x::1::4da0778d-9c4c-40a8-a8dc-ce2f3650c658::SOLO" + }, + { + "type": 2, + "style": 2, + "label": "Upscale (4x)", + "custom": "MJ::JOB::upsample_v5_4x::1::4da0778d-9c4c-40a8-a8dc-ce2f3650c658::SOLO" }, { "type": 2, "style": 2, "label": "Zoom Out 2x", - "custom": "MJ::Outpaint::50::1::ad103d4c-1e5e-4726-b809-00a12f6ec6b6::SOLO" + "custom": "MJ::Outpaint::50::1::4da0778d-9c4c-40a8-a8dc-ce2f3650c658::SOLO" }, { "type": 2, "style": 2, "label": "Zoom Out 1.5x", - "custom": "MJ::Outpaint::75::1::ad103d4c-1e5e-4726-b809-00a12f6ec6b6::SOLO" + "custom": "MJ::Outpaint::75::1::4da0778d-9c4c-40a8-a8dc-ce2f3650c658::SOLO" }, { "type": 2, "style": 2, "label": "Custom Zoom", - "custom": "MJ::CustomZoom::ad103d4c-1e5e-4726-b809-00a12f6ec6b6" + "custom": "MJ::CustomZoom::4da0778d-9c4c-40a8-a8dc-ce2f3650c658" }, { "type": 2, "style": 2, "label": "⬅️", - "custom": "MJ::JOB::pan_left::1::ad103d4c-1e5e-4726-b809-00a12f6ec6b6::SOLO" + "custom": "MJ::JOB::pan_left::1::4da0778d-9c4c-40a8-a8dc-ce2f3650c658::SOLO" }, { "type": 2, "style": 2, "label": "➡️", - "custom": "MJ::JOB::pan_right::1::ad103d4c-1e5e-4726-b809-00a12f6ec6b6::SOLO" + "custom": "MJ::JOB::pan_right::1::4da0778d-9c4c-40a8-a8dc-ce2f3650c658::SOLO" }, { "type": 2, "style": 2, "label": "⬆️", - "custom": "MJ::JOB::pan_up::1::ad103d4c-1e5e-4726-b809-00a12f6ec6b6::SOLO" + "custom": "MJ::JOB::pan_up::1::4da0778d-9c4c-40a8-a8dc-ce2f3650c658::SOLO" }, { "type": 2, "style": 2, "label": "⬇️", - "custom": "MJ::JOB::pan_down::1::ad103d4c-1e5e-4726-b809-00a12f6ec6b6::SOLO" + "custom": "MJ::JOB::pan_down::1::4da0778d-9c4c-40a8-a8dc-ce2f3650c658::SOLO" }, { "type": 2, "style": 2, "label": "❤️", - "custom": "MJ::BOOKMARK::ad103d4c-1e5e-4726-b809-00a12f6ec6b6" + "custom": "MJ::BOOKMARK::4da0778d-9c4c-40a8-a8dc-ce2f3650c658" } ] } \ No newline at end of file diff --git a/src/discord.message.ts b/src/discord.message.ts index 188edfb..84c3920 100644 --- a/src/discord.message.ts +++ b/src/discord.message.ts @@ -47,6 +47,7 @@ export class MidjourneyMessage { callback: (any: any) => void; }) => { const httpStatus = await this.RetrieveMessages(request); + console.log(`got httpStatus, sending to callback...`); callback(httpStatus); await sleep(this.config.ApiInterval); }; @@ -63,6 +64,7 @@ export class MidjourneyMessage { const seed = prompt.match(/\[(.*?)\]/)?.[1]; this.log(`seed:`, seed); const data = await this.safeRetrieveMessages(this.config.Limit); + console.log(`got data, assessing data...`); for (let i = 0; i < data.length; i++) { const item = data[i]; if ( @@ -72,10 +74,12 @@ export class MidjourneyMessage { const itemTimestamp = new Date(item.timestamp).getTime(); if (itemTimestamp < timestamp) { this.log("old message"); + console.log(`old message`); continue; } if (item.attachments.length === 0) { this.log("no attachment"); + console.log(`no attachment`); break; } let uri = item.attachments[0].url; @@ -84,6 +88,7 @@ export class MidjourneyMessage { "https://cdn.discordapp.com/", this.config.ImageProxy ); + console.log(`found image url`); } //waiting if ( item.attachments[0].filename.startsWith("grid") || @@ -92,6 +97,7 @@ export class MidjourneyMessage { this.log(`content`, item.content); const progress = this.content2progress(item.content); loading?.(uri, progress); + console.log(`content found: `, item.content); break; } //finished @@ -106,6 +112,7 @@ export class MidjourneyMessage { progress: "done", options: formatOptions(item.components), }; + console.log(`ok to return msg: `, msg); return msg; } } @@ -137,11 +144,13 @@ export class MidjourneyMessage { for (let i = 0; i < this.config.MaxWait; i++) { const msg = await this.FilterMessages(timestamp, prompt, loading); if (msg !== null) { + console.log(`waitMessage returning with msg: `, msg); return msg; } this.log(i, "wait no message found"); await sleep(1000 * 2); } + console.log(`waitMessage returning...`); return null; } @@ -161,6 +170,7 @@ export class MidjourneyMessage { this.log(`HTTP error! status: ${response.status}`); } const data: any = await response.json(); + console.log(`Got response with data: `, data); return data; } } diff --git a/src/discord.ws.ts b/src/discord.ws.ts index 058bdd7..9a9fb95 100644 --- a/src/discord.ws.ts +++ b/src/discord.ws.ts @@ -76,6 +76,7 @@ export class WsMessage { async onceReady() { return new Promise((resolve) => { + console.log(`once1`); this.once("ready", (user) => { //print user nickname console.log(`🎊 ws ready!!! Hi: ${user.global_name}`); @@ -135,7 +136,7 @@ export class WsMessage { private async messageCreate(message: any) { const { embeds, id, nonce, components, attachments } = message; if (nonce) { - // this.log("waiting start image or info or error"); + this.log("waiting start image or info or error"); this.updateMjEventIdByNonce(id, nonce); if (embeds?.[0]) { const { color, description, title } = embeds[0]; @@ -175,6 +176,7 @@ export class WsMessage { } } } + else console.log("no nounce"); if (!nonce && attachments?.length > 0 && components?.length > 0) { this.done(message); @@ -274,10 +276,10 @@ export class WsMessage { } private async onMessageCreate(message: any) { const { channel_id, author, interaction } = message; - if (channel_id !== this.config.ChannelId) return; - if (author?.id !== this.config.BotId) return; - if (interaction && interaction.user.id !== this.UserId) return; - // this.log("[messageCreate]", JSON.stringify(message)); + if (channel_id !== this.config.ChannelId) { console.log("wrong channel id"); return; } + if (author?.id !== this.config.BotId) { console.log("wrong author"); return; } + if (interaction && interaction.user.id !== this.UserId) { console.log("wrong interaction"); return; } + this.log("[messageCreate]", JSON.stringify(message)); this.messageCreate(message); } @@ -307,7 +309,7 @@ export class WsMessage { } const message = msg.d; if (message.channel_id === this.config.ChannelId) { - this.log(data); + this.log("[discord.ws.ts parseMessage()", data); } this.log("event", msg.t); // console.log(data); @@ -508,6 +510,9 @@ export class WsMessage { } emit(event: string, message: any) { + console.log(`emit(): ${event} with message: `, message); + console.log(`emit(): event: `, this.event); + this.event .filter((e) => e.event === event) .forEach((e) => e.callback(message)); @@ -517,12 +522,15 @@ export class WsMessage { } //FIXME: emitMJ rename private emitMJ(id: string, data: any) { + console.log(`emitMj(): ${id} with data: `, data); const event = this.getEventById(id); if (!event) return; + else console.log(`found event: `, event); this.emit(event.nonce, data); } on(event: string, callback: (message: any) => void) { + console.log(`cb1`); this.event.push({ event, callback }); } onSystem( @@ -535,6 +543,7 @@ export class WsMessage { | "interactionSuccess", callback: (message: any) => void ) { + console.log(`cb2`); this.on(event, callback); } private emitSystem( @@ -547,16 +556,19 @@ export class WsMessage { | "interactionCreate", message: MJEmit ) { + console.log(`emitSystem: `, type); this.emit(type, message); } once(event: string, callback: (message: any) => void) { const once = (message: any) => { + console.log(`cb4`); this.remove(event, once); callback(message); }; this.event.push({ event, callback: once }); } remove(event: string, callback: (message: any) => void) { + console.log(`cb5 removing event ${event} with callback: `, callback); this.event = this.event.filter( (e) => e.event !== event && e.callback !== callback ); @@ -566,6 +578,7 @@ export class WsMessage { } //FIXME: USE ONCE onceInfo(callback: (message: any) => void) { + console.log(`cb6`); const once = (message: any) => { this.remove("info", once); callback(message); @@ -576,36 +589,50 @@ export class WsMessage { onceSettings(callback: (message: any) => void) { const once = (message: any) => { this.remove("settings", once); + console.log(`cb6`); callback(message); }; this.event.push({ event: "settings", callback: once }); } onceMJ(nonce: string, callback: (data: any) => void) { + console.log(`cb7`); const once = (message: any) => { + console.log(`cb8`); this.remove(nonce, once); //FIXME: removeWaitMjEvent this.removeWaitMjEvent(nonce); callback(message); }; //FIXME: addWaitMjEvent + this.waitMjEvents.set(nonce, { nonce }); + console.log(`cb9`); this.event.push({ event: nonce, callback: once }); } private removeSkipMessageId(messageId: string) { + + console.log("skipMessageId: ", this.skipMessageId); const index = this.skipMessageId.findIndex((id) => id !== messageId); if (index !== -1) { this.skipMessageId.splice(index, 1); } + console.log("new skipMessageId: ", this.skipMessageId); } private removeWaitMjEvent(nonce: string) { - this.waitMjEvents.delete(nonce); + //this.waitMjEvents.delete(nonce); + this.waitMjEvents.clear(); } onceImage(nonce: string, callback: (data: MJEmit) => void) { + console.log(`cb10`); const once = (data: MJEmit) => { + console.log(`cb11`); const { message, error } = data; if (error || (message && message.progress === "done")) { + console.log(`cb12. removing because message is done`); this.remove(nonce, once); } + console.log(`calling back data: `, data); + console.log(`call back: `, callback); callback(data); }; this.event.push({ event: nonce, callback: once }); @@ -627,15 +654,21 @@ export class WsMessage { if (messageId) this.skipMessageId.push(messageId); return new Promise((resolve, reject) => { const handleImageMessage = ({ message, error }: MJEmit) => { + console.log(`handling image message...`); if (error) { + console.log(`erroring...`); this.removeWaitMjEvent(nonce); reject(error); return; } if (message && message.progress === "done") { + console.log(`removing wait mjevent...`); this.removeWaitMjEvent(nonce); + console.log(`removing skip message id...`); messageId && this.removeSkipMessageId(messageId); + console.log(`resolving...`); resolve(message); + console.log(`returning...`); return; } message && loading && loading(message.uri, message.progress || ""); @@ -655,15 +688,18 @@ export class WsMessage { } this.removeWaitMjEvent(nonce); this.waitMjEvents.set(nonce, { nonce }); + console.log(`once2`); this.onceImage(nonce, handleImageMessage); return nonce; }, }); + console.log(`once3`); this.onceImage(nonce, handleImageMessage); }); } async waitDescribe(nonce: string) { return new Promise((resolve) => { + console.log(`once4`); this.onceMJ(nonce, (message) => { resolve(message); }); @@ -671,6 +707,7 @@ export class WsMessage { } async waitShorten(nonce: string) { return new Promise((resolve) => { + console.log(`once5`); this.onceMJ(nonce, (message) => { resolve(message); }); @@ -678,6 +715,7 @@ export class WsMessage { } async waitContent(event: string) { return new Promise((resolve) => { + console.log(`once6`); this.once(event, (message) => { resolve(message); }); @@ -685,6 +723,7 @@ export class WsMessage { } async waitInfo() { return new Promise((resolve, reject) => { + console.log(`once7`); this.onceInfo((message) => { resolve(formatInfo(message)); }); @@ -692,6 +731,7 @@ export class WsMessage { } async waitSettings() { return new Promise((resolve, reject) => { + console.log(`once8`); this.onceSettings((message) => { resolve({ id: message.id, diff --git a/src/midjourne.api.ts b/src/midjourne.api.ts index 35a8363..fee602f 100644 --- a/src/midjourne.api.ts +++ b/src/midjourne.api.ts @@ -26,6 +26,7 @@ export class MidjourneyApi extends Command { { request, callback: (any: any) => { + console.log(`cb13`); resolve(any); }, }, @@ -46,6 +47,7 @@ export class MidjourneyApi extends Command { request: any; callback: (any: any) => void; }) => { + console.log(`cb14`); const httpStatus = await this.interactions(request); callback(httpStatus); await sleep(this.config.ApiInterval); @@ -71,6 +73,7 @@ export class MidjourneyApi extends Command { config: this.config, }); } + console.log("interactions() response: ", response); return response.status; } catch (error) { console.error(error); @@ -224,7 +227,9 @@ export class MidjourneyApi extends Command { nonce, }; console.log("submitCustomId", JSON.stringify(payload)); - return this.safeIteractions(payload); + const safeIteractionsResponse = this.safeIteractions(payload); + console.log(`Returning safeIteractionsResponse: `, safeIteractionsResponse); + return safeIteractionsResponse; } async RemixApi({ @@ -331,14 +336,17 @@ export class MidjourneyApi extends Command { "::SOLO", "" ); - console.log("Reformatted custom for modal (removed SOLO, etc): ", customId); - return this.ModalSubmitApi({ + customId+="::1"; + console.log("[midjourne.api CustomPanImagineApi] Reformatted custom for modal (removed SOLO, etc): ", customId); + const modalSubmitApi = this.ModalSubmitApi({ nonce, msgId, customId, prompt, submitCustomId: CustomPanModalSubmitID, }); + console.log(`Returning ModalSubmitApi(etc)`, modalSubmitApi); + return modalSubmitApi; } async InfoApi(nonce?: string) { diff --git a/src/midjourney.ts b/src/midjourney.ts index bf8fb88..2009c02 100644 --- a/src/midjourney.ts +++ b/src/midjourney.ts @@ -279,7 +279,7 @@ export class Midjourney extends MidjourneyMessage { return ""; } const newNonce = nextNonce(); - console.log("Got ImageMessage. Type: "+custom2Type(customId)); + console.log("[midjourney Custom()] Got ImageMessage. Type: "+custom2Type(customId)); switch (custom2Type(customId)) { case "customPan": const panHttpStatus = await this.MJApi.CustomPanImagineApi({ @@ -293,6 +293,7 @@ export class Midjourney extends MidjourneyMessage { `CustomPanImagineApi failed with status ${panHttpStatus}` ); } + console.log(`returning newNounce`, newNonce); return newNonce; case "customZoom": const httpStatus = await this.MJApi.CustomZoomImagineApi({ @@ -334,7 +335,9 @@ export class Midjourney extends MidjourneyMessage { if (content === undefined || content === "") { throw new Error(`content is required`); } - return await this.WaitMessage(content, loading); + const waitMessageResponse = await this.WaitMessage(content, loading) + return waitMessageResponse; + } async ZoomOut({