miet-schedule-api 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- miet_schedule_api-0.1.0/LICENSE +21 -0
- miet_schedule_api-0.1.0/MANIFEST.in +3 -0
- miet_schedule_api-0.1.0/PKG-INFO +157 -0
- miet_schedule_api-0.1.0/README.md +134 -0
- miet_schedule_api-0.1.0/miet_schedule_api/__init__.py +34 -0
- miet_schedule_api-0.1.0/miet_schedule_api/consts.py +56 -0
- miet_schedule_api-0.1.0/miet_schedule_api/core.py +303 -0
- miet_schedule_api-0.1.0/miet_schedule_api/parser.py +150 -0
- miet_schedule_api-0.1.0/miet_schedule_api.egg-info/PKG-INFO +157 -0
- miet_schedule_api-0.1.0/miet_schedule_api.egg-info/SOURCES.txt +15 -0
- miet_schedule_api-0.1.0/miet_schedule_api.egg-info/dependency_links.txt +1 -0
- miet_schedule_api-0.1.0/miet_schedule_api.egg-info/requires.txt +1 -0
- miet_schedule_api-0.1.0/miet_schedule_api.egg-info/top_level.txt +1 -0
- miet_schedule_api-0.1.0/pyproject.toml +27 -0
- miet_schedule_api-0.1.0/requirements.txt +1 -0
- miet_schedule_api-0.1.0/setup.cfg +4 -0
- miet_schedule_api-0.1.0/setup.py +27 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Deka
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the Software), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: miet-schedule-api
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Небольшая библиотека для получения расписания групп МИЭТ
|
|
5
|
+
Home-page: https://github.com/TheDIMONDK/miet_schedule_api
|
|
6
|
+
Author: Deka
|
|
7
|
+
Author-email: Deka <dka@disroot.org>
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Homepage, https://github.com/TheDIMONDK/miet_schedule_api
|
|
10
|
+
Project-URL: Repository, https://github.com/TheDIMONDK/miet_schedule_api
|
|
11
|
+
Project-URL: Issues, https://github.com/TheDIMONDK/miet_schedule_api/issues
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Requires-Python: >=3.6
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: requests>=2.25.0
|
|
19
|
+
Dynamic: author
|
|
20
|
+
Dynamic: home-page
|
|
21
|
+
Dynamic: license-file
|
|
22
|
+
Dynamic: requires-python
|
|
23
|
+
|
|
24
|
+
# MIET Schedule API
|
|
25
|
+
|
|
26
|
+
Небольшая библиотека для получения и структурирования расписания указанных групп МИЭТ.
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
## Возможности
|
|
30
|
+
- Получение расписания для любой группы из списка МИЭТ.
|
|
31
|
+
- Проверка существования группы перед запросом, используя официальное API.
|
|
32
|
+
- Получение расписания на одну дату или диапазон дат, формат: `ДД.ММ.ГГГГ` или `ДД.ММ.ГГГГ-ДД.ММ.ГГГГ`.
|
|
33
|
+
- Получение расписания на текущую, следующую или предыдущую неделю.
|
|
34
|
+
- Кэширование данных в едином файле `last_data.json`, чтобы не мучать API МИЭТ.
|
|
35
|
+
- Принудительное обновление кэша через параметр `force=True`.
|
|
36
|
+
- Пропуск дней, состоящих только из военной подготовки, управляется флагом `SKIP_MILITARY`.
|
|
37
|
+
- Автоматическое определение года начала семестра: если текущий месяц >= сентября, используется текущий год, иначе - предыдущий.
|
|
38
|
+
- Возможность явно установить дату начала семестра через функцию `set_semester_start()`.
|
|
39
|
+
- Возврат результата с мета-информацией: `isFromCache` источник данных, `data` само расписание и `meta` - метаинформация о неделях для каждой даты.
|
|
40
|
+
- Возврат в виде словаря или отформатированной строки JSON, это управляется параметрами `return_json` и `pretty`.
|
|
41
|
+
|
|
42
|
+
> Важно: библиотека пока не учитывает каникулы и праздничные дни.
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
## Структура вывода
|
|
46
|
+
```jsonc
|
|
47
|
+
{
|
|
48
|
+
"isFromCache": true, // Вывод был закэширован, или было прямое обращение к API?
|
|
49
|
+
"data": {
|
|
50
|
+
"01.09.2026": { // День
|
|
51
|
+
"1": {
|
|
52
|
+
"time": ["09:00", "10:20"],
|
|
53
|
+
"title": "Название",
|
|
54
|
+
"type": "Лекция",
|
|
55
|
+
"full_name": "Фамилия Имя Отчество",
|
|
56
|
+
"room": "1201"
|
|
57
|
+
},
|
|
58
|
+
...
|
|
59
|
+
},
|
|
60
|
+
"02.09.2026": {...},
|
|
61
|
+
...
|
|
62
|
+
},
|
|
63
|
+
"meta": {
|
|
64
|
+
"weeks": {
|
|
65
|
+
"01.09.2026": {
|
|
66
|
+
"number": 1, // Номер недели по счёту в этом дне
|
|
67
|
+
"type": 0, // Тип недели, 1-й/2-й числитель/знаменатель в виде простого ID
|
|
68
|
+
"typeString": "Числитель - 1" // Тоже самое, но уже приведённое к читаемому виду
|
|
69
|
+
},
|
|
70
|
+
"02.09.2026": {...},
|
|
71
|
+
...
|
|
72
|
+
},
|
|
73
|
+
"total_weeks": 20 // Общее количество недель
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
## Установка
|
|
80
|
+
### Локальная установка / для разработки
|
|
81
|
+
```sh
|
|
82
|
+
pip install -e .
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Установка из PyPI
|
|
86
|
+
```sh
|
|
87
|
+
pip install miet_schedule_api
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Установка из GitHub
|
|
91
|
+
```sh
|
|
92
|
+
pip install git+https://github.com/TheDIMONDK/miet_schedule_api.git
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Использование
|
|
96
|
+
```py
|
|
97
|
+
from miet_schedule_api import *
|
|
98
|
+
|
|
99
|
+
# Получить список всех существующих групп
|
|
100
|
+
groups = get_groups_list()
|
|
101
|
+
print(groups)
|
|
102
|
+
|
|
103
|
+
# Расписание на один день, смотрим на само расписание без метаданных
|
|
104
|
+
schedule = get_schedule(group="ИТД-11", date_str="01.09.2026")
|
|
105
|
+
print(schedule["data"])
|
|
106
|
+
|
|
107
|
+
# Диапазон дат, вдобавок возвращаем и красивую JSON-строку
|
|
108
|
+
schedule_json = get_schedule_range(
|
|
109
|
+
group="ИТД-11",
|
|
110
|
+
start_date_str="01.09.2026",
|
|
111
|
+
end_date_str="05.09.2026",
|
|
112
|
+
return_json=True,
|
|
113
|
+
pretty=True
|
|
114
|
+
)
|
|
115
|
+
print(schedule_json)
|
|
116
|
+
|
|
117
|
+
# Расписание+метаданные текущей недели с понедельника по воскресенье
|
|
118
|
+
current_week = get_current_week(group="ИТД-11", return_json=True, pretty=True)
|
|
119
|
+
print(current_week)
|
|
120
|
+
|
|
121
|
+
# Расписание+метаданные следующей недели относительно сегодня
|
|
122
|
+
next_week = get_next_week(group="ИТД-11", return_json=True, pretty=True)
|
|
123
|
+
print(next_week)
|
|
124
|
+
|
|
125
|
+
# Расписание+метаданные предыдущей недели относительно заданной даты
|
|
126
|
+
prev_week = get_previous_week(group="ИТД-11", date_str="15.09.2026", return_json=True, pretty=True)
|
|
127
|
+
print(prev_week)
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
## Параметры функций
|
|
132
|
+
- `group` (str, обязательный) - код группы.
|
|
133
|
+
- `return_json` (bool, default=False) - если True, возвращает строку JSON вместо словаря.
|
|
134
|
+
- `pretty` (bool, default=False) - если True и `return_json=True`, JSON выводится с отступами.
|
|
135
|
+
- `force` (bool, default=False) - принудительно запрашивает данные с сервера, игнорируя кэш.
|
|
136
|
+
- `date_str` (str) - дата в формате `ДД.ММ.ГГГГ`, для функций недели опциональна.
|
|
137
|
+
- `start_date_str`, `end_date_str` (str) - начальная и конечная даты диапазона.
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
## Разработка
|
|
141
|
+
### Сборка пакета
|
|
142
|
+
```sh
|
|
143
|
+
pip install build
|
|
144
|
+
python -m build
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Конфигурация
|
|
148
|
+
Базовые настройки по умолчанию находятся в `miet_schedule_api/consts.py`:
|
|
149
|
+
|
|
150
|
+
- `API_URL` - URL для запроса расписания.
|
|
151
|
+
- `GROUPS_URL` - URL для получения списка групп.
|
|
152
|
+
- `TOTAL_WEEKS` - общее количество недель в семестре, по умолчанию 20.
|
|
153
|
+
- `SKIP_MILITARY` - пропускать ли дни с военной подготовкой.
|
|
154
|
+
- `SEMESTER_START` - автоматически вычисляется, но можно переопределить, если нужно.
|
|
155
|
+
|
|
156
|
+
## Лицензия
|
|
157
|
+
MIT
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# MIET Schedule API
|
|
2
|
+
|
|
3
|
+
Небольшая библиотека для получения и структурирования расписания указанных групп МИЭТ.
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
## Возможности
|
|
7
|
+
- Получение расписания для любой группы из списка МИЭТ.
|
|
8
|
+
- Проверка существования группы перед запросом, используя официальное API.
|
|
9
|
+
- Получение расписания на одну дату или диапазон дат, формат: `ДД.ММ.ГГГГ` или `ДД.ММ.ГГГГ-ДД.ММ.ГГГГ`.
|
|
10
|
+
- Получение расписания на текущую, следующую или предыдущую неделю.
|
|
11
|
+
- Кэширование данных в едином файле `last_data.json`, чтобы не мучать API МИЭТ.
|
|
12
|
+
- Принудительное обновление кэша через параметр `force=True`.
|
|
13
|
+
- Пропуск дней, состоящих только из военной подготовки, управляется флагом `SKIP_MILITARY`.
|
|
14
|
+
- Автоматическое определение года начала семестра: если текущий месяц >= сентября, используется текущий год, иначе - предыдущий.
|
|
15
|
+
- Возможность явно установить дату начала семестра через функцию `set_semester_start()`.
|
|
16
|
+
- Возврат результата с мета-информацией: `isFromCache` источник данных, `data` само расписание и `meta` - метаинформация о неделях для каждой даты.
|
|
17
|
+
- Возврат в виде словаря или отформатированной строки JSON, это управляется параметрами `return_json` и `pretty`.
|
|
18
|
+
|
|
19
|
+
> Важно: библиотека пока не учитывает каникулы и праздничные дни.
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
## Структура вывода
|
|
23
|
+
```jsonc
|
|
24
|
+
{
|
|
25
|
+
"isFromCache": true, // Вывод был закэширован, или было прямое обращение к API?
|
|
26
|
+
"data": {
|
|
27
|
+
"01.09.2026": { // День
|
|
28
|
+
"1": {
|
|
29
|
+
"time": ["09:00", "10:20"],
|
|
30
|
+
"title": "Название",
|
|
31
|
+
"type": "Лекция",
|
|
32
|
+
"full_name": "Фамилия Имя Отчество",
|
|
33
|
+
"room": "1201"
|
|
34
|
+
},
|
|
35
|
+
...
|
|
36
|
+
},
|
|
37
|
+
"02.09.2026": {...},
|
|
38
|
+
...
|
|
39
|
+
},
|
|
40
|
+
"meta": {
|
|
41
|
+
"weeks": {
|
|
42
|
+
"01.09.2026": {
|
|
43
|
+
"number": 1, // Номер недели по счёту в этом дне
|
|
44
|
+
"type": 0, // Тип недели, 1-й/2-й числитель/знаменатель в виде простого ID
|
|
45
|
+
"typeString": "Числитель - 1" // Тоже самое, но уже приведённое к читаемому виду
|
|
46
|
+
},
|
|
47
|
+
"02.09.2026": {...},
|
|
48
|
+
...
|
|
49
|
+
},
|
|
50
|
+
"total_weeks": 20 // Общее количество недель
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
## Установка
|
|
57
|
+
### Локальная установка / для разработки
|
|
58
|
+
```sh
|
|
59
|
+
pip install -e .
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Установка из PyPI
|
|
63
|
+
```sh
|
|
64
|
+
pip install miet_schedule_api
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Установка из GitHub
|
|
68
|
+
```sh
|
|
69
|
+
pip install git+https://github.com/TheDIMONDK/miet_schedule_api.git
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Использование
|
|
73
|
+
```py
|
|
74
|
+
from miet_schedule_api import *
|
|
75
|
+
|
|
76
|
+
# Получить список всех существующих групп
|
|
77
|
+
groups = get_groups_list()
|
|
78
|
+
print(groups)
|
|
79
|
+
|
|
80
|
+
# Расписание на один день, смотрим на само расписание без метаданных
|
|
81
|
+
schedule = get_schedule(group="ИТД-11", date_str="01.09.2026")
|
|
82
|
+
print(schedule["data"])
|
|
83
|
+
|
|
84
|
+
# Диапазон дат, вдобавок возвращаем и красивую JSON-строку
|
|
85
|
+
schedule_json = get_schedule_range(
|
|
86
|
+
group="ИТД-11",
|
|
87
|
+
start_date_str="01.09.2026",
|
|
88
|
+
end_date_str="05.09.2026",
|
|
89
|
+
return_json=True,
|
|
90
|
+
pretty=True
|
|
91
|
+
)
|
|
92
|
+
print(schedule_json)
|
|
93
|
+
|
|
94
|
+
# Расписание+метаданные текущей недели с понедельника по воскресенье
|
|
95
|
+
current_week = get_current_week(group="ИТД-11", return_json=True, pretty=True)
|
|
96
|
+
print(current_week)
|
|
97
|
+
|
|
98
|
+
# Расписание+метаданные следующей недели относительно сегодня
|
|
99
|
+
next_week = get_next_week(group="ИТД-11", return_json=True, pretty=True)
|
|
100
|
+
print(next_week)
|
|
101
|
+
|
|
102
|
+
# Расписание+метаданные предыдущей недели относительно заданной даты
|
|
103
|
+
prev_week = get_previous_week(group="ИТД-11", date_str="15.09.2026", return_json=True, pretty=True)
|
|
104
|
+
print(prev_week)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
## Параметры функций
|
|
109
|
+
- `group` (str, обязательный) - код группы.
|
|
110
|
+
- `return_json` (bool, default=False) - если True, возвращает строку JSON вместо словаря.
|
|
111
|
+
- `pretty` (bool, default=False) - если True и `return_json=True`, JSON выводится с отступами.
|
|
112
|
+
- `force` (bool, default=False) - принудительно запрашивает данные с сервера, игнорируя кэш.
|
|
113
|
+
- `date_str` (str) - дата в формате `ДД.ММ.ГГГГ`, для функций недели опциональна.
|
|
114
|
+
- `start_date_str`, `end_date_str` (str) - начальная и конечная даты диапазона.
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
## Разработка
|
|
118
|
+
### Сборка пакета
|
|
119
|
+
```sh
|
|
120
|
+
pip install build
|
|
121
|
+
python -m build
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Конфигурация
|
|
125
|
+
Базовые настройки по умолчанию находятся в `miet_schedule_api/consts.py`:
|
|
126
|
+
|
|
127
|
+
- `API_URL` - URL для запроса расписания.
|
|
128
|
+
- `GROUPS_URL` - URL для получения списка групп.
|
|
129
|
+
- `TOTAL_WEEKS` - общее количество недель в семестре, по умолчанию 20.
|
|
130
|
+
- `SKIP_MILITARY` - пропускать ли дни с военной подготовкой.
|
|
131
|
+
- `SEMESTER_START` - автоматически вычисляется, но можно переопределить, если нужно.
|
|
132
|
+
|
|
133
|
+
## Лицензия
|
|
134
|
+
MIT
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Небольшая библиотека для получения расписания групп МИЭТ.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from .core import (
|
|
6
|
+
get_schedule,
|
|
7
|
+
get_schedule_range,
|
|
8
|
+
get_current_week,
|
|
9
|
+
get_next_week,
|
|
10
|
+
get_previous_week,
|
|
11
|
+
fetch_schedule,
|
|
12
|
+
get_groups_list,
|
|
13
|
+
validate_group,
|
|
14
|
+
load_cached_data,
|
|
15
|
+
save_cached_data,
|
|
16
|
+
set_semester_start,
|
|
17
|
+
set_skip_military,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
__version__ = "0.1.0"
|
|
21
|
+
__all__ = [
|
|
22
|
+
"get_schedule",
|
|
23
|
+
"get_schedule_range",
|
|
24
|
+
"get_current_week",
|
|
25
|
+
"get_next_week",
|
|
26
|
+
"get_previous_week",
|
|
27
|
+
"fetch_schedule",
|
|
28
|
+
"get_groups_list",
|
|
29
|
+
"validate_group",
|
|
30
|
+
"load_cached_data",
|
|
31
|
+
"save_cached_data",
|
|
32
|
+
"set_semester_start",
|
|
33
|
+
"set_skip_military",
|
|
34
|
+
]
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Константы для скрипта расписания.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# URL API расписания МИЭТ
|
|
9
|
+
API_URL = "https://miet.ru/schedule/data"
|
|
10
|
+
|
|
11
|
+
# URL API списка групп
|
|
12
|
+
GROUPS_URL = "https://miet.ru/schedule/groups"
|
|
13
|
+
|
|
14
|
+
# Общее количество недель в семестре
|
|
15
|
+
TOTAL_WEEKS = 20
|
|
16
|
+
|
|
17
|
+
# Если истина, дни, состоящие только из занятий "Военная подготовка",
|
|
18
|
+
# будут считаться свободными и возвращаться как {}
|
|
19
|
+
SKIP_MILITARY = True
|
|
20
|
+
|
|
21
|
+
# Внутренняя переменная для хранения даты начала семестра
|
|
22
|
+
_SEMESTER_START = None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def get_semester_start() -> str:
|
|
26
|
+
"""
|
|
27
|
+
Функция для возврата даты начала семестра в формате ДД.ММ.ГГГГ.
|
|
28
|
+
Если дата не была установлена явно через сеттер,
|
|
29
|
+
она вычисляется автоматически на основе текущей даты:
|
|
30
|
+
- если текущий месяц >= 9 (сентябрь), то год текущий,
|
|
31
|
+
- иначе год предыдущий.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
global _SEMESTER_START
|
|
35
|
+
if _SEMESTER_START is None:
|
|
36
|
+
_CURRENT_YEAR = datetime.now().year
|
|
37
|
+
_CURRENT_MONTH = datetime.now().month
|
|
38
|
+
if _CURRENT_MONTH >= 9:
|
|
39
|
+
_SEMESTER_START = f"01.09.{_CURRENT_YEAR}"
|
|
40
|
+
|
|
41
|
+
else:
|
|
42
|
+
_SEMESTER_START = f"01.09.{_CURRENT_YEAR - 1}"
|
|
43
|
+
|
|
44
|
+
return _SEMESTER_START
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def set_semester_start(new_start: str):
|
|
48
|
+
"""
|
|
49
|
+
Явно устанавливает дату начала семестра в формате ДД.ММ.ГГГГ.
|
|
50
|
+
"""
|
|
51
|
+
global _SEMESTER_START
|
|
52
|
+
_SEMESTER_START = new_start
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# Для обратной совместимости сохраняем константу, но она теперь вычисляется при первом обращении
|
|
56
|
+
SEMESTER_START = get_semester_start()
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Основной модуль библиотеки для получения расписания.
|
|
3
|
+
Предоставляет функции для загрузки, кэширования и парсинга расписания.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import json
|
|
7
|
+
import os
|
|
8
|
+
import requests
|
|
9
|
+
from datetime import datetime, timedelta
|
|
10
|
+
from .consts import API_URL, GROUPS_URL, TOTAL_WEEKS, SKIP_MILITARY, get_semester_start, set_semester_start
|
|
11
|
+
from .parser import build_schedule_for_date, get_week_info
|
|
12
|
+
|
|
13
|
+
def get_groups_list() -> list:
|
|
14
|
+
"""
|
|
15
|
+
Функция для получения списка всех доступных групп из API.
|
|
16
|
+
"""
|
|
17
|
+
try:
|
|
18
|
+
response = requests.get(GROUPS_URL)
|
|
19
|
+
response.raise_for_status()
|
|
20
|
+
|
|
21
|
+
return response.json()
|
|
22
|
+
|
|
23
|
+
except requests.exceptions.RequestException as e:
|
|
24
|
+
raise RuntimeError(f"Ошибка при получении списка групп: {e}")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def validate_group(group: str) -> bool:
|
|
28
|
+
"""
|
|
29
|
+
Функция для проверки, существует ли указанная группа.
|
|
30
|
+
"""
|
|
31
|
+
groups = get_groups_list()
|
|
32
|
+
return group in groups
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def fetch_schedule(group: str) -> dict:
|
|
36
|
+
"""
|
|
37
|
+
Функция для выполнения POST-запроса к API расписания и получения самого расписания в виде JSON-ответа.
|
|
38
|
+
"""
|
|
39
|
+
try:
|
|
40
|
+
response = requests.post(API_URL, data={"group": group})
|
|
41
|
+
response.raise_for_status()
|
|
42
|
+
return response.json()
|
|
43
|
+
|
|
44
|
+
except requests.exceptions.RequestException as e:
|
|
45
|
+
raise RuntimeError(f"Ошибка при запросе расписания для группы {group}: {e}")
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def load_cached_data(group: str) -> dict | None:
|
|
49
|
+
"""
|
|
50
|
+
Функция для загрузки данных для указанной группы из единого файла кэша.
|
|
51
|
+
Возвращает словарь с данными расписания или None, если группа не найдена.
|
|
52
|
+
"""
|
|
53
|
+
cache_path = "last_data.json"
|
|
54
|
+
if not os.path.exists(cache_path):
|
|
55
|
+
return None
|
|
56
|
+
|
|
57
|
+
try:
|
|
58
|
+
with open(cache_path, "r", encoding="utf-8") as f:
|
|
59
|
+
all_data = json.load(f)
|
|
60
|
+
return all_data.get(group)
|
|
61
|
+
|
|
62
|
+
except (json.JSONDecodeError, IOError):
|
|
63
|
+
return None
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def save_cached_data(group: str, data: dict):
|
|
67
|
+
"""
|
|
68
|
+
Функция для сохранения данных для указанной группы в единый файл кэша.
|
|
69
|
+
Если файл существует, обновляет запись для группы, иначе, создаёт новый.
|
|
70
|
+
"""
|
|
71
|
+
cache_path = "last_data.json"
|
|
72
|
+
all_data = {}
|
|
73
|
+
if os.path.exists(cache_path):
|
|
74
|
+
try:
|
|
75
|
+
with open(cache_path, "r", encoding="utf-8") as f:
|
|
76
|
+
all_data = json.load(f)
|
|
77
|
+
|
|
78
|
+
except (json.JSONDecodeError, IOError):
|
|
79
|
+
all_data = {}
|
|
80
|
+
|
|
81
|
+
all_data[group] = data
|
|
82
|
+
|
|
83
|
+
with open(cache_path, "w", encoding="utf-8") as f:
|
|
84
|
+
json.dump(all_data, f, ensure_ascii=False, indent=2)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def get_schedule(group: str, date_str: str, force: bool = False, return_json: bool = False, pretty: bool = False):
|
|
88
|
+
"""
|
|
89
|
+
Функция для получения структурированного расписания для указанной группы и даты.
|
|
90
|
+
|
|
91
|
+
Аргументы:
|
|
92
|
+
group: код группы / обязательный параметр
|
|
93
|
+
date_str: дата в формате ДД.ММ.ГГГГ
|
|
94
|
+
force: если True, принудительно запрашивает данные с сервера
|
|
95
|
+
return_json: если True, возвращает строку JSON, иначе словарь
|
|
96
|
+
pretty: если True, форматирует JSON с отступами; работает только при return_json=True
|
|
97
|
+
|
|
98
|
+
Возвращает словарь или строку JSON.
|
|
99
|
+
"""
|
|
100
|
+
if not validate_group(group):
|
|
101
|
+
raise ValueError(f"Группа '{group}' не найдена в списке доступных групп.")
|
|
102
|
+
|
|
103
|
+
is_from_cache = False
|
|
104
|
+
schedule_data = None
|
|
105
|
+
|
|
106
|
+
if not force:
|
|
107
|
+
cached = load_cached_data(group)
|
|
108
|
+
if cached is not None:
|
|
109
|
+
schedule_data = cached
|
|
110
|
+
is_from_cache = True
|
|
111
|
+
|
|
112
|
+
else:
|
|
113
|
+
schedule_data = fetch_schedule(group)
|
|
114
|
+
save_cached_data(group, schedule_data)
|
|
115
|
+
|
|
116
|
+
else:
|
|
117
|
+
schedule_data = fetch_schedule(group)
|
|
118
|
+
save_cached_data(group, schedule_data)
|
|
119
|
+
|
|
120
|
+
if schedule_data is None:
|
|
121
|
+
raise RuntimeError(f"Не удалось получить данные расписания для группы {group}.")
|
|
122
|
+
|
|
123
|
+
result_data = build_schedule_for_date(schedule_data, date_str)
|
|
124
|
+
|
|
125
|
+
week_info = get_week_info(date_str)
|
|
126
|
+
meta = {
|
|
127
|
+
"weeks": {date_str: week_info},
|
|
128
|
+
"total_weeks": TOTAL_WEEKS
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
result = {
|
|
132
|
+
"isFromCache": is_from_cache,
|
|
133
|
+
"data": result_data,
|
|
134
|
+
"meta": meta
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if return_json:
|
|
138
|
+
indent = 2 if pretty else None
|
|
139
|
+
return json.dumps(result, ensure_ascii=False, indent=indent)
|
|
140
|
+
|
|
141
|
+
return result
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def get_schedule_range(group: str, start_date_str: str, end_date_str: str, force: bool = False, return_json: bool = False, pretty: bool = False):
|
|
145
|
+
"""
|
|
146
|
+
Функция для получения структурированного расписания для указанной группы и диапазона дат.
|
|
147
|
+
|
|
148
|
+
Аргументы:
|
|
149
|
+
group: код группы / обязательный параметр
|
|
150
|
+
start_date_str: начальная дата в формате ДД.ММ.ГГГГ
|
|
151
|
+
end_date_str: конечная дата в формате ДД.ММ.ГГГГ
|
|
152
|
+
force: если True, принудительно запрашивает данные с сервера
|
|
153
|
+
return_json: если True, возвращает строку JSON, иначе словарь
|
|
154
|
+
pretty: если True, форматирует JSON с отступами; работает только при return_json=True
|
|
155
|
+
|
|
156
|
+
Возвращает словарь или строку JSON.
|
|
157
|
+
"""
|
|
158
|
+
if not validate_group(group):
|
|
159
|
+
raise ValueError(f"Группа '{group}' не найдена в списке доступных групп.")
|
|
160
|
+
|
|
161
|
+
start = datetime.strptime(start_date_str, "%d.%m.%Y")
|
|
162
|
+
end = datetime.strptime(end_date_str, "%d.%m.%Y")
|
|
163
|
+
if start > end:
|
|
164
|
+
start, end = end, start
|
|
165
|
+
|
|
166
|
+
is_from_cache = False
|
|
167
|
+
schedule_data = None
|
|
168
|
+
|
|
169
|
+
if not force:
|
|
170
|
+
cached = load_cached_data(group)
|
|
171
|
+
if cached is not None:
|
|
172
|
+
schedule_data = cached
|
|
173
|
+
is_from_cache = True
|
|
174
|
+
|
|
175
|
+
else:
|
|
176
|
+
schedule_data = fetch_schedule(group)
|
|
177
|
+
save_cached_data(group, schedule_data)
|
|
178
|
+
|
|
179
|
+
else:
|
|
180
|
+
schedule_data = fetch_schedule(group)
|
|
181
|
+
save_cached_data(group, schedule_data)
|
|
182
|
+
|
|
183
|
+
if schedule_data is None:
|
|
184
|
+
raise RuntimeError(f"Не удалось получить данные расписания для группы {group}.")
|
|
185
|
+
|
|
186
|
+
result_data = {}
|
|
187
|
+
weeks_info = {}
|
|
188
|
+
current = start
|
|
189
|
+
delta = timedelta(days=1)
|
|
190
|
+
while current <= end:
|
|
191
|
+
date_str = current.strftime("%d.%m.%Y")
|
|
192
|
+
day_result = build_schedule_for_date(schedule_data, date_str)
|
|
193
|
+
result_data.update(day_result)
|
|
194
|
+
weeks_info[date_str] = get_week_info(date_str)
|
|
195
|
+
current += delta
|
|
196
|
+
|
|
197
|
+
meta = {
|
|
198
|
+
"weeks": weeks_info,
|
|
199
|
+
"total_weeks": TOTAL_WEEKS
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
result = {
|
|
203
|
+
"isFromCache": is_from_cache,
|
|
204
|
+
"data": result_data,
|
|
205
|
+
"meta": meta
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if return_json:
|
|
209
|
+
indent = 2 if pretty else None
|
|
210
|
+
return json.dumps(result, ensure_ascii=False, indent=indent)
|
|
211
|
+
|
|
212
|
+
return result
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def get_current_week(group: str, date_str: str = None, force: bool = False, return_json: bool = False, pretty: bool = False):
|
|
216
|
+
"""
|
|
217
|
+
Функция для получения расписания на текущую неделю / с понедельника по воскресенье,
|
|
218
|
+
относительно заданной даты или текущей даты, если date_str не указан.
|
|
219
|
+
|
|
220
|
+
Аргументы:
|
|
221
|
+
group: код группы / обязательный параметр
|
|
222
|
+
date_str: опционально, дата в формате ДД.ММ.ГГГГ, от которой вычисляется неделя; если не указана, используется сегодняшняя дата
|
|
223
|
+
force: если True, принудительно запрашивает данные с сервера
|
|
224
|
+
return_json: если True, возвращает строку JSON, иначе словарь
|
|
225
|
+
pretty: если True, форматирует JSON с отступами
|
|
226
|
+
|
|
227
|
+
Возвращает словарь или строку JSON с расписанием на неделю.
|
|
228
|
+
"""
|
|
229
|
+
if date_str is None:
|
|
230
|
+
date_str = datetime.now().strftime("%d.%m.%Y")
|
|
231
|
+
dt = datetime.strptime(date_str, "%d.%m.%Y")
|
|
232
|
+
start_of_week = dt - timedelta(days=dt.weekday()) # понедельник
|
|
233
|
+
end_of_week = start_of_week + timedelta(days=6)
|
|
234
|
+
start_str = start_of_week.strftime("%d.%m.%Y")
|
|
235
|
+
end_str = end_of_week.strftime("%d.%m.%Y")
|
|
236
|
+
return get_schedule_range(group, start_str, end_str, force, return_json, pretty)
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def get_next_week(group: str, date_str: str = None, force: bool = False, return_json: bool = False, pretty: bool = False):
|
|
240
|
+
"""
|
|
241
|
+
Функция для получения расписания на следующую неделю / с понедельника по воскресенье
|
|
242
|
+
относительно заданной даты или текущей даты, если date_str не указан.
|
|
243
|
+
|
|
244
|
+
Аргументы:
|
|
245
|
+
group: код группы / обязательный параметр
|
|
246
|
+
date_str: опционально, дата в формате ДД.ММ.ГГГГ, от которой вычисляется неделя; если не указана, используется сегодняшняя дата
|
|
247
|
+
force: если True, принудительно запрашивает данные с сервера
|
|
248
|
+
return_json: если True, возвращает строку JSON, иначе словарь
|
|
249
|
+
pretty: если True, форматирует JSON с отступами
|
|
250
|
+
|
|
251
|
+
Возвращает словарь или строку JSON с расписанием на неделю.
|
|
252
|
+
"""
|
|
253
|
+
if date_str is None:
|
|
254
|
+
date_str = datetime.now().strftime("%d.%m.%Y")
|
|
255
|
+
dt = datetime.strptime(date_str, "%d.%m.%Y")
|
|
256
|
+
start_of_week = dt - timedelta(days=dt.weekday()) + timedelta(days=7)
|
|
257
|
+
end_of_week = start_of_week + timedelta(days=6)
|
|
258
|
+
start_str = start_of_week.strftime("%d.%m.%Y")
|
|
259
|
+
end_str = end_of_week.strftime("%d.%m.%Y")
|
|
260
|
+
return get_schedule_range(group, start_str, end_str, force, return_json, pretty)
|
|
261
|
+
|
|
262
|
+
def get_previous_week(group: str, date_str: str = None, force: bool = False, return_json: bool = False, pretty: bool = False):
|
|
263
|
+
"""
|
|
264
|
+
Метод для получения расписания на предыдущую неделю / с понедельника по воскресенье
|
|
265
|
+
относительно заданной даты или текущей даты, если date_str не указан.
|
|
266
|
+
|
|
267
|
+
Аргументы:
|
|
268
|
+
group: код группы / обязательный параметр
|
|
269
|
+
date_str: опционально, дата в формате ДД.ММ.ГГГГ, от которой вычисляется неделя; если не указана, используется сегодняшняя дата
|
|
270
|
+
force: если True, принудительно запрашивает данные с сервера
|
|
271
|
+
return_json: если True, возвращает строку JSON, иначе словарь
|
|
272
|
+
pretty: если True, форматирует JSON с отступами
|
|
273
|
+
|
|
274
|
+
Возвращает словарь или строку JSON с расписанием на неделю.
|
|
275
|
+
"""
|
|
276
|
+
if date_str is None:
|
|
277
|
+
date_str = datetime.now().strftime("%d.%m.%Y")
|
|
278
|
+
|
|
279
|
+
dt = datetime.strptime(date_str, "%d.%m.%Y")
|
|
280
|
+
start_of_week = dt - timedelta(days=dt.weekday()) - timedelta(days=7)
|
|
281
|
+
end_of_week = start_of_week + timedelta(days=6)
|
|
282
|
+
start_str = start_of_week.strftime("%d.%m.%Y")
|
|
283
|
+
end_str = end_of_week.strftime("%d.%m.%Y")
|
|
284
|
+
|
|
285
|
+
return get_schedule_range(group, start_str, end_str, force, return_json, pretty)
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
def get_semester_start():
|
|
289
|
+
"""Возвращает дату начала семестра."""
|
|
290
|
+
from .consts import get_semester_start as _get
|
|
291
|
+
return _get()
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def set_semester_start(new_start: str):
|
|
295
|
+
"""Устанавливает дату начала семестра."""
|
|
296
|
+
from .consts import set_semester_start as _set
|
|
297
|
+
_set(new_start)
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
def set_skip_military(value: bool):
|
|
301
|
+
"""Включает или выключает пропуск дней военной подготовки."""
|
|
302
|
+
global SKIP_MILITARY
|
|
303
|
+
SKIP_MILITARY = value
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Модуль парсинга расписания МИЭТ.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
from datetime import datetime
|
|
7
|
+
from .consts import get_semester_start, SKIP_MILITARY
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def compute_week_type(date_str: str) -> int:
|
|
11
|
+
"""
|
|
12
|
+
Функция для вычисления типа недели 0-3 на основе даты и начала семестра.
|
|
13
|
+
Формула: разница в днях % 28 // 7.
|
|
14
|
+
Дата и начало семестра ожидаются в формате ДД.ММ.ГГГГ.
|
|
15
|
+
"""
|
|
16
|
+
date = datetime.strptime(date_str, "%d.%m.%Y").date()
|
|
17
|
+
semester_start = datetime.strptime(get_semester_start(), "%d.%m.%Y").date()
|
|
18
|
+
delta = (date - semester_start).days
|
|
19
|
+
if delta < 0:
|
|
20
|
+
return 0
|
|
21
|
+
return (delta % 28) // 7
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def compute_week_number(date_str: str) -> int:
|
|
25
|
+
"""
|
|
26
|
+
Функция для вычисления абсолютного номера недели, начиная с 1, на основе даты.
|
|
27
|
+
"""
|
|
28
|
+
date = datetime.strptime(date_str, "%d.%m.%Y").date()
|
|
29
|
+
semester_start = datetime.strptime(get_semester_start(), "%d.%m.%Y").date()
|
|
30
|
+
|
|
31
|
+
delta = (date - semester_start).days
|
|
32
|
+
if delta < 0:
|
|
33
|
+
return 0
|
|
34
|
+
|
|
35
|
+
return delta // 7 + 1
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def get_week_type_string(week_type: int) -> str:
|
|
39
|
+
"""
|
|
40
|
+
Функция для преобразования числового типа недели (0-3) в строку.
|
|
41
|
+
"""
|
|
42
|
+
mapping = {
|
|
43
|
+
0: "Числитель - 1",
|
|
44
|
+
1: "Знаменатель - 1",
|
|
45
|
+
2: "Числитель - 2",
|
|
46
|
+
3: "Знаменатель - 2",
|
|
47
|
+
}
|
|
48
|
+
return mapping.get(week_type, "Неизвестно")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def get_week_info(date_str: str) -> dict:
|
|
52
|
+
"""
|
|
53
|
+
Функция для получения информации о неделе для заданной даты:
|
|
54
|
+
{
|
|
55
|
+
"number": номер недели, начиная с 1,
|
|
56
|
+
"type": числовой тип 0-3,
|
|
57
|
+
"typeString": строковое представление
|
|
58
|
+
}
|
|
59
|
+
"""
|
|
60
|
+
week_type = compute_week_type(date_str)
|
|
61
|
+
week_number = compute_week_number(date_str)
|
|
62
|
+
type_string = get_week_type_string(week_type)
|
|
63
|
+
return {
|
|
64
|
+
"number": week_number,
|
|
65
|
+
"type": week_type,
|
|
66
|
+
"typeString": type_string
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def extract_lesson_type(name: str) -> tuple:
|
|
71
|
+
"""
|
|
72
|
+
Функция для извлечения типа занятия из строки названия и получения очищенного названия и типа.
|
|
73
|
+
Пример: "Ноксология [Лек]" -> ("Ноксология", "Лекция")
|
|
74
|
+
Типы: Лек -> Лекция, Пр -> Практика, Сем -> Семинар, Лаб -> Лабораторная.
|
|
75
|
+
Если тип не распознан, возвращается "Неизвестно".
|
|
76
|
+
"""
|
|
77
|
+
match = re.search(r'\[(.*?)\]$', name)
|
|
78
|
+
if not match:
|
|
79
|
+
return name.strip(), "Неизвестно"
|
|
80
|
+
|
|
81
|
+
type_code = match.group(1).strip()
|
|
82
|
+
clean_name = re.sub(r'\s*\[.*?\]$', '', name).strip()
|
|
83
|
+
|
|
84
|
+
type_map = {
|
|
85
|
+
"Лек": "Лекция",
|
|
86
|
+
"Пр": "Практика",
|
|
87
|
+
"Сем": "Семинар",
|
|
88
|
+
"Лаб": "Лабораторная",
|
|
89
|
+
}
|
|
90
|
+
lesson_type = type_map.get(type_code, "Неизвестно")
|
|
91
|
+
|
|
92
|
+
return clean_name, lesson_type
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def parse_time(time_str: str) -> str:
|
|
96
|
+
"""
|
|
97
|
+
Функция для преобразования строки времени вида "0001-01-01T09:00:00" в формат "ЧЧ:ММ".
|
|
98
|
+
"""
|
|
99
|
+
time_part = time_str.split('T')[1]
|
|
100
|
+
return time_part[:-3]
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def build_schedule_for_date(schedule_data: dict, target_date_str: str) -> dict:
|
|
104
|
+
"""
|
|
105
|
+
Функция для преобразования сырых данных расписания в словарь из JSON
|
|
106
|
+
в формате ДД.ММ.ГГГГ ведущие нули необязательны.
|
|
107
|
+
Возвращает структурированный сортированный словарь.
|
|
108
|
+
|
|
109
|
+
Если включён флаг SKIP_MILITARY и все занятия на эту дату являются
|
|
110
|
+
"Военная подготовка", возвращается {дата: {}}, как бы "выходной".
|
|
111
|
+
"""
|
|
112
|
+
target_date_obj = datetime.strptime(target_date_str, "%d.%m.%Y").date()
|
|
113
|
+
formatted_date = target_date_obj.strftime("%d.%m.%Y")
|
|
114
|
+
|
|
115
|
+
day_of_week = target_date_obj.isoweekday()
|
|
116
|
+
week_type = compute_week_type(formatted_date)
|
|
117
|
+
|
|
118
|
+
lessons = []
|
|
119
|
+
for item in schedule_data.get("Data", []):
|
|
120
|
+
if item.get("Day") == day_of_week and item.get("DayNumber") == week_type:
|
|
121
|
+
lessons.append(item)
|
|
122
|
+
|
|
123
|
+
if SKIP_MILITARY and lessons:
|
|
124
|
+
all_military = all("Военная подготовка" in item["Class"]["Name"] for item in lessons)
|
|
125
|
+
if all_military:
|
|
126
|
+
return {formatted_date: {}}
|
|
127
|
+
|
|
128
|
+
lessons.sort(key=lambda x: x["Time"]["Code"])
|
|
129
|
+
|
|
130
|
+
result = {formatted_date: {}}
|
|
131
|
+
for lesson in lessons:
|
|
132
|
+
time_info = lesson["Time"]
|
|
133
|
+
class_info = lesson["Class"]
|
|
134
|
+
room_info = lesson["Room"]
|
|
135
|
+
|
|
136
|
+
pair_number = time_info["Code"]
|
|
137
|
+
time_from = parse_time(time_info["TimeFrom"])
|
|
138
|
+
time_to = parse_time(time_info["TimeTo"])
|
|
139
|
+
|
|
140
|
+
clean_title, lesson_type = extract_lesson_type(class_info["Name"])
|
|
141
|
+
|
|
142
|
+
result[formatted_date][pair_number] = {
|
|
143
|
+
"time": [time_from, time_to],
|
|
144
|
+
"title": clean_title,
|
|
145
|
+
"type": lesson_type,
|
|
146
|
+
"full_name": class_info["TeacherFull"],
|
|
147
|
+
"room": room_info["Name"]
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return result
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: miet-schedule-api
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Небольшая библиотека для получения расписания групп МИЭТ
|
|
5
|
+
Home-page: https://github.com/TheDIMONDK/miet_schedule_api
|
|
6
|
+
Author: Deka
|
|
7
|
+
Author-email: Deka <dka@disroot.org>
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Homepage, https://github.com/TheDIMONDK/miet_schedule_api
|
|
10
|
+
Project-URL: Repository, https://github.com/TheDIMONDK/miet_schedule_api
|
|
11
|
+
Project-URL: Issues, https://github.com/TheDIMONDK/miet_schedule_api/issues
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Requires-Python: >=3.6
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: requests>=2.25.0
|
|
19
|
+
Dynamic: author
|
|
20
|
+
Dynamic: home-page
|
|
21
|
+
Dynamic: license-file
|
|
22
|
+
Dynamic: requires-python
|
|
23
|
+
|
|
24
|
+
# MIET Schedule API
|
|
25
|
+
|
|
26
|
+
Небольшая библиотека для получения и структурирования расписания указанных групп МИЭТ.
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
## Возможности
|
|
30
|
+
- Получение расписания для любой группы из списка МИЭТ.
|
|
31
|
+
- Проверка существования группы перед запросом, используя официальное API.
|
|
32
|
+
- Получение расписания на одну дату или диапазон дат, формат: `ДД.ММ.ГГГГ` или `ДД.ММ.ГГГГ-ДД.ММ.ГГГГ`.
|
|
33
|
+
- Получение расписания на текущую, следующую или предыдущую неделю.
|
|
34
|
+
- Кэширование данных в едином файле `last_data.json`, чтобы не мучать API МИЭТ.
|
|
35
|
+
- Принудительное обновление кэша через параметр `force=True`.
|
|
36
|
+
- Пропуск дней, состоящих только из военной подготовки, управляется флагом `SKIP_MILITARY`.
|
|
37
|
+
- Автоматическое определение года начала семестра: если текущий месяц >= сентября, используется текущий год, иначе - предыдущий.
|
|
38
|
+
- Возможность явно установить дату начала семестра через функцию `set_semester_start()`.
|
|
39
|
+
- Возврат результата с мета-информацией: `isFromCache` источник данных, `data` само расписание и `meta` - метаинформация о неделях для каждой даты.
|
|
40
|
+
- Возврат в виде словаря или отформатированной строки JSON, это управляется параметрами `return_json` и `pretty`.
|
|
41
|
+
|
|
42
|
+
> Важно: библиотека пока не учитывает каникулы и праздничные дни.
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
## Структура вывода
|
|
46
|
+
```jsonc
|
|
47
|
+
{
|
|
48
|
+
"isFromCache": true, // Вывод был закэширован, или было прямое обращение к API?
|
|
49
|
+
"data": {
|
|
50
|
+
"01.09.2026": { // День
|
|
51
|
+
"1": {
|
|
52
|
+
"time": ["09:00", "10:20"],
|
|
53
|
+
"title": "Название",
|
|
54
|
+
"type": "Лекция",
|
|
55
|
+
"full_name": "Фамилия Имя Отчество",
|
|
56
|
+
"room": "1201"
|
|
57
|
+
},
|
|
58
|
+
...
|
|
59
|
+
},
|
|
60
|
+
"02.09.2026": {...},
|
|
61
|
+
...
|
|
62
|
+
},
|
|
63
|
+
"meta": {
|
|
64
|
+
"weeks": {
|
|
65
|
+
"01.09.2026": {
|
|
66
|
+
"number": 1, // Номер недели по счёту в этом дне
|
|
67
|
+
"type": 0, // Тип недели, 1-й/2-й числитель/знаменатель в виде простого ID
|
|
68
|
+
"typeString": "Числитель - 1" // Тоже самое, но уже приведённое к читаемому виду
|
|
69
|
+
},
|
|
70
|
+
"02.09.2026": {...},
|
|
71
|
+
...
|
|
72
|
+
},
|
|
73
|
+
"total_weeks": 20 // Общее количество недель
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
## Установка
|
|
80
|
+
### Локальная установка / для разработки
|
|
81
|
+
```sh
|
|
82
|
+
pip install -e .
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Установка из PyPI
|
|
86
|
+
```sh
|
|
87
|
+
pip install miet_schedule_api
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Установка из GitHub
|
|
91
|
+
```sh
|
|
92
|
+
pip install git+https://github.com/TheDIMONDK/miet_schedule_api.git
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Использование
|
|
96
|
+
```py
|
|
97
|
+
from miet_schedule_api import *
|
|
98
|
+
|
|
99
|
+
# Получить список всех существующих групп
|
|
100
|
+
groups = get_groups_list()
|
|
101
|
+
print(groups)
|
|
102
|
+
|
|
103
|
+
# Расписание на один день, смотрим на само расписание без метаданных
|
|
104
|
+
schedule = get_schedule(group="ИТД-11", date_str="01.09.2026")
|
|
105
|
+
print(schedule["data"])
|
|
106
|
+
|
|
107
|
+
# Диапазон дат, вдобавок возвращаем и красивую JSON-строку
|
|
108
|
+
schedule_json = get_schedule_range(
|
|
109
|
+
group="ИТД-11",
|
|
110
|
+
start_date_str="01.09.2026",
|
|
111
|
+
end_date_str="05.09.2026",
|
|
112
|
+
return_json=True,
|
|
113
|
+
pretty=True
|
|
114
|
+
)
|
|
115
|
+
print(schedule_json)
|
|
116
|
+
|
|
117
|
+
# Расписание+метаданные текущей недели с понедельника по воскресенье
|
|
118
|
+
current_week = get_current_week(group="ИТД-11", return_json=True, pretty=True)
|
|
119
|
+
print(current_week)
|
|
120
|
+
|
|
121
|
+
# Расписание+метаданные следующей недели относительно сегодня
|
|
122
|
+
next_week = get_next_week(group="ИТД-11", return_json=True, pretty=True)
|
|
123
|
+
print(next_week)
|
|
124
|
+
|
|
125
|
+
# Расписание+метаданные предыдущей недели относительно заданной даты
|
|
126
|
+
prev_week = get_previous_week(group="ИТД-11", date_str="15.09.2026", return_json=True, pretty=True)
|
|
127
|
+
print(prev_week)
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
## Параметры функций
|
|
132
|
+
- `group` (str, обязательный) - код группы.
|
|
133
|
+
- `return_json` (bool, default=False) - если True, возвращает строку JSON вместо словаря.
|
|
134
|
+
- `pretty` (bool, default=False) - если True и `return_json=True`, JSON выводится с отступами.
|
|
135
|
+
- `force` (bool, default=False) - принудительно запрашивает данные с сервера, игнорируя кэш.
|
|
136
|
+
- `date_str` (str) - дата в формате `ДД.ММ.ГГГГ`, для функций недели опциональна.
|
|
137
|
+
- `start_date_str`, `end_date_str` (str) - начальная и конечная даты диапазона.
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
## Разработка
|
|
141
|
+
### Сборка пакета
|
|
142
|
+
```sh
|
|
143
|
+
pip install build
|
|
144
|
+
python -m build
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Конфигурация
|
|
148
|
+
Базовые настройки по умолчанию находятся в `miet_schedule_api/consts.py`:
|
|
149
|
+
|
|
150
|
+
- `API_URL` - URL для запроса расписания.
|
|
151
|
+
- `GROUPS_URL` - URL для получения списка групп.
|
|
152
|
+
- `TOTAL_WEEKS` - общее количество недель в семестре, по умолчанию 20.
|
|
153
|
+
- `SKIP_MILITARY` - пропускать ли дни с военной подготовкой.
|
|
154
|
+
- `SEMESTER_START` - автоматически вычисляется, но можно переопределить, если нужно.
|
|
155
|
+
|
|
156
|
+
## Лицензия
|
|
157
|
+
MIT
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
MANIFEST.in
|
|
3
|
+
README.md
|
|
4
|
+
pyproject.toml
|
|
5
|
+
requirements.txt
|
|
6
|
+
setup.py
|
|
7
|
+
miet_schedule_api/__init__.py
|
|
8
|
+
miet_schedule_api/consts.py
|
|
9
|
+
miet_schedule_api/core.py
|
|
10
|
+
miet_schedule_api/parser.py
|
|
11
|
+
miet_schedule_api.egg-info/PKG-INFO
|
|
12
|
+
miet_schedule_api.egg-info/SOURCES.txt
|
|
13
|
+
miet_schedule_api.egg-info/dependency_links.txt
|
|
14
|
+
miet_schedule_api.egg-info/requires.txt
|
|
15
|
+
miet_schedule_api.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
requests>=2.25.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
miet_schedule_api
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "miet-schedule-api"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Небольшая библиотека для получения расписания групп МИЭТ"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
authors = [
|
|
12
|
+
{name = "Deka", email = "dka@disroot.org"}
|
|
13
|
+
]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
]
|
|
19
|
+
requires-python = ">=3.6"
|
|
20
|
+
dependencies = [
|
|
21
|
+
"requests>=2.25.0"
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[project.urls]
|
|
25
|
+
Homepage = "https://github.com/TheDIMONDK/miet_schedule_api"
|
|
26
|
+
Repository = "https://github.com/TheDIMONDK/miet_schedule_api"
|
|
27
|
+
Issues = "https://github.com/TheDIMONDK/miet_schedule_api/issues"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
requests>=2.25.0
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
from setuptools import setup, find_packages
|
|
4
|
+
|
|
5
|
+
with open("README.md", "r", encoding="utf-8") as fh:
|
|
6
|
+
long_description = fh.read()
|
|
7
|
+
|
|
8
|
+
setup(
|
|
9
|
+
name="miet-schedule-api",
|
|
10
|
+
version="0.1.0",
|
|
11
|
+
author="Deka",
|
|
12
|
+
author_email="dka@disroot.org",
|
|
13
|
+
description="Небольшая библиотека для получения расписания групп МИЭТ",
|
|
14
|
+
long_description=long_description,
|
|
15
|
+
long_description_content_type="text/markdown",
|
|
16
|
+
url="https://github.com/TheDIMONDK/miet_schedule_api",
|
|
17
|
+
packages=find_packages(),
|
|
18
|
+
classifiers=[
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"License :: OSI Approved :: MIT License",
|
|
21
|
+
"Operating System :: OS Independent",
|
|
22
|
+
],
|
|
23
|
+
python_requires=">=3.6",
|
|
24
|
+
install_requires=[
|
|
25
|
+
"requests>=2.25.0",
|
|
26
|
+
],
|
|
27
|
+
)
|