diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 30f413d..17701df 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,11 +14,6 @@ repos: stages: [commit] - id: go-mod-tidy stages: [commit] - - repo: https://github.com/Jerome1337/pre-commit-swaggo-swag - rev: master - hooks: - - id: swag - stages: [commit] - repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook rev: v3.0.0 hooks: diff --git a/broker/apn.go b/broker/apn.go deleted file mode 100644 index 6e8a015..0000000 --- a/broker/apn.go +++ /dev/null @@ -1,26 +0,0 @@ -package broker - -import ( - "log" - - "github.com/streadway/amqp" -) - -var apnPushQueue *amqp.Queue - -func declareAPNPushQueue() { - var err error - - if apnPushQueue, err = declareQueue("notifications.push.apn"); err != nil { - log.Fatalln("Failed to declare APN push notifications queue:", err) - } -} - -// PublishToAPNPushQueue publish a message to the notification APN queue -func PublishToAPNPushQueue(body []byte) { - publishToQueue(apnPushQueue, amqp.Publishing{ - DeliveryMode: amqp.Persistent, - ContentType: "application/json", - Body: body, - }) -} diff --git a/broker/consumer.go b/broker/consumer.go index 607b25d..7a3edff 100644 --- a/broker/consumer.go +++ b/broker/consumer.go @@ -1,19 +1,23 @@ package broker -import "log" +import ( + "encoding/json" + "log" + + "github.com/qimpl/notifications/models" + "github.com/qimpl/notifications/services" +) // InitConsumer connects to RabbitMQ, declares and consumes queues func InitConsumer() { Connect() declareEmailQueue() - declareAPNPushQueue() - declareFCMPushQueue() + declarePushQueue() forever := make(chan bool) consumeEmailQueue() - consumeAPNPushQueue() - consumeFCMPushQueue() + consumePushQueue() log.Println("Waiting messages") <-forever @@ -42,9 +46,9 @@ func consumeEmailQueue() { } -func consumeAPNPushQueue() { +func consumePushQueue() { msgs, err := ch.Consume( - apnPushQueue.Name, + pushQueue.Name, "APN Push Notifications", false, false, @@ -53,34 +57,14 @@ func consumeAPNPushQueue() { nil, ) if err != nil { - log.Println("Failed to register APN Push notifications queue consumer:", err) - } - - go func() { - for d := range msgs { - log.Printf("Message APN: %s", d.Body) - d.Ack(false) - } - }() -} - -func consumeFCMPushQueue() { - msgs, err := ch.Consume( - fcmPushQueue.Name, - "FCM Push Notifications", - false, - false, - false, - false, - nil, - ) - if err != nil { - log.Println("Failed to register FCM Push notifications queue consumer:", err) + log.Println("Failed to register Push notifications queue consumer:", err) } go func() { for d := range msgs { - log.Printf("Message FCM: %s", d.Body) + notification := models.PushNotification{} + json.Unmarshal(d.Body, ¬ification) + services.PushNotification(¬ification) d.Ack(false) } }() diff --git a/broker/fcm.go b/broker/fcm.go deleted file mode 100644 index 0e1a29a..0000000 --- a/broker/fcm.go +++ /dev/null @@ -1,26 +0,0 @@ -package broker - -import ( - "log" - - "github.com/streadway/amqp" -) - -var fcmPushQueue *amqp.Queue - -func declareFCMPushQueue() { - var err error - - if fcmPushQueue, err = declareQueue("notifications.push.fcm"); err != nil { - log.Fatalln("Failed to declare FCM push notifications queue:", err) - } -} - -// PublishToFCMPushQueue publish a message to the notification FCM queue -func PublishToFCMPushQueue(body []byte) { - publishToQueue(fcmPushQueue, amqp.Publishing{ - DeliveryMode: amqp.Persistent, - ContentType: "application/json", - Body: body, - }) -} diff --git a/broker/producer.go b/broker/producer.go index 12958e2..33bedb8 100644 --- a/broker/producer.go +++ b/broker/producer.go @@ -7,8 +7,7 @@ func InitProducer() { Connect() declareEmailQueue() - declareAPNPushQueue() - declareFCMPushQueue() + declarePushQueue() } func declareQueue(name string) (*amqp.Queue, error) { diff --git a/broker/push.go b/broker/push.go new file mode 100644 index 0000000..b973aee --- /dev/null +++ b/broker/push.go @@ -0,0 +1,29 @@ +package broker + +import ( + "log" + + "github.com/streadway/amqp" +) + +var pushQueue *amqp.Queue + +func declarePushQueue() { + var err error + + if pushQueue, err = declareQueue("notifications.push"); err != nil { + log.Fatalln("Failed to declare Push notifications queue:", err) + } +} + +// PublishToPushQueue publish a message to the push notification queue +func PublishToPushQueue(body []byte) { + publishToQueue( + pushQueue, + amqp.Publishing{ + DeliveryMode: amqp.Persistent, + ContentType: "application/json", + Body: body, + }, + ) +} diff --git a/docs/docs.go b/docs/docs.go index 5252c70..8944b99 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -65,14 +65,14 @@ var doc = `{ "models.Notification": { "type": "object", "properties": { - "device_id": { - "type": "string", - "example": "00000-00000-00000-00000" - }, "email": { "type": "string", "example": "john.doe@foo.com" }, + "expo_push_token": { + "type": "string", + "example": "ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]" + }, "message": { "type": "string", "example": "Hello my friend" @@ -88,7 +88,7 @@ var doc = `{ }, "example": [ "[\"email\"", - " \"apn\"]" + " \"push\"]" ] } } diff --git a/docs/swagger.json b/docs/swagger.json index 6c9429b..ed594f6 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -48,14 +48,14 @@ "models.Notification": { "type": "object", "properties": { - "device_id": { - "type": "string", - "example": "00000-00000-00000-00000" - }, "email": { "type": "string", "example": "john.doe@foo.com" }, + "expo_push_token": { + "type": "string", + "example": "ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]" + }, "message": { "type": "string", "example": "Hello my friend" @@ -71,7 +71,7 @@ }, "example": [ "[\"email\"", - " \"apn\"]" + " \"push\"]" ] } } diff --git a/docs/swagger.yaml b/docs/swagger.yaml index b99ee89..19a450f 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -2,12 +2,12 @@ basePath: /api/v1 definitions: models.Notification: properties: - device_id: - example: 00000-00000-00000-00000 - type: string email: example: john.doe@foo.com type: string + expo_push_token: + example: ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx] + type: string message: example: Hello my friend type: string @@ -17,7 +17,7 @@ definitions: type: example: - '["email"' - - ' "apn"]' + - ' "push"]' items: type: string type: array diff --git a/go.mod b/go.mod index 3e39578..ced727b 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/joho/godotenv v1.3.0 github.com/mailru/easyjson v0.7.6 // indirect github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect + github.com/oliveroneill/exponent-server-sdk-golang v0.0.0-20200627013714-266e8e6ee5ad github.com/rs/cors v1.7.0 github.com/streadway/amqp v1.0.0 github.com/stretchr/testify v1.6.1 // indirect diff --git a/go.sum b/go.sum index 15574d9..7ea07ab 100644 --- a/go.sum +++ b/go.sum @@ -79,6 +79,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/oliveroneill/exponent-server-sdk-golang v0.0.0-20200627013714-266e8e6ee5ad h1:HsCb37kk4nKk5o/Fx9L4YVN1vb6MQf4dXOamz0nhYWg= +github.com/oliveroneill/exponent-server-sdk-golang v0.0.0-20200627013714-266e8e6ee5ad/go.mod h1:Isv/48UnAjtxS8FD80Bito3ZJqZRyIMxKARIEITfW4k= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= diff --git a/handlers/notification.go b/handlers/notification.go index 580a9ad..51b54d8 100644 --- a/handlers/notification.go +++ b/handlers/notification.go @@ -44,24 +44,16 @@ func AddNotification(w http.ResponseWriter, r *http.Request) { }) broker.PublishToEmailQueue(emailNotification) - case models.APN: - APNNotification, _ := json.Marshal(models.PushNotification{ - Type: models.APN, - Title: notification.Title, - Message: notification.Message, - DeviceID: notification.DeviceID, + case models.Push: + PushNotification, _ := json.Marshal(models.PushNotification{ + Type: models.Push, + Title: notification.Title, + Message: notification.Message, + ExpoPushToken: notification.ExpoPushToken, }) - broker.PublishToAPNPushQueue(APNNotification) - case models.FCM: - FCMNotification, _ := json.Marshal(models.PushNotification{ - Type: models.FCM, - Title: notification.Title, - Message: notification.Message, - DeviceID: notification.DeviceID, - }) + broker.PublishToPushQueue(PushNotification) - broker.PublishToFCMPushQueue(FCMNotification) default: continue } diff --git a/models/notification.go b/models/notification.go index 66529d7..a37c449 100644 --- a/models/notification.go +++ b/models/notification.go @@ -6,19 +6,17 @@ type NotificationType string const ( // Email notification type Email NotificationType = "email" - // APN Push notification type - APN NotificationType = "apn" - // FCM Push notification type - FCM NotificationType = "fcm" + // Push notification type + Push NotificationType = "push" ) // Notification structure used inside the POST method handler type Notification struct { - Type []NotificationType `json:"type" example:"[\"email\", \"apn\"]"` - Title string `json:"title" example:"My Notification"` - Message string `json:"message" example:"Hello my friend"` - DeviceID string `json:"device_id" example:"00000-00000-00000-00000"` - Email string `json:"email" example:"john.doe@foo.com"` + Type []NotificationType `json:"type" example:"[\"email\", \"push\"]"` + Title string `json:"title" example:"My Notification"` + Message string `json:"message" example:"Hello my friend"` + ExpoPushToken string `json:"expo_push_token" example:"ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]"` + Email string `json:"email" example:"john.doe@foo.com"` } // EmailNotification structure used when publishing a new message inside the "email notifications" RabbitMQ queue @@ -31,8 +29,8 @@ type EmailNotification struct { // PushNotification structure used when publishing a new message inside one of the "push notifications" RabbitMQ queue type PushNotification struct { - Type NotificationType `json:"type" example:"apn"` - Title string `json:"title" example:"My Notification"` - Message string `json:"message" example:"Hello my friend"` - DeviceID string `json:"device_id" example:"00000-00000-00000-00000"` + Type NotificationType `json:"type" example:"push"` + Title string `json:"title" example:"My Notification"` + Message string `json:"message" example:"Hello my friend"` + ExpoPushToken string `json:"expo_push_token" example:"ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]"` } diff --git a/services/push_notifications.go b/services/push_notifications.go new file mode 100644 index 0000000..f7e9884 --- /dev/null +++ b/services/push_notifications.go @@ -0,0 +1,41 @@ +package services + +import ( + "fmt" + "log" + + "github.com/qimpl/notifications/models" + + expo "github.com/oliveroneill/exponent-server-sdk-golang/sdk" +) + +// PushNotification send a push notification to given Expo push tokens +func PushNotification(notification *models.PushNotification) { + expoPushToken, err := expo.NewExponentPushToken(notification.ExpoPushToken) + + if err != nil { + log.Println("ERROR", err) + } + + client := expo.NewPushClient(nil) + + response, err := client.Publish( + &expo.PushMessage{ + To: []expo.ExponentPushToken{expoPushToken}, + Body: notification.Message, + Data: map[string]string{"withSome": "data"}, + Sound: "default", + Title: notification.Title, + Priority: expo.DefaultPriority, + }, + ) + + if err != nil { + log.Println("PUBLISH ERROR", err) + return + } + + if response.ValidateResponse() != nil { + fmt.Println(response.PushMessage.To, "failed") + } +}