USER
Вот мой telegram бот:
👉
import os
import asyncio
import logging
from collections import defaultdict
from dotenv import load_dotenv
from telethon import TelegramClient, events, Button
# Загрузка переменных окружения
load_dotenv()
API_ID = os.getenv("API_ID")
API_HASH = os.getenv("API_HASH")
BOT_TOKEN = os.getenv("BOT_TOKEN")
CHANNEL_ID = int(os.getenv("CHANNEL_ID"))
INTERIM_CHAT_ID = int(os.getenv("INTERIM_CHAT_ID"))
ALLOWED_USER_ID = int(os.getenv("ALLOWED_USER_ID"))
# Инициализация клиента
client = TelegramClient('bot', API_ID, API_HASH)
client.start(bot_token=BOT_TOKEN)
# Настройка логирования
logging.basicConfig(filename="bot.log", level=logging.INFO)
# Словари для хранения сообщений
pending_albums = {}
pending_messages = {}
grouped_messages = defaultdict(list)
ALBUM_TIMEOUT = 1.0
@client.on(events.NewMessage(func=lambda e: e.is_private and e.sender_id == ALLOWED_USER_ID))
async def handle_message(event):
message = event.message
if message.text and message.text.startswith('/'):
return
if message.grouped_id:
group_id = str(message.grouped_id)
grouped_messages[group_id].append(message)
if len(grouped_messages[group_id]) == 1:
asyncio.create_task(schedule_group_send(group_id))
else:
# Отправляем само сообщение в промежуточный канал
sent_message = await client.send_message(
INTERIM_CHAT_ID,
message
)
# Создаём инлайн-кнопки
buttons = [
[
Button.inline("✅ Отправить", data=f"send_message:{message.id}"),
Button.inline("❌ Отменить", data=f"cancel_message:{message.id}")
]
]
# Отправляем сообщение с кнопками
buttons_message = await client.send_message(
INTERIM_CHAT_ID,
"Выберите действие для сообщения:",
buttons=buttons
)
pending_messages[message.id] = {
'interim_message': sent_message,
'buttons_message_id': buttons_message.id,
'sender_id': message.sender_id,
'message': message
}
await event.delete()
async def schedule_group_send(group_id):
await asyncio.sleep(ALBUM_TIMEOUT)
if group_id in grouped_messages:
messages = grouped_messages.pop(group_id)
# Создаём списки для медиа и подписей
media_list = [msg.media for msg in messages]
caption = "\n".join([msg.text for msg in messages if msg.text])
# Отправляем альбом в промежуточный канал как единое целое
sent_messages = await client.send_file(
INTERIM_CHAT_ID,
media_list,
caption=caption,
silent=True
)
# Создаём инлайн-кнопки для альбома
buttons = [
[
Button.inline("✅ Отправить", data=f"send_album:{group_id}"),
Button.inline("❌ Отменить", data=f"cancel_album:{group_id}")
]
]
# Отправляем сообщение с кнопками после альбома
buttons_message = await client.send_message(
INTERIM_CHAT_ID,
"Выберите действие для альбома:",
buttons=buttons
)
pending_albums[group_id] = {
'message_ids': [msg.id for msg in sent_messages],
'buttons_message_id': buttons_message.id,
'sender_id': messages[0].sender_id,
'messages': messages
}
# Удаляем исходные сообщения
for msg in messages:
await msg.delete()
@client.on(events.CallbackQuery)
async def callback_handler(event):
data = event.data.decode('utf-8')
if ':' not in data:
return
command, identifier = data.split(':', 1)
if command in ['send_album', 'cancel_album']:
pending = pending_albums.get(identifier)
if not pending or pending['sender_id'] != event.sender_id:
await event.answer("У вас нет доступа к этой функции.", alert=True)
return
if command == 'send_album':
# Пересылаем все сообщения альбома из промежуточного канала в основной канал
await client.forward_messages(
CHANNEL_ID,
pending['message_ids'],
from_peer=INTERIM_CHAT_ID
)
# Удаляем сообщения альбома и кнопки
await client.delete_messages(INTERIM_CHAT_ID, pending['message_ids'])
await client.delete_messages(INTERIM_CHAT_ID, [pending['buttons_message_id']])
del pending_albums[identifier]
await event.answer("Альбом успешно отправлен в канал.", alert=True)
elif command == 'cancel_album':
# Удаляем сообщения альбома и кнопки
await client.delete_messages(INTERIM_CHAT_ID, pending['message_ids'])
await client.delete_messages(INTERIM_CHAT_ID, [pending['buttons_message_id']])
del pending_albums[identifier]
await event.answer("Отправка альбома отменена.", alert=True)
elif command in ['send_message', 'cancel_message']:
message_id = int(identifier)
pending = pending_messages.get(message_id)
if not pending or pending['sender_id'] != event.sender_id:
await event.answer("У вас нет доступа к этой функции.", alert=True)
return
if command == 'send_message':
# Пересылаем сообщение из промежуточного канала в основной канал
await client.forward_messages(
CHANNEL_ID,
pending['interim_message'].id,
from_peer=INTERIM_CHAT_ID
)
# Удаляем оба сообщения из промежуточного канала
await client.delete_messages(INTERIM_CHAT_ID, [pending['interim_message'].id, pending['buttons_message_id']])
del pending_messages[message_id]
await event.answer("Сообщение отправлено в канал.", alert=True)
elif command == 'cancel_message':
# Удаляем оба сообщения
await client.delete_messages(INTERIM_CHAT_ID, [pending['interim_message'].id, pending['buttons_message_id']])
del pending_messages[message_id]
await event.answer("Отправка отменена.", alert=True)
print("Бот запущен!")
client.run_until_disconnected()
👈
Как его пошагово шаг за шагом развернуть на PythonAnywhere 24/7. У меня есть .env, но нету requirements.txt, как его быстро сделать в терминале со всеми зависимостями➡️ASSISTANT
Развернуть вашего Telegram-бота на PythonAnywhere и настроить его для непрерывной работы можно, следуя следующим пошаговым инструкциям. В этом руководстве я также покажу, как быстро создать `requirements.txt` для вашего проекта.
### Шаг 1: Создайте аккаунт на PythonAnywhere
1. Перейдите на [PythonAnywhere](https://www.pythonanywhere.com/) и зарегистрируйтесь, если у вас ещё нет аккаунта.
2. Войдите в свой аккаунт.
### Шаг 2: Подготовьте файлы вашего бота
#### 2.1. Структура файлов
Убедитесь, что у вас есть следующие файлы:
- `bot.py` — ваш скрипт бота.
- `.env` — файл с переменными окружения.
#### 2.2. Создайте архив проекта
Если у вас файлы находятся локально, создайте ZIP-архив с этими файлами для удобной загрузки.
### Шаг 3: Загрузите файлы на PythonAnywhere
1. Перейдите на вкладку **Files** в вашем кабинете PythonAnywhere.
2. Перейдите в директорию, где вы хотите разместить бот (например, `/home/yourusername/telegram_bot/`).
3. Нажмите на кнопку **Upload a file** и загрузите `bot.py` и `.env`. Если у вас ZIP-архив, загрузите его и затем распакуйте с помощью консоли.
### Шаг 4: Создайте виртуальное окружение
Использование виртуального окружения изолирует зависимости вашего проекта.
1. Перейдите во вкладку **Consoles** и откройте новую консоль Bash.
2. Создайте виртуальное окружение (например, с именем `venv`):
```bash
python3 -m venv venv
```
3. Активируйте виртуальное окружение:
```bash
source venv/bin/activate
```
### Шаг 5: Создайте `requirements.txt`
Поскольку у вас нет `requirements.txt`, вы можете создать его автоматически, используя `pip`.
1. В активированном виртуальном окружении установите все необходимые библиотеки, если они ещё не установлены:
```bash
pip install telethon python-dotenv
```
2. Проверьте установленные пакеты и создайте `requirements.txt`:
```bash
pip freeze > requirements.txt
```
Это создаст файл `requirements.txt` с перечнем всех установленных зависимостей.
### Шаг 6: Установите зависимости
1. Убедитесь, что виртуальное окружение активно. Если нет, активируйте его снова:
```bash
source venv/bin/activate
```
2. Установите зависимости из `requirements.txt`:
```bash
pip install -r requirements.txt
```
### Шаг 7: Настройте файл `.env`
1. Убедитесь, что файл `.env` содержит все необходимые переменные окружения:
```
API_ID=ваш_api_id
API_HASH=ваш_api_hash
BOT_TOKEN=ваш_bot_token
CHANNEL_ID=ваш_channel_id
INTERIM_CHAT_ID=ваш_interim_chat_id
ALLOWED_USER_ID=ваш_allowed_user_id
```
2. Вы можете редактировать файл `.env` через вкладку **Files** или используя консоль:
```bash
nano .env
```
После внесения изменений нажмите `Ctrl + X`, затем `Y` и `Enter` для сохранения.
### Шаг 8: Тестирование бота
Перед настройкой непрерывной работы убедитесь, что бот работает корректно.
1. В консоли убедитесь, что виртуальное окружение активно:
```bash
source venv/bin/activate
```
2. Запустите бота:
```bash
python bot.py
```
3. Проверьте логи и убедитесь, что бот подключился и функционирует как ожидается.
4. Чтобы остановить бота, нажмите `Ctrl + C`.
### Шаг 9: Настройте Always On задачу
Для того чтобы бот работал постоянно, необходимо настроить Always On задачу.
1. Перейдите во вкладку **Web** (даже если вы не создаёте веб-приложение).
2. Пролистайте до раздела **Always On tasks** и нажмите **Add a new always-on task**.
3. В поле **Command** укажите путь к вашему скрипту. Например:
```bash
/home/yourusername/venv/bin/python /home/yourusername/telegram_bot/bot.py
```
**Примечание:** Убедитесь, что пути корректны и соответствуют вашей файловой структуре.
4. Нажмите **Create Task**.
### Шаг 10: Настройте переменные окружения
PythonAnywhere не использует `.env` по умолчанию при запуске скриптов через Always On задачи. Необходимо экспортировать их перед запуском скрипта.
1. Отредактируйте команду Always On задачи, чтобы она загружала переменные из `.env`. Например, используйте следующий синтаксис:
```bash
/bin/bash -c "source /home/yourusername/telegram_bot/venv/bin/activate && export $(cat /home/yourusername/telegram_bot/.env | xargs) && python /home/yourusername/telegram_bot/bot.py"
```
**Или**, если вы используете `python-dotenv`, убедитесь, что ваш скрипт правильно загружает `.env`.
### Шаг 11: Запуск и мониторинг
1. После создания Always On задачи, бот должен начать работать автоматически.
2. Перейдите во вкладку **Tasks**, чтобы увидеть статус ваших Always On задач.
3. Для проверки логов перейдите во вкладку **Files** и откройте `bot.log`.
### Дополнительные советы
- **Логи и отладка:** Регулярно проверяйте файл `bot.log` на предмет ошибок и другой информации.
- **Обновления кода:** Если вы вносите изменения в код, перезапустите Always On задачу через интерфейс PythonAnywhere.
- **Безопасность:** Убедитесь, что ваш `.env` файл не доступен публично и содержит только необходимые переменные.
### Пример команды Always On задачи с загрузкой `.env`
Если вы хотите автоматически загружать переменные окружения из `.env` перед запуском бота, можно создать обёртку-скрипт. Вот как это сделать:
1. Создайте файл `start_bot.sh` в директории вашего бота.
```bash
nano /home/yourusername/telegram_bot/start_bot.sh
```
2. Вставьте следующий содержимое:
```bash
#!/bin/bash
source /home/yourusername/telegram_bot/venv/bin/activate
export $(grep -v '^#' /home/yourusername/telegram_bot/.env | xargs)
python /home/yourusername/telegram_bot/bot.py
```
3. Сделайте скрипт исполняемым:
```bash
chmod +x /home/yourusername/telegram_bot/start_bot.sh
```
4. В настройках Always On задачи укажите команду:
```bash
/home/yourusername/telegram_bot/start_bot.sh
```
Этот скрипт активирует виртуальное окружение, экспортирует переменные из `.env` и запускает вашего бота.
### Заключение
Следуя этим шагам, вы сможете успешно развернуть вашего Telegram-бота на PythonAnywhere и обеспечить его непрерывную работу. Убедитесь, что все переменные окружения корректны и зависимости установлены правильно. Регулярно проверяйте логи для своевременного обнаружения и исправления возможных ошибок.
Если у вас возникнут дополнительные вопросы или проблемы, обратитесь к [документации PythonAnywhere](https://help.pythonanywhere.com/) или задайте их в соответствующих сообществах.
Удачи с вашим ботом!