Integrations
This page covers the setup and integration of Spotify, Last.fm, Top Chart API, and Lavalink plugins with Meww.me.
Spotify
Spotify integration serves two purposes:
- Lavalink Source - Resolves Spotify URLs to playable audio via the LavaSrc plugin.
- Dashboard OAuth - Allows users to connect their Spotify account for playlist import and viewing.
Spotify API Credentials
- Go to the Spotify Developer Dashboard (opens in a new tab).
- Click Create App.
- Note the Client ID and Client Secret.
- Under Redirect URIs, add your dashboard callback URL.
Bot Configuration (config.yml)
lavalink:
SPOTIFY:
enable: true
id: "your_spotify_client_id"
secret: "your_spotify_client_secret"
redirectUri: "https://your-domain.com/auth/spotify/callback"These credentials are used by the bot for:
- Refreshing Spotify access tokens (
SpotifygetAccessToken.ts) - Dashboard Spotify OAuth flow (
SpotifyOAuthService.ts) - Playlist import functionality
Lavalink Configuration (application.yml)
The Lavalink server also needs Spotify credentials for the LavaSrc plugin to resolve Spotify URLs to audio:
plugins:
lavasrc:
providers:
- "ytsearch:\"%ISRC%\""
- "ytsearch:%QUERY%"
sources:
spotify: true
spotify:
clientId: "your_spotify_client_id"
clientSecret: "your_spotify_client_secret"
countryCode: "US"The bot's config.yml and Lavalink's application.yml use the same Spotify credentials but for different purposes:
- Bot (
config.yml) - metadata resolution, API calls, OAuth - Lavalink (
application.yml) - audio source resolution via LavaSrc
Why Both Need Credentials
User pastes Spotify URL
│
▼
Bot receives URL → Sends to Lavalink
│ │
▼ ▼
Bot resolves metadata Lavalink (LavaSrc) resolves
(title, artist, art) Spotify → ISRC → YouTube audio
using Spotify API using Spotify APIThe bot needs Spotify API access for metadata, search, and playlist features. Lavalink needs it independently to convert Spotify tracks to playable audio from other sources (typically YouTube via ISRC matching).
Dashboard Spotify Features
When a user connects their Spotify account via the dashboard:
- View their Spotify playlists
- Import Spotify playlists into bot playlists
- View top tracks and listening stats
The OAuth flow is handled by SpotifyOAuthService.ts in the dashboard backend.
Last.fm
Last.fm integration provides automatic scrobbling of tracks played through the bot.
Last.fm API Credentials
- Go to Last.fm API Account Creation (opens in a new tab).
- Create an application.
- Note the API Key and Shared Secret.
- Set the Callback URL to your WebServer's Last.fm endpoint.
Configuration (config.yml)
features:
WebServer:
enable: true
Port: 2444
BaseUrl: "https://ws.example.com"
LAST_FM_SCROBBLED:
Enable: true
ApiKey: "your_lastfm_api_key"
Secret: "your_lastfm_shared_secret"
Callback: "https://ws.example.com/lastfm"
scheduleScrobble: 60000| Key | Type | Description |
|---|---|---|
Enable | boolean | Enable Last.fm scrobbling |
ApiKey | string | Last.fm API key |
Secret | string | Last.fm shared secret |
Callback | string | Public URL for the Last.fm OAuth callback. Must be accessible from the internet |
scheduleScrobble | number | Scrobble processing interval in milliseconds (default: 60000 = 1 minute) |
How Scrobbling Works
User plays a track via the bot
│
▼
trackStart event fires
│
▼
ScrobbleToLastFM checks if user has a linked Last.fm account
│
▼
If linked: queue the track for scrobbling
│
▼
Scheduled scrobble job (every 60s) processes the queue
│
▼
Sends scrobble to Last.fm API: track.scrobbleLinking a Last.fm Account
Users link their Last.fm account through one of two methods:
Discord Command
/lastfm connectThe bot sends a link to the Last.fm authorization page. After the user authorizes, they are redirected to the Callback URL, where the bot exchanges the token and stores the session key.
Dashboard
The guild settings page has a Last.fm section where users can connect and disconnect their account. This uses the same OAuth flow.
Account Data
When a user links their Last.fm account, the following is stored in the database:
| Field | Description |
|---|---|
lastFmSessionKey | Last.fm session key for API calls |
lastFmUsername | Last.fm username |
Music Trivia Integration
The Last.fm API key is also used by the Music Trivia system for:
- Fetching personalized recommendations via
user.getRecommendedTracks - Fetching track/artist tags for genre classification via
track.getTopTagsandartist.getTopTags
If no Last.fm API key is configured, the trivia system silently falls back to the static song bank.
Lavalink Plugins
The Lavalink server uses several plugins for extended source support. These are configured in Lavalink's application.yml (reference file at additional-file/application.yml):
LavaSrc
Resolves tracks from Spotify, Apple Music, Deezer, Tidal, and Yandex Music.
plugins:
lavasrc:
sources:
spotify: true
applemusic: true
deezer: true
tidal: true
yandexmusic: false
spotify:
clientId: "..."
clientSecret: "..."
applemusic:
mediaAPIToken: "..."
deezer:
masterDecryptionKey: "..."
tidal:
countryCode: "US"LavaSearch
Provides search functionality across multiple sources.
SponsorBlock
Skips sponsored segments in YouTube videos.
plugins:
sponsorblock:
categories:
- "sponsor"
- "selfpromo"
- "interaction"
- "intro"
- "outro"
- "preview"YouTube Source
Required for YouTube playback. May require poToken configuration for reliable access.
plugins:
youtube:
enabled: true
clients:
- "MUSIC"
- "WEB"
- "ANDROID_TESTSUITE"Top Chart API
The dashboard player features Top Tracks Today and Top Country Tracks sections. These are powered by the Meww.me Top Chart API (opens in a new tab), a JSON API service that scrapes daily Spotify chart data from Kworb.net and enriches it with Spotify metadata.
How It Works
The bot fetches chart data via SpotifyTopChartService.ts:
Dashboard Player
|
v
DashboardPlugin.ts → GET /api/top-chart?country=...
|
v
SpotifyTopChartService.ts
|
v
https://topchart-api.vercel.app/api/stats/tracks?country=...
|
v
Response: Top 50 tracks with rank, title, artist, cover art, Spotify URLResults are cached in-memory for 1 hour per country. If a country-specific request fails, it falls back to the global chart.
Default API
By default, the bot uses the hosted instance at:
https://topchart-api.vercel.app/api/stats/tracksThis is configured in SpotifyTopChartService.ts:
const CHARTGURU_BASE = "https://topchart-api.vercel.app/api/stats/tracks";Supported Countries
| Code | Country | Code | Country |
|---|---|---|---|
global | Global | kr | South Korea |
us | United States | in | India |
gb | United Kingdom | au | Australia |
id | Indonesia | es | Spain |
jp | Japan | it | Italy |
de | Germany | ca | Canada |
fr | France | se | Sweden |
br | Brazil | ph | Philippines |
mx | Mexico | tr | Turkey |
nl | Netherlands | ar | Argentina |
API Response Format
{
"tracks": [
{
"trackId": "2plbrEY59IikOBgBGLjaoe",
"name": "Die With A Smile",
"mainArtistName": "Lady Gaga, Bruno Mars",
"rank": 1,
"previousRank": 1,
"rankDelta": 0,
"dailyStreams": 8500000,
"totalStreams": 3200000000,
"imageUrl": "https://i.scdn.co/image/...",
"spotifyUrl": "https://open.spotify.com/track/..."
}
]
}API Endpoints
| Method | Endpoint | Description |
|---|---|---|
GET | /api/stats/tracks | Top daily tracks with streams, rank, Spotify metadata |
GET | /api/stats/tracks/history | Track stream/rank history |
GET | /api/stats/countries | List of supported countries |
GET | /api/stats/last-updated | Timestamp of last data refresh |
Query parameters for /api/stats/tracks:
| Param | Default | Description |
|---|---|---|
country | global | Country code (e.g., id, us, gb) |
limit | 25 | Number of results |
Self-Hosting the Top Chart API
You can deploy your own instance of the Top Chart API from github.com/lrmn7/mewwme-top-chart (opens in a new tab).
Prerequisites
- Node.js 18+
- MySQL / PostgreSQL / SQLite database
- Spotify Developer (opens in a new tab) app credentials
Quick Setup
# Clone the repository
git clone https://github.com/lrmn7/mewwme-top-chart.git
cd mewwme-top-chart
# Install dependencies
npm install
# Copy environment variables
cp .env.example .envEdit .env:
SPOTIFY_CLIENT_ID=your_spotify_client_id
SPOTIFY_CLIENT_SECRET=your_spotify_client_secret
DATABASE_URL="mysql://user:password@host:3306/database"
ADMIN_SECRET=your_secret_here
SCRAPE_COUNTRIES=global,id,us,gb,jp,kr,de,fr,br,mx,in,au,es,it,ca,se,ph,tr,ar,nl
TOP_TRACKS_LIMIT=25
PORT=3301Database setup:
npx prisma generate
npx prisma db pushThree database schema variants are provided:
prisma/schema.prisma- MySQL (default)prisma/schema.postgresql.prisma- PostgreSQLprisma/schema.sqlite.prisma- SQLite (local dev)
To switch database, copy the desired schema to schema.prisma and update DATABASE_URL.
Run the server:
# Development
npm run dev
# Production
npm run build
npm startDeployment Architecture
The recommended deployment uses a hybrid architecture:
GitHub Actions (cron: 06:00 & 18:00 UTC)
1. Scrape Kworb.net
2. Enrich via Spotify API
3. Write to MySQL
|
v
MySQL Database
|
v
Vercel (API server)
/api/stats/tracks
/api/stats/countries
|
v
Discord Bot / Client- GitHub Actions handles data scraping on a cron schedule (no time limits)
- Vercel serves the JSON API (fast, serverless)
- MySQL database stores all track data (shared between both)
Alternatively, you can use any Node.js hosting (Hostinger, VPS, etc.) with the included server.js.
Connecting to Your Self-Hosted Instance
After deploying, update SpotifyTopChartService.ts in the bot backend to point to your own URL:
const CHARTGURU_BASE = "https://your-domain.com/api/stats/tracks";Rebuild the bot and restart.