vk feed module
This commit is contained in:
parent
747713bce0
commit
90d8c02a08
@ -1,7 +1,8 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
import environ
|
import environ
|
||||||
import raven
|
import sentry_sdk
|
||||||
|
from sentry_sdk.integrations.django import DjangoIntegration
|
||||||
|
|
||||||
BASE_DIR = environ.Path(__file__) - 2
|
BASE_DIR = environ.Path(__file__) - 2
|
||||||
|
|
||||||
@ -23,7 +24,6 @@ INSTALLED_APPS = [
|
|||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
|
|
||||||
'raven.contrib.django.raven_compat',
|
|
||||||
'django_extensions',
|
'django_extensions',
|
||||||
'bootstrap4',
|
'bootstrap4',
|
||||||
'djconfig',
|
'djconfig',
|
||||||
@ -109,7 +109,7 @@ LOGIN_URL = 'cabinet:login'
|
|||||||
LOGIN_REDIRECT_URL = 'cabinet:index'
|
LOGIN_REDIRECT_URL = 'cabinet:index'
|
||||||
LOGOUT_REDIRECT_URL = LOGIN_URL
|
LOGOUT_REDIRECT_URL = LOGIN_URL
|
||||||
|
|
||||||
RAVEN_CONFIG = {
|
sentry_sdk.init(
|
||||||
'dsn': env.str('SENTRY_DSN', None),
|
dsn=env.str('SENTRY_DSN', None),
|
||||||
'release': raven.fetch_git_sha(str(BASE_DIR)),
|
integrations=[DjangoIntegration()],
|
||||||
}
|
)
|
||||||
|
@ -30,3 +30,4 @@ class FeedsAppConfigForm(ConfigForm):
|
|||||||
feed_bot_token = forms.CharField(required=True)
|
feed_bot_token = forms.CharField(required=True)
|
||||||
vk_username = forms.CharField(required=True)
|
vk_username = forms.CharField(required=True)
|
||||||
vk_password = forms.CharField(required=True)
|
vk_password = forms.CharField(required=True)
|
||||||
|
vk_auth = forms.CharField(required=False, widget=forms.Textarea())
|
||||||
|
25
feeds/migrations/0002_vkfeedmoduleconfig.py
Normal file
25
feeds/migrations/0002_vkfeedmoduleconfig.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# Generated by Django 2.1.5 on 2019-01-25 16:06
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('feeds', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='VKFeedModuleConfig',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('owner_id', models.IntegerField()),
|
||||||
|
('send_text', models.BooleanField(default=True)),
|
||||||
|
('send_links', models.BooleanField(default=True)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
@ -28,8 +28,8 @@ class Feed(models.Model):
|
|||||||
if self.last_check and timezone.now() < self.last_check + self.check_interval:
|
if self.last_check and timezone.now() < self.last_check + self.check_interval:
|
||||||
return
|
return
|
||||||
|
|
||||||
self.lock = True
|
# self.lock = True
|
||||||
self.save()
|
# self.save()
|
||||||
execute_feed.delay(self.pk)
|
execute_feed.delay(self.pk)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
from .echo import EchoFeedModuleConfig
|
from .echo import EchoFeedModuleConfig
|
||||||
|
from .vk_feed import VKFeedModuleConfig
|
||||||
|
|
||||||
FEED_MODULES = [EchoFeedModuleConfig]
|
FEED_MODULES = [EchoFeedModuleConfig, VKFeedModuleConfig]
|
||||||
|
77
feeds/modules/vk_feed.py
Normal file
77
feeds/modules/vk_feed.py
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
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()
|
||||||
|
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, a['audio'].get('duration'),
|
||||||
|
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
|
@ -1,3 +1,6 @@
|
|||||||
|
from pprint import pprint
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from telebot import TeleBot
|
from telebot import TeleBot
|
||||||
from djconfig import config
|
from djconfig import config
|
||||||
@ -7,8 +10,13 @@ from config.celery import app
|
|||||||
|
|
||||||
@app.task()
|
@app.task()
|
||||||
def execute_feed(feed_pk):
|
def execute_feed(feed_pk):
|
||||||
config._reload_maybe()
|
|
||||||
from feeds.models import Feed
|
from feeds.models import Feed
|
||||||
|
from django.db import connections
|
||||||
|
|
||||||
|
c = connections['default'].cursor()
|
||||||
|
print(c.db.__dict__)
|
||||||
|
|
||||||
|
# config._reload_maybe()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
feed = Feed.objects.get(pk=feed_pk)
|
feed = Feed.objects.get(pk=feed_pk)
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
|
import yaml
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
|
from djconfig import config
|
||||||
|
from jconfig.base import BaseConfig
|
||||||
|
from yaml.parser import ParserError
|
||||||
|
|
||||||
from cabinet.utils import CabinetViewMixin
|
from cabinet.utils import CabinetViewMixin
|
||||||
from feeds.forms import FeedForm, get_config_form
|
from feeds.forms import FeedForm, get_config_form, FeedsAppConfigForm
|
||||||
from feeds.models import Feed
|
from feeds.models import Feed
|
||||||
|
|
||||||
|
|
||||||
@ -36,3 +40,19 @@ class BaseFeedConfigView(CabinetViewMixin, TemplateView):
|
|||||||
ctx['feed_form'], ctx['config_form'] = self.get_forms() if forms is None else forms
|
ctx['feed_form'], ctx['config_form'] = self.get_forms() if forms is None else forms
|
||||||
ctx['feed_module'] = self.get_content_type().model_class()
|
ctx['feed_module'] = self.get_content_type().model_class()
|
||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
|
|
||||||
|
class DatabaseConfig(BaseConfig):
|
||||||
|
__slots__ = ()
|
||||||
|
|
||||||
|
def load(self, **kwargs):
|
||||||
|
config._reload_maybe()
|
||||||
|
try:
|
||||||
|
settings = yaml.load(config.vk_auth)
|
||||||
|
except (ParserError, AttributeError):
|
||||||
|
settings = {}
|
||||||
|
settings.setdefault(self.section_name, {})
|
||||||
|
return settings
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
FeedsAppConfigForm(data={'vk_auth': yaml.dump(self._settings)}).save()
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
amqp==2.3.2
|
amqp==2.3.2
|
||||||
|
beautifulsoup4==4.7.1
|
||||||
billiard==3.5.0.5
|
billiard==3.5.0.5
|
||||||
celery==4.2.1
|
celery==4.2.1
|
||||||
certifi==2018.11.29
|
certifi==2018.11.29
|
||||||
@ -17,12 +18,13 @@ psycopg2-binary==2.7.6.1
|
|||||||
pyTelegramBotAPI==3.6.6
|
pyTelegramBotAPI==3.6.6
|
||||||
pytz==2018.9
|
pytz==2018.9
|
||||||
PyYAML==3.13
|
PyYAML==3.13
|
||||||
raven==6.10.0
|
|
||||||
redis==3.0.1
|
redis==3.0.1
|
||||||
requests==2.21.0
|
requests==2.21.0
|
||||||
|
sentry-sdk==0.6.9
|
||||||
six==1.12.0
|
six==1.12.0
|
||||||
|
soupsieve==1.7.3
|
||||||
urllib3==1.24.1
|
urllib3==1.24.1
|
||||||
uWSGI==2.0.17.1
|
uWSGI==2.0.17.1
|
||||||
vine==1.2.0
|
vine==1.2.0
|
||||||
vk-api==11.3.0
|
-e git+https://github.com/python273/vk_api@442281c9392109945dd6ed85a423d2fe8d068e7d#egg=vk_api
|
||||||
Werkzeug==0.14.1
|
Werkzeug==0.14.1
|
||||||
|
Loading…
Reference in New Issue
Block a user