The miniplug API is heavily Promise-based. Most methods return Promises.

miniplug uses the Bluebird library. That means that Promises returned by miniplug have all the useful methods from Bluebird, too. See its API reference for a list.

Promises work really well with JavaScript async functions. Async functions are not available in most engines yet. You can compile async functions to generator functions, which are widely supported, using async-to-gen, or using Babel with the babel-plugin-transform-async-to-generator transform. If you do not want a build step, you can use the Bluebird .coroutine method to write similar-looking code with generator functions.

mp = miniplug(opts={})

Create a miniplug instance. Available options:

  • opts.guest - If true, will log in as a guest user. Defaults to false.
  • opts.email and opts.password - Login credentials. Only email/password login is supported at the moment.
import miniplug from 'miniplug'

const mp = miniplug({ guest: true })
const mp = miniplug({
  email: 'example@test.com',
  password: 'hunter2'


Add a plugin to enhance miniplug's functionality. Returns the miniplug instance for chaining.

import lotteryPlugin from 'miniplug-lottery'

  .use((instance) => { /* Add other custom methods to `instance` */ })

mp.join(room): Promise<Room>

Join a room. The parameter is the room's slug. If your room URL is https://plug.dj/loves-kpop, the slug is loves-kpop.

mp.join('loves-kpop').then(() => {

mp.room(): Room

Get the current room object.

console.log('I am in:', mp.room().name)

mp.getRooms(query='', page=0, limit=50): Promise<Array<Room>>

List open rooms, like on the plug.dj dashboard.

query is a search query. page and limit can be used for pagination.

mp.getRooms('reggae').then((rooms) => {
  rooms.forEach((room) => {

mp.getFavorites(query='', page=0, limit=50): Promise<Array<Room>>

List the current user's favorites.

query is a search query. page and limit can be used for pagination.

mp.validateRoomName(name): Promise<{slug: string}>

Check if a room name is valid and available. Returns a Promise that resolves with an object containing the room's slug if the name is valid and available, and rejects if the name is invalid or unavailable.

  .then((o) => console.log('Room is available with slug:', o.slug))
  .catch((err) => console.log(err.message))

mp.createRoom(name, isPrivate = false): Promise<Room>

Create a new room. Note that plug.dj will derive an unchangeable URL slug from the name. This slug may collide with existing rooms.

mp.createRoom('My private test room!', true).then((room) => {
  return room.favorite()

mp.favoriteRoom(id): Promise

Add a room to the bot user's favorites.

mp.favoriteRoom(123456).then(() => {

mp.unfavoriteRoom(id): Promise

Remove a room from the bot user's favorites.

mp.unfavoriteRoom(123456).then(() => {

mp.getRoomState(): Promise<Room>

Get the current room object, but fresh from the plug.dj API and not cached. This is like an async version of mp.room(). Using mp.room() should be preferred whenever possible.

mp.me(): User

Get the current logged-in user. Will be null when logged in as a guest user.

console.log('Logged in as', mp.me().username)

mp.user(id): User

Synchronously get a user object from the current room. Returns null if the requested user is not in the room.

console.log('Some other user:', mp.user(123456).username)

mp.users(): Array<User>

Synchronously get all user objects from the current room.

console.log('Users:', mp.users().map((user) => user.username))

mp.guests(): number

Get the number of guests in the current room.

mp.getMe(): Promise<User>

Get the current logged-in user from the plug.dj web API. mp.me() should be used instead whenever possible.

mp.getUser(id): Promise<User>

Get a user object by ID. The user does not have to be in the same room as the bot.

mp.getUsers(...ids): Promise<Array<User>>

Get multiple users. User IDs can be passed in an array or as separate arguments. Up to 50 user objects can be requested at a time.

mp.getUsers(123456, 654321).then((users) => {
  console.log('Found:', users)

mp.saveSettings(settings): Promise

Save user settings. See the PlugCommunity documentation for a list of available settings.

mp.setAvatar(avatar): Promise

Set the bot user's avatar.

mp.setBadge(badge): Promise

Set the bot user's badge.

mp.setBlurb(blurb): Promise

Set the bot user's profile blurb / bio.

mp.setLanguage(lang): Promise

Set the bot user's language preference.

mp.getTransactions(): Promise<Array>

Get the bot user's transaction history.

mp.score(): {positive, negative, grabs, listeners}

Get the score for the currently playing media.

Returns an object with properties:

  • positive - Amount of woots.
  • negative - Amount of mehs.
  • grabs - Amount of grabs.
  • listeners - Amount of listeners.
const score = mp.score()
mp.chat(`Score: ${score.positive} woots - ${score.negative} mehs - ${score.grabs} grabs`)

mp.vote(direction): Promise

Vote on the currently playing media.

direction is 1 for woot, -1 for meh.

const direction = Math.random() < 0.5 ? -1 : 1

mp.woot(): Promise

Woot the currently playing media.

mp.woot().then(() => {
  mp.chat('Great track! Wooted!')

mp.meh(): Promise

Meh the currently playing media.

mp.meh().then(() => {
  mp.chat('Ew, I don\'t like this. :(')

mp.dj(): User

Get the current DJ. Returns null if there is no DJ.

mp.dj().chat('Nice play!')
// β†’ "@Username Nice play!"

mp.waitlist(): Waitlist

Get the current waitlist. A Waitlist object is a JavaScript array containing User objects, so the typical JavaScript array methods can be used:

mp.waitlist().forEach((user, position) => {
  console.log(`#${position + 1} - ${user.username}`)

There are also some additional methods:

// By user ID
// or by user object.


mp.joinWaitlist(): Promise

Join the waitlist.

mp.leaveWaitlist(): Promise

Leave the waitlist.

mp.setCycle(cycle): Promise

Change whether the waitlist should cycle.

// Disable waitlist cycle when there are 20 or more DJs.
mp.on('waitlistUpdate', (waitlist) => {
  if (waitlist.length < 20) {
  } else {

mp.enableCycle(): Promise

Enable waitlist cycle. Shorthand to setCycle(true).

mp.disableCycle(): Promise

Disable waitlist cycle. Shorthand to setCycle(false).

mp.setLock(lock): Promise

Change whether normal users can join the waitlist. If the waitlist is locked, only Resident DJs and up can join.

mp.setLock(true).then(() => {
  mp.chat('Sorry! Only staff can join the waitlist at the moment.')

mp.lockWaitlist(): Promise

Lock the waitlist, preventing users from joining. Shorthand to setLock(true).

mp.unlockWaitlist(): Promise

Unlock the waitlist, allowing everyone to join. Shorthand to setLock(false).

mp.addDJ(uid): Promise

Add a user to the end of the waitlist. uid is the user's ID.

mp.moveDJ(uid, position): Promise

Move a user in the waitlist. uid is the user's ID. position is the target position, starting at 0.

// Add a user to position #2 in the waitlist.
mp.addDJ(123456).then(() => {
  return mp.moveDJ(123456, 1)

mp.removeDJ(uid): Promise

Remove a user from the waitlist. uid is the user's ID.

const user = mp.user(123456)
mp.removeDJ(user.id).then(() => {
  return user.chat('I removed you from the waitlist. Sorry! πŸ™ˆ')

mp.chat(message): Promise<ChatMessage>

Send a chat message. Returns a Promise that will resolve with the message once it is sent.

// Send a temporary greeting that is deleted after 5 seconds.
// Note that the bot user needs to have the appropriate staff permissions to be
// able to delete its own messages.

  .delay(5000) // Using Bluebird's .delay() method
  .then((message) => message.delete())

mp.emote(message): Promise<ChatMessage>

Send an emote chat message, like /me or /em on the plug.dj web client.

mp.emote('does a little dance')
  .then((message) => { /* Resolves to the message, just like mp.chat(). */ })

mp.deleteChat(id): Promise

Delete a chat message by ID.

// Delete all incoming chat:
mp.on('chat', (message) => {

mp.getPlaylists(): Promise<Array<Playlist>>

Get all the user's playlists.

// Using Bluebird's `.each()` method
mp.getPlaylists().each((playlist) => {
  console.log(`${playlist.name} (${playlist.count})`)

mp.getActivePlaylist(): Promise<Playlist>

Get the user's active playlist.

mp.getActivePlaylist().then((playlist) => {
  return playlist.insert({
    format: mp.MEDIA_SOURCE.YOUTUBE,
    cid: 'UT4zZzAtWm4',
    author: 'Ovcoco',
    title: 'Your Ghost',
    duration: 209,
    image: 'https://i.ytimg.com/vi/UT4zZzAtWm4/default.jpg'

mp.createPlaylist(name): Promise<Playlist>

Create a new playlist.

mp.createPlaylist('Test playlist').then((playlist) => {
  return Promise.all([
      // your favourite songs

mp.deletePlaylist(id): Promise

Permanently delete a playlist by ID.

Alias: playlist.delete()

mp.activatePlaylist(id): Promise

Set a playlist to active by ID.

Alias: playlist.activate()

mp.renamePlaylist(id, name): Promise

Rename a playlist.

Alias: playlist.rename(name)

mp.shufflePlaylist(id): Promise<Array<Media>

Shuffle a playlist. Returns a Promise that resolves with the shuffled media items.

Alias: playlist.shuffle()

mp.getMedia(id): Promise<Array<Media>

Get the media items in a playlist.

Alias: playlist.getMedia()

mp.updateMedia(pid, mid, author, title): Promise<{author, title}>

Update the author and title tags of a media item. Returns a Promise that resolves with the new actual author and title as used by plug.dj, with HTML escapes.

mp.updateMedia(playlist.id, media.id, 'Test Author', '& Test Title').then(({ author, title }) => {
  // author == "Test Author"
  // title == "&amp; Test Title"

Alias: media.update(author, title)

mp.moveMedia(pid, mids, before): Promise

Move existing media items to a different position in the playlist.

Alias: playlist.move()

mp.insertMedia(id, media, append=true): Promise

Insert new media items into a playlist.

Alias: playlist.insert()

mp.deleteMedia(pid, mids): Promise<Array<Media>

Alias: media.delete()

mp.getProducts(type, category='all'): Promise<StoreProduct>

Get the product listing from a store category. type is one of 'avatars', 'badges' or 'misc'. category selects a specific category, like a page in the store. See Product Categories for an overview of available categories for each product type.

import randomItem from 'random-item'
mp.getProducts('avatars', 'island').then((products) => {
  return randomItem(products).purchase()

mp.getStoreAvatars(category='all'): Promise<StoreProduct>

Get the avatars store listing. Shorthand to getProducts('avatars', category).

mp.getStoreBadges(category='all'): Promise<StoreProduct>

Get the badges store listing. Shorthand to getProducts('badges', category).

mp.getStoreMisc(category='all'): Promise<StoreProduct>

Get the miscellaneous store listing. Shorthand to getProducts('misc', category).

mp.getInventory(type): Promise<InventoryProduct>

Get the products purchased by the user.

mp.getOwnedAvatars(): Promise<InventoryProduct>

Get the avatars purchased by the user.

mp.getOwnedBadges(): Promise<InventoryProduct>

Get the badges purchased by the user.

mp.purchase(product): Promise

Purchase an avatar or a badge. product is a product ID, or a StoreProduct.

mp.validateUsername(name): Promise<{slug: string}>

Check if a user name is valid and available. Returns a Promise that resolves with an object containing the new profile slug if the name is valid and available, and rejects if the name is invalid or unavailable.

  .then((o) => console.log('Username is available with slug:', o.slug))
  .catch((err) => console.log(err.message))

mp.purchaseNameChange(username): Promise

Purchase a name change.

mp.notifications(): Array<Notification>

Get a list of current notifications.

// Acknowledge all notifications.
const promises = mp.notifications().map((notif) => {
  return notif.acknowledge()

// Wait for all acknowledgements to go through.
Promise.all(promises).then(() => {
  console.log('All clear!')

mp.getNotifications(): Promise<Array<Notification>>

Get current notifications from the plug.dj Web API. Normally mp.notifications() should be preferred instead, because it's instant.

mp.acknowledgeNotification(id): Promise

Acknowledge and remove a notification. id is the numeric unique ID of the notification.


room.id: number

The room's unique ID.

room.name: string

The room's name.

room.slug: string

The room's unique URL slug.

mp.chat('Visit us at https://plug.dj/' + mp.room().slug + '!')

room.join(): Promise

Join this room. See mp.join(room).

// Join the most populous room.
mp.getRooms().then((rooms) => {
  const room = rooms[0]
  return room.join()

room.favorite(): Promise

Add this room to the bot user's favorites.

// Add the top 50 most populous rooms to favorites.
  .map((room) => room.favorite())
  .then(() => {
    console.log('Added lots of favorites')

room.unfavorite(): Promise

Remove this room from the bot user's favorites.

// Remove the current room from favorites.
mp.room().unfavorite().then(() => {


user.id: number

User ID.

user.username: string


user.chat(text): Promise<ChatMessage>

Send a chat message directed at this user. Prepends @Username to the provided text.

// β†’ "@Username Hello!"

user.emote(text): Promise<ChatMessage>

Send an emote chat message directed at this user.

// β†’ "/me @Username Hello!"

user.mention(): string

Get a string to mention the user in the chat.

const mentionStr = mp.user(123456).mention()
// β†’ "@Username"

This function is also used when stringifying a user object, for example when embedding it in a template string:

const message = `Hello ${mp.user(123456)}!`
// β†’ "Hello @Username!"

user.add(): Promise

Add the user to the waitlist.

user.move(position): Promise

Move the user to a different position in the waitlist.

user.remove(): Promise

Remove the user from the waitlist or the DJ Booth.

user.skip(historyId): Promise

Skip the user. historyId is the ID of the currently playing track, i.e. mp.historyEntry().id.

user.befriend(): Promise

Send or accept a friend request to/from this user.

user.rejectRequest(): Promise

Reject a friend request from this user.

user.ignore(): Promise

Ignore the user in chat.

user.unignore(): Promise

Stop ignoring the user in chat.

user.mute(duration, reason): Promise

Mute the user in chat. duration is a MUTE_DURATION. reason is a MUTE_REASON.

user.unmute(): Promise

Unmute the user in chat.

user.ban(duration, reason): Promise

Ban the user from the room. duration is a BAN_DURATION. reason is a BAN_REASON.

user.unban(): Promise

Unban the user from the room.


Waitlist objects are JavaScript arrays of User objects. Like JavaScript arrays, Waitlist objects are zero-indexed, so the user on top of the waitlist (#1 on plug.dj) is waitlist[0].

// Notify users when they're about to play.
mp.on('advance', () => {
  const waitlist = mp.waitlist()
  if (waitlist.length >= 1) {
    waitlist[0].chat('You\'re up next!')

Because Waitlist objects are JavaScript arrays, all the usual JavaScript array methods can be used. Note that most native JavaScript array methods return plain JavaScript arrays, and not Waitlist objects.

const firstTen = mp.waitlist().slice(0, 10)
// firstTen is NOT a Waitlist object--just an array of the first ten users.

waitlist.contains(user): bool

Check if a user is in the waitlist. user is a User object or a user ID.

if (mp.waitlist().contains(123456)) {
  mp.user(123456).chat('You\'re in the waitlist, Hermione!')

This is similar to the Array#includes method of JavaScript arrays. However, includes only checks that exactly the given object is in the array, whereas contains checks whether an object representing the same user as the given object or ID is in the array.

waitlist.positionOf(user): number

Returns the position of a user in the waitlist. user is a User object or a user ID. Returns -1 if the given user is not in the waitlist.

This is similar to the Array#indexOf method of JavaScript arrays. The same differences apply as with waitlist.contains.


message.id: string

Message ID.

message.message: string

Message text contents.

message.uid: number

User ID of the sender of the message.

message.un: string

Username of the sender of the message.

message.getUser(): Promise<User>

Get the sender of the message.

message.own(): bool

Returns true if the message was sent by the logged-in user, or false if it was sent by someone else.

mp.chat('My own message').then((message) => {
  assert.ok(message.own() === true)

mp.on('chat', (message) => {
  // True if it was sent using mp.chat() or mp.emote().
  // False if it was sent by some other user.

message.reply(text): Promise<ChatMessage>

Reply to the sender of the message using an @-mention.

mp.on('chat', (message) => {
  if (message.message === '!myid') {
    // Sends "@Username Your user ID is 123456"
    message.reply('Your user ID is ' + message.uid)

message.emote(text): Promise<ChatMessage>

Reply to the sender of the message using an @-mention in an emote message.

message.delete(): Promise

Delete the message.

mp.on('chat', (message) => {
  message.delete().then(() => {
    console.log('Deleted message from ' + message.un)


playlist.id: number

The playlist ID.

playlist.name: string

Playlist name.

playlist.count: number

The amount of media items in the playlist.

playlist.active: bool

True if this is the active playlist.

playlist.delete(): Promise

Permanently delete the playlist.

playlist.activate(): Promise

Set this playlist to active.

playlist.rename(name): Promise

Rename the playlist.

playlist.shuffle(): Promise<Array<Media>>

Shuffle the items in the playlist. Returns a Promise that resolves to the shuffled media items in the playlist.

playlist.getMedia(): Promise<Array<Media>>

Get the items in the playlist.

playlist.insert(media, append=true): Promise<{id, count}>

Add media items to the playlist. media can be a Media object or ID, or an array of Media objects or IDs. When append is true, the medias are added to the end of the playlist. When append is false, they are added to the front.

Returns a Promise that resolves to an object containing the playlist id, and the new total count of items in the playlist.

playlist.move(media, before): Promise<Array<Media>>

Move media items in the playlist. media can be a Media object or ID, or an array of Media objects or IDs. The items will be moved in front of the Media objects or ID given in before. If before is -1, the items will be moved to the end of the playlist.

Returns a Promise that resolves with the Media items in the playlist after the move was finished.


media.id: number

The media ID on plug.dj.

media.format: MEDIA_SOURCE


media.cid: string

The media ID on the relevant source.

media.author: string

The author / artist tag of the media.

media.title: string

The title tag of the media.

media.duration: number

Duration in seconds of the media.

media.image: string

A URL pointing to a thumbnail image.

media.update(author, title): Promise<{author, title}>

Update the author and title tags of a media item. Returns a Promise that resolves with the new actual author and title as used by plug.dj, with HTML escapes.

media.delete(): Promise

Delete the media from the playlist it belongs to.


entry.id: string

The unique ID of the history entry.

entry.media: Media

The media that was played.

entry.room: Room

The room where the history entry was played. Note that this .room object only contains three of the Room class properties:

  • entry.room.name - The name of the room;
  • entry.room.slug - The URL slug of the room;
  • entry.room.private - Whether the room is private.

There is not currently a way to load a full Room object if you need more information. This will hopefully be added in a future update.

entry.user: User

The user that played this song. Note that this .user object only contains two of the User class properties:

  • entry.user.id - The user's ID. This allows you to use most User class methods.
  • entry.user.username - The user's name.

If you need anything else, use the entry.getUser() method to load a full User object.

entry.time: Date

Timestamp at which the history entry was played.

entry.score: {positive, negative, grabs, listeners}

An object describing audience response to the song. Contains four properties, all numbers:

  • entry.score.positive - The amount of woots.
  • entry.score.negative - The amount of mehs.
  • entry.score.grabs - The amount of grabs.
  • entry.score.listeners - The amount of people in the room at the time the song was played.

entry.getUser(): Promise<User>

Get the full user object of the user who played this song.


product.type: string

The product type: 'avatars', 'badges', or 'misc'.

product.category: string

The product category, i.e. the page on which it appears in the store. See Product Categories.

product.id: number

The product ID.

product.name: string

The product name. This is not a human-readable name. Examples include "classic01" and "admin-o01".

product.level: number

The minimum level the user has to have to unlock the product.

product.pp: number?

The price of the product in plug points. If the product cannot be purchased with points, this property will not exist (i.e. be undefined).

product.sub: number?

1 if the product is for Subscribers only. Subscriber-only products are automatically added to the inventories of subscribed users. If the product is not automatically available to subscribers, this property will not exist (i.e. be undefined).

Note that 1 is a "truthy" value and undefined is falsy, so a simple if statement can be used to check if a product is subscriber-only:

mp.getStoreAvatars().each((avatar) => {
  let description = `Avatar: ${avatar.name}`
  if ('pp' in avatar) {
    description += ` - Points: ${avatar.pp}`
  if ('cash' in avatar) {
    description += ` - $${avatar.cash}`
  if (avatar.sub) {
    description += ' - Free for Subscribers'

product.cash: number?

The price of the product in US dollars. If the product cannot be purchased with real money, this property will not exist (i.e. be undefined).

product.purchase(): Promise

Purchase the product. Only works for products that can be purchased with points.


product.type: string

The product type: 'avatars', 'badges', or 'misc'.

product.category: string

The product category, i.e. the page on which it appears in the user's inventory. See Product Categories.

product.name: string

The internal product name.


A plug.dj service notification. These are the notifications listed on your user profile under My Profile Β» Notifications.

notification.id: number

Unique ID of the notification.

notification.action: string

Type of notification. This determines what the Notification's value stands for. Miniplug parses the value for some notification types.

  • levelUp - The user leveled up. level is the new level.
  • custom - A custom notification sent by plug.dj. message contains the notification message. Note that the message can contain HTML.
  • gift - The user received a gift. from contains the username of the sender, and amount contains the amount of PP that was gifted.
  • boostExpired - An XP boost purchased by the user has expired. Obsolete, since plug.dj doesn't sell XP boosts anymore.

notification.timestamp: Date

Date and time when the notification came in.

notification.value: string

Raw value of the notification. This can mean different things for different actions. It's best to use one of the other properties documented below if you can.

See notification.action.

notification.level: number

The user's new level after leveling up. Only present when the notification action is levelUp.

notification.message: string

HTML message contents of a plug.dj announcement notification. Only present when the notification action is custom.

notification.from: string

Nickname of the sender of a gift. Only present when the notification action is gift.

notification.amount: number

Amount of PP in a gift. Only present when the notification action is gift.

notification.acknowledge(): Promise

Acknowledge and remove the notification.

Mute Durations

import { MUTE_DURATION } from 'miniplug'


15 minutes.


30 minutes.


45 minutes.

Mute Reasons

import { MUTE_REASON } from 'miniplug'


Violating community rules.


Verbal abuse or harassment.


Spamming or trolling.


Offensive language.


Negative attitude

Ban Durations

import { BAN_DURATION } from 'miniplug'


A 1 hour ban.


A 1 day ban.


A permanent ban.

Ban Reasons

import { BAN_REASON } from 'miniplug'


Spamming or trolling.


Verbal abuse or offensive language.


Playing offensive videos/songs.


Repeatedly playing inappropriate genre(s).


Negative attitude.

Media Sources

import { MEDIA_SOURCE } from 'miniplug'


Identifies a YouTube video.


Identifies a SoundCloud track.

Product Categories

Note: These listings were last updated on 03 December 2016. It's not guaranteed to be 100% correct. If you spot a mistake or a missing category, please send a PR!


  • 'classic'
  • 'hiphop'
  • 'rave'
  • 'base'
  • 'country'
  • '80s'
  • 'rock'
  • '2014hw'
  • 'robot'
  • 'zoo'
  • 'warrior'
  • 'dragon'
  • '2014winter'
  • 'sea'
  • 'island'
  • 'diner'
  • 'beach'
  • 'nyc'


  • 'b-original'
  • 'b-sea'
  • 'b-island'
  • 'b-rave'
  • 'b-base'
  • 'b-food'
  • 'b-diner'
  • 'b-country'
  • 'b-robot'
  • 'b-zoo'
  • 'b-hiphop'
  • 'b-80s'
  • 'b-warrior'
  • 'b-beach'
  • 'b-nyc'


  • 'username'
  • 'boost' is obsolete, but used to contain XP boost items in the past.

mp.get/post/put/del(url: string, data: object): Promise

These are low-level REST methods. You most likely do not need to use them directly. Instead, use one of the methods described in the rest of this document.

Send an HTTP request to the given plug.dj API endpoint. The url is relative to the plug.dj API base URL. data is used for the request body for POST, PUT and DELETE requests, and as the query string for GET requests.

mp.get('rooms', { q: 'k-pop' }).then(console.log)
// sends `GET https://plug.dj/_/rooms?q=k-pop`

mp.post('booth/skip', { userID: 123456, historyID: mp.historyEntry().id })
// sends `POST https://plug.dj/_/booth/skip` with a request body like:
// { "userID": 123456, "historyID": "ab0c47eb-6c92-45f8-8711-75e27977db06" }



Fired when the DJ booth advances, and the next song starts playing.


  • next - The new HistoryEntry, or null if there is no new DJ.
  • previous - The previous HistoryEntry, or null if there was no DJ earlier.
mp.on('advance', (next, previous) => {
  if (previous) {
    console.log('Last song:', previous.media.author, '-', previous.media.title)
  if (next) {
    console.log('Next song:', next.media.author, '-', next.media.title)


Fired when a chat message is received.


mp.on('chat', (message) => {
  if (/^!whoami/.test(message.message)) {
    message.reply(`You are ${message.un}, #${message.uid}.`)


Fired when a user grabs the current song.


  • user - The User who grabbed the song.
mp.on('grab', (user) => {
  const media = mp.media()
  console.log(user.mention(), 'grabbed', media.author, '-', media.title)


Fired when a guest joins the room. Does not receive any parameters.

mp.on('guestJoin', () => {
  console.log('A wild guest appeared!')


Fired when a guest leaves the room. Does not receive any parameters.

mp.on('guestLeave', () => {
  console.log('A guest left the room.')


Fired when an attribute of the current room updates.


  • change - Object containing the new attribute/value pair. For example, if the welcome message was changed, the object may contain { welcome: 'Hello!' }.
  • user - The staff User who made the change.
const roomProperties = mp.room().toJSON()

mp.on('roomUpdate', (change) => {
  Object.assign(roomProperties, change)


Fired when the room name was changed.


  • name - The new room name.
  • user - The staff User who made the change.
mp.on('roomNameUpdate', (name, user) => {
  console.log(user.mention(), 'changed the room name to', name)


Fired when the room description was changed.


  • description - The new room description.
  • user - The staff User who made the change.
mp.on('roomDescriptionUpdate', (description, user) => {
  console.log(user.mention(), 'changed the room description to:')


Fired when the room welcome message was changed.


  • welcome - The new welcome message.
  • user - The staff User who made the change.
mp.on('roomWelcomeUpdate', (welcome, user) => {
  console.log(user.mention(), 'changed the welcome message.')
  console.log('New users will now see', welcome)


Fired when the room's minimum chat level changes.


  • minChatLevel - The new minimum chat level.
  • user - The staff User who made the change.
mp.on('roomMinChatLevelUpdate', (level, user) => {
  console.log(user.mention(), 'changed the minimum chat level to', level)


Fired when a user joins the room.


  • user - The User object of the new user.
mp.on('userJoin', (user) => {


Fired when a user leaves the room.


  • user - The User object of the leaving user.
import { BAN_DURATION, BAN_REASON } from 'miniplug'
mp.on('userLeave', (user) => {
  // Alright then. GOOD BYE AND NEVER COME BACK!! πŸ˜ πŸ’’


Fired when a user woots or mehs a song.


  • data - An object with two properties:
  • user - The User who voted.
  • vote - The direction of the vote: 1 for a woot, -1 for a meh.
mp.on('vote', (data) => {
  if (data.vote === 1) {
    console.log(data.user.mention(), 'wooted this track!')
  } else if (data.vote === -1) {
    console.log(data.user.mention(), 'meh\'d this track…')


Fired when the waitlist changes.


mp.on('waitlistUpdate', (next, previous) => {
  const me = mp.me()

  // Notify the next DJ that it is almost their turn.
  if (next.length > 0) {
    next[0].send('You are next!')

  // Both parameters are full Waitlist objects.
  console.log('I moved from', previous.positionOf(me), 'to', next.positionOf(me))