diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..10e932d
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..0707604
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/team-project.iml b/.idea/team-project.iml
new file mode 100644
index 0000000..34a1e97
--- /dev/null
+++ b/.idea/team-project.iml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/team-project1.iml b/.idea/team-project1.iml
new file mode 100644
index 0000000..d0876a7
--- /dev/null
+++ b/.idea/team-project1.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/21.png b/21.png
new file mode 100644
index 0000000..b75110d
Binary files /dev/null and b/21.png differ
diff --git a/graphics.py b/graphics.py
new file mode 100644
index 0000000..9bbdcb2
--- /dev/null
+++ b/graphics.py
@@ -0,0 +1,89 @@
+import matplotlib.pyplot as plt
+from matplotlib.ticker import AutoMinorLocator
+import numpy as np
+import pylab as pltt
+import datetime
+import matplotlib.dates as mdates
+
+
+dict_with_data = {datetime.datetime(2020, 12, 7, 1): 53,
+ datetime.datetime(2020, 12, 7, 2): 14,
+ datetime.datetime(2020, 12, 7, 3): 15,
+ datetime.datetime(2020, 12, 7, 4): 12,
+ datetime.datetime(2020, 12, 7, 5): 35,
+ datetime.datetime(2020, 12, 7, 6): 31,
+ datetime.datetime(2020, 12, 7, 7): 2}
+
+label_of_image = "zsd"
+
+sample_data = {datetime.datetime(2020, 12, 7): 53,
+ datetime.datetime(2020, 12, 8): 14,
+ datetime.datetime(2020, 12, 9): 15,
+ datetime.datetime(2020, 12, 10): 12,
+ datetime.datetime(2020, 12, 11): 35,
+ datetime.datetime(2020, 12, 12): 31,
+ datetime.datetime(2020, 12, 13): 2}
+
+
+def create_weekday_image(dict_with_data, label_of_image):
+ if len(dict_with_data) > 7:
+ return
+ day_of_week = [0, 1, 2, 3, 4, 5, 6]
+ online_on_this_weekday = [0, 0, 0, 0, 0, 0, 0]
+ for date in dict_with_data:
+ online_on_this_weekday[date.weekday()] = dict_with_data[date]
+ labels = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
+ pltt.rcParams['figure.figsize'] = 7, 5
+ pltt.bar(day_of_week, online_on_this_weekday, align='center')
+ pltt.xticks(day_of_week, labels)
+ pltt.savefig(label_of_image + '.png')
+ pltt.close()
+
+
+def create_daily_image(dict_with_data, label_of_image):
+ 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]
+ 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("images/" + label_of_image + ".png")
+
+
+def create_graph_image(period, total_time, y_axis, label_of_graph):
+ number_of_dots = total_time//period
+ x = np.linspace(1, number_of_dots, number_of_dots)
+ figure, ax = plt.subplots(figsize=(number_of_dots, 10))
+ ax.set_title(label_of_graph, fontsize=16)
+ 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, y_axis, c="red")
+ ax.plot(x, y_axis)
+ ax.xaxis.set_minor_locator(AutoMinorLocator())
+ ax.yaxis.set_minor_locator(AutoMinorLocator())
+ return figure
+
+
+#figure1 = create_graph_image(1, 11, [1, 2, 3, 4, 5, 64, 40, 8, 7, 5, 9], "28 ноября")
+#figure1.savefig("images/plot.png")
+create_weekday_image(sample_data, "21")
+plt.imsave
+create_daily_image(dict_with_data, label_of_image)
\ No newline at end of file
diff --git a/images/zsd.png b/images/zsd.png
new file mode 100644
index 0000000..b60273e
Binary files /dev/null and b/images/zsd.png differ
diff --git a/main.py b/main.py
index dc51b8e..cae29ca 100644
--- a/main.py
+++ b/main.py
@@ -1,69 +1,252 @@
-import vk
-import datetime
-
-
-token = "65e6efa565e6efa565e6efa54f6593fb1f665e665e6efa53a5c6937a4636b3416a8bd92"
-session1 = vk.AuthSession(access_token=token)
-vk_api = vk.API(session1, v=5.92)
-
-group_id = 'memkn'
-
-
-def get_user_last_seen(profile_id):
- """
- gets when user was online
- :param profile_id:
- :return time:
- """
- value = vk_api.users.get(user_ids=profile_id, fields='last_seen')
- if 'last_seen' not in value[0]:
- return None
- online_time = datetime.datetime.fromtimestamp(value[0]['last_seen']['time'])
- return online_time
-
-
-def get_group_followers(group_page_id):
- """
- getting group followers
- :param group_page_id:
- :return list of followers id:
- """
- value = vk_api.groups.getMembers(group_id=group_page_id)
- followers_id = []
- for user in value['items']:
- followers_id.append(user)
- return followers_id
-
-
-def approximate_time(real_time):
- approximated_online_time = real_time.replace(minute=(real_time.minute + 2) % 60)
- return approximated_online_time
-
-
-def is_online(online_time):
- now_time = datetime.datetime.now()
- now_time = now_time.replace(microsecond=0)
- if online_time >= now_time:
- return 1
- else:
- return 0
-
-
-def online_proportion(group_page_id):
- group_members_ids = get_group_followers(group_page_id)
- group_amount = 0
- group_online = 0
- for profile in group_members_ids:
- profile_last_seen = get_user_last_seen(str(profile))
- if profile_last_seen is not None:
- group_amount += 1
- profile_last_seen = approximate_time(profile_last_seen)
- group_online += is_online(profile_last_seen)
- if group_amount == 0:
- return -1
- else:
- percent_online = group_online / group_amount * 100
- return percent_online
-
-
-print(online_proportion(group_id))
+import vk
+import datetime
+import time
+import random
+import math
+
+
+class Group:
+ """
+ we don't really need this now but i suppose it would be useful in the nearest future
+ """
+
+ def __init__(self, group_id, freq):
+ self.group_id = group_id
+ self.begin = datetime.datetime.now()
+ self.frequency = freq
+
+ def count_online_proportion(self):
+ """
+ gets the number of members online, ant the total number of members, not counting those,
+ whose info is not is not available
+ :param self: the object of the class Group. We need the group id
+ :return: two integers - the number of members with available online-information and the number of members online
+ """
+ amount = 0
+ online = 0
+ your_group_info = vk_api.groups.getById(group_id=self.group_id, fields='members_count')
+ number_of_members = your_group_info[0]['members_count']
+ one_more_number_of_members = number_of_members
+ already_count = 0
+ while already_count < number_of_members:
+ 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:
+ online += x['online']
+ else:
+ one_more_number_of_members -= 1
+ already_count += 1000
+ if one_more_number_of_members == 0:
+ return -1, -1
+ else:
+ return one_more_number_of_members, online
+
+
+our_group_id = "memkn_funclub"
+token = "65e6efa565e6efa565e6efa54f6593fb1f665e665e6efa53a5c6937a4636b3416a8bd92"
+group_token = "17e681fbe171945431a04f1abc752d41ff888698288abf74124de4e782c67f36e76484601991870f56b7a"
+analyse_group_id = 'memkn'
+session1 = vk.AuthSession(access_token=token)
+vk_api = vk.API(session1, v=5.92)
+album_id = "278041850"
+month_length = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
+
+
+def upload_picture(picture_path):
+ r = requests.get('https://api.vk.com/method/photos.getUploadServer',
+ params={
+ 'access_token': token,
+ 'album_id': album_id,
+ 'group_id': our_group_id,
+ }).json()
+ url = r['response']['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': token,
+ 'album_id': ur['aid'],
+ 'group_id': ur['gid'],
+ 'server': ur['server'],
+ 'photos_list': ur['photos_list'],
+ 'hash': ur['hash']
+ }).json()
+ print(result)
+
+def get_user_last_seen(profile_id):
+ """
+ shows when user was online
+ :param profile_id:
+ :return time:
+ """
+ value = vk_api.users.get(user_ids=profile_id, fields='last_seen')
+ if 'last_seen' not in value[0]:
+ return None
+ online_time = datetime.datetime.fromtimestamp(value[0]['last_seen']['time'])
+ return online_time
+
+
+def get_group_followers(group_page_id, done):
+ """
+ gets the list of the group members, not more than 1000
+ :param group_page_id:
+ :param done: shows the indent
+ :return list of members' ids:
+ """
+ value = vk_api.groups.getMembers(group_id=group_page_id, offset=done)
+ followers_id = []
+ for user in value['items']:
+ followers_id.append(user)
+ return followers_id
+
+
+'''
+# probably we will not need this one, but who knows...
+
+def get_user_followers(id):
+ """
+ shows when user was online
+ :param id:
+ :return time:
+ """
+ value = vk_api.users.getFollowers(user_id=id)
+ followers_id = []
+ for user in value['items']:
+ followers_id.append(user)
+ return followers_id
+'''
+
+
+def approximate_time(real_time):
+ """
+ gets time user was last seen and adds two minutes
+ :param real_time: time user was last seen online
+ :return: real_time plus 2 min
+ """
+
+ hours = real_time.hour
+ days = real_time.day
+ months = real_time.month
+ years = real_time.year
+ # обработка редких случаев
+ if years % 4 == 0 and years % 100 != 0 or years % 400 == 0:
+ month_length[1] += 1
+ if real_time.minute >= 58:
+ hours = real_time.hour + 1
+ if hours == 24:
+ hours = 0
+ days += 1
+ if days > month_length[months - 1]:
+ days = 1
+ months += 1
+ if months > 12:
+ months = 1
+ years += 1
+
+ approximate_online_time = real_time.replace(minute=(real_time.minute + 2) % 60,
+ hour=hours, day=days, month=months, year=years)
+ return approximate_online_time
+
+
+def is_online(online_time):
+ # just checks if the user is online or not, returns 0 or 1
+
+ now_time = datetime.datetime.now()
+ now_time = now_time.replace(microsecond=0)
+ if online_time >= now_time:
+ return 1
+ else:
+ return 0
+
+
+'''
+# it is so long and long-working shit that i don't want to re-write it. I suppose, we have something better
+
+def count_online(id):
+ amount = 0
+ online = 0
+ your_group = vk_api.groups.getById(group_id=id, fields='members_count')
+ number_of_them = your_group[0]['members_count']
+ if number_of_them <= 10000:
+ done = 0
+ while done < number_of_them:
+ group_members_ids = get_group_followers(id, done)
+ for x in group_members_ids:
+ last = get_user_last_seen(str(x))
+ if last is not None:
+ amount += 1
+ delta_last = delta_time(last)
+ online += is_online(delta_last)
+ done += 1000
+ if amount == 0:
+ return -1
+ else:
+ return amount, online
+ else:
+ piece = number_of_them // 100
+ for i in range(piece):
+ group_members_ids = get_group_followers(id, 100 * i)
+ x = random.randint(0, 100)
+ last = get_user_last_seen(str(group_members_ids[x]))
+ if last is not None:
+ amount += 1
+ delta_last = approximate_time(last)
+ online += is_online(delta_last)
+ number_of_them -= piece * 100
+ group_members_ids = get_group_followers(id, piece * 100)
+ x = random.randint(0, number_of_them - 1)
+ last = get_user_last_seen(str(group_members_ids[x]))
+ if last is not None:
+ amount += 1
+ delta_last = approximate_time(last)
+ online += is_online(delta_last)
+ return amount, online
+'''
+
+analyse_group_id = input()
+frequency = input()
+if frequency == "as frequently as possible":
+ frequency_number = 0
+elif frequency.isdigit():
+ frequency_number = int(frequency)
+else:
+ print("Error")
+ exit()
+n = int(input())
+
+group = Group(analyse_group_id, frequency_number)
+
+t0 = time.time()
+all_members, online_members = group.count_online_proportion()
+percent = online_members / all_members * 100
+percent = math.ceil(percent)
+
+# print("In this group i have got information about " + str(all_members) + " users")
+
+# print("Online percent in " + analyse_group_id + " is " + str(percent) + "%")
+t0 = time.time() - t0
+if t0 >= group.frequency * 60:
+ print("Sorry, I can't work so fastly, so I will count statistics as fastly as i can")
+ for i in range(n):
+ current_time = datetime.datetime.now()
+
+ all_members, online_members = group.count_online_proportion()
+ percent = online_members / all_members * 100
+ percent = math.ceil(percent)
+
+ print("Time: " + str(current_time) + ". Online percent in " + analyse_group_id + " is " + str(percent) + "%")
+ print("____________________________________________________________________________________________________")
+else:
+ for i in range(n):
+ current_time = datetime.datetime.now()
+ t0 = time.time()
+
+ all_members, online_members = group.count_online_proportion()
+ percent = online_members / all_members * 100
+ percent = math.ceil(percent)
+
+ print("Time: " + str(current_time) + ". Online percent in " + analyse_group_id + " is " + str(percent) + "%")
+ print("____________________________________________________________________________________________________")
+ t0 = time.time() - t0
+ time.sleep(group.frequency * 60 - t0)
+exit()
diff --git a/messages_test.py b/messages_test.py
new file mode 100644
index 0000000..e1adbaa
--- /dev/null
+++ b/messages_test.py
@@ -0,0 +1,560 @@
+import vk
+import datetime
+import requests
+import time
+import random
+import math
+from collections import deque
+
+
+class Group:
+ def __init__(self, group_id, freq, master_id):
+ """
+ group_id: the group to analyse
+ master_id: id of the user who gave the task
+ frequency: how many minutes should pass between two adjoining analyses
+ analyses_per_day: daily amount of analyses
+ percents: online percents in each 'moment' of the week (not more than 672 moments)
+ archive: old data, we need this to delete old info whe 4 weeks pass
+ number: technical moment. Actually, first three weeks are special: to count the average meaning we need not to
+ divide by 4, but to divide by the number - spacial for each array cell.
+ Just because we don't have enough information yet!!
+ index_to_date: in the storage we keep the moment of time as a code - gust an integer number. But the user
+ would prefer 'Mon, 00:00: 30%' to '0: 30%'. That's why we need this array
+ """
+ self.group_id = group_id
+ self.begin = datetime.datetime.now()
+ self.master_id = master_id
+ self.frequency = datetime.timedelta(hours=freq//60, minutes=(freq % 60))
+ #making period in datetime format
+ self.analyses_per_day = 1440 // freq
+ analyses_per_week = self.analyses_per_day * 7
+ #self.percents = [0 for i in range(analyses_per_week)]
+ self.avg_percents = {}
+ for i in range(analyses_per_week):
+ self.avg_percents[self.begin + self.frequency * i] = 0
+ self.archive = [[0, 0, 0, 0] for i in range(analyses_per_week)]
+ self.number = [0 for i in range(analyses_per_week)]
+ self.index_to_date = []
+ for i in range(analyses_per_week):
+ week_day = i // self.analyses_per_day
+ time_index = i % self.analyses_per_day * self.frequency
+ hour_index = time_index // 60
+ minute_index = time_index % 60
+ s = days_of_the_week[week_day] + ", " + str(hour_index) + ":" + str(minute_index)
+ if minute_index == 0:
+ s += '0'
+ self.index_to_date.append(s)
+
+ def count_online_proportion(self):
+ """
+ gets the number of members online, ant the total number of members, not counting those,
+ whose info is not is not available
+ :param self: the object of the class Group. We need the group id
+ :return: two integers - the number of members with available online-information and the number of members online
+ """
+ amount = 0
+ online = 0
+ your_group_info = vk_api.groups.getById(group_id=self.group_id, fields='members_count')
+ number_of_members = your_group_info[0]['members_count']
+ one_more_number_of_members = number_of_members
+ already_count = 0
+ while already_count < number_of_members:
+ 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:
+ online += x['online']
+ else:
+ one_more_number_of_members -= 1
+ already_count += 1000
+ if one_more_number_of_members == 0:
+ return -1, -1
+ else:
+ return one_more_number_of_members, online
+
+ def group_analyse(self):
+ """
+ counts the online percent
+ :return:
+ """
+ t0 = time.time()
+
+ all_members, online_members = self.count_online_proportion()
+ percent = online_members / all_members * 100
+ percent = math.ceil(percent)
+
+ t0 = time.time() - t0
+ return t0, percent
+
+ def update_data(self, new_one, cell_to_update):
+ if self.number[cell_to_update] >= 4:
+ self.percents[cell_to_update] *= 4
+ self.percents[cell_to_update] = self.percents[cell_to_update] - self.archive[cell_to_update][0] + new_one
+ self.percents[cell_to_update] /= 4
+ else:
+ self.percents[cell_to_update] *= self.number[cell_to_update]
+ self.percents[cell_to_update] = self.percents[cell_to_update] + new_one
+ self.number[cell_to_update] += 1
+ self.percents[cell_to_update] /= self.number[cell_to_update]
+ for j in range(3):
+ self.archive[cell_to_update][j] = self.archive[cell_to_update][j + 1]
+ self.archive[cell_to_update][3] = new_one
+
+ def recommend_day(self, count):
+ day = datetime.datetime.now().weekday()
+ start = day * self.analyses_per_day
+ finish = (day + 1) * self.analyses_per_day
+ recommend_message = "Today the best time was "
+ max_online, best_time = 0, 0
+ for i in range(start, finish):
+ if self.percents[i] > max_online:
+ max_online = self.percents[i]
+ best_time = i
+ recommend_message += self.index_to_date[best_time] + ": " + str(max_online) + "%"
+ vk_api2.messages.send(user_id=self.master_id, message=recommend_message, random_id=count)
+ return count + 1
+
+ def recommend_week(self, count):
+ recommend_message = "This week the best time was "
+ max_online, best_time, max_average_during_the_day, best_day = 0, 0, 0, 0
+ for j in range(7):
+ average = 0
+ for i in range(self.analyses_per_day * j, self.analyses_per_day * (j + 1)):
+ average += self.percents[i]
+ if self.percents[i] > max_online:
+ max_online = self.percents[i]
+ best_time = i
+ if average > max_average_during_the_day:
+ max_average_during_the_day = average
+ best_day = j
+ max_average_during_the_day /= self.analyses_per_day
+ recommend_message += self.index_to_date[best_time] + ": " + str(max_online) + "%"
+ vk_api2.messages.send(user_id=self.master_id, message=recommend_message, random_id=count)
+ recommend_message = "This week, the day with the biggest average online percent was " + \
+ days_of_the_week[best_day] + ": " + str(max_average_during_the_day) + "%"
+ vk_api2.messages.send(user_id=self.master_id, message=recommend_message, random_id=(count + 1))
+ return count + 2
+
+ def work_and_print(self, count):
+ """
+ updates data and sends current online percent
+ :param count - is needed to send messages:
+ :return:
+ """
+ week_day = datetime.datetime.now().weekday()
+ t = datetime.datetime.now()
+ array_cell = self.analyses_per_day * week_day + (t.hour * 60 + t.minute) // self.frequency
+ start_time, percent = self.group_analyse()
+ self.update_data(percent, array_cell)
+ string = "Online percent in " + self.group_id + " is " + str(percent) + "%"
+ vk_api2.messages.send(user_id=self.master_id, message=string, random_id=count)
+ return count + 1
+
+ '''
+ def group_analyse_console(self):
+ t0 = time.time()
+ all_members, online_members = self.count_online_proportion()
+ percent = online_members / all_members * 100
+ percent = math.ceil(percent)
+
+ t0 = time.time() - t0
+ if t0 >= self.frequency * 60:
+ print("Sorry, I can't work so fast, so I will count statistics as fast as i can")
+ while True:
+ # message, user_id = get_message(my_number_group_id)
+ current_time = datetime.datetime.now()
+
+ all_members, online_members = self.count_online_proportion()
+ percent = online_members / all_members * 100
+ percent = math.ceil(percent)
+
+ print("Time: " + str(current_time) + ". Online percent in " + self.group_id + " is " + str(
+ percent) + "%")
+ print(
+ "_____________________________________________________________________________________________")
+ else:
+ while True:
+ current_time = datetime.datetime.now()
+ t0 = time.time()
+
+ all_members, online_members = self.count_online_proportion()
+ percent = online_members / all_members * 100
+ percent = math.ceil(percent)
+
+ print("Time: " + str(current_time) + ". Online percent in " + self.group_id + " is " + str(
+ percent) + "%")
+ print(
+ "_____________________________________________________________________________________________")
+ t0 = time.time() - t0
+ time.sleep(self.frequency * 60 - t0)
+ '''
+
+ def repeat_the_process(self, count, next_time):
+ """
+ :param count - is needed to send messages to the user:
+ :param next_time - when to analyse again:
+ :return:
+ """
+ next_time = count_new_time(next_time, self.frequency)
+ count = self.work_and_print(count)
+ return next_time, count
+
+ def count_times(self, count):
+ """
+ This function runs in the very beginning. It counts when to start analysing and when to give recommendations
+ """
+ current_time = datetime.datetime.now()
+ minutes_now = current_time.minute + current_time.hour * 60
+ round_current_time = current_time.replace(microsecond=0, second=0)
+ next_time = count_new_time(round_current_time, self.frequency - minutes_now % self.frequency)
+ next_recommend = current_time.replace(microsecond=0, second=0, minute=0, hour=0)
+ next_recommend = count_new_time(next_recommend, 1440)
+ ok_message = "OK! Starting in " + str(self.frequency - minutes_now % self.frequency) + " minutes!"
+ vk_api2.messages.send(user_id=self.master_id, message=ok_message, random_id=count)
+ return count + 1, next_time, next_recommend
+
+
+token = "65e6efa565e6efa565e6efa54f6593fb1f665e665e6efa53a5c6937a4636b3416a8bd92"
+group_token = "17e681fbe171945431a04f1abc752d41ff888698288abf74124de4e782c67f36e76484601991870f56b7a"
+analyse_group_id = 'memkn'
+my_group_id = 'memkn_funclub'
+my_number_group_id = 200698416
+
+session1 = vk.AuthSession(access_token=token)
+session2 = vk.AuthSession(access_token=group_token)
+vk_api = vk.API(session1, v=5.92)
+vk_api2 = vk.API(session2, v=5.92)
+
+month_length = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
+days_of_the_week = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
+
+
+def get_user_last_seen(profile_id):
+ """
+ shows when user was online
+ :param profile_id:
+ :return time:
+ """
+ value = vk_api.users.get(user_ids=profile_id, fields='last_seen')
+ if 'last_seen' not in value[0]:
+ return None
+ online_time = datetime.datetime.fromtimestamp(value[0]['last_seen']['time'])
+ return online_time
+
+
+def get_group_followers(group_page_id, done):
+ """
+ gets the list of the group members, not more than 1000
+ :param group_page_id:
+ :param done: shows the indent
+ :return list of members' ids:
+ """
+ value = vk_api.groups.getMembers(group_id=group_page_id, offset=done)
+ followers_id = []
+ for user in value['items']:
+ followers_id.append(user)
+ return followers_id
+
+
+def approximate_time(real_time):
+ """
+ gets time user was last seen and adds two minutes
+ :param real_time: time user was last seen online
+ :return: real_time plus delta min
+ """
+
+ hours = real_time.hour
+ days = real_time.day
+ months = real_time.month
+ years = real_time.year
+ # обработка редких случаев
+ if years % 4 == 0 and years % 100 != 0 or years % 400 == 0:
+ month_length[1] += 1
+ if real_time.minute >= 58:
+ hours = real_time.hour + 1
+ if hours == 24:
+ hours = 0
+ days += 1
+ if days > month_length[months - 1]:
+ days = 1
+ months += 1
+ if months > 12:
+ months = 1
+ years += 1
+
+ approximate_online_time = real_time.replace(minute=(real_time.minute + 2) % 60,
+ hour=hours, day=days, month=months, year=years)
+ return approximate_online_time
+
+
+def is_online(online_time):
+ # just checks if the user is online or not, returns 0 or 1
+
+ now_time = datetime.datetime.now()
+ now_time = now_time.replace(microsecond=0)
+ if online_time >= now_time:
+ return 1
+ else:
+ return 0
+
+
+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
+ (server=server_, key=key_, ts=ts_)).json()
+ if len(response['updates']) > 0:
+ return response['updates'][0]['object']['body'], response['updates'][0]['object']['user_id'], response['ts']
+ return "", -1, response['ts']
+
+
+def count_new_time(time_now, period):
+ # gets the time, when the counting stats process was last started and returns time, when to start the process again.
+ # just adds period.
+ d_minutes = period
+ d_hours = 0
+ if period > 59:
+ d_minutes = period % 60
+ d_hours = period // 60
+ minutes = time_now.minute
+ hours = time_now.hour
+ days = time_now.day
+ months = time_now.month
+ years = time_now.year
+ if years % 4 == 0 and years % 100 != 0 or years % 400 == 0:
+ month_length[1] += 1
+
+ minutes = (minutes + d_minutes) % 60
+ if minutes < time_now.minute:
+ hours += 1
+ hours += d_hours
+ if hours > 23:
+ hours %= 24
+ days += 1
+ if days > month_length[time_now.month - 1]:
+ days = 1
+ months += 1
+ if months > 12:
+ months = 1
+ years += 1
+ month_length[1] -= 1
+
+ new_time = time_now.replace(minute=minutes, hour=hours, day=days, month=months, year=years)
+ return new_time
+
+
+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: ...
+ if message == "stop" or message == "Stop":
+ return 1, "", -1
+ if message == "":
+ return 0, "", -1
+ if message == "lsr_memkn6":
+ return 2, "", -1
+ if message.count(';') == 1:
+ index = message.find(';')
+ if message[0: 9].strip() != "group_id:" or message[index + 1:].count('d') != 1 \
+ or message[index + 1: message[index + 1:].find('d') + 3 + index].strip() != "period:":
+ return -1, "", -1
+ period = message[message[index + 1:].find('d') + 3 + index:].strip()
+ group = message[9: index].strip()
+ if not check_for_correct(group):
+ return 5, "", -1
+ if not period.isdigit():
+ return -1, "", -1
+ elif int(period) < 60 and 60 % int(period) != 0 or int(period) < 15 or 1440 % int(period) != 0:
+ return 6, "", -1
+ else:
+ return 3, group, int(period)
+ string1 = message[0: 6]
+ string2 = message[0: 5]
+ if string1 == "Привет" or string1 == "привет" or string2 == "Hello" or string2 == "hello":
+ return 4, "", -1
+ if message == "Recommend: day" or message == "recommend: day":
+ return 7, "", -1
+ if message == "Recommend: week" or message == "recommend: week":
+ return 8, "", -1
+ return -1, "", -1
+
+
+def switch_off(count, current_user_id):
+ # switches the bot off, the special password is needed
+ vk_api2.messages.send(user_id=current_user_id, message="Goodbye!", random_id=count)
+ return 0, count + 1
+
+
+def incorrect_id(count, current_user_id):
+ # informs about the mistake
+ vk_api2.messages.send(user_id=current_user_id, message="Wrong group id!", random_id=count)
+ return count + 1
+
+
+def incorrect_period_value(count, current_user_id):
+ # informs about the mistake
+ s = "Period should be not less than 15 and should divide 1440!"
+ vk_api2.messages.send(user_id=current_user_id, message=s, random_id=count)
+ return count + 1
+
+
+def cancel_the_task(have_a_task, current_user_id, count, master_id):
+ # Cancels the current task, it is is asked by the user who gave the task earlier
+ if have_a_task and current_user_id == master_id:
+ vk_api2.messages.send(user_id=current_user_id, message="Your task is cancelled!", random_id=count)
+ return 0, count + 1
+ 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=count)
+ return 1, count + 1
+ else:
+ vk_api2.messages.send(user_id=current_user_id, message="Я сделал ничего, не благодари!",
+ random_id=count)
+ return 0, count + 1
+
+
+def say_hello(count, current_user_id):
+ # sends a message 'Ну привет, ....'
+ string = "Ну привет, "
+ 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=count)
+ return count + 1
+
+
+def instruction_message(count, current_user_id):
+ # sends the message if user did send us the message of an unknown format
+ string = "Maaaaaaan! I don't understand you... \n"
+ string += "You can SAY HELLO: your message should start with 'hello' or 'привет'; \n"
+ string += "You can give me a task in such a way: 'group_id: 'the_group_id'; period: 'period'. \n"
+ string += "Period should be pretty and not too small) \n"
+ string += "You can cancel YOUR task: just send 'stop' \n"
+ string += "Have a good day!!\n"
+ # vk_api2.messages.send(user_id=current_user_id, sticker_id=8616, random_id=count)
+ vk_api2.messages.send(user_id=current_user_id, message=string, attachment="photo-200698416_457239021",
+ random_id=(count + 1))
+ return count + 2
+
+
+def first_process(count, master_id, group):
+ t0 = time.time()
+ time_start = datetime.datetime.now()
+ next_time = count_new_time(time_start, group.frequency)
+ # next_minutes - when to count again
+ count = group.work_and_print(count, master_id)
+ t0 = time.time() - t0
+ # if analysing took more time than the period:
+ if t0 > group.frequency * 60:
+ vk_api2.messages.send(user_id=master_id, message="Can't work so fast((",
+ random_id=count)
+ next_time = datetime.datetime.now()
+ group.frequency = 0
+ return next_time, count + 1
+ return next_time, count
+
+
+def check_for_correct(group_id):
+ try:
+ your_group_info = vk_api.groups.getById(group_id=group_id, fields='members_count', count=1)
+ except vk.exceptions.VkAPIError:
+ return 0
+ return 1
+
+
+def not_available(count, current_user_id):
+ vk_api2.messages.send(user_id=current_user_id, message="Not available now!", random_id=count)
+ vk_api2.messages.send(user_id=current_user_id, sticker_id=4331, random_id=(count + 1))
+ return count + 2
+
+
+# starts working, gives default values to some variables
+
+some = vk_api2.groups.getLongPollServer(group_id=my_number_group_id)
+current_ts = some['ts']
+server = some['server']
+key = some['key']
+change_server = count_new_time(datetime.datetime.now().replace(microsecond=0, second=0), 50)
+message = ""
+run = 1
+count = 10000
+master_id = -1
+have_a_task = 0
+next_recommend = datetime.datetime.now()
+next_time = datetime.datetime.now()
+
+# the end of 'initialization' block
+
+while run:
+ # wait for new requests
+ message, current_user_id, current_ts = get_message(my_number_group_id, server, current_ts, key)
+
+ # if it is time to change LongPollServer
+ if datetime.datetime.now() >= change_server:
+ some = vk_api2.groups.getLongPollServer(group_id=my_number_group_id)
+ current_ts = some['ts']
+ server = some['server']
+ key = some['key']
+ change_server = count_new_time(change_server, 50)
+
+ # chek if it is time to analyse again
+ if have_a_task and datetime.datetime.now() >= next_time:
+ next_time, count = group.repeat_the_process(count, next_time)
+
+ # check if it is time to give recommendations
+ if have_a_task and datetime.datetime.now() >= next_recommend:
+ count = group.recommend_day(count)
+ if datetime.datetime.now().weekday() == 0:
+ count = group.recommend_week(count)
+ next_recommend = count_new_time(next_recommend, 1440)
+
+ code, analyse_group_id, frequency_number = process_input_message(message)
+
+ if code == 3:
+ # this code means that user gave a correct task
+ if not have_a_task or current_user_id == master_id:
+ '''
+ if the bot is free or is working on the task of the same user, who is giving a new one. In this case
+ bot receives a new task and forgets about the old one if it did exist
+ '''
+ have_a_task = 1
+ # group initialising block
+ group = Group(analyse_group_id, frequency_number, current_user_id)
+ master_id = group.master_id
+ # counting time when to start and when to give a new recommendation
+ count, next_time, next_recommend = group.count_times(count)
+ else:
+ # in the case when the user wants to give a new task while bot is already working on the OTHER user's task.
+ count = not_available(count, current_user_id)
+ elif code == 2:
+ # if the bot has received a secret password which switches it off
+ run, count = switch_off(count, current_user_id)
+ elif code == 1:
+ # if the user WHO GAVE A TASK decided to cancel it with a 'stop' or 'Stop' command
+ if have_a_task:
+ del group
+ have_a_task, count = cancel_the_task(have_a_task, current_user_id, count, master_id)
+ elif code == 4:
+ # greeting
+ count = say_hello(count, current_user_id)
+ elif code == -1:
+ # unknown message
+ count = instruction_message(count, current_user_id)
+ elif code == 5:
+ # if the group does not exist
+ count = incorrect_id(count, current_user_id)
+ elif code == 6:
+ '''
+ if the period doesn't divide 60 (if it is less than 60) or if it doesn't divide 1440
+ (number of minutes in a day)
+ '''
+ count = incorrect_period_value(count, current_user_id)
+ elif code == 7:
+ # If the user needs today's best online percent and the time it happened
+ if have_a_task and current_user_id == master_id:
+ count = group.recommend_day(count)
+ else:
+ count = not_available(count, current_user_id)
+ elif code == 8:
+ # If the user needs week's best online percent and the time it happened
+ if have_a_task and current_user_id == master_id:
+ count = group.recommend_week(count)
+ else:
+ count = not_available(count, current_user_id)
diff --git a/upload.py b/upload.py
new file mode 100644
index 0000000..5f70bee
--- /dev/null
+++ b/upload.py
@@ -0,0 +1,39 @@
+import vk
+import datetime
+import time
+import random
+import math
+import requests
+import json
+
+our_group_id = 200698416
+token = "65e6efa565e6efa565e6efa54f6593fb1f665e665e6efa53a5c6937a4636b3416a8bd92"
+group_token = "17e681fbe171945431a04f1abc752d41ff888698288abf74124de4e782c67f36e76484601991870f56b7a"
+analyse_group_id = 'memkn'
+new_token = "812c2975fc2ac0785252d97e8b5011f45e873a00dfb98b15299aec060ff7b890d06c4822feab0626e198c"
+session1 = vk.AuthSession(access_token=new_token)
+vk_api = vk.API(session1, v=5.92)
+album_id = 278041850
+month_length = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
+version = '5.95'
+
+
+def upload_picture(picture_path):
+ 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 result
+
+
+upload_picture("21.png")