Перейти к публикации
Форум ботоводов
admin

Пересылать сообщения из чужих чатов и каналов в свои

Рекомендованные сообщения

Всем привет!

Сегодня речь пойдет о создании бота на базе самодельного телеграм-клиента. Т.е. смысл такой - берутся исходники телеграма, компилируются, получаем библиотеку.

С этой библиотекой работаем от своего имени на питоне - такой бот будет работать от лица пользователя, и иметь те же возможности, которые имеет каждый, у кого есть телеграм - читать, пересылать, удалять и т.п. 

Например, если у вас есть доступ к платному закрытому каналу, или шифрованному чату, вы сможете пересылать оттуда информацию в любой другой чат, где у вас есть право голоса - и никаких ботов не нужно будет приглашать, а тем более давать им права админа.

Создание такого бота обойдется в 3 этапа, первый из которых можно пропустить, если у вас Windows 10 64 bit - просто возьмите мои готовые библиотеки. 

Этап 1 - получить исходники телеграм, установить дополнительные нужные модули, скомпилировать, получить на выходе нужную библиотеку dll. Об этом будет следующий пост. Вы можете пропустить его и скачать готовую tdjson.dll для своей платформы. Я выложу для Windows 10 64, а так она кросплатформенная, можете компилировать себе под любые современные ОС.

Этап 2 - Скопировать библиотеку в нужную папку, зарегистрировать, создать application в telegram и получить API ключи.

Этап 3 - непосредственно запустить код на питоне, указав API ключи и свой номер телефона, смотреть как переселаются сообщения и пить пиво

  • Like 2

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Этап 1 - сложный, его можно пропустить

Для начала будет нужно скомпилировать себе библиотеку от телеграма 
Для этого понадобится программа Git for Windows
Скачиваем, устанавливаем, теперь давайте создадим папку, где будем ТВОРИТЬ!
У меня это будет папка C:/code/examples/telegram – в ней будет всё, как промежуточное, так и итоговое. В этой папке теперь создадим папку src. На новой папке src щелкаем правой кнопкой мыши, и выбираем в контекстном меню Git Bash Here:

image.png.b70011e062281e99fbf825daf424c132.png

В появившемся окне пишем (обратите внимание на точку в конце:

git clone https://github.com/tdlib/td.git .

image.png.c4e8796da3eba7084b213724edb99f7b.png

Жмем Enter

Иходники библиотеки начинают скачиваться

image.png.03a0c56e13fa676ed7e7c519e1023e75.png

После окончания в папке src должно появиться множество файлов, окно с git можно закрыть

image.png.3c892920074902c9d55fc6f60d3d4c5e.png

Теперь нам потребуется:

Microsoft Visual Studio – можете скачать с официального сайта последнюю версию Community, при установке укажите, что собираетесь программировать на C++ (и на чем угодно еще, если хотите). Обязательно установите английский языковой пакет.

Вот тут небольшая справка по установке

Если у кого-то уже студия стоит, то нужно запустить инсталлер, в нём выбрать языковые пакеты и добавить английский.

Скрин для всех:

image.png.41e1b07f0f26694459ccbef39d216c75.png

Без английского ничего не получится, уот так вот.

Gperf – просто скачайте и кликайте да, да, да, далее. Потом нужно будет добавить путь в переменные окружения:

image.png.cf7a5ce41a271b54608119b93c9cc938.png

vcpkg – тут сложнее, создайте папку C:\vcpkg, на ней правой кнопкой, Git Bash Here, в окне вбейте

git clone https://github.com/Microsoft/vcpkg.git .

image.png.2ceeb33f2c8ed31e1aea018c218acaf3.png

Жмете Enter, ждете, пока скачается, потом НЕ закрывайте окно (а если закрыли, снова правой кнопкой на папке -> Git Bash Here). В этом окне выполните команду:

./bootstrap-vcpkg.bat

image.png.6784ada5ce0f172029b2dab3f141aeee.png

Будет довольно много движений, в итоге всё установится

image.png.f822923d7c4e3856ff29984aa10783c4.png

Теперь установим всё, что нужно для сборки исходников телеграмма. В этом же окне выполним команду:

./vcpkg.exe install openssl:x64-windows openssl:x86-windows zlib:x64-windows zlib:x86-windows

Если увидите что-то такое, то пролистайте статью вверх – вам нужна Visual Studio с английским языковым пакетом:

image.png.5054df1838f5690c98fec0d1081a3b4a.png

А вообще, если процесс пошел, то на этом этапе можно пойти покушать, это надолго. Нормальная установка выглядит как то так:

image.png.15a1f7fd867ce9bceb1a5dd86040b927.png

И заканчивается примерно так:

image.png.c2b88b766de89acb05a8e222a18949e4.png

Скачайте и установите CMake. При установке выберите вот этот пункт:

image.png.7b58d38ed4549f3a7203c0826bd268e2.png

Теперь давайте попробуем собрать исходники в работающую библиотеку. Для этого запустим командную строку (cmd), в ней выполним следующие команды:

cd C:\code\examples\telegram\src\cmake
cmake -DCMAKE_TOOLCHAIN_FILE=C:\vcpkg\scripts\buildsystems\vcpkg.cmake -A x64 ..
cmake --build . --config Release

Если вы хотите 32 битную версию, уберите из строк выше -A x64, скомпилируется 32

Итог выполнения сборки будет таким:

image.png.e612914f602970fc961ef1dcf97ddcf0.png

А в папке Cmake\Debug должны появиться нужные нам DLL

image.png.c0a17304e9159f869b4d8d7efaa555f7.png

Нас, в частности, интересует файл tdjson.dll

На этом этапе работа завершена - мы получили файл tdjson.dll и можем работать с ним из любого языка программирования, который умеет вызывать сишные функции. В нашем случае это Python.

Небольшая ремарка - если вы собираетесь писать код на C++, Java, .Net, то достаточно подключить в проект соответствующие файлы.

Примеры работы на разных языках есть в том же скачанном репозитории, C:\code\examples\telegram\src\example

  • Like 2

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Этап 2 - подготовка

На этом этапе подразумевается, что у вас уже есть файл tdjson.dll - вы или скомпилировали его, или взяли мой, или скачали откуда-то из интернета для своей платформы.

Рекомендую положить его в C:\Windows\System32 (нужны права администратора), а так же скопировать в папку с программой C:\code\examples\telegram. 

Запустите командную строку от имени администратора, и в ней выполните команду 

regsvr32 tdjson.dll

Впрочем, оно может выдавать ошибки, и не факт, что по делу, так что можете пока не обращать на ошибки внимания.

Теперь нужно завести application в телеграмме, что бы можно было использовать вашу программу.

Перейдите по этой ссылке, увидите такое:

image.png.503df87778a1cf5260d83321ca86db4a.png

Перейдите в API development tools

image.png.4a154594bfbc5c652d78e817f30008f6.png

Заполните нужные поля и введите описание (platform - Desktop)

image.png.7805e82bb770fa3e7515be2fccdefc31.png

И на следующем шагу получите API ключи и всё такое:

image.png.3fb0fe2a9acc9566a08334ac44157671.png

Отлично. Теперь можно полноценно пользоваться телеграммом.

  • Like 2

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Этап 3 - непосредственно запуск и работа

В директории C:\code\examples\telegram создайте файл main.py со следующим содержимым:

# -*- coding: utf-8 -*-

#
# Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#
from ctypes.util import find_library
from ctypes import *
import json
import sys

API_KEY = 111111
API_HASH = '........'
PHONE_NUMBER = '+7913212313'

# load shared library
tdjson_path = find_library("tdjson") or "tdjson.dll"

if tdjson_path is None:
    print('can\'t find tdjson library')
    quit()
tdjson = CDLL(tdjson_path)

# load TDLib functions from shared library
td_json_client_create = tdjson.td_json_client_create
td_json_client_create.restype = c_void_p
td_json_client_create.argtypes = []

td_json_client_receive = tdjson.td_json_client_receive
td_json_client_receive.restype = c_char_p
td_json_client_receive.argtypes = [c_void_p, c_double]

td_json_client_send = tdjson.td_json_client_send
td_json_client_send.restype = None
td_json_client_send.argtypes = [c_void_p, c_char_p]

td_json_client_execute = tdjson.td_json_client_execute
td_json_client_execute.restype = c_char_p
td_json_client_execute.argtypes = [c_void_p, c_char_p]

td_json_client_destroy = tdjson.td_json_client_destroy
td_json_client_destroy.restype = None
td_json_client_destroy.argtypes = [c_void_p]

td_set_log_file_path = tdjson.td_set_log_file_path
td_set_log_file_path.restype = c_int
td_set_log_file_path.argtypes = [c_char_p]

td_set_log_max_file_size = tdjson.td_set_log_max_file_size
td_set_log_max_file_size.restype = None
td_set_log_max_file_size.argtypes = [c_longlong]

td_set_log_verbosity_level = tdjson.td_set_log_verbosity_level
td_set_log_verbosity_level.restype = None
td_set_log_verbosity_level.argtypes = [c_int]

fatal_error_callback_type = CFUNCTYPE(None, c_char_p)

td_set_log_fatal_error_callback = tdjson.td_set_log_fatal_error_callback
td_set_log_fatal_error_callback.restype = None
td_set_log_fatal_error_callback.argtypes = [fatal_error_callback_type]

# initialize TDLib log with desired parameters
def on_fatal_error_callback(error_message):
    print('TDLib fatal error: ', error_message)

td_set_log_verbosity_level(2)
c_on_fatal_error_callback = fatal_error_callback_type(on_fatal_error_callback)
td_set_log_fatal_error_callback(c_on_fatal_error_callback)

# create client
client = td_json_client_create()

# simple wrappers for client usage
def td_send(query):
    query = json.dumps(query).encode('utf-8')
    td_json_client_send(client, query)

def td_receive():
    result = td_json_client_receive(client, 1.0)
    if result:
        result = json.loads(result.decode('utf-8'))
    return result

def td_execute(query):
    query = json.dumps(query).encode('utf-8')
    result = td_json_client_execute(client, query)
    if result:
        result = json.loads(result.decode('utf-8'))
    return result

td_send({'@type': 'getAuthorizationState', '@extra': 1.01234})

chat_ids = []
chats = []
choosen_chat_id = 0

non_bmp_map = dict.fromkeys(range(0x10000, sys.maxunicode + 1), 0xfffd)

# main events cycle
while True:
    event = td_receive()
    if event:
        # if client is closed, we need to destroy it and create new client
        if event['@type'] == 'updateAuthorizationState' and event['authorization_state']['@type'] == 'authorizationStateClosed':
            break

        if event['@type'] in ['updateSupergroup', 'updateNewChat', 'updateChatLastMessage', 'updateUser']:
            continue
        if  event.get('@extra') == 1001001:
            chat_ids = event['chat_ids']
            for chat_id in chat_ids:
                td_send({'@type':'getChat', 'chat_id':chat_id, 'extra':1001011})
        if event['@type'] == 'updateNewMessage' and event['message']['chat_id'] == choosen_chat_id:
            
            message_type = event['message']['content']['@type']
            print("*"*80)
            print("Получено:", message_type)
            print("-"*80)
            if message_type == 'messageText':
                message_text = event['message']['content']['text']['text'].translate(non_bmp_map)
                print(message_text)
                
                td_send({'@type':'sendMessage', 'chat_id':target_chat_id, 'input_message_content': {
						 '@type': 'inputMessageText',
						 'text': {
						 '@type': 'formattedText',
						 'text': message_text
						}}}
                         )
                
                
            print("-"*80)
            print(event)
            
            print("*"*80)
            
        if event['@type'] == 'chat':
            title = event['title'].translate(non_bmp_map)
            print('Получен чат', len(chats),  title, event['id'])
            chats.append({'title': title, 'id': event['id']})
            if len(chats) == len(chat_ids):
                chat_id = int(input('Выберите чат для мониторинга (1 - {m_ch})'.format(m_ch=len(chats))))
                print("Выбран чат", chats[chat_id])
                choosen_chat_id = chats[chat_id]['id']

                chat_id = int(input('Выберите чат для пересылки (1 - {m_ch})'.format(m_ch=len(chats))))
                print("Выбран чат", chats[chat_id])
                target_chat_id = chats[chat_id]['id']

                if target_chat_id == choosen_chat_id:
                    print("Нельзя два раза выбрать одно и то же!!!!")
                    break
                
        if event['@type'] == "authorizationStateWaitTdlibParameters":
            td_send({'@type': 'setTdlibParameters',
			'parameters': {'use_test_dc': False,
			'api_id':API_KEY,
			'api_hash': API_HASH,
			'device_model': 'Desktop',
			'system_version': 'Unknown',
			'application_version': "0.0",
			'system_language_code': 'en',
			'database_directory': 'Database',
			'files_directory': 'Files',
			'use_file_database': True,
			'use_chat_info_database': True,
			'use_message_database': True,
			}
			})
            td_send({'@type': 'checkDatabaseEncryptionKey',})
            
        elif event['@type'] == 'updateAuthorizationState' and  event['authorization_state']['@type'] == 'authorizationStateWaitPhoneNumber':
            td_send({'@type': 'setAuthenticationPhoneNumber', 'phone_number': PHONE_NUMBER})

        elif event['@type'] == 'updateAuthorizationState' and  event['authorization_state']['@type'] == 'authorizationStateWaitCode':
            code = input("Enter code:")
            td_send({'@type': 'checkAuthenticationCode', 'code': code})

        elif event['@type'] == 'updateAuthorizationState'    and  event['authorization_state']['@type'] == 'authorizationStateReady':
            td_send({'@type': 'getChats',  'limit': 100, 'offset_order':2**63-1, '@extra': 1001001})
            td_send({'@type': 'getMe', '@extra': 1001111})
            
        sys.stdout.flush()

td_json_client_destroy(client)

Я взял пример из C:\code\examples\telegram\src\example\python и подогнал под себя.

Тут смысл такой - вам нужно в строках 

API_KEY = 111111
API_HASH = '........'
PHONE_NUMBER = '+7913212313'

указать API_KEY и Hash из телеграмма, которые вы получили на этапе 2. Так же нужно указать свой номер, под которым вы зарегистрированы в телеграмме.

Для чистоты эксперимента желательно что бы телеграм был запущен у вас на компе или телефоне, что бы туда пришел код подтверждения - через СМС я не добавлял.

Этот скрипт нужно запустить из питона 64 битной версии! Это важно.

image.png.56b9df09c82f035c0f44e3f2f98b28d0.png

Открываете в Idle, меняете апи-ключи и телефон и нажимаете F5 - скрипт запускается, при первом запуске должна появиться надпись

Enter code:

А в телеграм придет сообщение с кодом. 

image.png.af6e51bff40c85c86ed53b58bf30314d.png

Введите код, и в телеграм придет второе сообщение о найденом новом устройстве.

Потом, и при любом другом запуске, вам будет выдаваться список из 100 ваших чатов, примерно в том же порядке, в каком вы их видите в телеграмме, сначала прикрепленные чаты, потом самые свежеобновленные.

image.thumb.png.f83324fdfff1f76009f6279fd2897861.png

А потом, на основании списка, вам будет предложено выбрать чат/канал источник, и чат/канал, куда пересылать сообщения

image.png.61d77ec811c6987b4bb945324c61f3ff.png

В указанном примере, все текстовые сообщения из канала Mash будут от моего имени переправляться в группу Баблофил. Разумеется, это только для примера.

 

  • Like 2

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Так-с, ну собственно задача выполнена. Немного об ограничениях - сейчас берутся 100 самых свежих чатов, из-за особенностей работы АПИ. Можно сделать больше, но это нужно больше кода писать, сейчас не вижу в этом смысла. Оба канала - источник и приемник, должны быть в первой сотне. Можете их прикрепить, тогда они всегда гарантировано будут сверху. Можете захардкодить ID каналов, что бы сразу пересылать из одного в другой.

Еще бот пересылает текстовые сообщения - пусть с картинками и прочим. Это большинство сообщений телеграмма в большинстве каналов, но бот не будет пересылать пост-картинку. Если выложили картинку, с описанием или нет, бот её проигнорит. Можно, конечно, добавить обработку и этого, но опять же нужно разбираться с этим и дописывать код.

Ну и еще разного рода смайлики могут быть обрезаны/заменены, т.к. TK, на котором написан Idle, не может их отображать.

Ну а в остальном всё работает из коробки и задел у такого большой, так что удачи, что бы вы там не планировали 🙂

Прикладываю файлы

Клиент telegram, скрипт для копирования сообщений канала

  • Like 2

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Подтверждаю!
Всё работает, если делать по подробно описанному мануалу! А если что-то идёт не так - сначала ВНИМАТЕЛЬНО перечитайте мануал, а потом уже задавайте вопросы и просите помощи!) Благодарю за проделанную работу и отзывчивость!

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
1 час назад, sunra1se сказал:

Подтверждаю!
Всё работает, если делать по подробно описанному мануалу! А если что-то идёт не так - сначала ВНИМАТЕЛЬНО перечитайте мануал, а потом уже задавайте вопросы и просите помощи!) Благодарю за проделанную работу и отзывчивость!

Кстати, для тех кто столкнётся с проблемой смайликов: 
UnicodeEncodeError: 'UCS-2' codec can't encode characters in position 597-597: Non-BMP character not supported in Tk
Варианта два.
Первый - простой и быстрый - уберите в коде команду print.
Второй - просто скачайте PyCharm, создайте новый проект и запустите код бота там.

Сам пошел по второму варианту, так как в таких вопросах чайник)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас

×