Переделан метод получения групп. Почти доделана публикация сообщений студентам

This commit is contained in:
serafim.urukov 2021-08-14 23:39:45 +03:00
parent ed1d5b8601
commit 0e9444bc34
4 changed files with 94 additions and 27 deletions

View File

@ -88,7 +88,7 @@ def grades():
@superuser
def broadcast(student):
"""Выполняет рассылку студентам."""
return flask.jsonify(student)
return flask.jsonify(app.db.get_all_groups())
@app.errorhandler(StudentAlreadyAuthed)

View File

@ -1,3 +1,4 @@
from collections import defaultdict
import os.path
import pathlib
from sys import path
@ -24,11 +25,13 @@ ASSIGNMENT_ALLOWS = 6
TOKEN_FILE = pathlib.Path() / ".secrets" / "token.json"
CLIENT_SECRET_FILE = pathlib.Path() / ".secrets" / "client_secret.json"
class StudentAlreadyAuthed(Exception):
def __init__(self, message):
self.message = message
super().__init__(self.message)
class AnotherStudentAlreadyAuthed(Exception):
def __init__(self, message):
self.message = message
@ -41,11 +44,13 @@ class Manager:
def __init__(
self,
spreadsheet_id: str = "1GKfmLwDVGjcpXFQAUyxM4RMQ5Nx6HAZ5VWenz2z--d0",
scopes: list = ['https://www.googleapis.com/auth/spreadsheets.readonly',
'https://www.googleapis.com/auth/spreadsheets',
'https://www.googleapis.com/auth/drive.file',
'https://www.googleapis.com/auth/drive.readonly',
'https://www.googleapis.com/auth/drive'],
scopes: list = [
"https://www.googleapis.com/auth/spreadsheets.readonly",
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/drive.file",
"https://www.googleapis.com/auth/drive.readonly",
"https://www.googleapis.com/auth/drive",
],
):
self.spreadsheet_id = spreadsheet_id
@ -74,7 +79,11 @@ class Manager:
def get_values(
self, range_name: str = "StudentList"
) -> list: # TODO: change subject
"""Получить значения с таблицы."""
"""Получить значения с таблицы.
Returns:
list of rows [[val1, val2, ...], [], ...]
"""
result = (
self.sheet.values()
@ -87,11 +96,17 @@ class Manager:
def write_values(self, values: list, range_name: str):
"""Записать значения в таблицу."""
body = {'values' : values}
result = self.sheet.values().update(
spreadsheetId=self.spreadsheet_id, range=range_name,
valueInputOption='USER_ENTERED', body=body).execute()
body = {"values": values}
result = (
self.sheet.values()
.update(
spreadsheetId=self.spreadsheet_id,
range=range_name,
valueInputOption="USER_ENTERED",
body=body,
)
.execute()
)
def get_group(self, group_id: str) -> Group:
"""Получить группу со студентами."""
@ -113,6 +128,23 @@ class Manager:
return group
def get_all_groups(self) -> list:
"""Получить список всех групп."""
values = self.get_values()
groups = defaultdict(lambda: Group("0"))
for row in values:
groups[row[GROUP_IDS]].group_id = row[GROUP_IDS]
groups[row[GROUP_IDS]].add_student(
Student(
int(row[STUDENT_NUMBERS]),
row[STUDENT_NAMES],
row[GROUP_IDS],
row[TELEGRAM_IDS],
)
)
return groups
def get_student_by_name(self, name: str) -> Student:
"""Получить студента по имени."""
@ -149,14 +181,14 @@ class Manager:
f = lambda row: student.group_id == row[GROUP_IDS] # TODO add subject
for row in filter(f, values):
assignment_value = self.get_values(row[ASSIGNMENT_RANGES])
toFloat = lambda x: float(x.replace(',','.'))
toFloat = lambda x: float(x.replace(",", "."))
ass_values = list(map(toFloat, assignment_value[student.number]))
student.add_assignment(
Assignment(row[ASSIGNMENT_NAMES], ass_values,
toFloat(row[ASSIGNMENT_WEIGHTS]))
Assignment(
row[ASSIGNMENT_NAMES], ass_values, toFloat(row[ASSIGNMENT_WEIGHTS])
)
)
def auth_by_token(self, token: str, tg_id: str) -> Student:
"""Аутентификация пользователя через token."""
@ -166,10 +198,11 @@ class Manager:
try:
row = next(filter(f, values))
if row[TELEGRAM_IDS] == tg_id:
raise StudentAlreadyAuthed('Студент уже зарегистрировался')
raise StudentAlreadyAuthed("Студент уже зарегистрировался")
elif row[TELEGRAM_IDS]:
raise AnotherStudentAlreadyAuthed(
'Другой студент зарегистрировался по token')
"Другой студент зарегистрировался по token"
)
row[TELEGRAM_IDS] = tg_id
self.write_values(values, "StudentList")
return Student(

View File

@ -7,15 +7,21 @@ class StudentNotFound(Exception):
super().__init__(self.message)
class Group:
class Group(dict):
"""Объект "Группа" для работы со списком студентов.
Используется для работы с множеством студентов.
"""
def __init__(self, group_id: str):
self.group_id: str = group_id
self._group_id: str = group_id
self._students: Student = []
dict.__init__(
self,
group_id=self.group_id,
students=self._students,
)
def __iter__(self):
"""Делегирует итератор на список студентов.
@ -26,6 +32,15 @@ class Group:
"""
return iter(self._students)
@property
def group_id(self):
return self._group_id
@group_id.setter
def group_id(self, value):
self["group_id"] = value
self._group_id = value
def add_student(self, student: Student):
"""Добавить студента в группу."""
self._students.append(student)

View File

@ -168,13 +168,21 @@ def broadcast(update: Update, context: CallbackContext):
r = requests.get(f"{HOST}/broadcast", params={"tg_id": user_id})
assert r.status_code == 200, "Доступ запрещен к /broadcast"
data = r.json()
access_message.edit_text(f"👨‍💻 {data['name']}")
context.bot_data["groups"] = data
access_message.edit_text(f"✅ Доступ получен")
groups_list = [k for k in data.keys()]
n = 5 # кол-во кнопок в строке
summary_keyboard = []
LOG.info(groups_list)
for i in range((len(groups_list) // n) + 1):
LOG.debug(groups_list[i * n : i * n + n])
keyboard_row = groups_list[i * n : i * n + n]
summary_keyboard.append(keyboard_row)
LOG.info(f"{summary_keyboard}")
reply_keyboard = telegram.ReplyKeyboardMarkup(
[
[telegram.KeyboardButton("5374"), telegram.KeyboardButton("5371")],
[telegram.KeyboardButton("1337")],
],
summary_keyboard,
one_time_keyboard=True,
)
update.message.reply_text("Выбери группу", reply_markup=reply_keyboard)
@ -187,15 +195,26 @@ def broadcast(update: Update, context: CallbackContext):
def publish_message(update: Update, context: CallbackContext):
"""Чел выбирает группу и для нее готовится сообщение."""
message = update.message.text
context.user_data["broadcast_to"] = message
update.message.reply_html(
"🖋 Сообщение для группы:", reply_markup=telegram.ReplyKeyboardRemove()
f"🖋 Сообщение для группы {message}:",
reply_markup=telegram.ReplyKeyboardRemove(),
)
return BROADCAST_PUBLISH_DONE
def publish_done(update: Update, context: CallbackContext):
"""Рассылка выполняется здесь."""
update.message.reply_html("📨 Сообщения разосланы")
# TODO: код работает с диктом, а не с классом. Переделать.
message = update.message.text
group = context.user_data["broadcast_to"]
LOG.info(f"send {group} a message {message}")
for student in context.bot_data["groups"][group]:
LOG.info(f"{student} send message: {message}")
if student.tg_id:
context.bot.send_message(chat_id=student.tg_id, text=message)
return ConversationHandler.END