diff --git a/README.md b/README.md index ca1f569..59eb315 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,7 @@ # Мой личный бот на python для ВК #### от dan63047 - Этот бот просто отвечает на поддержваемые запросы в переписке с сообществом. Был написан мною в целях изучения python - -Для того, что бы бот работал, сначала нужно создать в папке бота файл `config.py`, который должен иметь следующее содержание: - -```python -import vk_api -import pyowm -vk = vk_api.VkApi(token="vk_group_access_token") # Токен сообщества в ВК -vk_mda = vk_api.VkApi(token="vk_app_service_key") # Костыль для того, чтобы работал метод photos.get -group_id = 190322075 # Цифровой id вашего сообщества -album_for_command = 269199619 # Цифровой id альбома для команды !image -owner_id = 276193568 # Ваш цифровой id -owm = pyowm.OWM('OpenWeather_api_key', language='ru') # Ключ OpenWeather API для функции погоды -``` - -Установите в группе версию Long Poll API на 5.103 - -Запустите `dan63047bot.py`, что бы бот начал слушать сервер - # Функции бота - Чтобы воспользоваться функциями бота необходимо отправить команду и в некоторых случаях агрумент. Все команды начинаются с восклицательного знака * **!h, !help** — бот отправляет список команд и их краткое описание, а так же дату последнего обновления и ссылку на этот репозиторий @@ -44,16 +24,57 @@ owm = pyowm.OWM('OpenWeather_api_key', language='ru') # Ключ OpenWeather API * **!access *all/owner*** — позволяет в беседе установить уровень доступа к командам *!midnight*, *!subscribe* и *!debug*. *all* - все могут пользоваться. *owner* - только вы. Доступно только вам * **!turnoff** — даёт боту команду на выключение. Доступно только вам * **!admin_mode** — если чат, в которой активируется команда, является беседой и в ней у бота есть полномочия администратора, то бот переходит в режим модерации. Пока что он может только кикать людей за @all и @online. Введите ещё раз, чтобы выключить режим модерации. Доступно только вам +# Установка и запуск бота +## Как это делал я +Здесь я расскажу каким образом я запустил этого бота. Работает он у меня на [pythonanywhere](https://www.pythonanywhere.com/), причём аккаунт платный, ибо он использует MySQL базу данных, а также работает как Always-on task. Можно, конечно, не использовать БД и запускать бота в консоли, но он будет сыпать ошибками из-за тесной связи с этой самой БД, не будет сохранять данные о своей работе, да ещё и pythonanywhere выключит вашу консоль, если вы долго не будете посещать её. +Итак, заходим на pythonanywhere, входим или регистрируемся и покупаем самый дешёвый тариф Hacker за 5 баксов в месяц, этого должно хватить. + +Создаём консоль на bash и прописываем: + +`git clone https://github.com/dan63047/dan63047pythonbot.git` + +Эта команда создаст папку `dan63047pythonbot` и поместит туда бота. + +Теперь заходим в директорию бота (`cd dan63047pythonbot/`) и устанавливаем необходимые библиотеки: + +`pip3 install vk-api pyowm Wikipedia-API PyMySQL --user` + +Эта команда установит все необходимые библиотеки для работы бота. + +Теперь создадим базу данных, с которой бот будет работать. На том же pythonanywhere тыкаем на *Databases* в шапке сайта. Создаём пароль для вашей базы данных. По умолчанию будет создана база данных с названием `your_nickname$default`, но вы можете создать БД со своим названием. + +Настроим ваше сообщество для работы с ботом: заходим в *Управление -> Работа с API*. Здесь создаём токен сообщества с правами доступа к сообщениям, фотографиям и стене. Идем в *Long Poll API*, включаем его и ставим последнюю доступную версию (на момент написания этой версии README это 5.108). В *Типы событий* должны стоять галочки на следующих событиях: Входящее сообщение, Запрет на получение, Добавление записи на стене. + +Разберёмся с костылём для метода `photos.get`: Идем на `vk.com/dev`, нажимаем на *Мои приложения* и кликаем по *Создать приложение*. Новое приложение может называться как угодно, от него нам необходимо всего лишь сервисный ключ доступа, который можно найти, если нажать на *Настройки* + +Если вы планируете использовать команду !weather, сделайте следующее: +Перейдите по `openweathermap.org`, пройдите там регистрацию и создайте API ключ + +Создадим файл конфигурации для бота: В pythonanywhere тыкаем на *Files*, переходим в директорию *dan63047pythonbot* и создаём там новый фаил с названием `config.py`. В нём должно быть написано следующее: +```python +import vk_api +import pyowm +vk = vk_api.VkApi(token="vk_group_token") # Токен сообщества +vk_mda = vk_api.VkApi(token="vk_service_token") # Сервисный ключ доступа +group_id = 190322075 # Цифровой ид группы +album_for_command = 269199619 # Цифровой ид альбома для команды !image +owner_id = 276193568 # Цифровой ид вашей страницы вк, чтобы вы могли управлять ботом в переписке +owm = pyowm.OWM('openweathermap_api_key', language='ru') # Ключ OpenWeather API +mysql_host = 'pythonanywhere_nickname.mysql.pythonanywhere-services.com' # ссылка на хост БД. Вместо pythonanywhere_nickname должен быть ваш никнейм на pythonanywhere +mysql_user = 'pythonanywhere_nickname' # Ваш никнейм на pythonanywhere +mysql_pass = 'qwerty123' # Пароль, созданный вами для БД +mysql_db = 'pythonanywhere_nickname$default' # Название вашей БД. Вместо pythonanywhere_nickname должен быть ваш никнейм на pythonanywhere. Так же вместо default может быть ваше название БД +``` +И, наконец, запуск бота: в pythonanywhere тыкаем на *Tasks*, создаём и запускаем в *Always-on tasks* задачу `python3.8 /home/pythonanywhere_nickname/dan63047pythonbot/dan63047bot.py`, где вместо pythonanywhere_nickname должен быть ваш никнейм на pythonanywhere. После небольшого тупления pythonanywhere запустит вашего бота и он будет работать долго и счастливо. +## Другие варианты запуска бота +Скорее всего, вы можете найти где-нибудь VPS с базами данных или огранизовать всё на своём компьютере, но об этом я ничего не знаю. Напишите мне, чтобы рассказать, как у вас полностью получилось заставить работать бота. # Использованные библиотеки - * [vk_api](https://github.com/python273/vk_api) — модуль для создания скриптов для социальной сети Вконтакте * [pyowm](https://github.com/csparpa/pyowm) — модуль для получения погоды через OpenWeather API * [Wikipedia-API](https://github.com/martin-majlis/Wikipedia-API) — модуль для получения статей из Wikipedia -* [Pillow](https://github.com/python-pillow/Pillow) — Python Imaging Library fork - +* [PyMySQL](https://github.com/PyMySQL/PyMySQL/) — Pure Python MySQL Client # Дополнительно - С ботом можно пообщаться [здесь](https://vk.com/im?sel=-190322075) Автор бота: [Даниил Михайлов](https://vk.com/dan63047) diff --git a/dan63047bot.py b/dan63047bot.py index 16b3714..a0dc215 100644 --- a/dan63047bot.py +++ b/dan63047bot.py @@ -7,58 +7,22 @@ import pyowm import random import json import threading +import pymysql +from pymysql.cursors import DictCursor import wikipediaapi as wiki from collections import deque - -from PIL import Image - -from config import vk, owm, vk_mda, group_id, album_for_command, owner_id +from config import vk, owm, vk_mda, group_id, album_for_command, owner_id, mysql_host, mysql_pass, mysql_user, mysql_db from vk_api.bot_longpoll import VkBotLongPoll, VkBotEventType -bot = {} -users = {} -debug_array = {'vk_warnings': 0, 'logger_warnings': 0, 'start_time': 0, 'messages_get': 0, 'messages_answered': 0} -errors_array = {"access": "Отказано в доступе", "miss_argument": "Отсуствует аргумент"} - root_logger = logging.getLogger() root_logger.setLevel(logging.INFO) -handler = logging.FileHandler('bot.log', 'w', 'utf-8') +try: + handler = logging.FileHandler(f'logs/bot_log{str(datetime.datetime.now())}.log', 'w', 'utf-8') +except: + handler = logging.FileHandler('bot.log', 'w', 'utf-8') handler.setFormatter(logging.Formatter('[%(asctime)s][%(levelname)s] %(message)s')) root_logger.addHandler(handler) -longpoll = VkBotLongPoll(vk, group_id) - - -def update_users_json(massive): - with open("users.json", 'w') as write_file: - data = massive - json.dump(data, write_file) - write_file.close() - - -def load_users(): - try: - with open("users.json", 'r') as users_file: - users_not_json = json.load(users_file) - for i in users_not_json: - users[i] = users_not_json[i] - users_file.close() - for i in users: - if "midnight" not in users[i]: - users[i]["midnight"] = False - if 'await' not in users[i]: - users[i]['await'] = None - if 'access' not in users[i]: - users[i]['access'] = 1 - if 'new_post' not in users[i]: - users[i]['new_post'] = False - if 'admin_mode' not in users[i]: - users[i]['admin_mode'] = False - bot[int(i)] = VkBot(i, users[i]["midnight"], users[i]['await'], int(users[i]['access']), users[i]['new_post'], users[i]['admin_mode']) - except Exception as lol: - log(True, f"Problem with users.json: {str(lol)}") - - def log(warning, text): if warning: logging.warning(text) @@ -68,6 +32,140 @@ def log(warning, text): logging.info(text) print("[" + str(datetime.datetime.now()) + "] " + text) +log(False, "Script started") + +bot = {} +debug_array = {'vk_warnings': 0, 'logger_warnings': 0, 'start_time': 0, 'messages_get': 0, 'messages_answered': 0} +errors_array = {"access": "Отказано в доступе", "miss_argument": "Отсуствует аргумент"} + +longpoll = VkBotLongPoll(vk, group_id) + +class MySQL_worker(): + + def __init__(self): + try: + self._CON = pymysql.connect( + host= mysql_host, + user= mysql_user, + password= mysql_pass, + db= mysql_db, + charset='utf8mb4', + cursorclass=DictCursor + ) + cur = self._CON.cursor() + try: + cur.execute("SELECT * FROM bot_users") + except: + cur.execute("CREATE TABLE bot_users ( id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, chat_id INT UNSIGNED, awaiting VARCHAR(128), access TINYINT, midnight BOOL, new_post BOOL, admin_mode BOOL, game_wins INT UNSIGNED, game_defeats INT UNSIGNED, game_draws INT UNSIGNED)") + try: + cur.execute("SELECT * FROM tasks") + except: + cur.execute("CREATE TABLE tasks (id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, chat_id INT UNSIGNED, time INT UNSIGNED, task TEXT)") + cur.close() + log(False, f"Database connection established") + except Exception as e: + log(True, f"Unable to connect to database: {str(e)}") + + def set_new_user(self, peer_id, midnight=False, awaiting=None, access=1, new_post=False, admin_mode=False, game_wins=0, game_defeats=0, game_draws=0): + try: + cur = self._CON.cursor() + cur.execute("INSERT INTO bot_users (chat_id, awaiting, access, midnight, new_post, admin_mode, game_wins, game_defeats, game_draws) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)", (peer_id, awaiting, access, midnight, new_post, admin_mode, game_wins, game_defeats, game_draws)) + self._CON.commit() + cur.close() + except Exception as e: + log(True, f"Unable to add new user in database: {str(e)}") + + def get_all_users(self): + try: + cur = self._CON.cursor() + cur.execute("SELECT * FROM bot_users") + result = cur.fetchall() + cur.close() + return result + except Exception as e: + log(True, f"Unable to load user from database: {str(e)}") + + def get_from_users(self, from_id): + try: + cur = self._CON.cursor() + cur.execute("SELECT * FROM bot_users WHERE chat_id = %s", (from_id)) + result = cur.fetchall() + cur.close() + return result + except Exception as e: + log(True, f"Unable to load user from database: {str(e)}") + + def update_user(self, chat_id, thing, new_value): + try: + cur = self._CON.cursor() + cur.execute(f"UPDATE bot_users SET {thing} = %s WHERE bot_users.chat_id = %s;", (new_value, chat_id)) + self._CON.commit() + cur.close() + except Exception as e: + log(True, f"Unable to update info about user in database: {str(e)}") + + def delete_user(self, chat_id): + try: + cur = self._CON.cursor() + cur.execute("DELETE FROM bot_users WHERE chat_id = %s", (chat_id)) + self._CON.commit() + cur.close() + return True + except Exception as e: + log(True, f"Unable to delete user from database: {str(e)}") + return False + + def get_all_tasks(self): + try: + cur = self._CON.cursor() + cur.execute("SELECT * FROM tasks") + result = cur.fetchall() + cur.close() + return result + except Exception as e: + log(True, f"Unable to load tasks from database: {str(e)}") + + def set_new_task(self, chat_id, time, task): + try: + cur = self._CON.cursor() + cur.execute("INSERT INTO tasks (chat_id, time, task) VALUES (%s, %s, %s)", (chat_id, time, task)) + self._CON.commit() + cur.close() + except Exception as e: + log(True, f"Unable to add new task in database: {str(e)}") + + def get_from_tasks(self, from_id): + try: + cur = self._CON.cursor() + cur.execute("SELECT * FROM tasks WHERE chat_id = %s", (from_id)) + result = cur.fetchall() + cur.close() + return result + except Exception as e: + log(True, f"Unable to load tasks from database: {str(e)}") + + def delete_task(self, from_id, task): + try: + cur = self._CON.cursor() + cur.execute("DELETE FROM tasks WHERE chat_id = %s AND task = %s", (from_id, task)) + self._CON.commit() + cur.close() + return True + except Exception as e: + log(True, f"Unable to delete task from database: {str(e)}") + return False + +db = MySQL_worker() + +def load_users(): + try: + log(False, "Reading database") + get_info = db.get_all_users() + for i in get_info: + bot[int(i['chat_id'])] = VkBot(i['chat_id'], i['midnight'], i['awaiting'], int(i['access']), i['new_post'], i['admin_mode']) + except Exception as lol: + log(True, f"Problem with creating objects: {str(lol)}") + def toFixed(numObj, digits=0): return f"{numObj:.{digits}f}" @@ -86,6 +184,9 @@ class MyVkLongPoll(VkBotLongPoll): time.sleep(15) continue +def create_new_bot_object(chat_id): + bot[chat_id] = VkBot(chat_id) + db.set_new_user(chat_id) def get_weather(place): try: @@ -123,7 +224,7 @@ class VkBot: "!echo", "!game", "!debug", "!midnight", "!access", "!turnoff", "!reminder", "!subscribe", "!random", "!admin_mode"] def __str__(self): - return f"[BOT_{str(self._CHAT_ID)}] a: {str(self._ACCESS_LEVEL)}, mn: {str(self._MIDNIGHT_EVENT)}, await: {str(self._AWAITING_INPUT_MODE)}, tasks: {len(users[self._CHAT_ID]['tasks'])}, sub: {str(self._NEW_POST)}, adm: {str(self._ADMIN_MODE)}" + return f"[BOT_{str(self._CHAT_ID)}] a: {str(self._ACCESS_LEVEL)}, mn: {str(self._MIDNIGHT_EVENT)}, await: {str(self._AWAITING_INPUT_MODE)}, sub: {str(self._NEW_POST)}, adm: {str(self._ADMIN_MODE)}" def __del__(self): log(False, f"[BOT_{str(self._CHAT_ID)}] Bot-object has been deleted") @@ -170,7 +271,7 @@ class VkBot: self.change_await('reminder time') elif self._AWAITING_INPUT_MODE == 'reminder time': if self.reminder(message, "time"): - self.send("Напоминание установлено") + self.send("Напоминание установлено
Внимание: напоминание не сработает, если бот будет перезагружен") self.change_await() else: self.send("Неверный формат времени, введите время в формате дд.мм.гг чч:мм") @@ -238,7 +339,7 @@ class VkBot: elif message[0] == self._COMMANDS[10]: try: message[1] = message[1].lower() - respond['text'] = self.game(message[1]) + respond['text'] = self.game(message[1], user_id) except IndexError: respond['text'] = errors_array["miss_argument"] @@ -293,12 +394,9 @@ class VkBot: elif message[1] == "set": self.send("О чём мне вам напомнить? (Введите \"Назад\", чтобы отменить установку)") self.change_await("reminder task") - elif message[1] == "delete": - if len(users[self._CHAT_ID]['tasks']) == 0: - respond["text"] = "У вас не установлено ни одно напоминание" - else: - self.send(f"Введите название напоминания, которое необходимо удалить или \"Назад\", чтобы отменить удаление
{self.reminder(None, 'list')}") - self.change_await("reminder delete") + elif message[1] == "delete": + self.send(f"Введите название напоминания, которое необходимо удалить или \"Назад\", чтобы отменить удаление
{self.reminder(None, 'list')}") + self.change_await("reminder delete") else: respond['text'] = "Неверный аргумент" except IndexError: @@ -345,7 +443,6 @@ class VkBot: except Exception: respond["text"] = "У меня нет прав администратора" - if respond['text'] or respond['attachment']: self.send(respond['text'], respond['attachment']) @@ -391,12 +488,7 @@ class VkBot: try: datetime_object = time.strptime(string, '%d.%m.%y %H:%M') self._SET_UP_REMINDER['time'] = int(time.mktime(datetime_object)) - try: - users[self._CHAT_ID]['tasks'][self._SET_UP_REMINDER['time']] = self._SET_UP_REMINDER['task'] - except KeyError: - users[self._CHAT_ID].setdefault("tasks", {}) - users[self._CHAT_ID]['tasks'][self._SET_UP_REMINDER['time']] = self._SET_UP_REMINDER['task'] - update_users_json(users) + db.set_new_task(self._CHAT_ID, self._SET_UP_REMINDER['time'], self._SET_UP_REMINDER["task"]) log(False, f"[BOT_{self._CHAT_ID}] New reminder set") return True except ValueError: @@ -406,30 +498,31 @@ class VkBot: log(False, f"[BOT_{self._CHAT_ID}] Reminder worked") return True elif stage == "list": - if len(users[self._CHAT_ID]['tasks']) == 0: + tasks = db.get_from_tasks(self._CHAT_ID) + print(tasks) + if len(tasks) == 0: respond = "У вас не установлено ни одно напоминание" else: respond = 'Установленные напоминания:
' - for i in users[self._CHAT_ID]['tasks']: - datetime_time = datetime.datetime.fromtimestamp(int(i)) - respond += f"
{datetime_time.strftime('%d.%m.%y %H:%M')} - {users[self._CHAT_ID]['tasks'][i]}" + for i in tasks: + datetime_time = datetime.datetime.fromtimestamp(int(i['time'])) + respond += f"
{datetime_time.strftime('%d.%m.%y %H:%M')} - {i['task']}" return respond elif stage == "delete": - for i in users[self._CHAT_ID]['tasks']: - if users[self._CHAT_ID]['tasks'][i] == string: - users[self._CHAT_ID]['tasks'].pop(i) - return True - return False + return db.delete_task(self._CHAT_ID, string) - def game(self, thing): + def game(self, thing, user_id): + data = db.get_from_users(user_id) + if len(data) == 0: + create_new_bot_object(user_id) + data = db.get_from_users(user_id) + d = data[0] if thing == "статистика": - with open("data_file.json", "r") as read_file: - data = json.load(read_file) - if str(self._CHAT_ID) in data: - winrate = (data[str(self._CHAT_ID)]['wins'] / data[str(self._CHAT_ID)]['games']) * 100 - return f"Камень, ножницы, бумага
Сыграно игр: {data[str(self._CHAT_ID)]['games']}
Из них:
•Побед: {data[str(self._CHAT_ID)]['wins']}
•Поражений: {data[str(self._CHAT_ID)]['defeats']}
•Ничей: {data[str(self._CHAT_ID)]['draws']}
Процент побед: {toFixed(winrate, 2)}%" - else: - return "Похоже, вы ещё никогда не играли в Камень, ножницы, бумага" + try: + winrate = (d['game_wins']/(d['game_wins']+d['game_defeats']+d['game_draws'])) * 100 + except ZeroDivisionError: + winrate = 0 + return f"Камень, ножницы, бумага
Сыграно игр: {d['game_wins']+d['game_defeats']+d['game_draws']}
Из них:
•Побед: {d['game_wins']}
•Поражений: {d['game_defeats']}
•Ничей: {d['game_draws']}
Процент побед: {toFixed(winrate, 2)}%" elif thing == "камень" or thing == "ножницы" or thing == "бумага": things = ["камень", "ножницы", "бумага"] bot_thing = random.choice(things) @@ -454,36 +547,15 @@ class VkBot: if result == 2: response = f"Камень, ножницы, бумага
{thing} vs. {bot_thing}
Вы выиграли!" + db.update_user(user_id, "game_wins", d['game_wins']+1) elif result == 1: response = f"Камень, ножницы, бумага
{thing} vs. {bot_thing}
Вы проиграли!" + db.update_user(user_id, "game_defeats", d['game_defeats']+1) elif result == 0: response = f"Камень, ножницы, бумага
{thing} vs. {bot_thing}
Ничья!" + db.update_user(user_id, "game_draws", d['game_draws']+1) - with open("data_file.json", 'r') as write_file: - try: - data = json.load(write_file) - except Exception: - data = {} - if str(self._CHAT_ID) not in data: - data[str(self._CHAT_ID)] = {} - data[str(self._CHAT_ID)]["games"] = 0 - data[str(self._CHAT_ID)]["wins"] = 0 - data[str(self._CHAT_ID)]["defeats"] = 0 - data[str(self._CHAT_ID)]["draws"] = 0 - - if result == 2: - data[str(self._CHAT_ID)]["games"] += 1 - data[str(self._CHAT_ID)]["wins"] += 1 - elif result == 1: - data[str(self._CHAT_ID)]["games"] += 1 - data[str(self._CHAT_ID)]["defeats"] += 1 - elif result == 0: - data[str(self._CHAT_ID)]["games"] += 1 - data[str(self._CHAT_ID)]["draws"] += 1 - - with open("data_file.json", "w") as write_file: - json.dump(data, write_file) - return response + return response else: return "Неверный аргумент
Использование команды:
!game *камень/ножницы/бумага/статистика*" @@ -600,48 +672,23 @@ class VkBot: def change_await(self, awaiting=None): self._AWAITING_INPUT_MODE = awaiting - try: - users[self._CHAT_ID]['await']= self._AWAITING_INPUT_MODE - except KeyError: - users[self._CHAT_ID].setdefault("tasks", None) - users[self._CHAT_ID]['await']= self._AWAITING_INPUT_MODE - update_users_json(users) + db.update_user(self._CHAT_ID, "awaiting", self._AWAITING_INPUT_MODE) def change_access(self, level): self._ACCESS_LEVEL = level - try: - users[self._CHAT_ID]['access']= self._ACCESS_LEVEL - except KeyError: - users[self._CHAT_ID].setdefault("tasks", None) - users[self._CHAT_ID]['access']= self._ACCESS_LEVEL - update_users_json(users) + db.update_user(self._CHAT_ID, "access", self._ACCESS_LEVEL) def change_new_post(self, new_post): self._NEW_POST = new_post - try: - users[self._CHAT_ID]['new_post']= self._NEW_POST - except KeyError: - users[self._CHAT_ID].setdefault("new_post", None) - users[self._CHAT_ID]['new_post']= self._NEW_POST - update_users_json(users) + db.update_user(self._CHAT_ID, "new_post", self._NEW_POST) def change_midnight(self, midnight): self._MIDNIGHT_EVENT = midnight - try: - users[self._CHAT_ID]['midnight']= self._MIDNIGHT_EVENT - except KeyError: - users[self._CHAT_ID].setdefault("midnight", None) - users[self._CHAT_ID]['midnight']= self._MIDNIGHT_EVENT - update_users_json(users) + db.update_user(self._CHAT_ID, "midnight", self._MIDNIGHT_EVENT) def change_admin_mode(self, admin_mode): self._ADMIN_MODE = admin_mode - try: - users[self._CHAT_ID]['admin_mode']= self._ADMIN_MODE - except KeyError: - users[self._CHAT_ID].setdefault("admin_mode", None) - users[self._CHAT_ID]['admin_mode']= self._ADMIN_MODE - update_users_json(users) + db.update_user(self._CHAT_ID, "admin_mode", self._ADMIN_MODE) def send(self, message=None, attachment=None): try: @@ -679,19 +726,19 @@ def bots(): if int(event.message.peer_id) in bot: bot[event.message.peer_id].get_message(event) else: - bot[event.message.peer_id] = VkBot(event.message.peer_id) - users[event.message.peer_id] = {"midnight": False, "tasks": {}, "await": None, "access": 1, "new_post": False, 'admin_mode': False} - update_users_json(users) + create_new_bot_object(event.message.peer_id) bot[event.message.peer_id].get_message(event) elif event.type == VkBotEventType.WALL_POST_NEW: log(False, f"[NEW_POST] id{event.object.id}") + users = db.get_all_users() for i in users: bot[int(i)].event("post", event.object) elif event.type == VkBotEventType.MESSAGE_DENY: log(False, f"User {event.object.user_id} deny messages from that group") del bot[int(event.object.user_id)] - del users[int(event.object.user_id)] - update_users_json(users) + db.delete_user(event.object.user_id) + else: + log(False, f"Event {str(event.type)} happend") except Exception as kek: err = "Беды с ботом: " + str(kek) log(True, err) @@ -702,8 +749,9 @@ def midnight(): current_time = time.time()+10800 if int(current_time) % 86400 == 0: log(False, "[EVENT_STARTED] \"Midnight\"") + users = db.get_all_users() for i in users: - bot[int(i)].event("midnight") + bot[int(i['chat_id'])].event("midnight") log(False, "[EVENT_ENDED] \"Midnight\"") time.sleep(1) else: @@ -712,23 +760,16 @@ def midnight(): def check_tasks(): while True: try: - for i in users: + tasks = db.get_all_tasks() + for i in tasks: current_time = time.time()+10800 - if "tasks" in users[i]: - try: - for n in users[i]["tasks"]: - if int(n) == int(current_time): - bot[int(i)].reminder(users[i]['tasks'][n], "remind") - users[i]['tasks'].pop(n) - update_users_json(users) - except RuntimeError: - continue + if i['time'] == int(current_time): + bot[i['chat_id']].reminder(i['task'], "remind") + db.delete_task(i["chat_id"], i['task']) except RuntimeError: continue - time.sleep(0.3) + time.sleep(0.4) - -log(False, "Script started, reading users.json") load_users() tread_bots = threading.Thread(target=bots) tread_midnight = threading.Thread(target=midnight, daemon=True) @@ -736,5 +777,3 @@ tread_tasks = threading.Thread(target=check_tasks, daemon=True) tread_bots.start() tread_midnight.start() tread_tasks.start() - - diff --git a/help.txt b/help.txt index 3a60aee..eb89222 100644 --- a/help.txt +++ b/help.txt @@ -29,5 +29,5 @@ !h, !help - справка -Дата последнего обновления: 31.05.2020 (Добавлена очень справедливая функция) +Дата последнего обновления: 07.05.2020 (Данные бота теперь хранятся в базе данных) Проект бота на GitHub: https://github.com/dan63047/dan63047pythonbot