mirror of
https://github.com/abhinavxd/libredesk.git
synced 2025-10-23 05:11:57 +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.
|
||||
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.
|
||||
if err := app.conversation.DeleteConversation(conversationUUID); err != nil {
|
||||
app.lo.Error("error deleting conversation", "error", err)
|
||||
|
@@ -162,13 +162,15 @@ func handleSendMessage(r *fastglue.Request) error {
|
||||
}
|
||||
|
||||
if req.Private {
|
||||
if err := app.conversation.SendPrivateNote(media, user.ID, cuuid, req.Message); err != nil {
|
||||
return sendErrorEnvelope(r, err)
|
||||
}
|
||||
} 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 {
|
||||
message, err := app.conversation.SendPrivateNote(media, user.ID, cuuid, req.Message)
|
||||
if err != nil {
|
||||
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)
|
||||
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:
|
||||
// Make recipient list.
|
||||
to, cc, bcc, err := m.makeRecipients(conv.ID, conv.Contact.Email.String, conv.InboxMail)
|
||||
if err != nil {
|
||||
return fmt.Errorf("making recipients for reply action: %w", err)
|
||||
}
|
||||
return m.SendReply(
|
||||
_, err = m.SendReply(
|
||||
[]mmodels.Media{},
|
||||
conv.InboxID,
|
||||
user.ID,
|
||||
@@ -938,6 +941,9 @@ func (m *Manager) ApplyAction(action amodels.RuleAction, conv models.Conversatio
|
||||
bcc,
|
||||
map[string]any{}, /**meta**/
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("sending reply: %w", err)
|
||||
}
|
||||
case amodels.ActionSetSLA:
|
||||
slaID, err := strconv.Atoi(action.Value[0])
|
||||
if err != nil {
|
||||
@@ -951,6 +957,7 @@ func (m *Manager) ApplyAction(action amodels.RuleAction, conv models.Conversatio
|
||||
default:
|
||||
return fmt.Errorf("unknown action: %s", action.Type)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveConversationAssignee removes the assignee from the conversation.
|
||||
@@ -991,10 +998,16 @@ func (m *Manager) SendCSATReply(actorUserID int, conversation models.Conversatio
|
||||
// Make recipient list.
|
||||
to, cc, bcc, err := m.makeRecipients(conversation.ID, conversation.Contact.Email.String, conversation.InboxMail)
|
||||
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.
|
||||
|
@@ -356,8 +356,7 @@ func (m *Manager) MarkMessageAsPending(uuid string) error {
|
||||
}
|
||||
|
||||
// SendPrivateNote inserts a private message in a conversation.
|
||||
func (m *Manager) SendPrivateNote(media []mmodels.Media, senderID int, conversationUUID, content string) error {
|
||||
// Insert Message.
|
||||
func (m *Manager) SendPrivateNote(media []mmodels.Media, senderID int, conversationUUID, content string) (models.Message, error) {
|
||||
message := models.Message{
|
||||
ConversationUUID: conversationUUID,
|
||||
SenderID: senderID,
|
||||
@@ -369,18 +368,25 @@ func (m *Manager) SendPrivateNote(media []mmodels.Media, senderID int, conversat
|
||||
Private: true,
|
||||
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.
|
||||
func (m *Manager) SendReply(media []mmodels.Media, inboxID, senderID int, conversationUUID, content string, to, cc, bcc []string, meta map[string]interface{}) error {
|
||||
// Save to, cc and bcc in meta.
|
||||
func (m *Manager) SendReply(media []mmodels.Media, inboxID, senderID int, conversationUUID, content string, to, cc, bcc []string, meta map[string]interface{}) (models.Message, error) {
|
||||
var (
|
||||
message = models.Message{}
|
||||
)
|
||||
|
||||
// Clear empty fields in to, cc, bcc.
|
||||
to = stringutil.RemoveEmpty(to)
|
||||
cc = stringutil.RemoveEmpty(cc)
|
||||
bcc = stringutil.RemoveEmpty(bcc)
|
||||
|
||||
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
|
||||
|
||||
@@ -393,22 +399,22 @@ func (m *Manager) SendReply(media []mmodels.Media, inboxID, senderID int, conver
|
||||
|
||||
metaJSON, err := json.Marshal(meta)
|
||||
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.
|
||||
inbox, err := m.inboxStore.GetDBRecord(inboxID)
|
||||
if err != nil {
|
||||
return err
|
||||
return message, err
|
||||
}
|
||||
sourceID, err := stringutil.GenerateEmailMessageID(conversationUUID, inbox.From)
|
||||
if err != nil {
|
||||
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.
|
||||
message := models.Message{
|
||||
message = models.Message{
|
||||
ConversationUUID: conversationUUID,
|
||||
SenderID: senderID,
|
||||
Type: models.MessageOutgoing,
|
||||
@@ -421,16 +427,17 @@ func (m *Manager) SendReply(media []mmodels.Media, inboxID, senderID int, conver
|
||||
Meta: metaJSON,
|
||||
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.
|
||||
func (m *Manager) InsertMessage(message *models.Message) error {
|
||||
// Private message is always sent.
|
||||
if message.Private {
|
||||
message.Status = models.MessageStatusSent
|
||||
}
|
||||
|
||||
if len(message.Meta) == 0 || string(message.Meta) == "null" {
|
||||
message.Meta = json.RawMessage(`{}`)
|
||||
}
|
||||
@@ -438,14 +445,16 @@ func (m *Manager) InsertMessage(message *models.Message) error {
|
||||
// Convert HTML content to text for search.
|
||||
message.TextContent = stringutil.HTML2Text(message.Content)
|
||||
|
||||
// Insert Message.
|
||||
if err := m.q.InsertMessage.QueryRow(message.Type, message.Status, message.ConversationID, message.ConversationUUID, message.Content, message.TextContent, message.SenderID, message.SenderType,
|
||||
message.Private, message.ContentType, message.SourceID, message.Meta).Scan(&message.ID, &message.UUID, &message.CreatedAt); err != nil {
|
||||
// Insert and scan the message into the struct.
|
||||
if err := m.q.InsertMessage.Get(message,
|
||||
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)
|
||||
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 {
|
||||
m.mediaStore.Attach(media.ID, mmodels.ModelMessages, message.ID)
|
||||
}
|
||||
@@ -465,14 +474,20 @@ func (m *Manager) InsertMessage(message *models.Message) error {
|
||||
// Broadcast new message.
|
||||
m.BroadcastNewMessage(message)
|
||||
|
||||
// Refetch message and send webhook event for message created.
|
||||
updatedMessage, err := m.GetMessage(message.UUID)
|
||||
if err != nil {
|
||||
m.lo.Error("error fetching updated message for webhook event", "uuid", message.UUID, "error", err)
|
||||
} else {
|
||||
m.webhookStore.TriggerEvent(wmodels.EventMessageCreated, updatedMessage)
|
||||
// Refetch message if this message has media attachments, as media gets linked after inserting the message.
|
||||
if len(message.Media) > 0 {
|
||||
refetchedMessage, err := m.GetMessage(message.UUID)
|
||||
if err != nil {
|
||||
m.lo.Error("error fetching message after insert", "error", err)
|
||||
} 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
|
||||
}
|
||||
|
||||
@@ -530,7 +545,7 @@ func (m *Manager) InsertConversationActivity(activityType, conversationUUID, new
|
||||
content, err := m.getMessageActivityContent(activityType, newValue, actor.FullName())
|
||||
if err != nil {
|
||||
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{
|
||||
|
@@ -509,9 +509,9 @@ inserted_msg AS (
|
||||
$1, $2, (SELECT id FROM conversation_id),
|
||||
$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
|
||||
SELECT conversation_id
|
||||
|
Reference in New Issue
Block a user