2023-01-27 03:22:44 -08:00
import type { IExecuteFunctions } from 'n8n-core' ;
2020-06-23 08:18:01 -07:00
2023-01-27 03:22:44 -08:00
import type {
2020-08-18 17:55:36 -07:00
IBinaryKeyData ,
2020-06-24 21:06:48 -07:00
IDataObject ,
INodeExecutionData ,
INodeType ,
INodeTypeDescription ,
} from 'n8n-workflow' ;
2023-01-27 03:22:44 -08:00
import { NodeOperationError } from 'n8n-workflow' ;
2020-06-24 21:06:48 -07:00
2022-08-17 08:50:24 -07:00
import { SIGNL4ApiRequest } from './GenericFunctions' ;
2020-06-24 21:06:48 -07:00
export class Signl4 implements INodeType {
2020-06-23 08:18:01 -07:00
description : INodeTypeDescription = {
displayName : 'SIGNL4' ,
2020-06-24 21:06:48 -07:00
name : 'signl4' ,
2022-06-20 07:54:01 -07:00
// eslint-disable-next-line n8n-nodes-base/node-class-description-icon-not-svg
2020-06-23 08:18:01 -07:00
icon : 'file:signl4.png' ,
group : [ 'transform' ] ,
version : 1 ,
subtitle : '={{$parameter["operation"] + ": " + $parameter["resource"]}}' ,
2021-07-03 05:40:16 -07:00
description : 'Consume SIGNL4 API' ,
2020-06-23 08:18:01 -07:00
defaults : {
name : 'SIGNL4' ,
} ,
inputs : [ 'main' ] ,
outputs : [ 'main' ] ,
credentials : [
{
2020-06-24 21:06:48 -07:00
name : 'signl4Api' ,
2020-06-23 08:18:01 -07:00
required : true ,
2020-06-24 21:06:48 -07:00
} ,
2020-06-23 08:18:01 -07:00
] ,
properties : [
{
displayName : 'Resource' ,
name : 'resource' ,
type : 'options' ,
2022-05-20 14:47:24 -07:00
noDataExpression : true ,
2020-06-23 08:18:01 -07:00
options : [
{
name : 'Alert' ,
value : 'alert' ,
} ,
] ,
default : 'alert' ,
} ,
{
displayName : 'Operation' ,
name : 'operation' ,
type : 'options' ,
2022-05-20 14:47:24 -07:00
noDataExpression : true ,
2020-06-23 08:18:01 -07:00
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
resource : [ 'alert' ] ,
2020-06-23 08:18:01 -07:00
} ,
} ,
options : [
{
2020-06-24 21:06:48 -07:00
name : 'Send' ,
2020-06-23 08:18:01 -07:00
value : 'send' ,
2020-08-18 17:55:36 -07:00
description : 'Send an alert' ,
2022-07-10 13:50:51 -07:00
action : 'Send an alert' ,
2020-06-23 08:18:01 -07:00
} ,
2020-08-11 01:07:52 -07:00
{
name : 'Resolve' ,
value : 'resolve' ,
2020-08-18 17:55:36 -07:00
description : 'Resolve an alert' ,
2022-07-10 13:50:51 -07:00
action : 'Resolve an alert' ,
2020-08-11 01:07:52 -07:00
} ,
2020-06-23 08:18:01 -07:00
] ,
default : 'send' ,
} ,
{
2020-06-24 21:06:48 -07:00
displayName : 'Message' ,
name : 'message' ,
2020-06-23 08:18:01 -07:00
type : 'string' ,
default : '' ,
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'send' ] ,
resource : [ 'alert' ] ,
2020-06-23 08:18:01 -07:00
} ,
} ,
2022-05-06 14:01:25 -07:00
description : 'A more detailed description for the alert' ,
2020-06-23 08:18:01 -07:00
} ,
{
2020-06-24 21:06:48 -07:00
displayName : 'Additional Fields' ,
name : 'additionalFields' ,
type : 'collection' ,
placeholder : 'Add Field' ,
2020-06-23 08:18:01 -07:00
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'send' ] ,
resource : [ 'alert' ] ,
2020-06-23 08:18:01 -07:00
} ,
} ,
2020-06-24 21:06:48 -07:00
default : { } ,
options : [
{
displayName : 'Alerting Scenario' ,
name : 'alertingScenario' ,
type : 'options' ,
options : [
{
name : 'Single ACK' ,
value : 'single_ack' ,
2022-05-06 14:01:25 -07:00
description : 'In case only one person needs to confirm this Signl' ,
2020-06-24 21:06:48 -07:00
} ,
{
name : 'Multi ACK' ,
value : 'multi_ack' ,
2022-08-17 08:50:24 -07:00
description :
'In case this alert must be confirmed by the number of people who are on duty at the time this Singl is raised' ,
2020-06-24 21:06:48 -07:00
} ,
2020-06-23 08:18:01 -07:00
] ,
2020-06-24 21:06:48 -07:00
default : 'single_ack' ,
} ,
{
displayName : 'Attachments' ,
name : 'attachmentsUi' ,
placeholder : 'Add Attachments' ,
type : 'fixedCollection' ,
typeOptions : {
multipleValues : false ,
} ,
options : [
{
name : 'attachmentsBinary' ,
displayName : 'Attachments Binary' ,
values : [
{
displayName : 'Property Name' ,
name : 'property' ,
type : 'string' ,
placeholder : 'data' ,
default : '' ,
2022-08-17 08:50:24 -07:00
description :
'Name of the binary properties which contain data which should be added as attachment' ,
2020-06-24 21:06:48 -07:00
} ,
] ,
} ,
2020-06-23 08:18:01 -07:00
] ,
2020-06-24 21:06:48 -07:00
default : { } ,
2020-06-23 08:18:01 -07:00
} ,
{
2020-06-24 21:06:48 -07:00
displayName : 'External ID' ,
name : 'externalId' ,
type : 'string' ,
default : '' ,
2022-08-17 08:50:24 -07:00
description :
'If the event originates from a record in a 3rd party system, use this parameter to pass the unique ID of that record. That ID will be communicated in outbound webhook notifications from SIGNL4, which is great for correlation/synchronization of that record with the alert. If you resolve / close an alert you must use the same External ID as in the original alert.' ,
2020-06-23 08:18:01 -07:00
} ,
{
2020-06-24 21:06:48 -07:00
displayName : 'Filtering' ,
name : 'filtering' ,
type : 'boolean' ,
2022-04-22 09:29:51 -07:00
default : false ,
2022-08-17 08:50:24 -07:00
description :
'Whether to apply event filtering for this event, or not. If set to true, the event will only trigger a notification to the team, if it contains at least one keyword from one of your services and system categories (i.e. it is whitelisted)' ,
2020-06-23 08:18:01 -07:00
} ,
2020-06-24 21:06:48 -07:00
{
displayName : 'Location' ,
name : 'locationFieldsUi' ,
type : 'fixedCollection' ,
placeholder : 'Add Location' ,
default : { } ,
2022-08-17 08:50:24 -07:00
description :
"Transmit location information ('latitude, longitude') with your event and display a map in the mobile app" ,
2020-06-24 21:06:48 -07:00
options : [
{
name : 'locationFieldsValues' ,
displayName : 'Location' ,
values : [
{
displayName : 'Latitude' ,
name : 'latitude' ,
type : 'string' ,
required : true ,
2022-05-06 14:01:25 -07:00
description : 'The location latitude' ,
2020-06-24 21:06:48 -07:00
default : '' ,
} ,
{
displayName : 'Longitude' ,
name : 'longitude' ,
type : 'string' ,
required : true ,
2022-05-06 14:01:25 -07:00
description : 'The location longitude' ,
2020-06-24 21:06:48 -07:00
default : '' ,
} ,
] ,
2020-10-22 06:46:03 -07:00
} ,
2020-06-23 08:18:01 -07:00
] ,
} ,
2020-06-24 21:06:48 -07:00
{
displayName : 'Service' ,
name : 'service' ,
type : 'string' ,
default : '' ,
2022-05-06 14:01:25 -07:00
description : 'Assigns the alert to the service/system category with the specified name' ,
2020-06-23 08:18:01 -07:00
} ,
2020-06-24 21:06:48 -07:00
{
displayName : 'Title' ,
name : 'title' ,
type : 'string' ,
default : '' ,
2022-05-06 14:01:25 -07:00
description : 'The title or subject of this alert' ,
2020-06-23 08:18:01 -07:00
} ,
2020-06-24 21:06:48 -07:00
] ,
} ,
2020-08-11 01:07:52 -07:00
{
displayName : 'External ID' ,
name : 'externalId' ,
type : 'string' ,
default : '' ,
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'resolve' ] ,
resource : [ 'alert' ] ,
2020-08-11 01:07:52 -07:00
} ,
} ,
2022-08-17 08:50:24 -07:00
description :
'If the event originates from a record in a 3rd party system, use this parameter to pass the unique ID of that record. That ID will be communicated in outbound webhook notifications from SIGNL4, which is great for correlation/synchronization of that record with the alert. If you resolve / close an alert you must use the same External ID as in the original alert.' ,
2020-08-11 01:07:52 -07:00
} ,
2020-06-23 08:18:01 -07:00
] ,
} ;
async execute ( this : IExecuteFunctions ) : Promise < INodeExecutionData [ ] [ ] > {
2020-06-24 21:06:48 -07:00
const items = this . getInputData ( ) ;
2020-06-23 08:18:01 -07:00
const returnData : IDataObject [ ] = [ ] ;
2022-04-22 09:29:51 -07:00
const length = items . length ;
2020-06-24 21:06:48 -07:00
let responseData ;
2022-12-02 03:53:59 -08:00
const resource = this . getNodeParameter ( 'resource' , 0 ) ;
const operation = this . getNodeParameter ( 'operation' , 0 ) ;
2020-06-24 21:06:48 -07:00
for ( let i = 0 ; i < length ; i ++ ) {
2021-07-19 23:58:54 -07:00
try {
if ( resource === 'alert' ) {
//https://connect.signl4.com/webhook/docs/index.html
// Send alert
if ( operation === 'send' ) {
const message = this . getNodeParameter ( 'message' , i ) as string ;
2022-11-18 07:29:44 -08:00
const additionalFields = this . getNodeParameter ( 'additionalFields' , i ) ;
2021-01-31 11:07:32 -08:00
2021-07-19 23:58:54 -07:00
const data : IDataObject = {
message ,
} ;
2020-06-23 08:18:01 -07:00
2021-07-19 23:58:54 -07:00
if ( additionalFields . title ) {
data . title = additionalFields . title as string ;
}
2021-01-19 04:25:21 -08:00
2021-07-19 23:58:54 -07:00
if ( additionalFields . service ) {
data . service = additionalFields . service as string ;
}
if ( additionalFields . locationFieldsUi ) {
2022-08-17 08:50:24 -07:00
const locationUi = ( additionalFields . locationFieldsUi as IDataObject )
. locationFieldsValues as IDataObject ;
2021-07-19 23:58:54 -07:00
if ( locationUi ) {
data [ 'X-S4-Location' ] = ` ${ locationUi . latitude } , ${ locationUi . longitude } ` ;
}
2020-06-24 21:06:48 -07:00
}
2021-01-19 04:25:21 -08:00
2021-07-19 23:58:54 -07:00
if ( additionalFields . alertingScenario ) {
data [ 'X-S4-AlertingScenario' ] = additionalFields . alertingScenario as string ;
}
2021-01-19 04:25:21 -08:00
2021-07-19 23:58:54 -07:00
if ( additionalFields . filtering ) {
data [ 'X-S4-Filtering' ] = ( additionalFields . filtering as boolean ) . toString ( ) ;
}
2020-06-24 21:06:48 -07:00
2021-07-19 23:58:54 -07:00
if ( additionalFields . externalId ) {
data [ 'X-S4-ExternalID' ] = additionalFields . externalId as string ;
}
2021-01-19 04:25:21 -08:00
2021-07-19 23:58:54 -07:00
data [ 'X-S4-Status' ] = 'new' ;
2020-06-23 08:18:01 -07:00
2021-07-19 23:58:54 -07:00
data [ 'X-S4-SourceSystem' ] = 'n8n' ;
2021-01-19 04:25:21 -08:00
2021-07-19 23:58:54 -07:00
// Attachments
const attachments = additionalFields . attachmentsUi as IDataObject ;
if ( attachments ) {
if ( attachments . attachmentsBinary && items [ i ] . binary ) {
2022-08-17 08:50:24 -07:00
const propertyName = ( attachments . attachmentsBinary as IDataObject )
. property as string ;
2020-06-24 21:06:48 -07:00
2021-07-19 23:58:54 -07:00
const binaryProperty = ( items [ i ] . binary as IBinaryKeyData ) [ propertyName ] ;
2020-06-24 21:06:48 -07:00
2021-07-19 23:58:54 -07:00
if ( binaryProperty ) {
const supportedFileExtension = [ 'png' , 'jpg' , 'jpeg' , 'bmp' , 'gif' , 'mp3' , 'wav' ] ;
2020-06-24 21:06:48 -07:00
2021-07-19 23:58:54 -07:00
if ( ! supportedFileExtension . includes ( binaryProperty . fileExtension as string ) ) {
2022-08-17 08:50:24 -07:00
throw new NodeOperationError (
this . getNode ( ) ,
` Invalid extension, just ${ supportedFileExtension . join ( ',' ) } are supported} ` ,
{ itemIndex : i } ,
) ;
2021-07-19 23:58:54 -07:00
}
2020-06-24 21:06:48 -07:00
2022-01-03 13:42:42 -08:00
const binaryDataBuffer = await this . helpers . getBinaryDataBuffer ( i , propertyName ) ;
2021-07-19 23:58:54 -07:00
data . attachment = {
2022-01-03 13:42:42 -08:00
value : binaryDataBuffer ,
2021-07-19 23:58:54 -07:00
options : {
filename : binaryProperty.fileName ,
contentType : binaryProperty.mimeType ,
} ,
} ;
} else {
2022-08-17 08:50:24 -07:00
throw new NodeOperationError (
this . getNode ( ) ,
` Binary property ${ propertyName } does not exist on input ` ,
{ itemIndex : i } ,
) ;
2021-07-19 23:58:54 -07:00
}
2020-06-24 21:06:48 -07:00
}
}
2021-01-31 11:07:32 -08:00
2021-07-19 23:58:54 -07:00
responseData = await SIGNL4ApiRequest . call (
this ,
'POST' ,
'' ,
{ } ,
{
formData : data ,
} ,
) ;
}
// Resolve alert
if ( operation === 'resolve' ) {
const data : IDataObject = { } ;
2020-08-11 01:07:52 -07:00
2021-07-19 23:58:54 -07:00
data [ 'X-S4-ExternalID' ] = this . getNodeParameter ( 'externalId' , i ) as string ;
2020-08-18 17:55:36 -07:00
2021-07-19 23:58:54 -07:00
data [ 'X-S4-Status' ] = 'resolved' ;
2021-01-31 11:07:32 -08:00
2021-07-19 23:58:54 -07:00
data [ 'X-S4-SourceSystem' ] = 'n8n' ;
2020-08-11 01:07:52 -07:00
2021-07-19 23:58:54 -07:00
responseData = await SIGNL4ApiRequest . call (
this ,
'POST' ,
'' ,
{ } ,
{
formData : data ,
} ,
) ;
}
2020-06-24 21:06:48 -07:00
}
2021-07-19 23:58:54 -07:00
if ( Array . isArray ( responseData ) ) {
returnData . push . apply ( returnData , responseData as IDataObject [ ] ) ;
} else if ( responseData !== undefined ) {
returnData . push ( responseData as IDataObject ) ;
}
} catch ( error ) {
if ( this . continueOnFail ( ) ) {
returnData . push ( { error : error.message } ) ;
continue ;
}
throw error ;
2021-01-28 21:46:28 -08:00
}
2020-06-23 08:18:01 -07:00
}
return [ this . helpers . returnJsonArray ( returnData ) ] ;
}
}