configurable bot token

master
bakatrouble 5 years ago
parent 33ff1b800b
commit 999c6af8e7

@ -17,6 +17,27 @@
</li> </li>
</ul> </ul>
</nav> </nav>
{% if request.user.is_superuser %}
<hr class="separator" />
<div class="nav-subtitle">Admin</div>
<nav class="nav-main" role="navigation">
<ul class="nav nav-main">
<li class="nav-parent {% if sidebar_section %}nav-active{% endif %}">
<a href="#">
<i class="fas fa-cog" aria-hidden="true"></i>
<span>Configs</span>
</a>
<ul class="nav nav-children">
{% for slug, title in admin_configs.items %}
<li><a href="{% url 'cabinet:admin_config' slug=slug %}" class="nav-link">{{ title }}</a></li>
{% endfor %}
</ul>
</li>
</ul>
</nav>
{% endif %}
</div> </div>
<script> <script>

@ -0,0 +1,23 @@
{% extends 'cabinet/_internal_base.html' %}
{% load bootstrap4 %}
{% block breadcrumbs %}
<li><span>Configs</span></li>
<li><span>{{ form.title }}</span></li>
{% endblock %}
{% block content %}
<form action="" method="post" class="card">
{% csrf_token %}
<header class="card-header">
<h2 class="card-title">Config</h2>
</header>
<div class="card-body">
{% bootstrap_form form layout='horizontal' %}
</div>
<footer class="card-footer text-right">
<button type="submit" class="btn btn-primary">Save</button>
</footer>
</form>
{% endblock %}

@ -1,7 +1,7 @@
from django.contrib.auth.views import LogoutView from django.contrib.auth.views import LogoutView
from django.urls import path, include from django.urls import path, include
from cabinet.views import CabinetIndexView, LoginView from cabinet.views import CabinetIndexView, LoginView, AdminConfigView
app_name = 'cabinet' app_name = 'cabinet'
urlpatterns = [ urlpatterns = [
@ -9,4 +9,5 @@ urlpatterns = [
path('login/', LoginView.as_view(), name='login'), path('login/', LoginView.as_view(), name='login'),
path('logout/', LogoutView.as_view(), name='logout'), path('logout/', LogoutView.as_view(), name='logout'),
path('feeds/', include('feeds.urls', namespace='feeds')), path('feeds/', include('feeds.urls', namespace='feeds')),
path('admin/config/<slug>/', AdminConfigView.as_view(), name='admin_config'),
] ]

@ -1,3 +1,4 @@
import djconfig
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
@ -13,3 +14,9 @@ class CabinetViewMixin(LoginRequiredMixin):
ctx['title'] = self.get_title() ctx['title'] = self.get_title()
ctx['sidebar_section'] = self.sidebar_section ctx['sidebar_section'] = self.sidebar_section
return ctx return ctx
def cabinet_context_processor(ctx):
return {
'admin_configs': {form.slug: form.title for form in djconfig.config._registry},
}

@ -1,5 +1,7 @@
import djconfig
from django.contrib.auth.views import LoginView as BaseLoginView from django.contrib.auth.views import LoginView as BaseLoginView
from django.views.generic import TemplateView from django.http import Http404
from django.views.generic import TemplateView, FormView
from cabinet.utils import CabinetViewMixin from cabinet.utils import CabinetViewMixin
@ -23,3 +25,16 @@ class LoginView(BaseLoginView):
if not self.request.POST.get('remember'): if not self.request.POST.get('remember'):
self.request.session.set_expiry(0) self.request.session.set_expiry(0)
return res return res
class AdminConfigView(CabinetViewMixin, FormView):
template_name = 'cabinet/admin_config.html'
def get_title(self):
return '{} config'.format(self.get_form_class().title)
def get_form_class(self):
for form in djconfig.config._registry:
if form.slug == self.kwargs.get('slug'):
return form
raise Http404()

@ -2,15 +2,13 @@ import os
from celery import Celery from celery import Celery
config = {
'broker_url': 'redis://127.0.0.1:6379/1',
}
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings') os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
app = Celery('telegram_bots') app = Celery('telegram_bots')
app.config_from_object(config) app.config_from_object({
'broker_url': 'redis://127.0.0.1:6379/1',
})
app.autodiscover_tasks() app.autodiscover_tasks()

@ -26,9 +26,10 @@ INSTALLED_APPS = [
'raven.contrib.django.raven_compat', 'raven.contrib.django.raven_compat',
'django_extensions', 'django_extensions',
'bootstrap4', 'bootstrap4',
'djconfig',
'cabinet', 'cabinet.apps.CabinetConfig',
'feeds', 'feeds.apps.FeedsConfig',
] ]
MIDDLEWARE = [ MIDDLEWARE = [
@ -39,6 +40,7 @@ MIDDLEWARE = [
'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware', 'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware',
'djconfig.middleware.DjConfigMiddleware',
] ]
ROOT_URLCONF = 'config.urls' ROOT_URLCONF = 'config.urls'
@ -54,7 +56,9 @@ TEMPLATES = [
'django.template.context_processors.request', 'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth', 'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages', 'django.contrib.messages.context_processors.messages',
'djconfig.context_processors.config',
'config.utils.turbolinks', 'config.utils.turbolinks',
'cabinet.utils.cabinet_context_processor',
], ],
}, },
}, },
@ -82,6 +86,19 @@ STATICFILES_FINDERS = [
'django.contrib.staticfiles.finders.AppDirectoriesFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
] ]
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/1",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
}
}
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "default"
PUBLIC_ROOT = BASE_DIR.path('public') PUBLIC_ROOT = BASE_DIR.path('public')
STATIC_URL = '/static/' STATIC_URL = '/static/'
STATIC_ROOT = str(PUBLIC_ROOT.path('static')) STATIC_ROOT = str(PUBLIC_ROOT.path('static'))

@ -4,6 +4,6 @@ from django.views.generic import RedirectView
urlpatterns = [ urlpatterns = [
path('', RedirectView.as_view(pattern_name='cabinet:index')), path('', RedirectView.as_view(pattern_name='cabinet:index')),
path('admin/', admin.site.urls), path('config/', admin.site.urls),
path('cabinet/', include('cabinet.urls', namespace='cabinet')), path('cabinet/', include('cabinet.urls', namespace='cabinet')),
] ]

@ -1,3 +1,3 @@
DJANGO_DEBUG = False DJANGO_DEBUG=False
DATABASE_URL = postgres://bots:bots@localhost/bots DATABASE_URL=postgres://bots:bots@localhost/bots
SENTRY_DSN = https:// SENTRY_DSN=https://

@ -3,3 +3,12 @@ from django.apps import AppConfig
class FeedsConfig(AppConfig): class FeedsConfig(AppConfig):
name = 'feeds' name = 'feeds'
def ready(self):
self.register_config()
def register_config(self):
import djconfig
from .forms import FeedsAppConfigForm
djconfig.register(FeedsAppConfigForm)

@ -1,4 +1,6 @@
from django import forms
from django.forms import ModelForm from django.forms import ModelForm
from djconfig.forms import ConfigForm
from feeds.models import Feed from feeds.models import Feed
@ -19,3 +21,12 @@ def get_config_form(mdl):
model = mdl model = mdl
exclude = () exclude = ()
return ConfigForm return ConfigForm
class FeedsAppConfigForm(ConfigForm):
slug = 'feeds'
title = 'Feeds'
feed_bot_token = forms.CharField(required=True)
vk_username = forms.CharField(required=True)
vk_password = forms.CharField(required=True)

@ -1,15 +1,13 @@
# Generated by Django 2.1.5 on 2019-01-10 17:20 # Generated by Django 2.1.5 on 2019-01-19 05:35
from django.conf import settings from django.conf import settings
from django.db import migrations, models from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
import picklefield.fields import yamlfield.fields
class Migration(migrations.Migration): class Migration(migrations.Migration):
initial = True
dependencies = [ dependencies = [
('contenttypes', '0002_remove_content_type_name'), ('contenttypes', '0002_remove_content_type_name'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL), migrations.swappable_dependency(settings.AUTH_USER_MODEL),
@ -32,12 +30,13 @@ class Migration(migrations.Migration):
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=32)), ('title', models.CharField(max_length=32)),
('chat_id', models.CharField(max_length=33)), ('chat_id', models.CharField(max_length=33)),
('check_interval', models.DurationField()), ('check_interval', models.DurationField(help_text='in seconds')),
('last_check', models.DateTimeField(blank=True, null=True)), ('last_check', models.DateTimeField(blank=True, null=True)),
('last_id', picklefield.fields.PickledObjectField(blank=True, editable=False, null=True)), ('last_id', yamlfield.fields.YAMLField(blank=True, null=True)),
('config_id', models.PositiveIntegerField()), ('config_id', models.PositiveIntegerField()),
('config_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')), ('config_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
('lock', models.BooleanField(default=False)),
], ],
), ),
migrations.AlterUniqueTogether( migrations.AlterUniqueTogether(

@ -1,18 +0,0 @@
# Generated by Django 2.1.5 on 2019-01-10 18:41
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('feeds', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='feed',
name='lock',
field=models.BooleanField(default=False),
),
]

@ -1,18 +0,0 @@
# Generated by Django 2.1.5 on 2019-01-19 02:49
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('feeds', '0002_feed_lock'),
]
operations = [
migrations.AlterField(
model_name='feed',
name='check_interval',
field=models.DurationField(help_text='in seconds'),
),
]

@ -3,8 +3,8 @@ from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelatio
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.db import models from django.db import models
from django.utils import timezone from django.utils import timezone
from picklefield import PickledObjectField
from telebot import TeleBot from telebot import TeleBot
from yamlfield.fields import YAMLField
from feeds.tasks import execute_feed from feeds.tasks import execute_feed
@ -15,7 +15,7 @@ class Feed(models.Model):
chat_id = models.CharField(max_length=33) chat_id = models.CharField(max_length=33)
check_interval = models.DurationField(help_text='in seconds') check_interval = models.DurationField(help_text='in seconds')
last_check = models.DateTimeField(null=True, blank=True) last_check = models.DateTimeField(null=True, blank=True)
last_id = PickledObjectField(null=True, blank=True) last_id = YAMLField(null=True, blank=True)
lock = models.BooleanField(default=False) lock = models.BooleanField(default=False)
config_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) config_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)

@ -1,5 +1,6 @@
from django.utils import timezone from django.utils import timezone
from telebot import TeleBot from telebot import TeleBot
from djconfig import config
from config.celery import app from config.celery import app
@ -15,7 +16,7 @@ def execute_feed(feed_pk):
feed.lock = True feed.lock = True
feed.save() feed.save()
bot = TeleBot('450146961:AAFcb9tyIiKAi6BHR1ZYfWuTEkYjhO3xEFE') bot = TeleBot(config.feed_bot_token)
feed.last_id = feed.config.execute(bot, feed.chat_id, feed.last_id) feed.last_id = feed.config.execute(bot, feed.chat_id, feed.last_id)
feed.last_check = timezone.now() feed.last_check = timezone.now()
feed.save() feed.save()

@ -16,7 +16,18 @@
<h4>General options</h4> <h4>General options</h4>
{% bootstrap_form feed_form layout='horizontal' %} {% bootstrap_form feed_form layout='horizontal' %}
{% if feed %} {% if feed %}
Last check: {{ feed.last_check }} <div class="form-group row">
<label class="col-md-3 col-form-label" for="id_feed-last_check">Last check</label>
<div class="col-md-9">
<input type="text" value="{{ feed.last_check }}" class="form-control" placeholder="Last check" title="" id="id_feed-last_check" disabled>
</div>
</div>
<div class="form-group row">
<label class="col-md-3 col-form-label" for="id_feed-last_id">Last id</label>
<div class="col-md-9">
<textarea class="form-control" placeholder="Last id" id="id_feed-last_id" disabled>{{ feed.last_id }}</textarea>
</div>
</div>
{% endif %} {% endif %}
<hr> <hr>
<h4>Module options</h4> <h4>Module options</h4>

@ -5,14 +5,18 @@ certifi==2018.11.29
chardet==3.0.4 chardet==3.0.4
Django==2.1.5 Django==2.1.5
django-bootstrap4==0.0.7 django-bootstrap4==0.0.7
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
django-picklefield==2.0 django-redis==4.10.0
django-yamlfield==1.0.3
enum34==1.1.6
idna==2.8 idna==2.8
kombu==4.2.2.post1 kombu==4.2.2.post1
psycopg2-binary==2.7.6.1 psycopg2-binary==2.7.6.1
pyTelegramBotAPI==3.6.6 pyTelegramBotAPI==3.6.6
pytz==2018.9 pytz==2018.9
PyYAML==3.13
raven==6.10.0 raven==6.10.0
redis==3.0.1 redis==3.0.1
requests==2.21.0 requests==2.21.0
@ -20,4 +24,5 @@ six==1.12.0
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
Werkzeug==0.14.1 Werkzeug==0.14.1

@ -58,3 +58,9 @@ html.dark .userbox.show .dropdown-menu a:hover {
html.dark .turbolinks-progress-bar { html.dark .turbolinks-progress-bar {
background-color: #ccc; background-color: #ccc;
} }
html.dark .nav-subtitle {
color: #465162;
padding: 15px;
font-size: 12.8px;
font-size: 0.8rem;
}

@ -61,3 +61,9 @@ html.dark
.turbolinks-progress-bar .turbolinks-progress-bar
background-color #ccc background-color #ccc
.nav-subtitle
color: #465162
padding 15px
font-size 12.8px
font-size 0.8rem

Loading…
Cancel
Save