From 5b0d009353b85c1bdf3394f4f2c2d4088c351660 Mon Sep 17 00:00:00 2001 From: Eli Ribble Date: Sat, 23 May 2026 00:47:37 +0000 Subject: [PATCH] Get text messages for a contact and the phone status --- db/query/comms/contact_phone.go | 7 ++++++ db/query/comms/text_log.go | 3 ++- platform/contact.go | 9 +++++++- platform/message.go | 38 +++++++++++++++++++++++++++++++++ platform/types/message.go | 22 +++++++++++++++++++ resource/contact.go | 12 ++++++++--- 6 files changed, 86 insertions(+), 5 deletions(-) create mode 100644 platform/message.go create mode 100644 platform/types/message.go diff --git a/db/query/comms/contact_phone.go b/db/query/comms/contact_phone.go index ff53deec..9483f466 100644 --- a/db/query/comms/contact_phone.go +++ b/db/query/comms/contact_phone.go @@ -19,6 +19,13 @@ func ContactPhoneInsert(ctx context.Context, txn db.Ex, m model.ContactPhone) (m return db.ExecuteOneTx[model.ContactPhone](ctx, txn, statement) } +func ContactPhoneFromContactID(ctx context.Context, txn db.Ex, contact_id int64) (model.ContactPhone, error) { + statement := table.ContactPhone.SELECT( + table.ContactPhone.AllColumns, + ).FROM(table.ContactPhone). + WHERE(table.ContactPhone.ContactID.EQ(postgres.Int(contact_id))) + return db.ExecuteOneTx[model.ContactPhone](ctx, txn, statement) +} func ContactPhoneFromE164(ctx context.Context, txn db.Ex, e164 string) (model.ContactPhone, error) { statement := table.ContactPhone.SELECT( table.ContactPhone.AllColumns, diff --git a/db/query/comms/text_log.go b/db/query/comms/text_log.go index b5ce87dc..7efca35c 100644 --- a/db/query/comms/text_log.go +++ b/db/query/comms/text_log.go @@ -28,7 +28,8 @@ func TextLogsFromPhoneNumber(ctx context.Context, txn db.Ex, number string) ([]m table.TextLog.AllColumns, ).FROM(table.TextLog). WHERE(table.TextLog.Source.EQ(postgres.String(number)).OR( - table.TextLog.Destination.EQ(postgres.String(number)))) + table.TextLog.Destination.EQ(postgres.String(number)))). + ORDER_BY(table.TextLog.Created.DESC()) return db.ExecuteManyTx[model.TextLog](ctx, txn, statement) } func TextLogWelcomeFromDestination(ctx context.Context, txn db.Ex, destination string) ([]model.TextLog, error) { diff --git a/platform/contact.go b/platform/contact.go index 93ac931a..49174569 100644 --- a/platform/contact.go +++ b/platform/contact.go @@ -58,9 +58,16 @@ func ContactsForOrganization(ctx context.Context, org_id int32) (results []types phones := make([]types.Phone, len(contact_phones)) for i, p := range contact_phones { phone := phones_by_e164[p.E164] + status := "unconfirmed" + if phone.StopMessageID != nil { + status = "stopped" + } else if phone.ConfirmedMessageID != nil { + status = "confirmed" + } phones[i] = types.Phone{ - E164: phone.E164, CanSMS: phone.CanSms, + E164: phone.E164, + Status: status, } } if row.Name != "" || len(contact_phones) > 0 || len(contact_emails) > 0 { diff --git a/platform/message.go b/platform/message.go new file mode 100644 index 00000000..ec9dee62 --- /dev/null +++ b/platform/message.go @@ -0,0 +1,38 @@ +package platform + +import ( + "context" + "errors" + "fmt" + + "source.gleipnir.technology/Gleipnir/nidus-sync/db" + querycomms "source.gleipnir.technology/Gleipnir/nidus-sync/db/query/comms" + "source.gleipnir.technology/Gleipnir/nidus-sync/platform/types" +) + +func MessagesForContact(ctx context.Context, contact_id int64) ([]types.Message, error) { + //emails, err := querycomms.EmailsFromContactID + txn := db.PGInstance.PGXPool + contact_phone, err := querycomms.ContactPhoneFromContactID(ctx, txn, contact_id) + if err != nil { + if errors.Is(err, db.ErrNoRows) { + return []types.Message{}, nil + } + return nil, fmt.Errorf("contact_phone from contact id %d: %w", contact_id, err) + } + texts, err := querycomms.TextLogsFromPhoneNumber(ctx, txn, contact_phone.E164) + if err != nil { + return nil, fmt.Errorf("text log from contact id %d: %w", contact_id, err) + } + results := make([]types.Message, len(texts)) + for i, text := range texts { + results[i] = types.Message{ + Content: text.Content, + Created: text.Created, + Destination: text.Destination, + Source: text.Source, + Type: types.MessageTypeText, + } + } + return results, err +} diff --git a/platform/types/message.go b/platform/types/message.go new file mode 100644 index 00000000..d5161366 --- /dev/null +++ b/platform/types/message.go @@ -0,0 +1,22 @@ +package types + +import ( + "time" +) + +type MessageType int + +const ( + MessageTypeUnknown MessageType = iota + MessageTypeEmail + MessageTypeMailer + MessageTypeText +) + +type Message struct { + Content string `json:"content"` + Created time.Time `json:"created"` + Destination string `json:"destination"` + Source string `json:"source"` + Type MessageType `json:"type"` +} diff --git a/resource/contact.go b/resource/contact.go index b580cd06..cbf050f9 100644 --- a/resource/contact.go +++ b/resource/contact.go @@ -22,7 +22,8 @@ func Contact(r *router) *contactR { type contact struct { types.Contact - URI string + Messages []types.Message + URI string } func (res *contactR) ByIDGet(ctx context.Context, r *http.Request, user platform.User, qp QueryParams) (contact, *nhttp.ErrorWithStatus) { @@ -39,9 +40,14 @@ func (res *contactR) List(ctx context.Context, r *http.Request, user platform.Us if err != nil { return nil, nhttp.NewError("contact uri: %w", err) } + messages, err := platform.MessagesForContact(ctx, int64(c.ID)) + if err != nil { + return nil, nhttp.NewError("messages for contact: %w", err) + } result[i] = contact{ - Contact: c, - URI: uri, + Contact: c, + Messages: messages, + URI: uri, } } return result, nil