mirror of
https://github.com/n8n-io/n8n.git
synced 2024-11-17 10:04:08 -08:00
d6239d5bfb
* Update Compression node * Update Crypto node * Update DateTime node * Update EditImage node * Update EmailSend node * Update ExecuteWorkflow node * Update FTP node * Update Function node * Update FunctionItem node * Update ExecuteCommand node * Update OpenWeatherMap node * Update ReadBinaryFile node * Update ReadPdf node * Update RssFeedRead node & add URL validation * Update SpreadsheetFile node * Update Switch node * Update WriteBinaryFile node * Update Xml node * Update ActiveCampaign node * Update Airtable node * Update ApiTemplateIo node * Update Asana node * Update AwsLambda node * Update AwsSns node * Update AwsComprehend node * Update AwsRekognition node * Update AwsS3 node * Fix Error item * Update AwsSes node * Update AwsSqs node * Update Amqp node * Update Bitly node * Update Box node * Update Brandfetch node * Update CircleCi node * Update Clearbit node * Update ClickUp node * Update Cockpit node * Update CoinGecko node * Update Contentful node * Update ConvertKit node * Update Cortex node * Update CustomerIo node * Update DeepL node * Update Demio node * Update Disqus node * Update Drift node * Update Dropbox node * Update GetResponse node * Refactor & Update Ghost node * Update Github node * Update Gitlab node * Update GoogleAnalytics node * Update GoogleBooks node * Update GoogleCalendar node * Update GoogleDrive node * Update Gmail node * Update GoogleSheets node * Update GoogleSlides node * Update GoogleTasks node * Update Gotify node * Update GraphQL node * Update HackerNews node * Update Harvest node * Update HtmlExtract node * Update Hubspot node * Update Hunter node * Update Intercom node * Update Kafka node * Refactor & update Line node * Update LinkedIn node * Update Mailchimp node * Update Mandrill node * Update Matrix node * Update Mautic node * Update Medium node * Update MessageBird node * Update Mindee node * Update Mocean node * Update MondayCom node * Update MicrosoftExcel node * Update MicrosoftOneDrive node * Update MicrosoftOutlook node * Update Affinity node * Update Chargebee node * Update Discourse node * Update Freshdesk node * Update YouTube node * Update InvoiceNinja node * Update MailerLite node * Update Mailgun node * Update Mailjet node * Update Mattermost node * Update Nasa node * Update NextCloud node * Update OpenThesaurus node * Update Orbit node * Update PagerDuty node * Update PayPal node * Update Peekalink node * Update Phantombuster node * Update PostHog node * Update ProfitWell node * Refactor & Update Pushbullet node * Update QuickBooks node * Update Raindrop node * Update Reddit node * Update Rocketchat node * Update S3 node * Update Salesforce node * Update SendGrid node * Update SentryIo node * Update Shopify node * Update Signl4 node * Update Slack node * Update Spontit node * Update Spotify node * Update Storyblok node * Refactor & Update Strapi node * Refactor & Update Strava node * Update Taiga node * Refactor & update Tapfiliate node * Update Telegram node * Update TheHive node * Update Todoist node * Update TravisCi node * Update Trello node * Update Twilio node * Update Twist node * Update Twitter node * Update Uplead node * Update UProc node * Update Vero node * Update Webflow node * Update Wekan node * Update Wordpress node * Update Xero node * Update Yourls node * Update Zendesk node * Update ZohoCrm node * Refactor & Update Zoom node * Update Zulip node * Update Clockify node * Update MongoDb node * Update MySql node * Update MicrosoftTeams node * Update Stackby node * Refactor Discourse node * Support corner-case in Github node update * Support corner-case in Gitlab node update * Refactor & Update GoogleContacts node * Refactor Mindee node * Update Coda node * Lint fixes * Update Beeminder node * Update Google Firebase RealtimeDatabase node * Update HelpScout node * Update Mailcheck node * Update Paddle node * Update Pipedrive node * Update Pushover node * Update Segment node * Refactor & Update Vonage node * Added new conditions to warnings on execute batch cmd * Added keep only properties flag * Fixed code for keep only props * Added dependencies for image editing Co-authored-by: dali <servfrdali@yahoo.fr>
522 lines
13 KiB
TypeScript
522 lines
13 KiB
TypeScript
import {
|
|
IExecuteFunctions,
|
|
} from 'n8n-core';
|
|
|
|
import {
|
|
IBinaryKeyData,
|
|
IDataObject,
|
|
INodeExecutionData,
|
|
INodeType,
|
|
INodeTypeDescription,
|
|
NodeApiError,
|
|
NodeOperationError,
|
|
} from 'n8n-workflow';
|
|
|
|
import {
|
|
awsApiRequestREST,
|
|
keysTPascalCase,
|
|
} from './GenericFunctions';
|
|
|
|
export class AwsRekognition implements INodeType {
|
|
description: INodeTypeDescription = {
|
|
displayName: 'AWS Rekognition',
|
|
name: 'awsRekognition',
|
|
icon: 'file:rekognition.svg',
|
|
group: ['output'],
|
|
version: 1,
|
|
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
|
description: 'Sends data to AWS Rekognition',
|
|
defaults: {
|
|
name: 'AWS Rekognition',
|
|
color: '#305b94',
|
|
},
|
|
inputs: ['main'],
|
|
outputs: ['main'],
|
|
credentials: [
|
|
{
|
|
name: 'aws',
|
|
required: true,
|
|
},
|
|
],
|
|
properties: [
|
|
{
|
|
displayName: 'Resource',
|
|
name: 'resource',
|
|
type: 'options',
|
|
options: [
|
|
{
|
|
name: 'Image',
|
|
value: 'image',
|
|
},
|
|
],
|
|
default: 'image',
|
|
description: 'The operation to perform.',
|
|
},
|
|
{
|
|
displayName: 'Operation',
|
|
name: 'operation',
|
|
type: 'options',
|
|
options: [
|
|
{
|
|
name: 'Analyze',
|
|
value: 'analyze',
|
|
},
|
|
],
|
|
default: 'analyze',
|
|
description: 'The operation to perform.',
|
|
},
|
|
{
|
|
displayName: 'Type',
|
|
name: 'type',
|
|
type: 'options',
|
|
displayOptions: {
|
|
show: {
|
|
operation: [
|
|
'analyze',
|
|
],
|
|
resource: [
|
|
'image',
|
|
],
|
|
},
|
|
},
|
|
options: [
|
|
{
|
|
name: 'Detect Faces',
|
|
value: 'detectFaces',
|
|
},
|
|
{
|
|
name: 'Detect Labels',
|
|
value: 'detectLabels',
|
|
},
|
|
{
|
|
name: 'Detect Moderation Labels',
|
|
value: 'detectModerationLabels',
|
|
},
|
|
{
|
|
name: 'Detect Text',
|
|
value: 'detectText',
|
|
},
|
|
{
|
|
name: 'Recognize Celebrity',
|
|
value: 'recognizeCelebrity',
|
|
},
|
|
],
|
|
default: 'detectFaces',
|
|
description: 'The operation to perform.',
|
|
},
|
|
{
|
|
displayName: 'Binary Data',
|
|
name: 'binaryData',
|
|
type: 'boolean',
|
|
default: false,
|
|
required: true,
|
|
displayOptions: {
|
|
show: {
|
|
operation: [
|
|
'analyze',
|
|
],
|
|
resource: [
|
|
'image',
|
|
],
|
|
},
|
|
},
|
|
description: 'If the image to analize should be taken from binary field.',
|
|
},
|
|
{
|
|
displayName: 'Binary Property',
|
|
displayOptions: {
|
|
show: {
|
|
operation: [
|
|
'analyze',
|
|
],
|
|
resource: [
|
|
'image',
|
|
],
|
|
binaryData: [
|
|
true,
|
|
],
|
|
},
|
|
},
|
|
name: 'binaryPropertyName',
|
|
type: 'string',
|
|
default: 'data',
|
|
description: 'Object property name which holds binary data.',
|
|
required: true,
|
|
},
|
|
{
|
|
displayName: 'Bucket',
|
|
name: 'bucket',
|
|
displayOptions: {
|
|
show: {
|
|
operation: [
|
|
'analyze',
|
|
],
|
|
resource: [
|
|
'image',
|
|
],
|
|
binaryData: [
|
|
false,
|
|
],
|
|
},
|
|
},
|
|
type: 'string',
|
|
default: '',
|
|
required: true,
|
|
description: 'Name of the S3 bucket',
|
|
},
|
|
{
|
|
displayName: 'Name',
|
|
name: 'name',
|
|
displayOptions: {
|
|
show: {
|
|
operation: [
|
|
'analyze',
|
|
],
|
|
resource: [
|
|
'image',
|
|
],
|
|
binaryData: [
|
|
false,
|
|
],
|
|
},
|
|
},
|
|
type: 'string',
|
|
default: '',
|
|
required: true,
|
|
description: 'S3 object key name',
|
|
},
|
|
{
|
|
displayName: 'Additional Fields',
|
|
name: 'additionalFields',
|
|
type: 'collection',
|
|
placeholder: 'Add Field',
|
|
displayOptions: {
|
|
show: {
|
|
operation: [
|
|
'analyze',
|
|
],
|
|
resource: [
|
|
'image',
|
|
],
|
|
},
|
|
},
|
|
default: {},
|
|
options: [
|
|
{
|
|
displayName: 'Regions of Interest',
|
|
name: 'regionsOfInterestUi',
|
|
type: 'fixedCollection',
|
|
default: '',
|
|
placeholder: 'Add Region of Interest',
|
|
displayOptions: {
|
|
show: {
|
|
'/type': [
|
|
'detectText',
|
|
],
|
|
},
|
|
},
|
|
typeOptions: {
|
|
multipleValues: true,
|
|
},
|
|
options: [
|
|
{
|
|
name: 'regionsOfInterestValues',
|
|
displayName: 'Region of Interest',
|
|
values: [
|
|
{
|
|
displayName: 'Height',
|
|
name: 'height',
|
|
type: 'number',
|
|
description: 'Height of the bounding box as a ratio of the overall image height.',
|
|
default: 0,
|
|
},
|
|
{
|
|
displayName: 'Left',
|
|
name: 'left',
|
|
type: 'number',
|
|
description: 'Left coordinate of the bounding box as a ratio of overall image width.',
|
|
default: 0,
|
|
},
|
|
{
|
|
displayName: 'Top',
|
|
name: 'top',
|
|
type: 'number',
|
|
description: 'Top coordinate of the bounding box as a ratio of overall image height.',
|
|
default: 0,
|
|
},
|
|
{
|
|
displayName: 'Width',
|
|
name: 'Width',
|
|
type: 'number',
|
|
description: 'Width of the bounding box as a ratio of the overall image width.',
|
|
default: 0,
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
displayName: 'Version',
|
|
name: 'version',
|
|
displayOptions: {
|
|
show: {
|
|
'/binaryData': [
|
|
false,
|
|
],
|
|
},
|
|
},
|
|
type: 'string',
|
|
default: '',
|
|
description: 'If the bucket is versioning enabled, you can specify the object version',
|
|
},
|
|
{
|
|
displayName: 'Word Filter',
|
|
name: 'wordFilterUi',
|
|
type: 'collection',
|
|
default: '',
|
|
placeholder: 'Add Word Filter',
|
|
displayOptions: {
|
|
show: {
|
|
'/type': [
|
|
'detectText',
|
|
],
|
|
},
|
|
},
|
|
typeOptions: {
|
|
multipleValues: false,
|
|
},
|
|
options: [
|
|
{
|
|
displayName: 'Min Bounding Box Height',
|
|
name: 'MinBoundingBoxHeight',
|
|
type: 'number',
|
|
description: 'Sets the minimum height of the word bounding box. Words with bounding box heights lesser than this value will be excluded from the result. Value is relative to the video frame height.',
|
|
default: 0,
|
|
},
|
|
{
|
|
displayName: 'Min Bounding Box Width',
|
|
name: 'MinBoundingBoxWidth',
|
|
type: 'number',
|
|
description: 'Sets the minimum width of the word bounding box. Words with bounding boxes widths lesser than this value will be excluded from the result. Value is relative to the video frame width.',
|
|
default: 0,
|
|
},
|
|
{
|
|
displayName: 'Min Confidence',
|
|
name: 'MinConfidence',
|
|
type: 'number',
|
|
description: 'Sets the confidence of word detection. Words with detection confidence below this will be excluded from the result. Values should be between 50 and 100 as Text in Video will not return any result below 50.',
|
|
default: 0,
|
|
},
|
|
],
|
|
},
|
|
{
|
|
displayName: 'Max Labels',
|
|
name: 'maxLabels',
|
|
type: 'number',
|
|
displayOptions: {
|
|
show: {
|
|
'/type': [
|
|
'detectModerationLabels',
|
|
'detectLabels',
|
|
],
|
|
},
|
|
},
|
|
default: 0,
|
|
typeOptions: {
|
|
minValue: 0,
|
|
},
|
|
description: `Maximum number of labels you want the service to return in the response. The service returns the specified number of highest confidence labels.`,
|
|
},
|
|
{
|
|
displayName: 'Min Confidence',
|
|
name: 'minConfidence',
|
|
type: 'number',
|
|
displayOptions: {
|
|
show: {
|
|
'/type': [
|
|
'detectModerationLabels',
|
|
'detectLabels',
|
|
],
|
|
},
|
|
},
|
|
default: 0,
|
|
typeOptions: {
|
|
minValue: 0,
|
|
maxValue: 100,
|
|
},
|
|
description: `Specifies the minimum confidence level for the labels to return. Amazon Rekognition doesn't return any labels with a confidence level lower than this specified value.`,
|
|
},
|
|
{
|
|
displayName: 'Attributes',
|
|
name: 'attributes',
|
|
type: 'multiOptions',
|
|
displayOptions: {
|
|
show: {
|
|
'/type': [
|
|
'detectFaces',
|
|
],
|
|
},
|
|
},
|
|
options: [
|
|
{
|
|
name: 'All',
|
|
value: 'all',
|
|
},
|
|
{
|
|
name: 'Default',
|
|
value: 'default',
|
|
},
|
|
],
|
|
default: [],
|
|
description: `An array of facial attributes you want to be returned`,
|
|
},
|
|
],
|
|
},
|
|
],
|
|
};
|
|
|
|
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
|
const items = this.getInputData();
|
|
const returnData: IDataObject[] = [];
|
|
const qs: IDataObject = {};
|
|
let responseData;
|
|
const resource = this.getNodeParameter('resource', 0) as string;
|
|
const operation = this.getNodeParameter('operation', 0) as string;
|
|
for (let i = 0; i < items.length; i++) {
|
|
try {
|
|
if (resource === 'image') {
|
|
//https://docs.aws.amazon.com/rekognition/latest/dg/API_DetectModerationLabels.html#API_DetectModerationLabels_RequestSyntax
|
|
if (operation === 'analyze') {
|
|
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
|
|
|
|
let action = undefined;
|
|
|
|
const body: IDataObject = {};
|
|
|
|
const type = this.getNodeParameter('type', 0) as string;
|
|
|
|
if (type === 'detectModerationLabels') {
|
|
action = 'RekognitionService.DetectModerationLabels';
|
|
|
|
// property = 'ModerationLabels';
|
|
|
|
if (additionalFields.minConfidence) {
|
|
body['MinConfidence'] = additionalFields.minConfidence as number;
|
|
}
|
|
}
|
|
|
|
if (type === 'detectFaces') {
|
|
action = 'RekognitionService.DetectFaces';
|
|
|
|
// TODO: Add a later point make it possible to activate via option.
|
|
// If activated add an index to each of the found faces/tages/...
|
|
// to not loose the reference to the image it got found on if
|
|
// multilpe ones got supplied.
|
|
// property = 'FaceDetails';
|
|
|
|
if (additionalFields.attributes) {
|
|
body['Attributes'] = additionalFields.attributes as string;
|
|
}
|
|
}
|
|
|
|
if (type === 'detectLabels') {
|
|
action = 'RekognitionService.DetectLabels';
|
|
|
|
if (additionalFields.minConfidence) {
|
|
body['MinConfidence'] = additionalFields.minConfidence as number;
|
|
}
|
|
|
|
if (additionalFields.maxLabels) {
|
|
body['MaxLabels'] = additionalFields.maxLabels as number;
|
|
}
|
|
}
|
|
|
|
if (type === 'recognizeCelebrity') {
|
|
action = 'RekognitionService.RecognizeCelebrities';
|
|
}
|
|
|
|
if (type === 'detectText') {
|
|
action = 'RekognitionService.DetectText';
|
|
|
|
body.Filters = {};
|
|
|
|
const box = (additionalFields.regionsOfInterestUi as IDataObject || {}).regionsOfInterestValues as IDataObject[] || [];
|
|
|
|
if (box.length !== 0) {
|
|
//@ts-ignore
|
|
body.Filters.RegionsOfInterest = box.map((box: IDataObject) => {
|
|
return { BoundingBox: keysTPascalCase(box) };
|
|
});
|
|
}
|
|
|
|
const wordFilter = additionalFields.wordFilterUi as IDataObject || {};
|
|
if (Object.keys(wordFilter).length !== 0) {
|
|
//@ts-ignore
|
|
body.Filters.WordFilter = keysTPascalCase(wordFilter);
|
|
}
|
|
|
|
const binaryData = this.getNodeParameter('binaryData', 0) as boolean;
|
|
|
|
if (binaryData) {
|
|
|
|
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', 0) as string;
|
|
|
|
if (items[i].binary === undefined) {
|
|
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
|
|
}
|
|
|
|
if ((items[i].binary as IBinaryKeyData)[binaryPropertyName] === undefined) {
|
|
throw new NodeOperationError(this.getNode(), `No binary data property "${binaryPropertyName}" does not exists on item!`);
|
|
}
|
|
|
|
const binaryPropertyData = (items[i].binary as IBinaryKeyData)[binaryPropertyName];
|
|
|
|
Object.assign(body, {
|
|
Image: {
|
|
Bytes: binaryPropertyData.data,
|
|
},
|
|
});
|
|
|
|
} else {
|
|
|
|
const bucket = this.getNodeParameter('bucket', i) as string;
|
|
|
|
const name = this.getNodeParameter('name', i) as string;
|
|
|
|
Object.assign(body, {
|
|
Image: {
|
|
S3Object: {
|
|
Bucket: bucket,
|
|
Name: name,
|
|
},
|
|
},
|
|
});
|
|
|
|
if (additionalFields.version) {
|
|
//@ts-ignore
|
|
body.Image.S3Object.Version = additionalFields.version as string;
|
|
}
|
|
}
|
|
|
|
responseData = await awsApiRequestREST.call(this, 'rekognition', 'POST', '', JSON.stringify(body), {}, { 'X-Amz-Target': action, 'Content-Type': 'application/x-amz-json-1.1' });
|
|
|
|
}
|
|
}
|
|
}
|
|
if (Array.isArray(responseData)) {
|
|
returnData.push.apply(returnData, responseData as IDataObject[]);
|
|
} else {
|
|
returnData.push(responseData);
|
|
}
|
|
} catch (error) {
|
|
if (this.continueOnFail()) {
|
|
returnData.push({ error: error.message });
|
|
continue;
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
return [this.helpers.returnJsonArray(returnData)];
|
|
}
|
|
}
|