-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Пересылка постов из ВК в ТГ #37
base: main
Are you sure you want to change the base?
Conversation
💩 Code linting failed, use |
Summary
|
|
||
@event( | ||
type="wall_post_new", | ||
group_id=lambda i: int(i) == settings.VK_MONITORED_GROUP_ID if settings.VK_MONITORED_GROUP_ID else False, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Изначально предполагалось, что такие штуки прямо в коде будешь задавать. Не нужно их в настройки вносить
По факту эти @event
и есть конфиг, хоть и с кодом
async def send_to_telegram(message: str, photos: list = None): | ||
"""Отправляет сообщение и фотографии в Telegram канал""" | ||
if not settings.TELEGRAM_BOT_TOKEN or not settings.TELEGRAM_TARGET_CHANNEL_ID: | ||
logger.warning("Telegram bot token or channel ID not configured") | ||
return | ||
|
||
bot = Bot(token=settings.TELEGRAM_BOT_TOKEN) | ||
|
||
try: | ||
if not photos: | ||
# Если нет фотографий, отправляем только текст | ||
await bot.send_message( | ||
chat_id=settings.TELEGRAM_TARGET_CHANNEL_ID, | ||
text=message, | ||
parse_mode='HTML', | ||
disable_web_page_preview=False | ||
) | ||
elif len(photos) == 1: | ||
# Если только одна фотография, отправляем ее с подписью | ||
await bot.send_photo( | ||
chat_id=settings.TELEGRAM_TARGET_CHANNEL_ID, | ||
photo=photos[0], | ||
caption=message, | ||
parse_mode='HTML' | ||
) | ||
else: | ||
# Если несколько фотографий, отправляем их как медиагруппу | ||
media_group = [] | ||
|
||
# Первая фотография с подписью (текстом сообщения) | ||
media_group.append(InputMediaPhoto( | ||
media=photos[0], | ||
caption=message, | ||
parse_mode='HTML' | ||
)) | ||
|
||
# Все остальные фотографии без подписи | ||
for photo_url in photos[1:]: | ||
media_group.append(InputMediaPhoto( | ||
media=photo_url | ||
)) | ||
|
||
await bot.send_media_group( | ||
chat_id=settings.TELEGRAM_TARGET_CHANNEL_ID, | ||
media=media_group | ||
) | ||
|
||
logger.info(f"Message successfully sent to Telegram channel {settings.TELEGRAM_TARGET_CHANNEL_ID}") | ||
except Exception as e: | ||
logger.error(f"Failed to send message to Telegram: {e}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Этот код я бы унес в утилиты работы с телеграммом. Возможно, такой файл уже есть. Куда-нибудь в utils/telegram.py
И задавал бы Telegram channel id через параметр, а не через настройку. Из настроек убрал бы вообще это параметр. Просто захардкодить внутри @event
функции
for attachment in attachments: | ||
attachment_type = attachment.get("type") | ||
|
||
# Обрабатываем видео | ||
if attachment_type == "video": | ||
video_data = attachment.get("video", {}) | ||
video_id = video_data.get("id") | ||
video_owner_id = video_data.get("owner_id") | ||
video_title = video_data.get("title", "Видео") | ||
|
||
if video_id and video_owner_id: | ||
attachment_texts.append( | ||
f"\n\n<b>📹 {video_title}</b>: " | ||
f"<a href='https://vk.com/video{video_owner_id}_{video_id}'>Смотреть видео</a>" | ||
) | ||
|
||
# Обрабатываем ссылки | ||
elif attachment_type == "link": | ||
link_data = attachment.get("link", {}) | ||
link_url = link_data.get("url") | ||
link_title = link_data.get("title", "Ссылка") | ||
|
||
if link_url: | ||
attachment_texts.append( | ||
f"\n\n<b>🔗 {link_title}</b>: <a href='{link_url}'>Открыть ссылку</a>" | ||
) | ||
|
||
# Обрабатываем документы | ||
elif attachment_type == "doc": | ||
doc_data = attachment.get("doc", {}) | ||
doc_url = doc_data.get("url") | ||
doc_title = doc_data.get("title", "Документ") | ||
|
||
if doc_url: | ||
attachment_texts.append( | ||
f"\n\n<b>📄 {doc_title}</b>: <a href='{doc_url}'>Скачать документ</a>" | ||
) | ||
|
||
# Обрабатываем аудио | ||
elif attachment_type == "audio": | ||
audio_data = attachment.get("audio", {}) | ||
audio_id = audio_data.get("id") | ||
audio_owner_id = audio_data.get("owner_id") | ||
audio_artist = audio_data.get("artist", "") | ||
audio_title = audio_data.get("title", "Аудиозапись") | ||
|
||
if audio_id and audio_owner_id: | ||
attachment_texts.append( | ||
f"\n\n<b>🎵 {audio_artist} - {audio_title}</b>: " | ||
f"<a href='https://vk.com/audio{audio_owner_id}_{audio_id}'>Слушать</a>" | ||
) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Очень большая вложенность. +Проверить это не могу (нужно читать документацию ВК)
По первому пункту: лучше создать файл utils/vk.py
и вынести туда отдельными функциями для каждого типа сложений + общую функцию для обработки одного типа сложений. Тогда тут будет for a in attachments: обработай вложение
photos.append(photo_url) | ||
|
||
# Отправляем в Telegram | ||
import asyncio |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Импорты лучше делать в начале файла
|
||
# Отправляем в Telegram | ||
import asyncio | ||
asyncio.run(send_to_telegram(message, photos)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Вызывать асинхронный код отсюда не надо точно
except Exception as e: | ||
logger.exception(f"Error processing new VK post: {e}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Внутри обработчика событий и так должен быть большой try/except. Не нужно делать ещё один
WebhookStorage( | ||
system=WebhookSystems.VK, | ||
message=request_data, | ||
try: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Внутри router.post и так есть обработчик исключений, тут не нужен
db.session.commit() | ||
|
||
# Проверяем, это ли событие создания записи на стене | ||
is_wall_post = event_type == "wall_post_new" | ||
if is_wall_post: | ||
logger.info(f"Received new wall post event for group_id: {group_id}") | ||
|
||
# Запускаем обработку в фоновом режиме | ||
background_tasks.add_task(create_vk_chat, request_data) | ||
background_tasks.add_task(process_event, request_data) | ||
|
||
return PlainTextResponse('ok') | ||
except Exception as e: | ||
logger.exception(f"Error processing VK webhook: {e}") | ||
return PlainTextResponse('ok') # Всегда возвращаем ok, чтобы VK не повторял запрос |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Это не нужно. Для этого есть обработчик событий через @event
@router.post('/monitoring/configure') | ||
def configure_monitoring( | ||
config: MonitoringConfig, | ||
user: dict[str] = Depends(UnionAuth(["social.monitoring.configure"])), | ||
) -> dict: | ||
"""Настраивает мониторинг группы ВК и пересылку постов в Telegram канал""" | ||
# Здесь мы обновляем настройки приложения | ||
# В реальном приложении нужно будет сохранять эти настройки в базу данных | ||
# и загружать их при старте, а не менять глобальный объект | ||
|
||
settings = get_settings() | ||
|
||
# В данном примере мы напрямую изменяем настройки | ||
# Но лучше будет сохранить их в базу и обновлять при перезапуске | ||
# Для этого потребуется создать соответствующую модель БД | ||
settings.VK_MONITORED_GROUP_ID = config.vk_group_id | ||
settings.TELEGRAM_TARGET_CHANNEL_ID = config.telegram_channel_id | ||
|
||
logger.info(f"Monitoring configured for VK group {config.vk_group_id} with Telegram channel {config.telegram_channel_id}") | ||
|
||
return { | ||
"status": "success", | ||
"message": "Мониторинг настроен успешно", | ||
"vk_group_id": config.vk_group_id, | ||
"telegram_channel_id": config.telegram_channel_id | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Так это та же ручка, что уже есть.....
Добавлен функционал, позволяющий:
Для работы функционала необходимо добавить две переменные окружения:
TELEGRAM_TARGET_CHANNEL_ID
- ID канала Telegram для пересылки постовVK_MONITORED_GROUP_ID
- ID группы ВК для мониторингаИзменения просты в использовании и не нарушают существующий функционал.
Check-List
black
иisort
для Back-End илиPrettier
для Front-End?