From 09e4edee6bd7185d795a7825c239068b82f86fec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BD=D0=B4=D1=80=D0=B5=D0=B9=20=D0=A6=D0=BE=D0=B9?= Date: Fri, 6 Dec 2024 09:27:06 +0900 Subject: [PATCH] init commit --- bot/__init__.py | 0 bot/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 163 bytes bot/__pycache__/admin.cpython-311.pyc | Bin 0 -> 218 bytes bot/__pycache__/apps.cpython-311.pyc | Bin 0 -> 528 bytes bot/__pycache__/models.cpython-311.pyc | Bin 0 -> 215 bytes bot/admin.py | 3 + bot/apps.py | 6 + bot/bot.py | 39 +++++ bot/migrations/__init__.py | 0 .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 174 bytes bot/models.py | 3 + bot/tests.py | 3 + bot/urls.py | 0 bot/views.py | 3 + hotels/__init__.py | 0 hotels/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 166 bytes hotels/__pycache__/admin.cpython-311.pyc | Bin 0 -> 1130 bytes hotels/__pycache__/apps.cpython-311.pyc | Bin 0 -> 537 bytes hotels/__pycache__/models.cpython-311.pyc | Bin 0 -> 1969 bytes hotels/__pycache__/urls.cpython-311.pyc | Bin 0 -> 162 bytes hotels/admin.py | 17 ++ hotels/apps.py | 6 + hotels/migrations/0001_initial.py | 33 ++++ hotels/migrations/0002_initial.py | 22 +++ hotels/migrations/__init__.py | 0 .../__pycache__/0001_initial.cpython-311.pyc | Bin 0 -> 1913 bytes .../__pycache__/0002_initial.cpython-311.pyc | Bin 0 -> 1008 bytes .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 177 bytes hotels/models.py | 23 +++ hotels/tests.py | 3 + hotels/urls.py | 0 hotels/views.py | 3 + manage.py | 22 +++ req.txt | 25 +++ touchh/__init__.py | 0 touchh/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 166 bytes touchh/__pycache__/settings.cpython-311.pyc | Bin 0 -> 3183 bytes touchh/__pycache__/urls.cpython-311.pyc | Bin 0 -> 405 bytes touchh/__pycache__/wsgi.cpython-311.pyc | Bin 0 -> 686 bytes touchh/asgi.py | 16 ++ touchh/settings.py | 151 ++++++++++++++++++ touchh/urls.py | 6 + touchh/wsgi.py | 16 ++ users/__init__.py | 0 users/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 165 bytes users/__pycache__/admin.cpython-311.pyc | Bin 0 -> 1225 bytes users/__pycache__/apps.cpython-311.pyc | Bin 0 -> 534 bytes users/__pycache__/models.cpython-311.pyc | Bin 0 -> 2517 bytes users/__pycache__/urls.cpython-311.pyc | Bin 0 -> 161 bytes users/admin.py | 15 ++ users/apps.py | 6 + users/migrations/0001_initial.py | 59 +++++++ users/migrations/__init__.py | 0 .../__pycache__/0001_initial.cpython-311.pyc | Bin 0 -> 4580 bytes .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 176 bytes users/models.py | 51 ++++++ users/tests.py | 3 + users/urls.py | 0 users/views.py | 3 + 59 files changed, 537 insertions(+) create mode 100644 bot/__init__.py create mode 100644 bot/__pycache__/__init__.cpython-311.pyc create mode 100644 bot/__pycache__/admin.cpython-311.pyc create mode 100644 bot/__pycache__/apps.cpython-311.pyc create mode 100644 bot/__pycache__/models.cpython-311.pyc create mode 100644 bot/admin.py create mode 100644 bot/apps.py create mode 100644 bot/bot.py create mode 100644 bot/migrations/__init__.py create mode 100644 bot/migrations/__pycache__/__init__.cpython-311.pyc create mode 100644 bot/models.py create mode 100644 bot/tests.py create mode 100644 bot/urls.py create mode 100644 bot/views.py create mode 100644 hotels/__init__.py create mode 100644 hotels/__pycache__/__init__.cpython-311.pyc create mode 100644 hotels/__pycache__/admin.cpython-311.pyc create mode 100644 hotels/__pycache__/apps.cpython-311.pyc create mode 100644 hotels/__pycache__/models.cpython-311.pyc create mode 100644 hotels/__pycache__/urls.cpython-311.pyc create mode 100644 hotels/admin.py create mode 100644 hotels/apps.py create mode 100644 hotels/migrations/0001_initial.py create mode 100644 hotels/migrations/0002_initial.py create mode 100644 hotels/migrations/__init__.py create mode 100644 hotels/migrations/__pycache__/0001_initial.cpython-311.pyc create mode 100644 hotels/migrations/__pycache__/0002_initial.cpython-311.pyc create mode 100644 hotels/migrations/__pycache__/__init__.cpython-311.pyc create mode 100644 hotels/models.py create mode 100644 hotels/tests.py create mode 100644 hotels/urls.py create mode 100644 hotels/views.py create mode 100755 manage.py create mode 100644 req.txt create mode 100644 touchh/__init__.py create mode 100644 touchh/__pycache__/__init__.cpython-311.pyc create mode 100644 touchh/__pycache__/settings.cpython-311.pyc create mode 100644 touchh/__pycache__/urls.cpython-311.pyc create mode 100644 touchh/__pycache__/wsgi.cpython-311.pyc create mode 100644 touchh/asgi.py create mode 100644 touchh/settings.py create mode 100644 touchh/urls.py create mode 100644 touchh/wsgi.py create mode 100644 users/__init__.py create mode 100644 users/__pycache__/__init__.cpython-311.pyc create mode 100644 users/__pycache__/admin.cpython-311.pyc create mode 100644 users/__pycache__/apps.cpython-311.pyc create mode 100644 users/__pycache__/models.cpython-311.pyc create mode 100644 users/__pycache__/urls.cpython-311.pyc create mode 100644 users/admin.py create mode 100644 users/apps.py create mode 100644 users/migrations/0001_initial.py create mode 100644 users/migrations/__init__.py create mode 100644 users/migrations/__pycache__/0001_initial.cpython-311.pyc create mode 100644 users/migrations/__pycache__/__init__.cpython-311.pyc create mode 100644 users/models.py create mode 100644 users/tests.py create mode 100644 users/urls.py create mode 100644 users/views.py diff --git a/bot/__init__.py b/bot/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/bot/__pycache__/__init__.cpython-311.pyc b/bot/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5080794ff2b55e93e9479d5f5e5bd530c85517df GIT binary patch literal 163 zcmZ3^%ge<81YKJK(?RrO5CH>>P{wCAAY(d13PUi1CZpdhBrG=?}Mt(_ZPJC`+USfJ`k$y>jX>vw}eo}sketdjpUS>&ryk0@&FAkgB h{FKt1RJ$TppfMneiur-W2WCb_#t#fIqKFwN1^`gPCIkQg literal 0 HcmV?d00001 diff --git a/bot/__pycache__/admin.cpython-311.pyc b/bot/__pycache__/admin.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ef863636b5463294267f4dc23c68da48d5952350 GIT binary patch literal 218 zcmZ3^%ge<81YKJK)9r!uV-N=hn4pZ$LO{lJh7^Vr#vF!R#wbQch7_h?22JLdAO)I? zw^$QXax?S%G?{MkrDP@MrRVD<=jW9aWhNCd0~M@f_zY6_%UD0OIJKx)zoaO&EWgOm z(!x|fBflgyCq6eZFEKr}NWUb%G&v(fKPkUNA8eprLFF$Fo80`A(wtPgA`YM#j6hs0 W3nV@;Gcq#XU{JV#4HdBgRR92QOgDf4 literal 0 HcmV?d00001 diff --git a/bot/__pycache__/apps.cpython-311.pyc b/bot/__pycache__/apps.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4d2f554aabae3b4fe4f02d77938dd2748e650b83 GIT binary patch literal 528 zcmZuty-UMD6n~eb(oa!`LI(%OEC~ui1rb_B2caP1lI2Ky*R+!4;w2Gu>fqGLt^a`{ zuKpn%OI9bhN}W1+m!yK|dw1{s-o3AT@3~ehgP`%-g)L@9-g5a3>{h`y#BT|KOV^J4i0u(GnK;$Az zC5ojHRn*XuQkz9t^8Gfswta^gq-%JLP&YK%L#Gu->~u(7lBiu4b@W0~#Mrkzig8lL zSOmtd#8r%MV%yC7Eu>_ zwr@L>n-Pn9gMle}nsyL`MsUaFvQnW55H^Gu{qU^OoND!1Wn*+Anb%ga9bHW-`CzgT zmut*QRV7LT*9BS@53^y8_=Yg$_QG=^<|;yH20PQ=XTGMO%{lxPkEKuf`t^@1ZT1bi C(SoM{ literal 0 HcmV?d00001 diff --git a/bot/__pycache__/models.cpython-311.pyc b/bot/__pycache__/models.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d4871555d1590de5d78e81ff92edfcbe49ae426b GIT binary patch literal 215 zcmZ3^%ge<81YKJK(=CDYV-N=hn4pZ$LO{lJh7^Vr#vF!R#wbQch7_h?22JLdAO)I? zx7c#?Q&Mw^{WO_wai(M?=B4NBr6d(G10`27dmS1FOX<@3L zkzbOU6Q7%ymzbVfq+gO>nw*iLpOjys4>3%ypz;@o4Uk=$lWJGQ0W^dWh>K-`#0O?Z QM#dWqG8eF+A~v830Fy;FA^-pY literal 0 HcmV?d00001 diff --git a/bot/admin.py b/bot/admin.py new file mode 100644 index 00000000..8c38f3f3 --- /dev/null +++ b/bot/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/bot/apps.py b/bot/apps.py new file mode 100644 index 00000000..1cd7ff2e --- /dev/null +++ b/bot/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class BotConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'bot' diff --git a/bot/bot.py b/bot/bot.py new file mode 100644 index 00000000..e50bfaf1 --- /dev/null +++ b/bot/bot.py @@ -0,0 +1,39 @@ +from telegram import Update +from telegram.ext import Updater, CommandHandler, CallbackContext +from users.models import User, UserConfirmation +import uuid + +def start(update: Update, context: CallbackContext): + user_id = update.message.from_user.id + chat_id = update.message.chat_id + + user, created = User.objects.get_or_create(telegram_id=user_id, defaults={'chat_id': chat_id}) + if not user.confirmed: + confirmation_code = str(uuid.uuid4()) + UserConfirmation.objects.create(user=user, confirmation_code=confirmation_code) + update.message.reply_text(f"Ваш код подтверждения: {confirmation_code}") + else: + update.message.reply_text("Вы уже зарегистрированы!") + +def confirm(update: Update, context: CallbackContext): + user_id = update.message.from_user.id + code = ' '.join(context.args) + + try: + confirmation = UserConfirmation.objects.get(user__telegram_id=user_id, confirmation_code=code) + confirmation.user.confirmed = True + confirmation.user.save() + confirmation.delete() + update.message.reply_text("Регистрация подтверждена!") + except UserConfirmation.DoesNotExist: + update.message.reply_text("Неверный код подтверждения!") + +def main(): + updater = Updater("YOUR_TELEGRAM_BOT_TOKEN") + dispatcher = updater.dispatcher + + dispatcher.add_handler(CommandHandler("start", start)) + dispatcher.add_handler(CommandHandler("confirm", confirm)) + + updater.start_polling() + updater.idle() diff --git a/bot/migrations/__init__.py b/bot/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/bot/migrations/__pycache__/__init__.cpython-311.pyc b/bot/migrations/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9dee32096064b54ac3bc8dc0d5665cc19bc574ba GIT binary patch literal 174 zcmZ3^%ge<81YKJK(?RrO5CH>>P{wCAAY(d13PUi1CZpdhBrG=?}Mt(_ZPJC`+USfJ`k$y>jX>vw}eo}sker{%ZQDRAEeqOPDe0*kJ sW=VX!UP0wA4x8Nkl+v73yCPPgi6A?R`GLd-W=2NF4-7D(h#4pb0DK)PdjJ3c literal 0 HcmV?d00001 diff --git a/bot/models.py b/bot/models.py new file mode 100644 index 00000000..71a83623 --- /dev/null +++ b/bot/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/bot/tests.py b/bot/tests.py new file mode 100644 index 00000000..7ce503c2 --- /dev/null +++ b/bot/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/bot/urls.py b/bot/urls.py new file mode 100644 index 00000000..e69de29b diff --git a/bot/views.py b/bot/views.py new file mode 100644 index 00000000..91ea44a2 --- /dev/null +++ b/bot/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/hotels/__init__.py b/hotels/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hotels/__pycache__/__init__.cpython-311.pyc b/hotels/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ffc96a93284ae8b2f9a525231f39082595608aac GIT binary patch literal 166 zcmZ3^%ge<81i4!R(?RrO5CH>>P{wCAAY(d13PUi1CZpdhBrG=?}Mt(_ZPJC`+USfJ`k$y>jX>vveM6g&tK0Y%qvm`!Vub}c5hfQvN gN@-52T@fqLB#>Rj{6OLZGb1D82L>2X#0(Sz0M?%;Gynhq literal 0 HcmV?d00001 diff --git a/hotels/__pycache__/admin.cpython-311.pyc b/hotels/__pycache__/admin.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a1eea6910f98f42b943dc466b8642853fca29537 GIT binary patch literal 1130 zcma)5y-(Xf6u!y!MQUMa#p31U=8nY3j?=SKDV;L# z2V~?zi;sWM$2c+FGfXlu&c2xH-^ z>~mZuVXVAF5YEB}I92UE&o46_+iImUvJw|(^UjD2al{$(WZ zdr{1|7qxu1qY9C5Wv#(>JmK?5O(($}&yR&vRw%iUUbB8cMo^DjtXFZnQ8kw0Ybam5 zdbw6@pbRWi=Th`uB*-+S-Nm*hRyYGn}SzFpX3vA@e;WrZ9p3;`xUfg%T7 zWFZ6!oB~xIfvOBWsQ|BHWo9WoC^1c4h?&XYhLwT^M3oro&7NQ`| zB1@%;rBPLAXi4?VkC+o?=O1?H4e@N>px1`$Q;|0ghju59{F5PbXi^-ce+rg;@I9-0wncRt^1x0+^p z19pi=Y{t#Vk9&hbmJCf21fdb!bJ?}jX##`|;YL4W)@V(&`mC}wI+laiR@|Qs&QsTNm%hG=Kp98)jLfOXfT)4T45Sqd6^!J<>6|_Bvzi!YaJ*|EnR9VtSQubg^o)t+{N_dYl2k`BJuKfll4?|pvn z`S+YZhK57}W9RZ$h2Q;z{Ed_D5RQz4RWLS*Ml?<*WiHEcX!~?u*`M`u#77p1=D$xg zo^q>v*Le$edj_XBvI1iXzzX~iE1(6_Bp%vDr#R;Z%7#XD3oQO?i<sGmeWYq=OfgA9E8SczNUZ62cf{}4Gg7^!)t;TDEPEsGc*u%V1UVKVfcy7$QGpe zte0vw_(q;|f)`@Ea5oazYp6Lq5S^$+?~`mq8-YT|u5iP!slNLUxYR{v$5LvU#(l0> zR)17 zF3y`&wW$`Hv*DqVTD1+OV*H?}n#Ra^4mRx$v{54mBLJJ^CxS}z2BgoW@XcdRPvL4& z{jP-$u~#1_P!3kYHfhZ;KltRzO-uSvq#e?>}p{jG)N~p_F&x!ojJfLQgO)*DXglB;);p_J5_ZGwxlTES5+NjQxp?Z zaKrOO)l8PCu9;&v53Q9g#fGxFL3OR9+@tHRxW?+l?4bpyQl?a<%*7S+UfC4YHs1pG zr^Gx17jql|wax$~XZ;D#=>0m8iH(oik%`}|7n4pT*@`6Fkz`|`6P@0uwWHIWvC|#- zf-`f?8JX{#p56=cBY}MaaEQ>ju_qE>-fa)Ry?x<%W`}pu-#Wu9t>KmS@JeH`BcFdb z-j>gAr(f_pmz+B}N6xq8d|S>pZg%7uT$_1*X-9YDbW2XR<#glb9?uD9_sB``^1)R4 z`ndOzv0>%E`j`sPvE7b`&rs7h(5V9*NJD*m{|SCrUSVOsuH4n0!k<8>u+sbVtfB`SPsp!+c(gB7_s8Ck#d(*n zLI`dM5k=(+Owde8<|%OTl<&y_^--65F?UsrQn981K*giukK*moi%#?^9NVXw=bF== z?S!tf7mbfip6 z%Cx0S<2tJ8Q&iI+cu&P=rQ$(1tgWh*f-$S*yeuTFqc!U_zL$q^8~;nZ1X!H?vA+s^ z<~8@{W&$?FS7`kLu;=GEu0tlB{-Z;toc?2vmpIV504io1r8EA2@eC0 Nq!Z zK&`h190UOPoqm2RN>Eq_S?Pqat67mKb-iM1u5OtQk?R&jhEu-4@^0XQIeQ_ny%FEH zC_O3NQ$zwtNtzcF@mnn<5NxWTYp7VHjyE2O>q$ z?-JE_1r>$;6%h`=8|~Peo>7hQD_DW*6yVMFt+)0bycT);8srd1^4u_+sJ=vd_^Oo^ zxt)AdMpykiE+hXVE~9+MzKak56s`65#h3n!q*OAkrbVQA z)-kYaYfWSrx`|qS1wPI^rp(FvOmTQ^Wj#}1D+44{u3CB-Id+WB_=-bXLuW>|LUU`& znMY`sx+0Yf&D`Q3YT}Mz_)w*>Q!?~2M=NW5%oY&k!f91=TT0#!KxWRRmiaL;t?yI~ zLarn$+AJAF-qeu+9TM4~vGHRmRar<|QQkR|yrVWpEK{Wi4Y`PjuEmwCX5%ER@(`*j zQB;*4#T^6Daa2{ecQk{Am2x57)Lj~Q5{0ONOo+^~PMv4xoAmjHuCPOFvy(=m^Lk~D z=5Uc&Mk4vDX8Xhb1)9==UPnHwELt|wD<*SYhBeKsSVV*+66RLYyMcuAbL;uJh0lm$ zHPFR<@f$d!n}AnKIp(pGb8XbL?CA#|f0*N*s&&oOD#*^c)=s%v^@UFE^@Wq0nwpwc zFFcxT?Aq)i;e^$>^Ao*s_AZ~712^{`c7wv8y!W^p29flSiWeU5#D`zTZ{x(>XH740 z_s`(-JGiJ~)5ZzsIN^8+2glq_Jb{zh{UI-zJzPKf9w!UO$%2*6V==bTbWydZYsBRDm&zv!hV4nH``KZjVW;ndb~ zYRgM);h52hkKuG~zv-oOhw#Y3Uv6O7!0GMd^tPAY#xa`%W*A`RXb=~^#cAz0t$Aq; z$4cG)(BME)x(BBFJ6vHhHFau{)=1;{2LfZo@x4zXZ$x literal 0 HcmV?d00001 diff --git a/hotels/migrations/__pycache__/0002_initial.cpython-311.pyc b/hotels/migrations/__pycache__/0002_initial.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..67bac23f9411f9db80f3c3114f0c011523057482 GIT binary patch literal 1008 zcmZuv%}>-o6rX->TNc#Dg!qvNLX3Oqf{BSFhJ=7%{J=!;(o5~`45dxC#c6jFJng}Q z2M^phd+{Uk$E-;Yn>m?y@>T*TPQIDlVu(!J*Wd5G*Xet|H(w_wEd=ZH((AyM5&F$Z zwX`ufSp#s0Fv3!dTnXNCEO!)F>8P$MAsKBTtb9ONB}!C%gT5#T{eWk*Tn$TGsG@NSG>$IIr#+O5E1cTSH_a7U>Pfc?5Z*%TBKJWVHIoO zsYOQRA!a0c<2j8!LM~QLNm(CVJ62SkEtBKw?xq4mZ@*RHWX&2i3d86oG>|0S-nSSE6s?P z_#FaaOQ<9mQ@M|6J0XejW@CyOp747fvpf&-x-kJ<_q=yqKjyi>YU9#a9g{thV3M>$ zl2JY)W~^Ym&Nrhfr`CE(Nf;#0$v)F@nQo6YG=wVZ|?sfdc4+w4MX}7(*J91{te+Qun3O=Y5boTZsAFeQb zdRYvne}4U%vilpQj?B5CFa WB)vrcn**!3I)BUqrb literal 0 HcmV?d00001 diff --git a/hotels/migrations/__pycache__/__init__.cpython-311.pyc b/hotels/migrations/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b25131051d9a5f6184017476086a08695a623a35 GIT binary patch literal 177 zcmZ3^%ge<81i4!R(?RrO5CH>>P{wCAAY(d13PUi1CZpdhBrG=?}Mt(_ZPJC`+USfJ`k$y>jX>vveM6g&tH#5B`u_QA;uUJ1mJ~J<~ rBtBlRpz;@oO>TZlX-=wL5i8J8khR79K;i>4BO~Jn1{hJq3={(Z4>~KW literal 0 HcmV?d00001 diff --git a/hotels/models.py b/hotels/models.py new file mode 100644 index 00000000..ac8453df --- /dev/null +++ b/hotels/models.py @@ -0,0 +1,23 @@ +from django.db import models +from users.models import User + +class Hotel(models.Model): + name = models.CharField(max_length=255, verbose_name="Hotel Name") + pms_type = models.CharField( + max_length=50, + choices=[('bnovo', 'Bnovo'), ('travelline', 'Travel Line')], + verbose_name="PMS Type" + ) + api_key = models.CharField(max_length=255, blank=True, null=True, verbose_name="API Key") + public_key = models.CharField(max_length=255, blank=True, null=True, verbose_name="Public Key") + created_at = models.DateTimeField(auto_now_add=True, verbose_name="Created At") + + def __str__(self): + return self.name + +class UserHotel(models.Model): + user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="User") + hotel = models.ForeignKey(Hotel, on_delete=models.CASCADE, verbose_name="Hotel") + + def __str__(self): + return f"{self.user.username} - {self.hotel.name}" \ No newline at end of file diff --git a/hotels/tests.py b/hotels/tests.py new file mode 100644 index 00000000..7ce503c2 --- /dev/null +++ b/hotels/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/hotels/urls.py b/hotels/urls.py new file mode 100644 index 00000000..e69de29b diff --git a/hotels/views.py b/hotels/views.py new file mode 100644 index 00000000..91ea44a2 --- /dev/null +++ b/hotels/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/manage.py b/manage.py new file mode 100755 index 00000000..850eae6b --- /dev/null +++ b/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'touchh.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/req.txt b/req.txt new file mode 100644 index 00000000..89b7714f --- /dev/null +++ b/req.txt @@ -0,0 +1,25 @@ +anyio==4.6.2.post1 +asgiref==3.8.1 +certifi==2024.8.30 +Django==5.1.4 +django-filter==24.3 +django-jazzmin==3.0.1 +django-jet==1.0.8 +et_xmlfile==2.0.0 +h11==0.14.0 +httpcore==1.0.7 +httpx==0.28.0 +idna==3.10 +numpy==2.1.3 +openpyxl==3.1.5 +pandas==2.2.3 +pillow==11.0.0 +python-dateutil==2.9.0.post0 +python-dotenv==1.0.1 +python-telegram-bot==21.8 +pytz==2024.2 +PyYAML==6.0.2 +six==1.17.0 +sniffio==1.3.1 +sqlparse==0.5.2 +tzdata==2024.2 diff --git a/touchh/__init__.py b/touchh/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/touchh/__pycache__/__init__.cpython-311.pyc b/touchh/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..59b5ca498f04dd1b3bbbbd95a5027bd463178f1a GIT binary patch literal 166 zcmZ3^%ge<81c93a(?RrO5CH>>P{wCAAY(d13PUi1CZpdhBrG=?}Mt(_ZPJC`+USfJ`k$y>jX>vvejEaxX%*!l^kJl@x{Ka9Do1ape dlWJGQ3N#61S1~`3_`uA_$oPQ)Miemv#Q?+&Cldew literal 0 HcmV?d00001 diff --git a/touchh/__pycache__/settings.cpython-311.pyc b/touchh/__pycache__/settings.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e0bf537f3ba70c7079e62cf19fde7209c9cda980 GIT binary patch literal 3183 zcmb7G&2!tv6$ih+DN3R(S+Z*=ZY9%-K+}$*3am_F*NDy=GpNoz+p z^O4&K0%1j`Ph_==jsGW>j*rFy{bX;3jEDI5WwTkfwuWU;+6Jz7b-boZ8{O{4gU+MZ z)=_5D($6;@XP$LemsX!Na`L*_SUNp>{>AI1?&-tT*YeqUbGa#Gd{*c&<2=?>Zu1F~ zd$z$m$!#*Z^~Y8u_vE=F%VnY@bSzsI)Z0qCVVSztHg)BYaaO^aogD3&O>1#t&^Ezs z(>(8B!t_((p=Od`Q!}w@kU-bKx{(Q4YeS2c zf{=<&WgRn4trYW|;q9V9XYX2OtxpCRro@cd^X}M~Rp$L5uw7bOo5?%P|4=pbBPI{z zm4Z*lRG&}eB11vP^I(C8S}JvCH;)-kPGVHPapOI=q+?dkJ}?PYslPdv>u&&2%%8V) zxrHko8#>0AUCf0l)74eO$_|~FxYbbst;``<<2D+hi77b16^3Gi%s4yZ%#;9Ub;wDB zRr6a9C*8cS#UOmxZCH;!LQ}_I0qRU^b*Ov2Z|#D9z_VRw>$3^v>mq)@U?j`xn!nH7b>VL#&~L9V=0EOW$PX7@N9t|rRboygnSH67V7PBk4#Z~!UD3CGj`A*^Ww zxNBlwX(_5~gW;8{q3PDkkM*>tw3Sx3Rl@Ct*}Sp;!^hgYAlV=0c;n!Uk9AP)wy>_$ z-}eyEyKB`N@zsPpiNQ57IxMVk*5$G!=yt4o!(dR~mWJRAVYZY8Kup_Ku!^j>P^sm2 zcWL*mo8CL8S^MsRqaH3LKm-X2&W&X)A7B;0kKqQRjdKHl;MyodMY;}{#k!R`lHul& z*PMfDt*$k!`1ptw8*(5qGCtzB*HI6_3hVY)!!|5_q^@<&b*0fXN$3PlJIEpvCQ$?S ziDW9Kiebujzlmjp^`YQUhuet6Pu(OXLus^0+-Pd2&;>-vI+<J#el|$VJX%Vkxkgz1#C$cTmv7xCam;^g;@U~47 z-eP&q#si7+T)xT)(wE#{NT9%N)pkgNEtM(s)41OK!vEr^9E5{Yf-xMqeLH=lqxO3)r$<6~EM9fG7L= z()b?ez~}LJ2HvR0KcH+fPkHWKQuE{Q6&2|@&mc&}Q(v$DJ^a^~e|!0#*wPQNrFXFh zKico3A7i;*c#x!$RZlMpijhPwaFzP~rStX@gJ^8VJD^6SmmDmFlQ1wMV3Vd&_j>U` zm`Zb=erl$lp1+FI11j(!IYxY;baW7j2Z962Ccb3C+lvfnD!q0|r67DD*`Hzhsrk1r z-lbLs0bdFfZQ=_!iVIX^>M|t`d|ogPJIww#^QUp9>N2+ycfC-K!7?>H-%DJ@r+bmB z*i(>Yu~f{R-u+ BA3Xp7 literal 0 HcmV?d00001 diff --git a/touchh/__pycache__/urls.cpython-311.pyc b/touchh/__pycache__/urls.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7db3fc6ce68ae091bfc348ccd38567f09ddc0a9a GIT binary patch literal 405 zcmZuryGjE=6utA&oe2aYeDp;YOlmnB!w`473Oh8i%4=sjjGzZYE#KYR=mJM zU&C_XTozmujuiYR7rXm=11HQSPp(og^8zj$nU{VT*3J0zN4Lw?FwI$+@I%qnE=Xr_ vs!K%>LUY)j{f#;7%>Ik20oL01c(U~{m>x`z-f8cH_9}um@wjb{*wCKe1QBVK literal 0 HcmV?d00001 diff --git a/touchh/__pycache__/wsgi.cpython-311.pyc b/touchh/__pycache__/wsgi.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..34ce4beec08bf128be04e0de17187130593864a1 GIT binary patch literal 686 zcmY*X&ubGw6n?XtHoCP@#P&RtUIMyn4*?Ys8d^g{Q%YKtTsG_O%kGBRnPq2^+MasQ zzrm}giuC9|l1fq7Q^1qAKyN)c+qe+l{CG3--hAKphWWa>YJs->@B85=0`R-olveq- zxQg`RGX&6sfCL63J)*tIjKu7j1dt5NO!%@?US9M;C0IH$0M7N88vz5*Jky)=@(6m% zfzgHf^2tx@ZMW5?zTks6qyv#rB}RS}(KHi7^p$N{ZAI}zDkMs(BBb+tk1_8(L+VND z(L@9zhL0GIk#`<{vg@Aoy{OHGo93~9_YUvd+mf@|Lh;< zqH>EfcR@zJzVm9k)7o>py9WpDPOIy_+1ojMy?b(ZUc4<)shEedUd^kns};CzZU~v* zo9nQBE#EFsGgI^ARpjG16Fj%{#Q+E1h^c&Kf$$q#6@soC&Y{FiIx54l$hMw7Y3KqJ zGB@$K7h>kj`Ab(Y*y-{0t>^O>ev#EQivBtv-|1;)5<+H1l~iU>O!t9Ur?-nXg{{f| teG0}$>ldv3fVIiGJ$bx+0nJNjPM|rhZA@w#7q!jH+UDs>(Xu-l{4Zb}$ov2R literal 0 HcmV?d00001 diff --git a/touchh/asgi.py b/touchh/asgi.py new file mode 100644 index 00000000..f8d90caa --- /dev/null +++ b/touchh/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for touchh project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.1/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'touchh.settings') + +application = get_asgi_application() diff --git a/touchh/settings.py b/touchh/settings.py new file mode 100644 index 00000000..0f8991a4 --- /dev/null +++ b/touchh/settings.py @@ -0,0 +1,151 @@ +""" +Django settings for touchh project. + +Generated by 'django-admin startproject' using Django 5.1.4. + +For more information on this file, see +https://docs.djangoproject.com/en/5.1/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/5.1/ref/settings/ +""" + +from pathlib import Path + +import os + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'django-insecure-l_8uu8#p*^zf)9zry80)6u+!+2g1a4tg!wx7@^!uw(+^axyh&h' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = ['0.0.0.0', '192.168.219.140', '127.0.0.1'] + + +# Application definition + +INSTALLED_APPS = [ + 'jazzmin', + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'bot', + 'hotels', + 'users', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'touchh.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'touchh.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/5.1/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR / 'db.sqlite3', + } +} + + +# Password validation +# https://docs.djangoproject.com/en/5.1/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/5.1/topics/i18n/ + +LANGUAGE_CODE = 'ru-RU' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/5.1/howto/static-files/ +STATIC_ROOT = BASE_DIR / 'staticfiles' + +STATIC_URL = '/static/' +STATICFILES_DIRS = [BASE_DIR / 'static'] + + +# Default primary key field type +# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + + +JAZZMIN_SETTINGS = { + "site_title": "TOUCHH admin", + "site_header": "My Administration", + "site_brand": "Touchh", + "welcome_sign": "Welcome to system adminitration center", + "show_sidebar": True, + "navigation_expanded": True, + "icons": { + "auth": "fas fa-users-cog", + "users": "fas fa-users", + "bot": "fas fa-cogs", + }, + "footer": { + "copyright": False, # Убирает надпись Copyright + "version": False, # Убирает информацию о версии Jazzmin + } +} diff --git a/touchh/urls.py b/touchh/urls.py new file mode 100644 index 00000000..7aff8672 --- /dev/null +++ b/touchh/urls.py @@ -0,0 +1,6 @@ +from django.contrib import admin +from django.urls import path, include + +urlpatterns = [ + path('admin/', admin.site.urls), +] \ No newline at end of file diff --git a/touchh/wsgi.py b/touchh/wsgi.py new file mode 100644 index 00000000..d5f0e3ee --- /dev/null +++ b/touchh/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for touchh project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.1/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'touchh.settings') + +application = get_wsgi_application() diff --git a/users/__init__.py b/users/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/users/__pycache__/__init__.cpython-311.pyc b/users/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..75d05496e0194cc1c6238a6c6f5a8bdf20cdbd11 GIT binary patch literal 165 zcmZ3^%ge<81bJHm(?RrO5CH>>P{wCAAY(d13PUi1CZpdhBrG=?}Mt(_ZPJC`+USfJ`k$y>jX>vw}ekoX0e0*kJW=VX!UP0wA4x8Nk gl+v73yCPPgK_IJ&`GLd-W=2NF4-7D(h#4pb0H{+Y*8l(j literal 0 HcmV?d00001 diff --git a/users/__pycache__/admin.cpython-311.pyc b/users/__pycache__/admin.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..64088bb0977ef7ac2feefc625e808c6d21c38a39 GIT binary patch literal 1225 zcma)5%}*0S6rb6Tc3WB~V8IV0z{RXl8V@9*hQtt~3DSec%U&ky&d@H|?c(g#1W!Hi z2XMoaM~va$FrFdlp_vnjCvGKh;^cd~lz?F3%+7D$iT5G-x-NcVt-bF$n49Yo~hRqHU#G#xx8mErVHOJt(V{*gEaTCJiQ~`ax#2B`z ztTt>~ZYb1HA_CEnZpeJD@?O(TP%vZ^2vzX1(1P2#EI<&6y^%uzwkAs`mrUh@p|WN@7A-Xhr z?sa8gc53vT+qA9Bi?~olPYO2?oVf|yfMGOa3=xTw_aLB68+>H7({MD4stQXn!Sd!Qeyvp%UfWA&C?U9-Nt6z^i z+`s8Nq$8c`*7UY7y|7fK6yEi&|Lxe$4>gcd7ea)ql9ck(QX#6~{4@|!$PWig&1&PB_@`@cm|dsE zqLL3Ba_Aw4svuRBdT1%AK5*!vM~*!@k`JpnA@#(~C^>QJd$X~VxaoNJ?aaP!X5af} zzL)$SjfNy>pI=?bFZ(3v9~^X=cdxTkfX-uyNJKWIvYeG=?0XDPS;;D*uNZ1p^++=k zQ6EXfOXa7EB>e%m+p=Ea^MTJ#l@ff%Z9OPIQ5L0i;59naGLKBGS~k;j_OeA8jD2O3 zP{W$f?adaC&RRRFj4@IvD-$W}Au{pgJz2#gQMJ^`Ln4a!sSWQ_72<>2ZCT%uINyJ8 zet`>g=3zD@K!S}>&w4?D6U-u(gh`|ked>X4!tJ(fSYRTZG3g^QqBPc zr2mnWjgbN1Z;-2kFc0_Yq+G1<=mb8B$fa$vw1hWV8h20h*!lzR*EHB5O{+z4{@C8=16b2K z38pSNv4QWuYsNCoROZEC>%s&)@d{*iFq!#uoCh>Ph^Fz7roqZpgF-)|Y4@wTfpNpA zZ)s|7YGz^Lwzlx)+|(jN3GmpBVt%$_QwVRmNDab{<6GD>-G&5VlM1@);3|W?<&hgE zJoJhH^I)#Chdg#$uRK^X(Yiig9{14VaZFcR?{1I9-i1#*m)I$IuwgVPWMNRPRtVUv zcYm(}r=7q^+p8S&)#uwGX&}8d+Uh?ClsM6Z)7S3|oo)xc1HLyBm|ZmWTkVJxJG;5o z>Ki!#I|Z;9!eR)E`RX$OiwtjGX@yTZ14B;yloKCzhE4)3g0Kj}BEI@0z!D={zE=Fq zv#FQiW_)ftKG%xR)n{Kt&urdnMb9{aL1$1gZHgbW?3eVw|t^CNinYadh$rGy(R8ucEmxI}JvdMXUo zG^Nz7X*5{cuUkq(J)&wUrTwbqCBBBg2NNX$s78Gx2ucd^I3DOdo$EGeQ|vP6DQH$S zDCpFtuIdv9L8%NBdxlkIsTRsGih55?2=#;1O|4>nqv?c*nTN!Vi3_oR1ReOJh4L0e zpgAaX;sH;$9E0#x2v?b}9S&p7WT~2xI-g1_T*Xt&lCTa>>>YZMke0((Pr!S(2)G9t zPk1fan|w#vA0s*i29>?=%cWnhw$5B`#uniEYoztr9k<&IEQr0IPsiAM0A@IYy^jX- z(HL&G6mr@ZDDUZhg{8o_peJ zCC|MW{PRTf=2y++%64+4m0W46Lr&uC*0EON?2Ah;jb>tTJF(bGEY@$fRoS~Jq;QmV zBf>b+0e*s%^h(|wgUzs6adk}m5pZiN!!y8xdjPU3_+p>HOP46`ZTx3KB-E4X+rTxq zcwT4M0gh$e`VCB5k!9JDE;bKejx^jnd^u9ME`DuwR7O!BZ8xvI5uV+H{yVZy#2X#0(Sz0G4tj&;S4c literal 0 HcmV?d00001 diff --git a/users/admin.py b/users/admin.py new file mode 100644 index 00000000..3d03faec --- /dev/null +++ b/users/admin.py @@ -0,0 +1,15 @@ +from django.contrib import admin +from .models import User, UserConfirmation + +@admin.register(User) +class UserAdmin(admin.ModelAdmin): + list_display = ('username', 'telegram_id', 'chat_id', 'role', 'confirmed') + search_fields = ('username', 'telegram_id', 'chat_id') + list_filter = ('role', 'confirmed') + ordering = ('-id',) + +@admin.register(UserConfirmation) +class UserConfirmationAdmin(admin.ModelAdmin): + list_display = ('user', 'confirmation_code', 'created_at') + search_fields = ('user__username', 'confirmation_code') + list_filter = ('created_at',) diff --git a/users/apps.py b/users/apps.py new file mode 100644 index 00000000..72b14010 --- /dev/null +++ b/users/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class UsersConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'users' diff --git a/users/migrations/0001_initial.py b/users/migrations/0001_initial.py new file mode 100644 index 00000000..67cccc82 --- /dev/null +++ b/users/migrations/0001_initial.py @@ -0,0 +1,59 @@ +# Generated by Django 5.1.4 on 2024-12-05 23:39 + +import django.contrib.auth.models +import django.contrib.auth.validators +import django.db.models.deletion +import django.utils.timezone +import uuid +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + ] + + operations = [ + migrations.CreateModel( + name='User', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('password', models.CharField(max_length=128, verbose_name='password')), + ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), + ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), + ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')), + ('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')), + ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')), + ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')), + ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), + ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), + ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), + ('telegram_id', models.BigIntegerField(blank=True, null=True, unique=True, verbose_name='Telegram ID')), + ('chat_id', models.BigIntegerField(blank=True, null=True, unique=True, verbose_name='Chat ID')), + ('role', models.CharField(choices=[('admin', 'Administrator'), ('hotel_user', 'Hotel User')], default='hotel_user', max_length=20, verbose_name='Role')), + ('confirmed', models.BooleanField(default=False, verbose_name='Confirmed')), + ('groups', models.ManyToManyField(blank=True, related_name='custom_user_set', to='auth.group')), + ('user_permissions', models.ManyToManyField(blank=True, related_name='custom_user_set', to='auth.permission')), + ], + options={ + 'verbose_name': 'user', + 'verbose_name_plural': 'users', + 'abstract': False, + }, + managers=[ + ('objects', django.contrib.auth.models.UserManager()), + ], + ), + migrations.CreateModel( + name='UserConfirmation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('confirmation_code', models.UUIDField(default=uuid.uuid4, verbose_name='Confirmation Code')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='users.user', verbose_name='User')), + ], + ), + ] diff --git a/users/migrations/__init__.py b/users/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/users/migrations/__pycache__/0001_initial.cpython-311.pyc b/users/migrations/__pycache__/0001_initial.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..12dca8e9185f62b8fe1941a489428f43da8da157 GIT binary patch literal 4580 zcmb7IOKcm*8D1{m)Wf9wkR?&%I+hg6j!DUu)Ht@2=waE4V<&YaHD&^AR-7TZ)N)tZ zT}lxV7e4gRTXQH{9fHEWxG2nn4?XCRgN{B9iv>!|DL_xYF^z#1ITZb8mP^YP3$&}{ zKd*28|DXT01O2J5FDAhA$1C@WzwH-!5l#id&D(0XHA&t@pipF5uSBaXsyg z0?0gu;`PK4+`wy6kE0W+51mA(kPr8k`@H>S@RIwKk9oaEaj$o{eGG#qor$6k4b%r8 zgGHWntODAdeod+mZ$y%Sy!y;(nZ#G{j($H@+cdDMr_*DoB2khi)bFLps@IPzsI zWzkeoMAPUJx?G<*!grRV4_jrfi=IE@s8fgZd>dVTfT?Ctg0qP8EJZUO3IfMQ^|uvEXgpX0^Y%9M*0xjZ00QqsYTU>1L;V5Kby&3 z$X?9KlA&w6ndiS_Rt?d9Y?_8CSFmL%MQoWYWKC9wOct;-whg{Pifx!y+vqP{UW@U* z#7;8lH(8-_cXIDUxp&xFjdwYW2607Ewdel^Y^{&?B?Tc9q|*p1r{qeTGpe2T?DH?nDn`3q$558eLmkS#swC z)vAgh9DvTy*s@__D8IMi`yrwY8gUcR&}n#a{*%S|r5iM6KrFd;@jnYcg5JVUH?xel zm4yu7Hq7ZOZ_j4k@La)yYyK90>eM- z{C(d)@bG3UBt+k7`Nb2Vhaa|LLNxvBm=j4g6NBF;PLjd%-)uXB=l288#z;;kx=9AD z#-Qa4S|n~a6C-5w;@-M5dU5~wvvm>e*W@412FYj$T>C5|L2dm^$MAEpC z#!ecOc%hj{lQT1qPB~|0_Sag1@R3guq1h4_{Ls9y=>LJ!7o5UOV#$A4R*BrQ$aNbQ z=EW7ZW8HtBH5>i{Yixhb4_j^jLV!0n-R554pKNk7@DH~E8MeRTu2llC&+_Z6c@Vf6 zgeG+>2ne9S11QWSR)YLkS$3@KQ*>aF`e<_!g6`%=@`b(jPD@0);I=*_PX2#T1cd9)%ofW`F&= z&z&jMuaJ}Fg+wB3-l9ci1ycbbV|lDxFH>?AMk zpEy_|KVKuLLXvtTsXIxX#0`iYGBmk&${Cs@m+z2|HpwLov0R*?|-Nt#iVeH=A!}n#nV*aNuNrOJJl| z7#P`G{`Rhu%sR=rza6OuAKcJa%GH6 z%snbN6Lb6acQx|qCYjJ06Ph!jk$B}$x*VJ!t6z|`(nu>#S|RZbZq4(|n&+Rc|K+|j zd&8N%>&&i`&x&OGYclkpG4#M0;-`xS;dH?W(-O!FMq2Nk8wfr8fc=?@R|+O$bl9z# znRdy{@GqMCZvgWy;ApBF;N|^_4z<_OM#kNi>D0B8?Im7SGhR_O?=!a1&NluH;AP*f zQC~3axQZLl`zdnG{i3{UmSE_EpYrf`mQdt0F?U#KM>P{wCAAY(d13PUi1CZpdhBrG=?}Mt(_ZPJC`+USfJ`k$y>jX>vw}ekoX0Zf1H>Vo7FxUa@|Bd}dx| rNqoFsLFF$Fo80`A(wtPgB37W8AX|(1fy4)9Mn=XD3^1aI87Kw-+|?^i literal 0 HcmV?d00001 diff --git a/users/models.py b/users/models.py new file mode 100644 index 00000000..4760f274 --- /dev/null +++ b/users/models.py @@ -0,0 +1,51 @@ +from django.contrib.auth.models import AbstractUser +from django.db import models +import uuid + +class User(AbstractUser): + TELEGRAM_ROLES = [ + ('admin', 'Administrator'), + ('hotel_user', 'Hotel User'), + ] + + telegram_id = models.BigIntegerField( + unique=True, + null=True, + blank=True, + verbose_name="Telegram ID" + ) + chat_id = models.BigIntegerField( + unique=True, + null=True, + blank=True, + verbose_name="Chat ID" + ) + role = models.CharField( + max_length=20, + choices=TELEGRAM_ROLES, + default='hotel_user', + verbose_name="Role" + ) + confirmed = models.BooleanField(default=False, verbose_name="Confirmed") + + groups = models.ManyToManyField( + 'auth.Group', + related_name='custom_user_set', # Уникальное имя для обратной связи + blank=True + ) + user_permissions = models.ManyToManyField( + 'auth.Permission', + related_name='custom_user_set', # Уникальное имя для обратной связи + blank=True + ) + + def __str__(self): + return self.username or f"Telegram User {self.telegram_id}" + +class UserConfirmation(models.Model): + user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="User") + confirmation_code = models.UUIDField(default=uuid.uuid4, verbose_name="Confirmation Code") + created_at = models.DateTimeField(auto_now_add=True, verbose_name="Created At") + + def __str__(self): + return f"Confirmation for {self.user.username} - {self.confirmation_code}" \ No newline at end of file diff --git a/users/tests.py b/users/tests.py new file mode 100644 index 00000000..7ce503c2 --- /dev/null +++ b/users/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/users/urls.py b/users/urls.py new file mode 100644 index 00000000..e69de29b diff --git a/users/views.py b/users/views.py new file mode 100644 index 00000000..91ea44a2 --- /dev/null +++ b/users/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here.