Add binary data support to Telegram Node (#2249)

*  Add binary upload for Telegram

*  Improvements to #2247

Co-authored-by: pemontto <pemontto@gmail.com>
This commit is contained in:
Ricardo Espinoza 2021-09-27 18:47:39 -04:00 committed by GitHub
parent 3c256dc3f6
commit 389931da71
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 176 additions and 78 deletions

View file

@ -1,4 +1,5 @@
import {
BINARY_ENCODING,
IExecuteFunctions,
IHookFunctions,
ILoadOptionsFunctions,
@ -10,7 +11,7 @@ import {
} from 'request';
import {
IDataObject, NodeApiError, NodeOperationError,
IBinaryData, IDataObject, NodeApiError, NodeOperationError,
} from 'n8n-workflow';
// Interface in n8n
@ -142,7 +143,7 @@ export function addAdditionalFields(this: IExecuteFunctions, body: IDataObject,
* @param {object} body
* @returns {Promise<any>}
*/
export async function apiRequest(this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions | IWebhookFunctions, method: string, endpoint: string, body: object, query?: IDataObject, option: IDataObject = {}): Promise<any> { // tslint:disable-line:no-any
export async function apiRequest(this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions | IWebhookFunctions, method: string, endpoint: string, body: IDataObject, query?: IDataObject, option: IDataObject = {}): Promise<any> { // tslint:disable-line:no-any
const credentials = await this.getCredentials('telegramApi');
if (credentials === undefined) {
@ -152,12 +153,11 @@ export async function apiRequest(this: IHookFunctions | IExecuteFunctions | ILoa
query = query || {};
const options: OptionsWithUri = {
headers: {
},
headers: {},
method,
uri: `https://api.telegram.org/bot${credentials.accessToken}/${endpoint}`,
body,
qs: query,
uri: `https://api.telegram.org/bot${credentials.accessToken}/${endpoint}`,
json: true,
};
@ -192,3 +192,7 @@ export function getImageBySize(photos: IDataObject[], size: string): IDataObject
return photos[index];
}
export function getPropertyName(operation: string) {
return operation.replace('send', '').toLowerCase();
}

View file

@ -3,6 +3,7 @@ import {
} from 'n8n-core';
import {
IBinaryData,
ICredentialsDecrypted,
ICredentialTestFunctions,
IDataObject,
@ -16,6 +17,7 @@ import {
import {
addAdditionalFields,
apiRequest,
getPropertyName,
} from './GenericFunctions';
@ -740,6 +742,61 @@ export class Telegram implements INodeType {
required: true,
description: 'Unique identifier for the target chat or username of the target<br />channel (in the format @channelusername). To find your chat id ask @get_id_bot.',
},
// ----------------------------------
// message:sendAnimation/sendAudio/sendDocument/sendPhoto/sendSticker/sendVideo
// ----------------------------------
{
displayName: 'Binary Data',
name: 'binaryData',
type: 'boolean',
default: false,
required: true,
displayOptions: {
show: {
operation: [
'sendAnimation',
'sendAudio',
'sendDocument',
'sendPhoto',
'sendVideo',
'sendSticker',
],
resource: [
'message',
],
},
},
description: 'If the data to upload should be taken from binary field.',
},
{
displayName: 'Binary Property',
name: 'binaryPropertyName',
type: 'string',
default: 'data',
required: true,
displayOptions: {
show: {
operation: [
'sendAnimation',
'sendAudio',
'sendDocument',
'sendPhoto',
'sendVideo',
'sendSticker',
],
resource: [
'message',
],
binaryData: [
true,
],
},
},
placeholder: '',
description: 'Name of the binary property that contains the data to upload',
},
{
displayName: 'Message ID',
name: 'messageId',
@ -828,9 +885,12 @@ export class Telegram implements INodeType {
resource: [
'message',
],
binaryData: [
false,
],
},
},
description: 'Animation to send. Pass a file_id to send an animation that exists on the Telegram servers (recommended)<br />or pass an HTTP URL for Telegram to get an animation from the Internet.',
description: 'Animation to send. Pass a file_id to send an animation that exists on the Telegram servers (recommended)<br />, an HTTP URL for Telegram to get an animation from the Internet',
},
@ -851,9 +911,12 @@ export class Telegram implements INodeType {
resource: [
'message',
],
binaryData: [
false,
],
},
},
description: 'Audio file to send. Pass a file_id to send a file that exists on the Telegram servers (recommended)<br />or pass an HTTP URL for Telegram to get a file from the Internet.',
description: 'Audio file to send. Pass a file_id to send a file that exists on the Telegram servers (recommended)<br />, an HTTP URL for Telegram to get a file from the Internet',
},
@ -939,9 +1002,12 @@ export class Telegram implements INodeType {
resource: [
'message',
],
binaryData: [
false,
],
},
},
description: 'Document to send. Pass a file_id to send a file that exists on the Telegram servers (recommended)<br />or pass an HTTP URL for Telegram to get a file from the Internet.',
description: 'Document to send. Pass a file_id to send a file that exists on the Telegram servers (recommended)<br />, an HTTP URL for Telegram to get a file from the Internet',
},
@ -1131,9 +1197,12 @@ export class Telegram implements INodeType {
resource: [
'message',
],
binaryData: [
false,
],
},
},
description: 'Photo to send. Pass a file_id to send a photo that exists on the Telegram servers (recommended)<br />or pass an HTTP URL for Telegram to get a photo from the Internet.',
description: 'Photo to send. Pass a file_id to send a photo that exists on the Telegram servers (recommended)<br />, an HTTP URL for Telegram to get a photo from the Internet',
},
@ -1153,9 +1222,12 @@ export class Telegram implements INodeType {
resource: [
'message',
],
binaryData: [
false,
],
},
},
description: 'Sticker to send. Pass a file_id to send a file that exists on the Telegram servers (recommended)<br />or pass an HTTP URL for Telegram to get a .webp file from the Internet.',
description: 'Sticker to send. Pass a file_id to send a file that exists on the Telegram servers (recommended)<br />, an HTTP URL for Telegram to get a .webp file from the Internet',
},
@ -1175,12 +1247,14 @@ export class Telegram implements INodeType {
resource: [
'message',
],
binaryData: [
false,
],
},
},
description: 'Video file to send. Pass a file_id to send a file that exists on the Telegram servers (recommended)<br />or pass an HTTP URL for Telegram to get a file from the Internet.',
description: 'Video file to send. Pass a file_id to send a file that exists on the Telegram servers (recommended)<br />, an HTTP URL for Telegram to get a file from the Internet',
},
// ----------------------------------
// message:editMessageText/sendAnimation/sendAudio/sendLocation/sendMessage/sendPhoto/sendSticker/sendVideo
// ----------------------------------
@ -1756,7 +1830,7 @@ export class Telegram implements INodeType {
message: 'Token is not valid.',
};
}
} catch(err) {
} catch (err) {
return {
status: 'Error',
message: `Token is not valid; ${err.message}`,
@ -1787,6 +1861,7 @@ export class Telegram implements INodeType {
const operation = this.getNodeParameter('operation', 0) as string;
const resource = this.getNodeParameter('resource', 0) as string;
const binaryData = this.getNodeParameter('binaryData', 0, false) as boolean;
for (let i = 0; i < items.length; i++) {
try {
@ -1957,12 +2032,11 @@ export class Telegram implements INodeType {
endpoint = 'sendAnimation';
body.chat_id = this.getNodeParameter('chatId', i) as string;
body.animation = this.getNodeParameter('file', i) as string;
body.animation = this.getNodeParameter('file', i, '') as string;
// Add additional fields and replyMarkup
addAdditionalFields.call(this, body, i);
} else if (operation === 'sendAudio') {
// ----------------------------------
// message:sendAudio
@ -1971,7 +2045,7 @@ export class Telegram implements INodeType {
endpoint = 'sendAudio';
body.chat_id = this.getNodeParameter('chatId', i) as string;
body.audio = this.getNodeParameter('file', i) as string;
body.audio = this.getNodeParameter('file', i, '') as string;
// Add additional fields and replyMarkup
addAdditionalFields.call(this, body, i);
@ -1994,7 +2068,7 @@ export class Telegram implements INodeType {
endpoint = 'sendDocument';
body.chat_id = this.getNodeParameter('chatId', i) as string;
body.document = this.getNodeParameter('file', i) as string;
body.document = this.getNodeParameter('file', i, '') as string;
// Add additional fields and replyMarkup
addAdditionalFields.call(this, body, i);
@ -2056,7 +2130,7 @@ export class Telegram implements INodeType {
endpoint = 'sendPhoto';
body.chat_id = this.getNodeParameter('chatId', i) as string;
body.photo = this.getNodeParameter('file', i) as string;
body.photo = this.getNodeParameter('file', i, '') as string;
// Add additional fields and replyMarkup
addAdditionalFields.call(this, body, i);
@ -2069,7 +2143,7 @@ export class Telegram implements INodeType {
endpoint = 'sendSticker';
body.chat_id = this.getNodeParameter('chatId', i) as string;
body.sticker = this.getNodeParameter('file', i) as string;
body.sticker = this.getNodeParameter('file', i, '') as string;
// Add additional fields and replyMarkup
addAdditionalFields.call(this, body, i);
@ -2082,17 +2156,37 @@ export class Telegram implements INodeType {
endpoint = 'sendVideo';
body.chat_id = this.getNodeParameter('chatId', i) as string;
body.video = this.getNodeParameter('file', i) as string;
body.video = this.getNodeParameter('file', i, '') as string;
// Add additional fields and replyMarkup
addAdditionalFields.call(this, body, i);
}
} else {
throw new NodeOperationError(this.getNode(), `The resource "${resource}" is not known!`);
}
const responseData = await apiRequest.call(this, requestMethod, endpoint, body, qs);
let responseData;
if (binaryData === true) {
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', 0) as string;
const binaryData = items[i].binary![binaryPropertyName] as IBinaryData;
const dataBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
const propertyName = getPropertyName(operation);
const formData = {
...body,
[propertyName]: {
value: dataBuffer,
options: {
filename: binaryData.fileName,
contentType: binaryData.mimeType,
},
},
};
responseData = await apiRequest.call(this, requestMethod, endpoint, {}, qs, { formData });
} else {
responseData = await apiRequest.call(this, requestMethod, endpoint, body, qs);
}
if (resource === 'file' && operation === 'get') {
if (this.getNodeParameter('download', i, false) as boolean === true) {