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

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

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

Всем привет!

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

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

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

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

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

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

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

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


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

Этап 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

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


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

Этап 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

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

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


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

Этап 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 будут от моего имени переправляться в группу Баблофил. Разумеется, это только для примера.

 

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


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

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

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

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

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

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

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

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


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

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

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


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

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

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

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

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


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

Еще не использовал бота но возник вопрос он оставляет ссылку на канал с которого скопировал сообщение?

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


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

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

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

у тебя ошибок с кеннектом не было ?

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


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

вдруг кто подскажет как сделать фильтр сообщений если встречается ссылка что бы сообщение не пересылалось .?((((

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


Ссылка на сообщение
Поделиться на других сайтах
27.07.2019 в 12:28, mav3rick сказал:

Еще не использовал бота но возник вопрос он оставляет ссылку на канал с которого скопировал сообщение?

Нет, не оставляет

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


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

Нет, не оставляет

да я уже тестирую . спасибо только фильтр осталось понять как сделать (

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


Ссылка на сообщение
Поделиться на других сайтах
28.01.2019 в 18:31, admin сказал:

if message_type == 'messageText':

    message_text = event['message']['content']['text']['text'].translate(non_bmp_map)

Сюда нужно добавить какое то условие, например если нужны сообщения со словом hello, то как то так

if message_type == 'messageText':
                message_text = event['message']['content']['text']['text'].translate(non_bmp_map)
                #print(message_text)
                if 'hello' in message_text:
                  td_send({'@type':'sendMessage', 'chat_id':target_chat_id, 'input_message_content': {
                           '@type': 'inputMessageText',
                           'text': {
                           '@type': 'formattedText',
                           'text': message_text
                          }}}
                           )

 

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


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

Сюда нужно добавить какое то условие, например если нужны сообщения со словом hello, то как то так


if message_type == 'messageText':
                message_text = event['message']['content']['text']['text'].translate(non_bmp_map)
                #print(message_text)
                if 'hello' in message_text:
                  td_send({'@type':'sendMessage', 'chat_id':target_chat_id, 'input_message_content': {
                           '@type': 'inputMessageText',
                           'text': {
                           '@type': 'formattedText',
                           'text': message_text
                          }}}
                           )

 

а если не нужны сообщения со ссылками на сайт ?

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


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

Можно указать часть названия сайта, любое слово которое может встречаться в тексте

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


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

    Failed to fetch update: Unknown constructor found 0x450b7115
74ae4240 1cb5c415 00000001 62ba04d9 44f9b43d 00000100 00032d3f 320aa588 bddde532 460c7fec 5d58745f d192d072 d0b5d081 bfd020bc b8d080d1 b5d0b2d0
202e82d1 bcd098d0 8ed1b5d0 81d182d1 d0208fd1 d0bed0bb 20b8d0b3 d02081d1 d083d1ba d0b0d0ba 20b8d0bc b0d0bdd0 d084d120 d0202eb1 d0bed0a2 d08cd1bb
20bed0ba bed0bfd0 d0b4d020 d1bbd0b5 b2d02083 d0bbd020 d087d1b8 0083d1ba 000420fb 00000001 1cb5c415 00000001 2e13f4c3 00100062 320aa588 654c4008
7572446e 00000067 d559d8c8 1b31a7ab 320aa588 53d69076 00000002 0fb7cc3b 00000000 0001438d a51becd9 bbd67467 53d69076 00000002 0fb7cc3b 00000000
0001438f 3b6f23c4 7cff3e91 e26f42f1 1cb5c415 00000001 450b7115 00001540 460c7fec 20424618 6944202d 2e707361 206f7270 5323202d 65736e65 00000079
6662660a 626b6375 006b6f6f 6153276a 53d69076 00000002 0fb7fdef 00000000 0001c00d 2fb5cd35 157812c3 53d69076 00000002 0fb7fdef 00000000 0001c00f
0d2977bb 6ed8f138 5aaa8d1c 00000000 5d58745f 00000000

 

 

вот такие ошибки валятся в чем может быть дело?

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


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

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Гость
Ответить в тему...

×   Вставлено в виде отформатированного текста.   Вставить в виде обычного текста

  Разрешено не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставить изображения напрямую. Загрузите или вставьте изображения по ссылке.


×
×
  • Создать...