2023-01-27 03:22:44 -08:00
import type {
2023-03-09 09:13:15 -08:00
IHookFunctions ,
IWebhookFunctions ,
2023-01-27 03:22:44 -08:00
IDataObject ,
INodeType ,
INodeTypeDescription ,
IWebhookResponseData ,
} from 'n8n-workflow' ;
2022-08-17 08:50:24 -07:00
2024-01-19 00:09:11 -08:00
import { apiRequest , getImageBySize , getSecretToken } from './GenericFunctions' ;
2022-08-17 08:50:24 -07:00
2023-01-27 03:22:44 -08:00
import type { IEvent } from './IEvent' ;
2019-10-04 03:35:06 -07:00
export class TelegramTrigger implements INodeType {
description : INodeTypeDescription = {
displayName : 'Telegram Trigger' ,
name : 'telegramTrigger' ,
2021-02-04 00:50:39 -08:00
icon : 'file:telegram.svg' ,
2019-10-04 03:35:06 -07:00
group : [ 'trigger' ] ,
2024-01-19 00:09:11 -08:00
version : [ 1 , 1.1 ] ,
defaultVersion : 1.1 ,
2019-10-04 03:35:06 -07:00
subtitle : '=Updates: {{$parameter["updates"].join(", ")}}' ,
2021-07-03 05:40:16 -07:00
description : 'Starts the workflow on a Telegram update' ,
2019-10-04 03:35:06 -07:00
defaults : {
name : 'Telegram Trigger' ,
} ,
inputs : [ ] ,
outputs : [ 'main' ] ,
credentials : [
{
name : 'telegramApi' ,
required : true ,
2020-09-04 01:28:04 -07:00
} ,
2019-10-04 03:35:06 -07:00
] ,
webhooks : [
{
name : 'default' ,
httpMethod : 'POST' ,
responseMode : 'onReceived' ,
path : 'webhook' ,
} ,
] ,
properties : [
2024-01-19 00:09:11 -08:00
{
displayName :
'Due to Telegram API limitations, you can use just one Telegram trigger for each bot at a time' ,
name : 'telegramTriggerNotice' ,
type : 'notice' ,
default : '' ,
} ,
2019-10-04 03:35:06 -07:00
{
2023-01-10 02:20:53 -08:00
displayName : 'Trigger On' ,
2019-10-04 03:35:06 -07:00
name : 'updates' ,
type : 'multiOptions' ,
options : [
{
name : '*' ,
value : '*' ,
2022-05-06 14:01:25 -07:00
description : 'All updates' ,
2019-10-04 03:35:06 -07:00
} ,
{
2022-06-20 07:54:01 -07:00
name : 'Callback Query' ,
value : 'callback_query' ,
description : 'Trigger on new incoming callback query' ,
2019-10-04 03:35:06 -07:00
} ,
{
2022-06-03 10:23:49 -07:00
name : 'Channel Post' ,
2019-10-04 03:35:06 -07:00
value : 'channel_post' ,
2022-08-17 08:50:24 -07:00
description :
'Trigger on new incoming channel post of any kind — text, photo, sticker, etc' ,
2019-10-04 03:35:06 -07:00
} ,
{
2022-06-03 10:23:49 -07:00
name : 'Edited Channel Post' ,
2019-10-04 03:35:06 -07:00
value : 'edited_channel_post' ,
2022-08-17 08:50:24 -07:00
description :
'Trigger on new version of a channel post that is known to the bot and was edited' ,
2019-10-04 03:35:06 -07:00
} ,
2022-06-20 07:54:01 -07:00
{
name : 'Edited Message' ,
value : 'edited_message' ,
2022-08-17 08:50:24 -07:00
description :
'Trigger on new version of a channel post that is known to the bot and was edited' ,
2022-06-20 07:54:01 -07:00
} ,
2019-10-04 03:35:06 -07:00
{
2022-06-03 10:23:49 -07:00
name : 'Inline Query' ,
2019-10-04 03:35:06 -07:00
value : 'inline_query' ,
2022-05-06 14:01:25 -07:00
description : 'Trigger on new incoming inline query' ,
2019-10-04 03:35:06 -07:00
} ,
{
2022-06-20 07:54:01 -07:00
name : 'Message' ,
value : 'message' ,
description : 'Trigger on new incoming message of any kind — text, photo, sticker, etc' ,
2019-10-04 03:35:06 -07:00
} ,
{
2022-06-20 07:54:01 -07:00
name : 'Poll' ,
value : 'poll' ,
2023-01-10 02:20:53 -08:00
action : 'On Poll Change' ,
2022-08-17 08:50:24 -07:00
description :
'Trigger on new poll state. Bots receive only updates about stopped polls and polls, which are sent by the bot.' ,
2019-10-04 03:35:06 -07:00
} ,
{
2022-06-03 10:23:49 -07:00
name : 'Pre-Checkout Query' ,
2019-10-04 03:35:06 -07:00
value : 'pre_checkout_query' ,
2022-08-17 08:50:24 -07:00
description :
'Trigger on new incoming pre-checkout query. Contains full information about checkout.' ,
2019-10-04 03:35:06 -07:00
} ,
{
2022-06-20 07:54:01 -07:00
name : 'Shipping Query' ,
value : 'shipping_query' ,
2022-08-17 08:50:24 -07:00
description :
'Trigger on new incoming shipping query. Only for invoices with flexible price.' ,
2019-10-04 03:35:06 -07:00
} ,
] ,
required : true ,
2019-10-04 13:16:26 -07:00
default : [ ] ,
2019-10-04 03:35:06 -07:00
} ,
2022-09-02 03:38:24 -07:00
{
displayName :
'Every uploaded attachment, even if sent in a group, will trigger a separate event. You can identify that an attachment belongs to a certain group by <code>media_group_id</code> .' ,
name : 'attachmentNotice' ,
type : 'notice' ,
default : '' ,
} ,
2020-09-04 01:28:04 -07:00
{
displayName : 'Additional Fields' ,
name : 'additionalFields' ,
type : 'collection' ,
placeholder : 'Add Field' ,
default : { } ,
options : [
{
displayName : 'Download Images/Files' ,
2020-09-04 01:30:22 -07:00
name : 'download' ,
2020-09-04 01:28:04 -07:00
type : 'boolean' ,
default : false ,
2022-06-20 07:54:01 -07:00
// eslint-disable-next-line n8n-nodes-base/node-param-description-boolean-without-whether
2022-08-17 08:50:24 -07:00
description :
"Telegram delivers the image in multiple sizes. By default, just the large image would be downloaded. If you want to change the size, set the field 'Image Size'." ,
2020-09-04 01:28:04 -07:00
} ,
{
displayName : 'Image Size' ,
name : 'imageSize' ,
type : 'options' ,
2020-09-08 00:48:07 -07:00
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
download : [ true ] ,
2020-09-08 00:48:07 -07:00
} ,
} ,
2020-09-04 01:28:04 -07:00
options : [
{
name : 'Small' ,
value : 'small' ,
} ,
{
name : 'Medium' ,
value : 'medium' ,
} ,
{
name : 'Large' ,
value : 'large' ,
} ,
2022-02-18 07:09:44 -08:00
{
name : 'Extra Large' ,
value : 'extraLarge' ,
} ,
2020-09-04 01:28:04 -07:00
] ,
default : 'large' ,
description : 'The size of the image to be downloaded' ,
} ,
] ,
} ,
2019-10-04 03:35:06 -07:00
] ,
} ;
webhookMethods = {
default : {
2019-10-04 06:17:24 -07:00
async checkExists ( this : IHookFunctions ) : Promise < boolean > {
2020-09-02 01:53:38 -07:00
const endpoint = 'getWebhookInfo' ;
const webhookReturnData = await apiRequest . call ( this , 'POST' , endpoint , { } ) ;
2020-09-02 05:36:30 -07:00
const webhookUrl = this . getNodeWebhookUrl ( 'default' ) ;
2020-09-02 01:53:38 -07:00
2020-09-02 05:36:30 -07:00
if ( webhookReturnData . result . url === webhookUrl ) {
return true ;
2020-09-02 01:53:38 -07:00
}
2020-09-02 05:36:30 -07:00
return false ;
2019-10-04 06:17:24 -07:00
} ,
2019-10-04 03:35:06 -07:00
async create ( this : IHookFunctions ) : Promise < boolean > {
const webhookUrl = this . getNodeWebhookUrl ( 'default' ) ;
let allowedUpdates = this . getNodeParameter ( 'updates' ) as string [ ] ;
2023-07-25 06:59:44 -07:00
if ( ( allowedUpdates || [ ] ) . includes ( '*' ) ) {
2019-10-04 03:35:06 -07:00
allowedUpdates = [ ] ;
}
const endpoint = 'setWebhook' ;
2024-01-19 00:09:11 -08:00
const secret_token = getSecretToken . call ( this ) ;
2019-10-04 03:35:06 -07:00
const body = {
url : webhookUrl ,
allowed_updates : allowedUpdates ,
2024-01-19 00:09:11 -08:00
secret_token ,
2019-10-04 03:35:06 -07:00
} ;
await apiRequest . call ( this , 'POST' , endpoint , body ) ;
return true ;
} ,
async delete ( this : IHookFunctions ) : Promise < boolean > {
const endpoint = 'deleteWebhook' ;
const body = { } ;
try {
await apiRequest . call ( this , 'POST' , endpoint , body ) ;
2021-04-16 09:33:36 -07:00
} catch ( error ) {
2019-10-04 03:35:06 -07:00
return false ;
}
return true ;
} ,
} ,
} ;
2020-09-04 01:28:04 -07:00
async webhook ( this : IWebhookFunctions ) : Promise < IWebhookResponseData > {
2022-04-14 23:00:47 -07:00
const credentials = await this . getCredentials ( 'telegramApi' ) ;
2019-10-04 03:35:06 -07:00
2020-09-04 01:28:04 -07:00
const bodyData = this . getBodyData ( ) as IEvent ;
2024-01-19 00:09:11 -08:00
const headerData = this . getHeaderData ( ) ;
const nodeVersion = this . getNode ( ) . typeVersion ;
if ( nodeVersion > 1 ) {
const secret = getSecretToken . call ( this ) ;
if ( secret !== headerData [ 'x-telegram-bot-api-secret-token' ] ) {
const res = this . getResponseObject ( ) ;
res . status ( 403 ) . json ( { message : 'Provided secret is not valid' } ) ;
return {
noWebhookResponse : true ,
} ;
}
}
2020-09-04 01:28:04 -07:00
const additionalFields = this . getNodeParameter ( 'additionalFields' ) as IDataObject ;
2020-09-04 01:30:22 -07:00
if ( additionalFields . download === true ) {
2020-09-04 01:28:04 -07:00
let imageSize = 'large' ;
2021-12-02 23:53:20 -08:00
let key : 'message' | 'channel_post' = 'message' ;
if ( bodyData . channel_post ) {
key = 'channel_post' ;
}
2022-08-17 08:50:24 -07:00
if (
2022-12-02 12:54:28 -08:00
( bodyData [ key ] ? . photo && Array . isArray ( bodyData [ key ] ? . photo ) ) ||
2022-08-17 08:50:24 -07:00
bodyData [ key ] ? . document
) {
2020-09-04 01:28:04 -07:00
if ( additionalFields . imageSize ) {
imageSize = additionalFields . imageSize as string ;
}
let fileId ;
2021-12-02 23:53:20 -08:00
if ( bodyData [ key ] ? . photo ) {
2022-08-17 08:50:24 -07:00
let image = getImageBySize (
bodyData [ key ] ? . photo as IDataObject [ ] ,
imageSize ,
) as IDataObject ;
2020-09-04 01:28:04 -07:00
// When the image is sent from the desktop app telegram does not resize the image
// So return the only image avaiable
// Basically the Image Size parameter would work just when the images comes from the mobile app
if ( image === undefined ) {
2021-12-02 23:53:20 -08:00
image = bodyData [ key ] ! . photo ! [ 0 ] ;
2020-09-04 01:28:04 -07:00
}
fileId = image . file_id ;
} else {
2021-12-02 23:53:20 -08:00
fileId = bodyData [ key ] ? . document ? . file_id ;
2020-09-04 01:28:04 -07:00
}
2022-08-17 08:50:24 -07:00
const {
result : { file_path } ,
} = await apiRequest . call ( this , 'GET' , ` getFile?file_id= ${ fileId } ` , { } ) ;
2020-09-04 01:28:04 -07:00
2022-08-17 08:50:24 -07:00
const file = await apiRequest . call (
this ,
'GET' ,
'' ,
{ } ,
{ } ,
{
json : false ,
encoding : null ,
uri : ` https://api.telegram.org/file/bot ${ credentials . accessToken } / ${ file_path } ` ,
resolveWithFullResponse : true ,
} ,
) ;
2020-09-04 01:28:04 -07:00
const data = Buffer . from ( file . body as string ) ;
const fileName = file_path . split ( '/' ) . pop ( ) ;
2022-08-17 08:50:24 -07:00
const binaryData = await this . helpers . prepareBinaryData (
data as unknown as Buffer ,
2023-02-27 19:39:43 -08:00
fileName as string ,
2022-08-17 08:50:24 -07:00
) ;
2020-09-04 01:28:04 -07:00
return {
workflowData : [
[
{
json : bodyData as unknown as IDataObject ,
binary : {
data : binaryData ,
} ,
2020-10-22 06:46:03 -07:00
} ,
] ,
2020-09-04 01:28:04 -07:00
] ,
} ;
}
}
2019-10-04 03:35:06 -07:00
return {
2022-08-17 08:50:24 -07:00
workflowData : [ this . helpers . returnJsonArray ( [ bodyData as unknown as IDataObject ] ) ] ,
2019-10-04 03:35:06 -07:00
} ;
}
}