mirror of
https://github.com/owncast/owncast.git
synced 2024-10-10 19:16:02 +00:00
Rework how hiding messages works. (#1509)
* Rework how hiding messages work. Fixes #1350 * Remove unused function * Revert to old event name to support previously saved webhooks
This commit is contained in:
parent
2278fec70a
commit
b43c5e674e
@ -10,8 +10,8 @@ const (
|
|||||||
UserJoined EventType = "USER_JOINED"
|
UserJoined EventType = "USER_JOINED"
|
||||||
// UserNameChanged is the event sent when a chat username change takes place.
|
// UserNameChanged is the event sent when a chat username change takes place.
|
||||||
UserNameChanged EventType = "NAME_CHANGE"
|
UserNameChanged EventType = "NAME_CHANGE"
|
||||||
// VisibiltyToggled is the event sent when a chat message's visibility changes.
|
// VisibiltyUpdate is the event sent when a chat message's visibility changes.
|
||||||
VisibiltyToggled EventType = "VISIBILITY-UPDATE"
|
VisibiltyUpdate EventType = "VISIBILITY-UPDATE"
|
||||||
// PING is a ping message.
|
// PING is a ping message.
|
||||||
PING EventType = "PING"
|
PING EventType = "PING"
|
||||||
// PONG is a pong message.
|
// PONG is a pong message.
|
||||||
|
21
core/chat/events/setMessageVisibilityEvent.go
Normal file
21
core/chat/events/setMessageVisibilityEvent.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package events
|
||||||
|
|
||||||
|
// SetMessageVisibilityEvent is the event fired when one or more message
|
||||||
|
// visibilities are changed.
|
||||||
|
type SetMessageVisibilityEvent struct {
|
||||||
|
Event
|
||||||
|
UserMessageEvent
|
||||||
|
MessageIDs []string
|
||||||
|
Visible bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBroadcastPayload will return the object to send to all chat users.
|
||||||
|
func (e *SetMessageVisibilityEvent) GetBroadcastPayload() EventPayload {
|
||||||
|
return EventPayload{
|
||||||
|
"type": VisibiltyUpdate,
|
||||||
|
"id": e.ID,
|
||||||
|
"timestamp": e.Timestamp,
|
||||||
|
"ids": e.MessageIDs,
|
||||||
|
"visible": e.Visible,
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
package chat
|
package chat
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
"github.com/owncast/owncast/core/chat/events"
|
"github.com/owncast/owncast/core/chat/events"
|
||||||
"github.com/owncast/owncast/core/webhooks"
|
"github.com/owncast/owncast/core/webhooks"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
@ -14,23 +16,26 @@ func SetMessagesVisibility(messageIDs []string, visibility bool) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send an update event to all clients for each message.
|
// Send an event letting the chat clients know to hide or show
|
||||||
// Note: Our client expects a single message at a time, so we can't just
|
// the messages.
|
||||||
// send an array of messages in a single update.
|
event := events.SetMessageVisibilityEvent{
|
||||||
for _, id := range messageIDs {
|
MessageIDs: messageIDs,
|
||||||
message, err := getMessageByID(id)
|
Visible: visibility,
|
||||||
if err != nil {
|
|
||||||
log.Errorln(err)
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
payload := message.GetBroadcastPayload()
|
event.Event.SetDefaults()
|
||||||
payload["type"] = events.VisibiltyToggled
|
|
||||||
|
payload := event.GetBroadcastPayload()
|
||||||
if err := _server.Broadcast(payload); err != nil {
|
if err := _server.Broadcast(payload); err != nil {
|
||||||
log.Debugln(err)
|
return errors.New("error broadcasting message visibility payload " + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
go webhooks.SendChatEvent(message)
|
// Send webhook
|
||||||
|
wh := webhooks.WebhookEvent{
|
||||||
|
EventData: event,
|
||||||
|
Type: event.GetMessageType(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
webhooks.SendEventToWebhooks(wh)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -161,7 +161,7 @@ func GetChatModerationHistory() []events.UserMessageEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get all messages regardless of visibility
|
// Get all messages regardless of visibility
|
||||||
var query = "SELECT messages.id, user_id, body, eventType, hidden_at, timestamp, display_name, display_color, created_at, disabled_at, previous_names, namechanged_at FROM messages INNER JOIN users ON messages.user_id = users.id ORDER BY timestamp DESC"
|
query := "SELECT messages.id, user_id, body, eventType, hidden_at, timestamp, display_name, display_color, created_at, disabled_at, previous_names, namechanged_at FROM messages INNER JOIN users ON messages.user_id = users.id ORDER BY timestamp DESC"
|
||||||
result := getChat(query)
|
result := getChat(query)
|
||||||
|
|
||||||
_historyCache = &result
|
_historyCache = &result
|
||||||
@ -172,7 +172,7 @@ func GetChatModerationHistory() []events.UserMessageEvent {
|
|||||||
// GetChatHistory will return all the chat messages suitable for returning as user-facing chat history.
|
// GetChatHistory will return all the chat messages suitable for returning as user-facing chat history.
|
||||||
func GetChatHistory() []events.UserMessageEvent {
|
func GetChatHistory() []events.UserMessageEvent {
|
||||||
// Get all visible messages
|
// Get all visible messages
|
||||||
var query = fmt.Sprintf("SELECT messages.id, user_id, body, eventType, hidden_at, timestamp, display_name, display_color, created_at, disabled_at, previous_names, namechanged_at FROM messages, users WHERE messages.user_id = users.id AND hidden_at IS NULL AND disabled_at IS NULL ORDER BY timestamp DESC LIMIT %d", maxBacklogNumber)
|
query := fmt.Sprintf("SELECT messages.id, user_id, body, eventType, hidden_at, timestamp, display_name, display_color, created_at, disabled_at, previous_names, namechanged_at FROM messages, users WHERE messages.user_id = users.id AND hidden_at IS NULL AND disabled_at IS NULL ORDER BY timestamp DESC LIMIT %d", maxBacklogNumber)
|
||||||
m := getChat(query)
|
m := getChat(query)
|
||||||
|
|
||||||
// Invert order of messages
|
// Invert order of messages
|
||||||
@ -221,7 +221,6 @@ func saveMessageVisibility(messageIDs []string, visible bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
stmt, err := tx.Prepare("UPDATE messages SET hidden_at=? WHERE id IN (?" + strings.Repeat(",?", len(messageIDs)-1) + ")")
|
stmt, err := tx.Prepare("UPDATE messages SET hidden_at=? WHERE id IN (?" + strings.Repeat(",?", len(messageIDs)-1) + ")")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -252,41 +251,6 @@ func saveMessageVisibility(messageIDs []string, visible bool) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getMessageByID(messageID string) (*events.UserMessageEvent, error) {
|
|
||||||
var query = "SELECT * FROM messages WHERE id = ?"
|
|
||||||
row := _datastore.DB.QueryRow(query, messageID)
|
|
||||||
|
|
||||||
var id string
|
|
||||||
var userID string
|
|
||||||
var body string
|
|
||||||
var eventType models.EventType
|
|
||||||
var hiddenAt *time.Time
|
|
||||||
var timestamp time.Time
|
|
||||||
|
|
||||||
err := row.Scan(&id, &userID, &body, &eventType, &hiddenAt, ×tamp)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorln(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
user := user.GetUserByID(userID)
|
|
||||||
|
|
||||||
return &events.UserMessageEvent{
|
|
||||||
events.Event{
|
|
||||||
Type: eventType,
|
|
||||||
ID: id,
|
|
||||||
Timestamp: timestamp,
|
|
||||||
},
|
|
||||||
events.UserEvent{
|
|
||||||
User: user,
|
|
||||||
HiddenAt: hiddenAt,
|
|
||||||
},
|
|
||||||
events.MessageEvent{
|
|
||||||
Body: body,
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only keep recent messages so we don't keep more chat data than needed
|
// Only keep recent messages so we don't keep more chat data than needed
|
||||||
// for privacy and efficiency reasons.
|
// for privacy and efficiency reasons.
|
||||||
func runPruner() {
|
func runPruner() {
|
||||||
|
@ -29,6 +29,7 @@ export default class Chat extends Component {
|
|||||||
this.receivedFirstMessages = false;
|
this.receivedFirstMessages = false;
|
||||||
this.receivedMessageUpdate = false;
|
this.receivedMessageUpdate = false;
|
||||||
this.hasFetchedHistory = false;
|
this.hasFetchedHistory = false;
|
||||||
|
this.forceRender = false;
|
||||||
|
|
||||||
this.windowBlurred = false;
|
this.windowBlurred = false;
|
||||||
this.numMessagesSinceBlur = 0;
|
this.numMessagesSinceBlur = 0;
|
||||||
@ -69,6 +70,11 @@ export default class Chat extends Component {
|
|||||||
|
|
||||||
const { webSocketConnected, messages, chatUserNames, newMessagesReceived } =
|
const { webSocketConnected, messages, chatUserNames, newMessagesReceived } =
|
||||||
this.state;
|
this.state;
|
||||||
|
|
||||||
|
if (this.forceRender) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
webSocketConnected: nextSocket,
|
webSocketConnected: nextSocket,
|
||||||
messages: nextMessages,
|
messages: nextMessages,
|
||||||
@ -185,20 +191,30 @@ export default class Chat extends Component {
|
|||||||
(item) => item.id === messageId
|
(item) => item.id === messageId
|
||||||
);
|
);
|
||||||
|
|
||||||
// If the message already exists and this is an update event
|
|
||||||
// then update it.
|
|
||||||
if (messageType === 'VISIBILITY-UPDATE') {
|
|
||||||
const updatedMessageList = [...curMessages];
|
const updatedMessageList = [...curMessages];
|
||||||
|
|
||||||
|
// Change the visibility of messages by ID.
|
||||||
|
if (messageType === 'VISIBILITY-UPDATE') {
|
||||||
|
const idsToUpdate = message.ids;
|
||||||
|
const visible = message.visible;
|
||||||
|
|
||||||
|
updatedMessageList.forEach((item) => {
|
||||||
|
if (idsToUpdate.includes(item.id)) {
|
||||||
|
item.visible = visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.forceRender = true;
|
||||||
|
this.setState({
|
||||||
|
messages: updatedMessageList,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
} else if (existingIndex === -1 && messageVisible) {
|
||||||
const convertedMessage = {
|
const convertedMessage = {
|
||||||
...message,
|
...message,
|
||||||
type: 'CHAT',
|
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
|
// insert message at timestamp
|
||||||
const insertAtIndex = curMessages.findIndex((item, index) => {
|
const insertAtIndex = curMessages.findIndex((item, index) => {
|
||||||
const time = item.timestamp || messageTimestamp;
|
const time = item.timestamp || messageTimestamp;
|
||||||
@ -220,7 +236,6 @@ export default class Chat extends Component {
|
|||||||
this.setState({
|
this.setState({
|
||||||
messages: updatedMessageList,
|
messages: updatedMessageList,
|
||||||
});
|
});
|
||||||
}
|
|
||||||
} else if (existingIndex === -1) {
|
} else if (existingIndex === -1) {
|
||||||
// else if message doesn't exist, add it and extra username
|
// else if message doesn't exist, add it and extra username
|
||||||
const newState = {
|
const newState = {
|
||||||
@ -354,6 +369,8 @@ export default class Chat extends Component {
|
|||||||
const { username, readonly, chatInputEnabled, inputMaxBytes } = props;
|
const { username, readonly, chatInputEnabled, inputMaxBytes } = props;
|
||||||
const { messages, chatUserNames, webSocketConnected } = state;
|
const { messages, chatUserNames, webSocketConnected } = state;
|
||||||
|
|
||||||
|
this.forceRender = false;
|
||||||
|
|
||||||
const messageList = messages
|
const messageList = messages
|
||||||
.filter((message) => message.visible !== false)
|
.filter((message) => message.visible !== false)
|
||||||
.map(
|
.map(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user