From 121f5747dd7b59981d7443205284b8fc19e2cd28 Mon Sep 17 00:00:00 2001 From: ebo_shit <79515659+ebosh-alt@users.noreply.github.com> Date: Wed, 8 Feb 2023 18:01:53 +0300 Subject: [PATCH] add new payment --- .idea/design_skillbot.iml | 1 + .idea/jsLibraryMappings.xml | 6 ++ Payments.py | 71 +++++++++++++++++++++++ Reminders.py | 65 ++++++++++++++------- Users.py | 5 +- __pycache__/Enum_classes.cpython-311.pyc | Bin 1183 -> 1183 bytes __pycache__/Openai.cpython-311.pyc | Bin 1449 -> 1449 bytes __pycache__/Payments.cpython-311.pyc | Bin 0 -> 3775 bytes __pycache__/Reminders.cpython-311.pyc | Bin 3526 -> 4610 bytes __pycache__/SQLite.cpython-311.pyc | Bin 10014 -> 10014 bytes __pycache__/Users.cpython-311.pyc | Bin 2735 -> 2847 bytes __pycache__/config.cpython-311.pyc | Bin 1805 -> 2345 bytes __pycache__/functions.cpython-311.pyc | Bin 876 -> 4222 bytes __pycache__/keyboards.cpython-311.pyc | Bin 356 -> 353 bytes __pycache__/texts.cpython-311.pyc | Bin 122820 -> 125045 bytes config.py | 26 +++++++-- db.db | Bin 8192 -> 8192 bytes db.db-shm | Bin 0 -> 32768 bytes db.db-wal | Bin 0 -> 407912 bytes functions.py | 64 ++++++++++++++++++++ keyboards.py | 5 -- main.py | 42 ++++++++++++-- templates/index.html | 15 +++++ templates/index.js | 10 ++++ templates/pay.html | 25 ++++++++ texts.py | 33 ++++++++--- 26 files changed, 324 insertions(+), 44 deletions(-) create mode 100644 .idea/jsLibraryMappings.xml create mode 100644 Payments.py create mode 100644 __pycache__/Payments.cpython-311.pyc create mode 100644 db.db-shm create mode 100644 db.db-wal create mode 100644 templates/index.html create mode 100644 templates/index.js create mode 100644 templates/pay.html diff --git a/.idea/design_skillbot.iml b/.idea/design_skillbot.iml index d0876a7..69a52fe 100644 --- a/.idea/design_skillbot.iml +++ b/.idea/design_skillbot.iml @@ -4,5 +4,6 @@ + \ No newline at end of file diff --git a/.idea/jsLibraryMappings.xml b/.idea/jsLibraryMappings.xml new file mode 100644 index 0000000..4260f9d --- /dev/null +++ b/.idea/jsLibraryMappings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Payments.py b/Payments.py new file mode 100644 index 0000000..53beed1 --- /dev/null +++ b/Payments.py @@ -0,0 +1,71 @@ +import time +from asyncio import run +from multiprocessing import Process + +import schedule as schedule +from yookassa import Payment + +import functions +import texts +from Enum_classes import Flags +from config import users, bot, WEBHOOK_HOST + + +class Checking: + def __init__(self) -> None: + self.p0 = Process() + + def start_process(self, func, arg=None): + if arg is not None: + self.p0 = Process(target=func, args=(arg,)) + else: + self.p0 = Process(target=func) + self.p0.start() + + def stop_process(self): + self.p0.terminate() + + def check_pay(self, key: str): + try: + res = Payment.find_one(key) + return True + except: + return False + + async def work(self): + list_user_id: list = users.get_keys() + + for user_id in list_user_id: + try: + user = users.get(user_id) + + if not user.payment and user.flag == Flags.Payment: + if self.check_pay(user.key_payment): + await bot.send_message(chat_id=user_id, + text=texts.text_after_pay, + reply_markup=functions.create_keyboard( + name_buttons=["Начать историю"] + ), + parse_mode="Markdown", + disable_web_page_preview=True, + ) + user.payment = True + user.flag = Flags.NONE + users.update_info(user) + + except: + pass + + def start_schedule(self): + while True: + schedule.run_pending() + run(self.work()) + time.sleep(1) + + + + +if __name__ == "__main__": + checking = Checking() + checking.check_pay("2b75bee3-000f-5000-8000-136a5ca22d9b") + checking.start_process(func=checking.start_schedule) diff --git a/Reminders.py b/Reminders.py index b238d66..f306da5 100644 --- a/Reminders.py +++ b/Reminders.py @@ -3,13 +3,17 @@ from datetime import datetime from multiprocessing import Process +import schedule + +import functions import texts -from config import users, time_reminder_2, bot, time_reminder_1 +from config import users, time_reminder_2, bot, time_reminder_1, WEBHOOK_HOST, link_to_site class Reminders: def __init__(self) -> None: self.p0 = Process() + schedule.every().day.at("17:52").do(self.send_mes_1, mes=texts.text_for_reminder_3) def start_process(self, func, arg=None): if arg is not None: @@ -21,34 +25,53 @@ def start_process(self, func, arg=None): def stop_process(self): self.p0.terminate() + async def send_mes_1(self, mes: str): + list_user_id: list = users.get_keys() + for user_id in list_user_id: + user = users.get(user_id) + print(user_id) + # if not user.payment: + # await bot.send_message(chat_id=user_id, + # text=mes, + # reply_markup=functions.inl_create_keyboard(buttons= + # [["Оплатить 2990 руб.", + # WEBHOOK_HOST + f"/pay?user_id={user_id}&price=2990.00"]])) + @staticmethod async def work(): list_user_id = users.get_keys() now_time = datetime.now() - + for user_id in list_user_id: - try: - user = users.get(user_id) - if not user.payment and user.count_reminder != 2: - time_transition_payment = datetime.utcfromtimestamp(user.time_transition_payment) - if (now_time - time_transition_payment) > time_reminder_1 and user.count_reminder == 0: - await bot.send_message(chat_id=user_id, - text=texts.text_for_reminder_1, - parse_mode="Markdwon") - user.count_reminder += 1 - - elif (now_time - time_transition_payment) > time_reminder_2 and user.count_reminder == 1: - await bot.send_message(chat_id=user_id, - text=texts.text_for_reminder_2, - parse_mode="Markdown") - user.count_reminder += 1 - - users.update_info(user) - except: - pass + + user = users.get(user_id) + if not user.payment and user.count_reminder != 1: + time_transition_payment = datetime.utcfromtimestamp(user.time_transition_payment) + if (now_time - time_transition_payment) > time_reminder_1 and user.count_reminder == 0: + await bot.send_message(chat_id=user_id, + text=texts.text_for_reminder, + reply_markup=functions.inl_create_keyboard( + buttons=[["Оплатить 2990 руб.", + WEBHOOK_HOST + f"/pay?user_id={user_id}&price=2990.00"], + ["Узнать подробнее", link_to_site]]), + parse_mode="Markdown", + disable_web_page_preview=True) + user.count_reminder += 1 + users.update_info(user) + + if now_time.time().strftime("%H:%M") == "17:59": + + if not user.payment: + await bot.send_message(chat_id=user_id, + text=texts.text_for_reminder_3, + reply_markup=functions.inl_create_keyboard(buttons= + [["Оплатить 2990 руб.", + WEBHOOK_HOST + f"/pay?user_id={user_id}&price=2990.00"]])) + def start_schedule(self): while True: + schedule.run_pending() run(self.work()) time.sleep(10) diff --git a/Users.py b/Users.py index 36df6e4..b0880a4 100644 --- a/Users.py +++ b/Users.py @@ -4,13 +4,14 @@ class User: def __init__(self, key: int = None, flag: Flags = Flags.NONE, payment: bool = False, username: str = None, - time_transition_payment: int = None, count_reminder: int = 0) -> None: + time_transition_payment: int = None, count_reminder: int = 0, key_payment: str = None) -> None: self.key: int = key self.flag: Flags = flag self.payment: bool = payment self.username: str = username self.time_transition_payment: int = time_transition_payment self.count_reminder: int = count_reminder + self.key_payment = key_payment def get_tuple(self) -> tuple: return (self.key, @@ -19,6 +20,7 @@ def get_tuple(self) -> tuple: self.username, self.time_transition_payment, self.count_reminder, + self.key_payment, ) @@ -39,6 +41,7 @@ def get(self, id: int) -> User | bool: username=obj_tuple[3], time_transition_payment=obj_tuple[4], count_reminder=obj_tuple[5], + key_payment=obj_tuple[6], ) return obj return False diff --git a/__pycache__/Enum_classes.cpython-311.pyc b/__pycache__/Enum_classes.cpython-311.pyc index e7ac775d34d144f3286fb723885582d9169bf443..0c1a2259f8bc95ee8e0571be7be2f6c61c0678fc 100644 GIT binary patch delta 20 acmbQwIiHhzIWI340}u$!d$^H%3JU-+>IDn{ delta 20 acmbQwIiHhzIWI340}wE`-`mJNg#`dG=mg^c diff --git a/__pycache__/Openai.cpython-311.pyc b/__pycache__/Openai.cpython-311.pyc index 41d59dce41683e8a4b27561452c8d78697d77f87..af935e88bd39ffe1b21041c07792ed672eacf218 100644 GIT binary patch delta 27 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 JCk(Na^M4iyApigX delta 1774 zcmcIk-A^1<6u+@shX9K^?2B> zwd5R+3N*nJJG>674cz*aQf+muj@^`^60y}uZRN)yPGmh?_d@322)=!Nc<&7W+#ohd zaTZDOmTU=2VoIn)0n_8Bdsx3P)mj4^rygLDY)4vFj8$V< zydGSJhy5XZsW*be5PTI{hkBCZrl||8diK58#6{R|;#p2*acP)~F-N-6NmW$gtEUy$ zrVwQsUK+3+46vO>*iVwdHLzG9uE&6L>^lX3@ge;8UT1fM@9@`tVY=Mg^v%35i4vbI zE{BN``ZdeS!%eRolkxkN>SOoi?vN$i5!d1HhQO{V@z#V~>+JJ=Ky!IOv6 zG-u5g3x?nYGZSgo%vzr4+V8nuXgW&E{<{c)${ILA$`7gPqilL?dWkoGsGaoO;-p-MDWC3GaNw`obMgY&D&(5KVc~ zhvkdg(dO0XK6!gH8ZSrV%dc)ln^yZPL}d%%OAA9=7X~U4uMcv&1o5Gd6~Z?Ra{mbf zq@kr0OO#`Y&(3eg&Q+Iy-!-qyrSEGjnq-Za1sqL8CK zHBZ(!ynNWFVqM!hsBIjoa>T_7?bD>dlB(Ww!4O79ckuc%M2c2vF95U}7FlwpY*d!+rqzfF7te)~|oihRJ}oEd<{!>7V?(y0nL4gvO6-RU<;AX4F@5;PUSt^nJm zt5wDsLDDPaBvgH(J5M&vd^%e&O@pH?z<`N*p1rGeWiVMUkSP|%vg7`c`4dFpP9;=9 z@S}YJPbmk(QH7EaX(|Fl8*85>`wFtEP%Iw$|D2WZcC(e7J5|9@VhR z)N>+sFFQt^SV*C`hem{vQ?3bfAw8Q}m@=pH6@{4j0-4Tgb`p*vLkTk8p$~-{4Mnwx z(#qaGMk%x*3~s2jQEXO;huPyAHN=>Ua|;4RX^)r@y6KwO(Ozz9EjhNdBb)r&fiPJC z@VBT;^JJKQ7q2%I(Os}`$*Czs;QB1Vu+(DM$pjK$CJSOji9t(Jv*H6oCw(Ke`O7|I z%NMP=RiD3xRNYTP^s96+5o8_}IbWEaG|5rMHxLOiMGOE)$U$brdP0XBk)_RBxtgTO zZ8gMTwU4V;CRd+2x!TO;xGuLRxo7!Ozpcm8ww{>TkH9@`Ff`e}+6A0dcnAF_8!C!eg^t_uMti|7_4>~f-3QuKzjsBtZRYn%W%M}Pw&v-ac5SH~ZduPfyh^bY)KKyus(?h`y7NZ~ZjtGzTZ-yUQ_tXq7Oq#vq9Q8YUZUzK4 dM+adWY`gm#2}20h&_UR&3vYvY_dk2QlwV@J^@;!h delta 1007 zcmZ{i-Afcv6u|GD+4*#L)&1yW{Vda5Q$x|9$cU_<9)#N5N~ld{W@E`z?(9~`h7mqU zFDW<3=)ou|rJ_Hex9CBLU>{`(`U8BKWqs5BKdr!G=#yECGZ@wM;mfyU?5h6eFsZ=1H4uI zp+%8@hYC`LuX>Gl$X9E!YKpKrn1h>Va(iu(vIxvvJkrXd{D<7EV&HBsugHgkUX5B8 z@rY_fSe$nS&UMFNudL(?(-RKc2l^^uaS$wuz>owKP~4~dWuRr&lQpH^BY>r0AyynA z)&_(qSy>_1yLyD>`uPjKyqw-XDJ*n?;%1s*PZPT$w{KfU!*nB~h4$=yP{YcVa`_XLz(SX1r`CUGOS`(rf zaSU+)v3(obaEd@DZXWOm9{$BRGZ<9j3zkPfEZMKFytpIOUE%v|WwsjfETbaDc06Yn?TjZc4M*;XFyagf%O83b<>#C zm!>rP(xjL4sZCSgs{f)7VoW6aWMa~1lD_q+qjXbi&&-^2zB%7Hb0#w{4PVSXpY?hj zz;bqQwg^dV&w(tOKhDqZuY30G6r>;x_3ud5qyR{R7-T}mJ;UpUdz;xaej)()idR$E z7EA%l78yg+e+(;TkVtnW&j!t`9a`8{*upxXm32ZJ(!K@n6|4)|**4h9wj(EURd8YU zI&`pZ=wxp!A@j!$`KZelx~`P>z&7OJZps{-*D3p#E%N-EM*v970B^gvN<@9(a5xeg z?2il%$717iPm<-0^009XLTNY<2q%*%U$8Ig3k`&P!C=G}>JR&K>0*AxpUM9s0u{2) ze=#IQq^~k5jwx?Vp<*##-5Z^V#~*ML@tN7b zC=r{TkSH9BB@)e$3=;9_*^9_U*5m1i61|$qt#EvvD`j{jQ8L0kNY~Pcmy~NId>sbA zf<&zqv~Yn(Tqc*wi_cVX-EF*m{=L%UnMTi7+&1*&c^ zpDX8^`I^BiP^Szl(5HqF_DK3g`FXkOsFAK?(j_SCOpBo0q3b|(0!&B1RPC$*`!TQ^ M4uQQni&5O}Z@u*8&Hw-a delta 388 zcmZ1})XS&7oR^o20SJyfy_YD9Fh(d2$?63i~bQ%)Am!w#i4B+&4=wb1^Y#N=?4Nx@B??o2n?A ze?e-VqvtK2lGKWl__X|@_=3dB$(HQ?T>3!!LEb3Vn>>kqtB}eKG3gJy>>NxV7=T0r z%LjqUF&qy14}=vjFbI5LVH9;_yucv%fRn#NYy#g!PWdaG@(pYsSQrEYONut*nZ F7yzl}SCIe! diff --git a/__pycache__/functions.cpython-311.pyc b/__pycache__/functions.cpython-311.pyc index a4a34748af8267dc148d1c571b3d5a0a5d59a822..2457b8fa505bcdd269c315bb7bb499a46d3c0ac9 100644 GIT binary patch literal 4222 zcmd5<-)|E~9-sZ;^^di^4o-k1Z7v+#6}J#*LJEWsMBpg7ru53s5>c#;XA?HD*Y50^ z;K-4DQXc|}N~C*er0Yq3xZ|kcfs?3I>F$B+U$91dhcyyXrRpAdGlG*4PxqbmkJxUi zw(6a9yF1_c&U|OS^PTU^=R3214ut{;o`3%7o5W^6Lf^1L{gG#kR$86GQ8uV@h*ndezG*~}wNh7`aZw>X6EK&n2i zC9rbS88^kEPgsK(M?F?9qnW^j#x*r-=`-2nnRGT23L5u`YD7yOV ziokaVDiZ44THexEi3a+l3Ig&J1r+adMhb6NHltwFk$>jMgSI&M3{)cOhheI-N;K97 z>KTmObsT{;XkACPc38M8-U9iZ#<~onB`(hun{_b#?sE(1of?nO5)VLx_ZDcr(^z2+ z8S-}YCNjkZ{+e(REdXFIA`V`Qtx4_4^VrkcZ%Jt0V_5osvaQ(gPThW%w|b)}Hp}Wf z_O_ux#J)WGJ;MG!2ze0)Mxh~=0VCpZ^kHDhljrju>|KP~MF>Dk{E7^o3Rd~=@t>F% z<{BO@*28Dr5I4`aVUt67;fKr(uo^nGxOrfYrKK`SK$N*hH?VeX;EI(>QjRQovewM* z0}#D@fZjCLjoC$+$p$hifmpNH`R%TA=1Z>sCHLAQ|Jtr63Y)NRvIqESpN!_C2bQC-Ns{bW#U5l=zO7bp8 z-c>m6+OVUTxc9d0A1(Pu9sj7?>w)mUv_W}g?M!iZN!jZtdmkwWA1Vh+${|NN^hi1S zP&xWwdr3LrC?^Uh%h4UHIXk+e`V~$tpZ@J+InY@+Rt|MBGq<>8nJfF`<&Rc}t}k2< zFAK{;S@bR+DTzIWV~?9h0)3+Ih`^@Ebw=ZJl_*jJX7n}=^4zJ6roh%NS* zeXv5m>)I#W7Y}&<${q0jeOuQ!FMP#|Z}W5MR)-b%iPf&ZN=@MB}C0px!Lb* zit9jAYR6)|3potpU69Ni5CEIf=_otD7`m4)4IOuej@##_Y=hW}SyD_#F=1~6!-Zd! zw`_+))5A_qPheRt`$9K^H-e9Y9Zs;nIBy3BOTj@WIQUfH{ekBQNM)T!$kS0c`SIlH zFKlrud}TRWc#kl=Q}0Gwg<}^t!9qMFp|2V)v;GaCE3qVatH{OYMZ+ik5S!7 z#@jJD0qxl!W~6!mGEBz4IQFIYFO&Bt?bGLN>~Z%jUpbUBgN?@9MQy6?9mBc;fQ6Bz-FhQff+5cCG}ZwUpJ z@9q8N)d%X|a&}~*6q#@$6F)`A2Orvz%caO=Cvv$>%?r4Oe`l!h#p5YeH{x;14-cP; zbx^OWr`c~pHJS?3=DylxC6`XmtEQ>CKP7}+JZL~oB-q~!`wI)08o1wLahVFHMckhS z_X)&_MwZFPIJG9vV{#PZPcBMLEJ=;e zPOVJJPb^9)5&@dbGMR^~vHmm25PO4pzB#;aAFhj8$kodsN$jEquLGl7B`oPA)D6&B10|Ss+5qd?} U4a|ZOljQ_BCd&wLvVzSA0Fhx)w*UYD diff --git a/__pycache__/keyboards.cpython-311.pyc b/__pycache__/keyboards.cpython-311.pyc index ed21d3523b0b2aa73f8818e4082272745dfa5e18..8229b21d56778353ad3e03aa0d740ef24213418c 100644 GIT binary patch delta 42 xcmaFD^pJ^fIWI340}$Mw|2VmiVItoT#^TBBj2euZlMNW9m>)=FPYz%d0RR)U3@HEr delta 61 zcmaFJ^n{6TIWI340}vc~eJ8nxaU$Oj#^A~9j2etOlMNW9q(1O5NaiqJkjMrh22ltq IVh5@R06OXsK>z>% diff --git a/__pycache__/texts.cpython-311.pyc b/__pycache__/texts.cpython-311.pyc index 58448e25dafe9c6e15442a1b01f82726cb834842..9aed039638dbeee427cd703a329e231cbfd70388 100644 GIT binary patch delta 2496 zcmZuzTTEP46ulSdBa?vB(itpBdm2il3B|FGG&DXxHEI)UVq$8j722SEg-1he>%3HI zz=GVG(I!YVF-HC93@~MwVP-z;ugSh2{P1I1{qRfS!ygijYwbHT@@NaaGv}VO_u6Z% zy-)8KxBV^K>b|e7^;!6HH}l)OtABi6_jpy!_Eg*N+xCy!Z(Sd^yNB?+f#+2`Kg9C` zJi~ZiJ889DpYd;Rt*zQs;~WdTv{kZh+>IpsKiYwrses?EPP$QNI@lie`D9WG#vLPC$l!>%k2EpP+R7i0$S zKIKw71L3uCqc}V74&!vxU`NUwas9&xi}X>1D7a&8%o*Ok_q`4yQ~3HB7i9stz4wfU zW$ay(T$1Ktd`uIE^G~p4k8>>4+F`)N zZJgGs^X?~z>m6`X_4UnC#Q7Xb8kUTgo^=vQT#C-Qrae`1#|bqyH5=?mgMhTmnL`G6 zGe{c8z7d0s;|+mR%;b|V05>NY;vOOO_egG0nI|(0psy*I~XSHS#FdR^(!YScy*L@)KC;S>E8TbRemom;^YE(OhUhy zq(N&LKaHVGLQz!-cF}sHj)&pn2Uzg3TDoq6X$W82O(N7J6DiPK-%!6q1M z6Wb*kz;ttbsc~+p(XRR-JlI`rS@Lx$ZB7AtS4Idu5=(M~F>Uc3VaA~ZScsHElTb?sAB zr@#O*Z`_;6Gy^WzqI>MF0z}%*mAkQyg?yrixly3fK^E5(H%_y)h5J%>I=b^8id# zEaN=ATJQY(i!TgXHE~qwWmD!$*mV-Xd+6(&SF27&#Mk<10uKT$%5I9Wr`5}{h{9F$|?5dIgYb3Jz%|k+2A# z-Sl7pESRB9?hy&L%`2JSFfuRnzu$ZQ{FzJPf&Q-k!ONE~^$k=?;sv3MvscM=$}0+$ zFbh!n|fvx$zNHAWjj5u;F>@>a2n}cw?3?OrKPSm-Yi~qa%(H zAq5~xUVT!zaZy@_89eY5{-d&K7$06UjF+cwe^>r}tu2!H^=G?x=Z=A%p@FWmm-@Q; zdM@-{?C$BCJ9Xcl_Mcp;-}I*I@S_%wJZkaiqZSjji}nfM$IuWzR{v1q?4sSWZ|km* zSpH>yb>lN)1($u+&Nu8x-EvKJ;MFRzb}akmep6`2^?h*!{}1c|x{Uw; delta 470 zcmX|+&nt9M7{||4?xMn>}I3hrRP#k=SMv~-_P?o@1Wck72mPf%LuNnou|o_ z=WSnu>s2|6zABzk5?#)8R7Sk6e=admH^`(8S*gJ}*qNic2zA?XO*{l+e$E)|NnNgj ziN}r^Z+Em+lvMA~i?+kNJ0k7aZ~#TP{%Vk`GR+|;Q&N*UhddPE5^kWt@iMvGKu7_u zxI@HoCRT0vTbwqnS7K=sF2KyphD;iYQ9|GlTWt9U**4~~4(>*bgj6FRrVWBO1*B{6Nd>i=r5`IJ+-RqwZ6Bn&|N#R_#R{eLU+-Tg=KsFA z=)DTXSs%1|h*;m#ApbqZ)LAe-FRKEnPAyitLKV1h~#$)u1<8tHr>gG{o>A&-ybQ$Qg_ z6jMToQpzZ&f=^UZMKv|lQb#=vG}1&fVOnUVjdnWd7$7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUg WfC36Apnw7jD4>7>3Mla21nvQoT{VIL literal 0 HcmV?d00001 diff --git a/db.db-wal b/db.db-wal new file mode 100644 index 0000000000000000000000000000000000000000..e4c439efdcd6895cd0de9545016fb9303cbc326b GIT binary patch literal 407912 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 str: + payment = Payment.create({ + "amount": { + "value": price, + "currency": "RUB" + }, + "confirmation": { + "type": "embedded" + }, + "capture": True, + "description": user_id + }) + return payment.confirmation.confirmation_token + + + + + +def render_html(pay_token: str) -> str: + with open("./templates/index.html", "r", encoding='utf-8') as inf: + txt = inf.read() + soup = BeautifulSoup(txt, 'html.parser') + with open("./templates/index.js", "r", encoding='utf-8') as inf: + txt = inf.read() + new_soup = BeautifulSoup(txt, 'html.parser').prettify().split(" ") + new_soup[15] = f"'{pay_token}'," + txt = "" + new_soup = BeautifulSoup(txt, 'html.parser') + soup.body.append(new_soup) + return soup.prettify() def create_keyboard(name_buttons: list, ) -> types.ReplyKeyboardMarkup: @@ -10,3 +50,27 @@ def create_keyboard(name_buttons: list, ) -> types.ReplyKeyboardMarkup: ) keyboard.add(*array) return keyboard + + +def inl_create_keyboard(buttons: list[list], ): + keyboard = types.InlineKeyboardMarkup(row_width=len(buttons), resize_keyboard=True) + array = [] + for button in buttons: + if len(button) == 1: + array.append( + types.InlineKeyboardButton(text=button[0]) + ) + if len(button) == 2: + array.append( + types.InlineKeyboardButton(text=button[0], url=button[1]) + ) + if len(button) == 3: + array.append( + types.InlineKeyboardButton(text=button[0], url=button[1], callback_data="pay") + ) + keyboard.add(*array) + return keyboard + + +if __name__ == "__main__": + render_html(create_pay("55")) diff --git a/keyboards.py b/keyboards.py index 83d8f30..c04895e 100644 --- a/keyboards.py +++ b/keyboards.py @@ -1,10 +1,5 @@ from aiogram import types -# start_keyboard = types.ReplyKeyboardMarkup(row_width=3).add( -# types.KeyboardButton(text='Структура курса'), -# types.KeyboardButton(text='Сюжет курса'), -# types.KeyboardButton(text='Хочу начать'), -# ) name_buttons_by_start = ['Структура курса', 'Сюжет курса', 'Хочу начать'] diff --git a/main.py b/main.py index 330d8ad..12540a5 100644 --- a/main.py +++ b/main.py @@ -1,7 +1,10 @@ +from flask import Flask, request from aiogram import types import time +from multiprocessing import Process from Enum_classes import Flags +from Payments import Checking from Reminders import Reminders from Users import User from config import * @@ -20,8 +23,8 @@ async def start(message: types.Message): users.add(user) user = users.get(user_id) user.username = message.from_user.first_name - user.payment = False - # print(texts.start_text.format(username=user.username)) + + user.flag = Flags.NONE await bot.send_message(chat_id=user_id, text=texts.start_text.format(username=user.username), reply_markup=functions.create_keyboard(name_buttons=keyboards.name_buttons_by_start, @@ -35,11 +38,13 @@ async def start(message: types.Message): async def start(message: types.Message): user_id = message.from_user.id user = users.get(user_id) + if not user: user = User(key=user_id) users.add(user) user = users.get(user_id) user.username = message.from_user.first_name + user.flag = Flags.NONE users.update_info(user) @@ -109,7 +114,10 @@ async def main_hand(message: types.Message): elif text == "Хочу начать": await bot.send_message(chat_id=user_id, text=texts.text_for_payment, - reply_markup=types.ReplyKeyboardRemove(), + reply_markup=functions.inl_create_keyboard( + buttons=[["Оплатить 2990 руб.", + WEBHOOK_HOST + f"/pay?user_id={user_id}&price=2990.00"]] + ), parse_mode="Markdown", disable_web_page_preview=True, ) @@ -3249,7 +3257,33 @@ async def main_hand(message: types.Message): users.update_info(user) + +app = Flask(__name__) + + +@app.route("/pay", methods=["POST", "GET"]) +def payments(): + user_id = str(request.args.get('user_id')) + price = str(request.args.get('price')) + key = functions.create_pay(user_id, price=price) + user = users.get(int(user_id)) + user.key_payment = key.replace("ct-", "") + users.update_info(user) + return functions.render_html(functions.create_pay(user_id, price=price)) + + +def bot_start_polling(): + executor.start_polling(dispatcher=dp, skip_updates=True) + + if __name__ == "__main__": reminders = Reminders() reminders.start_process(func=reminders.start_schedule) - executor.start_polling(dp, skip_updates=False) + + bot_process = Process(target=bot_start_polling) + bot_process.start() + + checking = Checking() + checking.start_process(func=checking.start_schedule) + + app.run(host=WEBAPP_HOST, port=WEBAPP_PORT) diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..5945c8b --- /dev/null +++ b/templates/index.html @@ -0,0 +1,15 @@ + + + + + Прием платежа с помощью виджета ЮKassa + + + + + + +
+ + + \ No newline at end of file diff --git a/templates/index.js b/templates/index.js new file mode 100644 index 0000000..49a353d --- /dev/null +++ b/templates/index.js @@ -0,0 +1,10 @@ + + const checkout = new window.YooMoneyCheckoutWidget({ + confirmation_token: 'ct-2b759ab6-000f-5000-9000-1a6fd83ce42b', + return_url: 'https://t.me/test_for_flow_evg_bot', + error_callback: function(error) { + console.log(error) + } + }); + + checkout.render('payment-form'); diff --git a/templates/pay.html b/templates/pay.html new file mode 100644 index 0000000..0406d86 --- /dev/null +++ b/templates/pay.html @@ -0,0 +1,25 @@ + + + + + + Прием платежа с помощью виджета ЮKassa + + + + +
+
+ + + \ No newline at end of file diff --git a/texts.py b/texts.py index 70e8248..9438286 100644 --- a/texts.py +++ b/texts.py @@ -22,11 +22,13 @@ "заинтересовались ими.\n\nДерзайте, мир не может жить без магии! Выполняйте задания и помогайте своей " \ "знакомой фее! Я думаю вам улыбнется удача!" -text_for_payment = "Теперь про оплату. Я был бы рад сделать сервис бесплатным, ведь тогда я бы смог обучить еще " \ - "больше людей... Но над материалами работала команда экспертов, дизайнеров, редакторов и " \ - "программистов. Каждый из них вложил в этот курс душу. \n\nКстати, сегодня действует скидка — " \ - "70%.\n\nОплатить курс можно на этой странице:\nhttps://www.skillbots.ru/design\n\nПосле оплаты вы " \ - "получите код активации — пришлите его сюда." +text_for_payment = "Теперь про оплату. Я был бы рад сделать курс бесплатным, ведь тогда я бы смог обучить еще больше " \ + "людей... Но над материалами работала команда экспертов, дизайнеров, редакторов и программистов. " \ + "Каждый из нас вложил в этот курс душу.\n\nНо я уговорил команду не делать курс таким дорогущим, " \ + "как сейчас обычно стоят курсы по дизайну. Поэтому стоимость курса — всего 9900 руб. А сегодня для " \ + "вас действует скидка –70%. \n\nДо конца дня вы можете получить доступ всего за 2990 руб.\nКурс " \ + "запустится через 2 минуты после оплаты. \n\n\nЕсли вы уже приобрели курс ранее, то просто введите " \ + "код активации." not_successful_payment = "Извините, но ваш код не подходит. Приобрести код активации [можно на нашем " \ "сайте](https://www.skillbots.ru/design?utm_source=error_code_tg&utm_medium=tgbot). " \ @@ -35,8 +37,10 @@ text_after_pay = "Спасибо за оплату! \n\nНу что, начнем?" -text_for_reminder_1 = "Пришлите мне код активации, который можно получить здесь. После этого курс запустится.\n\nЕсли "\ - "есть какие-нибудь вопросы, то напиши нам на [@skillbots_support](https://t.me/skillbots_support)" +text_for_reminder = "Вы можете подробнее прочитать про наш курс на нашем сайте. Если у вас останутся вопросы, " \ + "то напишите на [@skillbots_support]" \ + "(https://t.me/skillbots_support)\n\nТакже напоминаю, " \ + "что сегодня у вас есть возможность получить курс всего за 2990 руб." text_for_reminder_2 = "Напоминаю, что сегодня действует скидка 70% — доступ к курсу можно получить всего за 2990 " \ "руб.\n\nУзнать подробнее про обучение можно на нашем " \ @@ -983,4 +987,17 @@ text__0135 = "Это неправильный ответ. Типично рекламное фото, на котором все хорошо, но не интересно. " -text__0136 = "👍Рад сообщить, что мы уже близки к цели. Остался один единственный рывок и мир роскошных спорткаров распахнет перед нами свои двери. " \ No newline at end of file +text__0136 = "👍Рад сообщить, что мы уже близки к цели. Остался один единственный рывок и мир роскошных спорткаров распахнет перед нами свои двери. " + +text_for_reminder_3 = "Осталось 4 часа! Вы еще можете приобрести курс по дизайну со скидкой 70% до 23:59. \n\n— Курс " \ + "поможет сделать первый шаг в дизайне и определиться с направлением\n— Занятия помогут " \ + "сформировать фундамент и систематизировать знания о дизайне\n— Проверочные занятия с " \ + "рекомендациями помогут скорректировать учебный трек\n— Сюжет не даст заскучать. Все занятия " \ + "рядом буду я — робот Никки ☺️\n— В курсе используется искусственный интеллект, который будет " \ + "отвечать на вопросы о дизайне" + +text_for_reminder_4 = '{username}, я заметил, что мы так и не начали проходить курс\nДля нас очень важно делать по-настоящему полезный продукт. Напиши нам, пожалуйста на @skillbots_support что именно тебе не понравилось и какие вопросы возникли?' + +text_for_reminder_5 = "{username}, у меня очень крутой подарок 🎁\n\nДля тебя сегодня действует персональная скидка — 90%\n\n\nДо 23:59 доступ к курсу можно приобрести почти бесплатно — за 990 руб.\nКурс будет доступен навсегда. " + +text_for_reminder_6 = "Осталось 3 часа! 🔥🔥🔥" \ No newline at end of file