Remove non-functional MAX auto-reaction, add real TG auto-reaction
MAX Bot API has no reaction endpoint (confirmed 404 in production logs), so drop the dead code path entirely instead of eating a warning every post. Telegram's setMessageReaction is a real Bot API method (verified against aiogram 3.21.0, the pinned version) - wire it up as a non-fatal best-effort call after a successful send, mirroring the same try/except-and-log pattern MAX already used.
This commit is contained in:
+3
-3
@@ -39,9 +39,6 @@ MAX_BOT_TOKEN=your_max_bot_token_here
|
|||||||
MAX_CHAT_ID=123456
|
MAX_CHAT_ID=123456
|
||||||
# MAX API Base URL
|
# MAX API Base URL
|
||||||
MAX_API_BASE_URL=https://platform-api2.max.ru
|
MAX_API_BASE_URL=https://platform-api2.max.ru
|
||||||
# MAX Auto Reaction emoji on published post
|
|
||||||
MAX_AUTO_REACTION=👍
|
|
||||||
MAX_AUTO_REACTION_ENABLED=true
|
|
||||||
|
|
||||||
# ==========================================
|
# ==========================================
|
||||||
# Polling, Reporting & Maintenance
|
# Polling, Reporting & Maintenance
|
||||||
@@ -83,6 +80,9 @@ FOOTER_TEXT=
|
|||||||
COMMON_TAGS=#redairsoft #страйкбол
|
COMMON_TAGS=#redairsoft #страйкбол
|
||||||
# Make the first line of the post bold
|
# Make the first line of the post bold
|
||||||
FORMAT_FIRST_LINE_BOLD=true
|
FORMAT_FIRST_LINE_BOLD=true
|
||||||
|
# Telegram auto-reaction emoji on published posts (real Bot API method, unlike MAX)
|
||||||
|
TG_AUTO_REACTION=👍
|
||||||
|
TG_AUTO_REACTION_ENABLED=true
|
||||||
|
|
||||||
# Logging Level (DEBUG, INFO, WARNING, ERROR)
|
# Logging Level (DEBUG, INFO, WARNING, ERROR)
|
||||||
LOG_LEVEL=INFO
|
LOG_LEVEL=INFO
|
||||||
|
|||||||
+2
-3
@@ -34,9 +34,6 @@ class Settings(BaseSettings):
|
|||||||
max_bot_token: str = ""
|
max_bot_token: str = ""
|
||||||
max_chat_id: str = "" # Destination chat ID in MAX
|
max_chat_id: str = "" # Destination chat ID in MAX
|
||||||
max_api_base_url: str = "https://platform-api2.max.ru"
|
max_api_base_url: str = "https://platform-api2.max.ru"
|
||||||
max_auto_reaction: str = "👍"
|
|
||||||
max_auto_reaction_enabled: bool = True
|
|
||||||
max_reaction_path_template: str = "/messages/{message_id}/reactions"
|
|
||||||
max_video_ready_attempts: int = 6
|
max_video_ready_attempts: int = 6
|
||||||
max_video_ready_delay_sec: float = 8.0
|
max_video_ready_delay_sec: float = 8.0
|
||||||
|
|
||||||
@@ -67,6 +64,8 @@ class Settings(BaseSettings):
|
|||||||
footer_text: str = ""
|
footer_text: str = ""
|
||||||
common_tags: str = ""
|
common_tags: str = ""
|
||||||
format_first_line_bold: bool = True
|
format_first_line_bold: bool = True
|
||||||
|
tg_auto_reaction: str = "👍"
|
||||||
|
tg_auto_reaction_enabled: bool = True
|
||||||
|
|
||||||
# Logging
|
# Logging
|
||||||
log_level: str = "INFO"
|
log_level: str = "INFO"
|
||||||
|
|||||||
@@ -129,11 +129,6 @@ class MAXAPIClient:
|
|||||||
raise RuntimeError(f"MAX upload {resp.status}: {data}")
|
raise RuntimeError(f"MAX upload {resp.status}: {data}")
|
||||||
return data
|
return data
|
||||||
|
|
||||||
async def react(self, path_template: str, message_id: str, reaction: str) -> None:
|
|
||||||
path = path_template.format(message_id=message_id)
|
|
||||||
payload = {"reaction": reaction}
|
|
||||||
await self.request("POST", path, json=payload)
|
|
||||||
|
|
||||||
|
|
||||||
class MAXPoster:
|
class MAXPoster:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
@@ -295,17 +290,6 @@ class MAXPoster:
|
|||||||
msg_obj = res.get("message") if isinstance(res.get("message"), dict) else res
|
msg_obj = res.get("message") if isinstance(res.get("message"), dict) else res
|
||||||
first_url = self.message_url_from_response(msg_obj)
|
first_url = self.message_url_from_response(msg_obj)
|
||||||
|
|
||||||
# Try auto reaction if enabled
|
|
||||||
if settings.max_auto_reaction_enabled and settings.max_auto_reaction:
|
|
||||||
try:
|
|
||||||
await client.react(
|
|
||||||
settings.max_reaction_path_template,
|
|
||||||
first_mid,
|
|
||||||
settings.max_auto_reaction,
|
|
||||||
)
|
|
||||||
except Exception as exc:
|
|
||||||
logger.warning("MAX auto reaction failed: {}", exc)
|
|
||||||
|
|
||||||
for group in media_groups[1:]:
|
for group in media_groups[1:]:
|
||||||
attachments = await self.upload_media_group(client, group)
|
attachments = await self.upload_media_group(client, group)
|
||||||
if not attachments:
|
if not attachments:
|
||||||
|
|||||||
+17
-1
@@ -9,7 +9,7 @@ from aiogram import Bot
|
|||||||
from aiogram.client.session.aiohttp import AiohttpSession
|
from aiogram.client.session.aiohttp import AiohttpSession
|
||||||
from aiogram.client.telegram import TelegramAPIServer
|
from aiogram.client.telegram import TelegramAPIServer
|
||||||
from aiogram.exceptions import TelegramRetryAfter
|
from aiogram.exceptions import TelegramRetryAfter
|
||||||
from aiogram.types import FSInputFile, InputMediaPhoto, InputMediaVideo
|
from aiogram.types import FSInputFile, InputMediaPhoto, InputMediaVideo, ReactionTypeEmoji
|
||||||
try:
|
try:
|
||||||
from .config import settings
|
from .config import settings
|
||||||
from .media_processor import ProcessedMedia
|
from .media_processor import ProcessedMedia
|
||||||
@@ -119,6 +119,18 @@ class TelegramPoster:
|
|||||||
await asyncio.sleep(2 ** attempt)
|
await asyncio.sleep(2 ** attempt)
|
||||||
raise RuntimeError("Telegram retries exhausted")
|
raise RuntimeError("Telegram retries exhausted")
|
||||||
|
|
||||||
|
async def set_reaction(self, message_id: int) -> None:
|
||||||
|
if not (settings.tg_auto_reaction_enabled and settings.tg_auto_reaction and self.bot):
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
await self.bot.set_message_reaction(
|
||||||
|
chat_id=self.chat_id,
|
||||||
|
message_id=message_id,
|
||||||
|
reaction=[ReactionTypeEmoji(emoji=settings.tg_auto_reaction)],
|
||||||
|
)
|
||||||
|
except Exception as exc:
|
||||||
|
logger.warning("Telegram auto reaction failed: {}", exc)
|
||||||
|
|
||||||
async def upload_media_for_file_ids(
|
async def upload_media_for_file_ids(
|
||||||
self, media_items: list[ProcessedMedia]
|
self, media_items: list[ProcessedMedia]
|
||||||
) -> dict[str, str]:
|
) -> dict[str, str]:
|
||||||
@@ -405,6 +417,8 @@ class TelegramPoster:
|
|||||||
mids = await self.send_rich_message(rich_msg)
|
mids = await self.send_rich_message(rich_msg)
|
||||||
url = tg_message_url(self.chat_id, mids[0]) if mids else None
|
url = tg_message_url(self.chat_id, mids[0]) if mids else None
|
||||||
logger.info("Sent Telegram rich message: {}", mids)
|
logger.info("Sent Telegram rich message: {}", mids)
|
||||||
|
if mids:
|
||||||
|
await self.set_reaction(mids[0])
|
||||||
return mids, url
|
return mids, url
|
||||||
except RichMessageUnavailable as exc:
|
except RichMessageUnavailable as exc:
|
||||||
logger.warning("Telegram sendRichMessage failed: {}. Falling back to standard send.", exc)
|
logger.warning("Telegram sendRichMessage failed: {}. Falling back to standard send.", exc)
|
||||||
@@ -412,4 +426,6 @@ class TelegramPoster:
|
|||||||
mids = await self.send_media_post(formatted_text, valid_media, file_ids)
|
mids = await self.send_media_post(formatted_text, valid_media, file_ids)
|
||||||
url = tg_message_url(self.chat_id, mids[0]) if mids else None
|
url = tg_message_url(self.chat_id, mids[0]) if mids else None
|
||||||
logger.info("Sent Telegram message: {}", mids)
|
logger.info("Sent Telegram message: {}", mids)
|
||||||
|
if mids:
|
||||||
|
await self.set_reaction(mids[0])
|
||||||
return mids, url
|
return mids, url
|
||||||
|
|||||||
Reference in New Issue
Block a user