A hosted version of the demo can be found at
Feature | Description | APIs/Primatives used |
---|---|---|
Chat | Uses the PubNub Chat SDK to show how a a chat application can be implemented with a public channel with features such as history, precense, metadata, delete/restore messages. | Public Channels, Join Channels, Create User, Presence, Send/Receive, History, Delete Message, Restore Message |
Broadcasting | Shows how Livepeer can make a real-time livestream with control over live playback, quality, and video/audio settings. | Player, Livestream Playback, Stream |
Moderation | Uses the PubNub Chat SDK to show how you can moderate your Live Events application by allowing users to report users/messages and on the other hand allowing the moderator or broadcaster to mute or ban users from the stream. | Flag/Report Messages, Flag/Report Message, Mute/Ban Users, Profanity Filtering |
To run this project yourself you will need a PubNub and Livepeer account.
-
PubNub Account (Free)
-
Livepeer Account (Free)
-
You’ll first need to sign up for a PubNub account. Once you sign up, you can get your unique PubNub keys from the PubNub Developer Portal.
-
Sign in to your PubNub Dashboard.
-
Click Apps, then Create New App.
-
Give your app a name, and click Create.
-
Click your new app to open its settings, then click its keyset.
-
Enable the Presence feature on your keyset (check 'Presence Deltas' and 'Generate Leave on TCP FIN or RST')
-
Enable the Message Persistence feature on your keyset and choose a duration
-
Enable the App Context feature on your keyset. Make sure you check all the checkboxes related to events, i.e. User and Channel Metadata Events as well as Membership Events.
-
The hosted variant of this app uses Functions for moderation, specifically https://www.pubnub.com/integrations/chat-message-profanity-filter/.
-
Copy the Publish and Subscribe keys and paste them into your app as specified in the next step.
-
Clone the repository
-
In the file
.env.example
delete the extention.example
and your keys here keeping the name of the keys the same.
Please fork the repository if you'd like to contribute. Pull requests are always welcome.
- To modify the application theme, modify the colors located at
/tailwind.config.ts
. Named colors are used throughout this application so changing them here will update the entire app.
chat.listenForEvents({
channel: string;
type?: "report";
callback: (event: Event<"report">) => unknown;
}): () => void
For the moderator/broadcaster to listen to report events by users. Set this value to a dedicated PUBNUB_INTERNAL_ADMIN_CHANNEL
where all report events are sent.
You will need to set up a server component and replace the baseURL
fround under components/chat/api/moderation.ts
to point at your server. The server component ensures that your PubNub Secret Key
is not stored on the client side of the application. All ban/mute
functionality should happen on the server side of this demo as you will need to initialize your PubNub Instance with the Secret Key
.
Keys.js
const publish_key = 'publish_key'; // ENTER YOUR PUBLISH KEY HERE
const subscribe_key = 'subscribe_key'; // ENTER YOUR SUBSCRIBE KEY HERE
const secret_key = 'secret_key'; // ENTER YOUR SECRET KEY HERE
const admin_key = 'admin'; // ENTER ADMIN UUID HERE
module.exports = {
publishKey: publish_key,
subscribeKey: subscribe_key,
secretKey: secret_key,
userId: admin_key
}
Moderation.js
const config_file = require('./keys.js')
const { Chat } = require("@pubnub/chat");
const setRestrictions = async (req, res) => {
// Get PubNub Admin UUID
const chat = await Chat.init(config_file);
// Parse ChannelID
const channelID = req.body.channelID;
const userID = req.body.userID;
const ban = req.body.ban;
const mute = req.body.mute;
if (channelID == null || userID == null) {
return res.status(500).send({
message: 'Error: channelID or userID was called on null. Ensure content-type is application/json and the POST request contains a channelID and a userID parameter'
})
}
if(ban == null){
return res.status(500).send({
message: 'Error: Have to include the current ban status when muting a user'
})
}
// If the channel has been created grab the channel object
const channelInstance = await chat.getChannel(channelID);
const userInstance = await chat.getUser(userID);
if(channelInstance == null || userInstance == null){
return res.status(500).send({
message: `Error: No channel instance matches the ID: ${channelID} or No user Instance matches the ID: ${userID}`
})
}
await channelInstance.setRestrictions(userInstance, {
ban: ban,
mute: mute,
reason: "Restricted by admin",
});
return res.status(200);
}
const deleteMessage = async (req, res) => {
// Get PubNub Admin UUID
const chat = await Chat.init(config_file);
const messageID = req.body.messageID;
const channelID = req.body.channelID;
// If the channel has been created grab the channel object
const channelInstance = await chat.getChannel(channelID);
if(channelInstance == null){
return res.status(500).send({
message: `Error: No channel instance matches the ID: ${channelID}`
})
}
const message = await channelInstance.getMessage(messageID);
// Soft delete a message so it is able to be restored
await message.delete({
soft: true,
});
return res.status(200);
}
const restoreMessage = async (req, res) => {
// Get PubNub Admin UUID
const chat = await Chat.init(config_file);
const messageID = req.body.messageID;
const channelID = req.body.channelID;
// If the channel has been created grab the channel object
const channelInstance = await chat.getChannel(channelID);
if(channelInstance == null){
return res.status(500).send({
message: `Error: No channel instance matches the ID: ${channelID}`
})
}
const message = await channelInstance.getMessage(messageID);
await message.restore();
return res.status(200);
}