Now bot work on mysql db. Big update of README
This commit is contained in:
parent
79fedeba68
commit
cf2b0e5213
69
README.md
69
README.md
|
@ -1,27 +1,7 @@
|
||||||
# Мой личный бот на python для ВК
|
# Мой личный бот на python для ВК
|
||||||
#### от dan63047
|
#### от dan63047
|
||||||
|
|
||||||
Этот бот просто отвечает на поддержваемые запросы в переписке с сообществом. Был написан мною в целях изучения python
|
Этот бот просто отвечает на поддержваемые запросы в переписке с сообществом. Был написан мною в целях изучения 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** — бот отправляет список команд и их краткое описание, а так же дату последнего обновления и ссылку на этот репозиторий
|
* **!h, !help** — бот отправляет список команд и их краткое описание, а так же дату последнего обновления и ссылку на этот репозиторий
|
||||||
|
@ -44,16 +24,57 @@ owm = pyowm.OWM('OpenWeather_api_key', language='ru') # Ключ OpenWeather API
|
||||||
* **!access *all/owner*** — позволяет в беседе установить уровень доступа к командам *!midnight*, *!subscribe* и *!debug*. *all* - все могут пользоваться. *owner* - только вы. Доступно только вам
|
* **!access *all/owner*** — позволяет в беседе установить уровень доступа к командам *!midnight*, *!subscribe* и *!debug*. *all* - все могут пользоваться. *owner* - только вы. Доступно только вам
|
||||||
* **!turnoff** — даёт боту команду на выключение. Доступно только вам
|
* **!turnoff** — даёт боту команду на выключение. Доступно только вам
|
||||||
* **!admin_mode** — если чат, в которой активируется команда, является беседой и в ней у бота есть полномочия администратора, то бот переходит в режим модерации. Пока что он может только кикать людей за @all и @online. Введите ещё раз, чтобы выключить режим модерации. Доступно только вам
|
* **!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) — модуль для создания скриптов для социальной сети Вконтакте
|
* [vk_api](https://github.com/python273/vk_api) — модуль для создания скриптов для социальной сети Вконтакте
|
||||||
* [pyowm](https://github.com/csparpa/pyowm) — модуль для получения погоды через OpenWeather API
|
* [pyowm](https://github.com/csparpa/pyowm) — модуль для получения погоды через OpenWeather API
|
||||||
* [Wikipedia-API](https://github.com/martin-majlis/Wikipedia-API) — модуль для получения статей из Wikipedia
|
* [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/im?sel=-190322075)
|
||||||
|
|
||||||
Автор бота: [Даниил Михайлов](https://vk.com/dan63047)
|
Автор бота: [Даниил Михайлов](https://vk.com/dan63047)
|
||||||
|
|
343
dan63047bot.py
343
dan63047bot.py
|
@ -7,58 +7,22 @@ import pyowm
|
||||||
import random
|
import random
|
||||||
import json
|
import json
|
||||||
import threading
|
import threading
|
||||||
|
import pymysql
|
||||||
|
from pymysql.cursors import DictCursor
|
||||||
import wikipediaapi as wiki
|
import wikipediaapi as wiki
|
||||||
from collections import deque
|
from collections import deque
|
||||||
|
from config import vk, owm, vk_mda, group_id, album_for_command, owner_id, mysql_host, mysql_pass, mysql_user, mysql_db
|
||||||
from PIL import Image
|
|
||||||
|
|
||||||
from config import vk, owm, vk_mda, group_id, album_for_command, owner_id
|
|
||||||
from vk_api.bot_longpoll import VkBotLongPoll, VkBotEventType
|
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 = logging.getLogger()
|
||||||
root_logger.setLevel(logging.INFO)
|
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'))
|
handler.setFormatter(logging.Formatter('[%(asctime)s][%(levelname)s] %(message)s'))
|
||||||
root_logger.addHandler(handler)
|
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):
|
def log(warning, text):
|
||||||
if warning:
|
if warning:
|
||||||
logging.warning(text)
|
logging.warning(text)
|
||||||
|
@ -68,6 +32,140 @@ def log(warning, text):
|
||||||
logging.info(text)
|
logging.info(text)
|
||||||
print("[" + str(datetime.datetime.now()) + "] " + 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):
|
def toFixed(numObj, digits=0):
|
||||||
return f"{numObj:.{digits}f}"
|
return f"{numObj:.{digits}f}"
|
||||||
|
@ -86,6 +184,9 @@ class MyVkLongPoll(VkBotLongPoll):
|
||||||
time.sleep(15)
|
time.sleep(15)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
def create_new_bot_object(chat_id):
|
||||||
|
bot[chat_id] = VkBot(chat_id)
|
||||||
|
db.set_new_user(chat_id)
|
||||||
|
|
||||||
def get_weather(place):
|
def get_weather(place):
|
||||||
try:
|
try:
|
||||||
|
@ -123,7 +224,7 @@ class VkBot:
|
||||||
"!echo", "!game", "!debug", "!midnight", "!access", "!turnoff", "!reminder", "!subscribe", "!random", "!admin_mode"]
|
"!echo", "!game", "!debug", "!midnight", "!access", "!turnoff", "!reminder", "!subscribe", "!random", "!admin_mode"]
|
||||||
|
|
||||||
def __str__(self):
|
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):
|
def __del__(self):
|
||||||
log(False, f"[BOT_{str(self._CHAT_ID)}] Bot-object has been deleted")
|
log(False, f"[BOT_{str(self._CHAT_ID)}] Bot-object has been deleted")
|
||||||
|
@ -170,7 +271,7 @@ class VkBot:
|
||||||
self.change_await('reminder time')
|
self.change_await('reminder time')
|
||||||
elif self._AWAITING_INPUT_MODE == 'reminder time':
|
elif self._AWAITING_INPUT_MODE == 'reminder time':
|
||||||
if self.reminder(message, "time"):
|
if self.reminder(message, "time"):
|
||||||
self.send("Напоминание установлено")
|
self.send("Напоминание установлено<br>Внимание: напоминание не сработает, если бот будет перезагружен")
|
||||||
self.change_await()
|
self.change_await()
|
||||||
else:
|
else:
|
||||||
self.send("Неверный формат времени, введите время в формате дд.мм.гг чч:мм")
|
self.send("Неверный формат времени, введите время в формате дд.мм.гг чч:мм")
|
||||||
|
@ -238,7 +339,7 @@ class VkBot:
|
||||||
elif message[0] == self._COMMANDS[10]:
|
elif message[0] == self._COMMANDS[10]:
|
||||||
try:
|
try:
|
||||||
message[1] = message[1].lower()
|
message[1] = message[1].lower()
|
||||||
respond['text'] = self.game(message[1])
|
respond['text'] = self.game(message[1], user_id)
|
||||||
except IndexError:
|
except IndexError:
|
||||||
respond['text'] = errors_array["miss_argument"]
|
respond['text'] = errors_array["miss_argument"]
|
||||||
|
|
||||||
|
@ -293,12 +394,9 @@ class VkBot:
|
||||||
elif message[1] == "set":
|
elif message[1] == "set":
|
||||||
self.send("О чём мне вам напомнить? (Введите \"Назад\", чтобы отменить установку)")
|
self.send("О чём мне вам напомнить? (Введите \"Назад\", чтобы отменить установку)")
|
||||||
self.change_await("reminder task")
|
self.change_await("reminder task")
|
||||||
elif message[1] == "delete":
|
elif message[1] == "delete":
|
||||||
if len(users[self._CHAT_ID]['tasks']) == 0:
|
self.send(f"Введите название напоминания, которое необходимо удалить или \"Назад\", чтобы отменить удаление<br>{self.reminder(None, 'list')}")
|
||||||
respond["text"] = "У вас не установлено ни одно напоминание"
|
self.change_await("reminder delete")
|
||||||
else:
|
|
||||||
self.send(f"Введите название напоминания, которое необходимо удалить или \"Назад\", чтобы отменить удаление<br>{self.reminder(None, 'list')}")
|
|
||||||
self.change_await("reminder delete")
|
|
||||||
else:
|
else:
|
||||||
respond['text'] = "Неверный аргумент"
|
respond['text'] = "Неверный аргумент"
|
||||||
except IndexError:
|
except IndexError:
|
||||||
|
@ -345,7 +443,6 @@ class VkBot:
|
||||||
except Exception:
|
except Exception:
|
||||||
respond["text"] = "У меня нет прав администратора"
|
respond["text"] = "У меня нет прав администратора"
|
||||||
|
|
||||||
|
|
||||||
if respond['text'] or respond['attachment']:
|
if respond['text'] or respond['attachment']:
|
||||||
self.send(respond['text'], respond['attachment'])
|
self.send(respond['text'], respond['attachment'])
|
||||||
|
|
||||||
|
@ -391,12 +488,7 @@ class VkBot:
|
||||||
try:
|
try:
|
||||||
datetime_object = time.strptime(string, '%d.%m.%y %H:%M')
|
datetime_object = time.strptime(string, '%d.%m.%y %H:%M')
|
||||||
self._SET_UP_REMINDER['time'] = int(time.mktime(datetime_object))
|
self._SET_UP_REMINDER['time'] = int(time.mktime(datetime_object))
|
||||||
try:
|
db.set_new_task(self._CHAT_ID, self._SET_UP_REMINDER['time'], self._SET_UP_REMINDER["task"])
|
||||||
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)
|
|
||||||
log(False, f"[BOT_{self._CHAT_ID}] New reminder set")
|
log(False, f"[BOT_{self._CHAT_ID}] New reminder set")
|
||||||
return True
|
return True
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
@ -406,30 +498,31 @@ class VkBot:
|
||||||
log(False, f"[BOT_{self._CHAT_ID}] Reminder worked")
|
log(False, f"[BOT_{self._CHAT_ID}] Reminder worked")
|
||||||
return True
|
return True
|
||||||
elif stage == "list":
|
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 = "У вас не установлено ни одно напоминание"
|
respond = "У вас не установлено ни одно напоминание"
|
||||||
else:
|
else:
|
||||||
respond = 'Установленные напоминания:<br>'
|
respond = 'Установленные напоминания:<br>'
|
||||||
for i in users[self._CHAT_ID]['tasks']:
|
for i in tasks:
|
||||||
datetime_time = datetime.datetime.fromtimestamp(int(i))
|
datetime_time = datetime.datetime.fromtimestamp(int(i['time']))
|
||||||
respond += f"<br>{datetime_time.strftime('%d.%m.%y %H:%M')} - {users[self._CHAT_ID]['tasks'][i]}"
|
respond += f"<br>{datetime_time.strftime('%d.%m.%y %H:%M')} - {i['task']}"
|
||||||
return respond
|
return respond
|
||||||
elif stage == "delete":
|
elif stage == "delete":
|
||||||
for i in users[self._CHAT_ID]['tasks']:
|
return db.delete_task(self._CHAT_ID, string)
|
||||||
if users[self._CHAT_ID]['tasks'][i] == string:
|
|
||||||
users[self._CHAT_ID]['tasks'].pop(i)
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
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 == "статистика":
|
if thing == "статистика":
|
||||||
with open("data_file.json", "r") as read_file:
|
try:
|
||||||
data = json.load(read_file)
|
winrate = (d['game_wins']/(d['game_wins']+d['game_defeats']+d['game_draws'])) * 100
|
||||||
if str(self._CHAT_ID) in data:
|
except ZeroDivisionError:
|
||||||
winrate = (data[str(self._CHAT_ID)]['wins'] / data[str(self._CHAT_ID)]['games']) * 100
|
winrate = 0
|
||||||
return f"Камень, ножницы, бумага<br>Сыграно игр: {data[str(self._CHAT_ID)]['games']}<br>Из них:<br>•Побед: {data[str(self._CHAT_ID)]['wins']}<br>•Поражений: {data[str(self._CHAT_ID)]['defeats']}<br>•Ничей: {data[str(self._CHAT_ID)]['draws']}<br>Процент побед: {toFixed(winrate, 2)}%"
|
return f"Камень, ножницы, бумага<br>Сыграно игр: {d['game_wins']+d['game_defeats']+d['game_draws']}<br>Из них:<br>•Побед: {d['game_wins']}<br>•Поражений: {d['game_defeats']}<br>•Ничей: {d['game_draws']}<br>Процент побед: {toFixed(winrate, 2)}%"
|
||||||
else:
|
|
||||||
return "Похоже, вы ещё никогда не играли в Камень, ножницы, бумага"
|
|
||||||
elif thing == "камень" or thing == "ножницы" or thing == "бумага":
|
elif thing == "камень" or thing == "ножницы" or thing == "бумага":
|
||||||
things = ["камень", "ножницы", "бумага"]
|
things = ["камень", "ножницы", "бумага"]
|
||||||
bot_thing = random.choice(things)
|
bot_thing = random.choice(things)
|
||||||
|
@ -454,36 +547,15 @@ class VkBot:
|
||||||
|
|
||||||
if result == 2:
|
if result == 2:
|
||||||
response = f"Камень, ножницы, бумага<br>{thing} vs. {bot_thing}<br>Вы выиграли!"
|
response = f"Камень, ножницы, бумага<br>{thing} vs. {bot_thing}<br>Вы выиграли!"
|
||||||
|
db.update_user(user_id, "game_wins", d['game_wins']+1)
|
||||||
elif result == 1:
|
elif result == 1:
|
||||||
response = f"Камень, ножницы, бумага<br>{thing} vs. {bot_thing}<br>Вы проиграли!"
|
response = f"Камень, ножницы, бумага<br>{thing} vs. {bot_thing}<br>Вы проиграли!"
|
||||||
|
db.update_user(user_id, "game_defeats", d['game_defeats']+1)
|
||||||
elif result == 0:
|
elif result == 0:
|
||||||
response = f"Камень, ножницы, бумага<br>{thing} vs. {bot_thing}<br>Ничья!"
|
response = f"Камень, ножницы, бумага<br>{thing} vs. {bot_thing}<br>Ничья!"
|
||||||
|
db.update_user(user_id, "game_draws", d['game_draws']+1)
|
||||||
|
|
||||||
with open("data_file.json", 'r') as write_file:
|
return response
|
||||||
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
|
|
||||||
else:
|
else:
|
||||||
return "Неверный аргумент<br>Использование команды:<br>!game *камень/ножницы/бумага/статистика*"
|
return "Неверный аргумент<br>Использование команды:<br>!game *камень/ножницы/бумага/статистика*"
|
||||||
|
|
||||||
|
@ -600,48 +672,23 @@ class VkBot:
|
||||||
|
|
||||||
def change_await(self, awaiting=None):
|
def change_await(self, awaiting=None):
|
||||||
self._AWAITING_INPUT_MODE = awaiting
|
self._AWAITING_INPUT_MODE = awaiting
|
||||||
try:
|
db.update_user(self._CHAT_ID, "awaiting", self._AWAITING_INPUT_MODE)
|
||||||
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)
|
|
||||||
|
|
||||||
def change_access(self, level):
|
def change_access(self, level):
|
||||||
self._ACCESS_LEVEL = level
|
self._ACCESS_LEVEL = level
|
||||||
try:
|
db.update_user(self._CHAT_ID, "access", self._ACCESS_LEVEL)
|
||||||
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)
|
|
||||||
|
|
||||||
def change_new_post(self, new_post):
|
def change_new_post(self, new_post):
|
||||||
self._NEW_POST = new_post
|
self._NEW_POST = new_post
|
||||||
try:
|
db.update_user(self._CHAT_ID, "new_post", self._NEW_POST)
|
||||||
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)
|
|
||||||
|
|
||||||
def change_midnight(self, midnight):
|
def change_midnight(self, midnight):
|
||||||
self._MIDNIGHT_EVENT = midnight
|
self._MIDNIGHT_EVENT = midnight
|
||||||
try:
|
db.update_user(self._CHAT_ID, "midnight", self._MIDNIGHT_EVENT)
|
||||||
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)
|
|
||||||
|
|
||||||
def change_admin_mode(self, admin_mode):
|
def change_admin_mode(self, admin_mode):
|
||||||
self._ADMIN_MODE = admin_mode
|
self._ADMIN_MODE = admin_mode
|
||||||
try:
|
db.update_user(self._CHAT_ID, "admin_mode", self._ADMIN_MODE)
|
||||||
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)
|
|
||||||
|
|
||||||
def send(self, message=None, attachment=None):
|
def send(self, message=None, attachment=None):
|
||||||
try:
|
try:
|
||||||
|
@ -679,19 +726,19 @@ def bots():
|
||||||
if int(event.message.peer_id) in bot:
|
if int(event.message.peer_id) in bot:
|
||||||
bot[event.message.peer_id].get_message(event)
|
bot[event.message.peer_id].get_message(event)
|
||||||
else:
|
else:
|
||||||
bot[event.message.peer_id] = VkBot(event.message.peer_id)
|
create_new_bot_object(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)
|
|
||||||
bot[event.message.peer_id].get_message(event)
|
bot[event.message.peer_id].get_message(event)
|
||||||
elif event.type == VkBotEventType.WALL_POST_NEW:
|
elif event.type == VkBotEventType.WALL_POST_NEW:
|
||||||
log(False, f"[NEW_POST] id{event.object.id}")
|
log(False, f"[NEW_POST] id{event.object.id}")
|
||||||
|
users = db.get_all_users()
|
||||||
for i in users:
|
for i in users:
|
||||||
bot[int(i)].event("post", event.object)
|
bot[int(i)].event("post", event.object)
|
||||||
elif event.type == VkBotEventType.MESSAGE_DENY:
|
elif event.type == VkBotEventType.MESSAGE_DENY:
|
||||||
log(False, f"User {event.object.user_id} deny messages from that group")
|
log(False, f"User {event.object.user_id} deny messages from that group")
|
||||||
del bot[int(event.object.user_id)]
|
del bot[int(event.object.user_id)]
|
||||||
del users[int(event.object.user_id)]
|
db.delete_user(event.object.user_id)
|
||||||
update_users_json(users)
|
else:
|
||||||
|
log(False, f"Event {str(event.type)} happend")
|
||||||
except Exception as kek:
|
except Exception as kek:
|
||||||
err = "Беды с ботом: " + str(kek)
|
err = "Беды с ботом: " + str(kek)
|
||||||
log(True, err)
|
log(True, err)
|
||||||
|
@ -702,8 +749,9 @@ def midnight():
|
||||||
current_time = time.time()+10800
|
current_time = time.time()+10800
|
||||||
if int(current_time) % 86400 == 0:
|
if int(current_time) % 86400 == 0:
|
||||||
log(False, "[EVENT_STARTED] \"Midnight\"")
|
log(False, "[EVENT_STARTED] \"Midnight\"")
|
||||||
|
users = db.get_all_users()
|
||||||
for i in users:
|
for i in users:
|
||||||
bot[int(i)].event("midnight")
|
bot[int(i['chat_id'])].event("midnight")
|
||||||
log(False, "[EVENT_ENDED] \"Midnight\"")
|
log(False, "[EVENT_ENDED] \"Midnight\"")
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
else:
|
else:
|
||||||
|
@ -712,23 +760,16 @@ def midnight():
|
||||||
def check_tasks():
|
def check_tasks():
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
for i in users:
|
tasks = db.get_all_tasks()
|
||||||
|
for i in tasks:
|
||||||
current_time = time.time()+10800
|
current_time = time.time()+10800
|
||||||
if "tasks" in users[i]:
|
if i['time'] == int(current_time):
|
||||||
try:
|
bot[i['chat_id']].reminder(i['task'], "remind")
|
||||||
for n in users[i]["tasks"]:
|
db.delete_task(i["chat_id"], i['task'])
|
||||||
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
|
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
continue
|
continue
|
||||||
time.sleep(0.3)
|
time.sleep(0.4)
|
||||||
|
|
||||||
|
|
||||||
log(False, "Script started, reading users.json")
|
|
||||||
load_users()
|
load_users()
|
||||||
tread_bots = threading.Thread(target=bots)
|
tread_bots = threading.Thread(target=bots)
|
||||||
tread_midnight = threading.Thread(target=midnight, daemon=True)
|
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_bots.start()
|
||||||
tread_midnight.start()
|
tread_midnight.start()
|
||||||
tread_tasks.start()
|
tread_tasks.start()
|
||||||
|
|
||||||
|
|
||||||
|
|
2
help.txt
2
help.txt
|
@ -29,5 +29,5 @@
|
||||||
|
|
||||||
!h, !help - справка
|
!h, !help - справка
|
||||||
|
|
||||||
Дата последнего обновления: 31.05.2020 (Добавлена очень справедливая функция)
|
Дата последнего обновления: 07.05.2020 (Данные бота теперь хранятся в базе данных)
|
||||||
Проект бота на GitHub: https://github.com/dan63047/dan63047pythonbot
|
Проект бота на GitHub: https://github.com/dan63047/dan63047pythonbot
|
||||||
|
|
Loading…
Reference in New Issue