add twitter feed

This commit is contained in:
bakatrouble 2019-03-09 22:11:42 +03:00
parent 10f3612cf7
commit dfb584116d
11 changed files with 136 additions and 6 deletions

View File

@ -24,5 +24,29 @@
<option name="ITERATION_ELEMENTS_WRAPPING" value="chop_down_if_not_single" /> <option name="ITERATION_ELEMENTS_WRAPPING" value="chop_down_if_not_single" />
</formatting-settings> </formatting-settings>
</DBN-SQL> </DBN-SQL>
<DBN-PSQL>
<case-options enabled="true">
<option name="KEYWORD_CASE" value="lower" />
<option name="FUNCTION_CASE" value="lower" />
<option name="PARAMETER_CASE" value="lower" />
<option name="DATATYPE_CASE" value="lower" />
<option name="OBJECT_CASE" value="preserve" />
</case-options>
<formatting-settings enabled="false" />
</DBN-PSQL>
<DBN-SQL>
<case-options enabled="true">
<option name="KEYWORD_CASE" value="lower" />
<option name="FUNCTION_CASE" value="lower" />
<option name="PARAMETER_CASE" value="lower" />
<option name="DATATYPE_CASE" value="lower" />
<option name="OBJECT_CASE" value="preserve" />
</case-options>
<formatting-settings enabled="false">
<option name="STATEMENT_SPACING" value="one_line" />
<option name="CLAUSE_CHOP_DOWN" value="chop_down_if_statement_long" />
<option name="ITERATION_ELEMENTS_WRAPPING" value="chop_down_if_not_single" />
</formatting-settings>
</DBN-SQL>
</code_scheme> </code_scheme>
</component> </component>

4
.idea/encodings.xml Normal file
View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with NO BOM" />
</project>

View File

@ -1,4 +1,4 @@
{% load staticfiles bootstrap4 cabinet %} {% load staticfiles cabinet %}
<!DOCTYPE html> <!DOCTYPE html>
<html class="fixed dark" lang="en"> <html class="fixed dark" lang="en">

View File

@ -1,5 +1,5 @@
{% extends 'cabinet/_internal_base.html' %} {% extends 'cabinet/_internal_base.html' %}
{% load bootstrap4 %} {% load crispy_forms_tags %}
{% block breadcrumbs %} {% block breadcrumbs %}
@ -14,7 +14,7 @@
<h2 class="card-title">Config</h2> <h2 class="card-title">Config</h2>
</header> </header>
<div class="card-body"> <div class="card-body">
{% bootstrap_form form layout='horizontal' %} {% crispy form %}
</div> </div>
<footer class="card-footer text-right"> <footer class="card-footer text-right">
<button type="submit" class="btn btn-primary">Save</button> <button type="submit" class="btn btn-primary">Save</button>

View File

@ -19,6 +19,7 @@ ALLOWED_HOSTS = env.list('DJANGO_ALLOWED_HOSTS', [])
INSTALLED_APPS = [ INSTALLED_APPS = [
'django_extensions', 'django_extensions',
'bootstrap4', 'bootstrap4',
'crispy_forms',
'djconfig', 'djconfig',
'django_celery_results', 'django_celery_results',
'django_celery_beat', 'django_celery_beat',
@ -113,6 +114,8 @@ LOGIN_URL = 'cabinet:login'
LOGIN_REDIRECT_URL = 'cabinet:index' LOGIN_REDIRECT_URL = 'cabinet:index'
LOGOUT_REDIRECT_URL = LOGIN_URL LOGOUT_REDIRECT_URL = LOGIN_URL
CRISPY_TEMPLATE_PACK = 'bootstrap4'
sentry_sdk.init( sentry_sdk.init(
dsn=env.str('SENTRY_DSN', None), dsn=env.str('SENTRY_DSN', None),
integrations=[DjangoIntegration()], integrations=[DjangoIntegration()],

View File

@ -1,3 +1,5 @@
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Fieldset
from django import forms from django import forms
from django.forms import ModelForm from django.forms import ModelForm
from djconfig.forms import ConfigForm from djconfig.forms import ConfigForm
@ -28,8 +30,25 @@ class FeedsAppConfigForm(ConfigForm):
title = 'Feeds' title = 'Feeds'
feed_bot_token = forms.CharField(required=True) feed_bot_token = forms.CharField(required=True)
russian_proxy_string = forms.CharField() russian_proxy_string = forms.CharField()
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()) vk_auth = forms.CharField(required=False, widget=forms.Textarea())
anticaptcha_token = forms.CharField() anticaptcha_token = forms.CharField()
twitter_consumer_api_key = forms.CharField(required=False)
twitter_consumer_api_secret = forms.CharField(required=False)
twitter_access_token = forms.CharField(required=False)
twitter_access_token_secret = forms.CharField(required=False)
helper = FormHelper()
helper.form_class = 'form-horizontal'
helper.label_class = 'col-sm-2'
helper.field_class = 'col-sm-10'
helper.layout = Layout(
Fieldset('Global', 'feed_bot_token'),
Fieldset('VK.com', 'russian_proxy_string', 'vk_username', 'vk_password', 'vk_auth', 'anticaptcha_token'),
Fieldset('Twitter', 'twitter_consumer_api_key', 'twitter_consumer_api_secret', 'twitter_access_token',
'twitter_access_token_secret'),
)

View File

@ -0,0 +1,23 @@
# Generated by Django 2.1.5 on 2019-03-09 19:11
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('feeds', '0004_vkmusicfeedmoduleconfig'),
]
operations = [
migrations.CreateModel(
name='TwitterFeedModuleConfig',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('screen_name', models.CharField(max_length=256)),
],
options={
'abstract': False,
},
),
]

View File

@ -4,7 +4,8 @@ from .vk_music import VKMusicFeedModuleConfig
from .dank_memes import DankMemesFeedModuleConfig from .dank_memes import DankMemesFeedModuleConfig
from .shitty_watercolour import ShittyWatercolourFeedModuleConfig from .shitty_watercolour import ShittyWatercolourFeedModuleConfig
from .wp_comic import WPComicFeedModuleConfig from .wp_comic import WPComicFeedModuleConfig
from .twitter import TwitterFeedModuleConfig
FEED_MODULES = [EchoFeedModuleConfig, VKFeedModuleConfig, VKMusicFeedModuleConfig, DankMemesFeedModuleConfig, FEED_MODULES = [EchoFeedModuleConfig, VKFeedModuleConfig, VKMusicFeedModuleConfig, DankMemesFeedModuleConfig,
ShittyWatercolourFeedModuleConfig, WPComicFeedModuleConfig] ShittyWatercolourFeedModuleConfig, WPComicFeedModuleConfig, TwitterFeedModuleConfig]

50
feeds/modules/twitter.py Normal file
View File

@ -0,0 +1,50 @@
import sentry_sdk
import twitter
from django.db import models
from djconfig import config
from telebot import TeleBot
from telebot.types import InputMediaPhoto, InputMediaVideo
from feeds.models import FeedModuleConfig
class TwitterFeedModuleConfig(FeedModuleConfig):
screen_name = models.CharField(max_length=256)
MODULE_NAME = 'Twitter feed'
def execute(self, bot: TeleBot, chat_id, last_id):
config._reload_maybe()
if last_id is None:
last_id = 0
api = twitter.Api(config.twitter_consumer_api_key, config.twitter_consumer_api_secret,
config.twitter_access_token, config.twitter_access_token_secret)
for status in reversed(api.GetUserTimeline(screen_name=self.screen_name, since_id=last_id)):
try:
text = status.text # type: str
for url in status.urls:
text = text.replace(url.url, url.expanded_url)
media = list(filter(lambda m: m.type in ('photo', 'animated_gif', 'video'), status.media))
if not len(media):
bot.send_message(chat_id, text)
elif len(media) == 1:
if media[0].type == 'photo':
bot.send_photo(chat_id, media[0].media_url_https, text)
elif media[0].type == 'animated_gif':
bot.send_document(chat_id, media[0].video_info['variants'][-1]['url'], caption=text)
else:
bot.send_video(chat_id, media[0].video_info['variants'][-1]['url'], caption=text)
else:
converted_media = []
for i, m in enumerate(media):
if m.type == 'photo':
converted_media.append(InputMediaPhoto(m.media_url_https, text if not i else None))
elif m.type in ('animated_gif', 'video'):
converted_media.append(InputMediaVideo(m.video_info['variants'][-1]['url'],
caption=text if not i else None))
bot.send_media_group(chat_id, converted_media)
except Exception as e:
sentry_sdk.capture_exception(e)
yield status.id

View File

@ -29,7 +29,7 @@ def execute_feed(feed_pk):
feed.lock = True feed.lock = True
feed.save() feed.save()
bot = TeleBot(config.feed_bot_token) bot = TeleBot(config.feed_bot_token, threaded=False)
for last_id in feed.config.execute(bot, feed.chat_id, feed.last_id): for last_id in feed.config.execute(bot, feed.chat_id, feed.last_id):
if last_id: if last_id:
feed.last_id = last_id feed.last_id = last_id

View File

@ -10,6 +10,7 @@ Django==2.1.5
django-bootstrap4==0.0.7 django-bootstrap4==0.0.7
django-celery-beat==1.4.0 django-celery-beat==1.4.0
django-celery-results==1.0.4 django-celery-results==1.0.4
django-crispy-forms==1.7.2
django-djconfig==0.9.0 django-djconfig==0.9.0
django-environ==0.4.5 django-environ==0.4.5
django-extensions==2.1.4 django-extensions==2.1.4
@ -18,20 +19,25 @@ django-redis==4.10.0
django-timezone-field==3.0 django-timezone-field==3.0
django-yamlfield==1.0.3 django-yamlfield==1.0.3
enum34==1.1.6 enum34==1.1.6
future==0.17.1
idna==2.8 idna==2.8
kombu==4.2.2.post1 kombu==4.2.2.post1
oauthlib==3.0.1
Pillow==5.4.1 Pillow==5.4.1
psycopg2-binary==2.7.6.1 psycopg2-binary==2.7.6.1
pyaes==1.6.1 pyaes==1.6.1
-e git+https://github.com/pyrogram/pyrogram@69922e5cf905df7da5a37602be48d063dea4212e#egg=Pyrogram Pyrogram==0.11.0
PySocks==1.6.8 PySocks==1.6.8
pyTelegramBotAPI==3.6.6 pyTelegramBotAPI==3.6.6
python-anticaptcha==0.3.1
python-crontab==2.3.6 python-crontab==2.3.6
python-dateutil==2.7.5 python-dateutil==2.7.5
python-twitter==3.5
pytz==2018.9 pytz==2018.9
PyYAML==3.13 PyYAML==3.13
redis==3.0.1 redis==3.0.1
requests==2.21.0 requests==2.21.0
requests-oauthlib==1.2.0
sentry-sdk==0.6.9 sentry-sdk==0.6.9
six==1.12.0 six==1.12.0
soupsieve==1.7.3 soupsieve==1.7.3