настройка отправки сообщения через правильный порт и ключ
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
2025-09-29 23:04:50 +03:00
parent af755115c8
commit a5d3b82092
5 changed files with 80 additions and 12 deletions
+42 -8
View File
@@ -8,6 +8,23 @@
2. **Интерфейс в веб-приложении** для отправки сообщений через браузер 2. **Интерфейс в веб-приложении** для отправки сообщений через браузер
3. **Обработку ошибок** и логирование всех операций 3. **Обработку ошибок** и логирование всех операций
## Архитектура системы
Система состоит из двух основных компонентов:
- **Веб-интерфейс** (`db_edit.py`) - работает на порту **5006** (WEBCTRL_PORT)
- **Telegram бот** (`tg_mainbot.py`) - работает на порту **5005** (WEBHOOK_PORT)
API endpoint `/send_message` находится в Telegram боте, поэтому все запросы должны отправляться на порт **5005**.
### Конфигурация портов
Порты настраиваются в файле `.env`:
- `WEBHOOK_PORT` - порт для Telegram бота (по умолчанию 5005)
- `WEBCTRL_PORT` - порт для веб-интерфейса (по умолчанию 5006)
Веб-интерфейс автоматически читает порт бота из переменных окружения и использует его для отправки запросов.
## Использование через веб-интерфейс ## Использование через веб-интерфейс
В заголовке страницы "Управление постами VK и событиями" добавлены два поля: В заголовке страницы "Управление постами VK и событиями" добавлены два поля:
@@ -32,6 +49,13 @@
POST /send_message POST /send_message
``` ```
### Заголовки запроса
```
Content-Type: application/json
X-API-Secret-Token: <секретный_токен>
```
### Параметры запроса ### Параметры запроса
```json ```json
@@ -41,6 +65,10 @@ POST /send_message
} }
``` ```
### Аутентификация
API защищен секретным токеном, который передается в заголовке `X-API-Secret-Token`. Токен берется из переменной окружения `WEBHOOK_SECRET`.
### Ответы ### Ответы
**Успешная отправка (200):** **Успешная отправка (200):**
@@ -65,13 +93,17 @@ POST /send_message
import requests import requests
def send_telegram_message(user_id, message): def send_telegram_message(user_id, message):
url = "http://localhost:8443/send_message" url = "http://localhost:5005/send_message"
data = { data = {
"user_id": user_id, "user_id": user_id,
"message": message "message": message
} }
headers = {
'Content-Type': 'application/json',
'X-API-Secret-Token': 'ваш_секретный_токен'
}
response = requests.post(url, json=data) response = requests.post(url, json=data, headers=headers)
result = response.json() result = response.json()
if result["success"]: if result["success"]:
@@ -84,8 +116,9 @@ def send_telegram_message(user_id, message):
```bash ```bash
# Используя curl # Используя curl
curl -X POST http://localhost:8443/send_message \ curl -X POST http://localhost:5005/send_message \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-H "X-API-Secret-Token: ваш_секретный_токен" \
-d '{"user_id": 123456789, "message": "Привет!"}' -d '{"user_id": 123456789, "message": "Привет!"}'
# Используя примерный скрипт # Используя примерный скрипт
@@ -96,11 +129,12 @@ python send_telegram_example.py 123456789 "Привет! Это тестовое
Система обрабатывает следующие типы ошибок: Система обрабатывает следующие типы ошибок:
1. **403 Forbidden** - Пользователь заблокировал бота или не начал с ним диалог 1. **401 Unauthorized** - Неверный или отсутствующий API токен
2. **400 Bad Request** - Неверный ID пользователя 2. **403 Forbidden** - Пользователь заблокировал бота или не начал с ним диалог
3. **429 Too Many Requests** - Превышен лимит отправки сообщений 3. **400 Bad Request** - Неверный ID пользователя или отсутствующие данные
4. **Пустое сообщение** - Не указан текст сообщения 4. **429 Too Many Requests** - Превышен лимит отправки сообщений
5. **Неверный формат ID** - user_id не является числом 5. **Пустое сообщение** - Не указан текст сообщения
6. **Неверный формат ID** - user_id не является числом
Все ошибки логируются в файл логов с указанием типа ошибки и ID пользователя. Все ошибки логируются в файл логов с указанием типа ошибки и ID пользователя.
+2
View File
@@ -509,6 +509,8 @@ def load_user(user_id):
@bp.before_request @bp.before_request
def before_request(): def before_request():
g.prefix = app.config['PREFIX'] g.prefix = app.config['PREFIX']
g.bot_port = os.getenv('WEBHOOK_PORT', '5005')
g.webhook_secret = os.getenv('WEBHOOK_SECRET')
# Маршруты Blueprint # Маршруты Blueprint
@bp.route('/') @bp.route('/')
+25 -3
View File
@@ -7,27 +7,49 @@
import sys import sys
import requests import requests
import json import json
import os
def send_message(user_id, message_text, bot_url="http://localhost:8443"): def send_message(user_id, message_text, bot_url=None, api_token=None):
""" """
Отправляет сообщение пользователю через Telegram бота Отправляет сообщение пользователю через Telegram бота
Args: Args:
user_id (int): ID пользователя в Telegram user_id (int): ID пользователя в Telegram
message_text (str): Текст сообщения message_text (str): Текст сообщения
bot_url (str): URL бота (по умолчанию localhost:8443) bot_url (str): URL бота (если не указан, берется из переменных окружения)
api_token (str): API токен для аутентификации (если не указан, берется из переменных окружения)
Returns: Returns:
tuple: (success: bool, message: str) tuple: (success: bool, message: str)
""" """
if bot_url is None:
# Пытаемся получить URL из переменных окружения
webhook_url = os.getenv('WEBHOOK_URL')
webhook_port = os.getenv('WEBHOOK_PORT', '5005')
if webhook_url:
# Извлекаем хост из WEBHOOK_URL
from urllib.parse import urlparse
parsed = urlparse(webhook_url)
bot_url = f"http://{parsed.hostname}:{webhook_port}"
else:
bot_url = f"http://localhost:{webhook_port}"
if api_token is None:
api_token = os.getenv('WEBHOOK_SECRET')
try: try:
url = f"{bot_url}/send_message" url = f"{bot_url}/send_message"
data = { data = {
"user_id": user_id, "user_id": user_id,
"message": message_text "message": message_text
} }
headers = {
'Content-Type': 'application/json',
'X-API-Secret-Token': api_token
}
response = requests.post(url, json=data, timeout=10) response = requests.post(url, json=data, headers=headers, timeout=10)
result = response.json() result = response.json()
if response.status_code == 200 and result.get("success"): if response.status_code == 200 and result.get("success"):
+4 -1
View File
@@ -790,7 +790,9 @@
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script> <script>
const PREFIX = "{{ g.prefix }}"; const PREFIX = "{{ g.prefix }}";
const BOT_PORT = "{{ g.bot_port }}";
console.log("Lister Prefix is:", PREFIX); // Должно выводить "/zilant" console.log("Lister Prefix is:", PREFIX); // Должно выводить "/zilant"
console.log("Bot Port is:", BOT_PORT); // Должно выводить порт бота
// Текущий выбранный пост и событие // Текущий выбранный пост и событие
let selectedPostId = null; let selectedPostId = null;
let selectedEventId = null; let selectedEventId = null;
@@ -2140,10 +2142,11 @@
sendBtn.disabled = true; sendBtn.disabled = true;
try { try {
const response = await fetch('/send_message', { const response = await fetch(`http://localhost:${BOT_PORT}/send_message`, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'X-API-Secret-Token': '{{ g.webhook_secret }}',
}, },
body: JSON.stringify({ body: JSON.stringify({
user_id: parseInt(userId), user_id: parseInt(userId),
+7
View File
@@ -1280,6 +1280,13 @@ def webhook():
@app.route('/send_message', methods=['POST']) @app.route('/send_message', methods=['POST'])
def send_message_api(): def send_message_api():
"""API endpoint для отправки сообщений через бота""" """API endpoint для отправки сообщений через бота"""
# Проверяем секретный токен для защиты API
api_token = request.headers.get('X-API-Secret-Token')
if api_token != WEBHOOK_SECRET:
logger.warning("Неверный API токен!")
log_event("security", "system", message="Попытка доступа к API с неверным токеном")
return {"success": False, "error": "Unauthorized"}, 401
try: try:
data = request.get_json() data = request.get_json()