mirror of
https://github.com/abhinavxd/libredesk.git
synced 2025-10-24 16:43:40 +00:00
return created message in message fetch API
This commit is contained in:
@@ -744,7 +744,7 @@ func handleCreateConversation(r *fastglue.Request) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send reply to the created conversation.
|
// Send reply to the created conversation.
|
||||||
if err := app.conversation.SendReply(media, req.InboxID, auser.ID /**sender_id**/, conversationUUID, req.Content, to, nil /**cc**/, nil /**bcc**/, map[string]any{} /**meta**/); err != nil {
|
if _, err := app.conversation.SendReply(media, req.InboxID, auser.ID /**sender_id**/, conversationUUID, req.Content, to, nil /**cc**/, nil /**bcc**/, map[string]any{} /**meta**/); err != nil {
|
||||||
// Delete the conversation if reply fails.
|
// Delete the conversation if reply fails.
|
||||||
if err := app.conversation.DeleteConversation(conversationUUID); err != nil {
|
if err := app.conversation.DeleteConversation(conversationUUID); err != nil {
|
||||||
app.lo.Error("error deleting conversation", "error", err)
|
app.lo.Error("error deleting conversation", "error", err)
|
||||||
|
|||||||
@@ -162,13 +162,15 @@ func handleSendMessage(r *fastglue.Request) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if req.Private {
|
if req.Private {
|
||||||
if err := app.conversation.SendPrivateNote(media, user.ID, cuuid, req.Message); err != nil {
|
message, err := app.conversation.SendPrivateNote(media, user.ID, cuuid, req.Message)
|
||||||
return sendErrorEnvelope(r, err)
|
if err != nil {
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if err := app.conversation.SendReply(media, conv.InboxID, user.ID, cuuid, req.Message, req.To, req.CC, req.BCC, map[string]any{} /**meta**/); err != nil {
|
|
||||||
return sendErrorEnvelope(r, err)
|
return sendErrorEnvelope(r, err)
|
||||||
}
|
}
|
||||||
|
return r.SendEnvelope(message)
|
||||||
}
|
}
|
||||||
return r.SendEnvelope(true)
|
message, err := app.conversation.SendReply(media, conv.InboxID, user.ID, cuuid, req.Message, req.To, req.CC, req.BCC, map[string]any{} /**meta**/)
|
||||||
|
if err != nil {
|
||||||
|
return sendErrorEnvelope(r, err)
|
||||||
|
}
|
||||||
|
return r.SendEnvelope(message)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -920,14 +920,17 @@ func (m *Manager) ApplyAction(action amodels.RuleAction, conv models.Conversatio
|
|||||||
}
|
}
|
||||||
return m.UpdateConversationStatus(conv.UUID, statusID, "", "", user)
|
return m.UpdateConversationStatus(conv.UUID, statusID, "", "", user)
|
||||||
case amodels.ActionSendPrivateNote:
|
case amodels.ActionSendPrivateNote:
|
||||||
return m.SendPrivateNote([]mmodels.Media{}, user.ID, conv.UUID, action.Value[0])
|
_, err := m.SendPrivateNote([]mmodels.Media{}, user.ID, conv.UUID, action.Value[0])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("sending private note: %w", err)
|
||||||
|
}
|
||||||
case amodels.ActionReply:
|
case amodels.ActionReply:
|
||||||
// Make recipient list.
|
// Make recipient list.
|
||||||
to, cc, bcc, err := m.makeRecipients(conv.ID, conv.Contact.Email.String, conv.InboxMail)
|
to, cc, bcc, err := m.makeRecipients(conv.ID, conv.Contact.Email.String, conv.InboxMail)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("making recipients for reply action: %w", err)
|
return fmt.Errorf("making recipients for reply action: %w", err)
|
||||||
}
|
}
|
||||||
return m.SendReply(
|
_, err = m.SendReply(
|
||||||
[]mmodels.Media{},
|
[]mmodels.Media{},
|
||||||
conv.InboxID,
|
conv.InboxID,
|
||||||
user.ID,
|
user.ID,
|
||||||
@@ -938,6 +941,9 @@ func (m *Manager) ApplyAction(action amodels.RuleAction, conv models.Conversatio
|
|||||||
bcc,
|
bcc,
|
||||||
map[string]any{}, /**meta**/
|
map[string]any{}, /**meta**/
|
||||||
)
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("sending reply: %w", err)
|
||||||
|
}
|
||||||
case amodels.ActionSetSLA:
|
case amodels.ActionSetSLA:
|
||||||
slaID, err := strconv.Atoi(action.Value[0])
|
slaID, err := strconv.Atoi(action.Value[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -951,6 +957,7 @@ func (m *Manager) ApplyAction(action amodels.RuleAction, conv models.Conversatio
|
|||||||
default:
|
default:
|
||||||
return fmt.Errorf("unknown action: %s", action.Type)
|
return fmt.Errorf("unknown action: %s", action.Type)
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveConversationAssignee removes the assignee from the conversation.
|
// RemoveConversationAssignee removes the assignee from the conversation.
|
||||||
@@ -991,10 +998,16 @@ func (m *Manager) SendCSATReply(actorUserID int, conversation models.Conversatio
|
|||||||
// Make recipient list.
|
// Make recipient list.
|
||||||
to, cc, bcc, err := m.makeRecipients(conversation.ID, conversation.Contact.Email.String, conversation.InboxMail)
|
to, cc, bcc, err := m.makeRecipients(conversation.ID, conversation.Contact.Email.String, conversation.InboxMail)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("making recipients for CSAT reply: %w", err)
|
return envelope.NewError(envelope.GeneralError, m.i18n.Ts("globals.messages.errorCreating", "name", "{globals.terms.csat}"), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return m.SendReply(nil /**media**/, conversation.InboxID, actorUserID, conversation.UUID, message, to, cc, bcc, meta)
|
// Send CSAT reply.
|
||||||
|
_, err = m.SendReply(nil /**media**/, conversation.InboxID, actorUserID, conversation.UUID, message, to, cc, bcc, meta)
|
||||||
|
if err != nil {
|
||||||
|
m.lo.Error("error sending CSAT reply", "conversation_uuid", conversation.UUID, "error", err)
|
||||||
|
return envelope.NewError(envelope.GeneralError, m.i18n.Ts("globals.messages.errorCreating", "name", "{globals.terms.csat}"), nil)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteConversation deletes a conversation.
|
// DeleteConversation deletes a conversation.
|
||||||
|
|||||||
@@ -356,8 +356,7 @@ func (m *Manager) MarkMessageAsPending(uuid string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SendPrivateNote inserts a private message in a conversation.
|
// SendPrivateNote inserts a private message in a conversation.
|
||||||
func (m *Manager) SendPrivateNote(media []mmodels.Media, senderID int, conversationUUID, content string) error {
|
func (m *Manager) SendPrivateNote(media []mmodels.Media, senderID int, conversationUUID, content string) (models.Message, error) {
|
||||||
// Insert Message.
|
|
||||||
message := models.Message{
|
message := models.Message{
|
||||||
ConversationUUID: conversationUUID,
|
ConversationUUID: conversationUUID,
|
||||||
SenderID: senderID,
|
SenderID: senderID,
|
||||||
@@ -369,18 +368,25 @@ func (m *Manager) SendPrivateNote(media []mmodels.Media, senderID int, conversat
|
|||||||
Private: true,
|
Private: true,
|
||||||
Media: media,
|
Media: media,
|
||||||
}
|
}
|
||||||
return m.InsertMessage(&message)
|
if err := m.InsertMessage(&message); err != nil {
|
||||||
|
return models.Message{}, err
|
||||||
|
}
|
||||||
|
return message, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendReply inserts a reply message in a conversation.
|
// SendReply inserts a reply message in a conversation.
|
||||||
func (m *Manager) SendReply(media []mmodels.Media, inboxID, senderID int, conversationUUID, content string, to, cc, bcc []string, meta map[string]interface{}) error {
|
func (m *Manager) SendReply(media []mmodels.Media, inboxID, senderID int, conversationUUID, content string, to, cc, bcc []string, meta map[string]interface{}) (models.Message, error) {
|
||||||
// Save to, cc and bcc in meta.
|
var (
|
||||||
|
message = models.Message{}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Clear empty fields in to, cc, bcc.
|
||||||
to = stringutil.RemoveEmpty(to)
|
to = stringutil.RemoveEmpty(to)
|
||||||
cc = stringutil.RemoveEmpty(cc)
|
cc = stringutil.RemoveEmpty(cc)
|
||||||
bcc = stringutil.RemoveEmpty(bcc)
|
bcc = stringutil.RemoveEmpty(bcc)
|
||||||
|
|
||||||
if len(to) == 0 {
|
if len(to) == 0 {
|
||||||
return envelope.NewError(envelope.GeneralError, m.i18n.Ts("globals.messages.empty", "name", "`to`"), nil)
|
return message, envelope.NewError(envelope.GeneralError, m.i18n.Ts("globals.messages.empty", "name", "`to`"), nil)
|
||||||
}
|
}
|
||||||
meta["to"] = to
|
meta["to"] = to
|
||||||
|
|
||||||
@@ -393,22 +399,22 @@ func (m *Manager) SendReply(media []mmodels.Media, inboxID, senderID int, conver
|
|||||||
|
|
||||||
metaJSON, err := json.Marshal(meta)
|
metaJSON, err := json.Marshal(meta)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return envelope.NewError(envelope.GeneralError, m.i18n.Ts("globals.messages.errorMarshalling", "name", "{globals.terms.meta}"), nil)
|
return message, envelope.NewError(envelope.GeneralError, m.i18n.Ts("globals.messages.errorMarshalling", "name", "{globals.terms.meta}"), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generage unique source ID i.e. message-id for email.
|
// Generage unique source ID i.e. message-id for email.
|
||||||
inbox, err := m.inboxStore.GetDBRecord(inboxID)
|
inbox, err := m.inboxStore.GetDBRecord(inboxID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return message, err
|
||||||
}
|
}
|
||||||
sourceID, err := stringutil.GenerateEmailMessageID(conversationUUID, inbox.From)
|
sourceID, err := stringutil.GenerateEmailMessageID(conversationUUID, inbox.From)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
m.lo.Error("error generating source message id", "error", err)
|
m.lo.Error("error generating source message id", "error", err)
|
||||||
return envelope.NewError(envelope.GeneralError, m.i18n.T("conversation.errorGeneratingMessageID"), nil)
|
return message, envelope.NewError(envelope.GeneralError, m.i18n.T("conversation.errorGeneratingMessageID"), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert Message.
|
// Insert Message.
|
||||||
message := models.Message{
|
message = models.Message{
|
||||||
ConversationUUID: conversationUUID,
|
ConversationUUID: conversationUUID,
|
||||||
SenderID: senderID,
|
SenderID: senderID,
|
||||||
Type: models.MessageOutgoing,
|
Type: models.MessageOutgoing,
|
||||||
@@ -421,16 +427,17 @@ func (m *Manager) SendReply(media []mmodels.Media, inboxID, senderID int, conver
|
|||||||
Meta: metaJSON,
|
Meta: metaJSON,
|
||||||
SourceID: null.StringFrom(sourceID),
|
SourceID: null.StringFrom(sourceID),
|
||||||
}
|
}
|
||||||
return m.InsertMessage(&message)
|
if err := m.InsertMessage(&message); err != nil {
|
||||||
|
return models.Message{}, err
|
||||||
|
}
|
||||||
|
return message, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// InsertMessage inserts a message and attaches the media to the message.
|
// InsertMessage inserts a message and attaches the media to the message.
|
||||||
func (m *Manager) InsertMessage(message *models.Message) error {
|
func (m *Manager) InsertMessage(message *models.Message) error {
|
||||||
// Private message is always sent.
|
|
||||||
if message.Private {
|
if message.Private {
|
||||||
message.Status = models.MessageStatusSent
|
message.Status = models.MessageStatusSent
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(message.Meta) == 0 || string(message.Meta) == "null" {
|
if len(message.Meta) == 0 || string(message.Meta) == "null" {
|
||||||
message.Meta = json.RawMessage(`{}`)
|
message.Meta = json.RawMessage(`{}`)
|
||||||
}
|
}
|
||||||
@@ -438,14 +445,16 @@ func (m *Manager) InsertMessage(message *models.Message) error {
|
|||||||
// Convert HTML content to text for search.
|
// Convert HTML content to text for search.
|
||||||
message.TextContent = stringutil.HTML2Text(message.Content)
|
message.TextContent = stringutil.HTML2Text(message.Content)
|
||||||
|
|
||||||
// Insert Message.
|
// Insert and scan the message into the struct.
|
||||||
if err := m.q.InsertMessage.QueryRow(message.Type, message.Status, message.ConversationID, message.ConversationUUID, message.Content, message.TextContent, message.SenderID, message.SenderType,
|
if err := m.q.InsertMessage.Get(message,
|
||||||
message.Private, message.ContentType, message.SourceID, message.Meta).Scan(&message.ID, &message.UUID, &message.CreatedAt); err != nil {
|
message.Type, message.Status, message.ConversationID, message.ConversationUUID,
|
||||||
|
message.Content, message.TextContent, message.SenderID, message.SenderType,
|
||||||
|
message.Private, message.ContentType, message.SourceID, message.Meta); err != nil {
|
||||||
m.lo.Error("error inserting message in db", "error", err)
|
m.lo.Error("error inserting message in db", "error", err)
|
||||||
return envelope.NewError(envelope.GeneralError, m.i18n.Ts("globals.messages.errorInserting", "name", "{globals.terms.message}"), nil)
|
return envelope.NewError(envelope.GeneralError, m.i18n.Ts("globals.messages.errorInserting", "name", "{globals.terms.message}"), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attach message to the media.
|
// Attach just inserted message to the media.
|
||||||
for _, media := range message.Media {
|
for _, media := range message.Media {
|
||||||
m.mediaStore.Attach(media.ID, mmodels.ModelMessages, message.ID)
|
m.mediaStore.Attach(media.ID, mmodels.ModelMessages, message.ID)
|
||||||
}
|
}
|
||||||
@@ -465,14 +474,20 @@ func (m *Manager) InsertMessage(message *models.Message) error {
|
|||||||
// Broadcast new message.
|
// Broadcast new message.
|
||||||
m.BroadcastNewMessage(message)
|
m.BroadcastNewMessage(message)
|
||||||
|
|
||||||
// Refetch message and send webhook event for message created.
|
// Refetch message if this message has media attachments, as media gets linked after inserting the message.
|
||||||
updatedMessage, err := m.GetMessage(message.UUID)
|
if len(message.Media) > 0 {
|
||||||
if err != nil {
|
refetchedMessage, err := m.GetMessage(message.UUID)
|
||||||
m.lo.Error("error fetching updated message for webhook event", "uuid", message.UUID, "error", err)
|
if err != nil {
|
||||||
} else {
|
m.lo.Error("error fetching message after insert", "error", err)
|
||||||
m.webhookStore.TriggerEvent(wmodels.EventMessageCreated, updatedMessage)
|
} else {
|
||||||
|
// Replace the message in the struct with the refetched message.
|
||||||
|
*message = refetchedMessage
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Trigger webhook for new message created.
|
||||||
|
m.webhookStore.TriggerEvent(wmodels.EventMessageCreated, message)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,7 +545,7 @@ func (m *Manager) InsertConversationActivity(activityType, conversationUUID, new
|
|||||||
content, err := m.getMessageActivityContent(activityType, newValue, actor.FullName())
|
content, err := m.getMessageActivityContent(activityType, newValue, actor.FullName())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
m.lo.Error("error could not generate activity content", "error", err)
|
m.lo.Error("error could not generate activity content", "error", err)
|
||||||
return err
|
return envelope.NewError(envelope.GeneralError, m.i18n.Ts("globals.messages.errorGenerating", "name", "{globals.terms.activityMessage}"), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
message := models.Message{
|
message := models.Message{
|
||||||
|
|||||||
@@ -509,9 +509,9 @@ inserted_msg AS (
|
|||||||
$1, $2, (SELECT id FROM conversation_id),
|
$1, $2, (SELECT id FROM conversation_id),
|
||||||
$5, $6, $7, $8, $9, $10, $11, $12
|
$5, $6, $7, $8, $9, $10, $11, $12
|
||||||
)
|
)
|
||||||
RETURNING id, uuid, created_at, conversation_id
|
RETURNING *
|
||||||
)
|
)
|
||||||
SELECT id, uuid, created_at FROM inserted_msg;
|
SELECT * FROM inserted_msg;
|
||||||
|
|
||||||
-- name: message-exists-by-source-id
|
-- name: message-exists-by-source-id
|
||||||
SELECT conversation_id
|
SELECT conversation_id
|
||||||
|
|||||||
Reference in New Issue
Block a user