Implement phase 3 and 4: Telegram and Twitter integration

This commit is contained in:
2026-01-18 22:42:48 +03:00
parent 836e8df344
commit f4725a5506
11 changed files with 726 additions and 7 deletions
+146 -1
View File
@@ -4,6 +4,9 @@ from sqlalchemy import and_, or_
from ..models.post import Post
from ..schemas.post import PostCreate, PostUpdate
from datetime import datetime
from ..integrations.telegram_bot import TelegramBot
from ..integrations.twitter_api import TwitterAPI
import os
class PostService:
@@ -85,4 +88,146 @@ class PostService:
"""Получить посты по статусу"""
return self.db.query(Post).filter(
and_(Post.owner_id == owner_id, Post.status == status)
).all()
).all()
def publish_post_to_telegram(self, post_id: int, chat_id: str) -> bool:
"""
Опубликовать пост в Telegram
Args:
post_id: ID поста в базе данных
chat_id: ID чата или канала в Telegram
Returns:
Успешность публикации
"""
# Получаем пост из базы данных
post = self.db.query(Post).filter(Post.id == post_id).first()
if not post:
return False
# Получаем токен бота из переменных окружения
bot_token = os.getenv("TELEGRAM_BOT_TOKEN")
if not bot_token:
raise ValueError("TELEGRAM_BOT_TOKEN environment variable is not set")
# Создаем экземпляр TelegramBot
bot = TelegramBot(bot_token)
try:
# Формируем сообщение из заголовка и содержимого поста
message = f"<b>{post.title}</b>\n\n{post.content}"
# Отправляем сообщение в Telegram
result = bot.send_message(chat_id=chat_id, text=message)
# Если публикация успешна, обновляем статус поста и время публикации
if result.get("ok"):
post.status = "published"
post.published_at = datetime.utcnow()
self.db.commit()
return True
else:
return False
except Exception as e:
print(f"Error publishing post to Telegram: {str(e)}")
return False
def publish_scheduled_posts(self, chat_id: str) -> int:
"""
Опубликовать все запланированные посты, время которых наступило
Args:
chat_id: ID чата или канала в Telegram
Returns:
Количество опубликованных постов
"""
scheduled_posts = self.get_scheduled_posts()
published_count = 0
for post in scheduled_posts:
try:
# Пытаемся опубликовать пост в Telegram
success = self.publish_post_to_telegram(post.id, chat_id)
if success:
published_count += 1
# Обновляем статус поста на published
post.status = "published"
post.published_at = datetime.utcnow()
self.db.commit()
else:
# Если публикация не удалась, помечаем пост как cancelled
post.status = "cancelled"
self.db.commit()
except Exception as e:
print(f"Error publishing scheduled post {post.id}: {str(e)}")
# Если возникла ошибка, помечаем пост как cancelled
post.status = "cancelled"
self.db.commit()
return published_count
def publish_post_to_twitter(self, post_id: int) -> bool:
"""
Опубликовать пост в Twitter
Args:
post_id: ID поста в базе данных
Returns:
Успешность публикации
"""
# Получаем пост из базы данных
post = self.db.query(Post).filter(Post.id == post_id).first()
if not post:
return False
# Получаем параметры для Twitter API из переменных окружения
twitter_consumer_key = os.getenv("TWITTER_CONSUMER_KEY")
twitter_consumer_secret = os.getenv("TWITTER_CONSUMER_SECRET")
twitter_access_token = os.getenv("TWITTER_ACCESS_TOKEN")
twitter_access_token_secret = os.getenv("TWITTER_ACCESS_TOKEN_SECRET")
if not all([twitter_consumer_key, twitter_consumer_secret, twitter_access_token, twitter_access_token_secret]):
raise ValueError("Twitter API credentials are not fully configured in environment variables")
# Создаем экземпляр TwitterAPI
twitter_api = TwitterAPI(
consumer_key=twitter_consumer_key,
consumer_secret=twitter_consumer_secret,
access_token=twitter_access_token,
access_token_secret=twitter_access_token_secret
)
try:
# Формируем текст твита из заголовка и содержимого поста
# Учитываем ограничение на 280 символов
combined_text = f"{post.title}\n\n{post.content}"
if len(combined_text) > 280:
# Обрезаем текст до 280 символов, возможно сокращая содержимое
truncated_title = post.title[:int(280*0.3)] # используем 30% на заголовок
remaining_chars = 280 - len(truncated_title) - 3 # -3 для "..."
if len(post.content) > remaining_chars:
combined_text = f"{truncated_title}...\n\n{post.content[:remaining_chars-4]}..."
else:
combined_text = f"{truncated_title}...\n\n{post.content}"
# Отправляем твит
result = twitter_api.post_tweet(combined_text)
# Если публикация успешна, обновляем статус поста и время публикации
if result.get("success"):
post.status = "published"
post.published_at = datetime.utcnow()
self.db.commit()
return True
else:
return False
except Exception as e:
print(f"Error publishing post to Twitter: {str(e)}")
return False