Приложение ВИШ — расписание РУТ (МИИТ)

Расписание Российского университета транспорта для студентов и сотрудников всех институтов. Расписание своей группы и любого преподавателя на день и на неделю, свободные аудитории МИИТ прямо сейчас, загруженность аудиторий, групп и преподавателей, уведомления об изменениях в расписании и ИИ-помощник по расписанию.

Институты

Приложение РУТ (МИИТ) охватывает пять институтов: ВИШ — Высшая инженерная школа, АГА — Академия гражданской авиации, АДХ — Академия дорожного хозяйства, ПИШ — Передовая инженерная школа «Академия ВСМ» и ИМТК — Институт международных транспортных коммуникаций. Расписание группы и расписание преподавателя ищутся одинаково в любом из них.

Что умеет приложение ВИШ
Разделы
Руководство

Уведомления и календари

Обновлено 27.10.2026

Как узнавать об изменениях в расписании, не спрашивая API каждую минуту. Сверено со стендом d1 23 октября 2026 года; методы этой страницы есть и на production.

Что выбрать

ЗадачаЧем решать
Расписание в Google Календаре, Apple Calendar, OutlookПодписка на календарную ленту GET /calendar/schedule.ics
Экзамены и зачёты в календареGET /session.ics
Бот или сервис, который сообщает об измененияхОпрос GET /schedule/changes раз в несколько минут
Полная копия расписания у себяGET /schedule раз в час-другой, сравнение по updatedAt
Push в браузерТолько для самого приложения ВИШ — см. ниже

Календарная лента

GET /calendar/schedule.ics отдаёт расписание в формате iCalendar с теми же фильтрами, что GET /schedule: group или groupId, teacher или teacherId, scope, dateFrom, dateTo, а ещё lessonIds и subjectIds (только эти занятия или предметы), locale (ru, en, zh) и attachment=1 (отдать файлом).

  • Ключ не нужен: это то же расписание, что видит любой посетитель.
  • Подпишитесь на адрес — календарь сам перечитывает его и подхватывает правки, отмены и удаления. У каждого занятия постоянный UID, поэтому изменение обновляет событие, а не добавляет второе.
  • Время — с часовым поясом (DTSTART;TZID=Europe/Moscow:…).
  • Не чаще 60 запросов в минуту с одного адреса.
text
https://d1.vish-app.ru/api/v1/calendar/schedule.ics?group=ШАД-111

GET /session.ics — то же для сессии: экзамены, зачёты и консультации группы или преподавателя.

Лента изменений

GET /schedule/changes — что недавно изменилось в расписании одной группы (groupId) или преподавателя (teacherId), новое сверху.

  • period=recent (по умолчанию) — последние изменения; limit — сколько.
  • period=weeks — изменения занятий этой и следующей недели.
  • У записи: lessonId, change (created, announced, updated, deleted), subject, room, startAt, endAt, changedFields, changes (поле, было, стало), origin (institute — правка в институте, source — новое расписание университета) и createdAt.

Как опрашивать: раз в 5–15 минут, запоминая id или createdAt последней обработанной записи, и обрабатывать только то, что новее. Ответ с period=weeks кэшируется на минуту — чаще спрашивать бессмысленно.

Push в браузере

POST /push/subscriptions и POST /push/unsubscribe подписывают браузер приложения ВИШ на уведомления об изменениях группы или преподавателя; публичный ключ VAPID для подписки — в GET /app-config (push.publicKey). Эти методы рассчитаны на само приложение ВИШ: подписку создаёт его service worker. Своему сайту или боту удобнее лента изменений.

Не удалось загрузить список методов APIОткрыть справочник API (откроется в новой вкладке)

Пример: лента и изменения

Пример скачивает календарную ленту группы, проверяет её формат и уникальность UID, а затем читает изменения этой и следующей недели. Группа — в VISH_GROUP, по умолчанию ШАД-111.

// The group's calendar feed and its recent changes; no key needed.
const API = process.env.VISH_API ?? 'https://d1.vish-app.ru/api/v1'
const GROUP = process.env.VISH_GROUP ?? 'ШАД-111'

const groups = await (await fetch(`${API}/groups?search=${encodeURIComponent(GROUP)}&all=1`)).json()
const group = groups.list.find((item) => item.name === GROUP)
if (!group) throw new Error(`group ${GROUP} not found`)

const feed = await fetch(`${API}/calendar/schedule.ics?group=${encodeURIComponent(GROUP)}`)
const calendar = await feed.text()
if (!feed.ok || !feed.headers.get('content-type')?.startsWith('text/calendar') || !calendar.startsWith('BEGIN:VCALENDAR')) {
	throw new Error(`not a calendar: HTTP ${feed.status}`)
}
const uids = [...calendar.matchAll(/^UID:(.+)$/gmu)].map((match) => match[1].trim())
if (new Set(uids).size !== uids.length) throw new Error('duplicate UIDs')

const response = await fetch(`${API}/schedule/changes?groupId=${group.id}&period=weeks`)
if (!response.ok) throw new Error(`changes: HTTP ${response.status}`)
const changes = (await response.json()).list
if (!Array.isArray(changes) || changes.some((item) => !item.lessonId || !item.change || !item.createdAt)) {
	throw new Error('unexpected changes answer')
}

console.log(`${GROUP}: ${uids.length} events in the feed, ${changes.length} changes this week and next`)
for (const item of changes.slice(0, 5)) {
	console.log(`- ${item.createdAt.slice(0, 16)} ${item.change}: ${item.subject?.ru ?? item.lessonId} (${item.changedFields?.join(', ') ?? ''})`)
}

Попробовать

Текущая неделя, сетка звонков и публичный ключ для push:

Попробовать запрос

Ключ нужен только методам с замком. Он живёт только на этой странице: не сохраняется, уходит лишь заголовком этого запроса и забывается, когда вы её покинете. Где взять ключ

Проверено: 2026-10, PWA aa337c45, platform bff65fce.