Skip to content

Commit

Permalink
Merge pull request #113 from nyaruka/delete_msg_task
Browse files Browse the repository at this point in the history
Add contact task to delete a message
  • Loading branch information
rowanseymour authored Aug 30, 2023
2 parents 0a15ccf + 18cfead commit f112201
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 0 deletions.
28 changes: 28 additions & 0 deletions core/models/msgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package models

import (
"context"
"database/sql"
"database/sql/driver"
"fmt"
"strings"
Expand Down Expand Up @@ -746,6 +747,33 @@ func NewMsgOut(oa *OrgAssets, c *flows.Contact, text string, atts []utils.Attach
return flows.NewMsgOut(urn, channelRef, text, atts, qrs, nil, flows.NilMsgTopic, locale, unsendableReason), channel
}

const sqlUpdateMsgDeletedBySender = `
UPDATE msgs_msg
SET visibility = 'X', text = '', attachments = '{}'
WHERE id = $1 AND org_id = $2 AND direction = 'I'`

func UpdateMessageDeletedBySender(ctx context.Context, db *sql.DB, orgID OrgID, msgID MsgID) error {
tx, err := db.BeginTx(ctx, nil)
if err != nil {
return errors.Wrap(err, "error beginning transaction")
}

res, err := tx.ExecContext(ctx, sqlUpdateMsgDeletedBySender, msgID, orgID)
if err != nil {
return errors.Wrap(err, "error updating message visibility")
}

// if there was such a message, remove its labels too
if rows, _ := res.RowsAffected(); rows == 1 {
_, err = tx.ExecContext(ctx, `DELETE FROM msgs_msg_labels WHERE msg_id = $1`, msgID)
if err != nil {
return errors.Wrap(err, "error removing message labels")
}
}

return errors.Wrap(tx.Commit(), "error committing transaction")
}

// NilID implementations

func (i *MsgID) Scan(value any) error { return null.ScanInt(value, i) }
Expand Down
25 changes: 25 additions & 0 deletions core/models/msgs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,31 @@ func TestFailMessages(t *testing.T) {
assertdb.Query(t, rt.DB, `SELECT status, failed_reason FROM msgs_msg WHERE id = $1`, out3.ID).Columns(map[string]any{"status": "F", "failed_reason": nil})
}

func TestUpdateMessageDeletedBySender(t *testing.T) {
ctx, rt := testsuite.Runtime()

defer testsuite.Reset(testsuite.ResetData)

in1 := testdata.InsertIncomingMsg(rt, testdata.Org1, testdata.TwilioChannel, testdata.Cathy, "hi", models.MsgStatusHandled)
in1.Label(rt, testdata.ReportingLabel, testdata.TestingLabel)
in2 := testdata.InsertIncomingMsg(rt, testdata.Org1, testdata.TwilioChannel, testdata.Cathy, "bye", models.MsgStatusHandled)
in2.Label(rt, testdata.ReportingLabel, testdata.TestingLabel)
out1 := testdata.InsertOutgoingMsg(rt, testdata.Org1, testdata.TwilioChannel, testdata.Cathy, "hi", nil, models.MsgStatusSent, false)

err := models.UpdateMessageDeletedBySender(ctx, rt.DB.DB, testdata.Org1.ID, in1.ID)
assert.NoError(t, err)

assertdb.Query(t, rt.DB, `SELECT visibility, text FROM msgs_msg WHERE id = $1`, in1.ID).Columns(map[string]any{"visibility": "X", "text": ""})
assertdb.Query(t, rt.DB, `SELECT count(*) FROM msgs_msg_labels WHERE msg_id = $1`, in1.ID).Returns(0)
assertdb.Query(t, rt.DB, `SELECT count(*) FROM msgs_msg_labels WHERE msg_id = $1`, in2.ID).Returns(2) // unchanged

// trying to delete an outgoing message is a noop
err = models.UpdateMessageDeletedBySender(ctx, rt.DB.DB, testdata.Org1.ID, out1.ID)
assert.NoError(t, err)

assertdb.Query(t, rt.DB, `SELECT visibility, text FROM msgs_msg WHERE id = $1`, out1.ID).Columns(map[string]any{"visibility": "V", "text": "hi"})
}

func TestGetMsgRepetitions(t *testing.T) {
_, rt := testsuite.Runtime()

Expand Down
11 changes: 11 additions & 0 deletions core/tasks/handler/contact_tasks.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const (
ExpirationEventType = "expiration_event"
TimeoutEventType = "timeout_event"
TicketClosedEventType = "ticket_closed"
MsgDeletedType = "msg_deleted"
)

// handleTimedEvent is called for timeout events
Expand Down Expand Up @@ -605,6 +606,11 @@ func handleTicketEvent(ctx context.Context, rt *runtime.Runtime, event *models.T
return nil
}

func handleMsgDeletedEvent(ctx context.Context, rt *runtime.Runtime, event *MsgDeletedEvent) error {
err := models.UpdateMessageDeletedBySender(ctx, rt.DB.DB, event.OrgID, event.MsgID)
return errors.Wrap(err, "error deleting message")
}

// handles a message as an inbox message, i.e. no flow
func handleAsInbox(ctx context.Context, rt *runtime.Runtime, oa *models.OrgAssets, contact *flows.Contact, msg *flows.MsgIn, attachments []utils.Attachment, logUUIDs []models.ChannelLogUUID, ticket *models.Ticket) error {
// usually last_seen_on is updated by handling the msg_received event in the engine sprint, but since this is an inbox
Expand Down Expand Up @@ -674,6 +680,11 @@ type StopEvent struct {
OccurredOn time.Time `json:"occurred_on"`
}

type MsgDeletedEvent struct {
OrgID models.OrgID `json:"org_id"`
MsgID models.MsgID `json:"message_id"`
}

// creates a new event task for the passed in timeout event
func newTimedTask(eventType string, orgID models.OrgID, contactID models.ContactID, sessionID models.SessionID, eventTime time.Time) *queue.Task {
event := &TimedEvent{
Expand Down
8 changes: 8 additions & 0 deletions core/tasks/handler/handle_contact_event.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,14 @@ func (t *HandleContactEventTask) Perform(ctx context.Context, rt *runtime.Runtim
}
err = handleTimedEvent(ctx, rt, contactEvent.Type, evt)

case MsgDeletedType:
evt := &MsgDeletedEvent{}
err = json.Unmarshal(contactEvent.Task, evt)
if err != nil {
return errors.Wrapf(err, "error unmarshalling deleted event: %s", event)
}
err = handleMsgDeletedEvent(ctx, rt, evt)

default:
return errors.Errorf("unknown contact event type: %s", contactEvent.Type)
}
Expand Down
1 change: 1 addition & 0 deletions testsuite/testsuite.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ DELETE FROM flows_flowrevision WHERE flow_id >= 30000;
DELETE FROM flows_flow WHERE id >= 30000;
DELETE FROM ivr_call;
DELETE FROM campaigns_eventfire;
DELETE FROM msgs_msg_labels;
DELETE FROM msgs_msg;
DELETE FROM msgs_broadcast_groups;
DELETE FROM msgs_broadcast_contacts;
Expand Down

0 comments on commit f112201

Please sign in to comment.