This commit is contained in:
@@ -3,18 +3,28 @@ SECRET_KEY=24af5f41dba9d8cc0dbc1841660da0b14d7df86ab5e0ed973cdd3bc2dbac23f6
|
||||
LOG_FILE = /opt/testbot-git/logs/testzilantposter.log
|
||||
# LOG_FILE = /opt/volk/logs/volkposter.log
|
||||
|
||||
# WORKMODE = "ZILANT"
|
||||
WORKMODE = "VOLK"
|
||||
WORKMODE = "ZILANT"
|
||||
# WORKMODE = "VOLK"
|
||||
|
||||
|
||||
|
||||
|
||||
# Telegram API через internal_relay (retransbot) — обязательно
|
||||
# Локально: http://127.0.0.1:8081
|
||||
# Через nginx: https://rbin.aabpro.ru
|
||||
RELAY_URL = "https://rbin.aabpro.ru"
|
||||
|
||||
# Webhook Responder-bot
|
||||
# WEBHOOK_URL = "https://bot.aabpro.ru/volk_bot"
|
||||
# WEBHOOK_URL — адрес, по которому internal_relay доставляет апдейты боту
|
||||
# (должен быть доступен с машины internal_relay). Не публичный URL для Telegram:
|
||||
# Telegram ходит на external_relay; setWebhook перехватывается relay.
|
||||
# WEBHOOK_URL = "http://127.0.0.1:5010/volk_bot"
|
||||
# WEBHOOK_PORT = 5010
|
||||
# WEBHOOK_SECRET = "cc0dbc1841660da0b14d7df86ab5e0ed973c"
|
||||
|
||||
# Webhook Responder-bot
|
||||
# Пример: бот и relay на одной машине — http://127.0.0.1:5005/testbot
|
||||
# Или URL через nginx, если internal_relay достучится до него
|
||||
WEBHOOK_URL = "https://bot.aabpro.ru/testbot"
|
||||
WEBHOOK_PORT = 5005
|
||||
WEBHOOK_SECRET = "cc0dbc1841660da0b14d7df86ab5e0ed973c"
|
||||
@@ -40,16 +50,18 @@ DEFPW=Z1l@ntAdm1n23
|
||||
|
||||
# VK access
|
||||
# Zilant group
|
||||
# VK_GROUP_ID = -3342146
|
||||
VK_GROUP_ID = -3342146
|
||||
# VOLK group
|
||||
VK_GROUP_ID = -58475527
|
||||
# VK_GROUP_ID = -58475527
|
||||
VK_ACCESS_TOKEN = 'e3732a7ee3732a7ee3732a7ea7e044a75fee373e3732a7e8bf4e48a52d012e946b952a8'
|
||||
VK_API_VERSION = '5.131'
|
||||
|
||||
# MySQL database
|
||||
# MDBASE = 'testposts'
|
||||
# MDBASE = 'tempzilant' # debug Zilant database
|
||||
MDBASE = 'volk_test' # debug VOLK database
|
||||
# Zilant 2026 database
|
||||
MDBASE = 'zilant_2026'
|
||||
# MDBASE = 'volk_test' # debug VOLK database
|
||||
# MDBASE = 'volkdata' # VOLK production database
|
||||
MDB_HOST = 'localhost'
|
||||
MDB_USER = 'testuser'
|
||||
@@ -61,16 +73,14 @@ MDB_PW = 'T38tU83r69'
|
||||
# Debug bot @posto_1638_bot
|
||||
# BOT_TOKEN = "8301828103:AAHDuBkw7EUkmMvv5TPpVJaLeeBLu-EB21U"
|
||||
# @info_1638_bot
|
||||
# POSTER_BOT_TOKEN = "8215624618:AAF6VtqRtFr4twFRTiTjedSDE6txkbIy6rc"
|
||||
POSTER_BOT_TOKEN = "8215624618:AAF6VtqRtFr4twFRTiTjedSDE6txkbIy6rc"
|
||||
# VOLK production bot @VOLK_informer_bot
|
||||
POSTER_BOT_TOKEN = "8279661544:AAEsJee6icCUn_AbWxhDpk2CLxQhzaartuI"
|
||||
# POSTER_BOT_TOKEN = "8279661544:AAEsJee6icCUn_AbWxhDpk2CLxQhzaartuI"
|
||||
# VOLK backup production bot @VOLK_informer2_bot
|
||||
# POSTER_BOT_TOKEN = "8001674071:AAFyGW4xibAFnuApEaSJvshqEyYHmD7RRts"
|
||||
# VOLK responder bot
|
||||
# RESPONDER_BOT_TOKEN = "8072579275:AAFiyKN1EPPnP5ZVZNTDGEriYJf1xADbfsY"
|
||||
# RESPONDER_BOT_NAME = "VOLK_responder_bot"
|
||||
|
||||
|
||||
# @posto_1638_bot
|
||||
RESPONDER_BOT_TOKEN = "8301828103:AAHDuBkw7EUkmMvv5TPpVJaLeeBLu-EB21U"
|
||||
RESPONDER_BOT_NAME = "posto_1638_bot"
|
||||
@@ -100,9 +110,9 @@ VK_NO_REPOST_TAG = "#окоЗиланта"
|
||||
# !! DB datetime is UTC !!
|
||||
#
|
||||
# Set 1 hour when Zilant is near
|
||||
EVENT_POST_DELAY = 60
|
||||
# EVENT_POST_DELAY = 60
|
||||
# keep 1 day when far from Zilant
|
||||
# EVENT_POST_DELAY = 1440
|
||||
EVENT_POST_DELAY = 1440
|
||||
|
||||
# Poster channel
|
||||
# Debug channel
|
||||
@@ -120,16 +130,16 @@ MAX_TEXT_LENGTH = 4000
|
||||
#
|
||||
# add event number and trailing /
|
||||
#
|
||||
# PZK_PREFIX = "https://reg.konvent.ru/zk2025/draft/plan/api/add/"
|
||||
# EVT_PREFIX = "https://reg.konvent.ru/zk2025/events/actions/api/"
|
||||
# DESC_PREFIX = "https://reg.konvent.ru/zk2025/events/actions/"
|
||||
PZK_PREFIX = "https://reg.konvent.ru/zk2026/draft/plan/api/add/"
|
||||
EVT_PREFIX = "https://reg.konvent.ru/zk2026/events/actions/api/"
|
||||
DESC_PREFIX = "https://reg.konvent.ru/zk2026/events/actions/"
|
||||
|
||||
# VOLK mode API links
|
||||
# add category ID (volk24_larp for ex.)
|
||||
VOLK_API_VERSION = "1.0"
|
||||
VOLK_CATEGORY_LIST = "https://base.volk-nn.ru/api/categories?event=volk26&form=volk26_event"
|
||||
VOLK_CATEGORY_DESC_PREFIX = "https://base.volk-nn.ru/api/category?event=volk26&form=volk26_event&category="
|
||||
VOLK_EVENT_LIST_PREFIX = "https://base.volk-nn.ru/api/applications?event=volk26&form=volk26_event&apps_on_page=200&page=0&category="
|
||||
# VOLK_API_VERSION = "1.0"
|
||||
# VOLK_CATEGORY_LIST = "https://base.volk-nn.ru/api/categories?event=volk26&form=volk26_event"
|
||||
# VOLK_CATEGORY_DESC_PREFIX = "https://base.volk-nn.ru/api/category?event=volk26&form=volk26_event&category="
|
||||
# VOLK_EVENT_LIST_PREFIX = "https://base.volk-nn.ru/api/applications?event=volk26&form=volk26_event&apps_on_page=200&page=0&category="
|
||||
|
||||
# Event status
|
||||
IS_EVENT = true
|
||||
@@ -143,7 +153,8 @@ LOG_DEBUG_DATA = false
|
||||
|
||||
# OpenRouter
|
||||
OR_KEY = "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"
|
||||
OR_MODEL_NAME = "qwen/qwen3-vl-235b-a22b-instruct"
|
||||
# OR_MODEL_NAME = "qwen/qwen3-vl-235b-a22b-instruct"
|
||||
OR_MODEL_NAME = "anthropic/claude-sonnet-5"
|
||||
# OR_MODEL_NAME = "deepseek/deepseek-chat-v3.1"
|
||||
# OR_MODEL_NAME = "deepseek/deepseek-r1-0528:free"
|
||||
# OR_MODEL_NAME = "qwen/qwen3-coder:free"
|
||||
|
||||
@@ -20,8 +20,9 @@ API endpoint `/send_message` находится в Telegram боте, поэто
|
||||
### Конфигурация портов
|
||||
|
||||
Порты и URL настраиваются в файле `.env`:
|
||||
- `RELAY_URL` - базовый URL **internal_relay** (все исходящие вызовы Bot API идут только через него)
|
||||
- `WEBHOOK_PORT` - порт для Telegram бота (по умолчанию 5005)
|
||||
- `WEBHOOK_URL` - полный URL бота (например, https://bot.aabpro.ru/testbot)
|
||||
- `WEBHOOK_URL` - URL доставки апдейтов от internal_relay к боту (доступен с машины relay; не URL, который видит Telegram напрямую)
|
||||
- `WEBCTRL_PORT` - порт для веб-интерфейса (по умолчанию 5006)
|
||||
|
||||
Веб-интерфейс автоматически читает URL и порт бота из переменных окружения и использует их для отправки запросов.
|
||||
|
||||
+5
-4
@@ -8,6 +8,7 @@ import httpx
|
||||
from datetime import datetime, timezone, timedelta
|
||||
from dotenv import load_dotenv
|
||||
from formatter import get_event_text
|
||||
from telegram_relay import bot_api_method_url
|
||||
|
||||
# Загрузка переменных окружения
|
||||
load_dotenv()
|
||||
@@ -188,8 +189,8 @@ async def tg_post_event(httpx_client, event_data):
|
||||
logger.info(f"Текст для публикации: {initial_text[:200]}..." if len(initial_text) > 200 else f"Текст для публикации: {initial_text}")
|
||||
|
||||
# Публикация первоначального сообщения без ссылок
|
||||
send_photo_url = f"https://api.telegram.org/bot{BOT_TOKEN}/sendPhoto"
|
||||
send_message_url = f"https://api.telegram.org/bot{BOT_TOKEN}/sendMessage"
|
||||
send_photo_url = bot_api_method_url(BOT_TOKEN, "sendPhoto")
|
||||
send_message_url = bot_api_method_url(BOT_TOKEN, "sendMessage")
|
||||
|
||||
if has_image:
|
||||
try:
|
||||
@@ -373,8 +374,8 @@ async def tg_post_event(httpx_client, event_data):
|
||||
|
||||
# Редактируем сообщение, добавляя ссылки
|
||||
logger.info(f"Попытка редактирования сообщения для события {event_data['number']}: message_id={message_id}, final_text_length={len(final_text)}")
|
||||
edit_caption_url = f"https://api.telegram.org/bot{BOT_TOKEN}/editMessageCaption"
|
||||
edit_text_url = f"https://api.telegram.org/bot{BOT_TOKEN}/editMessageText"
|
||||
edit_caption_url = bot_api_method_url(BOT_TOKEN, "editMessageCaption")
|
||||
edit_text_url = bot_api_method_url(BOT_TOKEN, "editMessageText")
|
||||
|
||||
if has_image:
|
||||
try:
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
"""
|
||||
Конфигурация доступа к Telegram Bot API через internal_relay (retransbot).
|
||||
|
||||
Все исходящие вызовы Bot API должны идти на RELAY_URL, а не на api.telegram.org.
|
||||
"""
|
||||
|
||||
import os
|
||||
from typing import Tuple
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
|
||||
def get_relay_url() -> str:
|
||||
"""Базовый URL internal_relay без завершающего слэша."""
|
||||
load_dotenv()
|
||||
relay = (os.getenv("RELAY_URL") or "").rstrip("/")
|
||||
if not relay:
|
||||
raise RuntimeError(
|
||||
"Требуется переменная окружения RELAY_URL "
|
||||
"(базовый URL internal_relay, например http://127.0.0.1:8081)"
|
||||
)
|
||||
return relay
|
||||
|
||||
|
||||
def configure_telebot_api() -> str:
|
||||
"""
|
||||
Настраивает pyTelegramBotAPI (telebot.apihelper) на работу через relay.
|
||||
Вызывать до создания TeleBot.
|
||||
"""
|
||||
from telebot import apihelper
|
||||
|
||||
relay = get_relay_url()
|
||||
apihelper.API_URL = f"{relay}/bot{{0}}/{{1}}"
|
||||
apihelper.FILE_URL = f"{relay}/file/bot{{0}}/{{1}}"
|
||||
return relay
|
||||
|
||||
|
||||
def get_ptb_base_urls() -> Tuple[str, str]:
|
||||
"""
|
||||
base_url и base_file_url для python-telegram-bot.Bot.
|
||||
Формат как в Bot API: .../bot и .../file/bot (библиотека сама дописывает token/method).
|
||||
"""
|
||||
relay = get_relay_url()
|
||||
return f"{relay}/bot", f"{relay}/file/bot"
|
||||
|
||||
|
||||
def bot_api_method_url(token: str, method: str) -> str:
|
||||
"""Полный URL метода Bot API через relay (для сырых httpx/requests вызовов)."""
|
||||
return f"{get_relay_url()}/bot{token}/{method}"
|
||||
+10
-2
@@ -6,6 +6,7 @@ from dotenv import load_dotenv
|
||||
from telegram import Bot
|
||||
from telegram.error import TelegramError, TimedOut
|
||||
from telegram.request import HTTPXRequest
|
||||
from telegram_relay import get_ptb_base_urls, get_relay_url
|
||||
|
||||
# Загрузка переменных окружения
|
||||
load_dotenv()
|
||||
@@ -74,8 +75,15 @@ async def make_test_post_async():
|
||||
media_write_timeout=120.0 # Таймаут для медиа (на будущее)
|
||||
)
|
||||
|
||||
# Создание экземпляра бота с кастомным Request
|
||||
bot = Bot(token=POSTER_BOT_TOKEN, request=request)
|
||||
# Создание экземпляра бота через internal_relay
|
||||
base_url, base_file_url = get_ptb_base_urls()
|
||||
bot = Bot(
|
||||
token=POSTER_BOT_TOKEN,
|
||||
request=request,
|
||||
base_url=base_url,
|
||||
base_file_url=base_file_url,
|
||||
)
|
||||
logger.info(f"Telegram Bot API через ретранслятор: {get_relay_url()}")
|
||||
|
||||
# Определяем путь к изображению в том же каталоге, что и скрипт
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
+8
-1
@@ -14,6 +14,7 @@ import requests
|
||||
from io import BytesIO
|
||||
from flask import Flask, request
|
||||
from formatter import get_post_text, get_event_text
|
||||
from telegram_relay import configure_telebot_api, get_relay_url
|
||||
|
||||
# Создаем Flask app на верхнем уровне для экспорта
|
||||
app = Flask(__name__)
|
||||
@@ -28,6 +29,7 @@ WEBHOOK_URL = os.getenv('WEBHOOK_URL')
|
||||
WEBHOOK_PORT = int(os.getenv('WEBHOOK_PORT', '8443'))
|
||||
WEBHOOK_SECRET = os.getenv('WEBHOOK_SECRET')
|
||||
LOG_FILE = os.getenv('LOG_FILE', 'bot.log')
|
||||
RELAY_URL = os.getenv('RELAY_URL')
|
||||
|
||||
# Настройка логирования
|
||||
logger = logging.getLogger('TG_bot')
|
||||
@@ -149,6 +151,7 @@ required_vars = {
|
||||
"RESPONDER_BOT_TOKEN": RESPONDER_BOT_TOKEN,
|
||||
"CHANNEL_ID": CHANNEL_ID,
|
||||
"WEBHOOK_URL": WEBHOOK_URL,
|
||||
"RELAY_URL": RELAY_URL,
|
||||
"MDB_HOST": MDB_HOST,
|
||||
"MDB_USER": MDB_USER,
|
||||
"MDB_PW": MDB_PW,
|
||||
@@ -165,6 +168,10 @@ apihelper.READ_TIMEOUT = 120 # Таймаут на чтение ответа (
|
||||
apihelper.CONNECT_TIMEOUT = 30 # Таймаут на подключение
|
||||
apihelper.RETRY_ON_TIMEOUT = True # Автоматические повторные попытки при таймауте
|
||||
|
||||
# Весь Bot API — только через internal_relay
|
||||
relay = configure_telebot_api()
|
||||
logger.info(f"Telegram Bot API через ретранслятор: {relay}")
|
||||
|
||||
# Создаем экземпляр бота
|
||||
bot = telebot.TeleBot(RESPONDER_BOT_TOKEN)
|
||||
|
||||
@@ -1438,7 +1445,7 @@ def setup_webhook():
|
||||
secret_token=WEBHOOK_SECRET,
|
||||
max_connections=40
|
||||
)
|
||||
logger.info(f"Вебхук установлен: {WEBHOOK_URL}")
|
||||
logger.info(f"Вебхук установлен через ретранслятор {get_relay_url()}: локальная доставка {WEBHOOK_URL}")
|
||||
logger.info(f"Секретный токен: {'установлен' if WEBHOOK_SECRET else 'не установлен'}")
|
||||
logger.info(f"Прослушивание порта: {WEBHOOK_PORT}")
|
||||
logger.info(f"Путь вебхука: {WEBHOOK_PATH}")
|
||||
|
||||
+10
-2
@@ -16,6 +16,7 @@ from formatter import get_event_text
|
||||
from telegram import Bot
|
||||
from telegram.error import TelegramError, TimedOut
|
||||
from telegram.request import HTTPXRequest
|
||||
from telegram_relay import get_ptb_base_urls, get_relay_url
|
||||
|
||||
# Настройка anyio для правильной работы в отдельном потоке
|
||||
# Устанавливаем правильный backend для anyio (используем asyncio)
|
||||
@@ -182,8 +183,15 @@ async def publish_to_tg(vk_post_id):
|
||||
media_write_timeout=120.0 # Таймаут для медиа
|
||||
)
|
||||
|
||||
# Создание экземпляра бота с кастомным Request
|
||||
bot = Bot(token=BOT_TOKEN, request=request)
|
||||
# Bot API только через internal_relay
|
||||
base_url, base_file_url = get_ptb_base_urls()
|
||||
bot = Bot(
|
||||
token=BOT_TOKEN,
|
||||
request=request,
|
||||
base_url=base_url,
|
||||
base_file_url=base_file_url,
|
||||
)
|
||||
logger.info(f"Telegram Bot API через ретранслятор: {get_relay_url()}")
|
||||
|
||||
# Создаем httpx клиент только для скачивания изображений
|
||||
timeout_config = httpx.Timeout(
|
||||
|
||||
+3
-2
@@ -8,6 +8,7 @@ import httpx
|
||||
from datetime import datetime, timezone
|
||||
from dotenv import load_dotenv
|
||||
from formatter import get_event_text
|
||||
from telegram_relay import bot_api_method_url
|
||||
|
||||
# Загрузка переменных окружения
|
||||
load_dotenv()
|
||||
@@ -113,8 +114,8 @@ async def tg_post_category(httpx_client, category_data):
|
||||
logger.info(f"Текст для публикации: {initial_text[:200]}..." if len(initial_text) > 200 else f"Текст для публикации: {initial_text}")
|
||||
|
||||
# Публикация сообщения
|
||||
send_photo_url = f"https://api.telegram.org/bot{BOT_TOKEN}/sendPhoto"
|
||||
send_message_url = f"https://api.telegram.org/bot{BOT_TOKEN}/sendMessage"
|
||||
send_photo_url = bot_api_method_url(BOT_TOKEN, "sendPhoto")
|
||||
send_message_url = bot_api_method_url(BOT_TOKEN, "sendMessage")
|
||||
|
||||
if has_image:
|
||||
try:
|
||||
|
||||
@@ -7,6 +7,7 @@ import sys
|
||||
import json
|
||||
from datetime import datetime
|
||||
from dotenv import load_dotenv
|
||||
from telegram_relay import bot_api_method_url, get_relay_url
|
||||
|
||||
# Загрузка переменных окружения
|
||||
load_dotenv()
|
||||
@@ -68,6 +69,7 @@ async def test_telegram_publish():
|
||||
logger.info(f" MAX_TEXT_LENGTH: {MAX_TEXT_LENGTH}")
|
||||
logger.info(f" PUBLISH_SILENTLY: {PUBLISH_SILENTLY}")
|
||||
logger.info(f" USE_SUBSCRIPTION_BOT: {USE_SUBSCRIPTION_BOT}")
|
||||
logger.info(f" RELAY_URL: {get_relay_url()}")
|
||||
|
||||
# Проверка обязательных параметров
|
||||
if not POSTER_BOT_TOKEN:
|
||||
@@ -147,7 +149,7 @@ async def test_telegram_publish():
|
||||
logger.info("=" * 80)
|
||||
logger.info("ПОПЫТКА ПОЛУЧЕНИЯ ИНФОРМАЦИИ О БОТЕ")
|
||||
logger.info("=" * 80)
|
||||
get_me_url = f"https://api.telegram.org/bot{POSTER_BOT_TOKEN}/getMe"
|
||||
get_me_url = bot_api_method_url(POSTER_BOT_TOKEN, "getMe")
|
||||
logger.info(f"URL запроса: {get_me_url}")
|
||||
logger.info(f"Метод: GET")
|
||||
|
||||
@@ -209,7 +211,7 @@ async def test_telegram_publish():
|
||||
logger.info("=" * 80)
|
||||
logger.info("ПОПЫТКА ОТПРАВКИ ТЕСТОВОГО СООБЩЕНИЯ")
|
||||
logger.info("=" * 80)
|
||||
send_message_url = f"https://api.telegram.org/bot{POSTER_BOT_TOKEN}/sendMessage"
|
||||
send_message_url = bot_api_method_url(POSTER_BOT_TOKEN, "sendMessage")
|
||||
logger.info(f"URL запроса: {send_message_url}")
|
||||
logger.info(f"Метод: POST")
|
||||
logger.info(f"Параметры запроса:")
|
||||
@@ -258,7 +260,7 @@ async def test_telegram_publish():
|
||||
logger.info("=" * 80)
|
||||
logger.info("ПОПЫТКА РЕДАКТИРОВАНИЯ СООБЩЕНИЯ")
|
||||
logger.info("=" * 80)
|
||||
edit_message_url = f"https://api.telegram.org/bot{POSTER_BOT_TOKEN}/editMessageText"
|
||||
edit_message_url = bot_api_method_url(POSTER_BOT_TOKEN, "editMessageText")
|
||||
logger.info(f"URL запроса: {edit_message_url}")
|
||||
logger.info(f"Метод: POST")
|
||||
logger.info(f"Параметры запроса:")
|
||||
@@ -336,7 +338,7 @@ async def test_telegram_publish():
|
||||
logger.info("=" * 80)
|
||||
logger.info("ПОПЫТКА ОТПРАВКИ ТЕСТОВОГО СООБЩЕНИЯ С КАРТИНКОЙ")
|
||||
logger.info("=" * 80)
|
||||
send_photo_url = f"https://api.telegram.org/bot{POSTER_BOT_TOKEN}/sendPhoto"
|
||||
send_photo_url = bot_api_method_url(POSTER_BOT_TOKEN, "sendPhoto")
|
||||
image_url = "https://base.volk-nn.ru/uploads/events/volk26/volk26_event/20251210_175059_0.jpg"
|
||||
|
||||
# Формируем текст для сообщения с картинкой
|
||||
@@ -391,7 +393,7 @@ async def test_telegram_publish():
|
||||
logger.info("=" * 80)
|
||||
logger.info("ПОПЫТКА РЕДАКТИРОВАНИЯ СООБЩЕНИЯ С КАРТИНКОЙ")
|
||||
logger.info("=" * 80)
|
||||
edit_photo_caption_url = f"https://api.telegram.org/bot{POSTER_BOT_TOKEN}/editMessageCaption"
|
||||
edit_photo_caption_url = bot_api_method_url(POSTER_BOT_TOKEN, "editMessageCaption")
|
||||
logger.info(f"URL запроса: {edit_photo_caption_url}")
|
||||
logger.info(f"Метод: POST")
|
||||
logger.info(f"Параметры запроса:")
|
||||
|
||||
Reference in New Issue
Block a user