Skip to content
This repository was archived by the owner on Feb 11, 2026. It is now read-only.

Commit 20f8a1c

Browse files
Merge pull request #43 from Rise0x00/rise0x00/refactoring
Refactoring telegram bridge
2 parents b325c95 + e9c72bd commit 20f8a1c

File tree

1 file changed

+113
-139
lines changed

1 file changed

+113
-139
lines changed

examples/telegram_bridge.py

Lines changed: 113 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -1,194 +1,168 @@
1-
# Всякая всячина
2-
import asyncio
3-
4-
# Библиотека для работы с файлами
5-
from io import BytesIO
6-
7-
import aiohttp
8-
9-
# Импорты библиотеки aiogram для TG-бота
10-
from aiogram import Bot, Dispatcher, types
1+
# УСТАНОВИТЬ ЗАВИСИМОСТИ - pip install maxapi-python aiogram==3.22.0
2+
import asyncio # Для асинхронности
3+
import aiohttp # Для асинхронных реквестов
4+
from io import BytesIO # Для хранения ответов файлом в RAM
5+
from aiogram import Bot, Dispatcher, types # Для ТГ
116

127
# Импорты библиотеки PyMax
13-
from pymax import MaxClient, Message, Photo
8+
from pymax import MaxClient, Message
149
from pymax.types import FileAttach, PhotoAttach, VideoAttach
1510

16-
# УСТАНОВИТЬ ЗАВИСИМОСТИ - pip install maxapi-python aiogram==3.22.0
17-
18-
19-
# Настройки ботов
2011
PHONE = "+79998887766" # Номер телефона Max
2112
telegram_bot_TOKEN = "token" # Токен TG-бота
2213

23-
chats = { # В формате айди чата в Max: айди чата в Telegram (айди чата Max можно узнать из ссылки на чат в веб версии web.max.ru)
14+
# Формат: id чата в Max: id чата в Tg
15+
# (Id чата в Max можно узнать из ссылки на чат в веб версии web.max.ru)
16+
chats = {
2417
-68690734055662: -1003177746657,
2518
}
2619

27-
28-
# Создаём зеркальный массив для отправки из Telegram в Max
20+
# Создаём зеркальный словарь для отправки из Telegram в Max
2921
chats_telegram = {value: key for key, value in chats.items()}
3022

23+
max_client = MaxClient(phone=PHONE, work_dir="cache", reconnect=True) # Инициализация клиента Max
3124

32-
# Инициализация клиента MAX
33-
client = MaxClient(phone=PHONE, work_dir="cache", reconnect=True)
34-
35-
36-
# Инициализация TG-бота
37-
telegram_bot = Bot(token=telegram_bot_TOKEN)
25+
telegram_bot = Bot(token=telegram_bot_TOKEN) # Инициализация TG-бота
3826
dp = Dispatcher()
3927

28+
async def download_file_bytes(url: str) -> BytesIO:
29+
"""Загружает файл по URL и возвращает его в виде BytesIO."""
30+
async with aiohttp.ClientSession() as session:
31+
async with session.get(url) as response:
32+
response.raise_for_status() # Кидаем exception в случае ошибки HTTP
33+
file_bytes = BytesIO(await response.read()) # Читаем ответ в файлоподобный объект
34+
file_bytes.name = response.headers.get("X-File-Name") # Ставим "файлу" имя из заголовков ответа
35+
return file_bytes
4036

4137
# Обработчик входящих сообщений MAX
42-
@client.on_message()
38+
@max_client.on_message()
4339
async def handle_message(message: Message) -> None:
4440
try:
45-
tg_id = chats[message.chat_id]
41+
tg_id = chats[message.chat_id] # pyright: ignore[reportArgumentType]
4642
except KeyError:
4743
return
4844

49-
sender = await client.get_user(user_id=message.sender)
50-
51-
if message.attaches:
52-
for attach in message.attaches:
53-
# Проверка на видео
54-
if isinstance(attach, VideoAttach):
55-
async with aiohttp.ClientSession() as session:
56-
try:
57-
# Получаем видео по айди
58-
video = await client.get_video_by_id(
59-
chat_id=message.chat_id,
60-
message_id=message.id,
61-
video_id=attach.video_id,
62-
)
63-
64-
# Загружаем видео по URL
65-
async with session.get(video.url) as response:
66-
response.raise_for_status() # Проверка на ошибки HTTP
67-
video_bytes = BytesIO(await response.read())
68-
video_bytes.name = response.headers.get("X-File-Name")
69-
70-
# Отправляем видео через телеграм бота
71-
await telegram_bot.send_video(
72-
chat_id=tg_id,
73-
caption=f"{sender.names[0].name}: {message.text}",
74-
video=types.BufferedInputFile(
75-
video_bytes.getvalue(), filename=video_bytes.name
76-
),
77-
)
78-
79-
# Очищаем память
80-
video_bytes.close()
81-
82-
except aiohttp.ClientError as e:
83-
print(f"Ошибка при загрузке видео: {e}")
84-
except Exception as e:
85-
print(f"Ошибка при отправке видео: {e}")
86-
87-
# Проверка на изображение
88-
elif isinstance(attach, PhotoAttach):
89-
async with aiohttp.ClientSession() as session:
90-
try:
91-
# Загружаем изображение по URL
92-
async with session.get(attach.base_url) as response:
93-
response.raise_for_status() # Проверка на ошибки HTTP
94-
photo_bytes = BytesIO(await response.read())
95-
photo_bytes.name = response.headers.get("X-File-Name")
96-
97-
# Отправляем фото через телеграм бота
98-
await telegram_bot.send_photo(
99-
chat_id=tg_id,
100-
caption=f"{sender.names[0].name}: {message.text}",
101-
photo=types.BufferedInputFile(
102-
photo_bytes.getvalue(), filename=photo_bytes.name
103-
),
104-
)
105-
106-
# Очищаем память
107-
photo_bytes.close()
108-
109-
except aiohttp.ClientError as e:
110-
print(f"Ошибка при загрузке изображения: {e}")
111-
except Exception as e:
112-
print(f"Ошибка при отправке фото: {e}")
113-
114-
# Проверка на файл
115-
elif isinstance(attach, FileAttach):
116-
async with aiohttp.ClientSession() as session:
117-
try:
118-
# Получаем файл по айди
119-
file = await client.get_file_by_id(
120-
chat_id=message.chat_id,
121-
message_id=message.id,
122-
file_id=attach.file_id,
123-
)
124-
125-
# Загружаем файл по URL
126-
async with session.get(file.url) as response:
127-
response.raise_for_status() # Проверка на ошибки HTTP
128-
file_bytes = BytesIO(await response.read())
129-
file_bytes.name = response.headers.get("X-File-Name")
130-
131-
# Отправляем файл через телеграм бота
132-
await telegram_bot.send_document(
133-
chat_id=tg_id,
134-
caption=f"{sender.names[0].name}: {message.text}",
135-
document=types.BufferedInputFile(
136-
file_bytes.getvalue(), filename=file_bytes.name
137-
),
138-
)
139-
140-
# Очищаем память
141-
file_bytes.close()
142-
143-
except aiohttp.ClientError as e:
144-
print(f"Ошибка при загрузке файла: {e}")
145-
except Exception as e:
146-
print(f"Ошибка при отправке файла: {e}")
45+
sender = await max_client.get_user(user_id=message.sender) # pyright: ignore[reportArgumentType]
46+
47+
if message.attaches: # Проверка на наличие вложений
48+
for attach in message.attaches: # Перебор всех вложений
49+
if isinstance(attach, VideoAttach): # Проверка на видео
50+
try:
51+
# Получаем видео из max по айди
52+
video = await max_client.get_video_by_id(
53+
chat_id=message.chat_id, # pyright: ignore[reportArgumentType]
54+
message_id=message.id,
55+
video_id=attach.video_id
56+
)
57+
58+
# Загружаем видео по URL
59+
video_bytes = await download_file_bytes(video.url) # pyright: ignore[reportOptionalMemberAccess]
60+
61+
# Отправляем видео через тг
62+
await telegram_bot.send_video(
63+
chat_id=tg_id,
64+
caption=f"{sender.names[0].name}: {message.text}", # pyright: ignore[reportOptionalMemberAccess]
65+
video=types.BufferedInputFile(video_bytes.getvalue(), filename=video_bytes.name)
66+
)
67+
68+
video_bytes.close() # Удаляем видео из памяти
69+
70+
except aiohttp.ClientError as e:
71+
print(f"Ошибка при загрузке видео: {e}")
72+
except Exception as e:
73+
print(f"Ошибка при отправке видео: {e}")
74+
75+
elif isinstance(attach, PhotoAttach): # Проверка на фото
76+
try:
77+
# Загружаем изображение по URL
78+
photo_bytes = await download_file_bytes(attach.base_url) # pyright: ignore[reportOptionalMemberAccess]
79+
80+
# Отправляем фото через тг бота
81+
await telegram_bot.send_photo(
82+
chat_id=tg_id,
83+
caption=f"{sender.names[0].name}: {message.text}", # pyright: ignore[reportOptionalMemberAccess]
84+
photo=types.BufferedInputFile(photo_bytes.getvalue(), filename=photo_bytes.name)
85+
)
86+
87+
photo_bytes.close() # Удаляем фото из памяти
88+
89+
except aiohttp.ClientError as e:
90+
print(f"Ошибка при загрузке изображения: {e}")
91+
except Exception as e:
92+
print(f"Ошибка при отправке фото: {e}")
93+
94+
elif isinstance(attach, FileAttach): # Проверка на файл
95+
try:
96+
# Получаем файл по айди
97+
file = await max_client.get_file_by_id(
98+
chat_id=message.chat_id, # pyright: ignore[reportArgumentType]
99+
message_id=message.id,
100+
file_id=attach.file_id
101+
)
102+
103+
# Загружаем файл по URL
104+
file_bytes = await download_file_bytes(file.url) # pyright: ignore[reportOptionalMemberAccess]
105+
106+
# Отправляем файл через тг бота
107+
await telegram_bot.send_document(
108+
chat_id=tg_id,
109+
caption=f"{sender.names[0].name}: {message.text}", # pyright: ignore[reportOptionalMemberAccess]
110+
document=types.BufferedInputFile(file_bytes.getvalue(), filename=file_bytes.name)
111+
)
112+
113+
file_bytes.close() # Удаляем файл из памяти
114+
115+
except aiohttp.ClientError as e:
116+
print(f"Ошибка при загрузке файла: {e}")
117+
except Exception as e:
118+
print(f"Ошибка при отправке файла: {e}")
147119
else:
148120
await telegram_bot.send_message(
149-
chat_id=tg_id, text=f"{sender.names[0].name}: {message.text}"
121+
chat_id=tg_id,
122+
text=f"{sender.names[0].name}: {message.text}" # pyright: ignore[reportOptionalMemberAccess]
150123
)
151124

152125

153126
# Обработчик запуска клиента, функция выводит все сообщения из чата "Избранное"
154-
@client.on_start
127+
@max_client.on_start
155128
async def handle_start() -> None:
156129
print("Клиент запущен")
157130

158131
# Получение истории сообщений
159-
history = await client.fetch_history(chat_id=0)
132+
history = await max_client.fetch_history(chat_id=0)
160133
if history:
161134
for message in history:
162-
user = await client.get_user(message.sender)
135+
user = await max_client.get_user(message.sender) # pyright: ignore[reportArgumentType]
163136
if user:
164137
print(f"{user.names[0].name}: {message.text}")
165138

166139

167-
# Обработчик сообщений Telegram
140+
# Обработчик сообщений из Telegram
168141
@dp.message()
169142
async def handle_tg_message(message: types.Message, bot: Bot) -> None:
170-
max_id = chats_telegram[message.chat.id]
171-
await client.send_message(
172-
chat_id=max_id,
173-
text=f"{message.from_user.first_name}: {message.text}",
174-
notify=True,
175-
)
176-
143+
try:
144+
max_id = chats_telegram[message.chat.id]
145+
await max_client.send_message(
146+
chat_id=max_id,
147+
text=f"{message.from_user.first_name}: {message.text}", # pyright: ignore[reportOptionalMemberAccess]
148+
)
149+
except KeyError:
150+
return
177151

178152
# Раннер ботов
179153
async def main() -> None:
180154
# TG-бот в фоне
181155
telegram_bot_task = asyncio.create_task(dp.start_polling(telegram_bot))
182156

183157
try:
184-
await client.start()
158+
await max_client.start()
185159
finally:
186-
await client.close()
160+
await max_client.close()
187161
telegram_bot_task.cancel()
188162

189163

190164
if __name__ == "__main__":
191165
try:
192166
asyncio.run(main())
193167
except KeyboardInterrupt:
194-
print("Программа остановлена пользователем.")
168+
print("Программа остановлена пользователем.")

0 commit comments

Comments
 (0)