2023-01-27 03:22:44 -08:00
import type {
2023-03-09 09:13:15 -08:00
IHookFunctions ,
IWebhookFunctions ,
2021-12-10 09:36:24 -08:00
IDataObject ,
ILoadOptionsFunctions ,
INodePropertyOptions ,
INodeType ,
INodeTypeDescription ,
IWebhookResponseData ,
} from 'n8n-workflow' ;
2024-08-29 06:55:53 -07:00
import { NodeConnectionType } from 'n8n-workflow' ;
2021-12-10 09:36:24 -08:00
2022-08-17 08:50:24 -07:00
import { snakeCase } from 'change-case' ;
import { workableApiRequest } from './GenericFunctions' ;
2021-12-10 09:36:24 -08:00
export class WorkableTrigger implements INodeType {
description : INodeTypeDescription = {
displayName : 'Workable Trigger' ,
name : 'workableTrigger' ,
2022-06-20 07:54:01 -07:00
// eslint-disable-next-line n8n-nodes-base/node-class-description-icon-not-svg
2021-12-10 09:36:24 -08:00
icon : 'file:workable.png' ,
group : [ 'trigger' ] ,
version : 1 ,
subtitle : '={{$parameter["triggerOn"]}}' ,
description : 'Starts the workflow when Workable events occur' ,
defaults : {
name : 'Workable Trigger' ,
} ,
inputs : [ ] ,
2024-08-29 06:55:53 -07:00
outputs : [ NodeConnectionType . Main ] ,
2021-12-10 09:36:24 -08:00
credentials : [
{
name : 'workableApi' ,
required : true ,
} ,
] ,
webhooks : [
{
name : 'default' ,
httpMethod : 'POST' ,
responseMode : 'onReceived' ,
path : 'webhook' ,
} ,
] ,
properties : [
{
displayName : 'Trigger On' ,
name : 'triggerOn' ,
type : 'options' ,
options : [
{
name : 'Candidate Created' ,
value : 'candidateCreated' ,
} ,
{
name : 'Candidate Moved' ,
value : 'candidateMoved' ,
} ,
] ,
default : '' ,
required : true ,
} ,
{
displayName : 'Filters' ,
name : 'filters' ,
type : 'collection' ,
placeholder : 'Add Filter' ,
default : { } ,
options : [
{
2022-06-03 10:23:49 -07:00
displayName : 'Job Name or ID' ,
2021-12-10 09:36:24 -08:00
name : 'job' ,
type : 'options' ,
typeOptions : {
loadOptionsMethod : 'getJobs' ,
} ,
default : '' ,
2022-08-17 08:50:24 -07:00
description :
'Get notifications only for one job. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.' ,
2021-12-10 09:36:24 -08:00
} ,
{
2022-06-03 10:23:49 -07:00
displayName : 'Stage Name or ID' ,
2021-12-10 09:36:24 -08:00
name : 'stage' ,
type : 'options' ,
typeOptions : {
loadOptionsMethod : 'getStages' ,
} ,
default : '' ,
2022-08-17 08:50:24 -07:00
description :
'Get notifications for specific stages. e.g. \'hired\'. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.' ,
2021-12-10 09:36:24 -08:00
} ,
] ,
} ,
] ,
} ;
methods = {
loadOptions : {
async getJobs ( this : ILoadOptionsFunctions ) : Promise < INodePropertyOptions [ ] > {
const returnData : INodePropertyOptions [ ] = [ ] ;
const { jobs } = await workableApiRequest . call ( this , 'GET' , '/jobs' ) ;
for ( const job of jobs ) {
returnData . push ( {
name : job.full_title ,
value : job.shortcode ,
} ) ;
}
return returnData ;
} ,
async getStages ( this : ILoadOptionsFunctions ) : Promise < INodePropertyOptions [ ] > {
const returnData : INodePropertyOptions [ ] = [ ] ;
const { stages } = await workableApiRequest . call ( this , 'GET' , '/stages' ) ;
for ( const stage of stages ) {
returnData . push ( {
name : stage.name ,
value : stage.slug ,
} ) ;
}
return returnData ;
} ,
} ,
} ;
webhookMethods = {
default : {
async checkExists ( this : IHookFunctions ) : Promise < boolean > {
const webhookUrl = this . getNodeWebhookUrl ( 'default' ) ;
const webhookData = this . getWorkflowStaticData ( 'node' ) ;
// Check all the webhooks which exist already if it is identical to the
// one that is supposed to get created.
2022-12-29 03:20:43 -08:00
const { subscriptions } = await workableApiRequest . call ( this , 'GET' , '/subscriptions' ) ;
2021-12-10 09:36:24 -08:00
for ( const subscription of subscriptions ) {
if ( subscription . target === webhookUrl ) {
webhookData . webhookId = subscription . id as string ;
return true ;
}
}
return false ;
} ,
async create ( this : IHookFunctions ) : Promise < boolean > {
2024-08-27 06:23:58 -07:00
const credentials = await this . getCredentials < {
2022-08-17 08:50:24 -07:00
accessToken : string ;
subdomain : string ;
2024-08-27 06:23:58 -07:00
} > ( 'workableApi' ) ;
2021-12-10 09:36:24 -08:00
const webhookData = this . getWorkflowStaticData ( 'node' ) ;
const webhookUrl = this . getNodeWebhookUrl ( 'default' ) ;
const triggerOn = this . getNodeParameter ( 'triggerOn' ) as string ;
const { stage , job } = this . getNodeParameter ( 'filters' ) as IDataObject ;
const endpoint = '/subscriptions' ;
const body : IDataObject = {
event : snakeCase ( triggerOn ) . toLowerCase ( ) ,
args : {
account_id : credentials.subdomain ,
2022-08-17 08:50:24 -07:00
. . . ( job && { job_shortcode : job } ) ,
. . . ( stage && { stage_slug : stage } ) ,
2021-12-10 09:36:24 -08:00
} ,
target : webhookUrl ,
} ;
const responseData = await workableApiRequest . call ( this , 'POST' , endpoint , body ) ;
if ( responseData . id === undefined ) {
// Required data is missing so was not successful
return false ;
}
webhookData . webhookId = responseData . id as string ;
return true ;
} ,
async delete ( this : IHookFunctions ) : Promise < boolean > {
const webhookData = this . getWorkflowStaticData ( 'node' ) ;
if ( webhookData . webhookId !== undefined ) {
const endpoint = ` /subscriptions/ ${ webhookData . webhookId } ` ;
try {
await workableApiRequest . call ( this , 'DELETE' , endpoint ) ;
} catch ( error ) {
return false ;
}
// Remove from the static workflow data so that it is clear
2023-03-03 09:49:19 -08:00
// that no webhooks are registered anymore
2021-12-10 09:36:24 -08:00
delete webhookData . webhookId ;
}
return true ;
} ,
} ,
} ;
async webhook ( this : IWebhookFunctions ) : Promise < IWebhookResponseData > {
const bodyData = this . getBodyData ( ) ;
return {
2022-08-17 08:50:24 -07:00
workflowData : [ this . helpers . returnJsonArray ( bodyData ) ] ,
2021-12-10 09:36:24 -08:00
} ;
}
}