Skip to content

Commit

Permalink
Release v1.1 (#2)
Browse files Browse the repository at this point in the history
* Refactor imports and logging in multiple files for consistency and clarity. Updated README.md to simplify bot token description. Enhanced error logging format across handlers for improved debugging. Consolidated model imports in database and service modules for better organization.

* Refactor song handling to track handling across the bot. Updated README.md for clarity. Replaced 'Song' with 'Track' in multiple files, including handlers, services, and models. Enhanced user interaction by updating inline keyboards and search functionalities to reflect the change from songs to tracks. Improved localization for new track terminology in English and Russian. This update streamlines the bot's functionality and improves user experience.

* Add configuration management and restructure bot modules

- Introduced a new `configs.py` file for centralized configuration management, replacing the previous `app/configs.py`.
- Updated `main.py` to utilize the new configuration structure for bot token and database settings.
- Removed the old `app/__init__.py` and `app/configs.py` files to streamline the codebase.
- Created new modules in the `bot` directory, including handlers, filters, and utilities, to enhance modularity and organization.
- Implemented various bot handlers for menu, language selection, search functionality, and track management, improving user interaction and experience.
- Added middleware for authentication and internationalization, ensuring user data is managed effectively and language preferences are respected.

This update enhances the bot's architecture, making it more maintainable and scalable for future features.

* Enhance language and menu handlers for improved user interaction

- Updated language and menu handlers to support both message and callback query events, streamlining the handling of user inputs.

- Refactored error handling to provide clearer logging for debugging purposes.

- Revised README.md to include a new feature for auto-detecting user language and clarified demo link description.

* Enhance localization and user language selection features

- Updated README.md to clarify multi-language support with flag icons and improved formatting for deployment and database management sections.

- Modified language handler to utilize gettext for language selection prompts, enhancing user experience based on language preferences.

- Added new localization entries for language selection prompts in both English and Russian, ensuring consistent messaging across languages.

* Refactor database configuration and search handling for improved functionality

- Changed the DBConfig class to use a property for constructing the database URL, enhancing encapsulation.

- Updated the get_all_from_page_handler to clarify variable names and improve readability.

- Added input validation in the search_handler to ensure search queries are trimmed and within a valid length.

- Enhanced error handling in the CRUD class to rollback sessions on exceptions, improving database reliability.

- Added new localization entries for search query errors in both English and Russian, improving user feedback.

* Implement subscription management features in the bot

- Added a new NotSubbedFilter to check if users are subscribed to required channels.

- Created a subscription handler to prompt users for subscription if not already subscribed.

- Introduced a SubscriptionRequired model to manage required subscriptions in the database.

- Updated inline keyboard functionality to include subscription prompts.

- Enhanced logging and error handling in subscription-related operations.

- Added localization entries for subscription messages in English and Russian.

* Enhance configuration management and localization support

- Added timezone configuration in `configs.py` and updated Docker setup to utilize the TIMEZONE environment variable.

- Refactored `NotSubbedFilter` to clarify subscription checks and updated localization messages for user prompts in English and Russian.

- Improved database session handling with new timeout and recycle settings in `engine.py`.

- Updated `auth_middleware.py` to use SQLAlchemy's `func.now()` for timestamp updates.

- Introduced a maximum file size limit for downloads in the `Music` service, enhancing error handling for large files.

* Refactor subscription management and improve logging

- Updated the subscription management system by renaming the SubscriptionRequired model to RequiredSubscriptions for clarity.

- Enhanced the NotSubbedFilter and subscription handler to utilize the new model, ensuring accurate subscription checks.

- Improved logging in the NotSubbedFilter to capture errors when fetching chat information.

- Refined logging configuration in main.py for better message formatting.

- Updated localization messages for subscription prompts in both English and Russian to enhance user experience.
  • Loading branch information
goldpulpy authored Jan 14, 2025
1 parent ff7abd7 commit 6bc123a
Show file tree
Hide file tree
Showing 41 changed files with 542 additions and 342 deletions.
5 changes: 3 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ RUN addgroup -S appgroup && adduser -S appuser -G appgroup

ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PIP_NO_CACHE_DIR=1

PIP_NO_CACHE_DIR=1 \
PIP_DISABLE_PIP_VERSION_CHECK=1

WORKDIR /app

COPY requirements.txt .
Expand Down
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@
- 🎧 Высокое качество звука
- 🌅 Аудио с обложкой
- 📱 Интуитивный интерфейс
- 🌍 Поддержка нескольких языков (английский, русский)
- 🐳 Легкое развертывание через Docker
- 🛡️ Безопасное хранение данных в PostgreSQL
- 📝 Лицензия: Apache License 2.0
- 🌍 Поддержка нескольких языков (🇬🇧 English, 🇷🇺 Русский)
- 🌍 Автоопределение языка пользователя
- 🐳 Легкое развертывание через **Docker**
- 🛡️ Безопасное хранение данных в **PostgreSQL**
- 📊 Управление базой данных через **Adminer**
- 📝 Лицензия: **Apache License 2.0**

## 🎥 Демо (Demo)

Expand Down Expand Up @@ -50,7 +52,7 @@

```env
# Bot Configuration
BOT_TOKEN=your_bot_token # Токен бота от BotFather
BOT_TOKEN=your_bot_token # Токен бота
TIMEZONE=UTC # Пример: Europe/Moscow
# Database Configuration
Expand Down
5 changes: 0 additions & 5 deletions app/__init__.py

This file was deleted.

28 changes: 0 additions & 28 deletions app/configs.py

This file was deleted.

4 changes: 0 additions & 4 deletions app/filters/__init__.py

This file was deleted.

81 changes: 0 additions & 81 deletions app/handlers/get_song.py

This file was deleted.

35 changes: 0 additions & 35 deletions app/handlers/menu.py

This file was deleted.

11 changes: 0 additions & 11 deletions app/utils.py

This file was deleted.

File renamed without changes.
6 changes: 6 additions & 0 deletions bot/filters/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"""Filters for the bot."""
from .language import LanguageFilter
from .not_subbed import NotSubbedFilter


__all__ = ['LanguageFilter', 'NotSubbedFilter']
2 changes: 1 addition & 1 deletion app/filters/language.py → bot/filters/language.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from aiogram import types
from aiogram.filters import Filter
from database.models.user import User
from database.models import User
from locales import support_languages


Expand Down
60 changes: 60 additions & 0 deletions bot/filters/not_subbed.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
"""Check if user is subbed to the channel."""
import logging
from aiogram import types
from aiogram.filters import Filter
from aiogram import Bot
from aiogram.enums import ChatMemberStatus
from database.models import RequiredSubscriptions, User
from database.crud import CRUD

logger = logging.getLogger(__name__)


class NotSubbedFilter(Filter):
"""
A filter that checks if a user is subbed to the channel.
"""

ALLOWED_STATUSES = {
ChatMemberStatus.MEMBER,
ChatMemberStatus.ADMINISTRATOR,
ChatMemberStatus.CREATOR,
}

async def __call__(
self, update: types.Message | types.CallbackQuery, user: User, bot: Bot
) -> bool:
"""
Check if the user is not subscribed to any required channels.
Returns True if user is NOT subscribed to ANY required channel.
Returns False if user is subscribed to ALL required channels.
"""
chats = await CRUD(RequiredSubscriptions).get_all()

if not chats:
return False

for chat in chats:
if await self._not_subscribe(chat, user, bot):
return True
return False

async def _not_subscribe(
self, sub: RequiredSubscriptions, user: User, bot: Bot
) -> bool:
"""
Check if the user is subscribed to the channel.
Returns True if user is NOT subscribed.
Returns False if user is subscribed or if channel is not accessible.
"""
try:
chat = await bot.get_chat(sub.chat_id)
except Exception as e:
logger.error(f"Failed to get chat {sub.chat_id}: {e}")
return False

try:
member = await chat.get_member(user.id)
return member.status not in self.ALLOWED_STATUSES
except Exception:
return True
8 changes: 5 additions & 3 deletions app/handlers/__init__.py → bot/handlers/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
"""Setup router for the bot."""
from aiogram import Dispatcher, Router
from . import (
get_track,
language,
menu,
faq,
search,
get_song,
pages
pages,
subscribe
)


Expand All @@ -18,8 +19,9 @@ def setup(dp: Dispatcher) -> None:
language.register(router)
menu.register(router)
faq.register(router)
subscribe.register(router)
search.register(router)
pages.register(router)
get_song.register(router)
get_track.register(router)

dp.include_router(router)
5 changes: 2 additions & 3 deletions app/handlers/faq.py → bot/handlers/faq.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@
import logging
from aiogram import types, Router, F
from aiogram.utils.i18n import gettext
from app.keyboards import inline
from bot.keyboards import inline

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


Expand All @@ -16,7 +15,7 @@ async def faq_handler(callback: types.CallbackQuery) -> None:
reply_markup=inline.get_back_keyboard(gettext, "menu")
)
except Exception as e:
logger.error(f"Failed to send message: {e}")
logger.error("Failed to send message: %s", e)


def register(router: Router) -> None:
Expand Down
Loading

0 comments on commit 6bc123a

Please sign in to comment.