matplobbot-shared 0.1.30__tar.gz → 0.1.31__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.

Potentially problematic release.


This version of matplobbot-shared might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: matplobbot-shared
3
- Version: 0.1.30
3
+ Version: 0.1.31
4
4
  Summary: Shared library for the Matplobbot ecosystem (database, services, i18n).
5
5
  Author: Ackrome
6
6
  Author-email: ivansergeyevich@gmail.com
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: matplobbot-shared
3
- Version: 0.1.30
3
+ Version: 0.1.31
4
4
  Summary: Shared library for the Matplobbot ecosystem (database, services, i18n).
5
5
  Author: Ackrome
6
6
  Author-email: ivansergeyevich@gmail.com
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name="matplobbot-shared",
5
- version="0.1.30", # Let's use the version from your requirements.txt
5
+ version="0.1.31", # Let's use the version from your requirements.txt
6
6
  packages=find_packages(include=['shared_lib', 'shared_lib.*']),
7
7
  description="Shared library for the Matplobbot ecosystem (database, services, i18n).",
8
8
  author="Ackrome",
@@ -0,0 +1,97 @@
1
+ # bot/services/schedule_service.py
2
+
3
+ from typing import List, Dict, Any
4
+ from datetime import datetime, date, time
5
+ from collections import defaultdict
6
+ from ics import Calendar, Event
7
+ from zoneinfo import ZoneInfo
8
+
9
+ from shared_lib.i18n import translator
10
+
11
+ names_shorter = defaultdict(lambda: 'Unknown')
12
+ to_add = {
13
+ 'Практические (семинарские) занятия': 'Семинар',
14
+ 'Лекции': 'Лекция',
15
+ 'Консультации текущие': 'Консультация',
16
+ 'Повторная промежуточная аттестация (экзамен)':'Пересдача'
17
+ }
18
+ names_shorter.update(to_add)
19
+
20
+
21
+
22
+ def format_schedule(schedule_data: List[Dict[str, Any]], lang: str, entity_name: str, entity_type: str, start_date: date, is_week_view: bool = False) -> str:
23
+ """Formats a list of lessons into a readable daily schedule."""
24
+ if not schedule_data:
25
+ # Different message for single day vs week
26
+ no_lessons_key = "schedule_no_lessons_week" if is_week_view else "schedule_no_lessons_day"
27
+ return f"🗓 *Расписание для \"{entity_name}\"*\n\n{translator.gettext(lang, no_lessons_key)}"
28
+
29
+ # Group lessons by date
30
+ days = defaultdict(list)
31
+ for lesson in schedule_data:
32
+ days[lesson['date']].append(lesson)
33
+
34
+ formatted_days = []
35
+ # Iterate through sorted dates to build the full schedule string
36
+ for date_str, lessons in sorted(days.items()):
37
+ date_obj = datetime.strptime(date_str, "%Y-%m-%d").date()
38
+
39
+ day_header = f"*{date_obj.strftime('%A, %d.%m.%Y')}*"
40
+
41
+ formatted_lessons = []
42
+ for lesson in sorted(lessons, key=lambda x: x['beginLesson']):
43
+ lesson_details = [
44
+ f"`{lesson['beginLesson']} - {lesson['endLesson']}`",
45
+ f"{lesson['discipline']} | {names_shorter[lesson['kindOfWork']]}"
46
+ ]
47
+
48
+ if entity_type == 'group':
49
+ lesson_details.append(f"*{lesson['auditorium']}* | {lesson['lecturer_title'].replace('_',' ')}")
50
+ elif entity_type == 'person': # Lecturer
51
+ lesson_details.append(f"*{lesson['auditorium']}* | {lesson.get('group', 'Группа не указана')}")
52
+ elif entity_type == 'auditorium':
53
+ lesson_details.append(f"{lesson.get('group', 'Группа не указана')} | {lesson['lecturer_title'].replace('_',' ')}")
54
+ else: # Fallback to a generic format
55
+ lesson_details.append(f"*{lesson['auditorium']}* | {lesson['lecturer_title'].replace('_',' ')}")
56
+
57
+ formatted_lessons.append("\n".join(lesson_details))
58
+
59
+ formatted_days.append(f"{day_header}\n" + "\n\n".join(formatted_lessons))
60
+
61
+ main_header = f"🗓 *Расписание для \"{entity_name}\"*"
62
+ return f"{main_header}\n\n" + "\n\n---\n\n".join(formatted_days)
63
+
64
+ def generate_ical_from_schedule(schedule_data: List[Dict[str, Any]], entity_name: str) -> str:
65
+ """
66
+ Generates an iCalendar (.ics) file string from schedule data.
67
+ """
68
+ cal = Calendar()
69
+ moscow_tz = ZoneInfo("Europe/Moscow")
70
+
71
+ if not schedule_data:
72
+ return cal.serialize()
73
+
74
+ for lesson in schedule_data:
75
+ try:
76
+ event = Event()
77
+ event.name = f"{lesson['discipline']} ({names_shorter[lesson['kindOfWork']]})"
78
+
79
+ lesson_date = datetime.strptime(lesson['date'], "%Y-%m-%d").date()
80
+ start_time = time.fromisoformat(lesson['beginLesson'])
81
+ end_time = time.fromisoformat(lesson['endLesson'])
82
+
83
+ event.begin = datetime.combine(lesson_date, start_time, tzinfo=moscow_tz)
84
+ event.end = datetime.combine(lesson_date, end_time, tzinfo=moscow_tz)
85
+
86
+ event.location = f"{lesson['auditorium']}, {lesson['building']}"
87
+
88
+ description_parts = [f"Преподаватель: {lesson['lecturer_title'].replace('_',' ')}"]
89
+ if 'group' in lesson: description_parts.append(f"Группа: {lesson['group']}")
90
+ event.description = "\n".join(description_parts)
91
+
92
+ cal.events.add(event)
93
+ except (ValueError, KeyError) as e:
94
+ logging.warning(f"Skipping lesson due to parsing error: {e}. Lesson data: {lesson}")
95
+ continue
96
+
97
+ return cal.serialize()
@@ -1,52 +0,0 @@
1
- # bot/services/schedule_service.py
2
-
3
- from typing import List, Dict, Any
4
- from datetime import datetime, date
5
- from collections import defaultdict
6
-
7
- names_shorter = defaultdict(lambda: 'Неизвестно')
8
- to_add = {
9
- 'Практические (семинарские) занятия': 'Семинар',
10
- 'Лекции': 'Лекция',
11
- 'Консультации текущие': 'Консультация',
12
- 'Повторная промежуточная аттестация (экзамен)':'Пересдача'
13
- }
14
- names_shorter.update(to_add)
15
-
16
-
17
-
18
- def format_schedule(schedule_data: List[Dict[str, Any]], lang: str, entity_name: str, start_date: date) -> str:
19
- """Formats a list of lessons into a readable daily schedule."""
20
- if not schedule_data:
21
- return f"🗓 *Расписание для \"{entity_name}\"*\n\nНа запрошенный день занятий нет."
22
-
23
- # Group lessons by date
24
- days = {}
25
- for lesson in schedule_data:
26
- date_str = lesson['date']
27
- if date_str not in days:
28
- days[date_str] = []
29
- days[date_str].append(lesson)
30
-
31
- # Find the first day with lessons that is on or after the start_date
32
- for date_str, lessons in sorted(days.items()):
33
- date_obj = datetime.strptime(date_str, "%Y-%m-%d").date()
34
- if date_obj >= start_date:
35
- # Found the first relevant day, format it and return immediately.
36
- day_header = f"🗓 *Расписание на {date_obj.strftime('%d.%m.%Y')} для \"{entity_name}\"*"
37
-
38
- formatted_lessons = []
39
- for lesson in sorted(lessons, key=lambda x: x['beginLesson']):
40
- formatted_lessons.append(
41
- f"`{lesson['beginLesson']} - {lesson['endLesson']} | {lesson['auditorium']}`\n"
42
- f"{lesson['discipline']} | {names_shorter[lesson['kindOfWork']]}\n"
43
- # f"{lesson['kindOfWork']}\n"
44
- # f"{lesson['auditorium']} ({lesson['building']})\n"
45
- f"{lesson['lecturer_title'].replace('_',' ')}\n"
46
- f"{lesson['lecturerEmail']}\n"
47
- )
48
-
49
- return f"{day_header}\n" + "\n\n".join(formatted_lessons)
50
-
51
- # If no lessons were found in the entire fetched range
52
- return f"🗓 *Расписание для \"{entity_name}\"*\n\nВ ближайшую неделю занятий не найдено."