Optionally disable chat rate limiter and add optional chat slur/language filter (#3681)
* feat(chat): basic profanity filter. For #3139 * feat(chat): add setting for disabling chat spam protection. Closes #3523 * feat(chat): wire up the new chat slur filter to admin and chat. Closes #3139
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Typography } from 'antd';
|
||||
import { Col, Row, Typography } from 'antd';
|
||||
import React, { ReactElement, useContext, useEffect, useState } from 'react';
|
||||
import { TEXTFIELD_TYPE_TEXTAREA } from '../../components/admin/TextField';
|
||||
import { TextFieldWithSubmit } from '../../components/admin/TextFieldWithSubmit';
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
API_CHAT_FORBIDDEN_USERNAMES,
|
||||
API_CHAT_SUGGESTED_USERNAMES,
|
||||
FIELD_PROPS_CHAT_JOIN_MESSAGES_ENABLED,
|
||||
FIELD_PROPS_ENABLE_CHAT_SLUR_FILTER,
|
||||
CHAT_ESTABLISHED_USER_MODE,
|
||||
FIELD_PROPS_DISABLE_CHAT,
|
||||
postConfigUpdateToAPI,
|
||||
@@ -23,6 +24,7 @@ import {
|
||||
TEXTFIELD_PROPS_CHAT_FORBIDDEN_USERNAMES,
|
||||
TEXTFIELD_PROPS_CHAT_SUGGESTED_USERNAMES,
|
||||
TEXTFIELD_PROPS_SERVER_WELCOME_MESSAGE,
|
||||
FIELD_PROPS_ENABLE_SPAM_PROTECTION,
|
||||
} from '../../utils/config-constants';
|
||||
import { ServerStatusContext } from '../../utils/server-status-context';
|
||||
|
||||
@@ -43,6 +45,8 @@ export default function ConfigChat() {
|
||||
instanceDetails,
|
||||
suggestedUsernames,
|
||||
chatEstablishedUserMode,
|
||||
chatSpamProtectionEnabled,
|
||||
chatSlurFilterEnabled,
|
||||
} = serverConfig;
|
||||
const { welcomeMessage } = instanceDetails;
|
||||
|
||||
@@ -65,6 +69,14 @@ export default function ConfigChat() {
|
||||
handleFieldChange({ fieldName: 'chatEstablishedUserMode', value: enabled });
|
||||
}
|
||||
|
||||
function handleChatSpamProtectionChange(enabled: boolean) {
|
||||
handleFieldChange({ fieldName: 'chatSpamProtectionEnabled', value: enabled });
|
||||
}
|
||||
|
||||
function handleChatSlurFilterChange(enabled: boolean) {
|
||||
handleFieldChange({ fieldName: 'chatSlurFilterEnabled', value: enabled });
|
||||
}
|
||||
|
||||
function resetForbiddenUsernameState() {
|
||||
setForbiddenUsernameSaveState(null);
|
||||
}
|
||||
@@ -155,6 +167,8 @@ export default function ConfigChat() {
|
||||
suggestedUsernames,
|
||||
welcomeMessage,
|
||||
chatEstablishedUserMode,
|
||||
chatSpamProtectionEnabled,
|
||||
chatSlurFilterEnabled,
|
||||
});
|
||||
}, [serverConfig]);
|
||||
|
||||
@@ -165,60 +179,80 @@ export default function ConfigChat() {
|
||||
return (
|
||||
<div className="config-server-details-form">
|
||||
<Title>Chat Settings</Title>
|
||||
<div className="form-module config-server-details-container">
|
||||
<ToggleSwitch
|
||||
fieldName="chatDisabled"
|
||||
{...FIELD_PROPS_DISABLE_CHAT}
|
||||
checked={!formDataValues.chatDisabled}
|
||||
reversed
|
||||
onChange={handleChatDisableChange}
|
||||
/>
|
||||
<ToggleSwitch
|
||||
fieldName="chatJoinMessagesEnabled"
|
||||
{...FIELD_PROPS_CHAT_JOIN_MESSAGES_ENABLED}
|
||||
checked={formDataValues.chatJoinMessagesEnabled}
|
||||
onChange={handleChatJoinMessagesEnabledChange}
|
||||
/>
|
||||
<ToggleSwitch
|
||||
fieldName="chatEstablishedUserMode"
|
||||
{...CHAT_ESTABLISHED_USER_MODE}
|
||||
checked={formDataValues.chatEstablishedUserMode}
|
||||
onChange={handleEstablishedUserModeChange}
|
||||
/>
|
||||
<TextFieldWithSubmit
|
||||
fieldName="welcomeMessage"
|
||||
{...TEXTFIELD_PROPS_SERVER_WELCOME_MESSAGE}
|
||||
type={TEXTFIELD_TYPE_TEXTAREA}
|
||||
value={formDataValues.welcomeMessage}
|
||||
initialValue={welcomeMessage}
|
||||
onChange={handleFieldChange}
|
||||
/>
|
||||
<br />
|
||||
<br />
|
||||
<EditValueArray
|
||||
title={TEXTFIELD_PROPS_CHAT_FORBIDDEN_USERNAMES.label}
|
||||
placeholder={TEXTFIELD_PROPS_CHAT_FORBIDDEN_USERNAMES.placeholder}
|
||||
description={TEXTFIELD_PROPS_CHAT_FORBIDDEN_USERNAMES.tip}
|
||||
values={formDataValues.forbiddenUsernames}
|
||||
handleDeleteIndex={handleDeleteForbiddenUsernameIndex}
|
||||
handleCreateString={handleCreateForbiddenUsername}
|
||||
submitStatus={forbiddenUsernameSaveState}
|
||||
/>
|
||||
<br />
|
||||
<br />
|
||||
<EditValueArray
|
||||
title={TEXTFIELD_PROPS_CHAT_SUGGESTED_USERNAMES.label}
|
||||
placeholder={TEXTFIELD_PROPS_CHAT_SUGGESTED_USERNAMES.placeholder}
|
||||
description={TEXTFIELD_PROPS_CHAT_SUGGESTED_USERNAMES.tip}
|
||||
values={formDataValues.suggestedUsernames}
|
||||
handleDeleteIndex={handleDeleteSuggestedUsernameIndex}
|
||||
handleCreateString={handleCreateSuggestedUsername}
|
||||
submitStatus={suggestedUsernameSaveState}
|
||||
continuousStatusMessage={getSuggestedUsernamesLimitWarning(
|
||||
formDataValues.suggestedUsernames.length,
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<Row gutter={[45, 16]}>
|
||||
<Col md={24} lg={12}>
|
||||
<div className="form-module">
|
||||
<ToggleSwitch
|
||||
fieldName="chatDisabled"
|
||||
{...FIELD_PROPS_DISABLE_CHAT}
|
||||
checked={!formDataValues.chatDisabled}
|
||||
reversed
|
||||
onChange={handleChatDisableChange}
|
||||
/>
|
||||
<ToggleSwitch
|
||||
fieldName="chatJoinMessagesEnabled"
|
||||
{...FIELD_PROPS_CHAT_JOIN_MESSAGES_ENABLED}
|
||||
checked={formDataValues.chatJoinMessagesEnabled}
|
||||
onChange={handleChatJoinMessagesEnabledChange}
|
||||
/>
|
||||
<TextFieldWithSubmit
|
||||
fieldName="welcomeMessage"
|
||||
{...TEXTFIELD_PROPS_SERVER_WELCOME_MESSAGE}
|
||||
type={TEXTFIELD_TYPE_TEXTAREA}
|
||||
value={formDataValues.welcomeMessage}
|
||||
initialValue={welcomeMessage}
|
||||
onChange={handleFieldChange}
|
||||
/>
|
||||
<br />
|
||||
<br />
|
||||
<EditValueArray
|
||||
title={TEXTFIELD_PROPS_CHAT_FORBIDDEN_USERNAMES.label}
|
||||
placeholder={TEXTFIELD_PROPS_CHAT_FORBIDDEN_USERNAMES.placeholder}
|
||||
description={TEXTFIELD_PROPS_CHAT_FORBIDDEN_USERNAMES.tip}
|
||||
values={formDataValues.forbiddenUsernames}
|
||||
handleDeleteIndex={handleDeleteForbiddenUsernameIndex}
|
||||
handleCreateString={handleCreateForbiddenUsername}
|
||||
submitStatus={forbiddenUsernameSaveState}
|
||||
/>
|
||||
<br />
|
||||
<br />
|
||||
<EditValueArray
|
||||
title={TEXTFIELD_PROPS_CHAT_SUGGESTED_USERNAMES.label}
|
||||
placeholder={TEXTFIELD_PROPS_CHAT_SUGGESTED_USERNAMES.placeholder}
|
||||
description={TEXTFIELD_PROPS_CHAT_SUGGESTED_USERNAMES.tip}
|
||||
values={formDataValues.suggestedUsernames}
|
||||
handleDeleteIndex={handleDeleteSuggestedUsernameIndex}
|
||||
handleCreateString={handleCreateSuggestedUsername}
|
||||
submitStatus={suggestedUsernameSaveState}
|
||||
continuousStatusMessage={getSuggestedUsernamesLimitWarning(
|
||||
formDataValues.suggestedUsernames.length,
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</Col>
|
||||
<Col md={24} lg={12}>
|
||||
<div className="form-module">
|
||||
<ToggleSwitch
|
||||
fieldName="chatSpamProtectionEnabled"
|
||||
{...FIELD_PROPS_ENABLE_SPAM_PROTECTION}
|
||||
checked={formDataValues.chatSpamProtectionEnabled}
|
||||
onChange={handleChatSpamProtectionChange}
|
||||
/>
|
||||
<ToggleSwitch
|
||||
fieldName="chatEstablishedUserMode"
|
||||
{...CHAT_ESTABLISHED_USER_MODE}
|
||||
checked={formDataValues.chatEstablishedUserMode}
|
||||
onChange={handleEstablishedUserModeChange}
|
||||
/>
|
||||
<ToggleSwitch
|
||||
fieldName="chatSlurFilterEnabled"
|
||||
{...FIELD_PROPS_ENABLE_CHAT_SLUR_FILTER}
|
||||
checked={formDataValues.chatSlurFilterEnabled}
|
||||
onChange={handleChatSlurFilterChange}
|
||||
/>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -152,6 +152,8 @@ export interface ConfigDetails {
|
||||
forbiddenUsernames: string[];
|
||||
suggestedUsernames: string[];
|
||||
chatDisabled: boolean;
|
||||
chatSpamProtectionEnabled: boolean;
|
||||
chatSlurFilterEnabled: boolean;
|
||||
federation: Federation;
|
||||
notifications: NotificationsConfig;
|
||||
chatJoinMessagesEnabled: boolean;
|
||||
|
||||
@@ -38,6 +38,8 @@ const API_HIDE_VIEWER_COUNT = '/hideviewercount';
|
||||
const API_CHAT_DISABLE = '/chat/disable';
|
||||
const API_CHAT_JOIN_MESSAGES_ENABLED = '/chat/joinmessagesenabled';
|
||||
const API_CHAT_ESTABLISHED_MODE = '/chat/establishedusermode';
|
||||
const API_CHAT_SPAM_PROTECTION_ENABLED = '/chat/spamprotectionenabled';
|
||||
const API_CHAT_SLUR_FILTER_ENABLED = '/chat/slurfilterenabled';
|
||||
const API_DISABLE_SEARCH_INDEXING = '/disablesearchindexing';
|
||||
const API_SOCKET_HOST_OVERRIDE = '/sockethostoverride';
|
||||
const API_VIDEO_SERVING_ENDPOINT = '/videoservingendpoint';
|
||||
@@ -258,6 +260,14 @@ export const FIELD_PROPS_DISABLE_CHAT = {
|
||||
useSubmit: true,
|
||||
};
|
||||
|
||||
export const FIELD_PROPS_ENABLE_SPAM_PROTECTION = {
|
||||
apiPath: API_CHAT_SPAM_PROTECTION_ENABLED,
|
||||
configPath: '',
|
||||
label: 'Spam Protection',
|
||||
tip: 'Limits how quickly messages can be sent to prevent spamming.',
|
||||
useSubmit: true,
|
||||
};
|
||||
|
||||
export const FIELD_PROPS_CHAT_JOIN_MESSAGES_ENABLED = {
|
||||
apiPath: API_CHAT_JOIN_MESSAGES_ENABLED,
|
||||
configPath: '',
|
||||
@@ -266,6 +276,14 @@ export const FIELD_PROPS_CHAT_JOIN_MESSAGES_ENABLED = {
|
||||
useSubmit: true,
|
||||
};
|
||||
|
||||
export const FIELD_PROPS_ENABLE_CHAT_SLUR_FILTER = {
|
||||
apiPath: API_CHAT_SLUR_FILTER_ENABLED,
|
||||
configPath: '',
|
||||
label: 'Chat language filter',
|
||||
tip: 'Filters out messages that contain offensive language.',
|
||||
useSubmit: true,
|
||||
};
|
||||
|
||||
export const CHAT_ESTABLISHED_USER_MODE = {
|
||||
apiPath: API_CHAT_ESTABLISHED_MODE,
|
||||
configPath: '',
|
||||
|
||||
@@ -69,6 +69,8 @@ const initialServerConfigState: ConfigDetails = {
|
||||
forbiddenUsernames: [],
|
||||
suggestedUsernames: [],
|
||||
chatDisabled: false,
|
||||
chatSpamProtectionEnabled: true,
|
||||
chatSlurFilterEnabled: false,
|
||||
chatJoinMessagesEnabled: true,
|
||||
chatEstablishedUserMode: false,
|
||||
hideViewerCount: false,
|
||||
|
||||
Reference in New Issue
Block a user