Skip to content

Instantly share code, notes, and snippets.

@git-ethan-mars
Created October 15, 2025 09:45
Show Gist options
  • Select an option

  • Save git-ethan-mars/1bf7ebaf9e8ea79fcf45bd612b6c3695 to your computer and use it in GitHub Desktop.

Select an option

Save git-ethan-mars/1bf7ebaf9e8ea79fcf45bd612b6c3695 to your computer and use it in GitHub Desktop.
import os
import requests
# === Конфигурация ===
MOODLE_URL = "https://elearn.urfu.ru"
TOKEN = os.getenv('moodle_token') # ← ЗАМЕНИТЕ на ваш токен!
DOWNLOAD_DIR = "downloads" # Папка для скачанных файлов
os.makedirs(DOWNLOAD_DIR, exist_ok=True)
def moodle_request(wsfunction: str, params: dict) -> dict:
"""Универсальный запрос к Moodle REST API."""
base_params = {
'wstoken': TOKEN,
'wsfunction': wsfunction,
'moodlewsrestformat': 'json'
}
base_params.update(params)
try:
resp = requests.post(f"{MOODLE_URL}/webservice/rest/server.php", data=base_params)
except requests.RequestException as e:
raise Exception(f"Ошибка сети: {e}")
if resp.status_code != 200:
raise Exception(f"HTTP {resp.status_code}: {resp.text[:500]}")
try:
data = resp.json()
except requests.JSONDecodeError:
raise Exception(f"Ответ не в формате JSON. Ответ: {resp.text[:500]}")
if isinstance(data, dict) and 'exception' in data:
raise Exception(f"Moodle error: {data.get('message', 'Unknown')}")
return data
def get_assign_id_by_cmid(cmid: int) -> int:
"""Получает assign id по cmid."""
data = moodle_request('core_course_get_course_module', {'cmid': cmid})
return data['cm']['instance']
def get_student_submission(assign_id: int, user_id: int):
"""Получает сабмит студента."""
data = moodle_request('mod_assign_get_submissions', {'assignmentids[0]': assign_id})
assignments = data.get('assignments', [])
if not assignments:
return None
submissions = assignments[0].get('submissions', [])
return next((s for s in submissions if s.get('userid') == user_id), None)
def extract_student_answer(submission: dict) -> str:
"""Извлекает текстовый ответ студента."""
for plugin in submission.get('plugins', []):
if plugin.get('type') == 'onlinetext':
for field in plugin.get('editorfields', []):
if field.get('name') == 'onlinetext':
return field.get('text', '')
return ""
def extract_teacher_comment(submission: dict) -> str:
"""Извлекает комментарий преподавателя."""
for plugin in submission.get('plugins', []):
if plugin.get('type') == 'comments':
for field in plugin.get('editorfields', []):
if field.get('name') == 'text':
return field.get('text', '')
return ""
def download_student_files(submission: dict, user_id: int):
"""
Скачивает все файлы, прикреплённые студентом к заданию.
Файлы сохраняются в папку downloads/.
"""
files = []
for plugin in submission.get('plugins', []):
if plugin.get('type') == 'file':
files.extend(plugin.get('fileareas', [{}])[0].get('files', []))
if not files:
print("📎 Файлы не прикреплены.")
return
print(f"📎 Найдено файлов: {len(files)}")
for f in files:
filename = f['filename']
file_url = f['fileurl']
# Добавляем токен к URL для доступа
if '?' in file_url:
download_url = f"{file_url}&token={TOKEN}"
else:
download_url = f"{file_url}?token={TOKEN}"
safe_filename = f"{user_id}_{filename}"
filepath = os.path.join(DOWNLOAD_DIR, safe_filename)
print(f" ↓ Скачивание: {safe_filename}")
try:
r = requests.get(download_url)
r.raise_for_status()
with open(filepath, 'wb') as out:
out.write(r.content)
print(f" ✅ Сохранён: {filepath}")
except Exception as e:
print(f" ❌ Ошибка при скачивании {filename}: {e}")
def save_grade(assign_id: int, user_id: int, grade: float, feedback: str, format_type: int = 1):
"""Выставляет оценку и комментарий."""
params = {
'assignmentid': assign_id,
'applytoall': 0,
'grades[0][userid]': user_id,
'grades[0][grade]': grade,
'grades[0][attemptnumber]': -1,
'grades[0][addattempt]': 0,
'grades[0][workflowstate]': 'graded',
'grades[0][plugindata][assignfeedbackcomments_editor][text]': feedback,
'grades[0][plugindata][assignfeedbackcomments_editor][format]': format_type,
}
moodle_request('mod_assign_save_grades', params)
print("✅ Оценка успешно выставлена!")
def main():
CMID = 177171 # из .../view.php?id=177171
STUDENT_ID = 55838 # из ...&userid=13267
try:
assign_id = get_assign_id_by_cmid(CMID)
submission = get_student_submission(assign_id, STUDENT_ID)
if not submission:
print("⚠️ Сабмит студента не найден.")
return
# Текстовый ответ
ans = extract_student_answer(submission)
print("\n📝 Текстовый ответ студента:")
print(ans or "[отсутствует]")
# Комментарий преподавателя
comm = extract_teacher_comment(submission)
print("\n💬 Текущий комментарий преподавателя:")
print(comm or "[отсутствует]")
# Скачивание файлов
print("\n📁 Работа с прикреплёнными файлами:")
download_student_files(submission, STUDENT_ID)
# Пример выставления оценки (раскомментируйте, если нужно)
# save_grade(assign_id, STUDENT_ID, grade=88.0, feedback="Хорошо, но есть замечания.")
except Exception as e:
print(f"❌ Ошибка: {e}")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment