first commit
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
import type {
|
||||
IDataObject,
|
||||
IExecuteFunctions,
|
||||
IHookFunctions,
|
||||
ILoadOptionsFunctions,
|
||||
JsonObject,
|
||||
IRequestOptions,
|
||||
IHttpRequestMethods,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeApiError } from 'n8n-workflow';
|
||||
|
||||
export async function humanticAiApiRequest(
|
||||
this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions,
|
||||
method: IHttpRequestMethods,
|
||||
resource: string,
|
||||
|
||||
body: any = {},
|
||||
qs: IDataObject = {},
|
||||
option: IDataObject = {},
|
||||
): Promise<any> {
|
||||
try {
|
||||
const credentials = await this.getCredentials('humanticAiApi');
|
||||
let options = {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
method,
|
||||
qs,
|
||||
body,
|
||||
uri: `https://api.humantic.ai/v1${resource}`,
|
||||
json: true,
|
||||
} satisfies IRequestOptions;
|
||||
|
||||
options = Object.assign({}, options, option);
|
||||
options.qs.apikey = credentials.apiKey;
|
||||
|
||||
if (Object.keys(options.body as IDataObject).length === 0) {
|
||||
delete options.body;
|
||||
}
|
||||
|
||||
const response = await this.helpers.request(options);
|
||||
|
||||
if (response.data && response.data.status === 'error') {
|
||||
throw new NodeApiError(this.getNode(), response.data as JsonObject);
|
||||
}
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw new NodeApiError(this.getNode(), error as JsonObject);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"node": "n8n-nodes-base.humanticAi",
|
||||
"nodeVersion": "1.0",
|
||||
"codexVersion": "1.0",
|
||||
"categories": ["Analytics"],
|
||||
"resources": {
|
||||
"credentialDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/credentials/humanticai/"
|
||||
}
|
||||
],
|
||||
"primaryDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.humanticai/"
|
||||
}
|
||||
],
|
||||
"generic": [
|
||||
{
|
||||
"label": "5 tasks you can automate with the new Notion API ",
|
||||
"icon": "⚡️",
|
||||
"url": "https://n8n.io/blog/5-tasks-you-can-automate-with-notion-api/"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
import type {
|
||||
IDataObject,
|
||||
IExecuteFunctions,
|
||||
INodeExecutionData,
|
||||
INodeType,
|
||||
INodeTypeDescription,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeConnectionTypes } from 'n8n-workflow';
|
||||
|
||||
import { humanticAiApiRequest } from './GenericFunctions';
|
||||
import { profileFields, profileOperations } from './ProfileDescription';
|
||||
|
||||
export class HumanticAi implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
displayName: 'Humantic AI',
|
||||
name: 'humanticAi',
|
||||
|
||||
icon: 'file:humanticai.svg',
|
||||
group: ['output'],
|
||||
version: 1,
|
||||
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
||||
description: 'Consume Humantic AI API',
|
||||
defaults: {
|
||||
name: 'Humantic AI',
|
||||
},
|
||||
usableAsTool: true,
|
||||
inputs: [NodeConnectionTypes.Main],
|
||||
outputs: [NodeConnectionTypes.Main],
|
||||
credentials: [
|
||||
{
|
||||
name: 'humanticAiApi',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Resource',
|
||||
name: 'resource',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
options: [
|
||||
{
|
||||
name: 'Profile',
|
||||
value: 'profile',
|
||||
},
|
||||
],
|
||||
default: 'profile',
|
||||
},
|
||||
// PROFILE
|
||||
...profileOperations,
|
||||
...profileFields,
|
||||
],
|
||||
};
|
||||
|
||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||
const items = this.getInputData();
|
||||
const returnData: IDataObject[] = [];
|
||||
const length = items.length;
|
||||
const qs: IDataObject = {};
|
||||
let responseData;
|
||||
const resource = this.getNodeParameter('resource', 0);
|
||||
const operation = this.getNodeParameter('operation', 0);
|
||||
for (let i = 0; i < length; i++) {
|
||||
if (resource === 'profile') {
|
||||
if (operation === 'create') {
|
||||
const userId = this.getNodeParameter('userId', i) as string;
|
||||
const sendResume = this.getNodeParameter('sendResume', i) as boolean;
|
||||
qs.userid = userId;
|
||||
|
||||
if (sendResume) {
|
||||
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i);
|
||||
const binaryData = this.helpers.assertBinaryData(i, binaryPropertyName);
|
||||
const binaryDataBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
|
||||
|
||||
responseData = await humanticAiApiRequest.call(
|
||||
this,
|
||||
'POST',
|
||||
'/user-profile/create',
|
||||
{},
|
||||
qs,
|
||||
{
|
||||
formData: {
|
||||
resume: {
|
||||
value: binaryDataBuffer,
|
||||
options: {
|
||||
filename: binaryData.fileName,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
} else {
|
||||
responseData = await humanticAiApiRequest.call(
|
||||
this,
|
||||
'GET',
|
||||
'/user-profile/create',
|
||||
{},
|
||||
qs,
|
||||
);
|
||||
}
|
||||
|
||||
if (responseData.data !== undefined) {
|
||||
responseData = responseData.data;
|
||||
} else {
|
||||
delete responseData.usage_stats;
|
||||
}
|
||||
}
|
||||
if (operation === 'get') {
|
||||
const userId = this.getNodeParameter('userId', i) as string;
|
||||
const options = this.getNodeParameter('options', i);
|
||||
|
||||
qs.userid = userId;
|
||||
|
||||
if (options.persona) {
|
||||
qs.persona = (options.persona as string[]).join(',');
|
||||
}
|
||||
|
||||
responseData = await humanticAiApiRequest.call(this, 'GET', '/user-profile', {}, qs);
|
||||
responseData = responseData.results;
|
||||
}
|
||||
if (operation === 'update') {
|
||||
const userId = this.getNodeParameter('userId', i) as string;
|
||||
const sendResume = this.getNodeParameter('sendResume', i) as string;
|
||||
qs.userid = userId;
|
||||
|
||||
if (sendResume) {
|
||||
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i);
|
||||
const binaryData = this.helpers.assertBinaryData(i, binaryPropertyName);
|
||||
const binaryDataBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
|
||||
|
||||
responseData = await humanticAiApiRequest.call(
|
||||
this,
|
||||
'POST',
|
||||
'/user-profile/create',
|
||||
{},
|
||||
qs,
|
||||
{
|
||||
formData: {
|
||||
resume: {
|
||||
value: binaryDataBuffer,
|
||||
options: {
|
||||
filename: binaryData.fileName,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
responseData = responseData.data;
|
||||
} else {
|
||||
const text = this.getNodeParameter('text', i) as string;
|
||||
const body: IDataObject = {
|
||||
text,
|
||||
};
|
||||
|
||||
qs.userid = userId;
|
||||
|
||||
responseData = await humanticAiApiRequest.call(
|
||||
this,
|
||||
'POST',
|
||||
'/user-profile/create',
|
||||
body,
|
||||
qs,
|
||||
);
|
||||
responseData = responseData.data;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Array.isArray(responseData)) {
|
||||
returnData.push.apply(returnData, responseData as IDataObject[]);
|
||||
} else {
|
||||
returnData.push(responseData as IDataObject);
|
||||
}
|
||||
}
|
||||
return [this.helpers.returnJsonArray(returnData)];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const profileOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['profile'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Create a profile',
|
||||
action: 'Create a profile',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Retrieve a profile',
|
||||
action: 'Get a profile',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
description: 'Update a profile',
|
||||
action: 'Update a profile',
|
||||
},
|
||||
],
|
||||
default: 'create',
|
||||
},
|
||||
];
|
||||
|
||||
export const profileFields: INodeProperties[] = [
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* profile:create */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'User ID',
|
||||
name: 'userId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['profile'],
|
||||
},
|
||||
},
|
||||
description:
|
||||
'The LinkedIn profile URL or email ID for creating a Humantic profile. If you are sending the resume, this should be a unique string.',
|
||||
},
|
||||
{
|
||||
displayName: 'Send Resume',
|
||||
name: 'sendResume',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['profile'],
|
||||
},
|
||||
},
|
||||
description: 'Whether to send a resume for a resume based analysis',
|
||||
},
|
||||
{
|
||||
displayName: 'Input Binary Field',
|
||||
name: 'binaryPropertyName',
|
||||
type: 'string',
|
||||
default: 'data',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['profile'],
|
||||
sendResume: [true],
|
||||
},
|
||||
},
|
||||
hint: 'The name of the input binary field containing the resume in PDF or DOCX format',
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* profile:get */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'User ID',
|
||||
name: 'userId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['get'],
|
||||
resource: ['profile'],
|
||||
},
|
||||
},
|
||||
description:
|
||||
'This value is the same as the User ID that was provided when the analysis was created. This could be a LinkedIn URL, email ID, or a unique string in case of resume based analysis.',
|
||||
},
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
type: 'collection',
|
||||
placeholder: 'Add option',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['get'],
|
||||
resource: ['profile'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Persona',
|
||||
name: 'persona',
|
||||
type: 'multiOptions',
|
||||
options: [
|
||||
{
|
||||
name: 'Sales',
|
||||
value: 'sales',
|
||||
},
|
||||
{
|
||||
name: 'Hiring',
|
||||
value: 'hiring',
|
||||
},
|
||||
],
|
||||
default: [],
|
||||
description:
|
||||
'Fetch the Humantic profile of the user for a particular persona type. Multiple persona values can be supported using comma as a delimiter.',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* profile:update */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'User ID',
|
||||
name: 'userId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['update'],
|
||||
resource: ['profile'],
|
||||
},
|
||||
},
|
||||
description:
|
||||
'This value is the same as the User ID that was provided when the analysis was created. Currently only supported for profiles created using LinkedIn URL.',
|
||||
},
|
||||
{
|
||||
displayName: 'Send Resume',
|
||||
name: 'sendResume',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['update'],
|
||||
resource: ['profile'],
|
||||
},
|
||||
},
|
||||
description: 'Whether to send a resume for a resume of the user',
|
||||
},
|
||||
{
|
||||
displayName: 'Text',
|
||||
name: 'text',
|
||||
type: 'string',
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['update'],
|
||||
resource: ['profile'],
|
||||
sendResume: [false],
|
||||
},
|
||||
},
|
||||
description: 'Additional text written by the user',
|
||||
},
|
||||
{
|
||||
displayName: 'Input Binary Field',
|
||||
name: 'binaryPropertyName',
|
||||
type: 'string',
|
||||
default: 'data',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['update'],
|
||||
resource: ['profile'],
|
||||
sendResume: [true],
|
||||
},
|
||||
},
|
||||
hint: 'The name of the input binary field containing the resume in PDF or DOCX format',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,6 @@
|
||||
<svg width="40" height="41" viewBox="0 0 40 41" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M36.4722 30.9096C38.2943 27.927 39.3443 24.4213 39.3443 20.6703C39.3443 9.80671 30.5367 1 19.6721 1C8.80751 1 0 9.80671 0 20.6703C0 31.534 8.80751 40.3407 19.6721 40.3407C23.9509 40.3407 27.9106 38.9748 31.1389 36.6552L40 40.0128L36.4722 30.9096Z" fill="#FEBD00"/>
|
||||
<path d="M33.214 28.9076C34.6756 26.5081 35.5179 23.6879 35.5179 20.6704C35.5179 11.9309 28.4526 4.84619 19.737 4.84619C11.0214 4.84619 3.95605 11.9309 3.95605 20.6704C3.95605 29.4098 11.0214 36.4945 19.737 36.4945C23.1694 36.4945 26.3459 35.3957 28.9356 33.5297L36.044 36.2308L33.214 28.9076Z" fill="#FFCD3A"/>
|
||||
<path d="M29.1409 26.3907C30.1521 24.7244 30.7348 22.7659 30.7348 20.6704C30.7348 14.6013 25.8471 9.6814 19.8178 9.6814C13.7886 9.6814 8.90088 14.6013 8.90088 20.6704C8.90088 26.7395 13.7886 31.6594 19.8178 31.6594C22.1923 31.6594 24.3897 30.8963 26.1813 29.6005L31.0987 31.4763L29.1409 26.3907Z" fill="#FFD96B"/>
|
||||
<path d="M25.5211 24.1025C26.1318 23.1027 26.4837 21.9276 26.4837 20.6703C26.4837 17.0289 23.5317 14.0769 19.8903 14.0769C16.2488 14.0769 13.2969 17.0289 13.2969 20.6703C13.2969 24.3117 16.2488 27.2637 19.8903 27.2637C21.3244 27.2637 22.6515 26.8059 23.7335 26.0284L26.7035 27.1538L25.5211 24.1025Z" fill="#FFF4D3"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
Reference in New Issue
Block a user