From 0e41ded499a436f1cfe2907ef66ad3c1b5f071ca Mon Sep 17 00:00:00 2001 From: lpetrov02 <71082527+lpetrov02@users.noreply.github.com> Date: Mon, 28 Dec 2020 12:42:45 +0300 Subject: [PATCH 1/3] Add files via upload --- src/analyse_and_bot_functions.py | 119 ++++++++++++++++++++++++++++++- src/new_main.py | 19 ++++- 2 files changed, 135 insertions(+), 3 deletions(-) diff --git a/src/analyse_and_bot_functions.py b/src/analyse_and_bot_functions.py index ffb70e0..69c52c6 100644 --- a/src/analyse_and_bot_functions.py +++ b/src/analyse_and_bot_functions.py @@ -8,13 +8,25 @@ import time import random import math +import matplotlib.pyplot as plt +from matplotlib.ticker import AutoMinorLocator +import pylab as pltt +import datetime +import matplotlib.dates as mdates + + token = "65e6efa565e6efa565e6efa54f6593fb1f665e665e6efa53a5c6937a4636b3416a8bd92" group_token = "17e681fbe171945431a04f1abc752d41ff888698288abf74124de4e782c67f36e76484601991870f56b7a" +new_token = "812c2975fc2ac0785252d97e8b5011f45e873a00dfb98b15299aec060ff7b890d06c4822feab0626e198c" +our_group_id = 200698416 + analyse_group_id = 'memkn' my_group_id = 'memkn_funclub' my_number_group_id = 200698416 +album_id = 278041850 +version = '5.95' session1 = vk.AuthSession(access_token=token) session2 = vk.AuthSession(access_token=group_token) @@ -25,6 +37,29 @@ days_of_the_week = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] +def upload_picture(picture_path): + """ + uploading a picture to an album in vk group + :param picture_path: + :return an answer of request: + """ + r = vk_api.photos.getUploadServer(group_id=our_group_id, album_id=album_id) + url = r['upload_url'] + file = {'file1': open(picture_path, 'rb')} + ur = requests.post(url, files=file).json() + result = requests.get('https://api.vk.com/method/photos.save', + params={ + 'access_token': new_token, + 'album_id': ur['aid'], + 'group_id': ur['gid'], + 'server': ur['server'], + 'photos_list': ur['photos_list'], + 'hash': ur['hash'], + 'v': version, + }).json() + return url + + def get_message(group_id, server_, ts_, key_): # gets the message from the user response = requests.get('{server}?act=a_check&key={key}&ts={ts}&wait=25'.format @@ -52,7 +87,6 @@ def process_input_message(message): code 10: the user needs the advice how to give a task code 11: user wants to set time and has pressed the button code 12: user wants to set recommendation time and has entered this time already - :param message: the message that was sent by the user :return: special code, string - the group id or "" - and a number - the period of analysing or -1 """ @@ -366,10 +400,91 @@ def not_available(current_user_id): return +# dicts belong -- samples of dicts for functions + + +def time_from_db_to_date(time_string): + """ + time in table is string, so this formatting it to a timedate. example: + time_string = "Mon, 10:30" + 0123456789 + :param time_string: + :return timedate: + """ + + moment_hours = int(time_string[5])*10 + int(time_string[6]) + moment_minutes = int(time_string[8])*10 + int(time_string[9]) + moment_days = 7 + if time_string[:3] == "Mon": + moment_days = 1 + if time_string[:3] == "Tue": + moment_days = 2 + if time_string[:3] == "Wed": + moment_days = 3 + if time_string[:3] == "Thu": + moment_days = 4 + if time_string[:3] == "Fri": + moment_days = 5 + if time_string[:3] == "Sat": + moment_days = 6 + auxiliary_delta = datetime.timedelta(days=moment_days, hours=moment_hours, minutes=moment_minutes) + # time from the beginning of the week + abstract_sunday = datetime.datetime(2020, 12, 27) + final_time = abstract_sunday + auxiliary_delta + return final_time + + +def dict_with_strings_to_dict_for_plots(dict_with_strings): + """ + converting result of request to db to dict for plot funstions + :param dict_with_strings: + :return: + """ + new_dict = {} + for key in dict_with_strings: + key_for_new_dict = time_from_db_to_date(key) + new_dict[key_for_new_dict] = dict_with_strings[key] + return new_dict + + +def create_daily_image(dict_with_data, label_of_image): + """ + an image for daily report + :param dict_with_data: + :param label_of_image: + :return nothing: + """ + day_delta = 0 + prev_key = datetime.datetime.now() + for key in dict_with_data: + day_delta = key - prev_key + prev_key = key + period = day_delta.total_seconds() + period = period // 60 + number_of_dots = int(1440 // period) + y_axis = [0] * int(number_of_dots) + x_axis = [datetime.datetime(2020, 1, 1, 0, 0, 0) + day_delta * i for i in range(number_of_dots)] + for key in dict_with_data: + y_axis[int((key.minute + key.hour * 60) // period)] = dict_with_data[key] + # belong is decoration for graph + figure, ax = plt.subplots(figsize=(number_of_dots, 10)) + ax.set_title(label_of_image) + ax.set_xlabel("Время", fontsize=14) + ax.set_ylabel("Процент онлайна", fontsize=14) + ax.grid(which="major", linewidth=1.2) + ax.grid(which="minor", linestyle="--", color="gray", linewidth=0.5) + ax.scatter(x_axis, y_axis, c="red") + ax.plot(x_axis, y_axis) + my_fmt = mdates.DateFormatter('%H:%M') + ax.xaxis.set_major_formatter(my_fmt) + figure.savefig("../data/images/" + label_of_image + ".png") + return + + def task_by_button(current_user_id): r_id = get_new_random_id() vk_api2.messages.send( user_id=current_user_id, message="Send the group_id and the period with a whitespace between them and '$' in the beginning", random_id=r_id - ) + ) \ No newline at end of file diff --git a/src/new_main.py b/src/new_main.py index 057ca80..171d914 100644 --- a/src/new_main.py +++ b/src/new_main.py @@ -86,9 +86,10 @@ group.recommendation_for_this_week() next_recommend += datetime.timedelta(days=1) - code, return_message, frequency_number = func.process_input_message(message) + code, return_message, return_number = func.process_input_message(message) if code == 3: + frequency_number = return_number analyse_group_id = return_message # this code means that user gave a correct task if not have_a_task or current_user_id == master_id: @@ -172,3 +173,19 @@ file.close() else: not func.not_available(current_user_id) + elif code == 13: + if have_a_task and current_user_id == master_id: + stats_dict = group.daily_graph_request(return_number) + stats_dict = func.dict_with_strings_to_dict_for_plots(stats_dict) + ph_id = "photos" + str(current_user_id) + \ + datetime.datetime.now().day + datetime.datetime.now().hour + \ + datetime.datetime.now().minute + datetime.datetime.now().second + func.create_daily_image(stats_dict, ph_id) + res_url = func.upload_picture(f'../data/image/{ph_id}') + stop_ind = res_url.find('%') + vk_api2.messages.send( + user_id=current_user_id, + message=f"Get it!", + random_id=r_id, + attachment=res_url[32: stop_ind] + ) From 31f9633e9347d5dc55c0961fb232e8e13afda605 Mon Sep 17 00:00:00 2001 From: lpetrov02 <71082527+lpetrov02@users.noreply.github.com> Date: Mon, 28 Dec 2020 13:18:20 +0300 Subject: [PATCH 2/3] Add files via upload --- .../analyse_and_bot_functions.cpython-38.pyc | Bin 8017 -> 11601 bytes src/analyse_and_bot_functions.py | 3 +++ 2 files changed, 3 insertions(+) diff --git a/src/__pycache__/analyse_and_bot_functions.cpython-38.pyc b/src/__pycache__/analyse_and_bot_functions.cpython-38.pyc index 5f1a8a5e932961cfd7d83e1f6e96dcb6aa37fadd..37c808aa75ac5d04842f8c813beb5fddbd2ba468 100644 GIT binary patch literal 11601 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 Date: Wed, 30 Dec 2020 23:01:57 +0300 Subject: [PATCH 3/3] Add files via upload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Немного причесал код и добавил функцию отправки последней загруженной картинки --- data/vk_bot.db | Bin 40960 -> 40960 bytes src/analyse_and_bot_functions.py | 344 ++++++++++++++----------------- src/group_class_with_db.py | 76 +++---- src/new_main.py | 26 +-- 4 files changed, 212 insertions(+), 234 deletions(-) diff --git a/data/vk_bot.db b/data/vk_bot.db index cd82bfaf6a72944be4f256c57d47e5fff9e555de..b684e5620e32d5ef72dcce3c2702630f42fd166a 100644 GIT binary patch literal 40960 zcmeI5dyL%Gb;oz!?-|cEU?2vs!EcP2_dWn)8$Yly25e&tIM{1@{lM?_t}(_uW_FiS zlp=~qih$CTB8n&lO4Agjh*C<@BqEW6C{0j;QbZA@DNR$9Ac9EGx%YR@`R(t}f10Ff z)89(Q%V%dlo;h>x-S3(EyR+-AT)lgEuzSaWp?w3x-Sw_XU6DxFqVDdlt|g!E>gvkE zpE&$Uz@Mb|Is9cmBJ|0B{WmxkT=cyH+#p`)>ne2>2MgbVPr{F|0$~Nh3WOC1D-c#7 ztUy?SumWKP!V3IfszAFOPfeLNEz&+TJg{}|;I4rqgPVs34)5Vl(ig8?ws`%r?)8h8 ztX|g5xO>j*-P>n(uUxZ!*@|Ur=XcNEIdov;;O2>Jn1nRQjOw zeyLO1SK3&*xU`^jS}9)qx8fVcuNI#vK3Ke?c&NCkxT07qo>5E}{-f|_;Twf775<=b zS7D^ErEqDXRhVAL=YN)eEB~$hbNN5Y-<`iHzde6>zCS-RKPmU~+&j7NF#tc_0!Zprd~zvi8%=q|2Y0m{6zdK@kir#$B)Lh##hH%@$Psw_Cf5;*w&+^P-i)H?O)HAt)I?h8v)-hl=uIe!-ngRZjRmNiZ&5|j z8&MR!U5bMDwg9x#?N$ZBdW(V}J+2@)Zw^2^)s86$&YKhj=TQa0d1CSl z&S3??c{l*=6dO_yoQD(y=RpO*c_0Ao^xCf=IQJT>#p8u2m46S1Jh3D-;Ch zla9*GwIL{A2yDs%B2+lqQ!P%=IIC}!n z&ZCxs;A|=g&W3{EtOuZ-M>Pe(Syd366$Qb0UI5y8Bx%(y0@W&}RSByE!6{jlAUGwe zI%wySBvpdol%PrwoRU)sf>UCuh3?0^q*Q|7l#oggoRU!qf>R=@gLWQCLL~@J38)0Y zDfyHjI3=DsXy=inQ-a`>a7qxIl1&MMQ=+MZb{kJlpr`Ijyh=Pk)%w3ln_b~oRUEaf>R=>gLWQC0woAe37`bQ z3HcLt^2eg^-)v_i{5RHKfc^i|kt1EDe<{6Q`kT^|rQZwt|6hIo4@I8v5%&Mx)v*6} zul(2rtSu`oQJBSH|6i@x*TrPnb=9f#!*Uk(|4@Xm|A$vm-D{|oMnC+F4Euj6NZ9{R zY-VbY5Wg#G`-HKfvui6rd*d4yD&xQ2xNzZ9f~ zYsml3{vYn7+|LT!Pp>V-Yy4yI2e0?XYyI(+0{k5RP8Q!RezW-H;v>boi^qyPiffAt zi}Q-76r+Xr3vU#@R(Q7XFkAz0q_DNHrqExQRWSKa^6%we&%cy^D*r(Kj{H#m`uwVV zD}PqLnEME>0(dp|Lhgy&7jm84{@k^>6}d)kdajuLdG=kn4&bHi)7gizcV>sPTe7RO zz1bPrNtur`?`B@hyqI}1bAM(Gt_0YWxg^ubbZ7GE57Td_Po$quKc2oXc1f%e>yG84 zA4cDfo`^mleH`}VZ;$ScZj3ICR-#j*>Bt9>A4Xn*9r;Hi_rxEF|5kiBJ`i6MKR-Sv zesVk-dq4I@?5nY7Vh_UZ{-M~W$j$bufIW!~iN%Tei7DyZ(l?~9N-s*ElRhOKN&P7G z52=?@f10{KHJaL=x+b+WbzbW9R3Z_L|7-la@xP5fmHhYQ50c+V{zdW+lQWW&5+5ht zg=-D?t9aExmyrf$n*C{9>#w%V5n65>tM)g0&4^+>W>~S7;r%rJ-lpO0G-eIMyJ^ho zhBwog)eL88W>v#mY0N5ychZP8`V4QRG3zzFkH)OW@HQH=mf0PAY>lSbrC7u4RIF}z z3ypm>!#ilqs)jevm{kn#pAoC~8Qwl))@ufW|8Bj&#Tq8ayHVIx|CfLilxNhVX>&>&y%*MlN|EScON#uQM}* zJI^n8FzkVq_-EcVL+*as<)STfz!n6DSXWo1>fQ1T55hCg1C&^Axy_rq#CpnY-rFVC zDz|xSmsqph-bAG&)+o2H3$l8-&HK7^yIQ%;+q%T6o?5`%)lv;9Bw5Amih4*{5y zys66&h5&EsGK3*;IX!NMFa*{p2#@HpAcUo|y;?yS0=%h9&IXL%RqB>7epf08q4bQm|!sSh~>< zU3=5;uw>RSJS>^j4G&9ZHN(S_S=I2cWL7aeEQ!_n3=d0Yy+#%x*G2c&dW@_=#9Bs{ zAYx4;D-f}Ukp+lY-N=X}Rx>gniB*k^M`9Ht!_i}~&d6va)@x)i66-NC7Kyct3`Js1 zBO{Sm!^l7+RyQ&ZiPek@Lt<4UqmWpo%!APVP^k9zm3asf>MipCB-B&p;YX-d=D|m( zS>~Zfs8PO%MkAqmd0`OM$`=MvwR}MkRSdt1;6_dbe^m9;&6xF?KE--WuVO9Jqgd0l z6l<8KVs+C{tY+$pRZUH?im3(}ELj!Bdd+!?^_T^UwamGSHO+j*8s;3u>Smr|H8WSS zs+pr$#mo*eSg2+x)@x=e)?;QU)-q=+)--1+)-e290X^sSy6IN8tC?wvRn3`-Rm>Sd z2CLLm#d^(W6zegkE7mfnDb_TnD%LPl6swz46swt&6|0()6swrYK?bXoQLNXL73(pR z6lW)pA!5RdE0RiOBY@(tD-XN-vZiFWp-@ zUfNN*qSRlSQ7RTcEWTBI1$zH47Vjz!7q2f~0$2Y}EhY;;hR*-x!c&F&3!TE=!iK`4 z!o0#s(D%Qae>MMn{;~W$`D1YH|C)R+bp83VtO`hPq5?c{UGN0OgQ z9!YLVu1YqNXC~8$pCrDY_*&wb!~==3#Qwy_#1iQ4Pf2ve-;2K%eTA$ z@&5RXcro^2?5)@Ht~iq4Ck z6!|3bZsgU-^O46Q_e73CQN54JWBlw)UpFv3zuUcrIL1#9Q+Oe5jGrT>@M_ZNZS>4} z)Luq3daI)F+T`dhih_6axT5I2IY8~M{OB=7(R-7k=sl_^dT$I+dpXhQ5k=8Eq9}TY z6-Dpi0JWDCjSeY_-b0F__n@NaJrJOFSAKNAqUhbHD0=rQirzf|YA-Dsy+Kj*?p74N zyA(z5&H%M9(~s^@6upCrqIbKZ=-n2eb_;QItD@)~P!zpe6h$vb`svGucGG3Vqa5m) zqL*VmQ}lAMXNq2q_8xWh<#5jwy&UhEqL%|cQ}lAg_o%BchkT~!<(SVDy&UwJqL-t- zM_qk6>@!6#$9<;g<-pGry&U-+b(a;7a_DD@UXJ}t(aXV~DSA2jd(>VMIm+RmDSA2n zGes{q08G)#Er3Vedd5uvQ}l8hz!bgQ2{1)3Hv=AZ>)8?>lXmpMwMXb(tSEXHDT-ch z3_Pz}&$u^Wie7FHn4*_E1g7ZaCc&d_J>xckDSEk4V2WOD6_}!zn+1=$^^DsErs(B{ zfhl^qWnhY4ZW=u5<{P&SOwr4Y15@;J>%bJf+&p;H%{Oizn4*^(2&U-e7J?~yxry+o zn{V7kFhwsn5=_y{tpro_ax>wmyZm^R+X<%V<%WVOdby=wie7FiJnH7#Srf;k%MYW| z6-95iqUh!3!t=WM#_a`DyuaLFFhwu77);U2O@>F^eB(BQDSEllV2WODHJGB8n+=b; z`Nr)AQ}lAf!4$pRaxg_NHys{z^NrgMrs(CygDHBs^{7V$Ql7ESUwxfxZ%6VkQS?gwb=20kBl(vo zdL{o7MX%&vqUe?U>!_`7NAfRG^h*9EieAaTMA0kx*HK&Fj^tmW=#~6S6upvviK18X zuca0MX%&vqUe?UOBB75e;u{!Sx53OQS?gwC5m3jzeLe1`PWgqo^>Su5=F1% zU!v%h{7V$Ql7Ahw>sd$gFH!VL{w0cD$-hL=EBV(^yPkC<{}M&7JO8zBUZTimtQ@a}e9abQ$Kv;pW0$~Nh3WOC1D-c#7tUy?SumWKP!V3I` zRUqvDf5V>8@Zp3N2rCd)Agn-Gfv^H$1;Pr16$mR3Rv@fESbD>ep8cmC`_8P=q?95_MG}g{6^SVl4U%jmnU286FW>|F|KE>x!t?+C?eqV?d2@D0<~=qNDa~*SMTbB#K@+n@AMBayF4DdgW}QqxNjqxSUNSie5RJNEE$tHjyZL zd2@D0<~=qNDa~ z*SMTbB#K@+n@AMBayF4DdgW}QqxNjqxSUNSie5RJNEE$tHjyZJ$K-6HqxNjqn4C={ z3f?g}n@AMAV{$f;D0<~=qNDa~*O;75B#K@+n@AMBayF4DdgW}QqxP)on4C={ie5RJ zNEE$tHjyZLP z=v|~JdM^@+@2=#2MdjE+MbUeqqUgOqQS_c4psv3CilVnqQS|mIir$_8b@gp2ir%K8 z=xr#9-grwRj@~=nH>&w3$MXxXa zTI%MTFaLTJy}tbGQS|!quSe1A%fFVo`R2>N9!0M&|9TX?zWnP^^!oCzrEb3Y@~=nH z>&w3$MXxXadKA6B{EO7f55D~CQS|!quSe1A%fB8)uP^^vit`Qo|M30)e$DUy*O44U z@4NudM@Mpuqjny3B*zei=eZ*}hA2GG9mz37(JMK|Q9F-1l4FRXS8@zd^h%B)ieAYv zj@o(DksL!5y^>>yqE~VZQS?fVan#PEj^r4k=#?Bp6upvTh@w|=jHPZKbtK0SMX%%- zqUepwzh@w|=3{mt-jv=bb?<2+Iff{DCC3m& zujCk_=#?DfsGDz+V~C;TJdL_pY zMX%%-M_qj-#}GxY=bb@i1TLlnJ|V~CzU*jqUelYD0;68P&?n`_qupq z`<|-un_ZZqSMsmB4=wx+Y4W>#yxY3@Ci&OhwrTILg&tD9!0M&|9TX?zWnP^^!oCz erLMld{OeKl`tq+w(d)~<9!0M&|01>d;XeT%Y57I~ literal 40960 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 0: @@ -70,10 +45,13 @@ def get_message(group_id, server_, ts_, key_): return "", -1, response['ts'] +# THE BLOCK OF FUNCTIONS WHICH PROCESS MESSAGES FROM A USER AND CHECK IF GIVEN PARAMETERS ARE CORRECT def process_input_message(message): - # gets the massage from the user and returns a code which depends on the message type. Also returns the group id - # and needed frequency. These fields will be used afterwards only if the message is: group_id: ...; period: ... """ + gets the massage from the user and returns a code which depends on the message type. Also returns the group id + and needed period. These fields will be used afterwards only if the message is: group_id: ...; period: ... + :param message: the massage got from the server + :return: special code, group id and period code -1: mistake code 0: no message code 1: user wants to cancel the task @@ -88,13 +66,10 @@ def process_input_message(message): code 10: the user needs the advice how to give a task code 11: user wants to set time and has pressed the button code 12: user wants to set recommendation time and has entered this time already - :param message: the message that was sent by the user - :return: special code, string - the group id or "" - and a number - the period of analysing or -1 """ + if message == "": return 0, "", -1 - if message[:2] == "gr" and message[2] == ':' and message[3:].strip() in days_of_the_week2: - return 13, "", days_of_the_week2[message[3:].strip()] if message[0] == '~': if not check_recommend_time(message): return -1, "", -1 @@ -146,66 +121,143 @@ def process_input_message(message): return -1, "", -1 +def check_recommend_time(time_string): + """ + the option 'set time' asks the user to enter the time ant this function checks if it is correct + :param time_string: string with that time + :return: + """ + if time_string[3] != ':' or not time_string[1: 3].isdigit() or not time_string[4: 6].isdigit(): + return 0 + hours = int(time_string[1: 3]) + if 0 <= hours < 24: + return 1 + return 0 + + +def check_for_correct(group_id_to_check): + """ + this function check if the group which the user asked to analyze, exists + :param group_id_to_check: that group's id + :return: + """ + your_group_info = vk_api2.groups.getById(group_id=group_id_to_check, fields='members_count', count=5) + if your_group_info[0]['id'] == my_number_group_id and group_id_to_check != 'memkn_funclub': + return 0 + return 1 + + +def check_period_for_correct(period): + """ + checks if the period value is OK, not 17 minutes, for example. We have special rules for this + :param period: + :return: + """ + if period < 15 or period > 1440: + return 0 + if period < 60 and 60 % period != 0: + return 0 + if 1440 % period != 0: + return 0 + return 1 + + +# THE BLOCK OF FUNCTIONS FOR COMMUNICATING def get_new_random_id(): + """ + random id is a special id of the message to send this message, it has to be unique during the hour + :return: counted random (not random!!!) id + """ t = datetime.datetime.now() - random_id = t.minute * 60000 + t.second * 1000 + t.microsecond + random_id = t.minute * 60000000 + t.second * 1000000 + t.microsecond return random_id -def switch_off(current_user_id, begin_file_): - # switches the bot off, the special password is needed +def switch_off(current_user_id, file_name): + """ + switches the bot off, the special password is needed + :param current_user_id: + :param file_name: file with the information about the current task, we need to rewrite it + :return: + """ r_id = get_new_random_id() - file_ = open(begin_file_, "w") - file_.write(f"-1 0 0 0") - file_.close() + file = open(file_name, "w") + file.write("-1 0 0 0") + file.close() vk_api2.messages.send(user_id=current_user_id, message="Goodbye!", random_id=r_id) - return + return 0 def incorrect_id(current_user_id): - # informs about the mistake + # informs about the mistake in group id r_id = get_new_random_id() - vk_api2.messages.send(user_id=current_user_id, message="Wrong group id!", random_id=r_id) + vk_api2.messages.send( + user_id=current_user_id, message="Ummmm... Something went wrong! Incorrect group id!", random_id=r_id + ) return def incorrect_period_value(current_user_id): - # informs about the mistake + # informs about the mistake in a period value r_id = get_new_random_id() - s = "Period should be not less than 15 and should divide 1440!" + s = "Bro, listen here! If your period is less than an hour, in should divide 60. And anyway, it should divide 1440)" vk_api2.messages.send(user_id=current_user_id, message=s, random_id=r_id) return -def cancel_the_task(have_a_task, current_user_id, master_id, begin_file_): - # Cancels the current task, it is is asked by the user who gave the task earlier +def cancel_the_task(have_a_task, current_user_id, master_id, file_name): + """ + Cancels the current task, it is is asked by the user who gave the task earlier + :param have_a_task: 1 if bot has a task already, 0 if it hasn't + :param current_user_id: id of the user who wants to cancel the task + :param master_id: id of the user who had given a task + :param file_name: file with the information about the current task, we need to change it + :return: + """ r_id = get_new_random_id() - file_ = open(begin_file_, "w") - file_.write(f"-1 0 0 0") - file_.close() if have_a_task and current_user_id == master_id: + file = open(file_name, "w") + file.write("-1 0 0 0") + file.close() vk_api2.messages.send(user_id=current_user_id, message="Your task is cancelled!", random_id=r_id) - return + return 0 elif have_a_task: vk_api2.messages.send(user_id=current_user_id, message="Sorry, I am working on the other user's task!", random_id=r_id) - return + return 1 else: vk_api2.messages.send(user_id=current_user_id, message="Я сделал ничего, не благодари!", random_id=r_id) - return + return 0 def say_hello(current_user_id): # sends a message 'Ну привет, ....' r_id = get_new_random_id() - string = "Ну привет, " + greetings = [ + "Ну привет, ", "Здарова бандит-", "Hi, bro ", "Здрасьте. Кто тут лох? Ага - ", "Приветики, ты просто космос, " + ] + index = random.randint(0, 4) + string = greetings[index] value = vk_api2.users.get(user_ids=current_user_id, fields='first_name') string += value[0]['first_name'] - something = vk_api2.messages.send(user_id=current_user_id, message=string, random_id=r_id) + vk_api2.messages.send(user_id=current_user_id, message=string, random_id=r_id) return +def send_last_upload(current_user_id): + """ + in development + :param current_user_id: + :return: + """ + r_id = get_new_random_id() + some = vk_api.photos.get(owner_id=-200698416, album_id='278041850', rev=1, count=1) + ph_id = some['items'][0]['id'] + string = "photo-200698416_" + str(ph_id) + vk_api2.messages.send(user_id=current_user_id, attachment=string, random_id=r_id + 1) + + def instruction_message(current_user_id): # sends the message if user did send us the message of an unknown format r_id = get_new_random_id() @@ -218,16 +270,12 @@ def instruction_message(current_user_id): return -def check_recommend_time(time_string): - if time_string[3] != ':' or not time_string[1: 3].isdigit() or not time_string[4: 6].isdigit(): - return 0 - hours = int(time_string[1: 3]) - if 0 <= hours < 24: - return 1 - return 0 - - def set_time(current_user_id): + """ + sends the keyboard with some variants of time when to send recommendations + :param current_user_id: id of the user who wants to set time + :return: + """ r_id = get_new_random_id() kb = \ @@ -238,52 +286,52 @@ def set_time(current_user_id): { "action": { "type": "text", - "payload": "{\"button\": \"2\"}", - "label": "~19:00" + "payload": "{\"button\": \"1\"}", + "label": "~22:00" }, - "color": "positive" + "color": "primary" }, { "action": { "type": "text", "payload": "{\"button\": \"2\"}", - "label": "~20:00" + "label": "~23:00" }, - "color": "primary" + "color": "positive" }, { "action": { "type": "text", "payload": "{\"button\": \"2\"}", - "label": "~21:00" + "label": "~00:00" }, - "color": "positive" + "color": "primary" } ], [ { "action": { "type": "text", - "payload": "{\"button\": \"1\"}", - "label": "~22:00" + "payload": "{\"button\": \"2\"}", + "label": "~19:00" }, - "color": "primary" + "color": "positive" }, { "action": { "type": "text", "payload": "{\"button\": \"2\"}", - "label": "~23:00" + "label": "~20:00" }, - "color": "positive" + "color": "primary" }, { "action": { "type": "text", "payload": "{\"button\": \"2\"}", - "label": "~00:00" + "label": "~21:00" }, - "color": "primary" + "color": "positive" } ] ] @@ -379,115 +427,43 @@ def send_big_instruction(current_user_id): return -def check_for_correct(group_id_to_check): - your_group_info = vk_api2.groups.getById(group_id=group_id_to_check, fields='members_count', count=5) - if your_group_info[0]['id'] == my_number_group_id and group_id_to_check != 'memkn_funclub': - return 0 - return 1 - - -def check_period_for_correct(period): - if period < 15 or period > 1440: - return 0 - if period < 60 and 60 % period != 0: - return 0 - if 1440 % period != 0: - return 0 - return 1 - - def not_available(current_user_id): r_id = get_new_random_id() - vk_api2.messages.send(user_id=current_user_id, message="Not available now!", random_id=r_id) + vk_api2.messages.send(user_id=current_user_id, message="Not available now, give a task at first!", random_id=r_id) vk_api2.messages.send(user_id=current_user_id, sticker_id=4331, random_id=(r_id + 1)) return -# dicts belong -- samples of dicts for functions - - -def time_from_db_to_date(time_string): - """ - time in table is string, so this formatting it to a timedate. example: - time_string = "Mon, 10:30" - 0123456789 - :param time_string: - :return timedate: - """ - - moment_hours = int(time_string[5])*10 + int(time_string[6]) - moment_minutes = int(time_string[8])*10 + int(time_string[9]) - moment_days = 7 - if time_string[:3] == "Mon": - moment_days = 1 - if time_string[:3] == "Tue": - moment_days = 2 - if time_string[:3] == "Wed": - moment_days = 3 - if time_string[:3] == "Thu": - moment_days = 4 - if time_string[:3] == "Fri": - moment_days = 5 - if time_string[:3] == "Sat": - moment_days = 6 - auxiliary_delta = datetime.timedelta(days=moment_days, hours=moment_hours, minutes=moment_minutes) - # time from the beginning of the week - abstract_sunday = datetime.datetime(2020, 12, 27) - final_time = abstract_sunday + auxiliary_delta - return final_time - - -def dict_with_strings_to_dict_for_plots(dict_with_strings): - """ - converting result of request to db to dict for plot funstions - :param dict_with_strings: - :return: - """ - new_dict = {} - for key in dict_with_strings: - key_for_new_dict = time_from_db_to_date(key) - new_dict[key_for_new_dict] = dict_with_strings[key] - return new_dict - - -def create_daily_image(dict_with_data, label_of_image): - """ - an image for daily report - :param dict_with_data: - :param label_of_image: - :return nothing: - """ - day_delta = 0 - prev_key = datetime.datetime.now() - for key in dict_with_data: - day_delta = key - prev_key - prev_key = key - period = day_delta.total_seconds() - period = period // 60 - number_of_dots = int(1440 // period) - y_axis = [0] * int(number_of_dots) - x_axis = [datetime.datetime(2020, 1, 1, 0, 0, 0) + day_delta * i for i in range(number_of_dots)] - for key in dict_with_data: - y_axis[int((key.minute + key.hour * 60) // period)] = dict_with_data[key] - # belong is decoration for graph - figure, ax = plt.subplots(figsize=(number_of_dots, 10)) - ax.set_title(label_of_image) - ax.set_xlabel("Время", fontsize=14) - ax.set_ylabel("Процент онлайна", fontsize=14) - ax.grid(which="major", linewidth=1.2) - ax.grid(which="minor", linestyle="--", color="gray", linewidth=0.5) - ax.scatter(x_axis, y_axis, c="red") - ax.plot(x_axis, y_axis) - my_fmt = mdates.DateFormatter('%H:%M') - ax.xaxis.set_major_formatter(my_fmt) - figure.savefig("../data/images/" + label_of_image + ".png") +def not_available_i_am_busy(current_user_id): + r_id = get_new_random_id() + vk_api2.messages.send(user_id=current_user_id, message="Impossible because... i am busy!", random_id=r_id) + vk_api2.messages.send(user_id=current_user_id, sticker_id=4331, random_id=(r_id + 1)) return def task_by_button(current_user_id): + # gives the instruction how to give a task r_id = get_new_random_id() vk_api2.messages.send( user_id=current_user_id, - message="Send the group_id and the period with a whitespace between them and '$' in the beginning", + message="Send the id of the group and the period with a whitespace between them and the '$' in the beginning", random_id=r_id - ) \ No newline at end of file + ) + + +def continue_the_old_task(file_name): + file = open(file_name, "r") + task_from_the_previous_session = list(file.readline().split()) + gr_id = -1 + have_a_task = 0 + usr_id = -1 + prd = 0 + rec_hr = -1 + if len(task_from_the_previous_session) > 0 and task_from_the_previous_session[0] != '-1': + gr_id = task_from_the_previous_session[0] + usr_id = int(task_from_the_previous_session[1]) + prd = int(task_from_the_previous_session[2]) + rec_hr = int(task_from_the_previous_session[3]) + have_a_task = 1 + return gr_id, prd, usr_id, rec_hr, have_a_task + file.close() diff --git a/src/group_class_with_db.py b/src/group_class_with_db.py index 6dd1eae..716beaa 100644 --- a/src/group_class_with_db.py +++ b/src/group_class_with_db.py @@ -7,12 +7,12 @@ import src.analyse_and_bot_functions as func import math -# from new_main import vk_api2 as vk_api2 -# from new_main import days_of_the_week as days_of_the_week con = sql.connect('../data/vk_bot.db') cur = con.cursor() + +# top secret information, close your eyes... token = "65e6efa565e6efa565e6efa54f6593fb1f665e665e6efa53a5c6937a4636b3416a8bd92" group_token = "17e681fbe171945431a04f1abc752d41ff888698288abf74124de4e782c67f36e76484601991870f56b7a" analyse_group_id = 'memkn' @@ -49,10 +49,8 @@ def __init__(self, group_id, freq, master_id): self.period = freq self.analyses_per_day = 1440 // self.period - # con = sql.connect('vk_bot.db') name = "stats" + str(self.master_id) with con: - # cur = con.cursor() cur.execute(f"CREATE TABLE IF NOT EXISTS {name} (" "'analyse_number' INTEGER, " "'average_percent' INTEGER, " @@ -70,24 +68,32 @@ def __init__(self, group_id, freq, master_id): con.commit() if table_existed is None or table_existed == []: for j in range(7): - for i in range(self.analyses_per_day * j, self.analyses_per_day * (j + 1)): - s = days_of_the_week[j] + ", " - hours = (i % self.analyses_per_day) * self.period // 60 - minutes = (i % self.analyses_per_day) * self.period % 60 - if hours < 10: - s += "0" - s += str(hours) + ":" - if minutes < 10: - s += "0" - s += str(minutes) - stats = (i, 0, 0, 0, 0, 0, 0, s) - cur.execute(f"""INSERT OR REPLACE INTO {name} VALUES (?, ?, ?, ?, ?, ?, ?, ?)""", stats) - con.commit() + self.fill_the_database(j) + + def fill_the_database(self, week_day): + """ + fills the database in '__init__' + :param week_day: + :return: + """ + name = "stats" + str(self.master_id) + for i in range(self.analyses_per_day * week_day, self.analyses_per_day * (week_day + 1)): + s = days_of_the_week[week_day] + ", " + hours = (i % self.analyses_per_day) * self.period // 60 + minutes = (i % self.analyses_per_day) * self.period % 60 + if hours < 10: + s += "0" + s += str(hours) + ":" + if minutes < 10: + s += "0" + s += str(minutes) + stats = (i, 0, 0, 0, 0, 0, 0, s) + cur.execute(f"""INSERT OR REPLACE INTO {name} VALUES (?, ?, ?, ?, ?, ?, ?, ?)""", stats) + con.commit() def del_table(self): - # con = sql.connect('vk_bot.db') + # deletes data from the table name = "stats" + str(self.master_id) - # cur = con.cursor() cur.execute(f"""DELETE FROM {name}""") con.commit() @@ -104,9 +110,11 @@ def count_online_proportion(self): number_of_members1 = number_of_members already_count = 0 while already_count < number_of_members: + # if we haven't checked all members yet group_members_ids = vk_api.groups.getMembers(group_id=self.group_id, offset=already_count, fields='online') for x in group_members_ids['items']: if 'online' in x: + # if the information about the online status is available online += x['online'] else: number_of_members1 -= 1 @@ -128,8 +136,12 @@ def group_analyse(self): return percent def update_data(self, new_one, cell_to_update): - # con = sql.connect('vk_bot.db') - # cur = con.cursor() + """ + updates the database after the analyze + :param new_one: the new value of online percent + :param cell_to_update: the cell of the database which we need to update + :return: + """ name = "stats" + str(self.master_id) sq = f"SELECT * FROM {name} WHERE analyse_number={cell_to_update}" @@ -159,26 +171,27 @@ def update_data(self, new_one, cell_to_update): def recommendation_for_this_day_of_the_week(self): """ + average stats and recommendation for this day of the week past 4 last weeks this function runs at about 00:00 daily and recommends: when it is going to be the best time for posts this day. :return: returns nothing, just sends a message with recommendation """ - # average stats and recommendation for this day of the week past 4 last weeks - # con = sql.connect('vk_bot.db') - # cur = con.cursor() name = "stats" + str(self.master_id) r_id = func.get_new_random_id() + # высняем, за сегодн давать рекомендацию или за завтра today_or_tomorrow = "today" day = datetime.datetime.now().weekday() if self.recommend_hour != 0: day = (day + 1) % 7 today_or_tomorrow = "tomorrow" + # выяснили start = day * self.analyses_per_day finish = (day + 1) * self.analyses_per_day + # если за нужный день нет данных, даём рекомендацию за другой, то есть основанную на сегодншней статистике sq = f"SELECT weeks_passed FROM {name} WHERE analyse_number={start}" cur.execute(sq) checker = cur.fetchone() @@ -187,6 +200,7 @@ def recommendation_for_this_day_of_the_week(self): start = day * self.analyses_per_day finish = (day + 1) * self.analyses_per_day + # начинаем обрабатывать статистику recommend_message = f"Possibly, {today_or_tomorrow} the best time will be " max_online, best_time = 0, 0 for i in range(start, finish): @@ -252,8 +266,6 @@ def get_one_day_information_v2( """ # needed for 'recommendation_for_this_week' - # con = sql.connect('vk_bot.db') - # cur = con.cursor() name = "stats" + str(self.master_id) summary_percents = 0 @@ -278,8 +290,6 @@ def recommendation_for_this_week(self): """ # recommendation gives the day with the highest average percents past 4 last weeks - # con = sql.connect('vk_bot.db') - # cur = con.cursor() name = "stats" + str(self.master_id) r_id = func.get_new_random_id() @@ -307,10 +317,6 @@ def give_today_stats(self): Gives today's time with the highest online percent :return: nothing """ - # Just today's stats - - # con = sql.connect('vk_bot.db') - # cur = con.cursor() name = "stats" + str(self.master_id) r_id = func.get_new_random_id() @@ -344,10 +350,6 @@ def give_this_week_stats(self): certain percents of the current week, not average :return: nothing """ - # Just this week stats - - # con = sql.connect('vk_bot.db') - # cur = con.cursor() name = "stats" + str(self.master_id) r_id = func.get_new_random_id() @@ -373,7 +375,6 @@ def give_this_week_stats(self): def work_and_print(self): """ updates data and sends current online percent - :param count - is needed to send messages: :return: """ r_id = func.get_new_random_id() @@ -407,6 +408,7 @@ def calculate_new_analyse_time(self): current_time = datetime.datetime.now().replace(second=0, microsecond=0) current_minutes = current_time.minute + current_time.hour * 60 minutes_to_wait = self.period - current_minutes % self.period + # начать анализ нужно так, чтобы попасть в период, то есть чтобы анализы каждый день начинались в полночь next_analyse_time = current_time + datetime.timedelta(0, 0, 0, minutes_to_wait // 60, minutes_to_wait % 60, 0, 0) next_recommend_time = current_time.replace(microsecond=0, second=0, minute=0, hour=0) + datetime.timedelta( diff --git a/src/new_main.py b/src/new_main.py index 171d914..795b37b 100644 --- a/src/new_main.py +++ b/src/new_main.py @@ -10,6 +10,8 @@ begin_file = "../data/begin_task.txt" + +# top secret, don't look please token = "65e6efa565e6efa565e6efa54f6593fb1f665e665e6efa53a5c6937a4636b3416a8bd92" group_token = "17e681fbe171945431a04f1abc752d41ff888698288abf74124de4e782c67f36e76484601991870f56b7a" analyse_group_id = 'memkn' @@ -44,15 +46,10 @@ file = open(begin_file, "r") task_from_the_previous_session = list(file.readline().split()) -if len(task_from_the_previous_session) > 0 and task_from_the_previous_session[0] != '-1': - gr_id = task_from_the_previous_session[0] - usr_id = int(task_from_the_previous_session[1]) - prd = int(task_from_the_previous_session[2]) - rec_hr = int(task_from_the_previous_session[3]) - have_a_task = 1 - group = gc.Group(gr_id, prd, usr_id) +gr_id, prd, master_id, rec_hr, have_a_task = func.continue_the_old_task(begin_file) +if have_a_task: + group = gc.Group(gr_id, prd, master_id) group.recommend_hour = rec_hr - master_id = usr_id next_time, next_recommend = group.calculate_new_analyse_time() hrs = datetime.datetime.now().hour if hrs > rec_hr: @@ -65,7 +62,7 @@ while run: # wait for new requests - message, current_user_id, current_ts = func.get_message(my_number_group_id, server, current_ts, key) + message, current_user_id, current_ts = func.get_message(server, current_ts, key) # if it is time to change LongPollServer if datetime.datetime.now() >= change_server: @@ -109,7 +106,7 @@ next_time, next_recommend = group.calculate_new_analyse_time() else: # in the case when the user wants to give a new task while bot is already working on the OTHER user's task. - func.not_available(current_user_id) + func.not_available_i_am_busy(current_user_id) elif code == 2: # if the bot has received a secret password which switches it off if have_a_task: @@ -172,14 +169,16 @@ file.write(f"{group.group_id} {group.master_id} {group.period} {group.recommend_hour}") file.close() else: - not func.not_available(current_user_id) + not func.not_available_i_am_busy(current_user_id) + ''' + IN DEVELOPMENT elif code == 13: if have_a_task and current_user_id == master_id: stats_dict = group.daily_graph_request(return_number) stats_dict = func.dict_with_strings_to_dict_for_plots(stats_dict) ph_id = "photos" + str(current_user_id) + \ - datetime.datetime.now().day + datetime.datetime.now().hour + \ - datetime.datetime.now().minute + datetime.datetime.now().second + str(datetime.datetime.now().day) + str(datetime.datetime.now().hour) + \ + str(datetime.datetime.now().minute) + str(datetime.datetime.now().second) func.create_daily_image(stats_dict, ph_id) res_url = func.upload_picture(f'../data/image/{ph_id}') stop_ind = res_url.find('%') @@ -189,3 +188,4 @@ random_id=r_id, attachment=res_url[32: stop_ind] ) + '''