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