настройка отправки сообщения через правильный порт и ключ
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
+42
-8
@@ -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 пользователя.
|
||||||
|
|
||||||
|
|||||||
@@ -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('/')
|
||||||
|
|||||||
@@ -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"):
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user