2021-07-20 04:22:29 +02:00
package chat
import (
"encoding/json"
"fmt"
"strings"
2021-08-13 07:40:10 +02:00
"time"
2021-07-20 04:22:29 +02:00
2022-08-10 04:56:45 +02:00
"github.com/owncast/owncast/config"
2021-07-20 04:22:29 +02:00
"github.com/owncast/owncast/core/chat/events"
"github.com/owncast/owncast/core/data"
"github.com/owncast/owncast/core/user"
"github.com/owncast/owncast/core/webhooks"
log "github.com/sirupsen/logrus"
)
2021-09-12 09:18:15 +02:00
func ( s * Server ) userNameChanged ( eventData chatClientEvent ) {
2021-07-20 04:22:29 +02:00
var receivedEvent events . NameChangeEvent
if err := json . Unmarshal ( eventData . data , & receivedEvent ) ; err != nil {
log . Errorln ( "error unmarshalling to NameChangeEvent" , err )
return
}
proposedUsername := receivedEvent . NewName
2022-04-21 23:55:26 +02:00
// Check if name is on the blocklist
2021-07-20 04:22:29 +02:00
blocklist := data . GetForbiddenUsernameList ( )
2022-08-15 03:09:16 +02:00
// Names have a max length
if len ( proposedUsername ) > config . MaxChatDisplayNameLength {
proposedUsername = proposedUsername [ : config . MaxChatDisplayNameLength ]
}
2021-07-20 04:22:29 +02:00
for _ , blockedName := range blocklist {
normalizedName := strings . TrimSpace ( blockedName )
normalizedName = strings . ToLower ( normalizedName )
if strings . Contains ( normalizedName , proposedUsername ) {
// Denied.
2022-09-21 19:03:16 +02:00
log . Debugln ( logSanitize ( eventData . client . User . DisplayName ) , "blocked from changing name to" , logSanitize ( proposedUsername ) , "due to blocked name" , normalizedName )
2021-07-20 04:22:29 +02:00
message := fmt . Sprintf ( "You cannot change your name to **%s**." , proposedUsername )
s . sendActionToClient ( eventData . client , message )
// Resend the client's user so their username is in sync.
eventData . client . sendConnectedClientInfo ( )
return
}
}
2022-04-21 23:55:26 +02:00
// Check if the name is not already assigned to a registered user.
if available , err := user . IsDisplayNameAvailable ( proposedUsername ) ; err != nil {
log . Errorln ( "error checking if name is available" , err )
return
} else if ! available {
2022-05-16 22:05:00 +02:00
message := fmt . Sprintf ( "The name **%s** has been already registered. If this is your name, please authenticate." , proposedUsername )
2022-04-21 23:55:26 +02:00
s . sendActionToClient ( eventData . client , message )
// Resend the client's user so their username is in sync.
eventData . client . sendConnectedClientInfo ( )
return
}
2021-07-20 04:22:29 +02:00
savedUser := user . GetUserByToken ( eventData . client . accessToken )
oldName := savedUser . DisplayName
// Save the new name
2022-08-15 03:09:16 +02:00
if err := user . ChangeUsername ( eventData . client . User . ID , proposedUsername ) ; err != nil {
2022-04-21 23:55:26 +02:00
log . Errorln ( "error changing username" , err )
}
2021-07-20 04:22:29 +02:00
// Update the connected clients associated user with the new name
2021-08-13 09:05:13 +02:00
now := time . Now ( )
2021-07-20 04:22:29 +02:00
eventData . client . User = savedUser
2021-08-13 09:05:13 +02:00
eventData . client . User . NameChangedAt = & now
2021-07-20 04:22:29 +02:00
// Send chat event letting everyone about about the name change
2022-08-15 03:09:16 +02:00
savedUser . DisplayName = proposedUsername
2021-07-20 04:22:29 +02:00
broadcastEvent := events . NameChangeBroadcast {
Oldname : oldName ,
}
broadcastEvent . User = savedUser
broadcastEvent . SetDefaults ( )
payload := broadcastEvent . GetBroadcastPayload ( )
if err := s . Broadcast ( payload ) ; err != nil {
log . Errorln ( "error broadcasting NameChangeEvent" , err )
return
}
// Send chat user name changed webhook
receivedEvent . User = savedUser
2021-09-13 10:26:28 +02:00
receivedEvent . ClientID = eventData . client . id
2021-07-20 04:22:29 +02:00
webhooks . SendChatEventUsernameChanged ( receivedEvent )
2022-05-26 22:52:04 +02:00
// Resend the client's user so their username is in sync.
eventData . client . sendConnectedClientInfo ( )
2021-07-20 04:22:29 +02:00
}
2022-08-10 04:56:45 +02:00
func ( s * Server ) userColorChanged ( eventData chatClientEvent ) {
var receivedEvent events . ColorChangeEvent
if err := json . Unmarshal ( eventData . data , & receivedEvent ) ; err != nil {
log . Errorln ( "error unmarshalling to ColorChangeEvent" , err )
return
}
// Verify this color is valid
if receivedEvent . NewColor > config . MaxUserColor {
log . Errorln ( "invalid color requested when changing user display color" )
return
}
// Save the new color
if err := user . ChangeUserColor ( eventData . client . User . ID , receivedEvent . NewColor ) ; err != nil {
log . Errorln ( "error changing user display color" , err )
}
}
2021-09-12 09:18:15 +02:00
func ( s * Server ) userMessageSent ( eventData chatClientEvent ) {
2021-07-20 04:22:29 +02:00
var event events . UserMessageEvent
if err := json . Unmarshal ( eventData . data , & event ) ; err != nil {
log . Errorln ( "error unmarshalling to UserMessageEvent" , err )
return
}
event . SetDefaults ( )
2021-09-13 10:26:28 +02:00
event . ClientID = eventData . client . id
2021-07-20 04:22:29 +02:00
// Ignore empty messages
if event . Empty ( ) {
return
}
2021-08-13 07:40:10 +02:00
// Ignore if the stream has been offline
if ! getStatus ( ) . Online && getStatus ( ) . LastDisconnectTime != nil {
disconnectedTime := getStatus ( ) . LastDisconnectTime . Time
if time . Since ( disconnectedTime ) > 5 * time . Minute {
return
}
2021-07-27 19:42:05 +02:00
}
2021-07-20 04:22:29 +02:00
event . User = user . GetUserByToken ( eventData . client . accessToken )
// Guard against nil users
if event . User == nil {
return
}
payload := event . GetBroadcastPayload ( )
if err := s . Broadcast ( payload ) ; err != nil {
log . Errorln ( "error broadcasting UserMessageEvent payload" , err )
return
}
// Send chat message sent webhook
webhooks . SendChatEvent ( & event )
2022-03-07 02:26:52 +01:00
chatMessagesSentCounter . Inc ( )
2021-07-20 04:22:29 +02:00
SaveUserMessage ( event )
2021-10-25 09:31:45 +02:00
eventData . client . MessageCount ++
2021-09-21 23:06:23 +02:00
_lastSeenCache [ event . User . ID ] = time . Now ( )
2021-07-20 04:22:29 +02:00
}
2022-09-21 19:03:16 +02:00
func logSanitize ( userValue string ) string {
// strip carriage return and newline from user-submitted values to prevent log injection
2022-09-21 19:24:16 +02:00
sanitizedValue := strings . ReplaceAll ( userValue , "\n" , "" )
sanitizedValue = strings . ReplaceAll ( sanitizedValue , "\r" , "" )
2022-09-21 19:03:16 +02:00
return fmt . Sprintf ( "userSuppliedValue(%s)" , sanitizedValue )
}