Skip to main content

Async Python client for Мирэа LKS (schedule, grades, attendance, ACS, SSO)

Project description

pymirea

PyPI CI License: MIT Python 3.11+

Асинхронный Python-клиент для Пульса МИРЭА.

Поддерживает: вход с 2FA через Keycloak SSO, расписание занятий, оценки, посещаемость (отметка + детали), события турникетов (ACS), регистрацию в e-sports, шифрование сессий (Fernet + HKDF).

Установка

pip install pymirea

Первый запрос за 30 секунд

import asyncio
from pymirea import Config, configure, MireaAuth

# Сгенерируйте свой ключ один раз и сохраните:
#   python -c "import secrets,base64; print(base64.b64encode(secrets.token_bytes(32)).decode())"
configure(Config(session_keys="ВАША_BASE64_СТРОКА_32_БАЙТА"))

async def main():
    auth = MireaAuth()
    result = await auth.login("ваш_логин@edu.mirea.ru", "пароль")

    if result.challenge:
        # МИРЭА просит OTP (приходит на университетскую почту)
        code = input("Код из email: ")
        result = await auth.complete_2fa(result.challenge, code)

    print("Вошли! Токены:", result.tokens)

asyncio.run(main())

Примеры использования

1. Простой скрипт — получить расписание

import asyncio
from pymirea import Config, configure, MireaAuth, MireaAPI

configure(Config(session_keys="..."))

async def main():
    auth = MireaAuth()
    result = await auth.login("login@edu.mirea.ru", "пароль")
    # ... обработка 2FA если потребуется ...

    api = MireaAPI(session_cookies=result.tokens)
    schedule = await api.get_schedule()
    for day in schedule.days:
        print(f"{day.date}:")
        for lesson in day.lessons:
            print(f"  {lesson.start} {lesson.subject}{lesson.teacher}")

asyncio.run(main())

Полная версия: examples/cli_schedule.py.

2. Telegram-бот на aiogram

from aiogram import Bot, Dispatcher, types
from pymirea import Config, configure, MireaAuth, MireaAPI

configure(Config(session_keys="..."))

bot = Bot(token="...")
dp = Dispatcher()

# user_id -> session cookies (в продакшене — в БД, зашифрованно через SessionCrypto)
sessions: dict[int, dict] = {}

@dp.message(commands=["schedule"])
async def cmd_schedule(msg: types.Message):
    cookies = sessions.get(msg.from_user.id)
    if not cookies:
        await msg.answer("Сначала /login")
        return
    api = MireaAPI(session_cookies=cookies)
    sched = await api.get_schedule()
    text = "\n".join(f"{l.start}{l.subject}" for d in sched.days for l in d.lessons)
    await msg.answer(text)

Полная версия: examples/telegram_bot.py.

3. Отметить посещаемость себе и друзьям одним QR-сканом

Классический MireaScanner-флоу — сделайте своё приложение за 20 минут:

from pymirea import MireaAPI, SessionCrypto
from pymirea.crypto import get_crypto

crypto = get_crypto()

# Загрузите из своей БД зашифрованные сессии друзей
friends = [
    (123, "Саша", crypto.decrypt_session(row_sasha)),
    (456, "Петя", crypto.decrypt_session(row_petya)),
]

api = MireaAPI(session_cookies=my_session)
results = await api.mark_attendance_for_group(qr_data, friends)

for r in results:
    print(f"{r.user_name}: {'✓' if r.success else '✗ ' + r.message}")

mark_attendance_for_group сам извлекает токен из QR-URL, проходит по всем переданным сессиям и возвращает список AttendanceResult — готово к отображению в UI.

4. FastAPI-веб-сервис

from fastapi import FastAPI, Depends, HTTPException
from pymirea import Config, configure, MireaAPI
from pymirea.crypto import get_crypto

configure(Config(session_keys="..."))
crypto = get_crypto()
app = FastAPI()

def current_session(token: str = Depends(...)) -> dict:
    """Расшифровать сессию пользователя из вашего хранилища."""
    encrypted = your_db.get_mirea_session(user_id_from(token))
    if not encrypted:
        raise HTTPException(401)
    return crypto.decrypt_session(encrypted)

@app.get("/api/schedule")
async def get_schedule(session: dict = Depends(current_session)):
    api = MireaAPI(session_cookies=session)
    return await api.get_schedule()

Полная версия: examples/fastapi_app.py.

Примеров для QR-сканирования в папке examples/ пока нет — PR приветствуется.

Шифрование сессий

Хранить cookies МИРЭА в БД в открытом виде нельзя — SessionCrypto оборачивает их в Fernet-токен с ключом, выведенным через HKDF из вашего session_keys:

from pymirea.crypto import get_crypto

crypto = get_crypto()
encrypted: str = crypto.encrypt_session(cookies_dict)   # сохраните в БД
decrypted: dict = crypto.decrypt_session(encrypted)     # прочтите из БД

При смене session_keys старые токены становятся нечитаемыми — храните старый ключ в legacy_bot_token для grace-period миграции.

Public API

Имя Назначение
Config / configure(Config) Конфигурация runtime (DI-style, вызывается один раз на старте)
MireaAuth login(), complete_2fa(), refresh-token flow
MireaAPI get_schedule(), get_grades(), get_attendance(), mark_attendance(), mark_attendance_for_group()
MireaACS События турникетов через pulse.mirea.ru
MireaEsports Регистрация в e-sports
SessionCrypto Шифрование/расшифровка cookies (Fernet + HKDF)
AuthChallenge / AuthResult Результаты login-флоу
get_authorization_header(cookies) Bearer-токен из dict сессии
try_refresh_tokens(cookies) Best-effort обновление access-токена
get_token_age_seconds(cookies) Сколько секунд токен живёт

Подробнее в исходниках: pymirea/.

Конфигурация

from pymirea import Config

Config(
    session_keys="base64-32-bytes",     # обязательно
    mirea_proxy="http://proxy:8080",    # опционально, для pulse.mirea.ru (датацентры заблокированы)
    legacy_bot_token=None,              # старый ключ для миграции при ротации
    request_timeout_s=15.0,
    breaker_failure_threshold=5,
    breaker_recovery_s=30.0,
)

Совместимость

  • Python 3.11+
  • Только async (нет sync-обёртки; для скриптов используйте asyncio.run)
  • Любой web-фреймворк: FastAPI, aiohttp, Sanic, Litestar, Quart — pymirea не привязан ни к одному
  • Любая БД для хранения сессий — pymirea даёт только примитивы шифрования

Что pymirea НЕ делает

  • ❌ Не хранит сессии — это задача вашего приложения (БД/Redis/файл)
  • ❌ Не управляет пользователями — у вас своя auth-система
  • ❌ Не предоставляет HTTP-handlers — пишите свои под свой фреймворк
  • ❌ Не парсит сложные нестандартные формы МИРЭА (профили, дипломы — TBD)

Если хочется готовый микросервис — соберите Telegram-бот / FastAPI-сервис на основе примеров.

Внести вклад

Issues и PR приветствуются. Особенно полезно:

  • Тесты для новых сценариев (logout, edge-cases в 2FA, etc.)
  • Поддержка дополнительных эндпоинтов МИРЭА
  • Примеры для других фреймворков (Discord-боты, CLI-tools, ...)

Лицензия

MIT — см. LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pymirea-0.2.0.tar.gz (56.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pymirea-0.2.0-py3-none-any.whl (55.1 kB view details)

Uploaded Python 3

File details

Details for the file pymirea-0.2.0.tar.gz.

File metadata

  • Download URL: pymirea-0.2.0.tar.gz
  • Upload date:
  • Size: 56.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pymirea-0.2.0.tar.gz
Algorithm Hash digest
SHA256 a5ab5168dade80f2794a4c0b79836e183cbff30bfd43204a720f43fab09647a9
MD5 8535bd1e7884d739d78ad807a806086d
BLAKE2b-256 8a84140b7eae1d1c7b61f167d317260c8251d781e15adb1b4ed5706b9515c1cf

See more details on using hashes here.

Provenance

The following attestation bundles were made for pymirea-0.2.0.tar.gz:

Publisher: release.yml on silverhans/pymirea

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pymirea-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: pymirea-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 55.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pymirea-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d589b71e4d4cefef140b5e0471fb1debe21085e54fcc89570df02290fcb5799c
MD5 fb084c85db35cf76b16f00263f61cb7b
BLAKE2b-256 3be73651ec7abc825578d9c93f3247cd0f8d85be5c107ce4094a58d2ee4bdfcf

See more details on using hashes here.

Provenance

The following attestation bundles were made for pymirea-0.2.0-py3-none-any.whl:

Publisher: release.yml on silverhans/pymirea

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page