From 077c26bc0ac32dacadd298fe6a81af90470b8259 Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Tue, 29 Dec 2020 17:26:48 +0100 Subject: [PATCH] Implement Telegram notifications Some refactoring --- INSTALL.md | 12 ++- cronhandler/__init__.py | 0 cronhandler/admin.py | 3 + cronhandler/apps.py | 5 ++ cronhandler/models.py | 3 + cronhandler/signals.py | 3 + cronhandler/tests.py | 3 + cronhandler/urls.py | 9 +++ cronhandler/views.py | 8 ++ .../bootstrap/js/bootstrap.bundle.js | 0 .../bootstrap/js/bootstrap.bundle.js.map | 0 .../bootstrap/js/bootstrap.bundle.min.js | 0 .../bootstrap/js/bootstrap.bundle.min.js.map | 0 .../{ => vendor}/bootstrap/js/bootstrap.js | 0 .../bootstrap/js/bootstrap.js.map | 0 .../bootstrap/js/bootstrap.min.js | 0 .../bootstrap/js/bootstrap.min.js.map | 0 .../{ => vendor}/bootstrap/scss/_alert.scss | 0 .../{ => vendor}/bootstrap/scss/_badge.scss | 0 .../bootstrap/scss/_breadcrumb.scss | 0 .../bootstrap/scss/_button-group.scss | 0 .../{ => vendor}/bootstrap/scss/_buttons.scss | 0 .../{ => vendor}/bootstrap/scss/_card.scss | 0 .../bootstrap/scss/_carousel.scss | 0 .../{ => vendor}/bootstrap/scss/_close.scss | 0 .../{ => vendor}/bootstrap/scss/_code.scss | 0 .../bootstrap/scss/_custom-forms.scss | 0 .../bootstrap/scss/_dropdown.scss | 0 .../{ => vendor}/bootstrap/scss/_forms.scss | 0 .../bootstrap/scss/_functions.scss | 0 .../{ => vendor}/bootstrap/scss/_grid.scss | 0 .../{ => vendor}/bootstrap/scss/_images.scss | 0 .../bootstrap/scss/_input-group.scss | 0 .../bootstrap/scss/_jumbotron.scss | 0 .../bootstrap/scss/_list-group.scss | 0 .../{ => vendor}/bootstrap/scss/_media.scss | 0 .../{ => vendor}/bootstrap/scss/_mixins.scss | 0 .../{ => vendor}/bootstrap/scss/_modal.scss | 0 .../{ => vendor}/bootstrap/scss/_nav.scss | 0 .../{ => vendor}/bootstrap/scss/_navbar.scss | 0 .../bootstrap/scss/_pagination.scss | 0 .../{ => vendor}/bootstrap/scss/_popover.scss | 0 .../{ => vendor}/bootstrap/scss/_print.scss | 0 .../bootstrap/scss/_progress.scss | 0 .../{ => vendor}/bootstrap/scss/_reboot.scss | 0 .../{ => vendor}/bootstrap/scss/_root.scss | 0 .../bootstrap/scss/_spinners.scss | 0 .../{ => vendor}/bootstrap/scss/_tables.scss | 0 .../{ => vendor}/bootstrap/scss/_toasts.scss | 0 .../{ => vendor}/bootstrap/scss/_tooltip.scss | 0 .../bootstrap/scss/_transitions.scss | 0 .../{ => vendor}/bootstrap/scss/_type.scss | 0 .../bootstrap/scss/_utilities.scss | 0 .../bootstrap/scss/_variables.scss | 0 .../bootstrap/scss/bootstrap-grid.scss | 0 .../bootstrap/scss/bootstrap-reboot.scss | 0 .../bootstrap/scss/bootstrap.scss | 0 .../bootstrap/scss/mixins/_alert.scss | 0 .../scss/mixins/_background-variant.scss | 0 .../bootstrap/scss/mixins/_badge.scss | 0 .../bootstrap/scss/mixins/_border-radius.scss | 0 .../bootstrap/scss/mixins/_box-shadow.scss | 0 .../bootstrap/scss/mixins/_breakpoints.scss | 0 .../bootstrap/scss/mixins/_buttons.scss | 0 .../bootstrap/scss/mixins/_caret.scss | 0 .../bootstrap/scss/mixins/_clearfix.scss | 0 .../bootstrap/scss/mixins/_deprecate.scss | 0 .../bootstrap/scss/mixins/_float.scss | 0 .../bootstrap/scss/mixins/_forms.scss | 0 .../bootstrap/scss/mixins/_gradients.scss | 0 .../scss/mixins/_grid-framework.scss | 0 .../bootstrap/scss/mixins/_grid.scss | 0 .../bootstrap/scss/mixins/_hover.scss | 0 .../bootstrap/scss/mixins/_image.scss | 0 .../bootstrap/scss/mixins/_list-group.scss | 0 .../bootstrap/scss/mixins/_lists.scss | 0 .../bootstrap/scss/mixins/_nav-divider.scss | 0 .../bootstrap/scss/mixins/_pagination.scss | 0 .../bootstrap/scss/mixins/_reset-text.scss | 0 .../bootstrap/scss/mixins/_resize.scss | 0 .../bootstrap/scss/mixins/_screen-reader.scss | 0 .../bootstrap/scss/mixins/_size.scss | 0 .../bootstrap/scss/mixins/_table-row.scss | 0 .../bootstrap/scss/mixins/_text-emphasis.scss | 0 .../bootstrap/scss/mixins/_text-hide.scss | 0 .../bootstrap/scss/mixins/_text-truncate.scss | 0 .../bootstrap/scss/mixins/_transition.scss | 0 .../bootstrap/scss/mixins/_visibility.scss | 0 .../bootstrap/scss/utilities/_align.scss | 0 .../bootstrap/scss/utilities/_background.scss | 0 .../bootstrap/scss/utilities/_borders.scss | 0 .../bootstrap/scss/utilities/_clearfix.scss | 0 .../bootstrap/scss/utilities/_display.scss | 0 .../bootstrap/scss/utilities/_embed.scss | 0 .../bootstrap/scss/utilities/_flex.scss | 0 .../bootstrap/scss/utilities/_float.scss | 0 .../scss/utilities/_interactions.scss | 0 .../bootstrap/scss/utilities/_overflow.scss | 0 .../bootstrap/scss/utilities/_position.scss | 0 .../scss/utilities/_screenreaders.scss | 0 .../bootstrap/scss/utilities/_shadows.scss | 0 .../bootstrap/scss/utilities/_sizing.scss | 0 .../bootstrap/scss/utilities/_spacing.scss | 0 .../scss/utilities/_stretched-link.scss | 0 .../bootstrap/scss/utilities/_text.scss | 0 .../bootstrap/scss/utilities/_visibility.scss | 0 .../bootstrap/scss/vendor/_rfs.scss | 0 .../datatables/dataTables.bootstrap4.css | 0 .../datatables/dataTables.bootstrap4.js | 0 .../datatables/dataTables.bootstrap4.min.css | 0 .../datatables/dataTables.bootstrap4.min.js | 0 .../datatables/jquery.dataTables.js | 0 .../datatables/jquery.dataTables.min.js | 0 .../jquery.easing.compatibility.js | 0 .../jquery-easing/jquery.easing.js | 0 .../jquery-easing/jquery.easing.min.js | 0 .../frontend/{ => vendor}/jquery/jquery.js | 0 .../{ => vendor}/jquery/jquery.min.js | 0 .../{ => vendor}/jquery/jquery.min.map | 0 .../{ => vendor}/jquery/jquery.slim.js | 0 .../{ => vendor}/jquery/jquery.slim.min.js | 0 .../{ => vendor}/jquery/jquery.slim.min.map | 0 frontend/templates/frontend/footer.html | 10 +-- frontend/templates/frontend/header.html | 2 +- frontend/templates/frontend/sidebar.html | 7 ++ kumify/settings.py | 9 ++- kumify/urls.py | 4 + localsettings.dist.py | 6 +- mood/models.py | 2 +- mood/templates/mood/notification_delete.html | 16 ++++ mood/templates/mood/notification_edit.html | 30 ++++++++ mood/templates/mood/notification_list.html | 28 +++++++ mood/urls.py | 6 +- mood/views.py | 77 ++++++++++++++++++- msgio/__init__.py | 0 msgio/admin.py | 12 +++ msgio/apps.py | 5 ++ msgio/gateways/__init__.py | 0 msgio/gateways/telegram.py | 31 ++++++++ msgio/handler.py | 29 +++++++ msgio/helpers.py | 0 msgio/models.py | 38 +++++++++ msgio/signals.py | 5 ++ msgio/tests.py | 3 + msgio/views.py | 3 + requirements.txt | 3 +- 146 files changed, 359 insertions(+), 13 deletions(-) create mode 100644 cronhandler/__init__.py create mode 100644 cronhandler/admin.py create mode 100644 cronhandler/apps.py create mode 100644 cronhandler/models.py create mode 100644 cronhandler/signals.py create mode 100644 cronhandler/tests.py create mode 100644 cronhandler/urls.py create mode 100644 cronhandler/views.py rename frontend/static/frontend/{ => vendor}/bootstrap/js/bootstrap.bundle.js (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/js/bootstrap.bundle.js.map (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/js/bootstrap.bundle.min.js (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/js/bootstrap.bundle.min.js.map (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/js/bootstrap.js (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/js/bootstrap.js.map (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/js/bootstrap.min.js (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/js/bootstrap.min.js.map (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_alert.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_badge.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_breadcrumb.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_button-group.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_buttons.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_card.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_carousel.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_close.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_code.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_custom-forms.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_dropdown.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_forms.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_functions.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_grid.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_images.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_input-group.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_jumbotron.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_list-group.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_media.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_mixins.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_modal.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_nav.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_navbar.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_pagination.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_popover.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_print.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_progress.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_reboot.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_root.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_spinners.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_tables.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_toasts.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_tooltip.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_transitions.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_type.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_utilities.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/_variables.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/bootstrap-grid.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/bootstrap-reboot.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/bootstrap.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_alert.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_background-variant.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_badge.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_border-radius.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_box-shadow.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_breakpoints.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_buttons.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_caret.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_clearfix.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_deprecate.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_float.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_forms.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_gradients.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_grid-framework.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_grid.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_hover.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_image.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_list-group.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_lists.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_nav-divider.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_pagination.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_reset-text.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_resize.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_screen-reader.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_size.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_table-row.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_text-emphasis.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_text-hide.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_text-truncate.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_transition.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/mixins/_visibility.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/utilities/_align.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/utilities/_background.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/utilities/_borders.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/utilities/_clearfix.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/utilities/_display.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/utilities/_embed.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/utilities/_flex.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/utilities/_float.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/utilities/_interactions.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/utilities/_overflow.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/utilities/_position.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/utilities/_screenreaders.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/utilities/_shadows.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/utilities/_sizing.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/utilities/_spacing.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/utilities/_stretched-link.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/utilities/_text.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/utilities/_visibility.scss (100%) rename frontend/static/frontend/{ => vendor}/bootstrap/scss/vendor/_rfs.scss (100%) rename frontend/static/frontend/{ => vendor}/datatables/dataTables.bootstrap4.css (100%) rename frontend/static/frontend/{ => vendor}/datatables/dataTables.bootstrap4.js (100%) rename frontend/static/frontend/{ => vendor}/datatables/dataTables.bootstrap4.min.css (100%) rename frontend/static/frontend/{ => vendor}/datatables/dataTables.bootstrap4.min.js (100%) rename frontend/static/frontend/{ => vendor}/datatables/jquery.dataTables.js (100%) rename frontend/static/frontend/{ => vendor}/datatables/jquery.dataTables.min.js (100%) rename frontend/static/frontend/{ => vendor}/jquery-easing/jquery.easing.compatibility.js (100%) rename frontend/static/frontend/{ => vendor}/jquery-easing/jquery.easing.js (100%) rename frontend/static/frontend/{ => vendor}/jquery-easing/jquery.easing.min.js (100%) rename frontend/static/frontend/{ => vendor}/jquery/jquery.js (100%) rename frontend/static/frontend/{ => vendor}/jquery/jquery.min.js (100%) rename frontend/static/frontend/{ => vendor}/jquery/jquery.min.map (100%) rename frontend/static/frontend/{ => vendor}/jquery/jquery.slim.js (100%) rename frontend/static/frontend/{ => vendor}/jquery/jquery.slim.min.js (100%) rename frontend/static/frontend/{ => vendor}/jquery/jquery.slim.min.map (100%) create mode 100644 mood/templates/mood/notification_delete.html create mode 100644 mood/templates/mood/notification_edit.html create mode 100644 mood/templates/mood/notification_list.html create mode 100644 msgio/__init__.py create mode 100644 msgio/admin.py create mode 100644 msgio/apps.py create mode 100644 msgio/gateways/__init__.py create mode 100644 msgio/gateways/telegram.py create mode 100644 msgio/handler.py create mode 100644 msgio/helpers.py create mode 100644 msgio/models.py create mode 100644 msgio/signals.py create mode 100644 msgio/tests.py create mode 100644 msgio/views.py diff --git a/INSTALL.md b/INSTALL.md index e7e115e..93cc52f 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -34,4 +34,14 @@ The application is then available at [http://localhost:8000/]. If you want to make your Kumify instance available through a network, you will need to set up something like gunicorn and nginx. How this works is beyond the scope of this document. To prepare your static files for this, make sure ```STATIC_ROOT``` is set to the correct location in localsettings.py if you don't use S3, then run: -```python3 manage.py collectstatic``` \ No newline at end of file +```python3 manage.py collectstatic``` + +### Cron job + +In order to use scheduled tasks, you need to make sure that the ```/cron/``` endpoint is called at regular intervals. Every five minutes should work fine. Use a command like ```curl http://localhost:8000/cron/```, for example. + +### Telegram webhook + +If you wish to receive incoming messages through the Telegram gateway, your server must be reachable from the Internet. Configure a public IP/domain name as well as an HTTPS certificate, then run: + +```python3 manage.py telegramwebhook``` \ No newline at end of file diff --git a/cronhandler/__init__.py b/cronhandler/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/cronhandler/admin.py b/cronhandler/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/cronhandler/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/cronhandler/apps.py b/cronhandler/apps.py new file mode 100644 index 0000000..ca5dbe7 --- /dev/null +++ b/cronhandler/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class CronhandlerConfig(AppConfig): + name = 'cronhandler' diff --git a/cronhandler/models.py b/cronhandler/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/cronhandler/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/cronhandler/signals.py b/cronhandler/signals.py new file mode 100644 index 0000000..72976d0 --- /dev/null +++ b/cronhandler/signals.py @@ -0,0 +1,3 @@ +from django.dispatch import Signal + +cron = Signal() \ No newline at end of file diff --git a/cronhandler/tests.py b/cronhandler/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/cronhandler/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/cronhandler/urls.py b/cronhandler/urls.py new file mode 100644 index 0000000..3da875a --- /dev/null +++ b/cronhandler/urls.py @@ -0,0 +1,9 @@ +from .views import CronHandlerView + +from django.urls import path + +app_name = "cron" + +urlpatterns = [ + path('', CronHandlerView.as_view(), name="cronhandler"), +] \ No newline at end of file diff --git a/cronhandler/views.py b/cronhandler/views.py new file mode 100644 index 0000000..3a6e140 --- /dev/null +++ b/cronhandler/views.py @@ -0,0 +1,8 @@ +from django.views.generic import View +from django.http import HttpResponse + +from .signals import cron + +class CronHandlerView(View): + def get(self, *args, **kwargs): + return HttpResponse() \ No newline at end of file diff --git a/frontend/static/frontend/bootstrap/js/bootstrap.bundle.js b/frontend/static/frontend/vendor/bootstrap/js/bootstrap.bundle.js similarity index 100% rename from frontend/static/frontend/bootstrap/js/bootstrap.bundle.js rename to frontend/static/frontend/vendor/bootstrap/js/bootstrap.bundle.js diff --git a/frontend/static/frontend/bootstrap/js/bootstrap.bundle.js.map b/frontend/static/frontend/vendor/bootstrap/js/bootstrap.bundle.js.map similarity index 100% rename from frontend/static/frontend/bootstrap/js/bootstrap.bundle.js.map rename to frontend/static/frontend/vendor/bootstrap/js/bootstrap.bundle.js.map diff --git a/frontend/static/frontend/bootstrap/js/bootstrap.bundle.min.js b/frontend/static/frontend/vendor/bootstrap/js/bootstrap.bundle.min.js similarity index 100% rename from frontend/static/frontend/bootstrap/js/bootstrap.bundle.min.js rename to frontend/static/frontend/vendor/bootstrap/js/bootstrap.bundle.min.js diff --git a/frontend/static/frontend/bootstrap/js/bootstrap.bundle.min.js.map b/frontend/static/frontend/vendor/bootstrap/js/bootstrap.bundle.min.js.map similarity index 100% rename from frontend/static/frontend/bootstrap/js/bootstrap.bundle.min.js.map rename to frontend/static/frontend/vendor/bootstrap/js/bootstrap.bundle.min.js.map diff --git a/frontend/static/frontend/bootstrap/js/bootstrap.js b/frontend/static/frontend/vendor/bootstrap/js/bootstrap.js similarity index 100% rename from frontend/static/frontend/bootstrap/js/bootstrap.js rename to frontend/static/frontend/vendor/bootstrap/js/bootstrap.js diff --git a/frontend/static/frontend/bootstrap/js/bootstrap.js.map b/frontend/static/frontend/vendor/bootstrap/js/bootstrap.js.map similarity index 100% rename from frontend/static/frontend/bootstrap/js/bootstrap.js.map rename to frontend/static/frontend/vendor/bootstrap/js/bootstrap.js.map diff --git a/frontend/static/frontend/bootstrap/js/bootstrap.min.js b/frontend/static/frontend/vendor/bootstrap/js/bootstrap.min.js similarity index 100% rename from frontend/static/frontend/bootstrap/js/bootstrap.min.js rename to frontend/static/frontend/vendor/bootstrap/js/bootstrap.min.js diff --git a/frontend/static/frontend/bootstrap/js/bootstrap.min.js.map b/frontend/static/frontend/vendor/bootstrap/js/bootstrap.min.js.map similarity index 100% rename from frontend/static/frontend/bootstrap/js/bootstrap.min.js.map rename to frontend/static/frontend/vendor/bootstrap/js/bootstrap.min.js.map diff --git a/frontend/static/frontend/bootstrap/scss/_alert.scss b/frontend/static/frontend/vendor/bootstrap/scss/_alert.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_alert.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_alert.scss diff --git a/frontend/static/frontend/bootstrap/scss/_badge.scss b/frontend/static/frontend/vendor/bootstrap/scss/_badge.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_badge.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_badge.scss diff --git a/frontend/static/frontend/bootstrap/scss/_breadcrumb.scss b/frontend/static/frontend/vendor/bootstrap/scss/_breadcrumb.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_breadcrumb.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_breadcrumb.scss diff --git a/frontend/static/frontend/bootstrap/scss/_button-group.scss b/frontend/static/frontend/vendor/bootstrap/scss/_button-group.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_button-group.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_button-group.scss diff --git a/frontend/static/frontend/bootstrap/scss/_buttons.scss b/frontend/static/frontend/vendor/bootstrap/scss/_buttons.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_buttons.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_buttons.scss diff --git a/frontend/static/frontend/bootstrap/scss/_card.scss b/frontend/static/frontend/vendor/bootstrap/scss/_card.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_card.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_card.scss diff --git a/frontend/static/frontend/bootstrap/scss/_carousel.scss b/frontend/static/frontend/vendor/bootstrap/scss/_carousel.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_carousel.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_carousel.scss diff --git a/frontend/static/frontend/bootstrap/scss/_close.scss b/frontend/static/frontend/vendor/bootstrap/scss/_close.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_close.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_close.scss diff --git a/frontend/static/frontend/bootstrap/scss/_code.scss b/frontend/static/frontend/vendor/bootstrap/scss/_code.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_code.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_code.scss diff --git a/frontend/static/frontend/bootstrap/scss/_custom-forms.scss b/frontend/static/frontend/vendor/bootstrap/scss/_custom-forms.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_custom-forms.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_custom-forms.scss diff --git a/frontend/static/frontend/bootstrap/scss/_dropdown.scss b/frontend/static/frontend/vendor/bootstrap/scss/_dropdown.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_dropdown.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_dropdown.scss diff --git a/frontend/static/frontend/bootstrap/scss/_forms.scss b/frontend/static/frontend/vendor/bootstrap/scss/_forms.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_forms.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_forms.scss diff --git a/frontend/static/frontend/bootstrap/scss/_functions.scss b/frontend/static/frontend/vendor/bootstrap/scss/_functions.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_functions.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_functions.scss diff --git a/frontend/static/frontend/bootstrap/scss/_grid.scss b/frontend/static/frontend/vendor/bootstrap/scss/_grid.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_grid.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_grid.scss diff --git a/frontend/static/frontend/bootstrap/scss/_images.scss b/frontend/static/frontend/vendor/bootstrap/scss/_images.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_images.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_images.scss diff --git a/frontend/static/frontend/bootstrap/scss/_input-group.scss b/frontend/static/frontend/vendor/bootstrap/scss/_input-group.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_input-group.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_input-group.scss diff --git a/frontend/static/frontend/bootstrap/scss/_jumbotron.scss b/frontend/static/frontend/vendor/bootstrap/scss/_jumbotron.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_jumbotron.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_jumbotron.scss diff --git a/frontend/static/frontend/bootstrap/scss/_list-group.scss b/frontend/static/frontend/vendor/bootstrap/scss/_list-group.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_list-group.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_list-group.scss diff --git a/frontend/static/frontend/bootstrap/scss/_media.scss b/frontend/static/frontend/vendor/bootstrap/scss/_media.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_media.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_media.scss diff --git a/frontend/static/frontend/bootstrap/scss/_mixins.scss b/frontend/static/frontend/vendor/bootstrap/scss/_mixins.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_mixins.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_mixins.scss diff --git a/frontend/static/frontend/bootstrap/scss/_modal.scss b/frontend/static/frontend/vendor/bootstrap/scss/_modal.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_modal.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_modal.scss diff --git a/frontend/static/frontend/bootstrap/scss/_nav.scss b/frontend/static/frontend/vendor/bootstrap/scss/_nav.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_nav.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_nav.scss diff --git a/frontend/static/frontend/bootstrap/scss/_navbar.scss b/frontend/static/frontend/vendor/bootstrap/scss/_navbar.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_navbar.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_navbar.scss diff --git a/frontend/static/frontend/bootstrap/scss/_pagination.scss b/frontend/static/frontend/vendor/bootstrap/scss/_pagination.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_pagination.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_pagination.scss diff --git a/frontend/static/frontend/bootstrap/scss/_popover.scss b/frontend/static/frontend/vendor/bootstrap/scss/_popover.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_popover.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_popover.scss diff --git a/frontend/static/frontend/bootstrap/scss/_print.scss b/frontend/static/frontend/vendor/bootstrap/scss/_print.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_print.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_print.scss diff --git a/frontend/static/frontend/bootstrap/scss/_progress.scss b/frontend/static/frontend/vendor/bootstrap/scss/_progress.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_progress.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_progress.scss diff --git a/frontend/static/frontend/bootstrap/scss/_reboot.scss b/frontend/static/frontend/vendor/bootstrap/scss/_reboot.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_reboot.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_reboot.scss diff --git a/frontend/static/frontend/bootstrap/scss/_root.scss b/frontend/static/frontend/vendor/bootstrap/scss/_root.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_root.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_root.scss diff --git a/frontend/static/frontend/bootstrap/scss/_spinners.scss b/frontend/static/frontend/vendor/bootstrap/scss/_spinners.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_spinners.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_spinners.scss diff --git a/frontend/static/frontend/bootstrap/scss/_tables.scss b/frontend/static/frontend/vendor/bootstrap/scss/_tables.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_tables.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_tables.scss diff --git a/frontend/static/frontend/bootstrap/scss/_toasts.scss b/frontend/static/frontend/vendor/bootstrap/scss/_toasts.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_toasts.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_toasts.scss diff --git a/frontend/static/frontend/bootstrap/scss/_tooltip.scss b/frontend/static/frontend/vendor/bootstrap/scss/_tooltip.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_tooltip.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_tooltip.scss diff --git a/frontend/static/frontend/bootstrap/scss/_transitions.scss b/frontend/static/frontend/vendor/bootstrap/scss/_transitions.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_transitions.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_transitions.scss diff --git a/frontend/static/frontend/bootstrap/scss/_type.scss b/frontend/static/frontend/vendor/bootstrap/scss/_type.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_type.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_type.scss diff --git a/frontend/static/frontend/bootstrap/scss/_utilities.scss b/frontend/static/frontend/vendor/bootstrap/scss/_utilities.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_utilities.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_utilities.scss diff --git a/frontend/static/frontend/bootstrap/scss/_variables.scss b/frontend/static/frontend/vendor/bootstrap/scss/_variables.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/_variables.scss rename to frontend/static/frontend/vendor/bootstrap/scss/_variables.scss diff --git a/frontend/static/frontend/bootstrap/scss/bootstrap-grid.scss b/frontend/static/frontend/vendor/bootstrap/scss/bootstrap-grid.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/bootstrap-grid.scss rename to frontend/static/frontend/vendor/bootstrap/scss/bootstrap-grid.scss diff --git a/frontend/static/frontend/bootstrap/scss/bootstrap-reboot.scss b/frontend/static/frontend/vendor/bootstrap/scss/bootstrap-reboot.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/bootstrap-reboot.scss rename to frontend/static/frontend/vendor/bootstrap/scss/bootstrap-reboot.scss diff --git a/frontend/static/frontend/bootstrap/scss/bootstrap.scss b/frontend/static/frontend/vendor/bootstrap/scss/bootstrap.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/bootstrap.scss rename to frontend/static/frontend/vendor/bootstrap/scss/bootstrap.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_alert.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_alert.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_alert.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_alert.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_background-variant.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_background-variant.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_background-variant.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_background-variant.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_badge.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_badge.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_badge.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_badge.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_border-radius.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_border-radius.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_border-radius.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_border-radius.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_box-shadow.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_box-shadow.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_box-shadow.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_box-shadow.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_breakpoints.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_breakpoints.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_breakpoints.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_breakpoints.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_buttons.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_buttons.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_buttons.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_buttons.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_caret.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_caret.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_caret.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_caret.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_clearfix.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_clearfix.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_clearfix.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_clearfix.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_deprecate.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_deprecate.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_deprecate.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_deprecate.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_float.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_float.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_float.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_float.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_forms.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_forms.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_forms.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_forms.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_gradients.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_gradients.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_gradients.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_gradients.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_grid-framework.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_grid-framework.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_grid-framework.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_grid-framework.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_grid.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_grid.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_grid.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_grid.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_hover.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_hover.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_hover.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_hover.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_image.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_image.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_image.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_image.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_list-group.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_list-group.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_list-group.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_list-group.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_lists.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_lists.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_lists.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_lists.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_nav-divider.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_nav-divider.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_nav-divider.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_nav-divider.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_pagination.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_pagination.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_pagination.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_pagination.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_reset-text.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_reset-text.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_reset-text.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_reset-text.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_resize.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_resize.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_resize.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_resize.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_screen-reader.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_screen-reader.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_screen-reader.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_screen-reader.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_size.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_size.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_size.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_size.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_table-row.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_table-row.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_table-row.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_table-row.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_text-emphasis.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_text-emphasis.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_text-emphasis.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_text-emphasis.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_text-hide.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_text-hide.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_text-hide.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_text-hide.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_text-truncate.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_text-truncate.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_text-truncate.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_text-truncate.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_transition.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_transition.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_transition.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_transition.scss diff --git a/frontend/static/frontend/bootstrap/scss/mixins/_visibility.scss b/frontend/static/frontend/vendor/bootstrap/scss/mixins/_visibility.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/mixins/_visibility.scss rename to frontend/static/frontend/vendor/bootstrap/scss/mixins/_visibility.scss diff --git a/frontend/static/frontend/bootstrap/scss/utilities/_align.scss b/frontend/static/frontend/vendor/bootstrap/scss/utilities/_align.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/utilities/_align.scss rename to frontend/static/frontend/vendor/bootstrap/scss/utilities/_align.scss diff --git a/frontend/static/frontend/bootstrap/scss/utilities/_background.scss b/frontend/static/frontend/vendor/bootstrap/scss/utilities/_background.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/utilities/_background.scss rename to frontend/static/frontend/vendor/bootstrap/scss/utilities/_background.scss diff --git a/frontend/static/frontend/bootstrap/scss/utilities/_borders.scss b/frontend/static/frontend/vendor/bootstrap/scss/utilities/_borders.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/utilities/_borders.scss rename to frontend/static/frontend/vendor/bootstrap/scss/utilities/_borders.scss diff --git a/frontend/static/frontend/bootstrap/scss/utilities/_clearfix.scss b/frontend/static/frontend/vendor/bootstrap/scss/utilities/_clearfix.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/utilities/_clearfix.scss rename to frontend/static/frontend/vendor/bootstrap/scss/utilities/_clearfix.scss diff --git a/frontend/static/frontend/bootstrap/scss/utilities/_display.scss b/frontend/static/frontend/vendor/bootstrap/scss/utilities/_display.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/utilities/_display.scss rename to frontend/static/frontend/vendor/bootstrap/scss/utilities/_display.scss diff --git a/frontend/static/frontend/bootstrap/scss/utilities/_embed.scss b/frontend/static/frontend/vendor/bootstrap/scss/utilities/_embed.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/utilities/_embed.scss rename to frontend/static/frontend/vendor/bootstrap/scss/utilities/_embed.scss diff --git a/frontend/static/frontend/bootstrap/scss/utilities/_flex.scss b/frontend/static/frontend/vendor/bootstrap/scss/utilities/_flex.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/utilities/_flex.scss rename to frontend/static/frontend/vendor/bootstrap/scss/utilities/_flex.scss diff --git a/frontend/static/frontend/bootstrap/scss/utilities/_float.scss b/frontend/static/frontend/vendor/bootstrap/scss/utilities/_float.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/utilities/_float.scss rename to frontend/static/frontend/vendor/bootstrap/scss/utilities/_float.scss diff --git a/frontend/static/frontend/bootstrap/scss/utilities/_interactions.scss b/frontend/static/frontend/vendor/bootstrap/scss/utilities/_interactions.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/utilities/_interactions.scss rename to frontend/static/frontend/vendor/bootstrap/scss/utilities/_interactions.scss diff --git a/frontend/static/frontend/bootstrap/scss/utilities/_overflow.scss b/frontend/static/frontend/vendor/bootstrap/scss/utilities/_overflow.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/utilities/_overflow.scss rename to frontend/static/frontend/vendor/bootstrap/scss/utilities/_overflow.scss diff --git a/frontend/static/frontend/bootstrap/scss/utilities/_position.scss b/frontend/static/frontend/vendor/bootstrap/scss/utilities/_position.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/utilities/_position.scss rename to frontend/static/frontend/vendor/bootstrap/scss/utilities/_position.scss diff --git a/frontend/static/frontend/bootstrap/scss/utilities/_screenreaders.scss b/frontend/static/frontend/vendor/bootstrap/scss/utilities/_screenreaders.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/utilities/_screenreaders.scss rename to frontend/static/frontend/vendor/bootstrap/scss/utilities/_screenreaders.scss diff --git a/frontend/static/frontend/bootstrap/scss/utilities/_shadows.scss b/frontend/static/frontend/vendor/bootstrap/scss/utilities/_shadows.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/utilities/_shadows.scss rename to frontend/static/frontend/vendor/bootstrap/scss/utilities/_shadows.scss diff --git a/frontend/static/frontend/bootstrap/scss/utilities/_sizing.scss b/frontend/static/frontend/vendor/bootstrap/scss/utilities/_sizing.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/utilities/_sizing.scss rename to frontend/static/frontend/vendor/bootstrap/scss/utilities/_sizing.scss diff --git a/frontend/static/frontend/bootstrap/scss/utilities/_spacing.scss b/frontend/static/frontend/vendor/bootstrap/scss/utilities/_spacing.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/utilities/_spacing.scss rename to frontend/static/frontend/vendor/bootstrap/scss/utilities/_spacing.scss diff --git a/frontend/static/frontend/bootstrap/scss/utilities/_stretched-link.scss b/frontend/static/frontend/vendor/bootstrap/scss/utilities/_stretched-link.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/utilities/_stretched-link.scss rename to frontend/static/frontend/vendor/bootstrap/scss/utilities/_stretched-link.scss diff --git a/frontend/static/frontend/bootstrap/scss/utilities/_text.scss b/frontend/static/frontend/vendor/bootstrap/scss/utilities/_text.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/utilities/_text.scss rename to frontend/static/frontend/vendor/bootstrap/scss/utilities/_text.scss diff --git a/frontend/static/frontend/bootstrap/scss/utilities/_visibility.scss b/frontend/static/frontend/vendor/bootstrap/scss/utilities/_visibility.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/utilities/_visibility.scss rename to frontend/static/frontend/vendor/bootstrap/scss/utilities/_visibility.scss diff --git a/frontend/static/frontend/bootstrap/scss/vendor/_rfs.scss b/frontend/static/frontend/vendor/bootstrap/scss/vendor/_rfs.scss similarity index 100% rename from frontend/static/frontend/bootstrap/scss/vendor/_rfs.scss rename to frontend/static/frontend/vendor/bootstrap/scss/vendor/_rfs.scss diff --git a/frontend/static/frontend/datatables/dataTables.bootstrap4.css b/frontend/static/frontend/vendor/datatables/dataTables.bootstrap4.css similarity index 100% rename from frontend/static/frontend/datatables/dataTables.bootstrap4.css rename to frontend/static/frontend/vendor/datatables/dataTables.bootstrap4.css diff --git a/frontend/static/frontend/datatables/dataTables.bootstrap4.js b/frontend/static/frontend/vendor/datatables/dataTables.bootstrap4.js similarity index 100% rename from frontend/static/frontend/datatables/dataTables.bootstrap4.js rename to frontend/static/frontend/vendor/datatables/dataTables.bootstrap4.js diff --git a/frontend/static/frontend/datatables/dataTables.bootstrap4.min.css b/frontend/static/frontend/vendor/datatables/dataTables.bootstrap4.min.css similarity index 100% rename from frontend/static/frontend/datatables/dataTables.bootstrap4.min.css rename to frontend/static/frontend/vendor/datatables/dataTables.bootstrap4.min.css diff --git a/frontend/static/frontend/datatables/dataTables.bootstrap4.min.js b/frontend/static/frontend/vendor/datatables/dataTables.bootstrap4.min.js similarity index 100% rename from frontend/static/frontend/datatables/dataTables.bootstrap4.min.js rename to frontend/static/frontend/vendor/datatables/dataTables.bootstrap4.min.js diff --git a/frontend/static/frontend/datatables/jquery.dataTables.js b/frontend/static/frontend/vendor/datatables/jquery.dataTables.js similarity index 100% rename from frontend/static/frontend/datatables/jquery.dataTables.js rename to frontend/static/frontend/vendor/datatables/jquery.dataTables.js diff --git a/frontend/static/frontend/datatables/jquery.dataTables.min.js b/frontend/static/frontend/vendor/datatables/jquery.dataTables.min.js similarity index 100% rename from frontend/static/frontend/datatables/jquery.dataTables.min.js rename to frontend/static/frontend/vendor/datatables/jquery.dataTables.min.js diff --git a/frontend/static/frontend/jquery-easing/jquery.easing.compatibility.js b/frontend/static/frontend/vendor/jquery-easing/jquery.easing.compatibility.js similarity index 100% rename from frontend/static/frontend/jquery-easing/jquery.easing.compatibility.js rename to frontend/static/frontend/vendor/jquery-easing/jquery.easing.compatibility.js diff --git a/frontend/static/frontend/jquery-easing/jquery.easing.js b/frontend/static/frontend/vendor/jquery-easing/jquery.easing.js similarity index 100% rename from frontend/static/frontend/jquery-easing/jquery.easing.js rename to frontend/static/frontend/vendor/jquery-easing/jquery.easing.js diff --git a/frontend/static/frontend/jquery-easing/jquery.easing.min.js b/frontend/static/frontend/vendor/jquery-easing/jquery.easing.min.js similarity index 100% rename from frontend/static/frontend/jquery-easing/jquery.easing.min.js rename to frontend/static/frontend/vendor/jquery-easing/jquery.easing.min.js diff --git a/frontend/static/frontend/jquery/jquery.js b/frontend/static/frontend/vendor/jquery/jquery.js similarity index 100% rename from frontend/static/frontend/jquery/jquery.js rename to frontend/static/frontend/vendor/jquery/jquery.js diff --git a/frontend/static/frontend/jquery/jquery.min.js b/frontend/static/frontend/vendor/jquery/jquery.min.js similarity index 100% rename from frontend/static/frontend/jquery/jquery.min.js rename to frontend/static/frontend/vendor/jquery/jquery.min.js diff --git a/frontend/static/frontend/jquery/jquery.min.map b/frontend/static/frontend/vendor/jquery/jquery.min.map similarity index 100% rename from frontend/static/frontend/jquery/jquery.min.map rename to frontend/static/frontend/vendor/jquery/jquery.min.map diff --git a/frontend/static/frontend/jquery/jquery.slim.js b/frontend/static/frontend/vendor/jquery/jquery.slim.js similarity index 100% rename from frontend/static/frontend/jquery/jquery.slim.js rename to frontend/static/frontend/vendor/jquery/jquery.slim.js diff --git a/frontend/static/frontend/jquery/jquery.slim.min.js b/frontend/static/frontend/vendor/jquery/jquery.slim.min.js similarity index 100% rename from frontend/static/frontend/jquery/jquery.slim.min.js rename to frontend/static/frontend/vendor/jquery/jquery.slim.min.js diff --git a/frontend/static/frontend/jquery/jquery.slim.min.map b/frontend/static/frontend/vendor/jquery/jquery.slim.min.map similarity index 100% rename from frontend/static/frontend/jquery/jquery.slim.min.map rename to frontend/static/frontend/vendor/jquery/jquery.slim.min.map diff --git a/frontend/templates/frontend/footer.html b/frontend/templates/frontend/footer.html index 2bd6732..81162d6 100644 --- a/frontend/templates/frontend/footer.html +++ b/frontend/templates/frontend/footer.html @@ -1,19 +1,19 @@ {% load static %} - - + + - + - - + + diff --git a/frontend/templates/frontend/header.html b/frontend/templates/frontend/header.html index a834ee9..700cc2f 100644 --- a/frontend/templates/frontend/header.html +++ b/frontend/templates/frontend/header.html @@ -20,7 +20,7 @@ - + {% for style in styles %} diff --git a/frontend/templates/frontend/sidebar.html b/frontend/templates/frontend/sidebar.html index 056556b..fded251 100644 --- a/frontend/templates/frontend/sidebar.html +++ b/frontend/templates/frontend/sidebar.html @@ -48,6 +48,13 @@ Moods + + + diff --git a/kumify/settings.py b/kumify/settings.py index 5d975a0..f8e2427 100644 --- a/kumify/settings.py +++ b/kumify/settings.py @@ -18,6 +18,8 @@ INSTALLED_APPS = [ 'common', 'frontend', 'mood', + 'msgio', + 'cronhandler', ] MIDDLEWARE = [ @@ -121,4 +123,9 @@ LOGIN_REDIRECT_URL = '/' LOGOUT_REDIRECT_URL = "/" DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage' if not AWS_ACCESS_KEY_ID else 'storages.backends.s3boto3.S3Boto3Storage' -STATICFILES_STORAGE = 'storages.backends.s3boto3.S3StaticStorage' if AWS_ACCESS_KEY_ID else 'django.contrib.staticfiles.storage.StaticFilesStorage' \ No newline at end of file +STATICFILES_STORAGE = 'storages.backends.s3boto3.S3StaticStorage' if AWS_ACCESS_KEY_ID else 'django.contrib.staticfiles.storage.StaticFilesStorage' + +try: + assert TELEGRAM_TOKEN +except NameError: + TELEGRAM_TOKEN = None \ No newline at end of file diff --git a/kumify/urls.py b/kumify/urls.py index b351302..4888ee9 100644 --- a/kumify/urls.py +++ b/kumify/urls.py @@ -16,9 +16,13 @@ Including another URLconf from django.contrib import admin from django.urls import path, include +from msgio.views import TelegramWebhookView + urlpatterns = [ path('admin/', admin.site.urls), path('accounts/', include('django.contrib.auth.urls')), path('', include("frontend.urls", "frontend")), path('mood/', include("mood.urls", "mood")), + path('cron/', include("cronhandler.urls", "cron")), + path('webhooks/telegram/', TelegramWebhookView.as_view()), ] diff --git a/localsettings.dist.py b/localsettings.dist.py index 5e72e95..f846d59 100644 --- a/localsettings.dist.py +++ b/localsettings.dist.py @@ -39,4 +39,8 @@ DB_HOST = None # Host name of the database server DB_PORT = 3306 # Port of the database server - the default value usually works DB_NAME = None # Name of the database to be used DB_USER = None # User name to authenticate with -DB_PASS = None # Password to authenticate with \ No newline at end of file +DB_PASS = None # Password to authenticate with + +# If you wish to enable the Telegram gateway to send and receive messages, enter the token you have received from the @BotFather here. + +TELEGRAM_TOKEN = None \ No newline at end of file diff --git a/mood/models.py b/mood/models.py index 492a93b..2cdf383 100644 --- a/mood/models.py +++ b/mood/models.py @@ -68,4 +68,4 @@ class AspectRating(models.Model): class StatusAspectRating(models.Model): status = models.ForeignKey(Status, models.CASCADE) aspect_rating = models.ForeignKey(AspectRating, models.SET_NULL, null=True) - comment = models.TextField(null=True, blank=True) \ No newline at end of file + comment = models.TextField(null=True, blank=True) diff --git a/mood/templates/mood/notification_delete.html b/mood/templates/mood/notification_delete.html new file mode 100644 index 0000000..2d8ab17 --- /dev/null +++ b/mood/templates/mood/notification_delete.html @@ -0,0 +1,16 @@ +{% extends "frontend/base.html" %} +{% block "content" %} + +
+
+
Delete {{ object.time }} Notification?
+
+
+
+

Are you sure you wish to delete this notification? This cannot be undone.

+
{% csrf_token %}
+
+
+
+ +{% endblock %} \ No newline at end of file diff --git a/mood/templates/mood/notification_edit.html b/mood/templates/mood/notification_edit.html new file mode 100644 index 0000000..5f4566e --- /dev/null +++ b/mood/templates/mood/notification_edit.html @@ -0,0 +1,30 @@ +{% extends "frontend/base.html" %} +{% block "content" %} + +{% if form.errors %} +{% for field in form %} +{% for error in field.errors %} + +{% endfor %} +{% endfor %} +{% endif %} +
+
+
Edit {{ object.time }}
+
+
+
+ {% csrf_token %} +
+ + +
+
+ +
+
+
+ +{% endblock %} \ No newline at end of file diff --git a/mood/templates/mood/notification_list.html b/mood/templates/mood/notification_list.html new file mode 100644 index 0000000..5a82619 --- /dev/null +++ b/mood/templates/mood/notification_list.html @@ -0,0 +1,28 @@ +{% extends "frontend/base.html" %} +{% block "content" %} + +
+
+
Your Daily Notifications
+
+
+
+ + + + + + + + {% for notification in object_list %} + + + + {% endfor %} + +
Time
{{ notification.time }}
+
+
+
+ +{% endblock %} \ No newline at end of file diff --git a/mood/urls.py b/mood/urls.py index a5064d0..b4341a4 100644 --- a/mood/urls.py +++ b/mood/urls.py @@ -1,4 +1,4 @@ -from .views import StatusListView, StatusViewView, StatusDeleteView, StatusEditView, StatusCreateView, ActivityListView, ActivityEditView, ActivityCreateView, ActivityDeleteView, MoodListView, MoodEditView +from .views import StatusListView, StatusViewView, StatusDeleteView, StatusEditView, StatusCreateView, ActivityListView, ActivityEditView, ActivityCreateView, ActivityDeleteView, MoodListView, MoodEditView, NotificationCreateView, NotificationDeleteView, NotificationEditView, NotificationListView from django.urls import path, include @@ -16,4 +16,8 @@ urlpatterns = [ path('activity//delete/', ActivityDeleteView.as_view(), name="activity_delete"), path('mood/', MoodListView.as_view(), name="mood_list"), path('mood//edit/', MoodEditView.as_view(), name="mood_edit"), + path('notification/', NotificationListView.as_view(), name="notification_list"), + path('notification//edit/', NotificationEditView.as_view(), name="notification_edit"), + path('notification//delete/', NotificationDeleteView.as_view(), name="notification_delete"), + path('notification/new/', NotificationCreateView.as_view(), name="notification_create"), ] \ No newline at end of file diff --git a/mood/views.py b/mood/views.py index d6f5779..a711867 100644 --- a/mood/views.py +++ b/mood/views.py @@ -2,10 +2,12 @@ from django.views.generic import TemplateView, ListView, UpdateView, DetailView, from django.contrib.auth.mixins import LoginRequiredMixin from django.shortcuts import get_object_or_404 from django.urls import reverse_lazy +from django.http import HttpResponseRedirect from .models import Status, Activity, Mood, StatusMedia, StatusActivity from .forms import StatusForm +from msgio.models import NotificationDailySchedule, Notification class StatusListView(LoginRequiredMixin, ListView): template_name = "mood/status_list.html" @@ -235,4 +237,77 @@ class MoodCreateView(LoginRequiredMixin, CreateView): return super().form_valid(form) def get_success_url(self): - return reverse_lazy("mood:activity_list") \ No newline at end of file + return reverse_lazy("mood:activity_list") + + +class NotificationListView(LoginRequiredMixin, ListView): + template_name = "mood/notification_list.html" + model = NotificationDailySchedule + fields = ["time"] + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["title"] = "Notifications" + context["subtitle"] = "The daily reminders you have set up." + context["buttons"] = [(reverse_lazy("mood:notification_create"), "New Notification", "plus")] + return context + + def get_queryset(self): + return NotificationDailySchedule.objects.filter(notification__recipient=self.request.user, notification__app="mood") + + +class NotificationCreateView(LoginRequiredMixin, CreateView): + template_name = "mood/notification_edit.html" + model = NotificationDailySchedule + fields = ["time"] + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["title"] = "Create Notification" + context["subtitle"] = "Add a new daily notification." + return context + + def form_valid(self, form): + notification = Notification.objects.create(content="Hi, it's time for a new Kumify entry! Go to %KUMIFYURL% to document your mood!", recipient=self.request.user, app="mood") + obj = form.save(commit=False) + obj.notification = notification + return super().form_valid(form) + + def get_success_url(self): + return reverse_lazy("mood:notification_list") + + +class NotificationEditView(LoginRequiredMixin, UpdateView): + template_name = "mood/notification_edit.html" + model = NotificationDailySchedule + fields = ["time"] + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["title"] = "Edit Notification" + context["subtitle"] = "Change the time of a daily notification." + context["buttons"] = [(reverse_lazy("mood:notification_delete", args=[self.kwargs["id"]]), "Delete Notification")] + return context + + def get_success_url(self): + return reverse_lazy("mood:notification_list") + + def get_object(self): + return get_object_or_404(NotificationDailySchedule, notification__recipient=self.request.user, id=self.kwargs["id"]) + + +class NotificationDeleteView(LoginRequiredMixin, DeleteView): + template_name = "mood/activity_delete.html" + model = NotificationDailySchedule + + def get_object(self): + return get_object_or_404(NotificationDailySchedule, notification__recipient=self.request.user, id=self.kwargs["id"]) + + def delete(self, request, *args, **kwargs): + self.object = self.get_object() + success_url = self.get_success_url() + self.object.notification.delete() + return HttpResponseRedirect(success_url) + + def get_success_url(self): + return reverse_lazy("mood:notification_list") \ No newline at end of file diff --git a/msgio/__init__.py b/msgio/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/msgio/admin.py b/msgio/admin.py new file mode 100644 index 0000000..2e847d1 --- /dev/null +++ b/msgio/admin.py @@ -0,0 +1,12 @@ +from django.contrib import admin + +from .models import GatewayUser, GatewayUserSetting, Notification, NotificationDailySchedule, NotificationDatetimeSchedule, NotificationDispatcher + +# Register your models here. + +admin.site.register(GatewayUser) +admin.site.register(GatewayUserSetting) +admin.site.register(Notification) +admin.site.register(NotificationDailySchedule) +admin.site.register(NotificationDatetimeSchedule) +admin.site.register(NotificationDispatcher) \ No newline at end of file diff --git a/msgio/apps.py b/msgio/apps.py new file mode 100644 index 0000000..fa0ea74 --- /dev/null +++ b/msgio/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class MsgioConfig(AppConfig): + name = 'msgio' diff --git a/msgio/gateways/__init__.py b/msgio/gateways/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/msgio/gateways/telegram.py b/msgio/gateways/telegram.py new file mode 100644 index 0000000..7c8c907 --- /dev/null +++ b/msgio/gateways/telegram.py @@ -0,0 +1,31 @@ +from django.conf import settings +from django.views.generic import View +from django.dispatch import receiver + +import json + +import telegram + +from ..signals import send_message +from ..models import GatewayUser + +class TelegramWebhookView(View): + def post(self, *args, **kwargs): + pass # TODO: Implement webhook receiver and management tool + +class TelegramDispatcher: + def __init__(self, token=settings.TELEGRAM_TOKEN): + self.bot = telegram.Bot(token=token) + + def send(self, message, chat_id): + self.bot.sendMessage(chat_id=chat_id, text=message) + +@receiver(send_message) +def telegram_sender(sender, **kwargs): + if kwargs["dispatcher"] == "telegram": + notification = kwargs["notification"] + + settings = GatewayUser.objects.get(user=notification.recipient, gateway="telegram") + chat_id = settings.gatewayusersetting_set.get(key="chat_id").value + + TelegramDispatcher().send(notification.content, chat_id) \ No newline at end of file diff --git a/msgio/handler.py b/msgio/handler.py new file mode 100644 index 0000000..1c2a7b4 --- /dev/null +++ b/msgio/handler.py @@ -0,0 +1,29 @@ +from django.dispatch import receiver +from django.utils.timezone import now + +from cronhandler.signals import cron + +from .models import Notification + +@receiver(cron) +def send_notifications(sender, **kwargs): + returns = [] + for notification in Notification.objects.all(): + for datetime in notification.notificationdatetimeschedule_set.all(): + if not datetime.sent and datetime.datetime <= now(): + try: + returns.append(notification.send()) + datetime.sent = True + datetime.save() + except: + pass # TODO: Implement some sort of error logging / admin notification + for daily in notification.notificationdailyschedule_set.all(): + if ((not daily.last_sent) or daily.last_sent < now().date()) and daily.time <= now().time(): + try: + returns.append(notification.send()) + daily.last_sent = now().date() + daily.save() + except: + pass # TODO: See above + + return returns \ No newline at end of file diff --git a/msgio/helpers.py b/msgio/helpers.py new file mode 100644 index 0000000..e69de29 diff --git a/msgio/models.py b/msgio/models.py new file mode 100644 index 0000000..833457f --- /dev/null +++ b/msgio/models.py @@ -0,0 +1,38 @@ +from django.db import models +from django.contrib.auth import get_user_model + +from .signals import send_message + +# Create your models here. + +class Notification(models.Model): + content = models.TextField() + recipient = models.ForeignKey(get_user_model(), models.CASCADE) + app = models.CharField(max_length=64, null=True, blank=True) + + def send(self): + for dispatcher in self.notificationdispatcher_set.all(): + return send_message.send_robust(self.__class__, dispatcher=dispatcher.dispatcher, notification=self) + +class NotificationDispatcher(models.Model): + notification = models.ForeignKey(Notification, models.CASCADE) + dispatcher = models.CharField(max_length=64) + +class NotificationDatetimeSchedule(models.Model): + notification = models.ForeignKey(Notification, models.CASCADE) + datetime = models.DateTimeField() + sent = models.BooleanField(default=False) + +class NotificationDailySchedule(models.Model): + notification = models.ForeignKey(Notification, models.CASCADE) + time = models.TimeField() + last_sent = models.DateField(null=True, blank=True) + +class GatewayUser(models.Model): + user = models.ForeignKey(get_user_model(), models.CASCADE) + gateway = models.CharField(max_length=64) + +class GatewayUserSetting(models.Model): + gatewayuser = models.ForeignKey(GatewayUser, models.CASCADE) + key = models.CharField(max_length=64) + value = models.CharField(max_length=256) \ No newline at end of file diff --git a/msgio/signals.py b/msgio/signals.py new file mode 100644 index 0000000..bd2f629 --- /dev/null +++ b/msgio/signals.py @@ -0,0 +1,5 @@ +from django.dispatch import Signal + +send_message = Signal() +message_sent = Signal() +message_received = Signal() \ No newline at end of file diff --git a/msgio/tests.py b/msgio/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/msgio/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/msgio/views.py b/msgio/views.py new file mode 100644 index 0000000..b1d30a8 --- /dev/null +++ b/msgio/views.py @@ -0,0 +1,3 @@ +from .handler import send_notifications + +from .gateways.telegram import TelegramWebhookView \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index a576b07..9008f88 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,4 +7,5 @@ django-storages git+git://github.com/Chive/django-multiupload.git@ba52e161a68ce19062c3655e89544c2d377990a0#egg=multiupload mysqlclient boto3 -argon2_cffi \ No newline at end of file +argon2_cffi +python-telegram-bot \ No newline at end of file