Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions nodes/LinkedApi/LinkedApi.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@ import {
FetchCompany,
FetchPerson,
FetchPost,
FetchJob,
ReactToPost,
RemoveConnection,
RetrieveConnections,
RetrievePendingRequests,
RetrievePerformance,
SearchCompanies,
SearchPeople,
SearchJobs,
SendConnectionRequest,
SendMessage,
SyncConversation,
Expand Down Expand Up @@ -61,13 +63,15 @@ const operations: Record<string, LinkedApiOperation> = {
fetchPerson: new FetchPerson(),
fetchCompany: new FetchCompany(),
fetchPost: new FetchPost(),
fetchJob: new FetchJob(),
reactToPost: new ReactToPost(),
removeConnection: new RemoveConnection(),
retrieveConnections: new RetrieveConnections(),
retrievePendingRequests: new RetrievePendingRequests(),
retrievePerformance: new RetrievePerformance(),
searchCompanies: new SearchCompanies(),
searchPeople: new SearchPeople(),
searchJobs: new SearchJobs(),
sendConnectionRequest: new SendConnectionRequest(),
sendMessage: new SendMessage(),
syncConversation: new SyncConversation(),
Expand Down Expand Up @@ -146,13 +150,15 @@ export class LinkedApi implements INodeType {
...operations.fetchPerson.operationFields,
...operations.fetchCompany.operationFields,
...operations.fetchPost.operationFields,
...operations.fetchJob.operationFields,
...operations.reactToPost.operationFields,
...operations.removeConnection.operationFields,
...operations.retrieveConnections.operationFields,
...operations.retrievePendingRequests.operationFields,
...operations.retrievePerformance.operationFields,
...operations.searchCompanies.operationFields,
...operations.searchPeople.operationFields,
...operations.searchJobs.operationFields,
...operations.sendConnectionRequest.operationFields,
...operations.sendMessage.operationFields,
...operations.syncConversation.operationFields,
Expand Down
16 changes: 16 additions & 0 deletions nodes/LinkedApi/operations/webhook/FetchJob.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { IExecuteFunctions, INodeProperties } from 'n8n-workflow';
import { createParameterWithDisplayOptions, jobUrlParameter } from '../../shared/SharedParameters';
import { StandardLinkedApiOperation } from '../../shared/LinkedApiOperation';
import { AVAILABLE_ACTION } from '../../shared/AvailableActions';

export class FetchJob extends StandardLinkedApiOperation {
operationName = AVAILABLE_ACTION.fetchJob;

fields: INodeProperties[] = [createParameterWithDisplayOptions(jobUrlParameter, this.show)];

public body(context: IExecuteFunctions): Record<string, any> {
return {
jobUrl: this.stringParameter(context, 'jobUrl'),
};
}
}
234 changes: 234 additions & 0 deletions nodes/LinkedApi/operations/webhook/SearchJobs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
/* eslint-disable n8n-nodes-base/node-param-options-type-unsorted-items */
/* eslint-disable n8n-nodes-base/node-param-multi-options-type-unsorted-items */
import type { IExecuteFunctions, INodeProperties } from 'n8n-workflow';
import {
createParameterWithDisplayOptions,
searchTermParameter,
limitParameter,
customSearchUrlParameter,
} from '../../shared/SharedParameters';
import { StandardLinkedApiOperation } from '../../shared/LinkedApiOperation';
import { AVAILABLE_ACTION } from '../../shared/AvailableActions';

export class SearchJobs extends StandardLinkedApiOperation {
operationName = AVAILABLE_ACTION.searchJobs;

fields: INodeProperties[] = [
createParameterWithDisplayOptions(
{ ...searchTermParameter, placeholder: 'product manager' },
this.show,
),
createParameterWithDisplayOptions(limitParameter, this.show),
{
displayName: 'Advanced Filter',
name: 'advancedFilter',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: this.show,
},
options: [
{
...customSearchUrlParameter,
placeholder: 'https://www.linkedin.com/jobs/search/?keywords=product%20manager',
},
{
displayName: 'Location',
name: 'location',
type: 'string',
default: '',
placeholder: 'San Francisco, California, United States',
description: 'Free-form location to filter by',
},
{
displayName: 'Date Posted',
name: 'datePosted',
type: 'options',
default: 'anyTime',
description: 'Filter by when the job was posted',
options: [
{ name: 'Any Time', value: 'anyTime' },
{ name: 'Past 24 Hours', value: 'past24Hours' },
{ name: 'Past Week', value: 'pastWeek' },
{ name: 'Past Month', value: 'pastMonth' },
],
},
{
displayName: 'Experience Levels',
name: 'experienceLevels',
type: 'multiOptions',
default: [],
description: 'Filter by experience level',
options: [
{ name: 'Internship', value: 'internship' },
{ name: 'Entry Level', value: 'entryLevel' },
{ name: 'Associate', value: 'associate' },
{ name: 'Mid-Senior Level', value: 'midSeniorLevel' },
{ name: 'Director', value: 'director' },
{ name: 'Executive', value: 'executive' },
],
},
{
displayName: 'Employment Types',
name: 'employmentTypes',
type: 'multiOptions',
default: [],
description: 'Filter by employment type',
options: [
{ name: 'Full Time', value: 'fullTime' },
{ name: 'Part Time', value: 'partTime' },
{ name: 'Contract', value: 'contract' },
{ name: 'Temporary', value: 'temporary' },
{ name: 'Volunteer', value: 'volunteer' },
{ name: 'Internship', value: 'internship' },
{ name: 'Other', value: 'other' },
],
},
{
displayName: 'Workplace Types',
name: 'workplaceTypes',
type: 'multiOptions',
default: [],
description: 'Filter by workplace type',
options: [
{ name: 'On-Site', value: 'onSite' },
{ name: 'Remote', value: 'remote' },
{ name: 'Hybrid', value: 'hybrid' },
],
},
{
displayName: 'Companies',
name: 'companies',
type: 'string',
default: '',
placeholder: 'Google; Microsoft',
description: 'Company names separated by semicolons',
},
{
displayName: 'Industries',
name: 'industries',
type: 'string',
default: '',
placeholder: 'Software Development; Technology',
description: 'Industries separated by semicolons',
},
{
displayName: 'Job Functions',
name: 'jobFunctions',
type: 'string',
default: '',
placeholder: 'Engineering; Product Management',
description: 'Job functions separated by semicolons',
},
{
displayName: 'Easy Apply',
name: 'easyApply',
type: 'boolean',
default: false,
description: 'Whether to only return jobs with Easy Apply',
},
{
displayName: 'Has Verifications',
name: 'hasVerifications',
type: 'boolean',
default: false,
description: 'Whether to only return jobs with verification signals',
},
{
displayName: 'Under 10 Applicants',
name: 'under10Applicants',
type: 'boolean',
default: false,
description: 'Whether to only return jobs with fewer than 10 applicants',
},
{
displayName: 'In Your Network',
name: 'inYourNetwork',
type: 'boolean',
default: false,
description: 'Whether to only return jobs from your network',
},
{
displayName: 'Fair Chance Employer',
name: 'fairChanceEmployer',
type: 'boolean',
default: false,
description: 'Whether to only return fair chance employer jobs',
},
],
},
];

public body(context: IExecuteFunctions): Record<string, any> {
const filter: Record<string, any> = {};
const advancedFilter = context.getNodeParameter('advancedFilter', this.itemIndex, {}) as {
customSearchUrl?: string;
location?: string;
datePosted?: string;
experienceLevels?: string[];
employmentTypes?: string[];
workplaceTypes?: string[];
companies?: string;
industries?: string;
jobFunctions?: string;
easyApply?: boolean;
hasVerifications?: boolean;
under10Applicants?: boolean;
inYourNetwork?: boolean;
fairChanceEmployer?: boolean;
};

const {
location,
datePosted,
experienceLevels,
employmentTypes,
workplaceTypes,
companies,
industries,
jobFunctions,
easyApply,
hasVerifications,
under10Applicants,
inYourNetwork,
fairChanceEmployer,
} = advancedFilter;

if (location) filter.location = location;
if (datePosted) filter.datePosted = datePosted;
if (experienceLevels && experienceLevels.length > 0) filter.experienceLevels = experienceLevels;
if (employmentTypes && employmentTypes.length > 0) filter.employmentTypes = employmentTypes;
if (workplaceTypes && workplaceTypes.length > 0) filter.workplaceTypes = workplaceTypes;
if (companies) {
filter.companies = companies
.split(';')
.map((s) => s.trim())
.filter((s) => s);
}
if (industries) {
filter.industries = industries
.split(';')
.map((s) => s.trim())
.filter((s) => s);
}
if (jobFunctions) {
filter.jobFunctions = jobFunctions
.split(';')
.map((s) => s.trim())
.filter((s) => s);
}
if (easyApply) filter.easyApply = true;
if (hasVerifications) filter.hasVerifications = true;
if (under10Applicants) filter.under10Applicants = true;
if (inYourNetwork) filter.inYourNetwork = true;
if (fairChanceEmployer) filter.fairChanceEmployer = true;

return {
term: this.stringParameter(context, 'searchTerm') || undefined,
limit: this.numberParameter(context, 'limit'),
customSearchUrl: advancedFilter.customSearchUrl || undefined,
filter,
};
}
}
2 changes: 2 additions & 0 deletions nodes/LinkedApi/operations/webhook/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export * from './CustomWorkflow';
export * from './FetchCompany';
export * from './FetchPerson';
export * from './FetchPost';
export * from './FetchJob';
export * from './NvFetchCompany';
export * from './NvFetchPerson';
export * from './NvSearchCompanies';
Expand All @@ -19,6 +20,7 @@ export * from './RetrievePerformance';
export * from './RetrieveSSI';
export * from './SearchCompanies';
export * from './SearchPeople';
export * from './SearchJobs';
export * from './SendConnectionRequest';
export * from './SendMessage';
export * from './SyncConversation';
Expand Down
14 changes: 14 additions & 0 deletions nodes/LinkedApi/shared/AvailableActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const AVAILABLE_ACTION = {
fetchCompany: 'fetchCompany',
fetchPerson: 'fetchPerson',
fetchPost: 'fetchPost',
fetchJob: 'fetchJob',
reactToPost: 'reactToPost',
removeConnection: 'removeConnection',
retrieveConnections: 'retrieveConnections',
Expand All @@ -17,6 +18,7 @@ export const AVAILABLE_ACTION = {
retrieveSSI: 'retrieveSSI',
searchCompanies: 'searchCompanies',
searchPeople: 'searchPeople',
searchJobs: 'searchJobs',
sendConnectionRequest: 'sendConnectionRequest',
sendMessage: 'sendMessage',
syncConversation: 'syncConversation',
Expand Down Expand Up @@ -93,6 +95,12 @@ export const availableStandardOperations: INodeProperties = {
description: 'Retrieve detailed information about a LinkedIn post',
action: 'Fetch post',
},
{
name: 'Fetch Job',
value: AVAILABLE_ACTION.fetchJob,
description: 'Fetch detailed information about a LinkedIn job',
action: 'Fetch job',
},
{
name: 'React to Post',
value: AVAILABLE_ACTION.reactToPost,
Expand Down Expand Up @@ -142,6 +150,12 @@ export const availableStandardOperations: INodeProperties = {
description: 'Search for people on LinkedIn',
action: 'Search people',
},
{
name: 'Search Jobs',
value: AVAILABLE_ACTION.searchJobs,
description: 'Search for jobs on LinkedIn',
action: 'Search jobs',
},
{
name: 'Send Connection Request',
value: AVAILABLE_ACTION.sendConnectionRequest,
Expand Down
10 changes: 10 additions & 0 deletions nodes/LinkedApi/shared/SharedParameters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,16 @@ export const postUrlParameter: INodeProperties = {
description: 'LinkedIn URL of the post',
};

export const jobUrlParameter: INodeProperties = {
displayName: 'Job URL',
name: 'jobUrl',
type: 'string',
required: true,
default: '',
placeholder: 'https://www.linkedin.com/jobs/view/4416248954/',
description: 'LinkedIn URL of the job',
};

export const commentTextParameter: INodeProperties = {
displayName: 'Comment Text',
name: 'commentText',
Expand Down
Loading