import os
import feedparser
import requests
import time
import vk_api
import g4f
# Конфигурация
VK_ACCESS_TOKEN = "(тут мой токен вк)"
VK_GROUP_ID = -226925342 # Указание отрицательного значения сразу
RSS_FEEDS = ["http://www.playground.ru/rss/news.xml"]
KEYWORDS = [
"шутер", "рпг", "экшен", "стратегия", "симулятор", "приключенческая игра", "платформер",
"файтинг", "песочница", "ммо", "мморпг", "хоррор", "пазл", "инди-игры", "виртуальная реальность",
"аркада", "квест", "спортивные игры", "гонки", "музыкальные игры", "стелс", "моба",
"королевская битва", "playstation", "xbox", "nintendo switch", "пк", "мобильные игры",
"вр-устройства", "пк-эксклюзивы", "консольные игры", "стриминг игр", "открытый мир", "пошаговые бои",
"реальное время", "крафтинг", "исследование мира", "квесты", "погоня", "рейтинг", "ранговая система",
"подземелья", "побеждение боссов", "система диалогов", "выживание", "мультиплеер", "кооператив",
"лутбоксы", "физика", "ачивки", "трофеи", "достижения", "лидеры", "игровой процесс", "сюжет",
"кинематографические вставки", "разработка игр", "игровой движок", "графика", "элементы сюжета",
"игровая физика", "прокачка персонажа", "влияние выбора", "локализация", "микротранзакции",
"платформенные элементы", "nintendo", "sony interactive entertainment", "microsoft", "ea",
"activision blizzard", "rockstar games", "ubisoft", "bethesda softworks", "valve", "cd projekt red",
"epic games", "square enix", "blizzard entertainment", "bioware", "insomniac games", "naughty dog",
"fromsoftware", "the last of us", "cyberpunk 2077", "the witcher 3", "call of duty", "fortnite",
"minecraft", "grand theft auto v", "red dead redemption 2", "assassin's creed", "overwatch", "elden ring",
"dark souls", "apex legends", "league of legends", "valorant", "among us", "world of warcraft",
"rocket league", "skyrim", "monster hunter world", "battlefield", "star wars", "battlefront"
]
POST_INTERVAL_MINUTES = 10
MAX_POSTS_PER_HOUR = 6
PUBLISHED_LINKS_FILE = "published_links.txt"
# Переменные для отслеживания публикаций
published_links = set()
post_count_last_hour = 0
last_post_time = time.time()
# Инициализация vk_api
vk_session = vk_api.VkApi(token=VK_ACCESS_TOKEN)
vk = vk_session.get_api()
def load_published_links():
"""Загружает опубликованные ссылки из файла."""
if not os.path.exists(PUBLISHED_LINKS_FILE):
return set()
with open(PUBLISHED_LINKS_FILE, "r", encoding="utf-8") as f:
return set(line.strip() for line in f)
def save_published_link(link):
"""Сохраняет ссылку в файл."""
with open(PUBLISHED_LINKS_FILE, "a", encoding="utf-8") as f:
f.write(link + "\n")
def summarize_text_g4f(text):
"""Функция для создания дружеского пересказа текста с использованием g4f."""
try:
prompt = f"Перескажи эту новость, словно друзьям: {text}"
response = g4f.ChatCompletion.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}]
)
# Проверка, что ответ - это словарь
print(f"Ответ от g4f: {response}") # Отладочный вывод
if isinstance(response, dict) and "choices" in response:
choices = response.get("choices", [])
if len(choices) > 0 and isinstance(choices[0], dict):
message = choices[0].get("message", {})
if "content" in message:
return message["content"].strip()
elif isinstance(response, str):
return response.strip() # Если ответ не словарь, возвращаем строку
except Exception as e:
print(f"Ошибка при составлении пересказа: {e}")
# Если что-то пошло не так, возвращаем первые 200 символов текста
return text[:200]
def upload_media(image_url=None):
"""Загружает изображение на сервер ВКонтакте и возвращает его ID."""
try:
# Если изображение не указано, пробуем загрузить дефолтное изображение
if not image_url:
print("Изображение не найдено, используем дефолтное изображение.")
image_url = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQnxtNlTBvcrh2i9G7NrSK68pGvKF7IdM4rpQ&s" # Заменить на URL дефолтного изображения
# Получаем сервер для загрузки фотографии
upload_server = vk.photos.getWallUploadServer(owner_id=VK_GROUP_ID) # Минус здесь уже
upload_url = upload_server['upload_url']
print(f"Upload URL: {upload_url}") # Логируем для отладки
# Загружаем изображение по URL
response = requests.get(image_url)
if response.status_code != 200:
print(f"Ошибка при скачивании изображения: {response.status_code}. Попробуем другие источники.")
# Здесь можно добавить дополнительную логику поиска альтернативных изображений
# Например, использование других URL из поля 'media_content' или 'enclosures'
return None
files = {'photo': ('image.jpg', response.content)}
upload_response = requests.post(upload_url, files=files).json()
# Логируем ответ от сервера загрузки
print(f"Upload response: {upload_response}")
if 'photo' in upload_response:
save_response = vk.photos.saveWallPhoto(
owner_id=VK_GROUP_ID,
photo=upload_response['photo'],
server=upload_response['server'],
hash=upload_response['hash']
)
if save_response:
photo_id = save_response[0]['id']
return photo_id
else:
print(f"Ошибка при сохранении фотографии: {save_response}")
else:
print(f"Ошибка при загрузке фотографии: {upload_response}")
return None
except Exception as e:
print(f"Ошибка при загрузке медиа: {e}")
return None
def publish_to_vk(title, summary, link, attachment=""):
"""Публикует пост в ВКонтакте с заголовком, описанием, ссылкой и изображением."""
try:
# Логируем, что публикуем
print(f"Публикуем пост:\nЗаголовок: {title}\nАнонс: {summary}\nСсылка: {link}\nAttachment: {attachment}")
# Проверка, если нет media (attachment), публикуем только текст
if not attachment:
print(f"Публикуем пост без изображения: {title}")
else:
print(f"Публикуем пост с изображением: {title}")
# Включаем более подробный лог
response = vk.wall.post(
owner_id=VK_GROUP_ID, # Убедитесь, что это отрицательное значение
from_group=1,
message=f" {title}\n\n{summary}\nПодробнее: {link}",
attachments=attachment, # Добавляем параметр attachments
)
# Логируем ответ от ВКонтакте для диагностики
print("Ответ от wall.post:", response)
if "post_id" in response:
print(f"Пост опубликован: https://vk.com/wall-{VK_GROUP_ID}_{response['post_id']}")
return True
else:
# Выводим подробную ошибку для диагностики
print(f"Ошибка при публикации на стене: {response}")
return False
except Exception as e:
print(f"Ошибка при отправке запроса на публикацию: {e}")
return False
def fetch_rss_feed(feed_url):
"""Получение и обработка RSS-ленты."""
global published_links, post_count_last_hour, last_post_time
print(f"Обработка RSS канала: {feed_url}") # Отладочный вывод
feed = feedparser.parse(feed_url)
for entry in feed.entries:
if entry.link in published_links:
continue
if any(keyword.lower() in (entry.title.lower() + entry.summary.lower()) for keyword in KEYWORDS):
if post_count_last_hour >= MAX_POSTS_PER_HOUR:
print("Достигнут лимит публикаций на час.")
break
title = entry.title
summary = summarize_text_g4f(entry.summary)
link = entry.link
# Извлекаем изображение из 'enclosure' или 'media_content'
image = None
if 'enclosures' in entry:
for enclosure in entry.enclosures:
if 'image' in enclosure.type:
image = enclosure.href
break
elif 'media_content' in entry:
image = entry.media_content[0]["url"]
# Загружаем и прикрепляем изображение
attachment = ""
if image:
photo_id = upload_media(image)
if photo_id:
attachment = f"photo-{VK_GROUP_ID}_{photo_id}" # Здесь изменено
# Публикация
if publish_to_vk(title, summary, link, attachment):
published_links.add(entry.link)
save_published_link(entry.link)
post_count_last_hour += 1
last_post_time = time.time()
# Пауза между публикациями
print("Публикация завершена. Ожидание 10 секунд.") # Отладочный вывод
time.sleep(10) # Пауза 10 секунд
def scheduler():
"""Запускает обработку RSS лент по расписанию."""
global post_count_last_hour
while True:
if time.time() - last_post_time >= 3600:
post_count_last_hour = 0 # Сброс счетчика постов
for feed_url in RSS_FEEDS:
fetch_rss_feed(feed_url)
time.sleep(600) # Запуск проверки каждые 10 минут
# Загрузка ранее опубликованных ссылок
published_links = load_published_links()
# Запуск планировщика
scheduler()