Stream Feeds Webhook
In order to build additional functionality into your feeds app such as automated profanity moderation, Stream webhooks can be implimented to intercept and modify the activities of a feed group.
This article will explain how to:
- Build a simple server to moderate activity text
- Configure the webhook in your dashboard
The data your webhook will receive will look similar to this:
[
{
deleted: [],
deleted_foreign_ids: [],
new: [
{
actor: '1',
verb: 'tweet',
object: '1',
target: null,
time: '2014-12-15T17:20:37.258',
foreign_id: null,
id: 'af781804-847e-11e4-8080-80012fb97b9e',
text: 'Hello world',
},
],
published_at: '2014-12-15T17:20:37.263518+00:00',
feed: 'user:2',
app_id: '123',
},
{
deleted: ['38f81366-847f-11e4-9c94-0cc47a024be0'],
deleted_foreign_ids: [['your_foreign_id', '2014-12-15T17:20:37.263518+00:00']],
new: [],
published_at: '2014-12-15T17:20:37.263518+00:00',
feed: 'timeline:1',
app_id: '123',
}
];
Use a simple npm package called "bad-words" to filter out profanities.
This function will replace any bad words with "*"s (none of this code is from a Stream Library):
const Filter = require("bad-words");
const customFilter = new Filter({ placeholder: "x" });
const textMiddleware = (text) => {
const filtered = customFilter.clean(text);
if (filtered === text) return false;
return filtered;
};
To use this function with every POST request add this code to the webhook server:
app.post("/", async (req, res) => {
try {
const activity = req.body[0].new[0];
const { text, id } = activity;
const badWords = textMiddleware(text);
if (badWords) {
await serverClient.activityPartialUpdate({
id,
set: { text: badWords },
});
}
res.status(200).send("OK");
} catch (err) {
res.status(500).send(err);
}
});
If 'textMiddleware(text)' returns a bad word replaced with "*"s, then 'activityPartialUpdate()' is called to replace the text that was just added to the feed.
Before configuring the webook in your dashboard, make sure the webhook returns your most recent APP Key on a GET request and a status of 200 for validation. Make sure that the response body is in plain text (no markup, whitespaces, ...):
app.get("/", (req, res) => {
try {
res.status(200).send(key);
} catch (err) {
res.status(500).send(err);
}
});
Configure this webhook in your dashboard by following these steps, once your server is deployed (or Ngrok is set up if testing locally - explained in this blog article about Chat webhooks - FYI, Stream Chat webhooks are much different than Stream Feeds webhooks):
- Stream Dashboard
- Click an App
- Click a Feed Group you would like to add the webhook to (ex. user)
- Toggle "Realtime Notifications" on
- Add your Webhook URL
- Click "Test Webhook"
- Click "Save"
- Click "Test Webhook"
- Add your Webhook URL
- Toggle "Realtime Notifications" on
- Click a Feed Group you would like to add the webhook to (ex. user)
- Click an App
Here is the entire webhook server file built with Express.js:
const express = require("express");
const cors = require("cors");
const stream = require("getstream");
const Filter = require("bad-words");
require("dotenv").config({ path: "server/.env" });
const key = process.env.REACT_APP_KEY;
const secret = process.env.REACT_APP_SECRET;
const serverClient = stream.connect(key, secret);
const app = express();
const PORT = process.env.PORT || 3001;
app.use(cors());
app.use(express.json());
app.get("/", (req, res) => {
try {
res.status(200).send(key);
} catch (err) {
res.status(500).send(err);
}
});
const customFilter = new Filter({ placeholder: "x" });
const textMiddleware = (text) => {
const filtered = customFilter.clean(text);
if (filtered === text) return false;
return filtered;
};
app.post("/", async (req, res) => {
try {
const activity = req.body[0].new[0];
const { text, id } = activity;
const badWords = textMiddleware(text);
if (badWords) {
await serverClient.activityPartialUpdate({
id,
set: { text:badWords },
});
}
res.status(200).send("OK");
} catch (err) {
res.status(500).send(err);
}
});
app.listen(PORT, () => console.log(`Webhook on port ${PORT}`));
Comments
0 comments
Please sign in to leave a comment.