Skip to content

Commit af0995f

Browse files
committed
Add FCM Token
1 parent be65389 commit af0995f

17 files changed

Lines changed: 240 additions & 36 deletions

android/app/src/main/java/com/httpsms/FirebaseMessagingService.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ class MyFirebaseMessagingService : FirebaseMessagingService() {
7171
return Result.failure()
7272
}
7373

74+
Receiver.registerReceivers(applicationContext)
75+
7476
val owner = Settings.getOwner(applicationContext) ?: return Result.failure()
7577
val message = getMessage(applicationContext, owner) ?: return Result.failure()
7678

android/app/src/main/java/com/httpsms/MainActivity.kt

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import android.app.NotificationChannel
77
import android.app.NotificationManager
88
import android.content.Context
99
import android.content.Intent
10-
import android.content.IntentFilter
1110
import android.content.pm.PackageManager
1211
import android.os.Bundle
1312
import android.telephony.PhoneNumberUtils
@@ -41,7 +40,7 @@ class MainActivity : AppCompatActivity() {
4140
setActiveStatus(this)
4241
registerListeners()
4342
refreshToken(this)
44-
registerReceivers()
43+
Receiver.registerReceivers(this)
4544
}
4645

4746
override fun onResume() {
@@ -51,18 +50,6 @@ class MainActivity : AppCompatActivity() {
5150
refreshToken(this)
5251
}
5352

54-
private fun registerReceivers() {
55-
this.registerReceiver(
56-
SentReceiver(),
57-
IntentFilter(SmsManagerService.ACTION_SMS_SENT)
58-
)
59-
60-
this.registerReceiver(
61-
DeliveredReceiver(),
62-
IntentFilter(SmsManagerService.ACTION_SMS_DELIVERED)
63-
)
64-
}
65-
6653
private fun refreshToken(context: Context) {
6754
if(!Settings.isLoggedIn(context)) {
6855
Timber.w("cannot refresh token because owner is not logged in")

android/app/src/main/java/com/httpsms/Receiver.kt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package com.httpsms
22

33
import android.content.Context
4+
import android.content.IntentFilter
45
import timber.log.Timber
56

7+
68
object Receiver {
79
fun isValid(context: Context, messageId: String?): Boolean {
810
if (messageId == null) {
@@ -21,4 +23,28 @@ object Receiver {
2123
}
2224
return true
2325
}
26+
27+
fun registerReceivers(context: Context) {
28+
try {
29+
context.unregisterReceiver(SentReceiver())
30+
} catch (error: IllegalArgumentException ) {
31+
Timber.e(error)
32+
}
33+
34+
context.registerReceiver(
35+
SentReceiver(),
36+
IntentFilter(SmsManagerService.ACTION_SMS_SENT)
37+
)
38+
39+
try {
40+
context.unregisterReceiver(DeliveredReceiver())
41+
} catch (error: IllegalArgumentException ) {
42+
Timber.e(error)
43+
}
44+
45+
context.registerReceiver(
46+
DeliveredReceiver(),
47+
IntentFilter(SmsManagerService.ACTION_SMS_DELIVERED)
48+
)
49+
}
2450
}

api/pkg/di/container.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
"os"
99
"time"
1010

11+
"firebase.google.com/go/messaging"
12+
1113
firebase "firebase.google.com/go"
1214
"firebase.google.com/go/auth"
1315
"github.com/NdoleStudio/http-sms-manager/pkg/middlewares"
@@ -62,6 +64,8 @@ func NewContainer(projectID string) (container *Container) {
6264

6365
container.RegisterPhoneRoutes()
6466

67+
container.RegisterNotificationListeners()
68+
6569
// this has to be last since it registers the /* route
6670
container.RegisterSwaggerRoutes()
6771

@@ -185,6 +189,17 @@ func (container *Container) FirebaseAuthClient() (client *auth.Client) {
185189
return authClient
186190
}
187191

192+
// FirebaseMessagingClient creates a new instance of messaging.Client
193+
func (container *Container) FirebaseMessagingClient() (client *messaging.Client) {
194+
container.logger.Debug(fmt.Sprintf("creating %T", client))
195+
messagingClient, err := container.FirebaseApp().Messaging(context.Background())
196+
if err != nil {
197+
msg := "cannot initialize firebase messaging client"
198+
container.logger.Fatal(stacktrace.Propagate(err, msg))
199+
}
200+
return messagingClient
201+
}
202+
188203
// FirebaseCredentials returns firebase credentials as bytes.
189204
func (container *Container) FirebaseCredentials() []byte {
190205
container.logger.Debug("creating firebase credentials")
@@ -437,6 +452,20 @@ func (container *Container) RegisterMessageThreadListeners() {
437452
}
438453
}
439454

455+
// RegisterNotificationListeners registers event listeners for listeners.NotificationListener
456+
func (container *Container) RegisterNotificationListeners() {
457+
container.logger.Debug(fmt.Sprintf("registering listners for %T", listeners.NotificationListener{}))
458+
_, routes := listeners.NewNotificationListener(
459+
container.Logger(),
460+
container.Tracer(),
461+
container.NotificationService(),
462+
)
463+
464+
for event, handler := range routes {
465+
container.EventDispatcher().Subscribe(event, handler)
466+
}
467+
}
468+
440469
// RegisterHeartbeatListeners registers event listeners for listeners.HeartbeatListener
441470
func (container *Container) RegisterHeartbeatListeners() {
442471
container.logger.Debug(fmt.Sprintf("registering listners for %T", listeners.HeartbeatListener{}))
@@ -462,6 +491,17 @@ func (container *Container) MessageService() (service *services.MessageService)
462491
)
463492
}
464493

494+
// NotificationService creates a new instance of services.NotificationService
495+
func (container *Container) NotificationService() (service *services.NotificationService) {
496+
container.logger.Debug(fmt.Sprintf("creating %T", service))
497+
return services.NewNotificationService(
498+
container.Logger(),
499+
container.Tracer(),
500+
container.FirebaseMessagingClient(),
501+
container.PhoneRepository(),
502+
)
503+
}
504+
465505
// RegisterMessageRoutes registers routes for the /messages prefix
466506
func (container *Container) RegisterMessageRoutes() {
467507
container.logger.Debug(fmt.Sprintf("registering %T routes", &handlers.MessageHandler{}))

api/pkg/events/message_api_sent_event.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package events
33
import (
44
"time"
55

6+
"github.com/NdoleStudio/http-sms-manager/pkg/entities"
7+
68
"github.com/google/uuid"
79
)
810

@@ -11,9 +13,10 @@ const EventTypeMessageAPISent = "message.api.sent"
1113

1214
// MessageAPISentPayload is the payload of the EventTypeMessageSent event
1315
type MessageAPISentPayload struct {
14-
ID uuid.UUID `json:"id"`
15-
Owner string `json:"owner"`
16-
Contact string `json:"contact"`
17-
RequestReceivedAt time.Time `json:"request_received_at"`
18-
Content string `json:"content"`
16+
ID uuid.UUID `json:"id"`
17+
UserID entities.UserID `json:"userID"`
18+
Owner string `json:"owner"`
19+
Contact string `json:"contact"`
20+
RequestReceivedAt time.Time `json:"request_received_at"`
21+
Content string `json:"content"`
1922
}

api/pkg/handlers/heartbeat_handler.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package handlers
33
import (
44
"fmt"
55

6-
"github.com/NdoleStudio/http-sms-manager/pkg/requests"
76
"github.com/NdoleStudio/http-sms-manager/pkg/services"
87
"github.com/NdoleStudio/http-sms-manager/pkg/telemetry"
98
"github.com/NdoleStudio/http-sms-manager/pkg/validators"
@@ -64,7 +63,7 @@ func (h *HeartbeatHandler) Index(c *fiber.Ctx) error {
6463

6564
ctxLogger := h.tracer.CtxLogger(h.logger, span)
6665

67-
var request requests.HeartbeatIndex
66+
var request services.HeartbeatIndex
6867
if err := c.QueryParser(&request); err != nil {
6968
msg := fmt.Sprintf("cannot marshall params [%s] into %T", c.OriginalURL(), request)
7069
ctxLogger.Warn(stacktrace.Propagate(err, msg))

api/pkg/handlers/message_handler.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ func (h *MessageHandler) PostSend(c *fiber.Ctx) error {
8383
return h.responseUnprocessableEntity(c, errors, "validation errors while sending message")
8484
}
8585

86-
message, err := h.service.SendMessage(ctx, request.ToMessageSendParams(c.OriginalURL()))
86+
message, err := h.service.SendMessage(ctx, request.ToMessageSendParams(h.userIDFomContext(c), c.OriginalURL()))
8787
if err != nil {
8888
msg := fmt.Sprintf("cannot send message with paylod [%s]", c.Body())
8989
ctxLogger.Error(stacktrace.Propagate(err, msg))
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package listeners
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/NdoleStudio/http-sms-manager/pkg/events"
8+
"github.com/NdoleStudio/http-sms-manager/pkg/services"
9+
"github.com/NdoleStudio/http-sms-manager/pkg/telemetry"
10+
cloudevents "github.com/cloudevents/sdk-go/v2"
11+
"github.com/palantir/stacktrace"
12+
)
13+
14+
// NotificationListener handles cloud events which sends notifications
15+
type NotificationListener struct {
16+
logger telemetry.Logger
17+
tracer telemetry.Tracer
18+
service *services.NotificationService
19+
}
20+
21+
// NewNotificationListener creates a new instance of NotificationListener
22+
func NewNotificationListener(
23+
logger telemetry.Logger,
24+
tracer telemetry.Tracer,
25+
service *services.NotificationService,
26+
) (l *NotificationListener, routes map[string]events.EventListener) {
27+
l = &NotificationListener{
28+
logger: logger.WithService(fmt.Sprintf("%T", l)),
29+
tracer: tracer,
30+
service: service,
31+
}
32+
33+
return l, map[string]events.EventListener{
34+
events.EventTypeMessageAPISent: l.onMessageAPISent,
35+
}
36+
}
37+
38+
// onMessageAPISent handles the events.EventTypeHeartbeatPhoneOutstanding event
39+
func (listener *NotificationListener) onMessageAPISent(ctx context.Context, event cloudevents.Event) error {
40+
ctx, span := listener.tracer.Start(ctx)
41+
defer span.End()
42+
43+
var payload events.MessageAPISentPayload
44+
if err := event.DataAs(&payload); err != nil {
45+
msg := fmt.Sprintf("cannot decode [%s] into [%T]", event.Data(), payload)
46+
return listener.tracer.WrapErrorSpan(span, stacktrace.Propagate(err, msg))
47+
}
48+
49+
sentParams := &services.NotificationMessageSentParams{
50+
UserID: payload.UserID,
51+
Owner: payload.Owner,
52+
MessageID: payload.ID,
53+
}
54+
55+
if err := listener.service.MessageSent(ctx, sentParams); err != nil {
56+
msg := fmt.Sprintf("cannot send notification with params [%+#v] for event with ID [%s]", sentParams, event.ID())
57+
return listener.tracer.WrapErrorSpan(span, stacktrace.Propagate(err, msg))
58+
}
59+
60+
return nil
61+
}

api/pkg/repositories/phone_repository.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,7 @@ type PhoneRepository interface {
1313

1414
// Index entities.Phone of a user
1515
Index(ctx context.Context, userID entities.UserID, params IndexParams) (*[]entities.Phone, error)
16+
17+
// Load a phone by user and phone number
18+
Load(ctx context.Context, userID entities.UserID, phoneNumber string) (*entities.Phone, error)
1619
}

api/pkg/requests/message_send_request.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package requests
33
import (
44
"time"
55

6+
"github.com/NdoleStudio/http-sms-manager/pkg/entities"
7+
68
"github.com/nyaruka/phonenumbers"
79

810
"github.com/NdoleStudio/http-sms-manager/pkg/services"
@@ -24,13 +26,14 @@ func (input *MessageSend) Sanitize() MessageSend {
2426
}
2527

2628
// ToMessageSendParams converts MessageSend to services.MessageSendParams
27-
func (input MessageSend) ToMessageSendParams(source string) services.MessageSendParams {
29+
func (input MessageSend) ToMessageSendParams(userID entities.UserID, source string) services.MessageSendParams {
2830
from, _ := phonenumbers.Parse(input.From, phonenumbers.UNKNOWN_REGION)
2931
to, _ := phonenumbers.Parse(input.To, phonenumbers.UNKNOWN_REGION)
3032

3133
return services.MessageSendParams{
3234
Source: source,
3335
Owner: *from,
36+
UserID: userID,
3437
RequestReceivedAt: time.Now().UTC(),
3538
Contact: *to,
3639
Content: input.Content,

0 commit comments

Comments
 (0)