remnashop

repository·main·Indexed 19 days ago

https://github.com/snoups/remnashop

A Telegram bot for the automated sale of VPN subscriptions, featuring deep integration with the Remnawave platform. It includes support for custom banners, Fluent-based translations with custom Telegram emoji support, and a comprehensive set of user management interactors for authentication, email verification, password changes, and advertisement link management.

Tokens
37.1K
Snippets
139
Records
167
Agent score
61%

What's inside remnashop

  1. Follow the translation key naming convention

    main

    All translation keys must follow a strict hierarchical structure to ensure consistency and prevent errors.

    Structure

    {category}-{scope}-{entity}-{action-or-state}

    Components

    PartDescriptionExample
    {category}Top-level type of textbtn, msg, ntf
    {scope}Logical group or subsystemuser, plan, subscription, error
    {entity}Specific object or sub-entitycontent, payment, link
    {action-or-state}Action (past tense) or State (adjective)created, failed, empty, invalid

    Rules

    1. Use lowercase with hyphens (-). No underscores or spaces.
    2. Follow the exact order: category $\rightarrow$ scope $\rightarrow$ entity $\rightarrow$ action/state.
    3. Actions should be past tense verbs (e.g., created, deleted).
    4. States should be adjectives (e.g., empty, not-found).
    5. Recommended: Max 5 segments and total length under 32 characters.
  2. Configure and use custom banners

    main

    You can provide custom banner images by placing them in the banners/ folder within your user volume. The system follows a specific lookup hierarchy to find the most relevant banner for a user's locale and current page. If no user-provided banner is found, the bot falls back to its built-in defaults.

    Configuration

    Enable or disable banners using the environment variable:

    • BOT_USE_BANNERS: Set to true to enable, false to disable.
    1. banners/{user_locale}/{page} (User volume)
    2. banners/{user_locale}/default (User volume)
    3. banners/{default_locale}/{page} (User volume)
    4. banners/{default_locale}/default (User volume)
    5. banners/default (User volume)
    6. banners/{user_locale}/{page} (Bot default)
    7. banners/default (Bot global default)

    Supported Banner Names

    Filenames must match one of these BannerName values:

    • DEFAULT: Fallback banner.
    • MENU: Main menu banner.
    • DASHBOARD: Dashboard banner.
    • SUBSCRIPTION: Subscription banner.
    • REFERRAL: Referral banner.

    Supported Formats

    JPG, JPEG, PNG, GIF, WEBP

  3. Customize the QR Code logo

    main

    To add branding to the generated invitation QR code, place a logo file in your user volume. The system will overlay this image in the center of the QR code.

    • Path: assets/logo.png
    • Format: PNG (preferably with a transparent background).
  4. Configure and override translations

    main

    The bot uses Fluent (.ftl) files for translations. You can override built-in translations or add new custom ones by placing custom.ftl files in your user volume translations/ folder.

    Configuration

    • APP_LOCALES: A comma-separated list of supported locales (e.g., ru,en).
    • APP_DEFAULT_LOCALE: The default locale.

    How Overrides Work

    For each locale, the bot loads files in this priority:

    1. assets/translations/{locale}/custom.ftl (Your overrides - Highest Priority)
    2. assets.default/translations/{locale}/*.ftl (Bot built-ins - Fallback)

    Custom Keys

    To avoid collisions with built-in keys, prefix your custom keys with custom-. Use the standard Fluent syntax:

    custom-key-name = Translation text

    Constraints

    • Buttons: Max 32 characters.
    • Messages: Max 1024 characters.
    # Custom menu buttons
    custom-menu-link1 = 1️⃣ First button
    custom-menu-link2 = 2️⃣ Second button
    
    # Custom plan names
    custom-plan-name1 = 1️⃣ Basic plan
    custom-plan-name2 = 2️⃣ Premium plan
  5. Use custom Telegram emojis in translations

    main

    You can include custom Telegram emojis in your .ftl translation files. This requires the bot to have a paid username or the owner to have Telegram Premium.

    Getting Emoji IDs

    Send the emoji to @getidsbot or @RawDataBot to retrieve the custom_emoji_id.

    Supported Syntax

    1. Full Format

    Best for explicit control:

    btn-example = <tg-emoji emoji-id="5406756500108501710">🎁</tg-emoji> Button text

    2. Short Format

    Best for brevity; the system expands this to the full tag automatically:

    btn-example = <e id="5406756500108501710">🎁</e> Button text

    Note: Always include a plain emoji inside the tag as a fallback for clients that do not support custom emojis.

    Usage Contexts

    • Buttons: Automatically recognized by Emoji* widgets (e.g., EmojiButton, EmojiBack).
    • Messages: Handled by the I18nFormat widget.

    Priority

    If a button's Style has icon_custom_emoji_id explicitly set via code, it will override the emoji found in the translation key text.

    # Example in buttons.ftl
    btn-menu =
        .connect = <tg-emoji emoji-id="5447410659077661506">🚀</tg-emoji> Connect
        .devices = <e id="5271604874419647061">📱</e> Devices
    
    # Example in messages
    msg-broadcast-main = <tg-emoji emoji-id="5424818078833715060">📢</tg-emoji> <b>Broadcast</b>
  6. Manage user discounts and trial availability

    main

    The profile_edit.py module provides several interactor classes for managing user profiles, specifically for administrative tasks like adjusting discounts, points, and trial status.

    Permissions

    Most profile editing operations require the Permission.USER_EDITOR permission. However, resetting one's own referral code is available to Permission.PUBLIC users, subject to system settings and cooldown periods.

    Security Rules

    For administrative commands, an actor can only edit a target user if:

    1. The actor is the target user themselves (actor.id == target_user.id).
    2. The actor's role is strictly greater than the target user's role (actor.role > target_user.role).

    If these conditions are not met, a PermissionDeniedError is raised.

  7. Referral Level logic

    main

    Referrals are organized into levels using the ReferralLevel enum. The level of a new referral is determined by the level of its parent in the referral chain:

    • If there is no parent (the referrer is not part of a chain), the level is ReferralLevel.FIRST.
    • If a parent exists, the new level is parent_level.value + 1.
    • The level cannot exceed the maximum value defined in the ReferralLevel enum.

    This hierarchy allows the system to track multi-level referral structures.

  8. Referral reward types and levels

    main

    The referral system utilizes the following enums to define how rewards are structured and distributed:

    Reward Types (ReferralRewardType):

    • POINTS: Grants user points.
    • EXTRA_DAYS: Grants subscription time.

    Referral Levels (ReferralLevel):

    • FIRST: The immediate referrer of the user.
    • SECOND: The referrer of the immediate referrer (the 'grand-referrer').

    Accrual Strategies (ReferralAccrualStrategy):

    • ON_FIRST_PAYMENT: Rewards are only triggered on the user's first successful purchase.
  9. Configure and use automated database backups

    main

    The AutoBackupDatabase interactor automates the creation of database backups based on system settings. It ensures backups are not created too frequently and manages disk space by rotating old files.

    Configuration Logic: The automation relies on the following settings retrieved via SettingsDao:

    • backup.enabled: If false, no backup is performed.
    • backup.interval_hours: The minimum time elapsed since the last backup (found in BACKUP_DIR) before a new one is triggered.
    • backup.max_files: The maximum number of backup files to retain in BACKUP_DIR. Once this limit is reached, the oldest files are deleted.
    • backup.send_to_chat: If true, the backup file is sent to administrators (Role.OWNER and Role.DEV) via the Notifier.

    Workflow:

    1. Checks if backups are enabled and if the interval_hours has passed since the last file in BACKUP_DIR.
    2. Creates a SQL dump in a temporary directory.
    3. Moves the dump to BACKUP_DIR with the name db_backup_<timestamp>.sql.
    4. Rotates files if the count exceeds max_files.
    5. Optionally notifies admins if send_to_chat is enabled.
  10. Supported Promocode Reward Types

    main

    The ActivatePromocode interactor supports the following PromocodeRewardType values, each affecting different parts of the user's account:

    • DURATION: Extends the subscription expire_at date by a specified number of days. A reward of 0 results in an unlimited subscription.
    • TRAFFIC: Increases the traffic_limit (in GB). A reward of 0 results in unlimited traffic.
    • DEVICES: Increases the device_limit. A reward of 0 results in unlimited devices.
    • SUBSCRIPTION: Applies a new plan from a plan_snapshot. This can either update an existing subscription or create a new one via Remnawave.
    • PERSONAL_DISCOUNT: Applies a percentage discount to the user's personal_discount field.
    • PURCHASE_DISCOUNT: Applies a percentage discount to the user's purchase_discount field.
  11. Configure API documentation (Swagger and ReDoc)

    main

    The Remnashop API documentation is controlled via the swagger_enabled flag in your AppConfig. When enabled, the following endpoints are available:

    • /docs: Swagger UI with persistAuthorization enabled.
    • /redoc: ReDoc documentation.
    • /openapi.json: The raw OpenAPI schema.

    Note that these endpoints are marked with include_in_schema=False, meaning they won't appear in the generated OpenAPI schema itself.