Merge pull request #12 from Faridik/11-fix-job-grades-checker

Исправлен баг с подпиской на изменения об оценках
This commit is contained in:
Serafim Urukov 2021-10-19 22:37:22 +03:00 committed by GitHub
commit 817b5d9329
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 35 deletions

View File

@ -109,13 +109,17 @@ def student():
@app.route("/students")
@availability
@superuser
def broadcast(*args, **kwargs):
def students(*args, **kwargs):
"""Выполняет рассылку студентам."""
sub_only = flask.request.args.get("sub_only", str(False))
include_assignments = flask.request.args.get("include_assignments", str(False))
include_assignments = include_assignments.lower() == "true"
if sub_only.lower() == "true":
return flask.jsonify(app.db.get_all_groups_only_sub_students())
return flask.jsonify(
app.db.get_all_groups_only_sub_students(include_assignments)
)
else:
return flask.jsonify(app.db.get_all_groups())
return flask.jsonify(app.db.get_all_groups(include_assignments))
@app.route("/sub")

View File

@ -47,7 +47,6 @@ def timed_lru_cache(seconds: int, maxsize: int = 128):
if datetime.utcnow() >= func.expiration:
func.cache_clear()
func.expiration = datetime.utcnow() + func.lifetime
print(*args)
return func(*args, **kwargs)
return wrapped_func
@ -122,7 +121,7 @@ class Manager:
else:
return self._cached_get_values(range_name)
@timed_lru_cache(seconds=25*60)
@timed_lru_cache(seconds=25 * 60)
def _cached_get_values(self, range_name):
return self._get_values(range_name)
@ -174,14 +173,13 @@ class Manager:
return group
def get_all_groups(self) -> list:
def get_all_groups(self, include_assingments: bool = False) -> 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(
student = Student(
number=int(row[STUDENT_NUMBERS]),
name=row[STUDENT_NAMES],
group_id=row[GROUP_IDS],
@ -189,19 +187,22 @@ class Manager:
subjects=row[STUDENT_SUBJECTS].split(","),
is_subbed=bool(int(row[STUDENT_SUBSCRIPTION])),
)
)
if include_assingments:
self.set_assignments_for_student(student)
groups[row[GROUP_IDS]].add_student(student)
return groups
def get_all_groups_only_sub_students(self) -> list:
def get_all_groups_only_sub_students(
self, include_assingments: bool = False
) -> list:
"""Получить список всех групп."""
values = self.get_values()
groups = defaultdict(lambda: Group("0"))
f = lambda row: row[STUDENT_SUBSCRIPTION] == "1"
for row in filter(f, values):
groups[row[GROUP_IDS]].group_id = row[GROUP_IDS]
groups[row[GROUP_IDS]].add_student(
Student(
student = Student(
number=int(row[STUDENT_NUMBERS]),
name=row[STUDENT_NAMES],
group_id=row[GROUP_IDS],
@ -209,8 +210,9 @@ class Manager:
subjects=row[STUDENT_SUBJECTS].split(","),
is_subbed=bool(int(row[STUDENT_SUBSCRIPTION])),
)
)
if include_assingments:
self.set_assignments_for_student(student)
groups[row[GROUP_IDS]].add_student(student)
return groups
def get_student_by_name(self, name: str) -> Student:

View File

@ -396,6 +396,7 @@ def variant(update: Update, context: CallbackContext):
def error(update: Update, context: CallbackContext):
LOG.error(msg="Exception while handling an update:", exc_info=context.error)
if context.error is not None:
update.message.reply_text("Ой, кажется у меня %s" % repr(context.error))
update.message.reply_sticker(MESSAGES.Stickers.DEAD)
return ConversationHandler.END
@ -407,18 +408,21 @@ def error(update: Update, context: CallbackContext):
def grades_checker(context: CallbackContext):
"""Задача по проверке оценок.
Пробегает по списку подписавшихся и для каждого студента запрашивает
`/grades/fingerprint`. Отпечаток (fingerprint) - текстовая строка
захешированных оценок. При изменении оценок, меняется и их хеш. Бот с каждым
вызовом задачи запоминает эти хеши всех студентов и сверяет их. Если вдруг
несовпадение, то значит, что данные об оценках были изменены.
Запрашивает список подписавшихся вместе с подключенными домашками. У
каждого студента проверяет отпечаток. Отпечаток (fingerprint) - текстовая
строка захешированных оценок. При изменении оценок, меняется и их хеш. Бот с
каждым вызовом задачи запоминает эти хеши всех студентов и сверяет их. Если
вдруг несовпадение, то значит, что данные об оценках были изменены.
Это простой и универсальный способ смотреть изменения, но он не дает инфы о
том, в каком задании появилась новая оценка.
"""
r = requests.get(f"{HOST}/students", params={"god_mode": True, "sub_only": True})
r = requests.get(
f"{HOST}/students",
params={"god_mode": True, "sub_only": True, "include_assignments": True},
)
data = r.json()
context.bot_data["groups"] = data
@ -429,8 +433,7 @@ def grades_checker(context: CallbackContext):
for group in data.values():
for student in group["students"]:
tg_id = student["tg_id"]
r = requests.get(f"{HOST}/grades/fingerprint", params={"tg_id": tg_id})
fingerprint = r.json().get("fingerprint", "")
fingerprint = student.get("fingerprint", "")
old_fingerprint = context.bot_data["fingerprints"][tg_id]
# При инициализации у старого отпечатка ещё не установлено значение.
# Там находится пустая строка, поэтому нужна дополн. проверка.