import os import tempfile import requests import sentry_sdk from django.db import models from djconfig import config from telebot import TeleBot from telebot.types import InputMediaPhoto from vk_api import VkApi from vk_api.audio import VkAudio from feeds.models import FeedModuleConfig from feeds.utils import DatabaseConfig def get_vk_photo(attachment): for size in (2560, 1280, 807, 604, 130, 75): if f'photo_{size}' in attachment: return attachment[f'photo_{size}'] return None def get_file(url): fname = '?'.join(url.split('?')[:-1]) extension = os.path.basename(fname).split('.')[-1] f = tempfile.NamedTemporaryFile(suffix=f'.{extension}' if extension else None) r = requests.get(url, stream=True) for chunk in r.iter_content(1024 * 1024): if chunk: f.write(chunk) f.seek(0) return f class VKFeedModuleConfig(FeedModuleConfig): owner_id = models.IntegerField() send_text = models.BooleanField(default=True) send_links = models.BooleanField(default=True) MODULE_NAME = 'VK feed' def execute(self, bot: TeleBot, chat_id, last_id): config._reload_maybe() if last_id is None: last_id = 0 vk_session = VkApi(login=config.vk_username, password=config.vk_password, config=DatabaseConfig, api_version='5.60') vk_session.auth() vk_audio = VkAudio(vk_session) vk = vk_session.get_api() wall_data = vk.wall.get(owner_id=self.owner_id) for post in reversed(wall_data['items']): if post['id'] > last_id: try: if self.send_text and post['text']: bot.send_message(chat_id, post['text']) if 'attachments' in post: photos = [] for image in filter(lambda a: 'photo' in a, post['attachments']): url = get_vk_photo(image['photo']) if url: photos.append(url.replace('\\', '')) if len(photos) == 1: bot.send_photo(chat_id, photos[0]) elif len(photos) > 1: bot.send_media_group(chat_id, [InputMediaPhoto(photo) for photo in photos]) for a in post['attachments']: if 'audio' in a: f = get_file(vk_audio.get_audio_by_id(a['audio']['owner_id'], a['audio']['id'])) bot.send_audio(chat_id, f, None, a['audio'].get('artist'), a['audio'].get('title')) if self.send_links: bot.send_message(chat_id, f"https://vk.com/wall{post['owner_id']}_{post['id']}", disable_web_page_preview=True) except Exception as e: sentry_sdk.capture_exception(e) last_id = post['id'] return last_id