Update chat message visibility for moderation (#524)

* update message viz in db

* create admin endpoint to update message visibility

* convert UpdateMessageVisibility api to take in an array of IDs to change visibility on instead

* Support requesting filtered or unfiltered chat messages

* Handle UPDATE chat events on front and backend for toggling messages

* Return entire message with UPDATE events

* Remove the UPDATE message type

* Revert "Remove the UPDATE message type"

This reverts commit 3a83df3d492f7ecf2bab65e845aa2b0365d3a7f6.

* update -> visibility update

* completely remove messages when they turn hidden on VISIBILITY-UPDATEs, and insert them if they turn visible

* Explicitly set visibility

* Fix multi-id sql updates

* increate scroll buffer a bit so chat scrolls when new large messages come in

* Add automated test around chat moderation

* Add new chat admin APIs to api spec

* Commit updated API documentation

Co-authored-by: Gabe Kangas <gabek@real-ity.com>
Co-authored-by: Owncast <owncast@owncast.online>
This commit is contained in:
gingervitis
2020-12-29 13:35:33 -08:00
committed by GitHub
parent 0452c4c5fc
commit 8a74af202d
18 changed files with 375 additions and 64 deletions

View File

@@ -39,7 +39,7 @@ export default class ChatMessageView extends Component {
render() {
const { message } = this.props;
const { author, timestamp } = message;
const { author, timestamp, visible } = message;
const { formattedMessage } = this.state;
if (!formattedMessage) {

View File

@@ -26,6 +26,7 @@ export default class Chat extends Component {
this.websocket = null;
this.receivedFirstMessages = false;
this.receivedMessageUpdate = false;
this.windowBlurred = false;
this.numMessagesSinceBlur = 0;
@@ -88,7 +89,7 @@ export default class Chat extends Component {
}
// scroll to bottom of messages list when new ones come in
if (messages.length > prevMessages.length) {
if (messages.length !== prevMessages.length) {
this.setState({
newMessagesReceived: true,
});
@@ -144,7 +145,7 @@ export default class Chat extends Component {
}
receivedWebsocketMessage(message) {
this.addMessage(message);
this.handleMessage(message);
}
handleNetworkingError(error) {
@@ -152,16 +153,48 @@ export default class Chat extends Component {
console.log(error);
}
addMessage(message) {
// handle any incoming message
handleMessage(message) {
const {
id: messageId,
type: messageType,
timestamp: messageTimestamp,
visible: messageVisible,
} = message;
const { messages: curMessages } = this.state;
const { messagesOnly } = this.props;
// if incoming message has same id as existing message, don't add it
const existing = curMessages.filter(function (item) {
return item.id === message.id;
})
const existingIndex = curMessages.findIndex(item => item.id === messageId);
if (existing.length === 0 || !existing) {
// If the message already exists and this is an update event
// then update it.
if (messageType === 'VISIBILITY-UPDATE') {
const updatedMessageList = [...curMessages];
const convertedMessage = {
...message,
type: 'CHAT',
};
// if message exists and should now hide, take it out.
if (existingIndex >= 0 && !messageVisible) {
this.setState({
messages: curMessages.filter(item => item.id !== messageId),
});
} else if (existingIndex === -1 && messageVisible) {
// insert message at timestamp
const insertAtIndex = curMessages.findIndex((item, index) => {
const time = item.timestamp || messageTimestamp;
const nextMessage = index < curMessages.length - 1 && curMessages[index + 1];
const nextTime = nextMessage.timestamp || messageTimestamp;
const messageTimestampDate = new Date(messageTimestamp);
return messageTimestampDate > (new Date(time)) && messageTimestampDate <= (new Date(nextTime));
});
updatedMessageList.splice(insertAtIndex + 1, 0, convertedMessage);
this.setState({
messages: updatedMessageList,
});
}
} else if (existingIndex === -1) {
// else if message doesn't exist, add it and extra username
const newState = {
messages: [...curMessages, message],
};
@@ -173,7 +206,7 @@ export default class Chat extends Component {
}
// if window is blurred and we get a new message, add 1 to title
if (!messagesOnly && message.type === 'CHAT' && this.windowBlurred) {
if (!messagesOnly && messageType === 'CHAT' && this.windowBlurred) {
this.numMessagesSinceBlur += 1;
}
}
@@ -279,7 +312,7 @@ export default class Chat extends Component {
const { username, messagesOnly, chatInputEnabled } = props;
const { messages, chatUserNames, webSocketConnected } = state;
const messageList = messages.map(
const messageList = messages.filter(message => message.visible !== false).map(
(message) =>
html`<${Message}
message=${message}

View File

@@ -48,7 +48,7 @@ export const CHAT_KEY_MODIFIERS = [
'Meta',
'Alt',
];
export const MESSAGE_JUMPTOBOTTOM_BUFFER = 260;
export const MESSAGE_JUMPTOBOTTOM_BUFFER = 300;
// app styling
export const WIDTH_SINGLE_COL = 730;