Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Ignore common developer files and directories
.git
.gitignore
.vscode/
.venv/

# Ignore dependency and build directories
__pycache__/
dist/

# Ignore sensitive files and logs
.env
*.log
10 changes: 10 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,13 @@ jobs:

- name: Coverage
run: uv run pytest --cov=app --cov-report=term --cov-report=xml --cov-fail-under=70

docker-build:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Build Docker image
run: docker build -t event-organizer-bot .
1 change: 1 addition & 0 deletions app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class Settings(BaseSettings):
basic_auth_username: str = Field(default="admin", env="ADMIN_BASIC_AUTH_USERNAME")
basic_auth_password: str = Field(default="admin", env="ADMIN_BASIC_AUTH_PASSWORD")
scheduler_interval_seconds: int = Field(default=60, env="SCHEDULER_INTERVAL_SECONDS")
allow_admin_upload_overwrite: bool = Field(default=False, env="ALLOW_ADMIN_UPLOAD_OVERWRITE")

database_url: str = Field(
default="sqlite:///./anonchatbot.db",
Expand Down
2 changes: 1 addition & 1 deletion app/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

Base = declarative_base()

SCHEMA_VERSION = 2
SCHEMA_VERSION = 3


def ensure_schema() -> None:
Expand Down
6 changes: 5 additions & 1 deletion app/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,16 @@
},
"messages": {
"main_menu": "Главное меню",
"event_started_broadcast": "Мероприятие началось! Следите за обновлениями в боте."
"event_started_broadcast": "Мероприятие началось! Следите за обновлениями в боте.",
"friend_attending": "Your friend {friend} is already attending!",
"friend_attending_unknown": "Someone"
},
"application": {
"already_created": "Заявка уже создана.",
"ask_full_name": "Как вас зовут? (Имя Фамилия)",
"ask_job": "Кем и где вы работаете? (позиция, компания)",
"ask_career": "Какой путь... (1)... (2)... В ответ напишите цифру",
"ask_friends": "Do you have/want any friends attending? Write down their usernames below.",
"confirmation": "Спасибо за вашу заявку! Ожидайте новостей по мероприятию.",
"cancelled": "Заявка отменена."
},
Expand All @@ -96,6 +99,7 @@
"unknown": "Unknown command",
"nickname_required": "Нужен nickname.",
"user_not_found": "Пользователь не найден.",
"application_not_found": "У пользователя нет заявки.",
"user_id_required": "Нужен user_id.",
"user_id_invalid": "Неверный user_id.",
"event_id_required": "Нужен id."
Expand Down
56 changes: 56 additions & 0 deletions app/locales/event_ru.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"buttons": {
"attend": "Принять участие",
"lecturer": "Подать заявку на доклад",
"showcase": "Показать проект"
},
"start": {
"new": "Привет, {name}!\n\nДобро пожаловать в бот Event Organizer Summit 2025. Выберите формат участия.",
"returning": "С возвращением, {name}!\n\nВы уже зарегистрированы на Event Organizer Summit 2025:\n{summary}\n\nИспользуйте /status для обновлений или выберите другой вариант ниже.",
"summary_item": "• {category}: {status}"
},
"help": {
"text": "Используйте /start, чтобы зарегистрироваться на Event Organizer Summit 2025, или /status, чтобы проверить статус заявки."
},
"registration": {
"callback": {
"attendee": "Спасибо! Заявка на участие в Event Organizer Summit 2025 получена. Скоро подтвердим.",
"lecturer": "Спасибо! Ваша заявка на доклад для Event Organizer Summit 2025 принята.",
"showcase": "Отлично! Заявка на демонстрацию проекта для Event Organizer Summit 2025 записана."
}
},
"admin_notifications": {
"approved": "Ваша заявка на Event Organizer Summit 2025 подтверждена. Ждем вас 18 октября в Берлине!",
"approved_priority": "Ваша заявка подтверждена с приоритетным доступом на Event Organizer Summit 2025. Ждем вас 18 октября в Берлине!",
"waitlisted": "Вы в листе ожидания Event Organizer Summit 2025. Сообщим, если появится место."
},
"bot": {
"menu": {
"application": "Заявка",
"cancel": "Отмена заявки",
"feedback": "Отзыв",
"schedule": "Афиша",
"status": "Статус",
"notifications": "Нотификации",
"home": "На главную"
},
"messages": {
"event_started_broadcast": "Event Organizer Summit 2025 начался! Следите за обновлениями в боте.",
"friend_attending": "Ваш друг {friend} уже участвует!",
"friend_attending_unknown": "Кто-то"
},
"application": {
"ask_friends": "Есть друзья, которые тоже придут? Напишите их username ниже.",
"confirmation": "Спасибо за регистрацию! Скоро пришлем детали по Event Organizer Summit 2025."
}
},
"admin": {
"dashboard": {
"title": "Обзор Event Organizer Summit 2025",
"subtitle": "Сводка по регистрациям, лимиту и рассылкам для саммита."
},
"posts": {
"title": "Запланированные посты для Event Organizer Summit 2025"
}
}
}
6 changes: 5 additions & 1 deletion app/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,16 @@
},
"messages": {
"main_menu": "Главное меню",
"event_started_broadcast": "Мероприятие началось! Следите за обновлениями в боте."
"event_started_broadcast": "Мероприятие началось! Следите за обновлениями в боте.",
"friend_attending": "Ваш друг {friend} уже участвует!",
"friend_attending_unknown": "Кто-то"
},
"application": {
"already_created": "Заявка уже создана.",
"ask_full_name": "Как вас зовут? (Имя Фамилия)",
"ask_job": "Кем и где вы работаете? (позиция, компания)",
"ask_career": "Какой путь... (1)... (2)... В ответ напишите цифру",
"ask_friends": "Есть друзья, которые тоже придут? Напишите их username ниже.",
"confirmation": "Спасибо за вашу заявку! Ожидайте новостей по мероприятию.",
"cancelled": "Заявка отменена."
},
Expand All @@ -96,6 +99,7 @@
"unknown": "Неизвестная команда",
"nickname_required": "Нужен nickname.",
"user_not_found": "Пользователь не найден.",
"application_not_found": "У пользователя нет заявки.",
"user_id_required": "Нужен user_id.",
"user_id_invalid": "Неверный user_id.",
"event_id_required": "Нужен id."
Expand Down
10 changes: 5 additions & 5 deletions app/localization.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
"""Simple localization helper backed by JSON message catalogs."""

from __future__ import annotations

import json
import logging
from dataclasses import dataclass
from functools import lru_cache
from importlib import resources
from typing import Any

DEFAULT_LOCALE = "en"
DEFAULT_LOCALE = "ru"
logger = logging.getLogger(__name__)


@dataclass(frozen=True)
Expand Down Expand Up @@ -59,11 +57,13 @@ def _load_messages(locale: str) -> dict[str, Any]:

@lru_cache(maxsize=None)
def get_localizer(locale: str) -> Localizer:
logger.info("get_localizer: locale chosen is %s", locale)
try:
messages = _load_messages(locale)
except FileNotFoundError:
if locale == DEFAULT_LOCALE:
raise
logger.error("Locale %s not found, using default one", locale)
return get_localizer(DEFAULT_LOCALE)

fallback = get_localizer(DEFAULT_LOCALE) if locale != DEFAULT_LOCALE else None
Expand Down
1 change: 1 addition & 0 deletions app/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class User(Base):
full_name = Column(String(255), nullable=True)
job = Column(String(255), nullable=True)
career_path = Column(String(255), nullable=True)
friend_usernames = Column(Text, nullable=True)
status = Column(Enum(UserStatus), default=UserStatus.NONE, nullable=False)
notifications_enabled = Column(Boolean, default=True, nullable=False)
is_subscribed = Column(Boolean, default=True, nullable=False)
Expand Down
Loading
Loading