Premium System
The premium system aggregates status from multiple sources into a single unified check. This page documents how premium works, how it is configured, and how it surfaces in the dashboard.
Premium Sources
Premium status is resolved from the following sources, checked in order:
| Priority | Source | Type | Description |
|---|---|---|---|
| 1 | Bot Owner | Automatic | OWNER_ID in config - always premium |
| 2 | Admin | Automatic | ADMIN array in config - always premium |
| 3 | Patreon | Webhook | Active pledges above MinTierPrice |
| 4 | Ko-fi | Webhook | Active subscriptions via Ko-fi webhook |
| 5 | Premium Role | Guild | Members with the configured premium role in the designated guild |
If any source returns true, the user is considered premium. The system does not require all sources - only one match is needed.
Unified Premium Check
The premium check is performed by resolveDashboardAccess.ts > buildDashboardUserPerm(). This function:
- Checks if the user is the bot owner or admin.
- Queries
PatreonServicefor active pledges tied to the user's Discord ID. - Queries
KofiServicefor active subscriptions tied to the user's Discord ID. - Checks if the user has the configured premium role in the designated guild.
The result is a permission object containing boolean flags for each feature.
Patreon Integration
Setup
- Create a Patreon account and set up a creator page.
- Create an API client at Patreon Developers (opens in a new tab).
- Get your Creator Access Token and Campaign ID.
- Set the webhook URL to your WebServer's public URL.
Patreon:
Enable: true
AccessToken: "your_creator_access_token"
CampaignId: "your_campaign_id"
MinTierPrice: 500 # $5.00 minimum tierTo find your Campaign ID, run:
node scripts/getCampignId.jsHow It Works
PatreonServicepolls the Patreon API for active pledges.- Pledge data is cached in
patreon_cache.json. - When a user's premium status is checked, the service looks up their Discord ID in the pledge data.
- Users with pledges at or above
MinTierPriceare considered premium.
Guild Redemption
Patreon premium users can claim premium for specific guilds. The redeemedGuilds array tracks which guilds have been claimed by each patron. The number of guilds a patron can claim depends on their tier.
Ko-fi Integration
Setup
- Go to your Ko-fi settings → Webhooks.
- Set the webhook URL to:
https://your-webserver-domain/kofi - Copy the Verification Token.
KoFi:
Enable: true
VerificationToken: "your_verification_token"How It Works
- Ko-fi sends webhook events to your Express WebServer at
/kofi. - The
verification_tokenin the request body is validated against config. KofiServiceprocesses subscription events:- Subscription Created - adds premium status
- Subscription Renewed - extends premium status
- Subscription Cancelled - marks for expiration
Supported Events
| Event Type | Action |
|---|---|
| Donation | Logged (does not grant premium by default) |
| Subscription | Grants premium status |
| Commission | Logged |
| Shop Order | Logged |
Premium Role
Users in a specific Discord guild who have a designated role are automatically considered premium.
PremiumRole:
Enable: true
GuildId: "your_support_server_id"
RoleId: "your_premium_role_id"This is checked in real-time - when a user loses the role, they lose premium status immediately.
Dashboard Access Control
The DASHBOARD_ACCESS config controls which dashboard features require premium, voting, or are open to everyone:
DASHBOARD_ACCESS:
Filters: ["Voter"]
TwentyFourSeven: ["Voter"]
Autoplay: ["Voter"]
LastFm: ["Voter"]
Spotify: ["Voter"]
SongRequest: ["Voter"]
Language: ["Voter"]
StatusVoiceChannel: ["Voter"]
Prefix: ["Voter"]
DjRole: ["Voter"]
ControlButton: ["Voter"]
Playlist: ["Voter"]
AiChat: ["Member"]Access Levels
| Level | Who Can Access | Behavior |
|---|---|---|
Member | Everyone | No restriction, no overlay |
Voter | Users who voted on Top.gg | Shows "Vote Required" overlay with vote link. Premium always bypasses |
Premium | Premium users only | Shows "Premium Required" overlay. Owner/Admin always bypass |
Manager | Manage Server permission | Requires guild-level permission |
Admin | Bot admins only | Only users in the ADMIN array |
Owner | Bot owner only | Only the OWNER_ID user |
How the Frontend Uses It
config.yml → resolveDashboardAccess.ts → getUserPremium API → Frontend components- Backend reads
DASHBOARD_ACCESSand evaluates the user's permission level. - The
/v1/user/:userId/premiumendpoint returns per-featureaccess(boolean) andrequirements(string level) objects. - The dashboard proxy forwards this to
/api/user/premium. - Frontend components check
access.<feature>and render a blurred overlay if access is denied.
Frontend Overlay
When access is denied, the dashboard renders:
- A blurred overlay over the feature section
- A lock icon
- A title indicating the requirement (e.g., "Vote Required")
- An action button (vote link or premium info)
Premium Data Flow
Backend Dashboard Proxy Frontend
┌────────────────┐ ┌───────────────────────┐ ┌──────────────────────┐
│ Premium Sources │ │ DashboardPlugin.ts │ │ │
│ • Patreon │ │ │ │ /profile │
│ • Ko-fi │--->│ GET /api/user/premium │--->│ -> isPremium badge │
│ • PremiumRole │ │ GET /api/player/:gid │ │ │
│ • Owner/Admin │ │ │ │ /dashboard/[guildId] │
└────────────────┘ └───────────────────────┘ │ -> sidebar status │
│ -> feature overlays│
└──────────────────────┘Profile Page
The /profile page shows a premium badge next to the username:
- Premium active: ★ Premium (green badge)
- Not premium: ☆ Not Premium (muted badge)
Player Sidebar
The guild dashboard sidebar shows:
- Premium active:
Premium: Activated(green) - Not premium:
Premium: Not Activated(muted)
Guild-Level vs User-Level
| Context | Checks | API |
|---|---|---|
/profile page | User-level only | GET /api/user/premium (no guildId) |
/dashboard/:guildId | User + Guild level | GET /api/user/premium?guildId=... |
| Playlist access | User-level only | GET /api/playlists/access |