UNPKG

n8n-nodes-telemaragonov

Version:

n8n node for Telegram integration using GRAMJS by telegram@totborodach

544 lines (543 loc) 22.1 kB
"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;