Skip to content

Commit e4ed5ea

Browse files
authored
Merge pull request #738 from nyaruka/urns_refactor
URNs refactor
2 parents 2292ce7 + 1b97543 commit e4ed5ea

40 files changed

+219
-211
lines changed

Diff for: backends/rapidpro/backend_test.go

+28-28
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/nyaruka/courier/test"
2424
"github.com/nyaruka/gocommon/dbutil/assertdb"
2525
"github.com/nyaruka/gocommon/httpx"
26+
"github.com/nyaruka/gocommon/i18n"
2627
"github.com/nyaruka/gocommon/jsonx"
2728
"github.com/nyaruka/gocommon/urns"
2829
"github.com/nyaruka/gocommon/uuids"
@@ -195,7 +196,7 @@ func (ts *BackendTestSuite) TestDeleteMsgByExternalID() {
195196
func (ts *BackendTestSuite) TestContact() {
196197
knChannel := ts.getChannel("KN", "dbc126ed-66bc-4e28-b67b-81dc3327c95d")
197198
clog := courier.NewChannelLog(courier.ChannelLogTypeUnknown, knChannel, nil)
198-
urn, _ := urns.NewTelURNForCountry("12065551518", "US")
199+
urn := urns.URN("tel:+12065551518")
199200

200201
ctx := context.Background()
201202
now := time.Now()
@@ -220,15 +221,15 @@ func (ts *BackendTestSuite) TestContact() {
220221
ts.True(contact2.CreatedOn_.Before(now2))
221222

222223
// load a contact by URN instead (this one is in our testdata)
223-
cURN, _ := urns.NewTelURNForCountry("+12067799192", "US")
224+
cURN := urns.URN("tel:+12067799192")
224225
contact, err = contactForURN(ctx, ts.b, knChannel.OrgID(), knChannel, cURN, nil, "", clog)
225226
ts.NoError(err)
226227
ts.NotNil(contact)
227228

228229
ts.Equal(null.String(""), contact.Name_)
229230
ts.Equal(courier.ContactUUID("a984069d-0008-4d8c-a772-b14a8a6acccc"), contact.UUID_)
230231

231-
urn, _ = urns.NewTelURNForCountry("12065551519", "US")
232+
urn = urns.URN("tel:+12065551519")
232233

233234
// long name are truncated
234235

@@ -243,7 +244,7 @@ func (ts *BackendTestSuite) TestContact() {
243244
func (ts *BackendTestSuite) TestContactRace() {
244245
knChannel := ts.getChannel("KN", "dbc126ed-66bc-4e28-b67b-81dc3327c95d")
245246
clog := courier.NewChannelLog(courier.ChannelLogTypeUnknown, knChannel, nil)
246-
urn, _ := urns.NewTelURNForCountry("12065551518", "US")
247+
urn := urns.URN("tel:+12065551518")
247248

248249
urnSleep = true
249250
defer func() { urnSleep = false }()
@@ -273,8 +274,7 @@ func (ts *BackendTestSuite) TestAddAndRemoveContactURN() {
273274
clog := courier.NewChannelLog(courier.ChannelLogTypeUnknown, knChannel, nil)
274275
ctx := context.Background()
275276

276-
cURN, err := urns.NewTelURNForCountry("+12067799192", "US")
277-
ts.NoError(err)
277+
cURN := urns.URN("tel:+12067799192")
278278

279279
contact, err := contactForURN(ctx, ts.b, knChannel.OrgID_, knChannel, cURN, nil, "", clog)
280280
ts.NoError(err)
@@ -287,7 +287,7 @@ func (ts *BackendTestSuite) TestAddAndRemoveContactURN() {
287287
ts.NoError(err)
288288
ts.Equal(len(contactURNs), 1)
289289

290-
urn, _ := urns.NewTelURNForCountry("12065551518", "US")
290+
urn := urns.URN("tel:+12065551518")
291291
addedURN, err := ts.b.AddURNtoContact(ctx, knChannel, contact, urn, nil)
292292
ts.NoError(err)
293293
ts.NotNil(addedURN)
@@ -314,7 +314,7 @@ func (ts *BackendTestSuite) TestContactURN() {
314314
knChannel := ts.getChannel("KN", "dbc126ed-66bc-4e28-b67b-81dc3327c95d")
315315
twChannel := ts.getChannel("TW", "dbc126ed-66bc-4e28-b67b-81dc3327c96a")
316316
clog := courier.NewChannelLog(courier.ChannelLogTypeUnknown, knChannel, nil)
317-
urn, _ := urns.NewTelURNForCountry("12065551515", "US")
317+
urn := urns.URN("tel:+12065551515")
318318

319319
ctx := context.Background()
320320

@@ -371,12 +371,12 @@ func (ts *BackendTestSuite) TestContactURN() {
371371

372372
// test that we don't use display when looking up URNs
373373
tgChannel := ts.getChannel("TG", "dbc126ed-66bc-4e28-b67b-81dc3327c98a")
374-
tgURN, _ := urns.NewTelegramURN(12345, "")
374+
tgURN := urns.URN("telegram:12345")
375375

376376
tgContact, err := contactForURN(ctx, ts.b, tgChannel.OrgID_, tgChannel, tgURN, nil, "", clog)
377377
ts.NoError(err)
378378

379-
tgURNDisplay, _ := urns.NewTelegramURN(12345, "Jane")
379+
tgURNDisplay := urns.URN("telegram:12345#Jane")
380380
displayContact, err := contactForURN(ctx, ts.b, tgChannel.OrgID_, tgChannel, tgURNDisplay, nil, "", clog)
381381

382382
ts.NoError(err)
@@ -393,7 +393,7 @@ func (ts *BackendTestSuite) TestContactURN() {
393393
ts.Equal(null.String("Jane"), tgContactURN.Display)
394394

395395
// try to create two contacts at the same time in goroutines, this tests our transaction rollbacks
396-
urn2, _ := urns.NewTelURNForCountry("12065551616", "US")
396+
urn2 := urns.URN("tel:+12065551616")
397397
var wait sync.WaitGroup
398398
var contact2, contact3 *Contact
399399
wait.Add(2)
@@ -419,8 +419,8 @@ func (ts *BackendTestSuite) TestContactURN() {
419419
func (ts *BackendTestSuite) TestContactURNPriority() {
420420
knChannel := ts.getChannel("KN", "dbc126ed-66bc-4e28-b67b-81dc3327c95d")
421421
twChannel := ts.getChannel("TW", "dbc126ed-66bc-4e28-b67b-81dc3327c96a")
422-
knURN, _ := urns.NewTelURNForCountry("12065551111", "US")
423-
twURN, _ := urns.NewTelURNForCountry("12065552222", "US")
422+
knURN := urns.URN("tel:+12065551111")
423+
twURN := urns.URN("tel:+12065552222")
424424
clog := courier.NewChannelLog(courier.ChannelLogTypeUnknown, knChannel, nil)
425425

426426
ctx := context.Background()
@@ -627,12 +627,12 @@ func (ts *BackendTestSuite) TestMsgStatus() {
627627

628628
// update URN when the new doesn't exist
629629
tx, _ := ts.b.db.BeginTxx(ctx, nil)
630-
oldURN, _ := urns.NewWhatsAppURN("55988776655")
630+
oldURN := urns.URN("whatsapp:55988776655")
631631
_ = insertContactURN(tx, newContactURN(channel.OrgID_, channel.ID_, NilContactID, oldURN, nil))
632632

633633
ts.NoError(tx.Commit())
634634

635-
newURN, _ := urns.NewWhatsAppURN("5588776655")
635+
newURN := urns.URN("whatsapp:5588776655")
636636
status = ts.b.NewStatusUpdate(channel, courier.MsgID(10000), courier.MsgStatusSent, clog6)
637637
status.SetURNUpdate(oldURN, newURN)
638638

@@ -646,8 +646,8 @@ func (ts *BackendTestSuite) TestMsgStatus() {
646646
ts.NoError(tx.Commit())
647647

648648
// new URN already exits but don't have an associated contact
649-
oldURN, _ = urns.NewWhatsAppURN("55999887766")
650-
newURN, _ = urns.NewWhatsAppURN("5599887766")
649+
oldURN = urns.URN("whatsapp:55999887766")
650+
newURN = urns.URN("whatsapp:5599887766")
651651
tx, _ = ts.b.db.BeginTxx(ctx, nil)
652652
contact, _ := contactForURN(ctx, ts.b, channel.OrgID_, channel, oldURN, nil, "", clog6)
653653
_ = insertContactURN(tx, newContactURN(channel.OrgID_, channel.ID_, NilContactID, newURN, nil))
@@ -668,8 +668,8 @@ func (ts *BackendTestSuite) TestMsgStatus() {
668668
ts.NoError(tx.Commit())
669669

670670
// new URN already exits and have an associated contact
671-
oldURN, _ = urns.NewWhatsAppURN("55988776655")
672-
newURN, _ = urns.NewWhatsAppURN("5588776655")
671+
oldURN = urns.URN("whatsapp:55988776655")
672+
newURN = urns.URN("whatsapp:5588776655")
673673
tx, _ = ts.b.db.BeginTxx(ctx, nil)
674674
_, _ = contactForURN(ctx, ts.b, channel.OrgID_, channel, oldURN, nil, "", clog6)
675675
otherContact, _ := contactForURN(ctx, ts.b, channel.OrgID_, channel, newURN, nil, "", clog6)
@@ -747,8 +747,8 @@ func (ts *BackendTestSuite) TestCheckForDuplicate() {
747747
ctx := context.Background()
748748
knChannel := ts.getChannel("KN", "dbc126ed-66bc-4e28-b67b-81dc3327c95d")
749749
twChannel := ts.getChannel("TW", "dbc126ed-66bc-4e28-b67b-81dc3327c96a")
750-
urn, _ := urns.NewTelURNForCountry("12065551215", knChannel.Country())
751-
urn2, _ := urns.NewTelURNForCountry("12065551277", knChannel.Country())
750+
urn := urns.URN("tel:+12065551215")
751+
urn2 := urns.URN("tel:+12065551277")
752752

753753
createAndWriteMsg := func(ch courier.Channel, u urns.URN, text, extID string) *Msg {
754754
clog := courier.NewChannelLog(courier.ChannelLogTypeUnknown, knChannel, nil)
@@ -900,14 +900,14 @@ func (ts *BackendTestSuite) TestOutgoingQueue() {
900900

901901
func (ts *BackendTestSuite) TestChannel() {
902902
noAddress := ts.getChannel("KN", "dbc126ed-66bc-4e28-b67b-81dc3327c99a")
903-
ts.Equal("US", noAddress.Country())
903+
ts.Equal(i18n.Country("US"), noAddress.Country())
904904
ts.Equal(courier.NilChannelAddress, noAddress.ChannelAddress())
905905

906906
knChannel := ts.getChannel("KN", "dbc126ed-66bc-4e28-b67b-81dc3327c95d")
907907

908908
ts.Equal("2500", knChannel.Address())
909909
ts.Equal(courier.ChannelAddress("2500"), knChannel.ChannelAddress())
910-
ts.Equal("RW", knChannel.Country())
910+
ts.Equal(i18n.Country("RW"), knChannel.Country())
911911
ts.Equal([]courier.ChannelRole{courier.ChannelRoleSend, courier.ChannelRoleReceive}, knChannel.Roles())
912912
ts.True(knChannel.HasRole(courier.ChannelRoleSend))
913913
ts.True(knChannel.HasRole(courier.ChannelRoleReceive))
@@ -1098,7 +1098,7 @@ func (ts *BackendTestSuite) TestWriteMsg() {
10981098
now := time.Now().Round(time.Microsecond).In(time.UTC)
10991099

11001100
// create a new courier msg
1101-
urn, _ := urns.NewTelURNForCountry("12065551212", knChannel.Country())
1101+
urn := urns.URN("tel:+12065551212")
11021102
msg := ts.b.NewIncomingMsg(knChannel, urn, "test123", "ext123", clog).WithReceivedOn(now).WithContactName("test contact").(*Msg)
11031103

11041104
// try to write it to our db
@@ -1197,7 +1197,7 @@ func (ts *BackendTestSuite) TestWriteMsgWithAttachments() {
11971197

11981198
knChannel := ts.getChannel("KN", "dbc126ed-66bc-4e28-b67b-81dc3327c95d")
11991199
clog := courier.NewChannelLog(courier.ChannelLogTypeUnknown, knChannel, nil)
1200-
urn, _ := urns.NewTelURNForCountry("12065551218", knChannel.Country())
1200+
urn := urns.URN("tel:+12065551218")
12011201

12021202
msg := ts.b.NewIncomingMsg(knChannel, urn, "two regular attachments", "", clog).(*Msg)
12031203
msg.WithAttachment("http://example.com/test.jpg")
@@ -1242,7 +1242,7 @@ func (ts *BackendTestSuite) TestPreferredChannelCheckRole() {
12421242
// have to round to microseconds because postgres can't store nanos
12431243
now := time.Now().Round(time.Microsecond).In(time.UTC)
12441244

1245-
urn, _ := urns.NewTelURNForCountry("12065552020", exChannel.Country())
1245+
urn := urns.URN("tel:+12065552020")
12461246
msg := ts.b.NewIncomingMsg(exChannel, urn, "test123", "ext123", clog).WithReceivedOn(now).WithContactName("test contact").(*Msg)
12471247

12481248
// try to write it to our db
@@ -1270,7 +1270,7 @@ func (ts *BackendTestSuite) TestChannelEvent() {
12701270
ctx := context.Background()
12711271
channel := ts.getChannel("KN", "dbc126ed-66bc-4e28-b67b-81dc3327c95d")
12721272
clog := courier.NewChannelLog(courier.ChannelLogTypeUnknown, channel, nil)
1273-
urn, _ := urns.NewTelURNForCountry("12065551616", channel.Country())
1273+
urn := urns.URN("tel:+12065551616")
12741274

12751275
event := ts.b.NewChannelEvent(channel, courier.EventTypeReferral, urn, clog).WithExtra(map[string]string{"ref_id": "12345"}).WithContactName("kermit frog")
12761276
err := ts.b.WriteChannelEvent(ctx, event, clog)
@@ -1319,7 +1319,7 @@ func (ts *BackendTestSuite) TestMailroomEvents() {
13191319

13201320
channel := ts.getChannel("KN", "dbc126ed-66bc-4e28-b67b-81dc3327c95d")
13211321
clog := courier.NewChannelLog(courier.ChannelLogTypeUnknown, channel, nil)
1322-
urn, _ := urns.NewTelURNForCountry("12065551616", channel.Country())
1322+
urn := urns.URN("tel:+12065551616")
13231323

13241324
event := ts.b.NewChannelEvent(channel, courier.EventTypeReferral, urn, clog).
13251325
WithExtra(map[string]string{"ref_id": "12345"}).

Diff for: backends/rapidpro/channel.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88

99
"github.com/lib/pq"
1010
"github.com/nyaruka/courier"
11+
"github.com/nyaruka/gocommon/i18n"
12+
"github.com/nyaruka/gocommon/urns"
1113
"github.com/nyaruka/null/v3"
1214
)
1315

@@ -56,11 +58,11 @@ func (c *Channel) ChannelAddress() courier.ChannelAddress {
5658
}
5759

5860
// Country returns the country code for this channel if any
59-
func (c *Channel) Country() string { return c.Country_.String }
61+
func (c *Channel) Country() i18n.Country { return i18n.Country(c.Country_.String) }
6062

6163
// IsScheme returns whether this channel serves only the passed in scheme
62-
func (c *Channel) IsScheme(scheme string) bool {
63-
return len(c.Schemes_) == 1 && c.Schemes_[0] == scheme
64+
func (c *Channel) IsScheme(scheme *urns.Scheme) bool {
65+
return len(c.Schemes_) == 1 && c.Schemes_[0] == scheme.Prefix
6466
}
6567

6668
// Roles returns the roles of this channel

Diff for: backends/rapidpro/urn.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ func setDefaultURN(db *sqlx.Tx, channel *Channel, contact *Contact, urn urns.URN
145145
existing.Priority = currPriority
146146

147147
// if this is a phone number and we just received a message on a tel scheme, set that as our new preferred channel
148-
if existing.Scheme == urns.TelScheme && scheme == urns.TelScheme && channel.HasRole(courier.ChannelRoleSend) {
148+
if existing.Scheme == urns.Phone.Prefix && scheme == urns.Phone.Prefix && channel.HasRole(courier.ChannelRoleSend) {
149149
existing.ChannelID = channel.ID()
150150
}
151151
currPriority--

Diff for: channel.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"database/sql/driver"
55
"errors"
66

7+
"github.com/nyaruka/gocommon/i18n"
8+
"github.com/nyaruka/gocommon/urns"
79
"github.com/nyaruka/gocommon/uuids"
810
"github.com/nyaruka/null/v3"
911
)
@@ -123,14 +125,14 @@ type Channel interface {
123125
Name() string
124126
ChannelType() ChannelType
125127
Schemes() []string
126-
Country() string
128+
Country() i18n.Country
127129
Address() string
128130
ChannelAddress() ChannelAddress
129131

130132
Roles() []ChannelRole
131133

132134
// is this channel for the passed in scheme (and only that scheme)
133-
IsScheme(string) bool
135+
IsScheme(*urns.Scheme) bool
134136

135137
// CallbackDomain returns the domain that should be used for any callbacks the channel registers
136138
CallbackDomain(fallbackDomain string) string

Diff for: go.mod

+10-10
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ go 1.22
44

55
require (
66
github.com/antchfx/xmlquery v1.4.0
7-
github.com/aws/aws-sdk-go v1.51.25
7+
github.com/aws/aws-sdk-go v1.52.3
88
github.com/buger/jsonparser v1.1.1
99
github.com/dghubble/oauth1 v0.7.3
1010
github.com/getsentry/sentry-go v0.27.0
@@ -13,18 +13,18 @@ require (
1313
github.com/gomodule/redigo v1.9.2
1414
github.com/gorilla/schema v1.3.0
1515
github.com/h2non/filetype v1.1.3
16-
github.com/jmoiron/sqlx v1.3.5
16+
github.com/jmoiron/sqlx v1.4.0
1717
github.com/lib/pq v1.10.9
1818
github.com/nyaruka/ezconf v0.3.0
19-
github.com/nyaruka/gocommon v1.53.2
19+
github.com/nyaruka/gocommon v1.54.2
2020
github.com/nyaruka/null/v3 v3.0.0
2121
github.com/nyaruka/redisx v0.8.0
2222
github.com/patrickmn/go-cache v2.1.0+incompatible
2323
github.com/pkg/errors v0.9.1
2424
github.com/samber/slog-multi v1.0.2
2525
github.com/samber/slog-sentry v1.2.2
2626
github.com/stretchr/testify v1.9.0
27-
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f
27+
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842
2828
golang.org/x/mod v0.17.0
2929
gopkg.in/go-playground/validator.v9 v9.31.0
3030
)
@@ -36,7 +36,7 @@ require (
3636
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
3737
github.com/go-playground/locales v0.14.1 // indirect
3838
github.com/go-playground/universal-translator v0.18.1 // indirect
39-
github.com/go-playground/validator/v10 v10.19.0 // indirect
39+
github.com/go-playground/validator/v10 v10.20.0 // indirect
4040
github.com/gofrs/uuid v4.4.0+incompatible // indirect
4141
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
4242
github.com/gorilla/websocket v1.5.1 // indirect
@@ -52,12 +52,12 @@ require (
5252
github.com/pmezard/go-difflib v1.0.0 // indirect
5353
github.com/samber/lo v1.39.0 // indirect
5454
github.com/shopspring/decimal v1.4.0 // indirect
55-
golang.org/x/crypto v0.22.0 // indirect
56-
golang.org/x/net v0.24.0 // indirect
55+
golang.org/x/crypto v0.23.0 // indirect
56+
golang.org/x/net v0.25.0 // indirect
5757
golang.org/x/sync v0.7.0 // indirect
58-
golang.org/x/sys v0.19.0 // indirect
59-
golang.org/x/text v0.14.0 // indirect
60-
google.golang.org/protobuf v1.33.0 // indirect
58+
golang.org/x/sys v0.20.0 // indirect
59+
golang.org/x/text v0.15.0 // indirect
60+
google.golang.org/protobuf v1.34.1 // indirect
6161
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
6262
gopkg.in/yaml.v3 v3.0.1 // indirect
6363
)

0 commit comments

Comments
 (0)