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:
Gabe Kangas
2024-04-09 22:25:41 -07:00
committed by GitHub
parent 04eaf8c20e
commit a450e62397
14 changed files with 352 additions and 142 deletions

View File

@ -13,19 +13,21 @@ import (
"github.com/gorilla/websocket"
"github.com/owncast/owncast/config"
"github.com/owncast/owncast/core/chat/events"
"github.com/owncast/owncast/core/data"
"github.com/owncast/owncast/core/user"
"github.com/owncast/owncast/geoip"
)
// Client represents a single chat client.
type Client struct {
ConnectedAt time.Time `json:"connectedAt"`
timeoutTimer *time.Timer
rateLimiter *rate.Limiter
conn *websocket.Conn
User *user.User `json:"user"`
server *Server
Geo *geoip.GeoDetails `json:"geo"`
ConnectedAt time.Time `json:"connectedAt"`
timeoutTimer *time.Timer
rateLimiter *rate.Limiter
messageFilter *ChatMessageFilter
conn *websocket.Conn
User *user.User `json:"user"`
server *Server
Geo *geoip.GeoDetails `json:"geo"`
// Buffered channel of outbound messages.
send chan []byte
accessToken string
@ -90,6 +92,7 @@ func (c *Client) readPump() {
// Allow 3 messages every two seconds.
limit := rate.Every(2 * time.Second / 3)
c.rateLimiter = rate.NewLimiter(limit, 1)
c.messageFilter = NewMessageFilter()
defer func() {
c.close()
@ -129,6 +132,12 @@ func (c *Client) readPump() {
continue
}
// Check if this message passes the optional language filter
if data.GetChatSlurFilterEnabled() && !c.messageFilter.Allow(string(message)) {
c.sendAction("Sorry, that message contained language that is not allowed in this chat.")
continue
}
message = bytes.TrimSpace(bytes.ReplaceAll(message, newline, space))
c.handleEvent(message)
}
@ -200,7 +209,13 @@ func (c *Client) close() {
}
func (c *Client) passesRateLimit() bool {
return c.User.IsModerator() || (c.rateLimiter.Allow() && !c.inTimeout)
// If spam rate limiting is disabled, or the user is a moderator, always
// allow the message.
if !data.GetChatSpamProtectionEnabled() || c.User.IsModerator() {
return true
}
return (c.rateLimiter.Allow() && !c.inTimeout)
}
func (c *Client) startChatRejectionTimeout() {