1.1.0 • Published 21 days ago

ttfm-socket v1.1.0

Weekly downloads
-
License
MIT
Repository
-
Last release
21 days ago

Turntable LIVE Socket Client

Welcome to the Turntable LIVE Socket Client! This package provides a TypeScript client to communicate with rooms on Turntable.

Installation

npm install ttfm-socket

Joining a Room

To join a room, you'll need to retrieve the UUID for that room using this endpoint. Then create an instance of the SocketClient and run the joinRoom method:

import { SocketClient } from "ttfm-socket";

const client = new SocketClient("https://socket.prod.tt.fm");
const token = "{your Turntable JWT}";

const { state } = await client.joinRoom(token, {
  roomUuid: "{room uuid}",
  password: "{optional room password}",
});

Assuming you are allowed to join the room (e.g. it's not full, the password is correct, etc.), joinRoom will resolve with an object containing state, an object representing the current room state. In this response, allUserData will be an empty object, to be filled in later (see updatedUserData). If your join request is rejected for any reason, joinRoom will throw an error.

Events

When the SocketClient receives a message broadcast from the server, it emits a corresponding event, which can be listened to.

serverMessage

This is emitted on all messages broadcast from the server. The value emitted here is the full message object, which contains both our custom message as well as other values such as messageId and sentAt.

statefulMessage

This is emitted when the SocketClient receives a server message that contains statePatch. The value emitted here is only our custom message without any of the extra values. The type of the message is narrowed so that the listener knows that statePatch will exist.

statelessMessage

This is emitted when the SocketClient receives a server message that contains params instead of statePatch. The value emitted here is only our custom message without any of the extra values. The type of the message is narrowed so that the listener knows that params will exist.

error

This is when the Primus connection has an error, or when the server returns an error after trying to run an Action. The value emitted here is a string error message, or potentially undefined if there is no error message available.

Connection States

There are four possible events here: connected, disconnected, reconnecting, and timeout. These are emitted when the connection state changes. There is no value emitted with these, so the listener will have 0 arguments.

Listening for Messages

Once a room has been joined, you should attach listeners to the SocketClient to handle incoming messages. To compute the state updates, we recommend the fast-json-patch package.

import { applyPatch } from "fast-json-patch";

client.on("statefulMessage", (message) => {
  const newState = applyPatch(
    prevState,
    message.statePatch,
    true,
    false,
  ).newDocument;
  // Save the new state
});

client.on("statelessMessage", (message) => {
  // Respond to the message based on its name and params
});

Listeners can also be added for specific messages:

client.on(ServerMessageName.kickedFromRoom, () => {
  // Clear local state and destroy the client
});

Actions

When a client wants to make some sort of update to the room, it can do so with the action method in the SocketClient class. Documentation for these actions can be found here. For example, to take the stage in a room a client would run the addDj action:

client.action<AddDjAction>(ActionName.addDj, { song: { ... } })

In this case, song is optional but should match the type MinimalCrateSongResDTO.

Messages

After a client or the server successfully runs an action in a room, the server will broadcast a message to every client connected to that room, including the one that ran the Action. As a convention, the names of these messages take the past-tense form of the name of the Action that spawned them. For example, the addDj Action correlates to the addedDj server message.

Stateful Messages

Most of the messages sent by the server come after some sort of room state update. For these, the message will take this shape:

{
  name: StatefulServerMessageNameType;
  statePatch: Operation[];
}

statePatch is a JSON-encoded series of operations for the client to perform in order to update its local state to stay in sync with the server. This adheres the JSON Patch format.

These are all of the stateful messages:

updatedUserData

Sent to the server after a client successfully joins a room, only to that single client. This will contain a statePatch that fills in the allUserData piece of the client state, which is not included in the initial state sent in response to the joinRoom action.

userJoined

Sent by the server to all clients when a user joins the room. This comes after a client successfully runs the joinRoom Action and is added to the Actionhero chatRoom.

userLeft

Sent by the server to all clients when a user leaves the room. When a client sends the Actionhero roomLeave message, or when its connection is closed, we enqueue a 20-second delayed Task. If the user has no active connections after that delay, the server will broadcast this userLeft message.

addedDj

Sent by the server to all clients when a user has been successfully added to the DJ lineup. This comes after a client runs the addDj Action.

removedDj

Sent by the server to all clients when a user has been successfully removed from the DJ lineup. This comes after a client or server runs the removeDj Action.

playedSong

Sent by the server to all clients when nowPlaying changes. This can be triggered by add/removing DJs, skips, kicks, bans, and the current song ending. This same message is sent when there is no next song to play, in which case nowPlaying will be null. The only Action that broadcasts this message is playSong.

updatedNextSong

Sent by the server to all clients when a DJ updates their next song via the updateNextSong Action. This might be followed by the playedSong message, but only if a DJ sends a non-null song and there isn't already something playing.

votedOnSong

Sent by the server to all clients when a user updates their song votes via the voteOnSong Action. This currently handles likes/dislikes and stars. The client state will have per-user voting information, as well as a computed vibeMeter value and an allVotes object that contains arrays of user UUIDs for each type of vote.

lookedUpSong

Sent by the server to all clients after a successful song lookup. This happens if a client sends a song placeholder with the addDj or updateNextSong Actions. It's unlikely the clients will need to do anything in response to this message, but it exists to keep the client state in sync with the server state to avoid errors on subsequent patches.

Stateless Messages

If a message does not accompany a room state update, the shape is slightly different:

{
  name: StatelessServerMessageNameType;
  params?: StatelessServerMessageParams;
}

These are all of the stateless messasges:

playedOneTimeAnimation

Sent by the server to all clients when a user sends a one-time animation. For this message, params takes the following shape:

{
  userUuid: string;
  animation: OneTimeAnimationType;
  emoji?: string;
}

emoji here is only defined if animation is OneTimeAnimation.emoji, and will only ever be a string with a single emoji character in it.

kickedFromRoom

Sent by the server only to the connection(s) for one specific user in a room. This indicates that the user was just kicked (or banned). Immediately following this message, the server will close the connection. This message has no params.

roomReset

Sent by the server after someone hits the /resetRoom endpoint for that room. This means that the room's state will be cleared and the server will close all connections that are currenly in the room. In response to this, the clients will need to open a new connection and rejoin the room via the joinRoom Action. This message has no params.

Examples

Support

If you have any questions or feedback about this package, please reach out to us on Discord or at help@turntabletlive.com.

1.1.0

21 days ago

1.0.7

2 months ago

1.0.6

2 months ago

1.0.4-0

3 months ago

1.0.5

3 months ago

1.0.4

3 months ago

1.0.2

3 months ago

1.0.0

5 months ago

1.0.0-beta.0

6 months ago

1.0.0-beta.1

6 months ago

0.2.6

8 months ago

0.2.5

8 months ago

0.2.4-0

8 months ago

0.2.3

8 months ago

0.2.2

9 months ago

0.2.1

9 months ago

0.2.0

9 months ago