configurable bot token
This commit is contained in:
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>
|
||||||
|
23
cabinet/templates/cabinet/admin_config.html
Normal file
23
cabinet/templates/cabinet/admin_config.html
Normal file
@ -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…
Reference in New Issue
Block a user