Premium Tier
Premium Tier
The Alphapy bot supports a Premium tier for mature users. Premium features are gated via utils/premium_guard.is_premium(user_id, guild_id).
One server per subscription. Each user has at most one active Premium subscription, and it applies to a single guild. Pay once and choose where you want full power (image reminders, Mockingbird mode, etc.). To move Premium to another server (e.g. your “home” server changed), use /premium_transfer in the target server, or request a transfer via support (dashboard coming later).
Features (Premium)
- Reminders with images – Add an image or banner URL (or attachment) to reminders; sent reminders show the image.
- Live session presets – (Documented; implementation can follow.)
- Mockingbird spicy mode – In
/growthcheckin, premium users get direct, sharp, no-sugar-coating replies.
Pricing (display only)
- €4.99 / month
- €29 / year (early bird)
- €49 lifetime (first 50 members)
Payment and webhooks (Stripe/Lemon Squeezy) are out of scope for the initial release; the guard and /premium command are in place.
Configuration
| Variable | Description |
|---|---|
PREMIUM_CHECKOUT_URL |
Checkout page URL for the “Get Premium” button. If unset, the button shows “Coming soon” (disabled). |
PREMIUM_CACHE_TTL_SECONDS |
TTL in seconds for the in-memory premium cache (default: 300). |
CORE_API_URL |
When set, the guard calls POST {CORE_API_URL}/premium/verify first (see below). |
ALPHAPY_SERVICE_KEY |
API key for Core-API premium verify. |
Guard behaviour
- Cache – In-memory cache keyed by
(user_id, guild_id)with configurable TTL. Cache hit returns immediately. - Core-API – If
CORE_API_URLandALPHAPY_SERVICE_KEYare set, the guard sendsPOST {CORE_API_URL}/premium/verifywith body{"user_id": int, "guild_id": int}and headerX-API-Key: ALPHAPY_SERVICE_KEY. Response is expected as{"premium": true|false, "tier": "monthly"|"yearly"|"lifetime"|null}. On 2xx andpremium: true, the user is treated as premium. - Local fallback – If Core is not configured or the request fails, the guard queries the local
premium_substable:status = 'active'and (expires_at IS NULLORexpires_at > NOW()). - Fail closed – On any error (timeout, DB failure), the guard returns
False.
Core-API contract (for later implementation)
- Endpoint:
POST {CORE_API_URL}/premium/verify - Headers:
Content-Type: application/json,X-API-Key: ALPHAPY_SERVICE_KEY - Body:
{"user_id": <discord user id>, "guild_id": <discord guild id>} - Response:
{"premium": true|false, "tier": "monthly"|"yearly"|"lifetime"|null}
Transfer (local DB)
When using the local premium_subs table (no Core-API or Core not configured), users can run /premium_transfer in the server they want Premium in. The guard updates the single active row’s guild_id and clears the cache. When Core-API is the source of truth, there may be no local row; transfer is then done via dashboard or support.
The database enforces at most one active subscription per user via a partial unique index on premium_subs (user_id) WHERE status = 'active' (migration 005).
GDPR
The premium_subs table stores only what is needed for access control: user_id, guild_id, tier, status, optional stripe_subscription_id (external ID for support), expires_at, created_at. No payment details, email, or other PII are stored in this table.
Lifetime cap
The “first 50 members” lifetime cap is enforced when processing payment/webhooks (e.g. Stripe or Lemon Squeezy), not in the guard. The guard only reads existing premium_subs or Core-API response.