n8n-nodes-telemaragonov
Version:
n8n node for Telegram integration using GRAMJS by telegram@totborodach
544 lines (543 loc) • 22.1 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.TelegramGramJs = void 0;
const n8n_workflow_1 = require("n8n-workflow");
const telegram_1 = require("telegram");
const sessions_1 = require("telegram/sessions");
const fs = __importStar(require("fs"));
class TelegramGramJs {
description = {
displayName: 'Telegram GramJS',
name: 'telegramGramJs',
icon: 'file:telegram.svg',
group: ['communication'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Interact with Telegram using GramJS',
defaults: {
name: 'Telegram GramJS',
},
inputs: ['main'],
outputs: ['main'],
credentials: [
{
name: 'telegramGramJsApi',
required: true,
},
],
properties: [
{
displayName: 'Resource',
name: 'resource',
type: 'options',
noDataExpression: true,
options: [
{
name: 'Message',
value: 'message',
},
{
name: 'Chat',
value: 'chat',
},
{
name: 'User',
value: 'user',
},
],
default: 'message',
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['message'],
},
},
options: [
{
name: 'Send',
value: 'send',
description: 'Send a message',
action: 'Send a message',
},
{
name: 'Get',
value: 'get',
description: 'Get messages from a chat',
action: 'Get messages from a chat',
},
{
name: 'Delete',
value: 'delete',
description: 'Delete a message',
action: 'Delete a message',
},
],
default: 'send',
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['chat'],
},
},
options: [
{
name: 'Get',
value: 'get',
description: 'Get chat information',
action: 'Get chat information',
},
{
name: 'Get Members',
value: 'getMembers',
description: 'Get chat members',
action: 'Get chat members',
},
{
name: 'History',
value: 'history',
description: 'Get chat message history',
action: 'Get chat message history',
},
{
name: 'Get File',
value: 'getFile',
description: 'Download file from message and output as binary',
action: 'Download file from message',
},
],
default: 'get',
},
{
displayName: 'Delete File After Output',
name: 'deleteFile',
type: 'boolean',
default: false,
description: 'Delete file from disk after output (recommended for temp files)',
displayOptions: {
show: {
resource: ['chat'],
operation: ['getFile'],
},
},
},
{
displayName: 'File Name',
name: 'fileName',
type: 'string',
description: 'File name for downloaded file (оставьте пустым для автоопределения)',
displayOptions: {
show: {
resource: ['chat'],
operation: ['getFile'],
},
},
default: '',
required: false,
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['user'],
},
},
options: [
{
name: 'Get',
value: 'get',
description: 'Get user information',
action: 'Get user information',
},
{
name: 'Get Me',
value: 'getMe',
description: 'Get current user information',
action: 'Get current user information',
},
],
default: 'get',
},
// Message operations
{
displayName: 'Chat ID',
name: 'chatId',
type: 'string',
displayOptions: {
show: {
resource: ['message'],
operation: ['send', 'get'],
},
},
default: '',
required: true,
description: 'Chat ID, username, or phone number',
},
{
displayName: 'Message Text',
name: 'messageText',
type: 'string',
displayOptions: {
show: {
resource: ['message'],
operation: ['send'],
},
},
default: '',
required: true,
description: 'Text of the message to send',
},
{
displayName: 'Message ID',
name: 'messageId',
type: 'number',
displayOptions: {
show: {
resource: ['message'],
operation: ['delete'],
},
},
default: 0,
required: true,
description: 'ID of the message to delete',
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
displayOptions: {
show: {
resource: ['message'],
operation: ['get'],
},
},
default: 10,
description: 'Number of messages to retrieve',
},
// Chat operations
{
displayName: 'Chat ID',
name: 'chatId',
type: 'string',
displayOptions: {
show: {
resource: ['chat'],
},
},
default: '',
required: true,
description: 'Chat ID, username, or phone number',
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
displayOptions: {
show: {
resource: ['chat'],
operation: ['history'],
},
},
default: 10,
description: 'Number of messages to retrieve from chat history',
},
// User operations
{
displayName: 'User ID',
name: 'userId',
type: 'string',
displayOptions: {
show: {
resource: ['user'],
operation: ['get'],
},
},
default: '',
required: true,
description: 'User ID, username, or phone number',
},
// Additional options
{
displayName: 'Additional Options',
name: 'additionalOptions',
type: 'collection',
placeholder: 'Add Option',
default: {},
options: [
{
displayName: 'Parse Mode',
name: 'parseMode',
type: 'options',
options: [
{
name: 'None',
value: '',
},
{
name: 'Markdown',
value: 'markdown',
},
{
name: 'HTML',
value: 'html',
},
],
default: '',
description: 'How to parse the message text',
},
{
displayName: 'Silent',
name: 'silent',
type: 'boolean',
default: false,
description: 'Whether to send the message silently',
},
],
},
{
displayName: 'Media',
name: 'media',
type: 'string',
description: 'Имя бинарного свойства с медиафайлом (например, photo, document)',
displayOptions: {
show: {
resource: ['message'],
operation: ['send'],
},
},
default: '',
required: false,
},
{
displayName: 'Message ID',
name: 'messageId',
type: 'number',
description: 'ID of the message to download file from',
displayOptions: {
show: {
resource: ['chat'],
operation: ['getFile'],
},
},
default: 0,
required: true,
},
],
};
async execute() {
const items = this.getInputData();
const returnData = [];
const credentials = await this.getCredentials('telegramGramJsApi');
const apiId = parseInt(credentials.apiId, 10);
const apiHash = credentials.apiHash;
const sessionString = credentials.sessionString;
const phoneNumber = credentials.phoneNumber;
const session = new sessions_1.StringSession(sessionString || '');
const client = new telegram_1.TelegramClient(session, apiId, apiHash, {
connectionRetries: 5,
});
try {
// Start the client
if (!sessionString) {
await client.start({
phoneNumber: async () => phoneNumber,
password: async () => {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Password authentication not supported in n8n node. Please use session string.');
},
phoneCode: async () => {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Phone code authentication not supported in n8n node. Please use session string.');
},
onError: (err) => {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Authentication error: ${err.message}`);
},
});
}
else {
await client.connect();
}
for (let i = 0; i < items.length; i++) {
const resource = this.getNodeParameter('resource', i);
const operation = this.getNodeParameter('operation', i);
let responseData;
if (resource === 'message') {
if (operation === 'send') {
const chatId = this.getNodeParameter('chatId', i);
const messageText = this.getNodeParameter('messageText', i);
const additionalOptions = this.getNodeParameter('additionalOptions', i);
const mediaProperty = this.getNodeParameter('media', i, '');
const sendOptions = {
message: messageText,
};
if (additionalOptions.parseMode) {
sendOptions.parseMode = additionalOptions.parseMode;
}
if (additionalOptions.silent) {
sendOptions.silent = additionalOptions.silent;
}
// Если передан media, отправляем файл
const binaryData = items[i].binary?.[mediaProperty];
if (mediaProperty && binaryData && binaryData.data) {
const buffer = Buffer.from(binaryData.data, 'base64');
// Отправка файла (фото/документ)
responseData = await client.sendFile(chatId, {
file: buffer,
caption: messageText,
parseMode: sendOptions.parseMode,
silent: sendOptions.silent,
});
}
else {
// Обычная отправка текста
responseData = await client.sendMessage(chatId, sendOptions);
}
}
else if (operation === 'get') {
const chatId = this.getNodeParameter('chatId', i);
const limit = this.getNodeParameter('limit', i);
const messages = await client.getMessages(chatId, { limit });
responseData = messages;
}
else if (operation === 'delete') {
const chatId = this.getNodeParameter('chatId', i);
const messageId = this.getNodeParameter('messageId', i);
responseData = await client.deleteMessages(chatId, [messageId], {
revoke: true,
});
}
}
else if (resource === 'chat') {
const chatId = this.getNodeParameter('chatId', i);
if (operation === 'get') {
responseData = await client.getEntity(chatId);
}
else if (operation === 'getMembers') {
const participants = await client.getParticipants(chatId);
responseData = participants;
}
else if (operation === 'history') {
const limit = this.getNodeParameter('limit', i, 10);
const messages = await client.getMessages(chatId, { limit });
responseData = messages;
}
else if (operation === 'getFile') {
const messageId = this.getNodeParameter('messageId', i);
let fileName = this.getNodeParameter('fileName', i, '');
const deleteFile = this.getNodeParameter('deleteFile', i, false);
const messages = await client.getMessages(chatId, { ids: [messageId] });
const message = messages[0];
if (message) {
let mimeType = 'application/octet-stream';
// Определяем имя и mimeType
if (!fileName && message.media) {
if (message.media.className === 'MessageMediaDocument' && message.media.document) {
const doc = message.media.document;
if (doc.attributes && Array.isArray(doc.attributes)) {
const nameAttr = doc.attributes.find((a) => a.fileName);
if (nameAttr && nameAttr.fileName)
fileName = nameAttr.fileName;
}
if (doc.mimeType)
mimeType = doc.mimeType;
}
if (message.media.className === 'MessageMediaPhoto' && message.media.photo) {
mimeType = 'image/jpeg';
fileName = 'photo.jpg';
}
}
if (!fileName)
fileName = 'file';
const filePath = `/tmp/${fileName}`;
await client.downloadMedia(message, { outputFile: filePath });
const fileBuffer = fs.readFileSync(filePath);
returnData.push({
json: { message: 'File downloaded' },
binary: {
data: {
data: fileBuffer.toString('base64'),
fileName,
mimeType,
},
},
});
if (deleteFile) {
fs.unlinkSync(filePath);
}
}
else {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'No message found');
}
continue;
}
}
else if (resource === 'user') {
if (operation === 'get') {
const userId = this.getNodeParameter('userId', i);
responseData = await client.getEntity(userId);
}
else if (operation === 'getMe') {
responseData = await client.getMe();
}
}
if (Array.isArray(responseData)) {
returnData.push(...responseData.map((item) => ({ json: item })));
}
else {
returnData.push({ json: responseData });
}
}
return [returnData];
}
catch (error) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
finally {
await client.disconnect();
}
}
}
exports.TelegramGramJs = TelegramGramJs;