matplobbot-shared 0.1.10__py3-none-any.whl

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.

@@ -0,0 +1,15 @@
1
+ Metadata-Version: 2.4
2
+ Name: matplobbot-shared
3
+ Version: 0.1.10
4
+ Summary: Shared library for the Matplobbot ecosystem (database, services, i18n).
5
+ Author: Ackrome
6
+ Author-email: ivansergeyevich@gmail.com
7
+ Requires-Python: >=3.11
8
+ Requires-Dist: asyncpg>=0.28.0
9
+ Requires-Dist: aiohttp>=3.9.0
10
+ Requires-Dist: certifi>=2023.7.22
11
+ Dynamic: author
12
+ Dynamic: author-email
13
+ Dynamic: requires-dist
14
+ Dynamic: requires-python
15
+ Dynamic: summary
@@ -0,0 +1,7 @@
1
+ services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ services/schedule_service.py,sha256=tKXgwZQWeaagQeqG_tKP2gLflWo_6kxKZOhW9PFvbK4,1835
3
+ services/university_api.py,sha256=Ui-zjfKOHCCf2Imh8CNtVOWegwuep7IB8gO9IKNUrrE,1898
4
+ matplobbot_shared-0.1.10.dist-info/METADATA,sha256=CWQjAyni2MwcOxPnwJbOH4UJCF3KxUFfrmJ5AfexNHQ,421
5
+ matplobbot_shared-0.1.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
6
+ matplobbot_shared-0.1.10.dist-info/top_level.txt,sha256=Xau8qVy0H_tHbGDNnS7i0vFz4WqB9lBwZHg0pGziYuM,9
7
+ matplobbot_shared-0.1.10.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ services
services/__init__.py ADDED
File without changes
@@ -0,0 +1,39 @@
1
+ # bot/services/schedule_service.py
2
+
3
+ from typing import List, Dict, Any
4
+ from datetime import datetime
5
+
6
+ def format_schedule(schedule_data: List[Dict[str, Any]], lang: str, entity_name: str) -> str:
7
+ """Formats a list of lessons into a readable daily schedule."""
8
+ if not schedule_data:
9
+ # This part is now handled in the handler to provide more context.
10
+ return f"🗓 *Расписание на {datetime.now().strftime('%d.%m.%Y')} для \"{entity_name}\"*\n\nНа этот день занятий нет."
11
+ # Group lessons by date
12
+ days = {}
13
+ for lesson in schedule_data:
14
+ date_str = lesson['date']
15
+ if date_str not in days:
16
+ days[date_str] = []
17
+ days[date_str].append(lesson)
18
+
19
+ # Format each day's schedule
20
+ formatted_days = []
21
+ for date_str, lessons in sorted(days.items()):
22
+ date_obj = datetime.strptime(date_str, "%Y-%m-%d")
23
+ # Example format, we'll use i18n later
24
+ day_header = f"🗓 *Расписание на {date_obj.strftime('%d.%m.%Y')} для \"{entity_name}\"*"
25
+
26
+ formatted_lessons = []
27
+ for lesson in sorted(lessons, key=lambda x: x['beginLesson']):
28
+ formatted_lessons.append(
29
+ f" `{lesson['beginLesson']} - {lesson['endLesson']}`\n"
30
+ f" *Предмет:* {lesson['discipline']}\n"
31
+ f" *Тип:* {lesson['kindOfWork']}\n"
32
+ f" *Аудитория:* {lesson['auditorium']} ({lesson['building']})\n"
33
+ f" *Преподаватель:* {lesson['lecturer_title']}\n"
34
+ f" *Почта преподавателя:* {lesson['lecturerEmail']}\n"
35
+ )
36
+
37
+ formatted_days.append(f"{day_header}\n" + "\n\n".join(formatted_lessons))
38
+
39
+ return "\n\n---\n\n".join(formatted_days)
@@ -0,0 +1,45 @@
1
+ import aiohttp
2
+ from datetime import datetime
3
+ from typing import List, Dict, Any
4
+ import ssl
5
+ import certifi
6
+
7
+ class RuzAPIError(Exception):
8
+ """Custom exception for RUZ API errors."""
9
+ pass
10
+
11
+ class RuzAPIClient:
12
+ """Asynchronous API client for ruz.fa.ru."""
13
+ def __init__(self, session: aiohttp.ClientSession):
14
+ self.HOST = "https://ruz.fa.ru"
15
+ self.session = session
16
+
17
+ async def _request(self, sub_url: str) -> Dict[str, Any]:
18
+ """Performs an asynchronous request to the RUZ API."""
19
+ full_url = self.HOST + sub_url
20
+ # Create an SSL context that uses the certifi bundle for verification.
21
+ # This is more reliable than the system's default trust store, especially in Docker.
22
+ ssl_context = ssl.create_default_context(cafile=certifi.where())
23
+
24
+ async with self.session.get(full_url, ssl=ssl_context) as response:
25
+ if response.status == 200:
26
+ return await response.json()
27
+ error_text = await response.text()
28
+ raise RuzAPIError(
29
+ f"RUZ API Error: Status {response.status} for URL {full_url}. Response: {error_text}"
30
+ )
31
+
32
+ async def search(self, term: str, search_type: str) -> List[Dict[str, Any]]:
33
+ """Generic search function."""
34
+ return await self._request(f"/api/search?term={term}&type={search_type}")
35
+
36
+ async def get_schedule(self, entity_type: str, entity_id: str, start: str, finish: str) -> List[Dict[str, Any]]:
37
+ """Generic function to get a schedule."""
38
+ return await self._request(f"/api/schedule/{entity_type}/{entity_id}?start={start}&finish={finish}&lng=1")
39
+
40
+ def create_ruz_api_client(session: aiohttp.ClientSession) -> RuzAPIClient:
41
+ """
42
+ Creates and returns a RuzAPIClient instance.
43
+ This function is intended to be called once during application startup.
44
+ """
45
+ return RuzAPIClient(session)