diff --git a/cmd/chat.go b/cmd/chat.go index 0dff6c24..b2de48f0 100644 --- a/cmd/chat.go +++ b/cmd/chat.go @@ -77,8 +77,9 @@ type conversationResponseWithBusinessHours struct { WorkingHoursUTCOffset *int `json:"working_hours_utc_offset,omitempty"` } -// handleGetChatLauncherSettings returns the live chat launcher settings for the widget +// handleGetChatLauncherSettings returns the live chat launcher settings for the widget. func handleGetChatLauncherSettings(r *fastglue.Request) error { + r.RequestCtx.Response.Header.Set("Access-Control-Allow-Origin", "*") _, config, err := validateLiveChatInbox(r) if err != nil { return sendErrorEnvelope(r, err) diff --git a/cmd/init.go b/cmd/init.go index 3d54872f..7b1f9b87 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -65,6 +65,7 @@ import ( _ "github.com/lib/pq" "github.com/redis/go-redis/v9" flag "github.com/spf13/pflag" + "github.com/volatiletech/null/v9" "github.com/zerodha/logf" ) @@ -662,7 +663,7 @@ func initEmailInbox(inboxRecord imodels.Inbox, msgStore inbox.MessageStore, usrS } // initLiveChatInbox initializes the live chat inbox. -func initLiveChatInbox(inboxRecord imodels.Inbox, msgStore inbox.MessageStore, usrStore inbox.UserStore) (inbox.Inbox, error) { +func initLiveChatInbox(inboxRecord imodels.Inbox, msgStore inbox.MessageStore, usrStore inbox.UserStore, signAvatarURL func(*null.String)) (inbox.Inbox, error) { var config livechat.Config // Load JSON data into Koanf. @@ -675,9 +676,10 @@ func initLiveChatInbox(inboxRecord imodels.Inbox, msgStore inbox.MessageStore, u } inbox, err := livechat.New(msgStore, usrStore, livechat.Opts{ - ID: inboxRecord.ID, - Config: config, - Lo: initLogger("livechat_inbox"), + ID: inboxRecord.ID, + Config: config, + Lo: initLogger("livechat_inbox"), + SignAvatarURL: signAvatarURL, }) if err != nil { @@ -690,13 +692,13 @@ func initLiveChatInbox(inboxRecord imodels.Inbox, msgStore inbox.MessageStore, u } // makeInboxInitializer creates an inbox initializer function. -func makeInboxInitializer(mgr *inbox.Manager) func(imodels.Inbox, inbox.MessageStore, inbox.UserStore) (inbox.Inbox, error) { +func makeInboxInitializer(mgr *inbox.Manager, signAvatarURL func(*null.String)) func(imodels.Inbox, inbox.MessageStore, inbox.UserStore) (inbox.Inbox, error) { return func(inboxR imodels.Inbox, msgStore inbox.MessageStore, usrStore inbox.UserStore) (inbox.Inbox, error) { switch inboxR.Channel { case inbox.ChannelEmail: return initEmailInbox(inboxR, msgStore, usrStore, mgr) case inbox.ChannelLiveChat: - return initLiveChatInbox(inboxR, msgStore, usrStore) + return initLiveChatInbox(inboxR, msgStore, usrStore, signAvatarURL) default: return nil, fmt.Errorf("unknown inbox channel: %s", inboxR.Channel) } @@ -706,15 +708,15 @@ func makeInboxInitializer(mgr *inbox.Manager) func(imodels.Inbox, inbox.MessageS // reloadInboxes reloads all inboxes. func reloadInboxes(app *App) error { app.lo.Info("reloading inboxes") - return app.inbox.Reload(ctx, makeInboxInitializer(app.inbox)) + return app.inbox.Reload(ctx, makeInboxInitializer(app.inbox, app.conversation.SignAvatarURL)) } // startInboxes registers the active inboxes and starts receiver for each. -func startInboxes(ctx context.Context, mgr *inbox.Manager, msgStore inbox.MessageStore, usrStore inbox.UserStore) { +func startInboxes(ctx context.Context, mgr *inbox.Manager, msgStore inbox.MessageStore, usrStore inbox.UserStore, signAvatarURL func(*null.String)) { mgr.SetMessageStore(msgStore) mgr.SetUserStore(usrStore) - if err := mgr.InitInboxes(makeInboxInitializer(mgr)); err != nil { + if err := mgr.InitInboxes(makeInboxInitializer(mgr, signAvatarURL)); err != nil { log.Fatalf("error initializing inboxes: %v", err) } diff --git a/cmd/main.go b/cmd/main.go index 5080f544..71ea6200 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -229,7 +229,7 @@ func main() { automation.SetConversationStore(conversation) // Start inboxes. - startInboxes(ctx, inbox, conversation, user) + startInboxes(ctx, inbox, conversation, user, conversation.SignAvatarURL) go automation.Run(ctx, automationWorkers) go autoassigner.Run(ctx, autoAssignInterval) diff --git a/internal/conversation/message.go b/internal/conversation/message.go index 5ac7699b..d2e1a002 100644 --- a/internal/conversation/message.go +++ b/internal/conversation/message.go @@ -1212,6 +1212,7 @@ func (m *Manager) broadcastMessageToWidgetClients(message *models.Message) { return } + m.SignAvatarURL(&message.Author.AvatarURL) liveChatInbox.BroadcastMessageToClients(message.ConversationUUID, conversation.ContactID, models.ChatMessage{ UUID: message.UUID, Status: message.Status, diff --git a/internal/inbox/channel/livechat/livechat.go b/internal/inbox/channel/livechat/livechat.go index 6ebadf7d..462398c0 100644 --- a/internal/inbox/channel/livechat/livechat.go +++ b/internal/inbox/channel/livechat/livechat.go @@ -10,6 +10,7 @@ import ( "github.com/abhinavxd/libredesk/internal/conversation/models" "github.com/abhinavxd/libredesk/internal/inbox" + "github.com/volatiletech/null/v9" "github.com/zerodha/logf" ) @@ -108,16 +109,18 @@ type LiveChat struct { lo *logf.Logger messageStore inbox.MessageStore userStore inbox.UserStore + signAvatarURL func(*null.String) // Signs a raw /uploads/ avatar path into a signed URL. clients map[string][]*Client // Maps user IDs to slices of clients (to handle multiple devices) clientsMutex sync.RWMutex } // Opts holds the options required for the live chat inbox. type Opts struct { - ID int - Config Config - From string - Lo *logf.Logger + ID int + Config Config + From string + Lo *logf.Logger + SignAvatarURL func(*null.String) } // New returns a new instance of the live chat inbox. @@ -129,6 +132,7 @@ func New(store inbox.MessageStore, userStore inbox.UserStore, opts Opts) (*LiveC lo: opts.Lo, messageStore: store, userStore: userStore, + signAvatarURL: opts.SignAvatarURL, clients: make(map[string][]*Client), } return lc, nil @@ -170,6 +174,11 @@ func (lc *LiveChat) Send(message models.OutboundMessage) error { message.Attachments[i].Content = nil } + avatarURL := sender.AvatarURL + if lc.signAvatarURL != nil { + lc.signAvatarURL(&avatarURL) + } + messageData := map[string]any{ "type": "new_message", "data": models.ChatMessage{ @@ -183,7 +192,7 @@ func (lc *LiveChat) Send(message models.OutboundMessage) error { ID: message.SenderID, FirstName: sender.FirstName, LastName: sender.LastName, - AvatarURL: sender.AvatarURL, + AvatarURL: avatarURL, AvailabilityStatus: sender.AvailabilityStatus, Type: sender.Type, LastActiveAt: sender.LastActiveAt,