owncast/core/chat/events.go
Ruffy 9c484efd36
Feature/oc 1316 add support for system message to single user (#1351)
* add public func to lookup a ChatClient by its clientId

* add facility to send a system message directly to a user

* add clientId field to UserEvent

* implement simple http endpoint to send a message to a user

* let mux handle new directSystemMessageToUser endpoint

* add ClientId to UserEvents across the codebase

* render body of system-message to client

* add clientId to Chat-Message

* add tests showing how url-parsing should work

* add simple rest endpoint helpers for parameter-parsing and easy routing

* use newly added rest-endpoint helper to rout to Client-Messaging controller

* use safe "ReadRestUrlParameter" to parse ClientId

* remove empty HandleFunc in router

* set Header directly to prevent built-in (platform-dependent) canonicalization to kick in

* fix typo in "Parameter" message

* remove debug-logging of HTTP headers in REST-helpers

* convert to uint32 to prevent overruns when converting to wraptype uint later on

* resolve linter-ouchies

* resolve linter potential nil-deref warning

* document the SendSystemMessageToClient endpoint in swaggerdoc

* remove clientId assignment causing potential nil dereference in userDisabledEvent-case

as the clientId isn't relevant here anyway

* make findClientById private, so its not accessible outside of core/chat

* remove redundant string type hint

* Update PR based on linter requirements

Co-authored-by: Raffael Rehberger <raffael@rtrace.io>
Co-authored-by: Gabe Kangas <gabek@real-ity.com>
2021-09-13 01:26:28 -07:00

115 lines
3.2 KiB
Go

package chat
import (
"encoding/json"
"fmt"
"strings"
"time"
"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"
)
func (s *Server) userNameChanged(eventData chatClientEvent) {
var receivedEvent events.NameChangeEvent
if err := json.Unmarshal(eventData.data, &receivedEvent); err != nil {
log.Errorln("error unmarshalling to NameChangeEvent", err)
return
}
proposedUsername := receivedEvent.NewName
blocklist := data.GetForbiddenUsernameList()
for _, blockedName := range blocklist {
normalizedName := strings.TrimSpace(blockedName)
normalizedName = strings.ToLower(normalizedName)
if strings.Contains(normalizedName, proposedUsername) {
// Denied.
log.Debugln(eventData.client.User.DisplayName, "blocked from changing name to", proposedUsername, "due to blocked name", normalizedName)
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
}
}
savedUser := user.GetUserByToken(eventData.client.accessToken)
oldName := savedUser.DisplayName
// Save the new name
user.ChangeUsername(eventData.client.User.ID, receivedEvent.NewName)
// Update the connected clients associated user with the new name
now := time.Now()
eventData.client.User = savedUser
eventData.client.User.NameChangedAt = &now
// Send chat event letting everyone about about the name change
savedUser.DisplayName = receivedEvent.NewName
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
receivedEvent.ClientID = eventData.client.id
webhooks.SendChatEventUsernameChanged(receivedEvent)
}
func (s *Server) userMessageSent(eventData chatClientEvent) {
var event events.UserMessageEvent
if err := json.Unmarshal(eventData.data, &event); err != nil {
log.Errorln("error unmarshalling to UserMessageEvent", err)
return
}
event.SetDefaults()
event.ClientID = eventData.client.id
// Ignore empty messages
if event.Empty() {
return
}
// 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
}
}
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)
SaveUserMessage(event)
eventData.client.MessageCount = eventData.client.MessageCount + 1
}