diff --git a/.env.example b/.env.example index b0f8c21..dbe84f0 100644 --- a/.env.example +++ b/.env.example @@ -31,20 +31,30 @@ YOOKASSA_PAYMENT_SUBJECT=payment # If unset, bot will use polling while YooKassa uses webhooks. TELEGRAM_WEBHOOK_BASE_URL=https://webhooks.yourdomain.tld -# Subscription Prices (integer values) -PRICE_1_MONTH=150 -PRICE_3_MONTHS=300 -PRICE_6_MONTHS=500 -PRICE_12_MONTHS=900 -# Telegram Stars Prices (integer values) +# Payment Methods +YOOKASSA_ENABLED=True +STARS_ENABLED=True +TRIBUTE_ENABLED=True + +# Subscription Options +1_MONTH_ENABLED=True +RUB_PRICE_1_MONTH=150 STARS_PRICE_1_MONTH=0 -STARS_PRICE_3_MONTHS=0 -STARS_PRICE_6_MONTHS=0 -STARS_PRICE_12_MONTHS=0 -# Tribute Payment Links TRIBUTE_LINK_1_MONTH= + +3_MONTHS_ENABLED=True +RUB_PRICE_3_MONTHS=300 +STARS_PRICE_3_MONTHS=0 TRIBUTE_LINK_3_MONTHS= + +6_MONTHS_ENABLED=True +RUB_PRICE_6_MONTHS=500 +STARS_PRICE_6_MONTHS=0 TRIBUTE_LINK_6_MONTHS= + +12_MONTHS_ENABLED=True +RUB_PRICE_12_MONTHS=900 +STARS_PRICE_12_MONTHS=0 TRIBUTE_LINK_12_MONTHS= # API key for verifying Tribute webhook signatures TRIBUTE_API_KEY= diff --git a/README.md b/README.md index fdc2e00..f98a47c 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,10 @@ This Telegram bot is designed to automate the sale and management of subscriptio * `YOOKASSA_PAYMENT_MODE`: e.g., `full_prepayment`. * `YOOKASSA_PAYMENT_SUBJECT`: e.g., `service`. * `TELEGRAM_WEBHOOK_BASE_URL`: (Optional) If you want Telegram updates via webhook. Can be the same as `YOOKASSA_WEBHOOK_BASE_URL`. If not set, the bot will use polling for Telegram updates. - * `PRICE_X_MONTH`: Prices for different subscription durations. + * **Payment Method Toggles:** `YOOKASSA_ENABLED`, `STARS_ENABLED`, `TRIBUTE_ENABLED`. + * **Subscription Options:** For each duration you can use variables like + `1_MONTH_ENABLED`, `RUB_PRICE_1_MONTH`, `STARS_PRICE_1_MONTH`, `TRIBUTE_LINK_1_MONTH` + (and corresponding variables for `3_MONTHS`, `6_MONTHS`, `12_MONTHS`). * **Panel API Settings:** * `PANEL_API_URL`: Full URL to your Remnawave panel's API (e.g., `http://localhost:3000/api` or `https://panel.yourdomain.com/api`). * `PANEL_API_KEY`: API Key for authenticating with the Remnawave panel. diff --git a/bot/handlers/user/subscription.py b/bot/handlers/user/subscription.py index ea1423c..2bd6045 100644 --- a/bot/handlers/user/subscription.py +++ b/bot/handlers/user/subscription.py @@ -111,6 +111,7 @@ async def select_subscription_period_callback_handler( currency_symbol_val, current_lang, i18n, + settings, ) try: diff --git a/bot/keyboards/inline/user_keyboards.py b/bot/keyboards/inline/user_keyboards.py index 6e1cc3d..e6d5f4c 100644 --- a/bot/keyboards/inline/user_keyboards.py +++ b/bot/keyboards/inline/user_keyboards.py @@ -112,16 +112,17 @@ def get_payment_method_keyboard(months: int, price: float, tribute_url: Optional[str], stars_price: Optional[int], currency_symbol_val: str, lang: str, - i18n_instance) -> InlineKeyboardMarkup: + i18n_instance, settings: Settings) -> InlineKeyboardMarkup: _ = lambda key, **kwargs: i18n_instance.gettext(lang, key, **kwargs) builder = InlineKeyboardBuilder() - if stars_price is not None: + if settings.STARS_ENABLED and stars_price is not None: builder.button(text=_("pay_with_stars_button"), callback_data=f"pay_stars:{months}:{stars_price}") - if tribute_url: + if settings.TRIBUTE_ENABLED and tribute_url: builder.button(text=_("pay_with_tribute_button"), url=tribute_url) - builder.button(text=_("pay_with_yookassa_button"), - callback_data=f"pay_yk:{months}:{price}") + if settings.YOOKASSA_ENABLED: + builder.button(text=_("pay_with_yookassa_button"), + callback_data=f"pay_yk:{months}:{price}") builder.button(text=_(key="cancel_button"), callback_data="main_action:subscribe") builder.adjust(1) diff --git a/config/settings.py b/config/settings.py index 7463c41..b3ab200 100644 --- a/config/settings.py +++ b/config/settings.py @@ -36,10 +36,19 @@ class Settings(BaseSettings): TELEGRAM_WEBHOOK_BASE_URL: Optional[str] = None - PRICE_1_MONTH: Optional[int] = Field(default=None) - PRICE_3_MONTHS: Optional[int] = Field(default=None) - PRICE_6_MONTHS: Optional[int] = Field(default=None) - PRICE_12_MONTHS: Optional[int] = Field(default=None) + YOOKASSA_ENABLED: bool = Field(default=True) + STARS_ENABLED: bool = Field(default=True) + TRIBUTE_ENABLED: bool = Field(default=True) + + MONTH_1_ENABLED: bool = Field(default=True, alias="1_MONTH_ENABLED") + MONTH_3_ENABLED: bool = Field(default=True, alias="3_MONTHS_ENABLED") + MONTH_6_ENABLED: bool = Field(default=True, alias="6_MONTHS_ENABLED") + MONTH_12_ENABLED: bool = Field(default=True, alias="12_MONTHS_ENABLED") + + RUB_PRICE_1_MONTH: Optional[int] = Field(default=None) + RUB_PRICE_3_MONTHS: Optional[int] = Field(default=None) + RUB_PRICE_6_MONTHS: Optional[int] = Field(default=None) + RUB_PRICE_12_MONTHS: Optional[int] = Field(default=None) STARS_PRICE_1_MONTH: Optional[int] = Field(default=None) STARS_PRICE_3_MONTHS: Optional[int] = Field(default=None) @@ -170,27 +179,27 @@ class Settings(BaseSettings): def subscription_options(self) -> Dict[int, float]: options: Dict[int, float] = {} - if self.PRICE_1_MONTH is not None: - options[1] = float(self.PRICE_1_MONTH) - if self.PRICE_3_MONTHS is not None: - options[3] = float(self.PRICE_3_MONTHS) - if self.PRICE_6_MONTHS is not None: - options[6] = float(self.PRICE_6_MONTHS) - if self.PRICE_12_MONTHS is not None: - options[12] = float(self.PRICE_12_MONTHS) + if self.MONTH_1_ENABLED and self.RUB_PRICE_1_MONTH is not None: + options[1] = float(self.RUB_PRICE_1_MONTH) + if self.MONTH_3_ENABLED and self.RUB_PRICE_3_MONTHS is not None: + options[3] = float(self.RUB_PRICE_3_MONTHS) + if self.MONTH_6_ENABLED and self.RUB_PRICE_6_MONTHS is not None: + options[6] = float(self.RUB_PRICE_6_MONTHS) + if self.MONTH_12_ENABLED and self.RUB_PRICE_12_MONTHS is not None: + options[12] = float(self.RUB_PRICE_12_MONTHS) return options @computed_field @property def stars_subscription_options(self) -> Dict[int, int]: options: Dict[int, int] = {} - if self.STARS_PRICE_1_MONTH is not None: + if self.STARS_ENABLED and self.MONTH_1_ENABLED and self.STARS_PRICE_1_MONTH is not None: options[1] = self.STARS_PRICE_1_MONTH - if self.STARS_PRICE_3_MONTHS is not None: + if self.STARS_ENABLED and self.MONTH_3_ENABLED and self.STARS_PRICE_3_MONTHS is not None: options[3] = self.STARS_PRICE_3_MONTHS - if self.STARS_PRICE_6_MONTHS is not None: + if self.STARS_ENABLED and self.MONTH_6_ENABLED and self.STARS_PRICE_6_MONTHS is not None: options[6] = self.STARS_PRICE_6_MONTHS - if self.STARS_PRICE_12_MONTHS is not None: + if self.STARS_ENABLED and self.MONTH_12_ENABLED and self.STARS_PRICE_12_MONTHS is not None: options[12] = self.STARS_PRICE_12_MONTHS return options @@ -198,13 +207,13 @@ class Settings(BaseSettings): @property def tribute_payment_links(self) -> Dict[int, str]: links: Dict[int, str] = {} - if self.TRIBUTE_LINK_1_MONTH: + if self.TRIBUTE_ENABLED and self.MONTH_1_ENABLED and self.TRIBUTE_LINK_1_MONTH: links[1] = self.TRIBUTE_LINK_1_MONTH - if self.TRIBUTE_LINK_3_MONTHS: + if self.TRIBUTE_ENABLED and self.MONTH_3_ENABLED and self.TRIBUTE_LINK_3_MONTHS: links[3] = self.TRIBUTE_LINK_3_MONTHS - if self.TRIBUTE_LINK_6_MONTHS: + if self.TRIBUTE_ENABLED and self.MONTH_6_ENABLED and self.TRIBUTE_LINK_6_MONTHS: links[6] = self.TRIBUTE_LINK_6_MONTHS - if self.TRIBUTE_LINK_12_MONTHS: + if self.TRIBUTE_ENABLED and self.MONTH_12_ENABLED and self.TRIBUTE_LINK_12_MONTHS: links[12] = self.TRIBUTE_LINK_12_MONTHS return links