Добавлено: ввод и проверка группы в БД и на сайте
This commit is contained in:
parent
1ce533325c
commit
d54ea60f30
104
bot.py
104
bot.py
|
@ -1,5 +1,6 @@
|
|||
from database.l9 import L9_DB
|
||||
from database.tg import TG_DB
|
||||
from database.shedule import Shedule_DB
|
||||
from utils.config import *
|
||||
import telegram
|
||||
from tg.keyboards import Keyboard
|
||||
|
@ -31,14 +32,47 @@ def initLogger():
|
|||
|
||||
|
||||
class Bot:
|
||||
def __init__(self, token: str, db: L9_DB, tg_db: TG_DB, limit=150):
|
||||
def __init__(
|
||||
self,
|
||||
token: str,
|
||||
db: L9_DB,
|
||||
tg_db: TG_DB,
|
||||
shedule: Shedule_DB,
|
||||
limit=150,
|
||||
):
|
||||
self.l9lk = db
|
||||
self.tg_db = tg_db
|
||||
self.shedule = shedule
|
||||
self.tg = telegram.Bot(token)
|
||||
self.limit = limit
|
||||
self.udpate_id = None
|
||||
self.isWork = True
|
||||
|
||||
def checkMessages(self):
|
||||
"""Проверка и обработка входящих сообщений"""
|
||||
|
||||
updates = self.tg.get_updates(offset=self.udpate_id, timeout=5)
|
||||
for update in updates:
|
||||
self.udpate_id = update.update_id + 1
|
||||
if update.message:
|
||||
query = update.message
|
||||
tag, l9Id, log = self.tg_db.getTag(query)
|
||||
logger.info(log)
|
||||
tgId = query.from_user.id
|
||||
|
||||
if tag == 'not_started':
|
||||
self.start(query)
|
||||
|
||||
if tag == 'add':
|
||||
self.addGroup(l9Id, query)
|
||||
|
||||
else:
|
||||
self.tg.sendMessage(
|
||||
tgId,
|
||||
"Ой!",
|
||||
reply_markup=Keyboard.menu(),
|
||||
)
|
||||
|
||||
def start(self, query: telegram.Message):
|
||||
"""Обработка нового пользователя"""
|
||||
|
||||
|
@ -67,27 +101,54 @@ class Bot:
|
|||
),
|
||||
)
|
||||
|
||||
def checkMessages(self):
|
||||
"""Проверка и обработка входящих сообщений"""
|
||||
def addGroup(self, l9Id: int, query: telegram.Message):
|
||||
"""Процесс добавления группы"""
|
||||
|
||||
updates = self.tg.get_updates(offset=self.udpate_id, timeout=5)
|
||||
for update in updates:
|
||||
self.udpate_id = update.update_id + 1
|
||||
if update.message:
|
||||
query = update.message
|
||||
tag, l9Id, log = self.tg_db.getTag(query)
|
||||
logger.info(log)
|
||||
tgId = query.from_user.id
|
||||
groupName = query.text
|
||||
tgId = query.from_user.id
|
||||
|
||||
if tag == 'not_started':
|
||||
self.start(query)
|
||||
result = self.shedule.checkGroupExists(groupName, l9Id)
|
||||
if 'OK' in result:
|
||||
_, groupName, specName = result.split(';')
|
||||
self.tg_db.changeTag(tgId, 'ready')
|
||||
self.tg.sendMessage(
|
||||
tgId,
|
||||
f'Поздравляем, твоя группа {groupName}, направление "{specName}", подключена!',
|
||||
reply_markup=Keyboard.menu(),
|
||||
)
|
||||
|
||||
else:
|
||||
self.tg.sendMessage(
|
||||
tgId,
|
||||
"Ой!",
|
||||
reply_markup=Keyboard.menu(),
|
||||
)
|
||||
elif result == 'Exists':
|
||||
self.tg.sendMessage(
|
||||
tgId,
|
||||
'❗️Эта группа у тебя уже подключена',
|
||||
reply_markup=Keyboard.cancel(),
|
||||
)
|
||||
|
||||
elif result == 'Error':
|
||||
self.tg.sendMessage(
|
||||
tgId,
|
||||
'❗У меня этой группы пока нет, а сайте возникла какая-то ошибка.\nПопробуйте позже',
|
||||
reply_markup=Keyboard.cancel(),
|
||||
)
|
||||
|
||||
elif 'ssau.ru' in result:
|
||||
self.tg_db.changeTag(tgId, f'conf_{result[21:]}')
|
||||
self.tg.sendMessage(
|
||||
tgId,
|
||||
(
|
||||
'Такой группы у меня пока нет в базе, но она есть на сайте\n'
|
||||
f'{result}\n'
|
||||
'Проверь, пожалуйста, что это твоя группа и нажми кнопку\n'
|
||||
),
|
||||
reply_markup=Keyboard.confirm(),
|
||||
)
|
||||
|
||||
else:
|
||||
self.tg.sendMessage(
|
||||
tgId,
|
||||
'К сожалению, такой группы нет ни в моей базе, ни на сайте университета :(',
|
||||
reply_markup=Keyboard.cancel(),
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -97,7 +158,10 @@ if __name__ == "__main__":
|
|||
config = loadJSON("config")
|
||||
l9lk = L9_DB(**config['sql'])
|
||||
tg_db = TG_DB(l9lk)
|
||||
bot = Bot(config['tg']['token'], l9lk, tg_db, config['tg']['limit'])
|
||||
shedule = Shedule_DB(l9lk)
|
||||
bot = Bot(
|
||||
config['tg']['token'], l9lk, tg_db, shedule, config['tg']['limit']
|
||||
)
|
||||
|
||||
logger.info("Bot ready!")
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ class Database:
|
|||
query.lower().find("drop") == -1
|
||||
and query.lower().find("truncate") == -1
|
||||
):
|
||||
print(query)
|
||||
self.cursor.execute(query)
|
||||
if commit:
|
||||
self.database.commit()
|
||||
|
@ -42,7 +43,7 @@ class Database:
|
|||
|
||||
with open(f'database/{filename}.sql', encoding='utf-8') as f:
|
||||
query = f.read()
|
||||
return self.execute(query, commit)
|
||||
return self.execute(query, commit).fetchall()
|
||||
|
||||
def initDatabase(self, name: str):
|
||||
"""Создать базу данных, если таковая отсутствует,
|
||||
|
@ -51,8 +52,8 @@ class Database:
|
|||
:name: название базы данных
|
||||
"""
|
||||
|
||||
self.execute(f"CREATE DATABASE IF NOT EXISTS {name}")
|
||||
self.execute(f"USE {name}")
|
||||
self.execute(f"CREATE DATABASE IF NOT EXISTS {name};")
|
||||
self.execute(f"USE {name};")
|
||||
|
||||
def initTable(self, name: str, head: str):
|
||||
"""Создать таблицу, если таковая отсутствует
|
|
@ -0,0 +1,34 @@
|
|||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
from ast import literal_eval
|
||||
import time
|
||||
import logging
|
||||
logger = logging.getLogger('bot')
|
||||
|
||||
def findInRasp(req) -> dict:
|
||||
"""Поиск группы (преподавателя) в расписании"""
|
||||
logger.debug(f'Find {req}')
|
||||
|
||||
rasp = requests.Session()
|
||||
rasp.headers['User-Agent'] = 'Mozilla/5.0'
|
||||
hed = rasp.get("https://ssau.ru/rasp/")
|
||||
if hed.status_code == 200:
|
||||
soup = BeautifulSoup(hed.text, 'lxml')
|
||||
csrf_token = soup.select_one('meta[name="csrf-token"]')['content']
|
||||
else:
|
||||
return 'Error'
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
rasp.headers['Accept'] = 'application/json'
|
||||
rasp.headers['X-CSRF-TOKEN'] = csrf_token
|
||||
result = rasp.post("https://ssau.ru/rasp/search", data = {'text':req})
|
||||
if result.status_code == 200:
|
||||
num = literal_eval(result.text)
|
||||
else:
|
||||
return 'Error'
|
||||
|
||||
if len(num) == 0:
|
||||
return None
|
||||
else:
|
||||
return num[0]
|
|
@ -1,30 +0,0 @@
|
|||
CREATE DATABASE IF NOT EXISTS `l9_db`;
|
||||
USE `l9_db`;
|
||||
|
||||
-- Пользователи системы
|
||||
CREATE TABLE IF NOT EXISTS `users` (
|
||||
`l9Id` bigint NOT NULL,
|
||||
-- Идентификатор пользователя системы
|
||||
|
||||
PRIMARY KEY (`l9Id`)
|
||||
);
|
||||
|
||||
-- Сведения о пользователях бота Telegram
|
||||
CREATE TABLE IF NOT EXISTS `tg_users` (
|
||||
`l9Id` bigint NOT NULL,
|
||||
-- Идентификатор пользователя системы
|
||||
|
||||
`tgId` bigint NOT NULL,
|
||||
-- ID пользователя в Telegram
|
||||
|
||||
`name` TEXT,
|
||||
-- (optional) Имя пользователя в Telegram
|
||||
|
||||
`posTag` varchar(30) DEFAULT 'not_started',
|
||||
-- Позиция пользователя в диалоге с ботом:
|
||||
-- (default) not_started - не вступил в диалог
|
||||
-- started - вступил в диалог
|
||||
|
||||
PRIMARY KEY (`l9Id`),
|
||||
CONSTRAINT `l9_tg` FOREIGN KEY (`l9Id`) REFERENCES `users` (`l9Id`) ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
|
@ -1,4 +1,4 @@
|
|||
from .asql import Database
|
||||
from .a_sql import Database
|
||||
|
||||
|
||||
class L9_DB:
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
from .l9 import L9_DB
|
||||
from .a_ssau_parser import *
|
||||
|
||||
|
||||
class Shedule_DB:
|
||||
"""Класс взаимодействия с базой расписания"""
|
||||
|
||||
def __init__(self, l9lk: L9_DB):
|
||||
self.l9lk = l9lk
|
||||
self.db = l9lk.db
|
||||
self.db.executeFile('shedule')
|
||||
|
||||
def checkGroupExists(self, groupName: str, l9Id: str) -> str:
|
||||
"""Проверка наличия группы в БД и на сайте, а также проверка,
|
||||
что пользователь ещё не подключен к группе
|
||||
|
||||
'OK;N_группы;Назв-е_спец-сти' - пользователь успешно подключен \n
|
||||
'Exists' - пользователь уже подключен к данной группе \n
|
||||
'ssau.ru/groupId=*' - группа отсутствует в базе, но есть на сайте \n
|
||||
'Error' - ошибка на стороне сайта
|
||||
'Empty' - группа нигде не обнаружена
|
||||
"""
|
||||
|
||||
groupIdInDB = self.l9lk.db.get(
|
||||
'groups',
|
||||
f'groupName LIKE "%{groupName}%"',
|
||||
['groupId', 'groupName', 'specName'],
|
||||
)
|
||||
|
||||
if groupIdInDB != []:
|
||||
groupIdInDB = groupIdInDB[0]
|
||||
|
||||
exists = self.l9lk.db.get(
|
||||
'groups_users',
|
||||
f'l9Id = {l9Id} AND groupId = {groupIdInDB[0]}',
|
||||
)
|
||||
if exists == []:
|
||||
self.l9lk.db.insert(
|
||||
'groups_users',
|
||||
{'l9Id': l9Id, 'groupId': groupIdInDB[0]},
|
||||
)
|
||||
return f'OK;{groupIdInDB[1]};{groupIdInDB[2]}'
|
||||
|
||||
else:
|
||||
return 'Exists'
|
||||
|
||||
else:
|
||||
group = findInRasp(groupName)
|
||||
if group != None:
|
||||
group_url = f'ssau.ru/{group["url"][2:]}'
|
||||
gr_num = group["text"]
|
||||
groupId = group["id"]
|
||||
|
||||
return group_url
|
||||
|
||||
elif group == 'Error':
|
||||
return 'Error'
|
||||
|
||||
else:
|
||||
return 'Empty'
|
|
@ -0,0 +1,45 @@
|
|||
-- Учебные группы
|
||||
CREATE TABLE IF NOT EXISTS `groups` (
|
||||
`groupId` bigint NOT NULL,
|
||||
-- Идентификатор группы, соответствует ID в расписании на сайте
|
||||
|
||||
`groupName` varchar(4) DEFAULT '0000',
|
||||
-- Учебный номер (наименование) группы
|
||||
|
||||
`specName` text,
|
||||
-- Код и название направления подготовки
|
||||
|
||||
PRIMARY KEY (`groupId`)
|
||||
);
|
||||
|
||||
|
||||
-- Сведения о группах пользователя и настройках каждой группы
|
||||
CREATE TABLE IF NOT EXISTS `groups_users` (
|
||||
`guId` bigint NOT NULL AUTO_INCREMENT,
|
||||
-- (service) Идентификатор сведения, устанавливается автоматически
|
||||
|
||||
`l9Id` bigint NOT NULL,
|
||||
-- Идентификатор пользователя системы
|
||||
|
||||
`groupId` bigint NOT NULL,
|
||||
-- ID группы, которой принадлежит пользователь
|
||||
|
||||
`firstTime` int DEFAULT '45',
|
||||
-- Время в минутах, за которое приходит уведомление о начале занятий
|
||||
|
||||
`firstNote` tinyint DEFAULT '1',
|
||||
-- Состояние уведомлений о начале занятий:
|
||||
-- 0 - выключены
|
||||
-- ненулевое значение - включены
|
||||
|
||||
`nextNote` tinyint DEFAULT '1',
|
||||
-- Состояние уведомлений о первой или следующей паре
|
||||
-- 0 - выключены
|
||||
-- ненулевое значение - включены
|
||||
|
||||
PRIMARY KEY (`guId`),
|
||||
KEY `guid_idx` (`l9Id`),
|
||||
KEY `gid_idx` (`groupId`),
|
||||
CONSTRAINT `gr_gu` FOREIGN KEY (`groupId`) REFERENCES `groups` (`groupId`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
CONSTRAINT `l9_gu` FOREIGN KEY (`l9Id`) REFERENCES `users` (`l9Id`) ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
|
@ -11,7 +11,7 @@ CREATE TABLE IF NOT EXISTS `tg_users` (
|
|||
|
||||
`posTag` varchar(30) DEFAULT 'not_started',
|
||||
-- Позиция пользователя в диалоге с ботом:
|
||||
-- (default) not_started - только что в диалог
|
||||
-- (default) not_started - только что вступил в диалог
|
||||
-- add - добавляет группу
|
||||
|
||||
PRIMARY KEY (`l9Id`),
|
||||
|
|
Reference in New Issue