n8n-nodes-piapi
Version:
Community n8n nodes for PiAPI - integrate generative AI capabilities (image, video, audio, 3D) into your workflows
426 lines • 17.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PiAPIMidjourney = void 0;
const n8n_workflow_1 = require("n8n-workflow");
const GenericFunctions_1 = require("../shared/GenericFunctions");
class PiAPIMidjourney {
constructor() {
this.description = {
displayName: 'PiAPI Midjourney',
name: 'piAPIMidjourney',
icon: 'file:../piapi.svg',
group: ['transform'],
version: 1,
description: 'Generate and manipulate images using PiAPI Midjourney',
defaults: {
name: 'Midjourney',
},
inputs: ["main"],
outputs: ["main"],
credentials: [
{
name: 'piAPIApi',
required: true,
},
],
properties: [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
options: [
{
name: 'Imagine',
value: 'imagine',
description: 'Generate 4 images from a text prompt',
},
{
name: 'Upscale',
value: 'upscale',
description: 'Upscale a selected image from a previous Imagine result',
},
{
name: 'Describe',
value: 'describe',
description: 'Generate prompt suggestions based on an image',
},
],
default: 'imagine',
description: 'Operation to perform',
},
{
displayName: 'Prompt',
name: 'prompt',
type: 'string',
typeOptions: {
rows: 4,
},
default: '',
required: true,
displayOptions: {
show: {
operation: ['imagine'],
},
},
description: 'Text prompt to generate images',
},
{
displayName: 'Aspect Ratio',
name: 'aspectRatio',
type: 'options',
options: [
{
name: 'Square (1:1)',
value: '1:1',
description: 'Square images',
},
{
name: 'Portrait (9:16)',
value: '9:16',
description: 'Vertical images',
},
{
name: 'Landscape (16:9)',
value: '16:9',
description: 'Horizontal widescreen images',
},
{
name: 'Ultra Landscape (21:9)',
value: '21:9',
description: 'Ultra-wide horizontal images',
},
],
default: '1:1',
displayOptions: {
show: {
operation: ['imagine'],
},
},
description: 'Aspect ratio of the generated images',
},
{
displayName: 'Process Mode',
name: 'processMode',
type: 'options',
options: [
{
name: 'Relax',
value: 'relax',
description: 'Lower priority but cheaper',
},
{
name: 'Fast',
value: 'fast',
description: 'Standard processing speed',
},
{
name: 'Turbo',
value: 'turbo',
description: 'Higher priority but more expensive',
},
],
default: 'fast',
displayOptions: {
show: {
operation: ['imagine', 'describe'],
},
},
description: 'Processing speed priority',
},
{
displayName: 'Skip Prompt Check',
name: 'skipPromptCheck',
type: 'boolean',
default: false,
displayOptions: {
show: {
operation: ['imagine'],
},
},
description: 'Whether to skip content filtering on prompts',
},
{
displayName: 'Origin Task ID',
name: 'originTaskId',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['upscale'],
},
},
description: 'Task ID of the original Imagine operation',
},
{
displayName: 'Image Index',
name: 'imageIndex',
type: 'options',
options: [
{
name: 'Image 1',
value: '1',
description: 'First image in the grid',
},
{
name: 'Image 2',
value: '2',
description: 'Second image in the grid',
},
{
name: 'Image 3',
value: '3',
description: 'Third image in the grid',
},
{
name: 'Image 4',
value: '4',
description: 'Fourth image in the grid',
},
],
default: '1',
required: true,
displayOptions: {
show: {
operation: ['upscale'],
},
},
description: 'Which image to upscale from the original grid',
},
{
displayName: 'Image Input Method',
name: 'imageInputMethod',
type: 'options',
options: [
{
name: 'URL',
value: 'url',
},
{
name: 'Binary Data',
value: 'binaryData',
},
],
default: 'url',
displayOptions: {
show: {
operation: ['describe'],
},
},
description: 'Method to input the image data',
},
{
displayName: 'Binary Property',
name: 'binaryPropertyName',
type: 'string',
default: 'data',
required: true,
displayOptions: {
show: {
operation: ['describe'],
imageInputMethod: ['binaryData'],
},
},
description: 'Name of the binary property containing the image data',
},
{
displayName: 'Image URL',
name: 'imageUrl',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['describe'],
imageInputMethod: ['url'],
},
},
description: 'URL of the image to describe',
},
{
displayName: 'Advanced Options',
name: 'advancedOptions',
type: 'collection',
placeholder: 'Add Option',
default: {},
options: [
{
displayName: 'Service Mode',
name: 'serviceMode',
type: 'options',
options: [
{
name: 'Public (PAYG)',
value: 'public',
description: 'Process under Pay-As-You-Go mode',
},
{
name: 'Private (HYA)',
value: 'private',
description: 'Process under Host-Your-Account mode',
},
],
default: '',
description: 'Choose how this task will be processed',
},
{
displayName: 'Bot ID',
name: 'botId',
type: 'number',
default: 0,
displayOptions: {
show: {
'/operation': ['describe'],
},
},
description: 'Specify which Midjourney account will process this task (HYA Pro Plan only)',
},
],
},
{
displayName: 'Wait For Completion',
name: 'waitForCompletion',
type: 'boolean',
default: false,
description: 'Whether to wait for the operation to complete before continuing',
},
{
displayName: 'Max Retries',
name: 'maxRetries',
type: 'number',
default: 60,
description: 'Maximum number of retries to check task status',
displayOptions: {
show: {
waitForCompletion: [true],
},
},
},
{
displayName: 'Retry Interval',
name: 'retryInterval',
type: 'number',
default: 5000,
description: 'Interval between retries in milliseconds',
displayOptions: {
show: {
waitForCompletion: [true],
},
},
},
],
};
}
async execute() {
var _a, _b;
const items = this.getInputData();
const returnData = [];
for (let i = 0; i < items.length; i++) {
try {
const operation = this.getNodeParameter('operation', i);
const waitForCompletion = this.getNodeParameter('waitForCompletion', i, false);
const advancedOptions = this.getNodeParameter('advancedOptions', i, {});
let response;
const config = {};
if (advancedOptions.serviceMode) {
config.service_mode = advancedOptions.serviceMode;
}
if (operation === 'imagine') {
const prompt = this.getNodeParameter('prompt', i);
const aspectRatio = this.getNodeParameter('aspectRatio', i, '1:1');
const processMode = this.getNodeParameter('processMode', i, 'fast');
const skipPromptCheck = this.getNodeParameter('skipPromptCheck', i, false);
const requestBody = {
model: 'midjourney',
task_type: 'imagine',
input: {
prompt,
aspect_ratio: aspectRatio,
process_mode: processMode,
skip_prompt_check: skipPromptCheck,
},
config,
};
response = await GenericFunctions_1.piApiRequest.call(this, 'POST', '/api/v1/task', requestBody);
}
else if (operation === 'upscale') {
const originTaskId = this.getNodeParameter('originTaskId', i);
const imageIndex = this.getNodeParameter('imageIndex', i);
const requestBody = {
model: 'midjourney',
task_type: 'upscale',
input: {
origin_task_id: originTaskId,
index: imageIndex,
},
config,
};
response = await GenericFunctions_1.piApiRequest.call(this, 'POST', '/api/v1/task', requestBody);
}
else if (operation === 'describe') {
const imageInputMethod = this.getNodeParameter('imageInputMethod', i);
const processMode = this.getNodeParameter('processMode', i, 'fast');
let imageUrl;
if (imageInputMethod === 'url') {
imageUrl = this.getNodeParameter('imageUrl', i);
}
else {
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i);
const binaryData = this.helpers.assertBinaryData(i, binaryPropertyName);
if (binaryData.mimeType && !binaryData.mimeType.includes('image')) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'The provided binary data is not an image', { itemIndex: i });
}
const base64String = Buffer.from(await this.helpers.getBinaryDataBuffer(i, binaryPropertyName)).toString('base64');
imageUrl = `data:${binaryData.mimeType};base64,${base64String}`;
}
const requestBody = {
model: 'midjourney',
task_type: 'describe',
input: {
image_url: imageUrl,
process_mode: processMode,
},
config,
};
if (advancedOptions.botId) {
requestBody.input.bot_id = advancedOptions.botId;
}
response = await GenericFunctions_1.piApiRequest.call(this, 'POST', '/api/v1/task', requestBody);
}
const taskId = (_a = response.data) === null || _a === void 0 ? void 0 : _a.task_id;
if (!taskId) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Failed to get a valid task ID from the API');
}
let executionData;
if (waitForCompletion) {
const maxRetries = this.getNodeParameter('maxRetries', i, 60);
const retryInterval = this.getNodeParameter('retryInterval', i, 5000);
executionData = await GenericFunctions_1.waitForTaskCompletion.call(this, taskId, maxRetries, retryInterval);
}
else {
executionData = {
task_id: taskId,
status: ((_b = response.data) === null || _b === void 0 ? void 0 : _b.status) || 'pending',
};
}
returnData.push({
json: executionData,
});
}
catch (error) {
if (this.continueOnFail()) {
returnData.push({
json: {
error: error.message,
},
});
continue;
}
throw error;
}
}
return [returnData];
}
}
exports.PiAPIMidjourney = PiAPIMidjourney;
//# sourceMappingURL=PiAPIMidjourney.node.js.map