Создание приложения для прослушивания телеграмм канала
Прежде всего, обратите внимание, что речь идет не о создании бота.
Моя цель - создать приложение, которое будет просто прослушивать любое количество телеграммных каналов, на которые подписана учетная запись, на которую я буду предоставлять его, и извлекать все сообщения, отправленные на эти каналы (как если бы я был обычным пользователем). Я думаю, что мне нужно будет
- Аутентифицировать себя, используя номер телефона моей учетной записи
- Уметь настроить прослушиватель обратного вызова для каждого канала или общего прослушивателя для всех входящих сообщений
Я искал вокруг telegram api
в течение пары дней, и я очень смущен тем, как это работает. Отказавшись от этого, я начал смотреть на готовые реализации, в основном для NodeJS
но все еще не смог найти конкретного решения. Я тестирую некоторые вещи с помощью telegram-js api, но запускаю его напрямую, используя node
не работал Нужно ли запускать в браузере? Есть ли более рациональный подход к этому? Желательно что-то с хорошей документацией.
PS: Я свободно говорю на Java и Javascript, поэтому я расставил приоритеты для библиотек, основанных на этих языках.
РЕДАКТИРОВАТЬ:
Вот код, который я написал (скопировал пример)
var { Telegram } = require("../libs/telegram");
var TypeLanguage = require("telegram-tl-node") ;
var MTProto = require("telegram-mt-node");
var schema = require("../libs/api-schema.json");
const APP_ID = "111111";
const APP_HASH = "fb6da8f6abdf876abd6a9d7bf6";
const SERVER = { host: "111.111.111.11", port: "443" };
const config = {
id: APP_ID,
hash: APP_HASH,
version: '0.0.1',
lang_code: 'en',
authKey: null
};
let telegram = new Telegram(MTProto, TypeLanguage);
telegram.useSchema(schema);
addPublicKeys(telegram);
let connection = new MTProto.net.HttpConnection(SERVER);
let client = telegram.createClient();
client.setConnection(connection);
connection.connect(function() {
let ready = client.setup(config);
ready.then(function(client) {
// it never resolves this promise
function callback(response) {
console.log(response);
}
client.callApi("help.getConfig").then(callback, callback);
});
});
Он использует эти 2 библиотеки: telegram-mt-node telegram-tl-node
4 ответа
Поздний ответ, но может помочь другим.
Вы можете использовать mtproto-core для аутентификации с помощью обычной учетной записи Telegram и слушать обновления (или делать все, что вы можете с клиентами Telegram, на самом деле)
Вот пример сценария, который я написал, который прослушивает новые сообщения из каналов / супергрупп, на которые подписан пользователь:
const { MTProto, getSRPParams } = require('@mtproto/core');
const prompts = require('prompts');
const api_id = ...; // insert api_id here
const api_hash = ' ... '; // insert api_hash here
async function getPhone() {
return (await prompts({
type: 'text',
name: 'phone',
message: 'Enter your phone number:'
})).phone
}
async function getCode() {
// you can implement your code fetching strategy here
return (await prompts({
type: 'text',
name: 'code',
message: 'Enter the code sent:',
})).code
}
async function getPassword() {
return (await prompts({
type: 'text',
name: 'password',
message: 'Enter Password:',
})).password
}
const mtproto = new MTProto({
api_id,
api_hash,
});
function startListener() {
console.log('[+] starting listener')
mtproto.updates.on('updates', ({ updates }) => {
const newChannelMessages = updates.filter((update) => update._ === 'updateNewChannelMessage').map(({ message }) => message) // filter `updateNewChannelMessage` types only and extract the 'message' object
for (const message of newChannelMessages) {
// printing new channel messages
console.log(`[${message.to_id.channel_id}] ${message.message}`)
}
});
}
// checking authentication status
mtproto
.call('users.getFullUser', {
id: {
_: 'inputUserSelf',
},
})
.then(startListener) // means the user is logged in -> so start the listener
.catch(async error => {
// The user is not logged in
console.log('[+] You must log in')
const phone_number = await getPhone()
mtproto.call('auth.sendCode', {
phone_number: phone_number,
settings: {
_: 'codeSettings',
},
})
.catch(error => {
if (error.error_message.includes('_MIGRATE_')) {
const [type, nextDcId] = error.error_message.split('_MIGRATE_');
mtproto.setDefaultDc(+nextDcId);
return sendCode(phone_number);
}
})
.then(async result => {
return mtproto.call('auth.signIn', {
phone_code: await getCode(),
phone_number: phone_number,
phone_code_hash: result.phone_code_hash,
});
})
.catch(error => {
if (error.error_message === 'SESSION_PASSWORD_NEEDED') {
return mtproto.call('account.getPassword').then(async result => {
const { srp_id, current_algo, srp_B } = result;
const { salt1, salt2, g, p } = current_algo;
const { A, M1 } = await getSRPParams({
g,
p,
salt1,
salt2,
gB: srp_B,
password: await getPassword(),
});
return mtproto.call('auth.checkPassword', {
password: {
_: 'inputCheckPasswordSRP',
srp_id,
A,
M1,
},
});
});
}
})
.then(result => {
console.log('[+] successfully authenticated');
// start listener since the user has logged in now
startListener()
});
})
Вы можете найти значения для api_id
а также api_hash
с https://my.telegram.org/.
При первом запуске сценарий запрашивает у пользователя phone_number, код и пароль.
[+] You must log in
√ Enter your phone number: ... <phone_number>
√ Enter the code sent: ... <code>
√ Enter Password: ... <2FA password>
и после того, как аутентификация завершена, выводится образец:
[+] starting listener
[13820XXXXX] Ja
[13820XXXXX] Bis bald guys��
[13820XXXXX] Ja. �
[13820XXXXX] Bis später
[13820XXXXX] Jaaa�
То, как я проверял статус аутентификации, было взято отсюда.
Стоит проверить альтернативные библиотеки, которые активны на момент написания (и могут использоваться для создания такого же поведения с): Airgram (tdlib) и GramJs
вот мой рабочий код с использованием gramjs и только на nodejs. Получение всех сообщений со всех каналов без задержек.
Примечание. Игнорируйте «Выполнить фрагмент кода», так как это лучший способ добавить весь код вместо форматирования.
Я использовал библиотеку gram.js и, по сути, сделал это :
import { TelegramClient } from 'telegram'
TelegramClient().addEventHandler(handler, { chats: [1234567890] })
Бот НЕ обязательно должен быть участником канала, который вы хотите слушать.
Мой код работает как приложение Node.js.
Сначала вам нужно создать токен, поговорив с @BotFather через Telegram.
Вы можете использовать библиотеку gram.js следующим образом:
Установите это:
npm install properties-reader npm install telegram npm install input
Тогда получите свой
apiId
иapiHash
из Telegram Auth в разделе «Конфигурация приложения».Создать файл
config.properties
с содержанием, подобным этому:[telegram] apiId=12345678 apiHash=12345678901234567890123456789012
Внутри вашего
nodejs
код, вы можете слушать определенный чат, подобный этому (см.chatId
внутри кода ниже):const PropertiesReader = require('properties-reader'); const configs = PropertiesReader('config.properties'); getProp = (bundle, key) => {return configs.get(`${bundle}.${key}`);} const { TelegramClient } = require("telegram"); const { StoreSession } = require("telegram/sessions"); const { NewMessage } = require("telegram/events"); const { EditedMessage } = require("telegram/events/EditedMessage"); const input = require("input"); const apiId = getProp("telegram", "apiId") const apiHash = getProp("telegram", "apiHash") const storeSession = new StoreSession("telegram_session"); // see: https://painor.gitbook.io/gramjs/getting-started/authorization#store-session (async () => { console.log("Loading interactive example..."); const client = new TelegramClient(storeSession, apiId, apiHash, { connectionRetries: 5, }); await client.start({ phoneNumber: async () => await input.text("Please enter your number: "), password: async () => await input.text("Please enter your password: "), phoneCode: async () => await input.text("Please enter the code you received: "), onError: (err) => console.log(err), }); console.log("You should now be connected."); client.session.save(); // Save the session to avoid logging in again async function eventPrint(event) { // see 'node_modules/telegram/tl/custom/message.d.ts' const message = event.message const isNew = message.editDate === undefined const text = message.text const date = new Date(message.date*1000) console.log(`The message is ${isNew ? 'new' : 'an update'}`) console.log(`The text is: ${text}`) console.log(`The date is: ${date}`) } // to get the chatId: // option 1: open telegram on a web browser, go to the chat, and look the url in the address bar // option 2: open telegram app, copy link to any message, it should be something like: https://t.me/c/1234567890/12345, the first number after "/c/" is the chatId const chatId = 1234567890 client.addEventHandler(eventPrint, new NewMessage({ chats: [chatId] })); client.addEventHandler(eventPrint, new EditedMessage({ chats: [chatId] })); })();