Repository: garpixcms/garpix_notify (language: python)

Issue:
Update tasks.py
Fix update beat_schedule


Discussion / hints:

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a6f22f8..a922bf8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+### 5.5.0 (10.05.2022)
+
+- Added the possibility of mass mailing,
+- Telecom operators added,
+- Fixed bugs.
+
 ### 5.4.2 (06.05.2022)
 
 - In "system" notifications, the id of this notification is additionally received
diff --git a/Pipfile b/Pipfile
index fecb0e8..91f12c1 100644
--- a/Pipfile
+++ b/Pipfile
@@ -15,7 +15,7 @@ celery = ">=4.4.2"
 django-solo = "*"
 fcm-django = "==0.3.11"
 requests = "*"
-django-ckeditor = "*"
+django-ckeditor = "==6.3.0"
 python-telegram-bot = "*"
 viberbot = "*"
 django-uuslug = "*"
@@ -24,7 +24,7 @@ redis = "*"
 channels = "==3.0.3"
 channels-redis = "==3.3.1"
 asgiref = "==3.2.10"
-mistune= "==0.8.4"
+mistune = "==0.8.4"
 
 [dev-packages]
 
diff --git a/Pipfile.lock b/Pipfile.lock
index cbde397..f7a7e97 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
 {
     "_meta": {
         "hash": {
-            "sha256": "a923168a61f7acc925f5f7433b3108898021fd4c243c5e1204f7542fce1205a6"
+            "sha256": "bea2ebfac5949402dcbda71e07a26e16511272179003610abcc67601124d1f61"
         },
         "pipfile-spec": 6,
         "requires": {
@@ -25,11 +25,10 @@
         },
         "amqp": {
             "hashes": [
-                "sha256:1e5f707424e544078ca196e72ae6a14887ce74e02bd126be54b7c03c971bef18",
-                "sha256:9cd81f7b023fc04bbb108718fbac674f06901b77bfcdce85b10e2a5d0ee91be5"
+                "sha256:2c1b13fecc0893e946c65cbd5f36427861cffa4ea2201d8f6fca22e2a373b5e2",
+                "sha256:6f0956d2c23d8fa6e7691934d8c3930eadb44972cbbd1a7ae3a520f735d43359"
             ],
-            "markers": "python_version >= '3.6'",
-            "version": "==5.0.9"
+            "version": "==5.1.1"
         },
         "apscheduler": {
             "hashes": [
@@ -51,7 +50,6 @@
                 "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15",
                 "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"
             ],
-            "markers": "python_version >= '3.6'",
             "version": "==4.0.2"
         },
         "attrs": {
@@ -59,15 +57,13 @@
                 "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4",
                 "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"
             ],
-            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
             "version": "==21.4.0"
         },
         "autobahn": {
             "hashes": [
-                "sha256:bd6f46315419ca0a5be4109f737410208ad5f19718f67ca6a4a674cc66ca9b18"
+                "sha256:57b7acf228d50d83cf327372b889e2a168a869275b26e17917ed0b4cf4d823a6"
             ],
-            "markers": "python_version >= '3.7'",
-            "version": "==21.11.1"
+            "version": "==22.4.2"
         },
         "automat": {
             "hashes": [
@@ -100,11 +96,10 @@
         },
         "bandit": {
             "hashes": [
-                "sha256:a81b00b5436e6880fa8ad6799bc830e02032047713cbb143a12939ac67eb756c",
-                "sha256:f5acd838e59c038a159b5c621cf0f8270b279e884eadd7b782d7491c02add0d4"
+                "sha256:2d63a8c573417bae338962d4b9b06fbc6080f74ecd955a092849e1e65c717bd2",
+                "sha256:412d3f259dab4077d0e7f0c11f50f650cc7d10db905d98f6520a95a18049658a"
             ],
-            "markers": "python_version >= '3.5'",
-            "version": "==1.7.1"
+            "version": "==1.7.4"
         },
         "billiard": {
             "hashes": [
@@ -115,27 +110,25 @@
         },
         "bleach": {
             "hashes": [
-                "sha256:0900d8b37eba61a802ee40ac0061f8c2b5dee29c1927dd1d233e075ebf5a71da",
-                "sha256:4d2651ab93271d1129ac9cbc679f524565cc8a1b791909c4a51eac4446a15994"
+                "sha256:08a1fe86d253b5c88c92cc3d810fd8048a16d15762e1e5b74d502256e5926aa1",
+                "sha256:c6d6cc054bdc9c83b48b8083e236e5f00f238428666d2ce2e083eaa5fd568565"
             ],
-            "markers": "python_version >= '3.6'",
-            "version": "==4.1.0"
+            "version": "==5.0.0"
         },
         "cachetools": {
             "hashes": [
                 "sha256:2cc0b89715337ab6dbba85b5b50effe2b0c74e035d83ee8ed637cf52f12ae001",
                 "sha256:61b5ed1e22a0924aed1d23b478f37e8d52549ff8a961de2909c69bf950020cff"
             ],
-            "markers": "python_version ~= '3.5'",
             "version": "==4.2.2"
         },
         "celery": {
             "hashes": [
-                "sha256:8aacd02fc23a02760686d63dde1eb0daa9f594e735e73ea8fb15c2ff15cb608c",
-                "sha256:e2cd41667ad97d4f6a2f4672d1c6a6ebada194c619253058b5f23704aaadaa82"
+                "sha256:d1398cadf30f576266b34370e28e880306ec55f7a4b6307549b0ae9c15663481",
+                "sha256:da31f8eae7607b1582e5ee2d3f2d6f58450585afd23379491e3d9229d08102d0"
             ],
             "index": "pypi",
-            "version": "==5.2.3"
+            "version": "==5.2.6"
         },
         "certifi": {
             "hashes": [
@@ -217,26 +210,24 @@
         },
         "charset-normalizer": {
             "hashes": [
-                "sha256:876d180e9d7432c5d1dfd4c5d26b72f099d503e8fcc0feb7532c9289be60fcbd",
-                "sha256:cb957888737fc0bbcd78e3df769addb41fd1ff8cf950dc9e7ad7793f1bf44455"
+                "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597",
+                "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"
             ],
             "markers": "python_version >= '3'",
-            "version": "==2.0.10"
+            "version": "==2.0.12"
         },
         "click": {
             "hashes": [
-                "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3",
-                "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"
+                "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e",
+                "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"
             ],
-            "markers": "python_version >= '3.6'",
-            "version": "==8.0.3"
+            "version": "==8.1.3"
         },
         "click-didyoumean": {
             "hashes": [
                 "sha256:a0713dc7a1de3f06bc0df5a9567ad19ead2d3d5689b434768a6145bff77c0667",
                 "sha256:f184f0d851d96b6d29297354ed981b7dd71df7ff500d82fa6d11f0856bee8035"
             ],
-            "markers": "python_full_version >= '3.6.2' and python_full_version < '4.0.0'",
             "version": "==0.3.0"
         },
         "click-plugins": {
@@ -258,9 +249,16 @@
                 "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b",
                 "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"
             ],
-            "markers": "python_version >= '3.5'",
+            "markers": "python_version > '3.4'",
             "version": "==0.4.4"
         },
+        "commonmark": {
+            "hashes": [
+                "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60",
+                "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"
+            ],
+            "version": "==0.9.1"
+        },
         "constantly": {
             "hashes": [
                 "sha256:586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35",
@@ -270,89 +268,83 @@
         },
         "coverage": {
             "hashes": [
-                "sha256:01774a2c2c729619760320270e42cd9e797427ecfddd32c2a7b639cdc481f3c0",
-                "sha256:03b20e52b7d31be571c9c06b74746746d4eb82fc260e594dc662ed48145e9efd",
-                "sha256:0a7726f74ff63f41e95ed3a89fef002916c828bb5fcae83b505b49d81a066884",
-                "sha256:1219d760ccfafc03c0822ae2e06e3b1248a8e6d1a70928966bafc6838d3c9e48",
-                "sha256:13362889b2d46e8d9f97c421539c97c963e34031ab0cb89e8ca83a10cc71ac76",
-                "sha256:174cf9b4bef0db2e8244f82059a5a72bd47e1d40e71c68ab055425172b16b7d0",
-                "sha256:17e6c11038d4ed6e8af1407d9e89a2904d573be29d51515f14262d7f10ef0a64",
-                "sha256:215f8afcc02a24c2d9a10d3790b21054b58d71f4b3c6f055d4bb1b15cecce685",
-                "sha256:22e60a3ca5acba37d1d4a2ee66e051f5b0e1b9ac950b5b0cf4aa5366eda41d47",
-                "sha256:2641f803ee9f95b1f387f3e8f3bf28d83d9b69a39e9911e5bfee832bea75240d",
-                "sha256:276651978c94a8c5672ea60a2656e95a3cce2a3f31e9fb2d5ebd4c215d095840",
-                "sha256:3f7c17209eef285c86f819ff04a6d4cbee9b33ef05cbcaae4c0b4e8e06b3ec8f",
-                "sha256:3feac4084291642165c3a0d9eaebedf19ffa505016c4d3db15bfe235718d4971",
-                "sha256:49dbff64961bc9bdd2289a2bda6a3a5a331964ba5497f694e2cbd540d656dc1c",
-                "sha256:4e547122ca2d244f7c090fe3f4b5a5861255ff66b7ab6d98f44a0222aaf8671a",
-                "sha256:5829192582c0ec8ca4a2532407bc14c2f338d9878a10442f5d03804a95fac9de",
-                "sha256:5d6b09c972ce9200264c35a1d53d43ca55ef61836d9ec60f0d44273a31aa9f17",
-                "sha256:600617008aa82032ddeace2535626d1bc212dfff32b43989539deda63b3f36e4",
-                "sha256:619346d57c7126ae49ac95b11b0dc8e36c1dd49d148477461bb66c8cf13bb521",
-                "sha256:63c424e6f5b4ab1cf1e23a43b12f542b0ec2e54f99ec9f11b75382152981df57",
-                "sha256:6dbc1536e105adda7a6312c778f15aaabe583b0e9a0b0a324990334fd458c94b",
-                "sha256:6e1394d24d5938e561fbeaa0cd3d356207579c28bd1792f25a068743f2d5b282",
-                "sha256:86f2e78b1eff847609b1ca8050c9e1fa3bd44ce755b2ec30e70f2d3ba3844644",
-                "sha256:8bdfe9ff3a4ea37d17f172ac0dff1e1c383aec17a636b9b35906babc9f0f5475",
-                "sha256:8e2c35a4c1f269704e90888e56f794e2d9c0262fb0c1b1c8c4ee44d9b9e77b5d",
-                "sha256:92b8c845527eae547a2a6617d336adc56394050c3ed8a6918683646328fbb6da",
-                "sha256:9365ed5cce5d0cf2c10afc6add145c5037d3148585b8ae0e77cc1efdd6aa2953",
-                "sha256:9a29311bd6429be317c1f3fe4bc06c4c5ee45e2fa61b2a19d4d1d6111cb94af2",
-                "sha256:9a2b5b52be0a8626fcbffd7e689781bf8c2ac01613e77feda93d96184949a98e",
-                "sha256:a4bdeb0a52d1d04123b41d90a4390b096f3ef38eee35e11f0b22c2d031222c6c",
-                "sha256:a9c8c4283e17690ff1a7427123ffb428ad6a52ed720d550e299e8291e33184dc",
-                "sha256:b637c57fdb8be84e91fac60d9325a66a5981f8086c954ea2772efe28425eaf64",
-                "sha256:bf154ba7ee2fd613eb541c2bc03d3d9ac667080a737449d1a3fb342740eb1a74",
-                "sha256:c254b03032d5a06de049ce8bca8338a5185f07fb76600afff3c161e053d88617",
-                "sha256:c332d8f8d448ded473b97fefe4a0983265af21917d8b0cdcb8bb06b2afe632c3",
-                "sha256:c7912d1526299cb04c88288e148c6c87c0df600eca76efd99d84396cfe00ef1d",
-                "sha256:cfd9386c1d6f13b37e05a91a8583e802f8059bebfccde61a418c5808dea6bbfa",
-                "sha256:d5d2033d5db1d58ae2d62f095e1aefb6988af65b4b12cb8987af409587cc0739",
-                "sha256:dca38a21e4423f3edb821292e97cec7ad38086f84313462098568baedf4331f8",
-                "sha256:e2cad8093172b7d1595b4ad66f24270808658e11acf43a8f95b41276162eb5b8",
-                "sha256:e3db840a4dee542e37e09f30859f1612da90e1c5239a6a2498c473183a50e781",
-                "sha256:edcada2e24ed68f019175c2b2af2a8b481d3d084798b8c20d15d34f5c733fa58",
-                "sha256:f467bbb837691ab5a8ca359199d3429a11a01e6dfb3d9dcc676dc035ca93c0a9",
-                "sha256:f506af4f27def639ba45789fa6fde45f9a217da0be05f8910458e4557eed020c",
-                "sha256:f614fc9956d76d8a88a88bb41ddc12709caa755666f580af3a688899721efecd",
-                "sha256:f9afb5b746781fc2abce26193d1c817b7eb0e11459510fba65d2bd77fe161d9e",
-                "sha256:fb8b8ee99b3fffe4fd86f4c81b35a6bf7e4462cba019997af2fe679365db0c49"
+                "sha256:06f54765cdbce99901871d50fe9f41d58213f18e98b170a30ca34f47de7dd5e8",
+                "sha256:114944e6061b68a801c5da5427b9173a0dd9d32cd5fcc18a13de90352843737d",
+                "sha256:1414e8b124611bf4df8d77215bd32cba6e3425da8ce9c1f1046149615e3a9a31",
+                "sha256:2781c43bffbbec2b8867376d4d61916f5e9c4cc168232528562a61d1b4b01879",
+                "sha256:2ab88a01cd180b5640ccc9c47232e31924d5f9967ab7edd7e5c91c68eee47a69",
+                "sha256:338c417613f15596af9eb7a39353b60abec9d8ce1080aedba5ecee6a5d85f8d3",
+                "sha256:3401b0d2ed9f726fadbfa35102e00d1b3547b73772a1de5508ef3bdbcb36afe7",
+                "sha256:462105283de203df8de58a68c1bb4ba2a8a164097c2379f664fa81d6baf94b81",
+                "sha256:4cd696aa712e6cd16898d63cf66139dc70d998f8121ab558f0e1936396dbc579",
+                "sha256:4d06380e777dd6b35ee936f333d55b53dc4a8271036ff884c909cf6e94be8b6c",
+                "sha256:61f4fbf3633cb0713437291b8848634ea97f89c7e849c2be17a665611e433f53",
+                "sha256:6d4a6f30f611e657495cc81a07ff7aa8cd949144e7667c5d3e680d73ba7a70e4",
+                "sha256:6f5fee77ec3384b934797f1873758f796dfb4f167e1296dc00f8b2e023ce6ee9",
+                "sha256:75b5dbffc334e0beb4f6c503fb95e6d422770fd2d1b40a64898ea26d6c02742d",
+                "sha256:7835f76a081787f0ca62a53504361b3869840a1620049b56d803a8cb3a9eeea3",
+                "sha256:79bf405432428e989cad7b8bc60581963238f7645ae8a404f5dce90236cc0293",
+                "sha256:8329635c0781927a2c6ae068461e19674c564e05b86736ab8eb29c420ee7dc20",
+                "sha256:8586b177b4407f988731eb7f41967415b2197f35e2a6ee1a9b9b561f6323c8e9",
+                "sha256:892e7fe32191960da559a14536768a62e83e87bbb867e1b9c643e7e0fbce2579",
+                "sha256:91502bf27cbd5c83c95cfea291ef387469f2387508645602e1ca0fd8a4ba7548",
+                "sha256:93b16b08f94c92cab88073ffd185070cdcb29f1b98df8b28e6649145b7f2c90d",
+                "sha256:9c9441d57b0963cf8340268ad62fc83de61f1613034b79c2b1053046af0c5284",
+                "sha256:ad8f9068f5972a46d50fe5f32c09d6ee11da69c560fcb1b4c3baea246ca4109b",
+                "sha256:afb03f981fadb5aed1ac6e3dd34f0488e1a0875623d557b6fad09b97a942b38a",
+                "sha256:b5ba058610e8289a07db2a57bce45a1793ec0d3d11db28c047aae2aa1a832572",
+                "sha256:baa8be8aba3dd1e976e68677be68a960a633a6d44c325757aefaa4d66175050f",
+                "sha256:c06455121a089252b5943ea682187a4e0a5cf0a3fb980eb8e7ce394b144430a9",
+                "sha256:c1a9942e282cc9d3ed522cd3e3cab081149b27ea3bda72d6f61f84eaf88c1a63",
+                "sha256:c488db059848702aff30aa1d90ef87928d4e72e4f00717343800546fdbff0a94",
+                "sha256:cb5311d6ccbd22578c80028c5e292a7ab9adb91bd62c1982087fad75abe2e63d",
+                "sha256:cbe91bc84be4e5ef0b1480d15c7b18e29c73bdfa33e07d3725da7d18e1b0aff2",
+                "sha256:cc692c9ee18f0dd3214843779ba6b275ee4bb9b9a5745ba64265bce911aefd1a",
+                "sha256:cc972d829ad5ef4d4c5fcabd2bbe2add84ce8236f64ba1c0c72185da3a273130",
+                "sha256:ceb6534fcdfb5c503affb6b1130db7b5bfc8a0f77fa34880146f7a5c117987d0",
+                "sha256:d522f1dc49127eab0bfbba4e90fa068ecff0899bbf61bf4065c790ddd6c177fe",
+                "sha256:db094a6a4ae6329ed322a8973f83630b12715654c197dd392410400a5bfa1a73",
+                "sha256:df32ee0f4935a101e4b9a5f07b617d884a531ed5666671ff6ac66d2e8e8246d8",
+                "sha256:e5af1feee71099ae2e3b086ec04f57f9950e1be9ecf6c420696fea7977b84738",
+                "sha256:e814a4a5a1d95223b08cdb0f4f57029e8eab22ffdbae2f97107aeef28554517e",
+                "sha256:f8cabc5fd0091976ab7b020f5708335033e422de25e20ddf9416bdce2b7e07d8",
+                "sha256:fbc86ae8cc129c801e7baaafe3addf3c8d49c9c1597c44bdf2d78139707c3c62"
             ],
             "index": "pypi",
-            "version": "==6.2"
+            "version": "==6.3.3"
         },
         "cryptography": {
             "hashes": [
-                "sha256:0a817b961b46894c5ca8a66b599c745b9a3d9f822725221f0e0fe49dc043a3a3",
-                "sha256:2d87cdcb378d3cfed944dac30596da1968f88fb96d7fc34fdae30a99054b2e31",
-                "sha256:30ee1eb3ebe1644d1c3f183d115a8c04e4e603ed6ce8e394ed39eea4a98469ac",
-                "sha256:391432971a66cfaf94b21c24ab465a4cc3e8bf4a939c1ca5c3e3a6e0abebdbcf",
-                "sha256:39bdf8e70eee6b1c7b289ec6e5d84d49a6bfa11f8b8646b5b3dfe41219153316",
-                "sha256:4caa4b893d8fad33cf1964d3e51842cd78ba87401ab1d2e44556826df849a8ca",
-                "sha256:53e5c1dc3d7a953de055d77bef2ff607ceef7a2aac0353b5d630ab67f7423638",
-                "sha256:596f3cd67e1b950bc372c33f1a28a0692080625592ea6392987dba7f09f17a94",
-                "sha256:5d59a9d55027a8b88fd9fd2826c4392bd487d74bf628bb9d39beecc62a644c12",
-                "sha256:6c0c021f35b421ebf5976abf2daacc47e235f8b6082d3396a2fe3ccd537ab173",
-                "sha256:73bc2d3f2444bcfeac67dd130ff2ea598ea5f20b40e36d19821b4df8c9c5037b",
-                "sha256:74d6c7e80609c0f4c2434b97b80c7f8fdfaa072ca4baab7e239a15d6d70ed73a",
-                "sha256:7be0eec337359c155df191d6ae00a5e8bbb63933883f4f5dffc439dac5348c3f",
-                "sha256:94ae132f0e40fe48f310bba63f477f14a43116f05ddb69d6fa31e93f05848ae2",
-                "sha256:bb5829d027ff82aa872d76158919045a7c1e91fbf241aec32cb07956e9ebd3c9",
-                "sha256:ca238ceb7ba0bdf6ce88c1b74a87bffcee5afbfa1e41e173b1ceb095b39add46",
-                "sha256:ca28641954f767f9822c24e927ad894d45d5a1e501767599647259cbf030b903",
-                "sha256:e0344c14c9cb89e76eb6a060e67980c9e35b3f36691e15e1b7a9e58a0a6c6dc3",
-                "sha256:ebc15b1c22e55c4d5566e3ca4db8689470a0ca2babef8e3a9ee057a8b82ce4b1",
-                "sha256:ec63da4e7e4a5f924b90af42eddf20b698a70e58d86a72d943857c4c6045b3ee"
-            ],
-            "markers": "python_version >= '3.6'",
-            "version": "==36.0.1"
+                "sha256:093cb351031656d3ee2f4fa1be579a8c69c754cf874206be1d4cf3b542042804",
+                "sha256:0cc20f655157d4cfc7bada909dc5cc228211b075ba8407c46467f63597c78178",
+                "sha256:1b9362d34363f2c71b7853f6251219298124aa4cc2075ae2932e64c91a3e2717",
+                "sha256:1f3bfbd611db5cb58ca82f3deb35e83af34bb8cf06043fa61500157d50a70982",
+                "sha256:2bd1096476aaac820426239ab534b636c77d71af66c547b9ddcd76eb9c79e004",
+                "sha256:31fe38d14d2e5f787e0aecef831457da6cec68e0bb09a35835b0b44ae8b988fe",
+                "sha256:3b8398b3d0efc420e777c40c16764d6870bcef2eb383df9c6dbb9ffe12c64452",
+                "sha256:3c81599befb4d4f3d7648ed3217e00d21a9341a9a688ecdd615ff72ffbed7336",
+                "sha256:419c57d7b63f5ec38b1199a9521d77d7d1754eb97827bbb773162073ccd8c8d4",
+                "sha256:46f4c544f6557a2fefa7ac8ac7d1b17bf9b647bd20b16decc8fbcab7117fbc15",
+                "sha256:471e0d70201c069f74c837983189949aa0d24bb2d751b57e26e3761f2f782b8d",
+                "sha256:59b281eab51e1b6b6afa525af2bd93c16d49358404f814fe2c2410058623928c",
+                "sha256:731c8abd27693323b348518ed0e0705713a36d79fdbd969ad968fbef0979a7e0",
+                "sha256:95e590dd70642eb2079d280420a888190aa040ad20f19ec8c6e097e38aa29e06",
+                "sha256:a68254dd88021f24a68b613d8c51d5c5e74d735878b9e32cc0adf19d1f10aaf9",
+                "sha256:a7d5137e556cc0ea418dca6186deabe9129cee318618eb1ffecbd35bee55ddc1",
+                "sha256:aeaba7b5e756ea52c8861c133c596afe93dd716cbcacae23b80bc238202dc023",
+                "sha256:dc26bb134452081859aa21d4990474ddb7e863aa39e60d1592800a8865a702de",
+                "sha256:e53258e69874a306fcecb88b7534d61820db8a98655662a3dd2ec7f1afd9132f",
+                "sha256:ef15c2df7656763b4ff20a9bc4381d8352e6640cfeb95c2972c38ef508e75181",
+                "sha256:f224ad253cc9cea7568f49077007d2263efa57396a2f2f78114066fd54b5c68e",
+                "sha256:f8ec91983e638a9bcd75b39f1396e5c0dc2330cbd9ce4accefe68717e6779e0a"
+            ],
+            "version": "==37.0.2"
         },
         "daphne": {
             "hashes": [
                 "sha256:76ffae916ba3aa66b46996c14fa713e46004788167a4873d647544e750e0e99f",
                 "sha256:a9af943c79717bc52fe64a3c236ae5d3adccc8b5be19c881b442d2c3db233393"
             ],
-            "markers": "python_version >= '3.6'",
             "version": "==3.0.2"
         },
         "deprecated": {
@@ -360,7 +352,6 @@
                 "sha256:43ac5335da90c31c24ba028af536a91d41d53f9e6901ddb021bcc572ce44e38d",
                 "sha256:64756e3e14c8c5eea9795d93c524551432a0be75629f8f29e67ab8caf076c76d"
             ],
-            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
             "version": "==1.2.13"
         },
         "django": {
@@ -373,18 +364,18 @@
         },
         "django-ckeditor": {
             "hashes": [
-                "sha256:9f66420907e41f5b4e698fa5671a00a86995776735f2c4696174aed4640fcbd8",
-                "sha256:df64dc9e62790ef824f609605d31be847bdbce1cc7aa94e49bd5ca60d7aa79bb"
+                "sha256:b5c03d77b9fe848bf12520512a82d07533afa8678040731b1d4d86c1dcea8344",
+                "sha256:d04f350f4a200c2a0f96307fc8827bd4e87af5694fb12d53189ba92025b2da37"
             ],
             "index": "pypi",
-            "version": "==6.2.0"
+            "version": "==6.3.0"
         },
         "django-js-asset": {
             "hashes": [
-                "sha256:8ec12017f26eec524cab436c64ae73033368a372970af4cf42d9354fcb166bdd",
-                "sha256:c163ae80d2e0b22d8fb598047cd0dcef31f81830e127cfecae278ad574167260"
+                "sha256:86f9f300d682537ddaf0487dc2ab356581b8f50c069bdba91d334a46e449f923",
+                "sha256:adc1ee1efa853fad42054b540c02205344bb406c9bddf87c9e5377a41b7db90f"
             ],
-            "version": "==1.2.2"
+            "version": "==2.0.0"
         },
         "django-solo": {
             "hashes": [
@@ -396,26 +387,26 @@
         },
         "django-uuslug": {
             "hashes": [
-                "sha256:bf0872618acc61f7ace65b96ae71d63f347595c8b990942834f1ba9448af19ec"
+                "sha256:047e713eeddecf11a674d4cd27ac72407f85ef13196856ba8dfeb4d691d521d4",
+                "sha256:5029077e9682db81a9f847cec9dc33c07f2e455e31f98931869e6220ca65a3e9"
             ],
             "index": "pypi",
-            "version": "==1.2.0"
+            "version": "==2.0.0"
         },
         "docutils": {
             "hashes": [
                 "sha256:23010f129180089fbcd3bc08cfefccb3b890b0050e1ca00c867036e9d161b98c",
                 "sha256:679987caf361a7539d76e584cbeddc311e3aee937877c87346f31debc63e9d06"
             ],
-            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
             "version": "==0.18.1"
         },
         "environs": {
             "hashes": [
-                "sha256:b1cb81fbc0568d85c8ca32328e17bd756a2bb16cff54371d18d15d1832b692aa",
-                "sha256:b5a197f70c590e8ad2d60d145ea2a2e90d4b1b05cdd04f8e18132d2760123971"
+                "sha256:1e549569a3de49c05f856f40bce86979e7d5ffbbc4398e7f338574c220189124",
+                "sha256:a76307b36fbe856bdca7ee9161e6c466fd7fcffc297109a118c59b54e27e30c9"
             ],
             "index": "pypi",
-            "version": "==9.4.0"
+            "version": "==9.5.0"
         },
         "fcm-django": {
             "hashes": [
@@ -429,7 +420,6 @@
                 "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d",
                 "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"
             ],
-            "markers": "python_version >= '3.6'",
             "version": "==4.0.1"
         },
         "flake8-polyfill": {
@@ -443,32 +433,29 @@
             "hashes": [
                 "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"
             ],
-            "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
             "version": "==0.18.2"
         },
         "garpix-qa": {
             "hashes": [
-                "sha256:1a24eb13b644c691443361bf46f775dea5e274bf59c90541af9164a7745b8e1a",
-                "sha256:9770b4c20087a3f1e498c518646508734fb48053b1821b094d5663ae529bd1ef"
+                "sha256:97daac2213d5d0cd21a7f9fbb59858b755a6ef927f1c9c950be3ae23ff46b59f",
+                "sha256:d7dc35ebd57b630afdb8b5e71fc045440e755aa82224ecb68b8dd8042fa8344a"
             ],
             "index": "pypi",
-            "version": "==1.3.0"
+            "version": "==1.9.0"
         },
         "gitdb": {
             "hashes": [
                 "sha256:8033ad4e853066ba6ca92050b9df2f89301b8fc8bf7e9324d412a63f8bf1a8fd",
                 "sha256:bac2fd45c0a1c9cf619e63a90d62bdc63892ef92387424b855792a6cabe789aa"
             ],
-            "markers": "python_version >= '3.6'",
             "version": "==4.0.9"
         },
         "gitpython": {
             "hashes": [
-                "sha256:26ac35c212d1f7b16036361ca5cff3ec66e11753a0d677fb6c48fa4e1a9dd8d6",
-                "sha256:fc8868f63a2e6d268fb25f481995ba185a85a66fcad126f039323ff6635669ee"
+                "sha256:1c885ce809e8ba2d88a29befeb385fcea06338d3640712b59ca623c220bb5704",
+                "sha256:5b68b000463593e05ff2b261acff0ff0972df8ab1b70d3cdbd41b546c8b8fc3d"
             ],
-            "markers": "python_version >= '3.7'",
-            "version": "==3.1.26"
+            "version": "==3.1.27"
         },
         "hiredis": {
             "hashes": [
@@ -514,7 +501,6 @@
                 "sha256:f52010e0a44e3d8530437e7da38d11fb822acfb0d5b12e9cd5ba655509937ca0",
                 "sha256:f8196f739092a78e4f6b1b2172679ed3343c39c61a3e9d722ce6fcf1dac2824a"
             ],
-            "markers": "python_version >= '3.6'",
             "version": "==2.0.0"
         },
         "hyperlink": {
@@ -533,11 +519,10 @@
         },
         "importlib-metadata": {
             "hashes": [
-                "sha256:899e2a40a8c4a1aec681feef45733de8a6c58f3f6a0dbed2eb6574b4387a77b6",
-                "sha256:951f0d8a5b7260e9db5e41d429285b5f451e928479f19d80818878527d36e95e"
+                "sha256:1208431ca90a8cca1a6b8af391bb53c1a2db74e5d1cef6ddced95d4b2062edc6",
+                "sha256:ea4c597ebf37142f827b8f39299579e31685c31d3a438b59f469406afd0f2539"
             ],
-            "markers": "python_version >= '3.7'",
-            "version": "==4.10.1"
+            "version": "==4.11.3"
         },
         "incremental": {
             "hashes": [
@@ -548,27 +533,25 @@
         },
         "jeepney": {
             "hashes": [
-                "sha256:1b5a0ea5c0e7b166b2f5895b91a08c14de8915afda4407fb5022a195224958ac",
-                "sha256:fa9e232dfa0c498bd0b8a3a73b8d8a31978304dcef0515adc859d4e096f96f4f"
+                "sha256:5efe48d255973902f6badc3ce55e2aa6c5c3b3bc642059ef3a91247bcfcc5806",
+                "sha256:c0a454ad016ca575060802ee4d590dd912e35c122fa04e70306de3d076cce755"
             ],
             "markers": "sys_platform == 'linux'",
-            "version": "==0.7.1"
+            "version": "==0.8.0"
         },
         "keyring": {
             "hashes": [
                 "sha256:9012508e141a80bd1c0b6778d5c610dd9f8c464d75ac6774248500503f972fb9",
                 "sha256:b0d28928ac3ec8e42ef4cc227822647a19f1d544f21f96457965dc01cf555261"
             ],
-            "markers": "python_version >= '3.7'",
             "version": "==23.5.0"
         },
         "kombu": {
             "hashes": [
-                "sha256:81a90c1de97e08d3db37dbf163eaaf667445e1068c98bfd89f051a40e9f6dbbd",
-                "sha256:eeaeb8024f3a5cfc71c9250e45cddb8493f269d74ada2f74909a93c59c4b4179"
+                "sha256:37cee3ee725f94ea8bb173eaab7c1760203ea53bbebae226328600f9d2799610",
+                "sha256:8b213b24293d3417bcf0d2f5537b7f756079e3ea232a8386dcc89a59fd2361a4"
             ],
-            "markers": "python_version >= '3.7'",
-            "version": "==5.2.3"
+            "version": "==5.2.4"
         },
         "m2r": {
             "hashes": [
@@ -586,11 +569,10 @@
         },
         "marshmallow": {
             "hashes": [
-                "sha256:04438610bc6dadbdddb22a4a55bcc7f6f8099e69580b2e67f5a681933a1f4400",
-                "sha256:4c05c1684e0e97fe779c62b91878f173b937fe097b356cd82f793464f5bc6138"
+                "sha256:2aaaab4f01ef4f5a011a21319af9fce17ab13bf28a026d1252adab0e035648d5",
+                "sha256:ff79885ed43b579782f48c251d262e062bce49c65c52412458769a4fb57ac30f"
             ],
-            "markers": "python_version >= '3.6'",
-            "version": "==3.14.1"
+            "version": "==3.15.0"
         },
         "mccabe": {
             "hashes": [
@@ -651,54 +633,58 @@
                 "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb",
                 "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"
             ],
-            "markers": "python_version >= '3.6'",
             "version": "==21.3"
         },
         "pbr": {
             "hashes": [
-                "sha256:176e8560eaf61e127817ef93d8a844803abb27a4d4637f0ff3bb783129be2e0a",
-                "sha256:672d8ebee84921862110f23fcec2acea191ef58543d34dfe9ef3d9f13c31cddf"
+                "sha256:e547125940bcc052856ded43be8e101f63828c2d94239ffbe2b327ba3d5ccf0a",
+                "sha256:e8dca2f4b43560edef58813969f52a56cef023146cbb8931626db80e6c1c4308"
             ],
-            "markers": "python_version >= '2.6'",
-            "version": "==5.8.0"
+            "version": "==5.9.0"
         },
         "pillow": {
             "hashes": [
-                "sha256:03b27b197deb4ee400ed57d8d4e572d2d8d80f825b6634daf6e2c18c3c6ccfa6",
-                "sha256:0b281fcadbb688607ea6ece7649c5d59d4bbd574e90db6cd030e9e85bde9fecc",
-                "sha256:0ebd8b9137630a7bbbff8c4b31e774ff05bbb90f7911d93ea2c9371e41039b52",
-                "sha256:113723312215b25c22df1fdf0e2da7a3b9c357a7d24a93ebbe80bfda4f37a8d4",
-                "sha256:2d16b6196fb7a54aff6b5e3ecd00f7c0bab1b56eee39214b2b223a9d938c50af",
-                "sha256:2fd8053e1f8ff1844419842fd474fc359676b2e2a2b66b11cc59f4fa0a301315",
-                "sha256:31b265496e603985fad54d52d11970383e317d11e18e856971bdbb86af7242a4",
-                "sha256:3586e12d874ce2f1bc875a3ffba98732ebb12e18fb6d97be482bd62b56803281",
-                "sha256:47f5cf60bcb9fbc46011f75c9b45a8b5ad077ca352a78185bd3e7f1d294b98bb",
-                "sha256:490e52e99224858f154975db61c060686df8a6b3f0212a678e5d2e2ce24675c9",
-                "sha256:500d397ddf4bbf2ca42e198399ac13e7841956c72645513e8ddf243b31ad2128",
-                "sha256:52abae4c96b5da630a8b4247de5428f593465291e5b239f3f843a911a3cf0105",
-                "sha256:6579f9ba84a3d4f1807c4aab4be06f373017fc65fff43498885ac50a9b47a553",
-                "sha256:68e06f8b2248f6dc8b899c3e7ecf02c9f413aab622f4d6190df53a78b93d97a5",
-                "sha256:6c5439bfb35a89cac50e81c751317faea647b9a3ec11c039900cd6915831064d",
-                "sha256:72c3110228944019e5f27232296c5923398496b28be42535e3b2dc7297b6e8b6",
-                "sha256:72f649d93d4cc4d8cf79c91ebc25137c358718ad75f99e99e043325ea7d56100",
-                "sha256:7aaf07085c756f6cb1c692ee0d5a86c531703b6e8c9cae581b31b562c16b98ce",
-                "sha256:80fe92813d208ce8aa7d76da878bdc84b90809f79ccbad2a288e9bcbeac1d9bd",
-                "sha256:95545137fc56ce8c10de646074d242001a112a92de169986abd8c88c27566a05",
-                "sha256:97b6d21771da41497b81652d44191489296555b761684f82b7b544c49989110f",
-                "sha256:98cb63ca63cb61f594511c06218ab4394bf80388b3d66cd61d0b1f63ee0ea69f",
-                "sha256:9f3b4522148586d35e78313db4db0df4b759ddd7649ef70002b6c3767d0fdeb7",
-                "sha256:a09a9d4ec2b7887f7a088bbaacfd5c07160e746e3d47ec5e8050ae3b2a229e9f",
-                "sha256:b5050d681bcf5c9f2570b93bee5d3ec8ae4cf23158812f91ed57f7126df91762",
-                "sha256:bb47a548cea95b86494a26c89d153fd31122ed65255db5dcbc421a2d28eb3379",
-                "sha256:bc462d24500ba707e9cbdef436c16e5c8cbf29908278af053008d9f689f56dee",
-                "sha256:c2067b3bb0781f14059b112c9da5a91c80a600a97915b4f48b37f197895dd925",
-                "sha256:d154ed971a4cc04b93a6d5b47f37948d1f621f25de3e8fa0c26b2d44f24e3e8f",
-                "sha256:d5dcea1387331c905405b09cdbfb34611050cc52c865d71f2362f354faee1e9f",
-                "sha256:ee6e2963e92762923956fe5d3479b1fdc3b76c83f290aad131a2f98c3df0593e",
-                "sha256:fd0e5062f11cb3e730450a7d9f323f4051b532781026395c4323b8ad055523c4"
+                "sha256:088df396b047477dd1bbc7de6e22f58400dae2f21310d9e2ec2933b2ef7dfa4f",
+                "sha256:09e67ef6e430f90caa093528bd758b0616f8165e57ed8d8ce014ae32df6a831d",
+                "sha256:0b4d5ad2cd3a1f0d1df882d926b37dbb2ab6c823ae21d041b46910c8f8cd844b",
+                "sha256:0b525a356680022b0af53385944026d3486fc8c013638cf9900eb87c866afb4c",
+                "sha256:1d4331aeb12f6b3791911a6da82de72257a99ad99726ed6b63f481c0184b6fb9",
+                "sha256:20d514c989fa28e73a5adbddd7a171afa5824710d0ab06d4e1234195d2a2e546",
+                "sha256:2b291cab8a888658d72b575a03e340509b6b050b62db1f5539dd5cd18fd50578",
+                "sha256:3f6c1716c473ebd1649663bf3b42702d0d53e27af8b64642be0dd3598c761fb1",
+                "sha256:42dfefbef90eb67c10c45a73a9bc1599d4dac920f7dfcbf4ec6b80cb620757fe",
+                "sha256:488f3383cf5159907d48d32957ac6f9ea85ccdcc296c14eca1a4e396ecc32098",
+                "sha256:4d45dbe4b21a9679c3e8b3f7f4f42a45a7d3ddff8a4a16109dff0e1da30a35b2",
+                "sha256:53c27bd452e0f1bc4bfed07ceb235663a1df7c74df08e37fd6b03eb89454946a",
+                "sha256:55e74faf8359ddda43fee01bffbc5bd99d96ea508d8a08c527099e84eb708f45",
+                "sha256:59789a7d06c742e9d13b883d5e3569188c16acb02eeed2510fd3bfdbc1bd1530",
+                "sha256:5b650dbbc0969a4e226d98a0b440c2f07a850896aed9266b6fedc0f7e7834108",
+                "sha256:66daa16952d5bf0c9d5389c5e9df562922a59bd16d77e2a276e575d32e38afd1",
+                "sha256:6e760cf01259a1c0a50f3c845f9cad1af30577fd8b670339b1659c6d0e7a41dd",
+                "sha256:7502539939b53d7565f3d11d87c78e7ec900d3c72945d4ee0e2f250d598309a0",
+                "sha256:769a7f131a2f43752455cc72f9f7a093c3ff3856bf976c5fb53a59d0ccc704f6",
+                "sha256:7c150dbbb4a94ea4825d1e5f2c5501af7141ea95825fadd7829f9b11c97aaf6c",
+                "sha256:8844217cdf66eabe39567118f229e275f0727e9195635a15e0e4b9227458daaf",
+                "sha256:8a66fe50386162df2da701b3722781cbe90ce043e7d53c1fd6bd801bca6b48d4",
+                "sha256:9370d6744d379f2de5d7fa95cdbd3a4d92f0b0ef29609b4b1687f16bc197063d",
+                "sha256:937a54e5694684f74dcbf6e24cc453bfc5b33940216ddd8f4cd8f0f79167f765",
+                "sha256:9c857532c719fb30fafabd2371ce9b7031812ff3889d75273827633bca0c4602",
+                "sha256:a4165205a13b16a29e1ac57efeee6be2dfd5b5408122d59ef2145bc3239fa340",
+                "sha256:b3fe2ff1e1715d4475d7e2c3e8dabd7c025f4410f79513b4ff2de3d51ce0fa9c",
+                "sha256:b6617221ff08fbd3b7a811950b5c3f9367f6e941b86259843eab77c8e3d2b56b",
+                "sha256:b761727ed7d593e49671d1827044b942dd2f4caae6e51bab144d4accf8244a84",
+                "sha256:baf3be0b9446a4083cc0c5bb9f9c964034be5374b5bc09757be89f5d2fa247b8",
+                "sha256:c17770a62a71718a74b7548098a74cd6880be16bcfff5f937f900ead90ca8e92",
+                "sha256:c67db410508b9de9c4694c57ed754b65a460e4812126e87f5052ecf23a011a54",
+                "sha256:d78ca526a559fb84faaaf84da2dd4addef5edb109db8b81677c0bb1aad342601",
+                "sha256:e9ed59d1b6ee837f4515b9584f3d26cf0388b742a11ecdae0d9237a94505d03a",
+                "sha256:f054b020c4d7e9786ae0404278ea318768eb123403b18453e28e47cdb7a0a4bf",
+                "sha256:f372d0f08eff1475ef426344efe42493f71f377ec52237bf153c5713de987251",
+                "sha256:f3f6a6034140e9e17e9abc175fc7a266a6e63652028e157750bd98e804a8ed9a",
+                "sha256:ffde4c6fabb52891d81606411cbfaf77756e3b561b566efd270b3ed3791fde4e"
             ],
             "index": "pypi",
-            "version": "==9.0.0"
+            "version": "==9.1.1"
         },
         "pkginfo": {
             "hashes": [
@@ -709,11 +695,10 @@
         },
         "prompt-toolkit": {
             "hashes": [
-                "sha256:1bb05628c7d87b645974a1bad3f17612be0c29fa39af9f7688030163f680bad6",
-                "sha256:e56f2ff799bacecd3e88165b1e2f5ebf9bcd59e80e06d395fa0cc4b8bd7bb506"
+                "sha256:62291dad495e665fca0bda814e342c69952086afb0f4094d0893d357e5c78752",
+                "sha256:bd640f60e8cecd74f0dc249713d433ace2ddc62b65ee07f96d358e0b152b6ea7"
             ],
-            "markers": "python_full_version >= '3.6.2'",
-            "version": "==3.0.24"
+            "version": "==3.0.29"
         },
         "psycopg2-binary": {
             "hashes": [
@@ -818,7 +803,6 @@
                 "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20",
                 "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"
             ],
-            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
             "version": "==2.8.0"
         },
         "pycparser": {
@@ -840,69 +824,63 @@
                 "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c",
                 "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"
             ],
-            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
             "version": "==2.4.0"
         },
         "pygments": {
             "hashes": [
-                "sha256:44238f1b60a76d78fc8ca0528ee429702aae011c265fe6a8dd8b63049ae41c65",
-                "sha256:4e426f72023d88d03b2fa258de560726ce890ff3b630f88c21cbb8b2503b8c6a"
+                "sha256:5eb116118f9612ff1ee89ac96437bb6b49e8f04d8a13b514ba26f620208e26eb",
+                "sha256:dc9c10fb40944260f6ed4c688ece0cd2048414940f1cea51b8b226318411c519"
             ],
-            "markers": "python_version >= '3.5'",
-            "version": "==2.11.2"
+            "version": "==2.12.0"
         },
         "pyopenssl": {
             "hashes": [
-                "sha256:5e2d8c5e46d0d865ae933bef5230090bdaf5506281e9eec60fa250ee80600cb3",
-                "sha256:8935bd4920ab9abfebb07c41a4f58296407ed77f04bd1a92914044b848ba1ed6"
+                "sha256:660b1b1425aac4a1bea1d94168a85d99f0b3144c869dd4390d27629d0087f1bf",
+                "sha256:ea252b38c87425b64116f808355e8da644ef9b07e429398bfece610f893ee2e0"
             ],
-            "version": "==21.0.0"
+            "version": "==22.0.0"
         },
         "pyparsing": {
             "hashes": [
-                "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea",
-                "sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"
+                "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb",
+                "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"
             ],
-            "markers": "python_version >= '3.6'",
-            "version": "==3.0.7"
+            "version": "==3.0.9"
         },
         "python-dotenv": {
             "hashes": [
-                "sha256:32b2bdc1873fd3a3c346da1c6db83d0053c3c62f28f1f38516070c4c8971b1d3",
-                "sha256:a5de49a31e953b45ff2d2fd434bbc2670e8db5273606c1e737cc6b93eff3655f"
+                "sha256:b7e3b04a59693c42c36f9ab1cc2acc46fa5df8c78e178fc33a8d4cd05c8d498f",
+                "sha256:d92a187be61fe482e4fd675b6d52200e7be63a12b724abbf931a40ce4fa92938"
             ],
-            "markers": "python_version >= '3.5'",
-            "version": "==0.19.2"
+            "version": "==0.20.0"
         },
         "python-slugify": {
             "hashes": [
-                "sha256:6d8c5df75cd4a7c3a2d21e257633de53f52ab0265cd2d1dc62a730e8194a7380",
-                "sha256:f13383a0b9fcbe649a1892b9c8eb4f8eab1d6d84b84bb7a624317afa98159cab"
+                "sha256:272d106cb31ab99b3496ba085e3fea0e9e76dcde967b5e9992500d1f785ce4e1",
+                "sha256:7b2c274c308b62f4269a9ba701aa69a797e9bca41aeee5b3a9e79e36b6656927"
             ],
-            "markers": "python_version >= '3.6'",
-            "version": "==5.0.2"
+            "version": "==6.1.2"
         },
         "python-telegram-bot": {
             "hashes": [
-                "sha256:833f39110f5d019b39a6c6fcbabd6ea1627eaaa0a26e618c0be099568672d791",
-                "sha256:d2c555431821f4ace0c1b7ce12af41999f01b793b275dee131f1034d08c01e3e"
+                "sha256:534f5bb0ff4ca34c9252e97e0b3bcdab81d97be0eb4821682a361cb426c00e55",
+                "sha256:baeff704baa2ac3dc17a944c02da888228ad258e89be2e5bcbd13a8a5102d573"
             ],
             "index": "pypi",
-            "version": "==13.10"
+            "version": "==13.11"
         },
         "pytz": {
             "hashes": [
-                "sha256:3672058bc3453457b622aab7a1c3bfd5ab0bdae451512f6cf25f64ed37f5b87c",
-                "sha256:acad2d8b20a1af07d4e4c9d2e9285c5ed9104354062f275f3fcd88dcef4f1326"
+                "sha256:1e760e2fe6a8163bc0b3d9a19c4f84342afa0a2affebfaa84b01b978a02ecaa7",
+                "sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c"
             ],
-            "version": "==2021.3"
+            "version": "==2022.1"
         },
         "pytz-deprecation-shim": {
             "hashes": [
                 "sha256:8314c9692a636c8eb3bda879b9f119e350e93223ae83e70e80c31675a0fdc1a6",
                 "sha256:af097bae1b616dde5c5744441e2ddc69e74dfdcb0c263129610d85b87445a59d"
             ],
-            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'",
             "version": "==0.1.0.post0"
         },
         "pyyaml": {
@@ -941,7 +919,6 @@
                 "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174",
                 "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"
             ],
-            "markers": "python_version >= '3.6'",
             "version": "==6.0"
         },
         "radon": {
@@ -953,19 +930,18 @@
         },
         "readme-renderer": {
             "hashes": [
-                "sha256:a50a0f2123a4c1145ac6f420e1a348aafefcc9211c846e3d51df05fe3d865b7d",
-                "sha256:b512beafa6798260c7d5af3e1b1f097e58bfcd9a575da7c4ddd5e037490a5b85"
+                "sha256:73b84905d091c31f36e50b4ae05ae2acead661f6a09a9abb4df7d2ddcdb6a698",
+                "sha256:a727999acfc222fc21d82a12ed48c957c4989785e5865807c65a487d21677497"
             ],
-            "markers": "python_version >= '3.6'",
-            "version": "==32.0"
+            "version": "==35.0"
         },
         "redis": {
             "hashes": [
-                "sha256:07420a3fbedd8e012c31d4fadac943fb81568946da202c5a5bc237774e5280a0",
-                "sha256:bc97d18938ca18d66737d0ef88584a2073069589e4026813cfba9ad6df9a9f40"
+                "sha256:84316970995a7adb907a56754d2b92d88fc2d252963dc5ac34c88f0f1a22c25d",
+                "sha256:94b617b4cd296e94991146f66fc5559756fbefe9493604f0312e4d3298ac63e9"
             ],
             "index": "pypi",
-            "version": "==4.1.1"
+            "version": "==4.3.1"
         },
         "requests": {
             "hashes": [
@@ -987,16 +963,22 @@
                 "sha256:50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd",
                 "sha256:97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c"
             ],
-            "markers": "python_version >= '3.7'",
             "version": "==2.0.0"
         },
+        "rich": {
+            "hashes": [
+                "sha256:d13c6c90c42e24eb7ce660db397e8c398edd58acb7f92a2a88a95572b838aaa4",
+                "sha256:d239001c0fb7de985e21ec9a4bb542b5150350330bbc1849f835b9cbc8923b91"
+            ],
+            "version": "==12.4.1"
+        },
         "secretstorage": {
             "hashes": [
-                "sha256:422d82c36172d88d6a0ed5afdec956514b189ddbfb72fefab0c8a1cee4eaf71f",
-                "sha256:fd666c51a6bf200643495a04abb261f83229dcb6fd8472ec393df7ffc8b6f195"
+                "sha256:0a8eb9645b320881c222e827c26f4cfcf55363e8b374a021981ef886657a912f",
+                "sha256:755dc845b6ad76dcbcbc07ea3da75ae54bb1ea529eb72d15f83d26499a5df319"
             ],
             "markers": "sys_platform == 'linux'",
-            "version": "==3.3.1"
+            "version": "==3.3.2"
         },
         "service-identity": {
             "hashes": [
@@ -1010,7 +992,6 @@
                 "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
                 "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
             ],
-            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
             "version": "==1.16.0"
         },
         "smmap": {
@@ -1018,7 +999,6 @@
                 "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94",
                 "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"
             ],
-            "markers": "python_version >= '3.6'",
             "version": "==5.0.0"
         },
         "sqlparse": {
@@ -1026,7 +1006,6 @@
                 "sha256:0c00730c74263a94e5a9919ade150dfc3b19c574389985446148402998287dae",
                 "sha256:48719e356bb8b42991bdbb1e8b83223757b93789c00910a616a071910ca4a64d"
             ],
-            "markers": "python_version >= '3.5'",
             "version": "==0.4.2"
         },
         "stevedore": {
@@ -1034,7 +1013,6 @@
                 "sha256:a547de73308fd7e90075bb4d301405bebf705292fa90a90fc3bcf9133f58616c",
                 "sha256:f40253887d8712eaa2bb0ea3830374416736dc8ec0e22f5a65092c1174c44335"
             ],
-            "markers": "python_version >= '3.6'",
             "version": "==3.5.0"
         },
         "text-unidecode": {
@@ -1088,75 +1066,58 @@
                 "sha256:fa2ba70284fa42c2a5ecb35e322e68823288a4251f9ba9cc77be04ae15eada68",
                 "sha256:fba85b6cd9c39be262fcd23865652920832b61583de2a2ca907dbd8e8a8c81e5"
             ],
-            "markers": "python_version >= '3.5'",
             "version": "==6.1"
         },
-        "tqdm": {
-            "hashes": [
-                "sha256:8dd278a422499cd6b727e6ae4061c40b48fce8b76d1ccbf5d34fca9b7f925b0c",
-                "sha256:d359de7217506c9851b7869f3708d8ee53ed70a1b8edbba4dbcb47442592920d"
-            ],
-            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
-            "version": "==4.62.3"
-        },
         "twine": {
             "hashes": [
-                "sha256:28460a3db6b4532bde6a5db6755cf2dce6c5020bada8a641bb2c5c7a9b1f35b8",
-                "sha256:8c120845fc05270f9ee3e9d7ebbed29ea840e41f48cd059e04733f7e1d401345"
+                "sha256:6f7496cf14a3a8903474552d5271c79c71916519edb42554f23f42a8563498a9",
+                "sha256:817aa0c0bdc02a5ebe32051e168e23c71a0608334e624c793011f120dbbc05b7"
             ],
             "index": "pypi",
-            "version": "==3.7.1"
+            "version": "==4.0.0"
         },
         "twisted": {
-            "extras": [
-                "tls"
-            ],
             "hashes": [
-                "sha256:13c1d1d2421ae556d91e81e66cf0d4f4e4e1e4a36a0486933bee4305c6a4fb9b",
-                "sha256:2cd652542463277378b0d349f47c62f20d9306e57d1247baabd6d1d38a109006"
+                "sha256:a047990f57dfae1e0bd2b7df2526d4f16dcdc843774dc108b78c52f2a5f13680",
+                "sha256:f9f7a91f94932477a9fc3b169d57f54f96c6e74a23d78d9ce54039a7f48928a2"
             ],
-            "markers": "python_full_version >= '3.6.7'",
-            "version": "==21.7.0"
+            "version": "==22.4.0"
         },
         "txaio": {
             "hashes": [
-                "sha256:7d6f89745680233f1c4db9ddb748df5e88d2a7a37962be174c0fd04c8dba1dc8",
-                "sha256:c16b55f9a67b2419cfdf8846576e2ec9ba94fe6978a83080c352a80db31c93fb"
+                "sha256:2e4582b70f04b2345908254684a984206c0d9b50e3074a24a4c55aba21d24d01",
+                "sha256:41223af4a9d5726e645a8ee82480f413e5e300dd257db94bc38ae12ea48fb2e5"
             ],
-            "markers": "python_version >= '3.6'",
-            "version": "==21.2.1"
+            "version": "==22.2.1"
         },
         "typing-extensions": {
             "hashes": [
-                "sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e",
-                "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"
+                "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708",
+                "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376"
             ],
-            "markers": "python_version >= '3.6'",
-            "version": "==4.0.1"
+            "version": "==4.2.0"
         },
         "tzdata": {
             "hashes": [
-                "sha256:3eee491e22ebfe1e5cfcc97a4137cd70f092ce59144d81f8924a844de05ba8f5",
-                "sha256:68dbe41afd01b867894bbdfd54fa03f468cfa4f0086bfb4adcd8de8f24f3ee21"
+                "sha256:238e70234214138ed7b4e8a0fab0e5e13872edab3be586ab8198c407620e2ab9",
+                "sha256:8b536a8ec63dc0751342b3984193a3118f8fca2afe25752bb9b7fffd398552d3"
             ],
             "markers": "python_version >= '3.6'",
-            "version": "==2021.5"
+            "version": "==2022.1"
         },
         "tzlocal": {
             "hashes": [
-                "sha256:0f28015ac68a5c067210400a9197fc5d36ba9bc3f8eaf1da3cbd59acdfed9e09",
-                "sha256:28ba8d9fcb6c9a782d6e0078b4f6627af1ea26aeaa32b4eab5324abc7df4149f"
+                "sha256:89885494684c929d9191c57aa27502afc87a579be5cdd3225c77c463ea043745",
+                "sha256:ee5842fa3a795f023514ac2d801c4a81d1743bbe642e3940143326b3a00addd7"
             ],
-            "markers": "python_version >= '3.6'",
-            "version": "==4.1"
+            "version": "==4.2"
         },
         "urllib3": {
             "hashes": [
-                "sha256:000ca7f471a233c2251c6c7023ee85305721bfdf18621ebff4fd17a8653427ed",
-                "sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c"
+                "sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14",
+                "sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e"
             ],
-            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_full_version < '4.0.0'",
-            "version": "==1.26.8"
+            "version": "==1.26.9"
         },
         "viberbot": {
             "hashes": [
@@ -1171,7 +1132,6 @@
                 "sha256:4c9dceab6f76ed92105027c49c823800dd33cacce13bdedc5b914e3514b7fb30",
                 "sha256:7d3b1624a953da82ef63462013bbd271d3eb75751489f9807598e8f340bd637e"
             ],
-            "markers": "python_version >= '3.6'",
             "version": "==5.0.0"
         },
         "wcwidth": {
@@ -1190,68 +1150,79 @@
         },
         "wrapt": {
             "hashes": [
-                "sha256:086218a72ec7d986a3eddb7707c8c4526d677c7b35e355875a0fe2918b059179",
-                "sha256:0877fe981fd76b183711d767500e6b3111378ed2043c145e21816ee589d91096",
-                "sha256:0a017a667d1f7411816e4bf214646d0ad5b1da2c1ea13dec6c162736ff25a374",
-                "sha256:0cb23d36ed03bf46b894cfec777eec754146d68429c30431c99ef28482b5c1df",
-                "sha256:1fea9cd438686e6682271d36f3481a9f3636195578bab9ca3382e2f5f01fc185",
-                "sha256:220a869982ea9023e163ba915077816ca439489de6d2c09089b219f4e11b6785",
-                "sha256:25b1b1d5df495d82be1c9d2fad408f7ce5ca8a38085e2da41bb63c914baadff7",
-                "sha256:2dded5496e8f1592ec27079b28b6ad2a1ef0b9296d270f77b8e4a3a796cf6909",
-                "sha256:2ebdde19cd3c8cdf8df3fc165bc7827334bc4e353465048b36f7deeae8ee0918",
-                "sha256:43e69ffe47e3609a6aec0fe723001c60c65305784d964f5007d5b4fb1bc6bf33",
-                "sha256:46f7f3af321a573fc0c3586612db4decb7eb37172af1bc6173d81f5b66c2e068",
-                "sha256:47f0a183743e7f71f29e4e21574ad3fa95676136f45b91afcf83f6a050914829",
-                "sha256:498e6217523111d07cd67e87a791f5e9ee769f9241fcf8a379696e25806965af",
-                "sha256:4b9c458732450ec42578b5642ac53e312092acf8c0bfce140ada5ca1ac556f79",
-                "sha256:51799ca950cfee9396a87f4a1240622ac38973b6df5ef7a41e7f0b98797099ce",
-                "sha256:5601f44a0f38fed36cc07db004f0eedeaadbdcec90e4e90509480e7e6060a5bc",
-                "sha256:5f223101f21cfd41deec8ce3889dc59f88a59b409db028c469c9b20cfeefbe36",
-                "sha256:610f5f83dd1e0ad40254c306f4764fcdc846641f120c3cf424ff57a19d5f7ade",
-                "sha256:6a03d9917aee887690aa3f1747ce634e610f6db6f6b332b35c2dd89412912bca",
-                "sha256:705e2af1f7be4707e49ced9153f8d72131090e52be9278b5dbb1498c749a1e32",
-                "sha256:766b32c762e07e26f50d8a3468e3b4228b3736c805018e4b0ec8cc01ecd88125",
-                "sha256:77416e6b17926d953b5c666a3cb718d5945df63ecf922af0ee576206d7033b5e",
-                "sha256:778fd096ee96890c10ce96187c76b3e99b2da44e08c9e24d5652f356873f6709",
-                "sha256:78dea98c81915bbf510eb6a3c9c24915e4660302937b9ae05a0947164248020f",
-                "sha256:7dd215e4e8514004c8d810a73e342c536547038fb130205ec4bba9f5de35d45b",
-                "sha256:7dde79d007cd6dfa65afe404766057c2409316135cb892be4b1c768e3f3a11cb",
-                "sha256:81bd7c90d28a4b2e1df135bfbd7c23aee3050078ca6441bead44c42483f9ebfb",
-                "sha256:85148f4225287b6a0665eef08a178c15097366d46b210574a658c1ff5b377489",
-                "sha256:865c0b50003616f05858b22174c40ffc27a38e67359fa1495605f96125f76640",
-                "sha256:87883690cae293541e08ba2da22cacaae0a092e0ed56bbba8d018cc486fbafbb",
-                "sha256:8aab36778fa9bba1a8f06a4919556f9f8c7b33102bd71b3ab307bb3fecb21851",
-                "sha256:8c73c1a2ec7c98d7eaded149f6d225a692caa1bd7b2401a14125446e9e90410d",
-                "sha256:936503cb0a6ed28dbfa87e8fcd0a56458822144e9d11a49ccee6d9a8adb2ac44",
-                "sha256:944b180f61f5e36c0634d3202ba8509b986b5fbaf57db3e94df11abee244ba13",
-                "sha256:96b81ae75591a795d8c90edc0bfaab44d3d41ffc1aae4d994c5aa21d9b8e19a2",
-                "sha256:981da26722bebb9247a0601e2922cedf8bb7a600e89c852d063313102de6f2cb",
-                "sha256:ae9de71eb60940e58207f8e71fe113c639da42adb02fb2bcbcaccc1ccecd092b",
-                "sha256:b73d4b78807bd299b38e4598b8e7bd34ed55d480160d2e7fdaabd9931afa65f9",
-                "sha256:d4a5f6146cfa5c7ba0134249665acd322a70d1ea61732723c7d3e8cc0fa80755",
-                "sha256:dd91006848eb55af2159375134d724032a2d1d13bcc6f81cd8d3ed9f2b8e846c",
-                "sha256:e05e60ff3b2b0342153be4d1b597bbcfd8330890056b9619f4ad6b8d5c96a81a",
-                "sha256:e6906d6f48437dfd80464f7d7af1740eadc572b9f7a4301e7dd3d65db285cacf",
-                "sha256:e92d0d4fa68ea0c02d39f1e2f9cb5bc4b4a71e8c442207433d8db47ee79d7aa3",
-                "sha256:e94b7d9deaa4cc7bac9198a58a7240aaf87fe56c6277ee25fa5b3aa1edebd229",
-                "sha256:ea3e746e29d4000cd98d572f3ee2a6050a4f784bb536f4ac1f035987fc1ed83e",
-                "sha256:ec7e20258ecc5174029a0f391e1b948bf2906cd64c198a9b8b281b811cbc04de",
-                "sha256:ec9465dd69d5657b5d2fa6133b3e1e989ae27d29471a672416fd729b429eb554",
-                "sha256:f122ccd12fdc69628786d0c947bdd9cb2733be8f800d88b5a37c57f1f1d73c10",
-                "sha256:f99c0489258086308aad4ae57da9e8ecf9e1f3f30fa35d5e170b4d4896554d80",
-                "sha256:f9c51d9af9abb899bd34ace878fbec8bf357b3194a10c4e8e0a25512826ef056",
-                "sha256:fd76c47f20984b43d93de9a82011bb6e5f8325df6c9ed4d8310029a55fa361ea"
-            ],
-            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
-            "version": "==1.13.3"
+                "sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3",
+                "sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b",
+                "sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4",
+                "sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2",
+                "sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656",
+                "sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3",
+                "sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff",
+                "sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310",
+                "sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a",
+                "sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57",
+                "sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069",
+                "sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383",
+                "sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe",
+                "sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87",
+                "sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d",
+                "sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b",
+                "sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907",
+                "sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f",
+                "sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0",
+                "sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28",
+                "sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1",
+                "sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853",
+                "sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc",
+                "sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3",
+                "sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3",
+                "sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164",
+                "sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1",
+                "sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c",
+                "sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1",
+                "sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7",
+                "sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1",
+                "sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320",
+                "sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed",
+                "sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1",
+                "sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248",
+                "sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c",
+                "sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456",
+                "sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77",
+                "sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef",
+                "sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1",
+                "sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7",
+                "sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86",
+                "sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4",
+                "sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d",
+                "sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d",
+                "sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8",
+                "sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5",
+                "sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471",
+                "sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00",
+                "sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68",
+                "sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3",
+                "sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d",
+                "sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735",
+                "sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d",
+                "sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569",
+                "sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7",
+                "sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59",
+                "sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5",
+                "sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb",
+                "sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b",
+                "sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f",
+                "sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462",
+                "sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015",
+                "sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af"
+            ],
+            "version": "==1.14.1"
         },
         "zipp": {
             "hashes": [
-                "sha256:9f50f446828eb9d45b267433fd3e9da8d801f614129124863f9c51ebceafb87d",
-                "sha256:b47250dd24f92b7dd6a0a8fc5244da14608f3ca90a5efcd37a3b1642fac9a375"
+                "sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad",
+                "sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099"
             ],
-            "markers": "python_version >= '3.7'",
-            "version": "==3.7.0"
+            "version": "==3.8.0"
         },
         "zope.interface": {
             "hashes": [
@@ -1307,7 +1278,6 @@
                 "sha256:f44e517131a98f7a76696a7b21b164bcb85291cee106a23beccce454e1f433a4",
                 "sha256:f7ee479e96f7ee350db1cf24afa5685a5899e2b34992fb99e1f7c1b0b758d263"
             ],
-            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
             "version": "==5.4.0"
         }
     },
diff --git a/backend/__init__.py b/backend/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/backend/_trial_temp/_trial_marker b/backend/_trial_temp/_trial_marker
new file mode 100755
index 0000000..e69de29
diff --git a/backend/app/migrations/garpix_notify/0010_auto_20220413_1516.py b/backend/app/migrations/garpix_notify/0010_auto_20220413_1516.py
new file mode 100644
index 0000000..4e6ad9e
--- /dev/null
+++ b/backend/app/migrations/garpix_notify/0010_auto_20220413_1516.py
@@ -0,0 +1,36 @@
+# Generated by Django 3.1 on 2022-04-13 15:16
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('garpix_notify', '0009_auto_20220404_0830'),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='notifycategory',
+            name='template',
+        ),
+        migrations.RemoveField(
+            model_name='notifytemplate',
+            name='category',
+        ),
+        migrations.RemoveField(
+            model_name='notifytemplate',
+            name='user',
+        ),
+        migrations.AddField(
+            model_name='notifycategory',
+            name='template_choice',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='template', to='garpix_notify.notifytemplate', verbose_name='Выбрать готовый шаблон для категории'),
+        ),
+        migrations.AlterField(
+            model_name='notifytemplate',
+            name='user_lists',
+            field=models.ManyToManyField(blank=True, to='garpix_notify.NotifyUserList', verbose_name='Списки пользователей для рассылки'),
+        ),
+    ]
diff --git a/backend/app/migrations/garpix_notify/0011_notifycategory_template.py b/backend/app/migrations/garpix_notify/0011_notifycategory_template.py
new file mode 100644
index 0000000..552ab63
--- /dev/null
+++ b/backend/app/migrations/garpix_notify/0011_notifycategory_template.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.1 on 2022-04-13 15:26
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('garpix_notify', '0010_auto_20220413_1516'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='notifycategory',
+            name='template',
+            field=models.TextField(default='{{text}}', verbose_name='Простой шаблон'),
+        ),
+    ]
diff --git a/backend/app/migrations/garpix_notify/0012_auto_20220414_1314.py b/backend/app/migrations/garpix_notify/0012_auto_20220414_1314.py
new file mode 100644
index 0000000..55e1e9b
--- /dev/null
+++ b/backend/app/migrations/garpix_notify/0012_auto_20220414_1314.py
@@ -0,0 +1,32 @@
+# Generated by Django 3.1 on 2022-04-14 13:14
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('garpix_notify', '0011_notifycategory_template'),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='notifytemplate',
+            name='email',
+        ),
+        migrations.AlterField(
+            model_name='notifyconfig',
+            name='is_telegram_enabled',
+            field=models.BooleanField(default=True, verbose_name='Разрешить отправку Telegram'),
+        ),
+        migrations.AlterField(
+            model_name='notifyuserlist',
+            name='mail_to_all',
+            field=models.BooleanField(default=False, verbose_name='Массовая рассылка для всех пользователей сайта'),
+        ),
+        migrations.AlterField(
+            model_name='smtpaccount',
+            name='port',
+            field=models.IntegerField(default=465, verbose_name='Порт'),
+        ),
+    ]
diff --git a/backend/app/migrations/garpix_notify/0013_auto_20220421_0814.py b/backend/app/migrations/garpix_notify/0013_auto_20220421_0814.py
new file mode 100644
index 0000000..398ddab
--- /dev/null
+++ b/backend/app/migrations/garpix_notify/0013_auto_20220421_0814.py
@@ -0,0 +1,28 @@
+# Generated by Django 3.1 on 2022-04-21 08:14
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('garpix_notify', '0012_auto_20220414_1314'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='notify',
+            name='users_list',
+            field=models.ManyToManyField(blank=True, to='garpix_notify.NotifyUserList', verbose_name='Списки пользователей для рассылки'),
+        ),
+        migrations.AlterField(
+            model_name='notify',
+            name='event',
+            field=models.IntegerField(blank=True, choices=[(1, 'Register'), (2, 'Feeback'), (3, 'Example 1'), (4, 'Example 2'), (5, 'TestEvent')], null=True, verbose_name='Событие'),
+        ),
+        migrations.AlterField(
+            model_name='notifytemplate',
+            name='event',
+            field=models.IntegerField(blank=True, choices=[(1, 'Register'), (2, 'Feeback'), (3, 'Example 1'), (4, 'Example 2'), (5, 'TestEvent')], null=True, verbose_name='Событие'),
+        ),
+    ]
diff --git a/backend/app/migrations/garpix_notify/0014_auto_20220422_0720.py b/backend/app/migrations/garpix_notify/0014_auto_20220422_0720.py
new file mode 100644
index 0000000..7ec91a2
--- /dev/null
+++ b/backend/app/migrations/garpix_notify/0014_auto_20220422_0720.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.1 on 2022-04-22 07:20
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('garpix_notify', '0013_auto_20220421_0814'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='notifyconfig',
+            name='sms_url_type',
+            field=models.IntegerField(choices=[(0, 'sms.ru'), (1, 'web.szk-info.ru'), (2, 'iqsms.ru'), (3, 'infosmska.ru'), (4, 'smsc.ru'), (5, 'sms-sending.ru')], default=0, verbose_name='URL СМС провайдера'),
+        ),
+    ]
diff --git a/backend/app/migrations/garpix_notify/0015_auto_20220422_0922.py b/backend/app/migrations/garpix_notify/0015_auto_20220422_0922.py
new file mode 100644
index 0000000..2b729d4
--- /dev/null
+++ b/backend/app/migrations/garpix_notify/0015_auto_20220422_0922.py
@@ -0,0 +1,24 @@
+# Generated by Django 3.2 on 2022-04-22 09:22
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('garpix_notify', '0014_auto_20220422_0720'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='notify',
+            name='category',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notifies', to='garpix_notify.notifycategory', verbose_name='Категория'),
+        ),
+        migrations.AlterField(
+            model_name='smtpaccount',
+            name='category',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='accounts', to='garpix_notify.notifycategory', verbose_name='Тип'),
+        ),
+    ]
diff --git a/backend/app/migrations/garpix_notify/0016_alter_notifyuserlistparticipant_options.py b/backend/app/migrations/garpix_notify/0016_alter_notifyuserlistparticipant_options.py
new file mode 100644
index 0000000..aeff48a
--- /dev/null
+++ b/backend/app/migrations/garpix_notify/0016_alter_notifyuserlistparticipant_options.py
@@ -0,0 +1,17 @@
+# Generated by Django 3.2 on 2022-04-22 09:42
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('garpix_notify', '0015_auto_20220422_0922'),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name='notifyuserlistparticipant',
+            options={'verbose_name': 'Дополнительный участник списка рассылки', 'verbose_name_plural': 'Дополнительные участники списка рассылки'},
+        ),
+    ]
diff --git a/backend/app/migrations/garpix_notify/0017_alter_notifyconfig_sms_url_type.py b/backend/app/migrations/garpix_notify/0017_alter_notifyconfig_sms_url_type.py
new file mode 100644
index 0000000..6b876ec
--- /dev/null
+++ b/backend/app/migrations/garpix_notify/0017_alter_notifyconfig_sms_url_type.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2 on 2022-04-26 08:27
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('garpix_notify', '0016_alter_notifyuserlistparticipant_options'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='notifyconfig',
+            name='sms_url_type',
+            field=models.IntegerField(choices=[(0, 'sms.ru'), (1, 'web.szk-info.ru'), (2, 'iqsms.ru'), (3, 'infosmska.ru'), (4, 'smsc.ru'), (5, 'sms-sending.ru'), (6, 'sms-prosto.ru')], default=0, verbose_name='URL СМС провайдера'),
+        ),
+    ]
diff --git a/backend/app/migrations/garpix_notify/0018_auto_20220426_1511.py b/backend/app/migrations/garpix_notify/0018_auto_20220426_1511.py
new file mode 100644
index 0000000..07d4110
--- /dev/null
+++ b/backend/app/migrations/garpix_notify/0018_auto_20220426_1511.py
@@ -0,0 +1,35 @@
+# Generated by Django 3.2 on 2022-04-26 15:11
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+        ('garpix_notify', '0017_alter_notifyconfig_sms_url_type'),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='notifycategory',
+            name='template_choice',
+        ),
+        migrations.AddField(
+            model_name='notifytemplate',
+            name='category',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='templates', to='garpix_notify.notifycategory', verbose_name='Категория'),
+        ),
+        migrations.AddField(
+            model_name='notifytemplate',
+            name='email',
+            field=models.EmailField(blank=True, help_text='Используется только в случае отсутствия указанного пользователя', max_length=255, null=True, verbose_name='Email получатель'),
+        ),
+        migrations.AddField(
+            model_name='notifytemplate',
+            name='user',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='Пользователь (получатель)'),
+        ),
+    ]
diff --git a/backend/app/migrations/garpix_notify/0019_auto_20220427_1217.py b/backend/app/migrations/garpix_notify/0019_auto_20220427_1217.py
new file mode 100644
index 0000000..0087f2d
--- /dev/null
+++ b/backend/app/migrations/garpix_notify/0019_auto_20220427_1217.py
@@ -0,0 +1,39 @@
+# Generated by Django 3.2 on 2022-04-27 12:17
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('garpix_notify', '0018_auto_20220426_1511'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='notify',
+            name='category',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notifies', to='garpix_notify.notifycategory', verbose_name='Категория'),
+        ),
+        migrations.AlterField(
+            model_name='notifytemplate',
+            name='category',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='templates', to='garpix_notify.notifycategory', verbose_name='Категория'),
+        ),
+        migrations.AlterField(
+            model_name='smtpaccount',
+            name='host',
+            field=models.CharField(default='smtp.yandex.com', max_length=255, verbose_name='Хост'),
+        ),
+        migrations.AlterField(
+            model_name='smtpaccount',
+            name='is_use_ssl',
+            field=models.BooleanField(default=True, verbose_name='Использовать SSL?'),
+        ),
+        migrations.AlterField(
+            model_name='smtpaccount',
+            name='is_use_tls',
+            field=models.BooleanField(default=False, verbose_name='Использовать TLS?'),
+        ),
+    ]
diff --git a/backend/app/migrations/garpix_notify/0020_notifyconfig_email_malling.py b/backend/app/migrations/garpix_notify/0020_notifyconfig_email_malling.py
new file mode 100644
index 0000000..ddf1484
--- /dev/null
+++ b/backend/app/migrations/garpix_notify/0020_notifyconfig_email_malling.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2 on 2022-05-11 12:54
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('garpix_notify', '0019_auto_20220427_1217'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='notifyconfig',
+            name='email_malling',
+            field=models.IntegerField(choices=[(0, 'Обычная рассылка'), (1, 'Скрытая рассылка')], default=1, help_text='Если выбрана обычная рассылка, то пользователи будут видеть email друг друга', verbose_name='Тип массовой рассылки'),
+        ),
+    ]
diff --git a/backend/app/migrations/garpix_notify/0021_auto_20220518_0854.py b/backend/app/migrations/garpix_notify/0021_auto_20220518_0854.py
new file mode 100644
index 0000000..21f929f
--- /dev/null
+++ b/backend/app/migrations/garpix_notify/0021_auto_20220518_0854.py
@@ -0,0 +1,24 @@
+# Generated by Django 3.1 on 2022-05-18 08:54
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('garpix_notify', '0020_notifyconfig_email_malling'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='notifycategory',
+            name='template',
+            field=models.TextField(default='{{text}}', verbose_name='Шаблон'),
+        ),
+        migrations.AlterField(
+            model_name='smtpaccount',
+            name='category',
+            field=models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, related_name='accounts', to='garpix_notify.notifycategory', verbose_name='Тип'),
+        ),
+    ]
diff --git a/backend/app/migrations/garpix_notify/0022_auto_20220518_0859.py b/backend/app/migrations/garpix_notify/0022_auto_20220518_0859.py
new file mode 100644
index 0000000..3434a56
--- /dev/null
+++ b/backend/app/migrations/garpix_notify/0022_auto_20220518_0859.py
@@ -0,0 +1,19 @@
+# Generated by Django 3.1 on 2022-05-18 08:59
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('garpix_notify', '0021_auto_20220518_0854'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='smtpaccount',
+            name='category',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='accounts', to='garpix_notify.notifycategory', verbose_name='Тип'),
+        ),
+    ]
diff --git a/backend/app/settings.py b/backend/app/settings.py
index e290d9f..731f469 100644
--- a/backend/app/settings.py
+++ b/backend/app/settings.py
@@ -13,6 +13,7 @@
 import os
 from pathlib import Path
 from environs import Env
+from garpix_notify.settings import *
 
 env = Env()
 env.read_env()
@@ -32,7 +33,6 @@
 ALLOWED_HOSTS = ['*']
 
 # Application definition
-
 INSTALLED_APPS = [
     'django.contrib.admin',
     'django.contrib.auth',
@@ -161,6 +161,7 @@
 FEEDBACK_EVENT = 2
 EXAMPLE_EVENT_1 = 3
 EXAMPLE_EVENT_2 = 4
+TEST_EVENT_2 = 5
 
 
 NOTIFY_EVENTS = {
@@ -176,6 +177,9 @@
     EXAMPLE_EVENT_2: {
         'title': 'Example 2',
     },
+    TEST_EVENT_2: {
+            'title': 'TestEvent',
+        },
 }
 
 CHOICES_NOTIFY_EVENT = [(k, v['title']) for k, v in NOTIFY_EVENTS.items()]
diff --git a/backend/app/views.py b/backend/app/views.py
index b64cf50..c43bc85 100644
--- a/backend/app/views.py
+++ b/backend/app/views.py
@@ -1,10 +1,16 @@
+import datetime
+
 from django.shortcuts import render
 from garpix_notify.models import Notify
 from django.conf import settings
 
+#Перед началом создайте шаблон для регистрации
+
 
 def example_send_notify(request):
-    Notify.send(settings.EXAMPLE_EVENT_1, {
+    Notify.send(settings.REGISTRATION_EVENT, {
         'confirmation_code': 'abcdef12345',
-    }, email='aleksey@garpix.com')
+        'message': 'Привет, тут твое сообщение'
+    }, email='example@garpix.com', send_at=(datetime.datetime.now() + datetime.timedelta(days=1))
+                )
     return render(request, 'example.html')
diff --git a/backend/garpix_notify/README.rst b/backend/garpix_notify/README.rst
index 1d42dc9..bec7ba4 100644
--- a/backend/garpix_notify/README.rst
+++ b/backend/garpix_notify/README.rst
@@ -7,6 +7,7 @@ Quickstart
 
 Install with pip:
 
+
 .. code-block:: bash
 
    pip install garpix_notify
@@ -97,12 +98,56 @@ Step 1. Set notify types in ``app/settings.py``\ , for example:
 
    CHOICES_NOTIFY_EVENT = [(k, v['title']) for k, v in NOTIFY_EVENTS.items()]
 
-Step 2. Go to the admin panel and go to the "Notifications" section - "SMTP accounts"
+Step 2. Import default settings in your ``app/settings.py``\
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.. code-block:: python
+
+    from garpix_notify.settings import *
+
+
+or copy from here if you want more customization
+
+.. code-block:: python
+
+    PERIODIC_SENDING = 60
+    EMAIL_MAX_DAY_LIMIT = 240
+    EMAIL_MAX_HOUR_LIMIT = 240
+    # SMS
+    SMS_URL_TYPE = 0
+    SMS_API_ID = 1234567890
+    SMS_LOGIN = ''
+    SMS_PASSWORD = ''
+    SMS_FROM = ''
+    # TELEGRAM
+    TELEGRAM_API_KEY = '000000000:AAAAAAAAAA-AAAAAAAA-_AAAAAAAAAAAAAA'
+    TELEGRAM_BOT_NAME = 'MySuperBot'
+    TELEGRAM_WELCOME_TEXT = 'Hello'
+    TELEGRAM_HELP_TEXT = '/set !help for HELP'
+    TELEGRAM_BAD_COMMAND_TEXT = 'Incorrect command format'
+    TELEGRAM_SUCCESS_ADDED_TEXT = 'Success'
+    TELEGRAM_FAILED_ADDED_TEXT = 'Failed'
+    # VIBER
+    VIBER_API_KEY = '000000000:AAAAAAAAAA-AAAAAAAA-_AAAAAAAAAAAAAA'
+    VIBER_BOT_NAME = 'MySuperViberBot'
+    VIBER_WELCOME_TEXT = 'Hello'
+    VIBER_SUCCESS_ADDED_TEXT = 'Success'
+    VIBER_FAILED_ADDED_TEXT = 'Failed'
+    VIBER_TEXT_FOR_NEW_SUB = 'HI!'
+    # SETTINGS
+    IS_EMAIL_ENABLED = True
+    IS_SMS_ENABLED = True
+    IS_PUSH_ENABLED = True
+    IS_TELEGRAM_ENABLED = True
+    IS_VIBER_ENABLED = True
+    EMAIL_MALLING = 1
+
+
+Step 3. Go to the admin panel and go to the "Notifications" section - "SMTP accounts"
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Add an SMTP account to send Email notifications. These will be the senders of Email notifications.
 
-Step 3. Also go to "Notifications" - "Categories"
+Step 4. Also go to "Notifications" - "Categories"
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Create a category that will be used to send emails. Usually one category is enough. The ability to enter several categories
@@ -130,7 +175,7 @@ In the code where it is necessary to work out sending a notification, we perform
    # third - the user to send it to (it is not necessary to specify his email, phone number, etc.,
    # because this will be determined automatically depending on the type of template)
 
-   # Пример
+   # Example
    user = request.user  # this will be the recipient of the notification.
 
    Notify(settings.REGISTRATION_EVENT, {
@@ -143,8 +188,19 @@ In the code where it is necessary to work out sending a notification, we perform
        'confirmation_code': 'abcdef12345',
    }, email='example@mail.ru')
 
-Do not forget run celery:
+   # If you need more detailed time settings, add send_at
+
+   Notify(settings.EXAMPLE_EVENT_1, {
+       'confirmation_code': 'abcdef12345',
+   }, email='example@mail.ru', send_at=(datetime.datetime.now() + datetime.timedelta(days=1)))
 
+Mass email mailing
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+To perform a mass mailing, you need to add user lists to the template.
+Or directly in the notification.
+
+Do not forget run celery:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 .. code-block::
 
    celery -A app worker --loglevel=info -B
diff --git a/backend/garpix_notify/admin/config.py b/backend/garpix_notify/admin/config.py
index 45fb513..8986a82 100644
--- a/backend/garpix_notify/admin/config.py
+++ b/backend/garpix_notify/admin/config.py
@@ -11,7 +11,7 @@ class NotifyConfigAdmin(SingletonModelAdmin):
                        'is_viber_enabled')
         }),
         ('Почта', {
-            'fields': ('email_max_day_limit', 'email_max_hour_limit')
+            'fields': ('email_max_day_limit', 'email_max_hour_limit', 'email_malling')
         }),
         ('СМС', {
             'fields': ('sms_url_type', 'sms_api_id', 'sms_login', 'sms_password', 'sms_from')
diff --git a/backend/garpix_notify/admin/notify.py b/backend/garpix_notify/admin/notify.py
index 07860c2..be23634 100644
--- a/backend/garpix_notify/admin/notify.py
+++ b/backend/garpix_notify/admin/notify.py
@@ -1,4 +1,5 @@
 from django.contrib import admin
+
 from ..models.notify import Notify
 from .log import NotifyErrorLogInline
 
@@ -24,3 +25,4 @@ class NotifyAdmin(admin.ModelAdmin):
     list_filter = ('event', 'state', 'type', 'category')
     search_fields = ('subject', 'text')
     raw_id_fields = ('user',)
+    filter_horizontal = ('users_list', )
diff --git a/backend/garpix_notify/admin/template.py b/backend/garpix_notify/admin/template.py
index 76f7744..00b9c23 100644
--- a/backend/garpix_notify/admin/template.py
+++ b/backend/garpix_notify/admin/template.py
@@ -2,6 +2,7 @@
 from ..models.template import NotifyTemplate
 from ..models.notify import Notify
 from django.http import HttpResponseRedirect
+from ..models import NotifyCategory, SMTPAccount
 
 
 @admin.register(NotifyTemplate)
@@ -32,6 +33,7 @@ class NotifyTemplateAdmin(admin.ModelAdmin):
     list_display = ('title', 'is_active', 'type', 'category', 'event', 'user', 'email', 'phone', 'send_at')
     list_filter = ('type', 'category', 'event', 'is_active')
     actions = ['create_mailing', ]
+    filter_horizontal = ('user_lists',)
 
     def create_mailing(self, request, queryset):
         count = Notify.send(event=None, context={}, notify_templates=queryset)
@@ -40,18 +42,18 @@ def create_mailing(self, request, queryset):
 
     def response_change(self, request, obj):
         from ..models.notify import Notify
-        if (obj.user and "_send_now" in request.POST) or (obj.email and "_send_now" in request.POST):
+        if obj.user_lists and "_send_now" in request.POST:
 
             context = obj.get_test_data()
             template = obj
             instance = Notify.objects.create(
-                subject=template.render_subject(template.subject),
-                text=template.render_text(context),
-                html=template.render_html(context),
-                user=template.user,
-                email=template.email,
-                type=template.type,
-                category=template.category
+                subject=obj.render_subject(template.subject),
+                text=obj.render_text(context),
+                html=obj.render_html(context),
+                user=obj.user,
+                email=obj.email,
+                type=obj.type,
+                category=obj.category,
             )
             instance.save()
             instance._send()
diff --git a/backend/garpix_notify/admin/user_list.py b/backend/garpix_notify/admin/user_list.py
index ddf4d83..252a9b0 100644
--- a/backend/garpix_notify/admin/user_list.py
+++ b/backend/garpix_notify/admin/user_list.py
@@ -6,7 +6,7 @@
 class NotifyUserListParticipantInline(admin.TabularInline):
     model = NotifyUserListParticipant
     raw_id_fields = ('user', )
-    fields = ('user', 'email')
+    fields = ('user', 'email', 'phone', 'viber_chat_id')
 
 
 @admin.register(NotifyUserList)
@@ -17,3 +17,4 @@ class NotifyUserListAdmin(admin.ModelAdmin):
     ]
     readonly_fields = ('created_at',)
     search_fields = ('title',)
+    filter_horizontal = ('user_groups',)
diff --git a/backend/garpix_notify/admin/user_list_participant.py b/backend/garpix_notify/admin/user_list_participant.py
new file mode 100644
index 0000000..e69de29
diff --git a/backend/garpix_notify/models/config.py b/backend/garpix_notify/models/config.py
index 4cef0a1..4bbd4b2 100644
--- a/backend/garpix_notify/models/config.py
+++ b/backend/garpix_notify/models/config.py
@@ -3,6 +3,14 @@
 
 
 class NotifyConfig(SingletonModel):
+    class EMAIL_MALLING:
+        CC = 0
+        BCC = 1
+        TYPES = (
+            (CC, 'Обычная рассылка'),
+            (BCC, 'Скрытая рассылка'),
+        )
+
     class SMS_URL:
         """
         URL СМС провайдера
@@ -10,13 +18,28 @@ class SMS_URL:
 
         SMSRU_ID = 0
         WEBSZK_ID = 1
+        IQSMS_ID = 2
+        INFOSMS_ID = 3
+        SMSCENTRE_ID = 4
+        SMS_SENDING_ID = 5
+        SMS_PROSTO_ID = 6
 
-        SMSRU_URL = 'http://sms.ru/send/'
+        SMSRU_URL = 'https://sms.ru/sms/send/'
         WEBSZK_URL = 'http://gateway.api.sc/get/'
+        IQSMS_URL = 'https://api.iqsms.ru/messages/v2/send.json'
+        INFOSMS_URL = 'http://api.infosmska.ru/interfaces/SendMessages.ashx'
+        SMSCENTRE_URL = 'https://smsc.ru/sys/send.php'
+        SMS_SENDING_URL = 'http://lcab.sms-sending.ru/lcabApi/sendSms.php'
+        SMS_PROSTO_URL = 'http://api.sms-prosto.ru/'
 
         TYPES = (
             (SMSRU_ID, 'sms.ru'),
             (WEBSZK_ID, 'web.szk-info.ru'),
+            (IQSMS_ID, 'iqsms.ru'),
+            (INFOSMS_ID, 'infosmska.ru'),
+            (SMSCENTRE_ID, 'smsc.ru'),
+            (SMS_SENDING_ID, 'sms-sending.ru'),
+            (SMS_PROSTO_ID, 'sms-prosto.ru')
         )
 
     periodic = models.IntegerField(default=60, verbose_name='Периодичность отправки уведомлений (сек.)')
@@ -60,8 +83,7 @@ class SMS_URL:
     is_email_enabled = models.BooleanField(default=True, verbose_name='Разрешить отправку Email')
     is_sms_enabled = models.BooleanField(default=True, verbose_name='Разрешить отправку SMS')
     is_push_enabled = models.BooleanField(default=True, verbose_name='Разрешить отправку PUSH')
-    is_telegram_enabled = models.BooleanField(default=True, verbose_name='Разрешить отправку Telegram',
-                                              help_text='Внимание! Telegram недоступен на серверах на территории РФ и работать на них не будет!.')
+    is_telegram_enabled = models.BooleanField(default=True, verbose_name='Разрешить отправку Telegram')
     is_viber_enabled = models.BooleanField(default=True, verbose_name='Разрешить отправку Viber')
 
     viber_success_added_text = models.TextField(blank=True,
@@ -78,7 +100,13 @@ class SMS_URL:
     viber_welcome_text = models.TextField(blank=True,
                                           default='для активации бота нужно отправить любое сообщения',
                                           verbose_name='Viber - Приветственный текст бота')
+    email_malling = models.IntegerField(default=EMAIL_MALLING.BCC, choices=EMAIL_MALLING.TYPES,
+                                        verbose_name='Тип массовой рассылки',
+                                        help_text='Если выбрана обычная рассылка, то пользователи будут видеть email друг друга')
 
     class Meta:
         verbose_name = 'Настройка'
         verbose_name_plural = 'Настройки'
+
+    def __str__(self):
+        return 'Настройки'
diff --git a/backend/garpix_notify/models/notify.py b/backend/garpix_notify/models/notify.py
index 9ed9f31..ccae64d 100644
--- a/backend/garpix_notify/models/notify.py
+++ b/backend/garpix_notify/models/notify.py
@@ -3,21 +3,23 @@
 from email.mime.application import MIMEApplication
 from email.mime.multipart import MIMEMultipart
 from email.mime.text import MIMEText
+from email.header import Header
 from typing import Optional
 from smtplib import SMTP, SMTP_SSL
-import requests
 from django.conf import settings
 from django.db import models, transaction
+from django.db.models import Q
 from django.template import Template, Context
 from django.utils.html import format_html
 from django.utils.module_loading import import_string
 from django.utils.safestring import mark_safe
 from django.utils.timezone import now
-from django.contrib.auth import get_user_model
 from django.db.models.signals import post_save
 from django.dispatch import receiver
 from viberbot import Api, BotConfiguration
 from viberbot.api.messages import TextMessage
+
+from .user_list import NotifyUserList
 from .category import NotifyCategory
 from .choices import TYPE, STATE
 from .config import NotifyConfig
@@ -27,6 +29,8 @@
 from .smtp import SMTPAccount
 from .template import NotifyTemplate
 from ..mixins import UserNotifyMixin
+from ..utils import receiving_users
+from ..utils.sms_checker import SMSCLient
 
 
 def chunks(s, n):
@@ -35,12 +39,31 @@ def chunks(s, n):
         yield s[start:start + n]
 
 
-class Notify(UserNotifyMixin):
+try:
+    config = NotifyConfig.get_solo()
+    IS_PUSH_ENABLED = config.is_push_enabled
+    IS_TELEGRAM_ENABLED = config.is_telegram_enabled
+    TELEGRAM_API_KEY = config.telegram_api_key
+    IS_VIBER_ENABLED = config.is_viber_enabled
+    VIBER_API_KEY = config.viber_api_key
+    VIBER_BOT_NAME = config.viber_bot_name
+    IS_EMAIL_ENABLED = config.is_email_enabled
+    EMAIL_MALLING = config.email_malling
+except Exception:
+    IS_PUSH_ENABLED = True
+    IS_TELEGRAM_ENABLED = True
+    IS_VIBER_ENABLED = True
+    IS_EMAIL_ENABLED = True
+    TELEGRAM_API_KEY = getattr(settings, 'TELEGRAM_API_KEY', '000000000:AAAAAAAAAA-AAAAAAAA-_AAAAAAAAAAAAAA')
+    VIBER_API_KEY = getattr(settings, 'VIBER_API_KEY', '000000000:AAAAAAAAAA-AAAAAAAA-_AAAAAAAAAAAAAA')
+    VIBER_BOT_NAME = getattr(settings, 'VIBER_BOT_NAME', 'MySuperBot')
+    EMAIL_MALLING = getattr(settings, 'EMAIL_MALLING', 1)
+
+
+class Notify(UserNotifyMixin, SMSCLient):
     """
     Уведомление
     """
-
-    # title = models.CharField(max_length=255, verbose_name='Название для админа')
     subject = models.CharField(max_length=255, default='', blank=True, verbose_name='Тема')
     text = models.TextField(verbose_name='Текст')
     html = models.TextField(verbose_name='HTML', blank=True, default='')
@@ -53,8 +76,7 @@ class Notify(UserNotifyMixin):
 
     type = models.IntegerField(choices=TYPE.CHOICES, verbose_name='Тип')
     state = models.IntegerField(choices=STATE.CHOICES, default=STATE.WAIT, verbose_name='Состояние')
-    category = models.ForeignKey(NotifyCategory, on_delete=models.CASCADE, related_name='notifies',
-                                 verbose_name='Категория')
+    category = models.ForeignKey(NotifyCategory, on_delete=models.CASCADE, related_name='notifies', verbose_name='Категория')
     event = models.IntegerField(choices=settings.CHOICES_NOTIFY_EVENT, blank=True, null=True, verbose_name='Событие')
     files = models.ManyToManyField(NotifyFile, verbose_name='Файлы')
 
@@ -62,6 +84,8 @@ class Notify(UserNotifyMixin):
     data_json = models.TextField(blank=True, null=True, verbose_name='Данные пуш-уведомления (JSON)')
     room_name = models.CharField(max_length=255, null=True, blank=True, verbose_name='Название комнаты')
 
+    users_list = models.ManyToManyField(NotifyUserList, blank=True, verbose_name='Списки пользователей для рассылки')
+
     created_at = models.DateTimeField(auto_now_add=True, verbose_name='Дата создания')
     send_at = models.DateTimeField(blank=True, null=True, verbose_name='Время начала отправки')
     sent_at = models.DateTimeField(blank=True, null=True, verbose_name='Дата отправки')
@@ -99,15 +123,28 @@ def _send(self):
 
     def send_email(self):
         account = self._get_valid_smtp_account()
+        emails = []
+        if self.users_list.all().count() != 0:
+            users_list = self.users_list.all()
+            receivers = receiving_users(users_list)
+            # Убираем дубликаты пользователей
+            receivers = list({v['email']: v for v in receivers}.values())
+            for user in receivers:
+                if user['email']:
+                    emails.append(user['email'])
+            if self.email:
+                emails.append(self.email)
+        else:
+            emails.append(self.email)
 
         try:
-            body = self._render_body(account.sender, self.category.template)
+            body = self._render_body(mail_from=account.sender, layout=self.category, emails=emails)
             server = SMTP_SSL(account.host, account.port) if account.is_use_ssl else SMTP(account.host, account.port)
             server.ehlo()
             if account.is_use_tls:
                 server.starttls()
             server.login(account.username, account.password)
-            server.sendmail(account.sender, [self.email], body.as_string())
+            server.sendmail(account.sender, emails, body.as_string())
             server.close()
             self.state = STATE.DELIVERED
             self.sent_at = now()
@@ -115,55 +152,9 @@ def send_email(self):
             self.state = STATE.REJECTED
             self.to_log(str(e))
 
-    def send_sms(self):
-        config = NotifyConfig.get_solo()
-
-        if not config.is_sms_enabled:
-            self.state = STATE.DISABLED
-            return
-
-        try:
-            msg = str(self.text.replace(' ', '+'))
-            if config.sms_url_type == NotifyConfig.SMS_URL.SMSRU_ID:
-                url = '{url}?msg={text}&to={to}&api_id={api_id}&from={from_text}&json=1'.format(
-                    url=NotifyConfig.SMS_URL.SMSRU_URL,
-                    api_id=config.sms_api_id,
-                    from_text=config.sms_from,
-                    to=self.phone,
-                    text=msg,
-                )
-                response = requests.get(url)
-                response_dict = response.json()
-                if response_dict.get('status'):
-                    self.state = STATE.DELIVERED
-                    self.sent_at = now()
-                else:
-                    self.state = STATE.REJECTED
-            else:
-                url = '{url}?user={user}&pwd={pwd}&sadr={from_text}&text={text}&dadr={to}'.format(
-                    url=NotifyConfig.SMS_URL.WEBSZK_URL,
-                    user=config.sms_login,
-                    pwd=config.sms_password,
-                    from_text=config.sms_from,
-                    to=self.phone,
-                    text=msg,
-                )
-                response = requests.get(url)
-                try:
-                    int(response.text)
-                    self.state = STATE.DELIVERED
-                    self.sent_at = now()
-                except Exception:
-                    self.state = STATE.REJECTED
-
-        except Exception as e:  # noqa
-            self.state = STATE.REJECTED
-            self.to_log(str(e))
-
     def send_push(self):
-        config = NotifyConfig.get_solo()
 
-        if not config.is_push_enabled:
+        if not IS_PUSH_ENABLED:
             self.state = STATE.DISABLED
             return
 
@@ -191,10 +182,9 @@ def send_push(self):
 
     def send_telegram(self):
         import telegram
-        config = NotifyConfig.get_solo()
-        bot = telegram.Bot(token=config.telegram_api_key)
+        bot = telegram.Bot(token=TELEGRAM_API_KEY)
 
-        if not config.is_telegram_enabled:
+        if not IS_TELEGRAM_ENABLED:
             self.state = STATE.DISABLED
             return
 
@@ -212,177 +202,25 @@ def send_telegram(self):
             self.state = STATE.REJECTED
             self.to_log(str(e))
 
-    # todo - упростить метод (too complex)
-    @staticmethod
-    def send(event, context, user=None, email=None, phone=None, files=None, data_json=None, notify_templates=None,  # noqa
-             viber_chat_id=None, room_name=None):
-        User = get_user_model()
-
-        if user is not None:
-            email = user.email if not email else email
-            phone = user.phone if not phone else phone
-
-        user_want_message_check = None
-        if hasattr(settings, 'NOTIFY_USER_WANT_MESSAGE_CHECK') and settings.NOTIFY_USER_WANT_MESSAGE_CHECK is not None:
-            user_want_message_check = import_string(settings.NOTIFY_USER_WANT_MESSAGE_CHECK)
-
-        # Для выбора шаблонов в action'е
-        if notify_templates:
-            templates = NotifyTemplate.objects.filter(id__in=notify_templates, event=event, is_active=True)
-        else:
-            templates = NotifyTemplate.objects.filter(event=event, is_active=True)
-
-        if files is None:
-            files = []
-
-        data_json = json.dumps(data_json) if data_json is not None else None
-
-        file_instances = []
-        for f in files:
-            instance = NotifyFile.objects.create(file=f)
-            file_instances.append(instance)
-
-        notification_count = 0
-        for template in templates:
-            # Формируем список основных и дополнительных получателей письма
-            # Первого получателя заполняем из шаблона, его данные могут быть пустыми - чтобы можно было через
-            # код отправить уведомление
-            if template.user or template.email or template.phone or template.viber_chat_id:
-                recievers = [{
-                    'user': template.user,
-                    'email': template.email,
-                    'phone': template.phone,
-                    'viber_chat_id': template.viber_chat_id,
-                }]
-            elif user or phone or email or viber_chat_id:
-                recievers = [{
-                    'user': user,
-                    'email': email,
-                    'phone': phone,
-                    'viber_chat_id': viber_chat_id,
-                }]
-            else:
-                recievers = []
-
-            for user_list in template.user_lists.all():
-                for participant in user_list.participants.all():
-                    # Если у участника из дополнительного списка ничего не заполнено - не отправляем уведомление
-                    if participant.user is not None:
-                        recievers.append({
-                            'user': participant.user,
-                            'email': participant.email,
-                            'phone': participant.phone,
-                            'viber_chat_id': participant.viber_chat_id,
-                        })
-                    elif participant.email is not None:
-                        recievers.append({
-                            'user': participant.user,
-                            'email': participant.email,
-                            'phone': participant.phone,
-                            'viber_chat_id': participant.viber_chat_id,
-                        })
-
-                # Если в списке отмечены группы
-                if user_list.user_groups and not user_list.mail_to_all:
-                    group_users = User.objects.filter(groups__in=list(user_list.user_groups.all()))
-                    for user in group_users:
-                        recievers.append(
-                            {
-                                'user': user,
-                                'email': user.email,
-                                'phone': user.phone,
-                                'viber_chat_id': user.viber_chat_id,
-                            }
-                        )
-                    # Убираем дубликаты пользователей
-                    recievers = list({v['email']: v for v in recievers}.values())
-
-                # Если в списке пользователей отмечены все пользователи
-                if user_list.mail_to_all:
-                    recievers = []
-                    users = User.objects.all()
-                    for user in users:
-                        recievers.append(
-                            {
-                                'user': user,
-                                'email': user.email,
-                                'phone': user.phone,
-                                'viber_chat_id': user.viber_chat_id,
-                            }
-                        )
-            for reciever in recievers:
-                template_user = reciever['user']
-                template_email = reciever['email']
-                template_phone = reciever['phone']
-                template_viber_chat_id = reciever['viber_chat_id']
-                # Если в шаблоне не указан получатель, то получатель тот, кого передали в коде
-                if template_user is None and template_email is None and template_phone is None and template_viber_chat_id is None:
-                    template_user = user
-                    template_email = email
-                    template_phone = phone
-                    template_viber_chat_id = viber_chat_id
-                    # Если пользователь заполнен, то перезаписываем поля емейла и номера телефона,
-                    # даже если они были переданы.
-                    if user is not None:
-                        template_email = user.email
-                        template_phone = user.phone
-                        template_viber_chat_id = user.viber_chat_id
-                # Проверка, хочет ли получить сообщение
-                if user_want_message_check is not None and not \
-                        user_want_message_check(event, template.type, template_user):  # noqa
-                    continue
-
-                local_context = context.copy()
-
-                # Добавляем пользователя в контекст, если его там не передали
-                if template_user is not None:
-                    if local_context is not None:
-                        local_context.update({
-                            'user': template_user,
-                        })
-                    else:
-                        local_context = {
-                            'user': template_user,
-                        }
-                local_context['event_id'] = event
-
-                instance = Notify.objects.create(
-                    subject=template.render_subject(local_context),
-                    text=template.render_text(local_context),
-                    html=template.render_html(local_context),
-                    user=template_user,
-                    email=template_email,
-                    phone=template_phone if template_phone is not None else "",
-                    viber_chat_id=template_viber_chat_id if template_viber_chat_id is not None else "",
-                    type=template.type,
-                    event=template.event,
-                    category=template.category,
-                    data_json=data_json,
-                    send_at=template.send_at,
-                    room_name=room_name
-                )
-                file_instance = instance.files
-                for f in file_instances:
-                    file_instance.add(f)
-                instance.save()
-                notification_count += 1
-
-        return notification_count
-
-    def _render_body(self, mail_from, layout):
+    def _render_body(self, mail_from, layout, emails):
         msg = MIMEMultipart('alternative')
-
-        msg['Subject'] = self.subject
+        if len(emails) > 1:
+            if EMAIL_MALLING == 1:
+                msg['BCC'] = ', '.join(emails)
+            else:
+                msg['СС'] = ', '.join(emails)
+        else:
+            msg['To'] = ''.join(emails)
+        msg['Subject'] = Header(self.subject, 'utf-8')
         msg['From'] = mail_from
-        msg['To'] = self.email
 
-        text = MIMEText(self.text, 'plain')
+        text = MIMEText(self.text, 'plain', 'utf-8')
         msg.attach(text)
 
         if self.html:
-            template = Template(layout)
+            template = Template(layout.template)
             context = Context({'text': mark_safe(self.html)})
-            html = MIMEText(mark_safe(template.render(context)), 'html')
+            html = MIMEText(mark_safe(template.render(context)), 'html', 'utf-8')
             msg.attach(html)
 
         for fl in self.files.all():
@@ -416,13 +254,12 @@ def to_log(self, error_text):
         log.save()
 
     def send_viber(self):
-        config = NotifyConfig.get_solo()
         viber = Api(BotConfiguration(
-            name=config.viber_bot_name,
+            name=VIBER_BOT_NAME,
             avatar='',
-            auth_token=config.viber_api_key
+            auth_token=VIBER_API_KEY
         ))
-        if not config.is_viber_enabled:
+        if not IS_VIBER_ENABLED:
             self.state = STATE.DISABLED
             return
         try:
@@ -451,8 +288,7 @@ def send_viber(self):
             self.to_log(str(e))
 
     def _get_valid_smtp_account(self) -> Optional[SMTPAccount]:
-        config = NotifyConfig.get_solo()
-        if not config.is_email_enabled:
+        if not IS_EMAIL_ENABLED:
             self.state = STATE.DISABLED
             return
 
@@ -463,6 +299,141 @@ def _get_valid_smtp_account(self) -> Optional[SMTPAccount]:
 
         return account
 
+    @staticmethod
+    def send(event, context, user=None, email=None, phone=None, files=None, data_json=None,  # noqa
+             viber_chat_id=None, room_name=None, notify_templates=None, send_at=None):
+        local_context = context.copy()
+
+        if user is not None:
+            email = user.email if not email else email
+            phone = user.phone if not phone else phone
+
+        user_want_message_check = None
+        if hasattr(settings, 'NOTIFY_USER_WANT_MESSAGE_CHECK') and settings.NOTIFY_USER_WANT_MESSAGE_CHECK is not None:
+            user_want_message_check = import_string(settings.NOTIFY_USER_WANT_MESSAGE_CHECK)
+
+        # Для выбора шаблонов из Категории или по ивенту
+        if notify_templates:
+            templates = NotifyTemplate.objects.filter(id__in=notify_templates, event=event, is_active=True)
+        else:
+            templates = NotifyTemplate.objects.filter(
+                Q(event=event) & Q(is_active=True)
+            )
+        if files is None:
+            files = []
+
+        data_json = json.dumps(data_json) if data_json is not None else None
+
+        file_instances = []
+        for f in files:
+            instance = NotifyFile.objects.create(file=f)
+            file_instances.append(instance)
+
+        notification_count = 0
+        receivers = []
+        for template in templates:
+            template_user = None
+            template_email = None
+            template_phone = None
+            template_viber_chat_id = None
+            if user or phone or email or viber_chat_id:
+                # Формируем список основных и дополнительных получателей письма
+                # Первого получателя заполняем из шаблона, его данные могут быть пустыми - чтобы можно было через
+                # код отправить уведомление
+                receivers = [{
+                    'user': user,
+                    'email': email,
+                    'phone': phone,
+                    'viber_chat_id': viber_chat_id,
+                }]
+            for receiver in receivers:
+                template_user = receiver['user']
+                template_email = receiver['email']
+                template_phone = receiver['phone']
+                template_viber_chat_id = receiver['viber_chat_id']
+                # Если в шаблоне не указаны получатели, то получатель тот, кого передали в функцию
+                if template_user is None and template_email is None:
+                    template_user = user
+                    template_email = email
+                    template_phone = phone
+                    template_viber_chat_id = viber_chat_id
+                    # Если пользователь заполнен, то перезаписываем поля емейла и номера телефона,
+                    # даже если они были переданы.
+                    if user is not None:
+                        template_email = user.email
+                        template_phone = user.phone
+                        template_viber_chat_id = user.viber_chat_id
+                # Проверка, хочет ли получить сообщение
+                if user_want_message_check is not None and not \
+                        user_want_message_check(event, template.type, template_user):  # noqa
+                    continue
+
+                # Добавляем пользователя в контекст, если его там не передали
+                if template_user is not None:
+                    if local_context is not None:
+                        local_context.update({
+                            'user': template_user,
+                        })
+                    else:
+                        local_context = {
+                            'user': template_user,
+                        }
+                local_context['event_id'] = event
+            # Проверка на наличие списка в шаблоне
+            # Если в шаблоне передаются списки пользователей, то отдаем их уведомлениям
+            # Если уведомление для одного пользователя, то создаем для одного
+            # Также идет проверка на время оправки
+            if send_at is not None:
+                notify_send = send_at
+            else:
+                notify_send = template.send_at
+            users_lists = template.user_lists.all()
+            if users_lists.count() == 0:
+                instance = Notify.objects.create(
+                    subject=template.render_subject(local_context),
+                    text=template.render_text(local_context),
+                    html=template.render_html(local_context),
+                    user=template_user,
+                    email=template_email,
+                    phone=template_phone if template_phone is not None else "",
+                    viber_chat_id=template_viber_chat_id if template_viber_chat_id is not None else "",
+                    type=template.type,
+                    event=template.event,
+                    category=template.category if template.category else None,
+                    data_json=data_json,
+                    send_at=notify_send,
+                    room_name=room_name
+                )
+                file_instance = instance.files
+                for f in file_instances:
+                    file_instance.add(f)
+                instance.save()
+                notification_count += 1
+            else:
+                instance = Notify.objects.create(
+                    subject=template.render_subject(local_context),
+                    text=template.render_text(local_context),
+                    html=template.render_html(local_context),
+                    user=template_user,
+                    email=template_email,
+                    phone=template_phone if template_phone is not None else "",
+                    viber_chat_id=template_viber_chat_id if template_viber_chat_id is not None else "",
+                    type=template.type,
+                    event=template.event,
+                    category=template.category if template.category else None,
+                    data_json=data_json,
+                    send_at=notify_send,
+                    room_name=room_name,
+                )
+                instance.users_list.add(*users_lists)
+                file_instance = instance.files
+                for f in file_instances:
+                    file_instance.add(f)
+                instance.save()
+                notification_count += 1
+
+        return notification_count
+
     class Meta:
         verbose_name = 'Уведомление'
         verbose_name_plural = 'Уведомления'
@@ -470,6 +441,6 @@ class Meta:
 
 @receiver(post_save, sender=Notify)
 def system_post_save(sender, instance, created, **kwargs):
-    from garpix_notify.tasks import send_system_notifications
+    from garpix_notify.tasks.tasks import send_system_notifications
     if created and instance.type == TYPE.SYSTEM:
         transaction.on_commit(lambda: send_system_notifications.delay(instance.pk))
diff --git a/backend/garpix_notify/models/smtp.py b/backend/garpix_notify/models/smtp.py
index a340c37..5452eee 100644
--- a/backend/garpix_notify/models/smtp.py
+++ b/backend/garpix_notify/models/smtp.py
@@ -6,16 +6,15 @@
 
 
 class SMTPAccount(models.Model):
-    host = models.CharField(default='smtp.yandex.ru', max_length=255, verbose_name='Хост')
-    port = models.IntegerField(default=587, verbose_name='Порт')
-    is_use_tls = models.BooleanField(default=True, verbose_name='Использовать TLS?')
-    is_use_ssl = models.BooleanField(default=False, verbose_name='Использовать SSL?')
+    host = models.CharField(default='smtp.yandex.com', max_length=255, verbose_name='Хост')
+    port = models.IntegerField(default=465, verbose_name='Порт')
+    is_use_tls = models.BooleanField(default=False, verbose_name='Использовать TLS?')
+    is_use_ssl = models.BooleanField(default=True, verbose_name='Использовать SSL?')
     sender = models.EmailField(max_length=255, blank=True, default='', verbose_name='Отправитель')
     username = models.CharField(max_length=255, blank=True, default='', verbose_name='Имя пользователя')
     password = models.CharField(max_length=255, blank=True, default='', verbose_name='Пароль пользователя')
     timeout = models.IntegerField(default=5000, verbose_name='Таймаут (сек.)')
     category = models.ForeignKey(NotifyCategory, on_delete=models.CASCADE, related_name='accounts', verbose_name='Тип')
-
     is_active = models.BooleanField(default=True, verbose_name='Включить аккаунт')
 
     email_hour_used_times = models.IntegerField(default=0, verbose_name='Количество использований в час')
diff --git a/backend/garpix_notify/models/template.py b/backend/garpix_notify/models/template.py
index 9bb9f4e..4efeb96 100644
--- a/backend/garpix_notify/models/template.py
+++ b/backend/garpix_notify/models/template.py
@@ -2,8 +2,8 @@
 from django.conf import settings
 from django.template import Template, Context
 
-from .choices import TYPE
 from .category import NotifyCategory
+from .choices import TYPE
 from .user_list import NotifyUserList
 
 from ckeditor_uploader.fields import RichTextUploadingField
@@ -16,8 +16,10 @@ class NotifyTemplate(UserNotifyMixin):
     text = models.TextField(verbose_name='Текст')
     html = RichTextUploadingField(verbose_name='HTML')
 
-    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, blank=True, null=True, verbose_name='Пользователь (получатель)')
-    email = models.EmailField(max_length=255, blank=True, null=True, verbose_name='Email получатель', help_text='Используется только в случае отсутствия указанного пользователя')
+    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, blank=True, null=True,
+                             verbose_name='Пользователь (получатель)')
+    email = models.EmailField(max_length=255, blank=True, null=True, verbose_name='Email получатель',
+                              help_text='Используется только в случае отсутствия указанного пользователя')
 
     type = models.IntegerField(choices=TYPE.CHOICES, verbose_name='Тип')
     category = models.ForeignKey(NotifyCategory, on_delete=models.CASCADE, related_name='templates', verbose_name='Категория')
@@ -27,7 +29,7 @@ class NotifyTemplate(UserNotifyMixin):
     is_active = models.BooleanField(default=True, verbose_name='Активный')
     send_at = models.DateTimeField(blank=True, null=True, verbose_name='Время начала отправки')
 
-    user_lists = models.ManyToManyField(NotifyUserList, blank=True, verbose_name='Списки пользователей, которые получат копию уведомления')
+    user_lists = models.ManyToManyField(NotifyUserList, blank=True, verbose_name='Списки пользователей для рассылки')
 
     def render_subject(self, ct):
         template = Template(self.subject)
diff --git a/backend/garpix_notify/models/user_list.py b/backend/garpix_notify/models/user_list.py
index baea821..b97b5bb 100644
--- a/backend/garpix_notify/models/user_list.py
+++ b/backend/garpix_notify/models/user_list.py
@@ -6,7 +6,7 @@ class NotifyUserList(models.Model):
     title = models.CharField(max_length=255, verbose_name='Название списка пользователей')
     created_at = models.DateTimeField(auto_now_add=True, verbose_name='Дата создания')
     user_groups = models.ManyToManyField(Group, blank=True, verbose_name='Группы пользователей')
-    mail_to_all = models.BooleanField(default=False, verbose_name='Отправить всем')
+    mail_to_all = models.BooleanField(default=False, verbose_name='Массовая рассылка для всех пользователей сайта')
 
     def __str__(self):
         return self.title
diff --git a/backend/garpix_notify/models/user_list_participant.py b/backend/garpix_notify/models/user_list_participant.py
index 3552176..78c529e 100644
--- a/backend/garpix_notify/models/user_list_participant.py
+++ b/backend/garpix_notify/models/user_list_participant.py
@@ -5,7 +5,8 @@
 
 
 class NotifyUserListParticipant(UserNotifyMixin):
-    user_list = models.ForeignKey(NotifyUserList, on_delete=models.CASCADE, related_name='participants', verbose_name='Список пользователей для рассылки')
+    user_list = models.ForeignKey(NotifyUserList, on_delete=models.CASCADE, related_name='participants',
+                                  verbose_name='Список пользователей для рассылки')
     created_at = models.DateTimeField(auto_now_add=True, verbose_name='Дата создания')
     user = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True, on_delete=models.SET_NULL,
                              related_name='user_lists', verbose_name='Пользователь (получатель)')
@@ -16,5 +17,5 @@ def __str__(self):
         return f'Участник рассылки {self.pk}'
 
     class Meta:
-        verbose_name = 'Участник списка пользователей'
-        verbose_name_plural = 'Участники списка пользователей'
+        verbose_name = 'Дополнительный участник списка рассылки'
+        verbose_name_plural = 'Дополнительные участники списка рассылки'
diff --git a/backend/garpix_notify/settings.py b/backend/garpix_notify/settings.py
new file mode 100644
index 0000000..15eec14
--- /dev/null
+++ b/backend/garpix_notify/settings.py
@@ -0,0 +1,28 @@
+# notify config
+
+PERIODIC_SENDING = 60
+EMAIL_MAX_DAY_LIMIT = 240
+EMAIL_MAX_HOUR_LIMIT = 240
+# SMS
+SMS_URL_TYPE = 0
+SMS_API_ID = 1234567890
+SMS_LOGIN = ''
+SMS_PASSWORD = ''
+SMS_FROM = ''
+# TELEGRAM
+TELEGRAM_API_KEY = '000000000:AAAAAAAAAA-AAAAAAAA-_AAAAAAAAAAAAAA'
+TELEGRAM_BOT_NAME = 'MySuperBot'
+TELEGRAM_WELCOME_TEXT = 'Hello'
+TELEGRAM_HELP_TEXT = '/set !help for HELP'
+TELEGRAM_BAD_COMMAND_TEXT = 'Incorrect command format'
+TELEGRAM_SUCCESS_ADDED_TEXT = 'Success'
+TELEGRAM_FAILED_ADDED_TEXT = 'Failed'
+# VIBER
+VIBER_API_KEY = '000000000:AAAAAAAAAA-AAAAAAAA-_AAAAAAAAAAAAAA'
+VIBER_BOT_NAME = 'MySuperViberBot'
+VIBER_WELCOME_TEXT = 'Hello'
+VIBER_SUCCESS_ADDED_TEXT = 'Success'
+VIBER_FAILED_ADDED_TEXT = 'Failed'
+VIBER_TEXT_FOR_NEW_SUB = 'HI!'
+# SETTINGS
+EMAIL_MALLING = 1
diff --git a/backend/garpix_notify/setup.py b/backend/garpix_notify/setup.py
index 3741107..08deb3f 100644
--- a/backend/garpix_notify/setup.py
+++ b/backend/garpix_notify/setup.py
@@ -8,7 +8,7 @@
 
 setup(
     name='garpix_notify',
-    version='5.4.2',
+    version='5.5.0',
     description='',
     long_description=long_description,
     url='https://github.com/garpixcms/garpix_notify',
diff --git a/backend/garpix_notify/static/js/admin/garpix_notify.js b/backend/garpix_notify/static/js/admin/garpix_notify.js
index dd42ecc..6cf55ab 100644
--- a/backend/garpix_notify/static/js/admin/garpix_notify.js
+++ b/backend/garpix_notify/static/js/admin/garpix_notify.js
@@ -1,17 +1,31 @@
 window.onload = function(){
     let sms_url = document.querySelector('#id_sms_url_type');
 
-    if (parseInt(sms_url.value) == 0) {
+    if (parseInt(sms_url.value) === 0) {
         document.querySelector('.field-sms_login').classList.add('admin-none');
         document.querySelector('.field-sms_password').classList.add('admin-none');
     }
     else {
         document.querySelector('.field-sms_api_id').classList.add('admin-none');
+        document.querySelector('.field-sms_from').classList.add('admin-none');
     }
 
     sms_url.addEventListener('change', (event) => {
         if (parseInt(event.currentTarget.value) === 0){
             document.querySelector('.field-sms_api_id').classList.remove('admin-none');
+            document.querySelector('.field-sms_from').classList.remove('admin-none');
+            document.querySelector('.field-sms_login').classList.add('admin-none');
+            document.querySelector('.field-sms_password').classList.add('admin-none');
+        }
+        else if (parseInt(event.currentTarget.value) === 3){
+            document.querySelector('.field-sms_api_id').classList.add('admin-none');
+            document.querySelector('.field-sms_from').classList.remove('admin-none');
+            document.querySelector('.field-sms_login').classList.remove('admin-none');
+            document.querySelector('.field-sms_password').classList.remove('admin-none');
+        }
+        else if (parseInt(event.currentTarget.value) === 6){
+            document.querySelector('.field-sms_api_id').classList.remove('admin-none');
+            document.querySelector('.field-sms_from').classList.remove('admin-none');
             document.querySelector('.field-sms_login').classList.add('admin-none');
             document.querySelector('.field-sms_password').classList.add('admin-none');
         }
@@ -19,6 +33,7 @@ window.onload = function(){
             document.querySelector('.field-sms_login').classList.remove('admin-none');
             document.querySelector('.field-sms_password').classList.remove('admin-none');
             document.querySelector('.field-sms_api_id').classList.add('admin-none');
+            document.querySelector('.field-sms_from').classList.add('admin-none');
         }
     });
 }
\ No newline at end of file
diff --git a/backend/garpix_notify/tasks/__init__.py b/backend/garpix_notify/tasks/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/backend/garpix_notify/tasks.py b/backend/garpix_notify/tasks/tasks.py
similarity index 87%
rename from backend/garpix_notify/tasks.py
rename to backend/garpix_notify/tasks/tasks.py
index 02dea43..3d5750b 100644
--- a/backend/garpix_notify/tasks.py
+++ b/backend/garpix_notify/tasks/tasks.py
@@ -3,9 +3,9 @@
 from asgiref.sync import async_to_sync
 from channels.layers import get_channel_layer
 
-from .models.choices import STATE, TYPE
-from .models.config import NotifyConfig
-from .models.notify import Notify
+from garpix_notify.models.choices import STATE, TYPE
+from garpix_notify.models.config import NotifyConfig
+from garpix_notify.models.notify import Notify
 
 
 @celery_app.task
@@ -50,7 +50,7 @@ def send_system_notifications(notify_pk):
 
 celery_app.conf.beat_schedule.update({
     'periodic_task': {
-        'task': 'garpix_notify.tasks.send_notifications',
+        'task': 'garpix_notify.tasks.tasks.send_notifications',
         'schedule': NotifyConfig.get_solo().periodic,
     },
 })
diff --git a/backend/garpix_notify/utils/__init__.py b/backend/garpix_notify/utils/__init__.py
index ba40e62..44742c9 100644
--- a/backend/garpix_notify/utils/__init__.py
+++ b/backend/garpix_notify/utils/__init__.py
@@ -1,1 +1,3 @@
 from .file import get_file_path
+from .sms_checker import SMSCLient
+from .receiving import receiving_users
diff --git a/backend/garpix_notify/utils/receiving.py b/backend/garpix_notify/utils/receiving.py
new file mode 100644
index 0000000..671cf8b
--- /dev/null
+++ b/backend/garpix_notify/utils/receiving.py
@@ -0,0 +1,45 @@
+from django.contrib.auth import get_user_model
+from django.db.models import Q
+
+
+def receiving_users(users_list):
+    User = get_user_model()
+    for user_list in users_list:
+        receivers = []
+        # Сначала проверям есть ли дополнительные списки получателей
+        # Если у участника из дополнительного списка ничего не заполнено - ему уведомление не отправляем
+        for participant in user_list.participants.all():
+            if participant.user or participant.email:
+                receivers.append({
+                    'user': participant.user,
+                    'email': participant.email,
+                    'phone': participant.phone,
+                    'viber_chat_id': participant.viber_chat_id,
+                })
+        # Проверяем рассылку, не отмечена ли массовая рассылка
+        if user_list.mail_to_all is False:
+            group_users = User.objects.filter(
+                Q(groups__in=list(
+                    user_list.user_groups.all()
+                )))
+            for user in group_users:
+                receivers.append(
+                    {
+                        'user': user,
+                        'email': user.email,
+                        'phone': user.phone,
+                        'viber_chat_id': user.viber_chat_id,
+                    }
+                )
+        else:
+            users = User.objects.all()
+            for user in users:
+                receivers.append(
+                    {
+                        'user': user,
+                        'email': user.email,
+                        'phone': user.phone,
+                        'viber_chat_id': user.viber_chat_id,
+                    }
+                )
+        return receivers
diff --git a/backend/garpix_notify/utils/sms_checker.py b/backend/garpix_notify/utils/sms_checker.py
new file mode 100644
index 0000000..3583fdf
--- /dev/null
+++ b/backend/garpix_notify/utils/sms_checker.py
@@ -0,0 +1,170 @@
+import requests
+from django.conf import settings
+from django.utils.timezone import now
+
+from ..models.config import NotifyConfig
+from garpix_notify.models.choices import STATE
+from garpix_notify.utils.receiving import receiving_users
+
+try:
+    config = NotifyConfig.get_solo()
+    IS_SMS_ENABLED = config.is_sms_enabled
+    SMS_URL_TYPE = config.sms_url_type
+    SMS_API_ID = config.sms_api_id
+    SMS_LOGIN = config.sms_login
+    SMS_PASSWORD = config.sms_password
+    SMS_FROM = config.sms_from
+except Exception:
+    IS_SMS_ENABLED = True
+    SMS_URL_TYPE = getattr(settings, 'SMS_URL_TYPE', 0)
+    SMS_API_ID = getattr(settings, 'SMS_API_ID', 1234567890)
+    SMS_LOGIN = getattr(settings, 'SMS_LOGIN', '')
+    SMS_PASSWORD = getattr(settings, 'SMS_PASSWORD', '')
+    SMS_FROM = getattr(settings, 'SMS_FROM', '')
+
+
+class SMSCLient:
+
+    def send_sms(self):
+
+        if not IS_SMS_ENABLED:
+            self.state = STATE.DISABLED
+            return
+
+        try:
+            users_list = self.users_list.all()
+            if users_list.count() == 0:
+                phones = self.phone
+            else:
+                receivers = receiving_users(users_list)
+                # Убираем дубликаты пользователей
+                receivers = list({v['phone']: v for v in receivers}.values())
+                phones = []
+                for user in receivers:
+                    if user['phone']:
+                        phones.append(user['phone'])
+                phones = ','.join(phones)
+            msg = str(self.text.replace(' ', '+'))
+            if SMS_URL_TYPE == NotifyConfig.SMS_URL.SMSRU_ID:
+                url = '{url}?api_id={api_id}&to={to}&msg={text}&json=1'.format(
+                    url=NotifyConfig.SMS_URL.SMSRU_URL,
+                    api_id=SMS_API_ID,
+                    from_text=SMS_FROM,
+                    to=phones,
+                    text=msg,
+                )
+            elif SMS_URL_TYPE == NotifyConfig.SMS_URL.INFOSMS_ID:
+                url = '{url}?login={user}&pwd={pwd}&phones={to}&message={text}&sender={from_text}'.format(
+                    url=NotifyConfig.SMS_URL.INFOSMS_URL,
+                    user=SMS_LOGIN,
+                    pwd=SMS_PASSWORD,
+                    from_text=SMS_FROM,
+                    to=phones,
+                    text=msg,
+                )
+            elif SMS_URL_TYPE == NotifyConfig.SMS_URL.IQSMS_ID:
+                url = '{url}?login={user}&password={pwd}&phone={to}&text={text}'.format(
+                    url=NotifyConfig.SMS_URL.IQSMS_URL,
+                    user=SMS_LOGIN,
+                    pwd=SMS_PASSWORD,
+                    to=phones,
+                    text=msg,
+                )
+            elif SMS_URL_TYPE == NotifyConfig.SMS_URL.SMSCENTRE_ID:
+                url = '{url}?login={user}&psw={pwd}&phones={to}&mes={text}'.format(
+                    url=NotifyConfig.SMS_URL.SMSCENTRE_URL,
+                    user=SMS_LOGIN,
+                    pwd=SMS_PASSWORD,
+                    to=phones,
+                    text=msg,
+                )
+            elif SMS_URL_TYPE == NotifyConfig.SMS_URL.SMS_SENDING_ID:
+                url = '{url}?login={user}&password={pwd}&txt={text}&to={to}'.format(
+                    url=NotifyConfig.SMS_URL.SMS_SENDING_URL,
+                    user=SMS_LOGIN,
+                    pwd=SMS_PASSWORD,
+                    to=phones,
+                    text=msg,
+                )
+            elif SMS_URL_TYPE == NotifyConfig.SMS_URL.SMS_PROSTO_ID:
+                url = '{url}?method=push_msg&format=json&key={api_id}&text={text}&phone={to}&sender_name={from_text}'.format(
+                    url=NotifyConfig.SMS_URL.SMS_PROSTO_URL,
+                    api_id=SMS_API_ID,
+                    from_text=SMS_FROM,
+                    to=phones,
+                    text=msg,
+                )
+            else:
+                url = '{url}?user={user}&pwd={pwd}&sadr={from_text}&text={text}&dadr={to}'.format(
+                    url=NotifyConfig.SMS_URL.WEBSZK_URL,
+                    user=SMS_LOGIN,
+                    pwd=SMS_PASSWORD,
+                    from_text=SMS_FROM,
+                    to=phones,
+                    text=msg,
+                )
+            response = requests.get(url)
+            response_dict = response.json()
+            try:
+                if SMS_URL_TYPE == NotifyConfig.SMS_URL.SMSRU_ID:
+                    if response_dict['status'] == 'OK':
+                        self.to_log(
+                            f"Статус: {response_dict['status']}, Код статуса: {response_dict['status_code']}, Описание: {response_dict['status_text']}")
+                        self.state = STATE.DELIVERED
+                        self.sent_at = now()
+                    else:
+                        self.to_log(
+                            f"Статус: {response_dict['status']}, Код статуса: {response_dict['status_code']}, "
+                            f"Описание ошибки: {response_dict['status_text']}")
+                        self.state = STATE.REJECTED
+                elif SMS_URL_TYPE == NotifyConfig.SMS_URL.WEBSZK_ID:
+                    try:
+                        int(response.text)
+                        self.state = STATE.DELIVERED
+                        self.sent_at = now()
+                    except Exception:
+                        self.state = STATE.REJECTED
+                elif SMS_URL_TYPE == NotifyConfig.SMS_URL.IQSMS_ID:
+                    if response_dict['status'] == 'ok':
+                        self.to_log(
+                            f"Статус: {response_dict['status']}, Код статуса: {response_dict['code']}, Описание: {response_dict['description']}")
+                        self.state = STATE.DELIVERED
+                        self.sent_at = now()
+                    else:
+                        self.to_log(
+                            f"Статус: {response_dict['status']}, Код статуса: {response_dict['code']}, "
+                            f"Описание ошибки: {response_dict['description']}")
+                        self.state = STATE.REJECTED
+                elif SMS_URL_TYPE == NotifyConfig.SMS_URL.INFOSMS_ID:
+                    self.state = STATE.DELIVERED
+                    self.sent_at = now()
+                elif SMS_URL_TYPE == NotifyConfig.SMS_URL.SMSCENTRE_ID:
+                    self.state = STATE.DELIVERED
+                    self.sent_at = now()
+                elif SMS_URL_TYPE == NotifyConfig.SMS_URL.SMS_SENDING_ID:
+                    if response_dict['code'] == 1:
+                        self.to_log(
+                            f"Статус: {response_dict['code']}, Описание: {response_dict['descr']}")
+                        self.state = STATE.DELIVERED
+                        self.sent_at = now()
+                    else:
+                        self.to_log(
+                            f"Статус: {response_dict['code']}, Описание ошибки: {response_dict['descr']}")
+                        self.state = STATE.REJECTED
+                elif SMS_URL_TYPE == NotifyConfig.SMS_URL.SMS_PROSTO_ID:
+                    if response_dict['response']['msg']['err_code'] == 0:
+                        self.to_log(
+                            f"Статус: {response_dict['response']['msg']['err_code']}, Описание: {response_dict['response']['msg']['text']}")
+                        self.state = STATE.DELIVERED
+                        self.sent_at = now()
+                    else:
+                        self.to_log(
+                            f"Статус: {response_dict['response']['msg']['err_code']}, Описание ошибки: {response_dict['response']['msg']['text']}")
+                        self.state = STATE.REJECTED
+            except Exception as e:
+                self.state = STATE.REJECTED
+                self.to_log(str(e))
+
+        except Exception as e:  # noqa
+            self.state = STATE.REJECTED
+            self.to_log(str(e))
diff --git a/backend/user/admin.py b/backend/user/admin.py
index 9583ca4..e43969c 100644
--- a/backend/user/admin.py
+++ b/backend/user/admin.py
@@ -1,5 +1,5 @@
 from django.contrib import admin
-from .models import User
+from user.models.user import User
 from django.contrib.auth.admin import UserAdmin
 
 
@@ -14,6 +14,9 @@ class UserAdmin(UserAdmin):
         }),
         ('Telegram', {
             'fields': ('telegram_chat_id', 'telegram_secret', 'get_telegram_connect_user_help'),
+        }),
+        (None, {
+            'fields': ('phone', ),
         })
     ) + UserAdmin.fieldsets
     readonly_fields = ['telegram_secret', 'get_telegram_connect_user_help'] + list(UserAdmin.readonly_fields)
diff --git a/backend/user/models/__init__.py b/backend/user/models/__init__.py
new file mode 100644
index 0000000..b7bb9be
--- /dev/null
+++ b/backend/user/models/__init__.py
@@ -0,0 +1,1 @@
+from .user import User
\ No newline at end of file
diff --git a/backend/user/models.py b/backend/user/models/user.py
similarity index 100%
rename from backend/user/models.py
rename to backend/user/models/user.py


Test patch:
diff --git a/backend/garpix_notify/tests.py b/backend/garpix_notify/tests.py
index c237125..112a261 100644
--- a/backend/garpix_notify/tests.py
+++ b/backend/garpix_notify/tests.py
@@ -1,13 +1,21 @@
-from django.test import TestCase
-from .models import NotifyTemplate
-from .models import NotifyCategory
+import django
+import os
+
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "app.settings")
+django.setup()
+
+from django.utils.crypto import get_random_string
+from unittest import TestCase
+
+from django.contrib.auth import get_user_model
+from django.contrib.auth.models import Group
+
 from .models import Notify
+from .models import NotifyCategory
+from .models import NotifyTemplate
 from .models import NotifyUserList
 from .models import NotifyUserListParticipant
 from .models.choices import TYPE
-from django.contrib.auth import get_user_model
-from django.contrib.auth.models import Group
-
 
 User = get_user_model()
 
@@ -18,17 +26,13 @@ def setUp(self):
         self.PASS_TEST_EVENT = 0
         # тестовый пользователь
         self.data_user = {
-            'username': 'test',
+            'username': 'email_test' + get_random_string(length=4),
             'email': 'test@garpix.com',
             'password': 'BlaBla123',
             'first_name': 'Ivan',
             'last_name': 'Ivanov',
         }
         # data
-        self.data_category = {
-            'title': 'Основная категория',
-            'template': '<div>{{text}}</div>',
-        }
         self.data_template_email = {
             'title': 'Тестовый темплейт',
             'subject': 'Тестовый темплейт {{user.email}}',
@@ -37,6 +41,10 @@ def setUp(self):
             'type': TYPE.EMAIL,
             'event': self.PASS_TEST_EVENT,
         }
+        self.data_category = {
+            'title': 'Основная категория_' + get_random_string(length=4),
+            'template': '<div>{{text}}</div>',
+        }
         self.sometext = 'bla bla'
         self.data_compiled_email = {
             'subject': f'Тестовый темплейт {self.data_user["email"]}',
@@ -81,14 +89,9 @@ def test_notify_email_positive(self):
     def test_notify_email_user_list(self):
         # Создание пользователя
         user = User.objects.create_user(**self.data_user)
-        # Создание категории
-        category = NotifyCategory.objects.create(**self.data_category)
-        category = NotifyCategory.objects.get(pk=category.pk)
-        self.assertEqual(category.title, self.data_category['title'])
-        self.assertEqual(category.template, self.data_category['template'])
         # Создание списка
-        user_list = NotifyUserList.objects.create(title='Админы')
-        group = Group.objects.create(name="Админы клиенты")
+        user_list = NotifyUserList.objects.create(title='userlist_' + get_random_string(length=4))
+        group = Group.objects.create(name='group_' + get_random_string(length=4))
         user_list.user_groups.add(group)
 
         user_list_participant1 = NotifyUserListParticipant.objects.create(  # noqa
@@ -103,10 +106,17 @@ def test_notify_email_user_list(self):
             email='test3@garpix.com',
         )
 
+        # Создание категории
+        category = NotifyCategory.objects.create(**self.data_category)
+        category = NotifyCategory.objects.get(pk=category.pk)
+        self.assertEqual(category.title, self.data_category['title'])
+        self.assertEqual(category.template, self.data_category['template'])
+
         # Создание шаблона
         template_email = NotifyTemplate.objects.create(category=category, **self.data_template_email)
-        template_email.user_lists.add(user_list)
         template_email = NotifyTemplate.objects.get(pk=template_email.pk)
+        template_email.user_lists.add(user_list)
+        template_email.save()
 
         self.assertEqual(template_email.title, self.data_template_email['title'])
         self.assertEqual(template_email.subject, self.data_template_email['subject'])
@@ -122,9 +132,9 @@ def test_notify_email_user_list(self):
             'user': user,
         }, user=user)
 
-        self.assertEqual(Notify.objects.all().count(), 3)
+        self.assertEqual(Notify.objects.all().count(), 2)
 
-        # notify 1
+        # notify
         notify = Notify.objects.get(user=user)
         self.assertEqual(notify.subject, self.data_compiled_email['subject'])
         self.assertEqual(notify.text, self.data_compiled_email['text'])
@@ -132,22 +142,6 @@ def test_notify_email_user_list(self):
         self.assertEqual(notify.type, self.data_compiled_email['type'])
         self.assertEqual(notify.event, self.data_compiled_email['event'])
         self.assertEqual(notify.email, 'test@garpix.com')
-        # notify 2
-        notify = Notify.objects.get(email='test2@garpix.com')
-        self.assertEqual(notify.subject, self.data_compiled_email['subject'])
-        self.assertEqual(notify.text, self.data_compiled_email['text'])
-        self.assertEqual(notify.html, self.data_compiled_email['html'])
-        self.assertEqual(notify.type, self.data_compiled_email['type'])
-        self.assertEqual(notify.event, self.data_compiled_email['event'])
-        self.assertEqual(notify.email, 'test2@garpix.com')
-        # notify 3
-        notify = Notify.objects.get(email='test3@garpix.com')
-        self.assertEqual(notify.subject, self.data_compiled_email['subject'])
-        self.assertEqual(notify.text, self.data_compiled_email['text'])
-        self.assertEqual(notify.html, self.data_compiled_email['html'])
-        self.assertEqual(notify.type, self.data_compiled_email['type'])
-        self.assertEqual(notify.event, self.data_compiled_email['event'])
-        self.assertEqual(notify.email, 'test3@garpix.com')
 
     def test_notify_viber(self):
         self.data_template_viber = {
@@ -159,12 +153,12 @@ def test_notify_viber(self):
             'event': self.PASS_TEST_EVENT,
         }
         self.data_viber_user = {
-            'username': 'test',
+            'username': 'viber_' + get_random_string(length=5),
             'viber_secret_key': '111',
             'viber_chat_id': 'm4FsaRu5kBi8HzSAC0liFQ==',
             'password': 'BlaBla123',
-            'first_name': 'Ivan',
-            'last_name': 'Ivanov',
+            'first_name': 'IvanViber',
+            'last_name': 'IvanovViber',
         }
         self.data_compiled_viber = {
             'subject': f'Тестовый темплейт {self.data_viber_user["viber_chat_id"]}',
@@ -175,19 +169,24 @@ def test_notify_viber(self):
         }
         # Создание пользователя
         user = User.objects.create_user(**self.data_viber_user)
+        # Создание списка
+        user_list = NotifyUserList.objects.create(title='viber_' + get_random_string(length=4))
+        user_list_participant1 = NotifyUserListParticipant.objects.create(  # noqa
+            user_list=user_list,
+        )
         # Создание категории
         category = NotifyCategory.objects.create(**self.data_category)
         category = NotifyCategory.objects.get(pk=category.pk)
+
         self.assertEqual(category.title, self.data_category['title'])
         self.assertEqual(category.template, self.data_category['template'])
-        # Создание списка
-        user_list = NotifyUserList.objects.create(title='viber_user_list')
-        user_list_participant1 = NotifyUserListParticipant.objects.create(  # noqa
-            user_list=user_list,
-        )
-        template_viber = NotifyTemplate.objects.create(category=category, **self.data_template_viber)
-        template_viber.user_lists.add(user_list)
+
+        # Создание шаблона
+        template_viber = NotifyTemplate.objects.create(**self.data_template_viber, category=category)
         template_viber = NotifyTemplate.objects.get(pk=template_viber.pk)
+        template_viber.user_lists.add(user_list)
+        template_viber.save()
+
         self.assertEqual(template_viber.title, self.data_template_viber['title'])
         self.assertEqual(template_viber.subject, self.data_template_viber['subject'])
         self.assertEqual(template_viber.text, self.data_template_viber['text'])
@@ -196,13 +195,15 @@ def test_notify_viber(self):
         self.assertEqual(template_viber.event, self.data_template_viber['event'])
         self.assertEqual(template_viber.category.id, category.id)
 
+        # Создание уведомления
         Notify.send(self.PASS_TEST_EVENT, {
             'sometext': self.sometext,
             'user': user,
         }, user=user)
-        self.assertEqual(Notify.objects.all().count(), 1)
 
-        # notify 1
+        self.assertEqual(Notify.objects.all().count(), 3)
+
+        # notify
         notify = Notify.objects.get(user=user)
         self.assertEqual(notify.subject, self.data_compiled_viber['subject'])
         self.assertEqual(notify.text, self.data_compiled_viber['text'])