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")