Добавлено: ввод и проверка группы в БД и на сайте

This commit is contained in:
far-galaxy 2023-01-31 21:33:46 +03:00
parent 1ce533325c
commit d54ea60f30
8 changed files with 229 additions and 55 deletions

104
bot.py
View File

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

View File

@ -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):
"""Создать таблицу, если таковая отсутствует

34
database/a_ssau_parser.py Normal file
View File

@ -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]

View File

@ -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
);

View File

@ -1,4 +1,4 @@
from .asql import Database
from .a_sql import Database
class L9_DB:

60
database/shedule.py Normal file
View File

@ -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'

45
database/shedule.sql Normal file
View File

@ -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
);

View File

@ -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`),