chore: add changelog and documentation updates
All checks were successful
CI / lint-and-test (push) Successful in 17s

- Created a new `CHANGELOG.md` file to document all notable changes to the project, adhering to the Keep a Changelog format.
- Updated `CONTRIBUTING.md` to include instructions for building and previewing documentation using MkDocs.
- Added `mkdocs.yml` configuration for documentation generation, including navigation structure and theme settings.
- Enhanced various documentation files, including API reference, architecture overview, configuration reference, and runbook, to provide comprehensive guidance for users and developers.
- Included new sections in the README for changelog and documentation links, improving accessibility to project information.
This commit is contained in:
2026-02-20 15:32:10 +03:00
parent b61e1ca8a5
commit 86f6d66865
88 changed files with 28912 additions and 118 deletions

View File

@@ -17,7 +17,17 @@ from duty_teller.i18n import t
def format_duty_message(duty, user, tz_name: str, lang: str = "en") -> str:
"""Build the text for the pinned message. duty, user may be None."""
"""Build the text for the pinned duty message.
Args:
duty: Duty instance or None.
user: User instance or None.
tz_name: Timezone name for display (e.g. Europe/Moscow).
lang: Language code for i18n ('ru' or 'en').
Returns:
Formatted message string; "No duty" if duty or user is None.
"""
if duty is None or user is None:
return t(lang, "duty.no_duty")
try:
@@ -53,7 +63,16 @@ def format_duty_message(duty, user, tz_name: str, lang: str = "en") -> str:
def get_duty_message_text(session: Session, tz_name: str, lang: str = "en") -> str:
"""Get current duty from DB and return formatted message."""
"""Get current duty from DB and return formatted message text.
Args:
session: DB session.
tz_name: Timezone name for display.
lang: Language code for i18n.
Returns:
Formatted duty message or "No duty" if none.
"""
now = datetime.now(timezone.utc)
result = get_current_duty(session, now)
if result is None:
@@ -63,26 +82,61 @@ def get_duty_message_text(session: Session, tz_name: str, lang: str = "en") -> s
def get_next_shift_end_utc(session: Session) -> datetime | None:
"""Return next shift end as naive UTC datetime for job scheduling."""
"""Return next shift end as naive UTC datetime for job scheduling.
Args:
session: DB session.
Returns:
Next shift end (naive UTC) or None.
"""
return get_next_shift_end(session, datetime.now(timezone.utc))
def save_pin(session: Session, chat_id: int, message_id: int) -> None:
"""Save or update the pinned message record for a chat."""
"""Save or update the pinned duty message record for a chat.
Args:
session: DB session.
chat_id: Telegram chat id.
message_id: Message id to store.
"""
save_group_duty_pin(session, chat_id, message_id)
def delete_pin(session: Session, chat_id: int) -> None:
"""Remove the pinned message record when the bot leaves the group."""
"""Remove the pinned message record for the chat (e.g. when bot leaves).
Args:
session: DB session.
chat_id: Telegram chat id.
"""
delete_group_duty_pin(session, chat_id)
def get_message_id(session: Session, chat_id: int) -> int | None:
"""Return message_id for the pin in this chat, or None."""
"""Return message_id for the pinned duty message in this chat.
Args:
session: DB session.
chat_id: Telegram chat id.
Returns:
Message id or None if no pin record.
"""
pin = get_group_duty_pin(session, chat_id)
return pin.message_id if pin else None
def get_all_pin_chat_ids(session: Session) -> list[int]:
"""Return all chat_ids that have a pinned duty message (for restoring jobs on startup)."""
"""Return all chat_ids that have a pinned duty message.
Used to restore update jobs on bot startup.
Args:
session: DB session.
Returns:
List of chat ids.
"""
return get_all_group_duty_pin_chat_ids(session)

View File

@@ -36,7 +36,21 @@ def run_import(
hour_utc: int,
minute_utc: int,
) -> tuple[int, int, int, int]:
"""Run import: delete range per user, insert duty/unavailable/vacation. Returns (num_users, num_duty, num_unavailable, num_vacation)."""
"""Run duty-schedule import: delete range per user, insert duty/unavailable/vacation.
For each entry: get_or_create_user_by_full_name, delete_duties_in_range for
the result date range, then insert duties (handover time in UTC), unavailable
(all-day), and vacation (consecutive ranges).
Args:
session: DB session.
result: Parsed duty schedule (start_date, end_date, entries).
hour_utc: Handover hour in UTC (0-23).
minute_utc: Handover minute in UTC (0-59).
Returns:
Tuple (num_users, num_duty, num_unavailable, num_vacation).
"""
from_date_str = result.start_date.isoformat()
to_date_str = result.end_date.isoformat()
num_duty = num_unavailable = num_vacation = 0