Skip to content

Commit

Permalink
Merge c59625e into cd8c402
Browse files Browse the repository at this point in the history
  • Loading branch information
nicpottier committed May 12, 2017
2 parents cd8c402 + c59625e commit b123837
Show file tree
Hide file tree
Showing 19 changed files with 637 additions and 390 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ To run the tests you need to create the test database:
$ createdb courier_test
$ createuser -P -E courier
$ psql -d courier_test -f schema.sql
$ psql -d courier_test -f testdata.sql
$ psql -d courier_test -c "GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO courier;"
$ psql -d courier_test -c "GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO courier;"
```
Expand Down
41 changes: 14 additions & 27 deletions channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@ package courier

import (
"database/sql"
"encoding/json"
"errors"
"log"
"strings"
"sync"
"time"

"github.com/nyaruka/courier/utils"
uuid "github.com/satori/go.uuid"
)

Expand Down Expand Up @@ -112,9 +111,6 @@ func loadChannelFromDB(s *server, channel *Channel, channelType ChannelType, uui
// select just the fields we need
err := s.db.Get(channel, lookupChannelFromUUIDSQL, channelType, uuid)

// parse our config
channel.parseConfig()

// we didn't find a match
if err == sql.ErrNoRows {
return ErrChannelNotFound
Expand Down Expand Up @@ -181,34 +177,25 @@ const localTTL = 60

// Channel is our struct for json and db representations of our channel
type Channel struct {
OrgID OrgID `json:"org_id" db:"org_id"`
ID ChannelID `json:"id" db:"id"`
UUID ChannelUUID `json:"uuid" db:"uuid"`
ChannelType ChannelType `json:"channel_type" db:"channel_type"`
Address string `json:"address" db:"address"`
Country string `json:"country" db:"country"`
Config string `json:"config" db:"config"`

expiration time.Time
config map[string]string
OrgID OrgID `json:"org_id" db:"org_id"`
ID ChannelID `json:"id" db:"id"`
UUID ChannelUUID `json:"uuid" db:"uuid"`
ChannelType ChannelType `json:"channel_type" db:"channel_type"`
Address sql.NullString `json:"address" db:"address"`
Country sql.NullString `json:"country" db:"country"`
Config utils.NullDict `json:"config" db:"config"`
expiration time.Time
}

// GetConfig returns the value of the passed in config key
func (c *Channel) GetConfig(key string) string { return c.config[key] }

func (c *Channel) parseConfig() {
c.config = make(map[string]string)

if c.Config != "" {
err := json.Unmarshal([]byte(c.Config), &c.config)
if err != nil {
log.Printf("ERROR parsing channel config '%s': %s", c.Config, err)
}
func (c *Channel) GetConfig(key string) string {
if c.Config.Valid {
return c.Config.Dict[key]
}
return ""
}

// Constructor to create a new empty channel
func newChannel(channelType ChannelType, uuid ChannelUUID) *Channel {
config := make(map[string]string)
return &Channel{ChannelType: channelType, UUID: uuid, config: config}
return &Channel{ChannelType: channelType, UUID: uuid}
}
34 changes: 20 additions & 14 deletions contact.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,19 @@ type ContactID struct {
// NilContactID represents our nil value for ContactID
var NilContactID = ContactID{sql.NullInt64{Int64: 0, Valid: false}}

// ContactUUID is our typing of a contact's UUID
type ContactUUID struct {
uuid.UUID
}

// Contact is our struct for a contact in the database
type Contact struct {
Org OrgID `db:"org_id"`
ID ContactID `db:"id"`
UUID string `db:"uuid"`
Name string `db:"name"`
Org OrgID `db:"org_id"`
ID ContactID `db:"id"`
UUID ContactUUID `db:"uuid"`
Name string `db:"name"`

URN ContactURNID `db:"urn_id"`
URNID ContactURNID `db:"urn_id"`

CreatedOn time.Time `db:"created_on"`
ModifiedOn time.Time `db:"modified_on"`
Expand All @@ -33,12 +38,6 @@ type Contact struct {
ModifiedBy int `db:"modified_by_id"`
}

const lookupContactFromURNSQL = `
SELECT c.org_id, c.id, c.uuid, c.name, u.id as "urn_id"
FROM contacts_contact AS c, contacts_contacturn AS u
WHERE u.urn = $1 AND u.contact_id = c.id AND u.org_id = $2 AND c.is_active = TRUE AND c.is_test = FALSE
`

const insertContactSQL = `
INSERT INTO contacts_contact(org_id, is_active, is_blocked, is_test, is_stopped, uuid, created_on, modified_on, created_by_id, modified_by_id, name)
VALUES(:org_id, TRUE, FALSE, FALSE, FALSE, :uuid, :created_on, :modified_on, :created_by_id, :modified_by_id, :name)
Expand All @@ -51,12 +50,19 @@ func insertContact(db *sqlx.DB, contact *Contact) error {
if err != nil {
return err
}
defer rows.Close()
if rows.Next() {
err = rows.Scan(&contact.ID)
}
return err
}

const lookupContactFromURNSQL = `
SELECT c.org_id, c.id, c.uuid, c.name, u.id as "urn_id"
FROM contacts_contact AS c, contacts_contacturn AS u
WHERE u.urn = $1 AND u.contact_id = c.id AND u.org_id = $2 AND c.is_active = TRUE AND c.is_test = FALSE
`

// contactForURN first tries to look up a contact for the passed in URN, if not finding one then creating one
func contactForURN(db *sqlx.DB, org OrgID, channel ChannelID, urn URN, name string) (*Contact, error) {
// try to look up our contact by URN
Expand All @@ -73,7 +79,7 @@ func contactForURN(db *sqlx.DB, org OrgID, channel ChannelID, urn URN, name stri

// didn't find it, we need to create it instead
contact.Org = org
contact.UUID = uuid.NewV4().String()
contact.UUID = ContactUUID{uuid.NewV4()}
contact.Name = name

// TODO: Set these to a system user
Expand All @@ -86,14 +92,14 @@ func contactForURN(db *sqlx.DB, org OrgID, channel ChannelID, urn URN, name stri
return nil, err
}

// now find our URN
// associate our URN
contactURN, err := ContactURNForURN(db, org, channel, contact.ID, urn)
if err != nil {
return nil, err
}

// save this URN on our contact
contact.URN = contactURN.ID
contact.URNID = contactURN.ID

// and return it
return &contact, err
Expand Down
4 changes: 2 additions & 2 deletions handlers/africastalking/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,10 @@ func (h *handler) ReceiveMessage(channel *courier.Channel, w http.ResponseWriter
}

// create our URN
urn := courier.NewTelURN(atMsg.From, channel.Country)
urn := courier.NewTelURNForChannel(atMsg.From, channel)

// build our msg
msg := courier.NewMsg(channel, urn, atMsg.Text).WithExternalID(atMsg.ID).WithReceivedOn(date)
msg := courier.NewIncomingMsg(channel, urn, atMsg.Text).WithExternalID(atMsg.ID).WithReceivedOn(date)
defer msg.Release()

// and finally queue our message
Expand Down
4 changes: 2 additions & 2 deletions handlers/blackmyna/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ func (h *bmHandler) ReceiveMessage(channel *courier.Channel, w http.ResponseWrit
}

// create our URN
urn := courier.NewTelURN(bmMsg.From, channel.Country)
urn := courier.NewTelURNForChannel(bmMsg.From, channel)

// build our msg
msg := courier.NewMsg(channel, urn, bmMsg.Text)
msg := courier.NewIncomingMsg(channel, urn, bmMsg.Text)
defer msg.Release()

// and finally queue our message
Expand Down
14 changes: 7 additions & 7 deletions handlers/kannel/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,13 @@ func (h *kannelHandler) ReceiveMessage(channel *courier.Channel, w http.Response
}

// create our date from the timestamp
date := time.Unix(kannelMsg.Timestamp, 0).UTC()
date := time.Unix(kannelMsg.TS, 0).UTC()

// create our URN
urn := courier.NewTelURN(kannelMsg.Sender, channel.Country)
urn := courier.NewTelURNForChannel(kannelMsg.Sender, channel)

// build our msg
msg := courier.NewMsg(channel, urn, kannelMsg.Message).WithExternalID(fmt.Sprintf("%d", kannelMsg.ID)).WithReceivedOn(date)
msg := courier.NewIncomingMsg(channel, urn, kannelMsg.Message).WithExternalID(fmt.Sprintf("%d", kannelMsg.ID)).WithReceivedOn(date)
defer msg.Release()

// and finally queue our message
Expand All @@ -63,10 +63,10 @@ func (h *kannelHandler) ReceiveMessage(channel *courier.Channel, w http.Response
}

type kannelMessage struct {
ID int64 `validate:"required" name:"id"`
Timestamp int64 `validate:"required" name:"ts"`
Message string `validate:"required" name:"message"`
Sender string `validate:"required" name:"sender"`
ID int64 `validate:"required" name:"id"`
TS int64 `validate:"required" name:"ts"`
Message string `validate:"required" name:"message"`
Sender string `validate:"required" name:"sender"`
}

var kannelStatusMapping = map[int]courier.MsgStatus{
Expand Down
2 changes: 1 addition & 1 deletion handlers/telegram/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func (h *telegramHandler) ReceiveMessage(channel *courier.Channel, w http.Respon
}

// build our msg
msg := courier.NewMsg(channel, urn, text).WithReceivedOn(date).WithExternalID(fmt.Sprintf("%d", te.Message.MessageID)).WithContactName(name)
msg := courier.NewIncomingMsg(channel, urn, text).WithReceivedOn(date).WithExternalID(fmt.Sprintf("%d", te.Message.MessageID)).WithContactName(name)
defer msg.Release()

if mediaURL != "" {
Expand Down
4 changes: 2 additions & 2 deletions handlers/twilio/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,15 @@ func (h *twHandler) ReceiveMessage(channel *courier.Channel, w http.ResponseWrit
}

// create our URN
urn := courier.NewTelURN(twMsg.From, twMsg.FromCountry)
urn := courier.NewTelURNForCountry(twMsg.From, twMsg.FromCountry)

if twMsg.Body != "" {
// Twilio sometimes sends concatenated sms as base64 encoded MMS
twMsg.Body = handlers.DecodePossibleBase64(twMsg.Body)
}

// build our msg
msg := courier.NewMsg(channel, urn, twMsg.Body).WithExternalID(twMsg.MessageSID)
msg := courier.NewIncomingMsg(channel, urn, twMsg.Body).WithExternalID(twMsg.MessageSID)
defer msg.Release()

// process any attached media
Expand Down
Loading

0 comments on commit b123837

Please sign in to comment.