Переезд
This commit is contained in:
commit
fa59858590
3 changed files with 176 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
env/
|
||||
173
news_tgbot.py
Executable file
173
news_tgbot.py
Executable file
|
|
@ -0,0 +1,173 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import logging
|
||||
from telegram import Update, ReplyKeyboardMarkup, InlineKeyboardMarkup, InlineKeyboardButton
|
||||
from telegram.ext import ApplicationBuilder, CommandHandler, MessageHandler, CallbackQueryHandler, filters, ContextTypes
|
||||
import vk_api
|
||||
import time
|
||||
|
||||
# Введите ваши токены
|
||||
TELEGRAM_TOKEN = 'ВАШ_ТОКЕН'
|
||||
VK_ACCESS_TOKEN = 'ВАШ_ОТКРЫТЫЙ_ТОКЕН'
|
||||
GROUP_IDS = [
|
||||
('ID 1', 'Название группы 1'),
|
||||
('ID 2', 'Название группы 2')
|
||||
] # Список ID групп ВКонтакте
|
||||
|
||||
# Логирование
|
||||
logging.basicConfig(
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
||||
level=logging.INFO
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Функция для получения новостей из конкретной группы ВКонтакте
|
||||
def get_vk_news(group_id, group_name):
|
||||
vk_session = vk_api.VkApi(token=VK_ACCESS_TOKEN)
|
||||
vk = vk_session.get_api()
|
||||
news = []
|
||||
|
||||
try:
|
||||
if group_id.isdigit():
|
||||
response = vk.wall.get(owner_id=f'-{group_id}', count=5) # Используем owner_id
|
||||
else:
|
||||
response = vk.wall.get(domain=group_id, count=5) # Используем domain
|
||||
for item in response['items']:
|
||||
post = {
|
||||
'text': item['text'],
|
||||
'group_name': group_name,
|
||||
'owner_id': item['owner_id'],
|
||||
'post_id': item['id'],
|
||||
'date': item['date'], # Добавляем дату публикации
|
||||
'photos': []
|
||||
}
|
||||
|
||||
# Проверяем наличие фотографий в посте
|
||||
if 'attachments' in item:
|
||||
for attachment in item['attachments']:
|
||||
if attachment['type'] == 'photo':
|
||||
max_size_photo = max(attachment['photo']['sizes'], key=lambda size: size['width'] * size['height'])
|
||||
post['photos'].append(max_size_photo['url'])
|
||||
|
||||
news.append(post)
|
||||
except vk_api.exceptions.ApiError as e:
|
||||
logger.error(f"Ошибка при получении новостей для группы {group_id}: {e}")
|
||||
|
||||
return news
|
||||
|
||||
# Функция для получения комментариев поста из ВКонтакте
|
||||
def get_vk_comments(owner_id, post_id):
|
||||
vk_session = vk_api.VkApi(token=VK_ACCESS_TOKEN)
|
||||
vk = vk_session.get_api()
|
||||
comments = []
|
||||
|
||||
try:
|
||||
response = vk.wall.getComments(owner_id=owner_id, post_id=post_id, count=10, extended=1)
|
||||
for comment in response['items']:
|
||||
# Получаем информацию о пользователе
|
||||
user_info = vk.users.get(user_ids=comment['from_id'])[0]
|
||||
comments.append({
|
||||
'text': comment['text'],
|
||||
'from_id': comment['from_id'],
|
||||
'from_name': f"{user_info['first_name']} {user_info['last_name']}",
|
||||
'date': comment['date']
|
||||
})
|
||||
except vk_api.exceptions.ApiError as e:
|
||||
logger.error(f"Ошибка при получении комментариев для поста {owner_id}_{post_id}: {e}")
|
||||
|
||||
return comments
|
||||
|
||||
# Функция разбивки длинного сообщения на несколько частей
|
||||
def split_message(message, max_length=4096):
|
||||
return [message[i:i+max_length] for i in range(0, len(message), max_length)]
|
||||
|
||||
# Функция форматирования даты
|
||||
def format_date(timestamp):
|
||||
return time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(timestamp))
|
||||
|
||||
# Функция обработки команды /start
|
||||
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||
if update.message:
|
||||
try:
|
||||
await update.message.reply_text('Привет! Я бот, который собирает новости из ВКонтакте.')
|
||||
await menu(update, context) # Сразу вызываем функцию menu
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при отправке сообщения: {e}")
|
||||
|
||||
# Функция обработки команды /menu
|
||||
async def menu(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||
keyboard = [[group[1]] for group in GROUP_IDS] # Кнопки с названиями групп
|
||||
reply_markup = ReplyKeyboardMarkup(keyboard, resize_keyboard=True)
|
||||
if update.message:
|
||||
try:
|
||||
await update.message.reply_text('Выберите группу:', reply_markup=reply_markup)
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при отправке сообщения: {e}")
|
||||
|
||||
# Функция для формирования инлайн-кнопок под каждым сообщением новости
|
||||
def generate_inline_keyboard(post_id, owner_id):
|
||||
keyboard = [[InlineKeyboardButton("Показать комментарии", callback_data=f"comments_{owner_id}_{post_id}")]]
|
||||
return InlineKeyboardMarkup(keyboard)
|
||||
|
||||
# Функция обработки нажатий кнопок
|
||||
async def button_handler(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||
text = update.message.text
|
||||
for group_id, group_name in GROUP_IDS:
|
||||
if text == group_name:
|
||||
news_items = get_vk_news(group_id, group_name)
|
||||
if news_items:
|
||||
for item in news_items:
|
||||
post_link = f"https://vk.com/wall{item['owner_id']}_{item['post_id']}"
|
||||
post_date = format_date(item['date'])
|
||||
message = f"{post_link}\nДата: {post_date}\nГруппа: {item['group_name']}\n\n{item['text']}"
|
||||
|
||||
# Добавляем кнопки под каждым сообщением новости
|
||||
inline_keyboard = generate_inline_keyboard(item['post_id'], item['owner_id'])
|
||||
|
||||
if item['photos']:
|
||||
for photo in item['photos']:
|
||||
await update.message.reply_photo(photo, caption=message, reply_markup=inline_keyboard)
|
||||
else:
|
||||
await update.message.reply_text(message, reply_markup=inline_keyboard)
|
||||
|
||||
else:
|
||||
await update.message.reply_text(f'Новостей нет для группы {group_name} или произошла ошибка при получении новостей.')
|
||||
break
|
||||
else:
|
||||
await update.message.reply_text('Неверная команда. Используйте меню для выбора группы.')
|
||||
|
||||
# Функция обработки нажатий на инлайн-кнопки
|
||||
async def callback_query_handler(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||
query = update.callback_query
|
||||
query_data = query.data.split('_')
|
||||
if query_data[0] == 'comments':
|
||||
owner_id = query_data[1]
|
||||
post_id = query_data[2]
|
||||
comments = get_vk_comments(owner_id, post_id)
|
||||
if comments:
|
||||
comment_text = '\n\n'.join([f"{comment['text']}\n\nКомментарий от: {comment['from_name']}\nВремя: {format_date(comment['date'])}" for comment in comments])
|
||||
if len(comment_text) > 4096:
|
||||
parts = split_message(comment_text)
|
||||
for part in parts:
|
||||
await query.message.reply_text(part)
|
||||
else:
|
||||
await query.message.reply_text(comment_text)
|
||||
else:
|
||||
await query.message.reply_text('Комментариев нет.')
|
||||
|
||||
# Удаляем кнопку "Назад в меню"
|
||||
await query.message.delete_reply_markup()
|
||||
|
||||
# Основная функция для запуска бота
|
||||
def main() -> None:
|
||||
application = ApplicationBuilder().token(TELEGRAM_TOKEN).build()
|
||||
|
||||
application.add_handler(CommandHandler("start", start))
|
||||
application.add_handler(CommandHandler("menu", menu))
|
||||
application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, button_handler))
|
||||
application.add_handler(CallbackQueryHandler(callback_query_handler))
|
||||
|
||||
application.run_polling()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
2
requirements.txt
Normal file
2
requirements.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
python-telegram-bot==20.3
|
||||
vk_api==11.9.8
|
||||
Loading…
Add table
Reference in a new issue