Skip to content

Commit

Permalink
notifications add type and interruptionLevel
Browse files Browse the repository at this point in the history
  • Loading branch information
konrad2002 committed Dec 5, 2024
1 parent aebe143 commit 1e6dc90
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 14 deletions.
6 changes: 3 additions & 3 deletions controller/notification_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func sendNotification(c *gin.Context) {
return
}

apnsId, body, status, err := service.SendPushNotification(device, request.Title, request.Subtitle, request.Message)
apnsId, body, status, err := service.SendPushNotification(device, request.Title, request.Subtitle, request.Message, request.InterruptionLevel)
if err != nil {
c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": err.Error()})
return
Expand All @@ -72,13 +72,13 @@ func sendNotificationForMeeting(c *gin.Context) {

meeting := c.Param("meeting")

var request dto.NotificationRequestDto
var request dto.MeetingNotificationRequestDto
if err := c.BindJSON(&request); err != nil {
c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": err.Error()})
return
}

users, notificationUsers, success, err := service.SendPushNotificationForMeeting(meeting, request.Title, request.Subtitle, request.Message)
users, notificationUsers, success, err := service.SendPushNotificationForMeeting(meeting, request)
if err != nil {
c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": err.Error()})
return
Expand Down
14 changes: 11 additions & 3 deletions dto/notification_request.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
package dto

type MeetingNotificationRequestDto struct {
Subtitle string `json:"subtitle"`
Message string `json:"message"`
MessageType string `json:"message_type"` // like athlete, meeting, schedule or favourites (see settings)
InterruptionLevel string `json:"interruption_level"` // passive, active, time-sensitive
}

type NotificationRequestDto struct {
Title string `json:"title"`
Subtitle string `json:"subtitle"`
Message string `json:"message"`
Title string `json:"title"`
Subtitle string `json:"subtitle"`
Message string `json:"message"`
InterruptionLevel string `json:"interruption_level"` // passive, active, time-sensitive
}

type NotificationResponseDto struct {
Expand Down
15 changes: 15 additions & 0 deletions model/notification_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,18 @@ type NotificationSettings struct {
Meeting bool `json:"meeting" bson:"meeting"`
Schedule bool `json:"schedule" bson:"schedule"`
}

func (user *NotificationUser) HasSetting(notificationType string) bool {
switch notificationType {
case "athlete":
return user.Settings.Athlete
case "favourites":
return user.Settings.Favourites
case "meeting":
return user.Settings.Meeting
case "schedule":
return user.Settings.Schedule

}
return false
}
40 changes: 32 additions & 8 deletions service/notification_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"bytes"
"fmt"
"github.com/swimresults/user-service/apns"
"github.com/swimresults/user-service/dto"
"github.com/swimresults/user-service/model"
"go.mongodb.org/mongo-driver/bson/primitive"
"golang.org/x/net/http2"
"io/ioutil"
Expand Down Expand Up @@ -63,8 +65,13 @@ func SendTestPushNotification(receiver string) error {
return nil
}

func SendPushNotificationForMeeting(meeting string, title string, subtitle string, message string) (int, int, int, error) {
athletes, err := ac.GetAthletesByMeeting(meeting)
func SendPushNotificationForMeeting(meetingId string, request dto.MeetingNotificationRequestDto) (int, int, int, error) {
meeting, err := GetMeetingById(meetingId)
if err != nil {
return 0, 0, 0, err
}

athletes, err := ac.GetAthletesByMeeting(meetingId)
if err != nil {
return 0, 0, 0, err
}
Expand All @@ -74,8 +81,17 @@ func SendPushNotificationForMeeting(meeting string, title string, subtitle strin
athleteIds = append(athleteIds, athlete.Identifier)
}

users, err := GetUsersByIsFollowerOrMe(athleteIds)
if err != nil {
var users []model.User
var err1 error
if request.MessageType == "athlete" {
users, err1 = GetUsersByIsMe(athleteIds)
} else if request.MessageType == "favourites" {
users, err1 = GetUsersByIsFollower(athleteIds)
} else {
users, err1 = GetUsersByIsFollowerOrMe(athleteIds)
}

if err1 != nil {
return 0, 0, 0, err
}

Expand All @@ -93,14 +109,18 @@ func SendPushNotificationForMeeting(meeting string, title string, subtitle strin

success := 0
for _, user := range notificationUsers {
if !user.HasSetting(request.MessageType) {
continue
}

wg.Add(1)
go func(receiver string, title string, subtitle string, message string, success *int) {
go func(receiver string, title string, subtitle string, message string, interruptionLevel string, success *int) {
defer wg.Done()
_, _, code, err := SendPushNotification(receiver, title, subtitle, message)
_, _, code, err := SendPushNotification(receiver, title, subtitle, message, interruptionLevel)
if err == nil || code == 200 {
*success++
}
}(user.Token, title, subtitle, message, &success)
}(user.Token, meeting.Series.NameMedium, request.Subtitle, request.Message, request.InterruptionLevel, &success)
}

wg.Wait() // Wait for all goroutines to finish
Expand All @@ -109,14 +129,18 @@ func SendPushNotificationForMeeting(meeting string, title string, subtitle strin
return len(users), len(notificationUsers), success, nil
}

func SendPushNotification(receiver string, title string, subtitle string, message string) (string, string, int, error) {
func SendPushNotification(receiver string, title string, subtitle string, message string, interruptionLevel string) (string, string, int, error) {
token := apns.GetToken()

t := &http2.Transport{}
c := &http.Client{
Transport: t,
}

if interruptionLevel == "" {
interruptionLevel = "active"
}

b := []byte(`
{
"aps": {
Expand Down
16 changes: 16 additions & 0 deletions service/user_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,22 @@ func GetUsersByIsFollowerOrMe(athleteIds []primitive.ObjectID) ([]model.User, er
})
}

func GetUsersByIsFollower(athleteIds []primitive.ObjectID) ([]model.User, error) {
return getUsersByBsonDocument(bson.M{
"$or": []interface{}{
bson.M{"following.athlete_id": athleteIds},
},
})
}

func GetUsersByIsMe(athleteIds []primitive.ObjectID) ([]model.User, error) {
return getUsersByBsonDocument(bson.M{
"$or": []interface{}{
bson.M{"own_athlete_id": bson.M{"$in": athleteIds}},
},
})
}

// GetUserByKeycloakId gets a user by keycloak id, creates new one if not existing so far
func GetUserByKeycloakId(id uuid.UUID) (model.User, error) {
user, err := getUserByBsonDocument(bson.D{{"keycloak_id", id.String()}})
Expand Down

0 comments on commit 1e6dc90

Please sign in to comment.