mattermost-community-enterp.../channels/app/platform/web_broadcast_hook.go
Claude ec1f89217a Merge: Complete Mattermost Server with Community Enterprise
Full Mattermost server source with integrated Community Enterprise features.
Includes vendor directory for offline/air-gapped builds.

Structure:
- enterprise-impl/: Enterprise feature implementations
- enterprise-community/: Init files that register implementations
- enterprise/: Bridge imports (community_imports.go)
- vendor/: All dependencies for offline builds

Build (online):
  go build ./cmd/mattermost

Build (offline/air-gapped):
  go build -mod=vendor ./cmd/mattermost

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 23:59:07 +09:00

91 lines
2.4 KiB
Go

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package platform
import (
"github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
type BroadcastHook interface {
// Process takes a WebSocket event and modifies it in some way. It is passed a HookedWebSocketEvent which allows
// safe modification of the event.
Process(msg *HookedWebSocketEvent, webConn *WebConn, args map[string]any) error
}
func (h *Hub) runBroadcastHooks(msg *model.WebSocketEvent, webConn *WebConn, hookIDs []string, hookArgs []map[string]any) *model.WebSocketEvent {
if len(hookIDs) == 0 {
return msg
}
hookedEvent := MakeHookedWebSocketEvent(msg)
for i, hookID := range hookIDs {
hook := h.broadcastHooks[hookID]
args := hookArgs[i]
if hook == nil {
mlog.Warn("runBroadcastHooks: Unable to find broadcast hook", mlog.String("hook_id", hookID))
continue
}
err := hook.Process(hookedEvent, webConn, args)
if err != nil {
mlog.Warn("runBroadcastHooks: Error processing hook", mlog.String("hook_id", hookID), mlog.Err(err))
}
}
return hookedEvent.Event()
}
// HookedWebSocketEvent is a wrapper for model.WebSocketEvent that is intended to provide a similar interface, except
// it ensures the original WebSocket event is not modified.
type HookedWebSocketEvent struct {
original *model.WebSocketEvent
copy *model.WebSocketEvent
}
func MakeHookedWebSocketEvent(event *model.WebSocketEvent) *HookedWebSocketEvent {
return &HookedWebSocketEvent{
original: event,
}
}
func (he *HookedWebSocketEvent) Add(key string, value any) {
he.copyIfNecessary()
he.copy.Add(key, value)
}
func (he *HookedWebSocketEvent) EventType() model.WebsocketEventType {
if he.copy == nil {
return he.original.EventType()
}
return he.copy.EventType()
}
// Get returns a value from the WebSocket event data. You should never mutate a value returned by this method.
func (he *HookedWebSocketEvent) Get(key string) any {
if he.copy == nil {
return he.original.GetData()[key]
}
return he.copy.GetData()[key]
}
// copyIfNecessary should be called by any mutative method to ensure that the copy is instantiated.
func (he *HookedWebSocketEvent) copyIfNecessary() {
if he.copy == nil {
he.copy = he.original.RemovePrecomputedJSON()
}
}
func (he *HookedWebSocketEvent) Event() *model.WebSocketEvent {
if he.copy == nil {
return he.original
}
return he.copy
}